@finkovsky/client
v0.2.0
Published
TypeScript client SDK for the Finkovsky API — typed financial analysis, equity data, and economic indicators.
Maintainers
Readme
@finkovsky/client
TypeScript client SDK for the Finkovsky API — typed financial analysis, equity data, and economic indicators.
Built on openapi-fetch (~2 KB, zero dependencies) with types generated by openapi-typescript.
Install
From local tarball
cd sdk/typescript
npm install && npm run build && npm pack
# Then, in your project:
npm install /path/to/finkovsky-client-0.1.0.tgzFrom source (development)
cd sdk/typescript
npm install
npm run buildQuick Start
import { createFinkovskyClient } from "@finkovsky/client";
const client = createFinkovskyClient({
apiKey: process.env.FINKOVSKY_API_KEY!,
baseUrl: "https://finkovsky-api.motosan.org", // default: https://api.finkovsky.com
});
// Equity quote — fully typed path and response
const { data, error } = await client.GET("/v1/equity/quote/{symbol}", {
params: { path: { symbol: "AAPL" } },
});
if (error) {
console.error("API error:", error);
} else {
console.log("Quote:", data);
}Usage Examples
Technical Analysis
// Full analysis (trend, stage2, CANSLIM, patterns, risk)
const { data: analysis } = await client.GET("/v1/ta/analyze/{symbol}", {
params: { path: { symbol: "AAPL" } },
});
// Crypto analysis
const { data: crypto } = await client.GET("/v1/ta/crypto/analyze/{symbol}", {
params: { path: { symbol: "BTC" } },
});
// Custom indicators
const { data: indicators } = await client.GET("/v1/ta/indicators/{symbol}", {
params: {
path: { symbol: "AAPL" },
query: { indicators: "sma,rsi" },
},
});
// Candlestick patterns
const { data: patterns } = await client.GET("/v1/ta/patterns/{symbol}", {
params: { path: { symbol: "AAPL" } },
});Screening
// Stage 2 (Mark Minervini)
const { data: stage2 } = await client.GET("/v1/ta/screener/stage2/{symbol}", {
params: { path: { symbol: "AAPL" } },
});
// → { passes: true, score: 5, max_score: 7, checks: { ... } }
// CANSLIM (William O'Neil)
const { data: canslim } = await client.GET("/v1/ta/screener/canslim/{symbol}", {
params: { path: { symbol: "AAPL" } },
});
// Entry signal
const { data: entry } = await client.GET("/v1/ta/screener/entry/{symbol}", {
params: { path: { symbol: "AAPL" } },
});
// Batch scan — multiple symbols at once
const { data: scan } = await client.GET("/v1/screener/scan", {
params: { query: { symbols: "AAPL,NVDA,TSM", filter: "stage2" } },
});
// Universe scan (e.g. S&P 500)
const { data: universe } = await client.GET("/v1/screener/universe/{name}", {
params: { path: { name: "sp500" }, query: { limit: 10 } },
});Risk & Position Sizing
const { data: risk } = await client.GET("/v1/ta/risk/{symbol}", {
params: {
path: { symbol: "NVDA" },
query: {
account_value: 100000,
risk_pct: 1.5,
stop_pct: 7,
target_multiple: 3,
},
},
});
// → { symbol, entry, stop_price, target, risk_reward_ratio, shares, position_value, ... }Equity Data
// Real-time quote
const { data: quote } = await client.GET("/v1/equity/quote/{symbol}", {
params: { path: { symbol: "AAPL" } },
});
// OHLCV history
const { data: bars } = await client.GET("/v1/equity/history/{symbol}", {
params: {
path: { symbol: "AAPL" },
query: { interval: "day", limit: 100 },
},
});
// Company profile
const { data: profile } = await client.GET("/v1/equity/profile/{symbol}", {
params: { path: { symbol: "AAPL" } },
});Economic Data
// FRED series (GDP, unemployment, etc.)
const { data: gdp } = await client.GET("/v1/economy/fred/{series_id}", {
params: {
path: { series_id: "GDP" },
query: { start_date: "2020-01-01" },
},
});
// Economic calendar
const { data: calendar } = await client.GET("/v1/economy/calendar", {
params: { query: { country: "US", importance: "high" } },
});RAG News Search
const { data: news } = await client.GET("/v1/rag/news/search", {
params: { query: { q: "TSMC earnings", symbol: "TSM", limit: 5 } },
});
// → { results: [{ title, url, score, snippet, published_at }], total }Taiwan Market
// Institutional flow (三大法人)
const { data: flow } = await client.GET("/v1/tw/institutional/{symbol}", {
params: { path: { symbol: "2330" }, query: { days: 10 } },
});
// Top institutional buys/sells
const { data: top } = await client.GET("/v1/tw/institutional/top", {
params: { query: { limit: 10, sort: "foreign_net" } },
});
// Margin trading (融資融券)
const { data: margin } = await client.GET("/v1/tw/margin/{symbol}", {
params: { path: { symbol: "2330" }, query: { days: 30 } },
});Error Handling
All methods return { data, error, response }. On success data is populated; on failure error contains the API error:
const { data, error, response } = await client.GET("/v1/ta/analyze/{symbol}", {
params: { path: { symbol: "INVALID" } },
});
if (error) {
// error: { error: string }
console.error(`HTTP ${response.status}:`, error.error);
return;
}
// data is typed based on the endpoint
console.log(data);Common HTTP status codes:
| Status | Meaning | |--------|---------| | 200 | Success | | 401 | Invalid or missing API key | | 404 | Resource not found (e.g. unknown symbol) | | 422 | Invalid parameters | | 429 | Rate limit exceeded | | 502 | Upstream data provider error | | 503 | Service temporarily unavailable |
Type Imports
All response types are re-exported for annotation convenience:
import type {
AnalysisResponse,
Stage2Response,
CanslimResponse,
EntrySignalResponse,
PatternResponse,
RiskResponse,
ScanResponse,
ErrorResponse,
HealthResponse,
RagNewsSearchResponse,
InstitutionalFlowResponse,
MarginTradingResponse,
} from "@finkovsky/client";API Coverage
All 22 REST endpoints from the Finkovsky OpenAPI spec are available as typed paths:
| Category | Endpoints |
|----------|-----------|
| Health | /health, /health/live, /health/ready, /health/workers |
| Technical Analysis | /v1/ta/analyze/{symbol}, /v1/ta/crypto/analyze/{symbol}, /v1/ta/indicators/{symbol}, /v1/ta/screener/stage2/{symbol}, /v1/ta/screener/canslim/{symbol}, /v1/ta/screener/entry/{symbol}, /v1/ta/patterns/{symbol}, /v1/ta/risk/{symbol} |
| Equity | /v1/equity/quote/{symbol}, /v1/equity/history/{symbol}, /v1/equity/profile/{symbol} |
| Economy | /v1/economy/fred/{series_id}, /v1/economy/calendar |
| Screener | /v1/screener/scan, /v1/screener/universe/{name} |
| RAG | /v1/rag/news/search |
| Taiwan Market | /v1/tw/institutional/{symbol}, /v1/tw/institutional/top, /v1/tw/margin/{symbol} |
Testing
npm install
npx vitest runTests cover client construction, auth middleware injection, URL building, query parameter serialization, and response parsing.
Regenerating Types
When the API schema changes, regenerate src/openapi.d.ts from a running API instance:
# From the repo root (recommended):
make sdk-gen
# Or from this directory:
FINKOVSKY_API_URL=http://localhost:3000 npm run genThe FINKOVSKY_API_URL env var defaults to http://localhost:3000. You can also use API_URL as an alias.
This fetches /openapi.json and runs openapi-typescript to produce the type definitions. You do not need the server running for npm run build — only for npm run gen.
CI type-sync check
A GitHub Actions workflow (.github/workflows/sdk-typecheck.yml) runs on every PR that touches API route files or the SDK. It:
- Builds and starts the API server
- Regenerates
src/openapi.d.tsfrom the live/openapi.json - Fails the build if the generated file differs from the committed version
- Runs
tsc --noEmitto verify the SDK compiles
If CI fails with a stale openapi.d.ts, start the API locally and run make sdk-gen, then commit the updated file.
Repo-root Makefile targets
| Target | Description |
|--------|-------------|
| make sdk-gen | Regenerate openapi.d.ts from a running API |
| make sdk-build | Install deps + build the SDK |
| make sdk-pack | Create a publishable .tgz tarball |
Build Output
dist/
index.js ESM module
index.cjs CommonJS module
index.d.ts Type declarations (ESM)
index.d.cts Type declarations (CJS)Both ESM (import) and CJS (require) are supported via the exports field in package.json.
License
Same license as the parent repository.
