@startsimpli/api 0.5.14 → 0.5.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/constants/endpoints.ts +15 -0
- package/src/index.ts +44 -0
- package/src/lib/markets-api.ts +333 -0
package/package.json
CHANGED
|
@@ -65,4 +65,19 @@ export const ENDPOINTS = {
|
|
|
65
65
|
|
|
66
66
|
// Companies / Feature flags
|
|
67
67
|
FEATURE_FLAGS: 'api/v1/companies/feature-flags',
|
|
68
|
+
|
|
69
|
+
// Markets (instruments, prices, analytics, news, health)
|
|
70
|
+
INSTRUMENTS: 'api/v1/markets/instruments',
|
|
71
|
+
INSTRUMENT: (symbol: string) => `api/v1/markets/instruments/${symbol}`,
|
|
72
|
+
INSTRUMENT_BARS: (symbol: string) => `api/v1/markets/instruments/${symbol}/bars`,
|
|
73
|
+
INSTRUMENT_LATEST: (symbol: string) => `api/v1/markets/instruments/${symbol}/latest`,
|
|
74
|
+
INSTRUMENT_ANALYTICS: (symbol: string) => `api/v1/markets/instruments/${symbol}/analytics`,
|
|
75
|
+
INSTRUMENT_NEWS: (symbol: string) => `api/v1/markets/instruments/${symbol}/news`,
|
|
76
|
+
MARKETS_HEALTH: 'api/v1/markets/health',
|
|
77
|
+
SECTOR_BREADTH: 'api/v1/markets/sector_breadth',
|
|
78
|
+
EARNINGS_CALENDAR: 'api/v1/markets/calendar',
|
|
79
|
+
TRADING_SNAPSHOTS: 'api/v1/markets/trading/snapshots',
|
|
80
|
+
|
|
81
|
+
// Sources ops
|
|
82
|
+
SOURCES_HEALTH: 'api/v1/sources/ops/health',
|
|
68
83
|
} as const;
|
package/src/index.ts
CHANGED
|
@@ -162,6 +162,7 @@ import { UsersApi } from './lib/users-api';
|
|
|
162
162
|
import { EnrichmentApi } from './lib/enrichment-api';
|
|
163
163
|
import { TargetListsApi } from './lib/target-lists-api';
|
|
164
164
|
import { MessageTemplatesApi } from './lib/message-templates-api';
|
|
165
|
+
import { MarketsApi } from './lib/markets-api';
|
|
165
166
|
|
|
166
167
|
import type { ApiClientConfig } from './lib/api-client';
|
|
167
168
|
|
|
@@ -185,5 +186,48 @@ export function createStartSimpliApi(config: ApiClientConfig = {}) {
|
|
|
185
186
|
enrichment: new EnrichmentApi(client),
|
|
186
187
|
targetLists: new TargetListsApi(client),
|
|
187
188
|
messageTemplates: new MessageTemplatesApi(client),
|
|
189
|
+
markets: new MarketsApi(client),
|
|
188
190
|
};
|
|
189
191
|
}
|
|
192
|
+
|
|
193
|
+
// Markets API
|
|
194
|
+
export { MarketsApi } from './lib/markets-api';
|
|
195
|
+
export type {
|
|
196
|
+
BarInterval,
|
|
197
|
+
Instrument,
|
|
198
|
+
PriceBar,
|
|
199
|
+
InstrumentFilters,
|
|
200
|
+
BarsParams,
|
|
201
|
+
AnalyticsMetric,
|
|
202
|
+
AnalyticsParams,
|
|
203
|
+
AnalyticsResponse,
|
|
204
|
+
ReturnsAnalytics,
|
|
205
|
+
VolatilityPoint,
|
|
206
|
+
BetaAnalytics,
|
|
207
|
+
PairSpreadPoint,
|
|
208
|
+
NewsDirection,
|
|
209
|
+
NewsSentimentLabel,
|
|
210
|
+
NewsEventType,
|
|
211
|
+
InstrumentNewsItem,
|
|
212
|
+
InstrumentNewsResponse,
|
|
213
|
+
NewsParams,
|
|
214
|
+
InstrumentHealth,
|
|
215
|
+
InstrumentHealthInterval,
|
|
216
|
+
SourceInstanceHealth,
|
|
217
|
+
MarketsHealth,
|
|
218
|
+
SectorBreadthParams,
|
|
219
|
+
SectorBreadthPoint,
|
|
220
|
+
SectorBreadthResponse,
|
|
221
|
+
EarningsCalendarParams,
|
|
222
|
+
EarningsTimeOfDay,
|
|
223
|
+
EarningsCalendarRow,
|
|
224
|
+
EarningsCalendarResponse,
|
|
225
|
+
PairConsensus,
|
|
226
|
+
CommitteeVotes,
|
|
227
|
+
PairSnapshot,
|
|
228
|
+
AlpacaPosition,
|
|
229
|
+
AlpacaSnapshot,
|
|
230
|
+
TradingSnapshot,
|
|
231
|
+
TradingSnapshotsResponse,
|
|
232
|
+
TradingSnapshotsParams,
|
|
233
|
+
} from './lib/markets-api';
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markets API wrapper for /api/v1/markets/*
|
|
3
|
+
*
|
|
4
|
+
* Backs the trade-simpli app: instruments, OHLCV bars, analytics
|
|
5
|
+
* (returns / volatility / beta / pair_spread), per-instrument news,
|
|
6
|
+
* and operational health rollup.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { PaginatedResponse } from '../types';
|
|
10
|
+
import { ENDPOINTS } from '../constants/endpoints';
|
|
11
|
+
import type { ApiClient } from './api-client';
|
|
12
|
+
|
|
13
|
+
export type BarInterval = '1d' | '1h' | '5m' | '1m';
|
|
14
|
+
|
|
15
|
+
export interface Instrument {
|
|
16
|
+
symbol: string;
|
|
17
|
+
name?: string | null;
|
|
18
|
+
instrumentType?: string | null;
|
|
19
|
+
exchange?: string | null;
|
|
20
|
+
isActive?: boolean;
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface PriceBar {
|
|
25
|
+
barDate: string;
|
|
26
|
+
open: number;
|
|
27
|
+
high: number;
|
|
28
|
+
low: number;
|
|
29
|
+
close: number;
|
|
30
|
+
volume?: number | null;
|
|
31
|
+
interval?: BarInterval;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface InstrumentFilters {
|
|
35
|
+
q?: string;
|
|
36
|
+
instrumentType?: string;
|
|
37
|
+
exchange?: string;
|
|
38
|
+
isActive?: boolean;
|
|
39
|
+
page?: number;
|
|
40
|
+
pageSize?: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface BarsParams {
|
|
44
|
+
interval?: BarInterval;
|
|
45
|
+
since?: string;
|
|
46
|
+
limit?: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export type AnalyticsMetric = 'returns' | 'volatility' | 'beta' | 'pair_spread';
|
|
50
|
+
|
|
51
|
+
export interface AnalyticsParams {
|
|
52
|
+
metric: AnalyticsMetric;
|
|
53
|
+
windowDays?: number;
|
|
54
|
+
window?: number;
|
|
55
|
+
interval?: BarInterval;
|
|
56
|
+
benchmark?: string;
|
|
57
|
+
vs?: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface ReturnsAnalytics {
|
|
61
|
+
symbol: string;
|
|
62
|
+
windowDays: number;
|
|
63
|
+
startPrice: number;
|
|
64
|
+
endPrice: number;
|
|
65
|
+
simpleReturn: number;
|
|
66
|
+
logReturn: number;
|
|
67
|
+
barCount: number;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface VolatilityPoint {
|
|
71
|
+
barDate: string;
|
|
72
|
+
volatility: number;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface BetaAnalytics {
|
|
76
|
+
symbol: string;
|
|
77
|
+
benchmark: string;
|
|
78
|
+
beta: number;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface PairSpreadPoint {
|
|
82
|
+
barDate: string;
|
|
83
|
+
longClose: number;
|
|
84
|
+
shortClose: number;
|
|
85
|
+
spread: number;
|
|
86
|
+
logSpread: number;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export type AnalyticsResponse =
|
|
90
|
+
| ReturnsAnalytics
|
|
91
|
+
| VolatilityPoint[]
|
|
92
|
+
| BetaAnalytics
|
|
93
|
+
| PairSpreadPoint[];
|
|
94
|
+
|
|
95
|
+
export type NewsDirection = 'bullish' | 'bearish' | 'neutral' | 'unclear';
|
|
96
|
+
export type NewsSentimentLabel = 'positive' | 'neutral' | 'negative';
|
|
97
|
+
export type NewsEventType =
|
|
98
|
+
| 'ceasefire'
|
|
99
|
+
| 'escalation'
|
|
100
|
+
| 'supply_disruption'
|
|
101
|
+
| 'opec'
|
|
102
|
+
| 'earnings'
|
|
103
|
+
| 'central_bank'
|
|
104
|
+
| 'regulatory'
|
|
105
|
+
| 'general';
|
|
106
|
+
|
|
107
|
+
export interface InstrumentNewsItem {
|
|
108
|
+
id: string;
|
|
109
|
+
title: string | null;
|
|
110
|
+
summary?: string | null;
|
|
111
|
+
url: string | null;
|
|
112
|
+
publisherName?: string | null;
|
|
113
|
+
publisherDomain?: string | null;
|
|
114
|
+
publishedAt?: string | null;
|
|
115
|
+
queryTag?: string | null;
|
|
116
|
+
confidence: number;
|
|
117
|
+
direction: NewsDirection | null;
|
|
118
|
+
sentiment: number | null;
|
|
119
|
+
sentimentLabel: NewsSentimentLabel | null;
|
|
120
|
+
eventType: NewsEventType;
|
|
121
|
+
marketMovingScore: number;
|
|
122
|
+
ingestedAt: string;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface InstrumentNewsResponse {
|
|
126
|
+
symbol: string;
|
|
127
|
+
count: number;
|
|
128
|
+
results: InstrumentNewsItem[];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface NewsParams {
|
|
132
|
+
limit?: number;
|
|
133
|
+
minConfidence?: number;
|
|
134
|
+
since?: string;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface SectorBreadthParams {
|
|
138
|
+
sector: string;
|
|
139
|
+
since?: string;
|
|
140
|
+
until?: string;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export interface SectorBreadthPoint {
|
|
144
|
+
barDate: string;
|
|
145
|
+
nUp: number;
|
|
146
|
+
nTotal: number;
|
|
147
|
+
pctUp: number;
|
|
148
|
+
meanReturn: number;
|
|
149
|
+
returnDispersion: number;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export interface SectorBreadthResponse {
|
|
153
|
+
sector: string;
|
|
154
|
+
interval: '1d';
|
|
155
|
+
members: string[];
|
|
156
|
+
count: number;
|
|
157
|
+
results: SectorBreadthPoint[];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export interface EarningsCalendarParams {
|
|
161
|
+
symbols: string[];
|
|
162
|
+
since?: string;
|
|
163
|
+
until?: string;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export type EarningsTimeOfDay = 'BMO' | 'AMC' | 'During' | 'Unknown';
|
|
167
|
+
|
|
168
|
+
export interface EarningsCalendarRow {
|
|
169
|
+
date: string;
|
|
170
|
+
symbol: string;
|
|
171
|
+
eventType: 'earnings';
|
|
172
|
+
confirmed: boolean;
|
|
173
|
+
timeOfDay: EarningsTimeOfDay;
|
|
174
|
+
epsEstimate: number | null;
|
|
175
|
+
reportedEps: number | null;
|
|
176
|
+
surprisePct: number | null;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export interface EarningsCalendarResponse {
|
|
180
|
+
symbolsRequested: string[];
|
|
181
|
+
since: string | null;
|
|
182
|
+
until: string | null;
|
|
183
|
+
count: number;
|
|
184
|
+
errors: Record<string, string>;
|
|
185
|
+
results: EarningsCalendarRow[];
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export type PairConsensus = 'BULL' | 'BEAR' | 'FLAT';
|
|
189
|
+
|
|
190
|
+
export interface CommitteeVotes {
|
|
191
|
+
bull: number;
|
|
192
|
+
bear: number;
|
|
193
|
+
flat: number;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export interface PairSnapshot {
|
|
197
|
+
topScore?: number | null;
|
|
198
|
+
consensus?: PairConsensus | null;
|
|
199
|
+
committeeVotes?: CommitteeVotes | null;
|
|
200
|
+
topConfig?: string | null;
|
|
201
|
+
thresholds?: { long?: number | null; short?: number | null } | null;
|
|
202
|
+
[key: string]: unknown;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export interface AlpacaPosition {
|
|
206
|
+
symbol: string;
|
|
207
|
+
qty: number;
|
|
208
|
+
side?: 'long' | 'short';
|
|
209
|
+
marketValue?: number | null;
|
|
210
|
+
avgEntryPrice?: number | null;
|
|
211
|
+
unrealizedPl?: number | null;
|
|
212
|
+
[key: string]: unknown;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export interface AlpacaSnapshot {
|
|
216
|
+
equity: number;
|
|
217
|
+
cash: number;
|
|
218
|
+
buyingPower: number;
|
|
219
|
+
positions: AlpacaPosition[];
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export interface TradingSnapshot {
|
|
223
|
+
id: string;
|
|
224
|
+
timestampUtc: string;
|
|
225
|
+
createdAt: string;
|
|
226
|
+
alpaca: AlpacaSnapshot;
|
|
227
|
+
pairs: Record<string, PairSnapshot>;
|
|
228
|
+
notes?: string | null;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export interface TradingSnapshotsResponse {
|
|
232
|
+
count: number;
|
|
233
|
+
results: TradingSnapshot[];
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export interface TradingSnapshotsParams {
|
|
237
|
+
since?: string;
|
|
238
|
+
limit?: number;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export interface InstrumentHealthInterval {
|
|
242
|
+
interval: BarInterval;
|
|
243
|
+
barCount: number;
|
|
244
|
+
latestBarAt?: string | null;
|
|
245
|
+
ageSeconds?: number | null;
|
|
246
|
+
isStale: boolean;
|
|
247
|
+
gaps30d: number;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export interface InstrumentHealth {
|
|
251
|
+
symbol: string;
|
|
252
|
+
name?: string | null;
|
|
253
|
+
intervals: InstrumentHealthInterval[];
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export interface SourceInstanceHealth {
|
|
257
|
+
sourceKey: string;
|
|
258
|
+
label?: string | null;
|
|
259
|
+
healthStatus: string;
|
|
260
|
+
consecutiveFailureCount: number;
|
|
261
|
+
runs24h: { total: number; completed: number; successRatio: number };
|
|
262
|
+
lastRunAt?: string | null;
|
|
263
|
+
lastSuccessAt?: string | null;
|
|
264
|
+
openDeadLetters: number;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export interface MarketsHealth {
|
|
268
|
+
generatedAt: string;
|
|
269
|
+
instruments: InstrumentHealth[];
|
|
270
|
+
sourceInstances: SourceInstanceHealth[];
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export class MarketsApi {
|
|
274
|
+
constructor(private client: ApiClient) {}
|
|
275
|
+
|
|
276
|
+
async listInstruments(filters?: InstrumentFilters): Promise<PaginatedResponse<Instrument>> {
|
|
277
|
+
return this.client.fetch.get<PaginatedResponse<Instrument>>(ENDPOINTS.INSTRUMENTS, {
|
|
278
|
+
params: filters as Record<string, unknown> | undefined,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
async getInstrument(symbol: string): Promise<Instrument> {
|
|
283
|
+
return this.client.fetch.get<Instrument>(ENDPOINTS.INSTRUMENT(symbol));
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
async getBars(symbol: string, params?: BarsParams): Promise<PriceBar[] | PaginatedResponse<PriceBar>> {
|
|
287
|
+
return this.client.fetch.get<PriceBar[] | PaginatedResponse<PriceBar>>(
|
|
288
|
+
ENDPOINTS.INSTRUMENT_BARS(symbol),
|
|
289
|
+
{ params: params as Record<string, unknown> | undefined },
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
async getLatestBar(symbol: string, interval: BarInterval = '1d'): Promise<PriceBar> {
|
|
294
|
+
return this.client.fetch.get<PriceBar>(ENDPOINTS.INSTRUMENT_LATEST(symbol), {
|
|
295
|
+
params: { interval },
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
async getAnalytics(symbol: string, params: AnalyticsParams): Promise<AnalyticsResponse> {
|
|
300
|
+
return this.client.fetch.get<AnalyticsResponse>(ENDPOINTS.INSTRUMENT_ANALYTICS(symbol), {
|
|
301
|
+
params: params as unknown as Record<string, unknown>,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
async getNews(symbol: string, params?: NewsParams): Promise<InstrumentNewsResponse> {
|
|
306
|
+
return this.client.fetch.get<InstrumentNewsResponse>(ENDPOINTS.INSTRUMENT_NEWS(symbol), {
|
|
307
|
+
params: params as Record<string, unknown> | undefined,
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
async getHealth(): Promise<MarketsHealth> {
|
|
312
|
+
return this.client.fetch.get<MarketsHealth>(ENDPOINTS.MARKETS_HEALTH);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
async getSectorBreadth(params: SectorBreadthParams): Promise<SectorBreadthResponse> {
|
|
316
|
+
return this.client.fetch.get<SectorBreadthResponse>(ENDPOINTS.SECTOR_BREADTH, {
|
|
317
|
+
params: params as unknown as Record<string, unknown>,
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
async getEarningsCalendar(params: EarningsCalendarParams): Promise<EarningsCalendarResponse> {
|
|
322
|
+
const { symbols, ...rest } = params;
|
|
323
|
+
return this.client.fetch.get<EarningsCalendarResponse>(ENDPOINTS.EARNINGS_CALENDAR, {
|
|
324
|
+
params: { ...rest, symbols: symbols.join(',') } as unknown as Record<string, unknown>,
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
async getTradingSnapshots(params?: TradingSnapshotsParams): Promise<TradingSnapshotsResponse> {
|
|
329
|
+
return this.client.fetch.get<TradingSnapshotsResponse>(ENDPOINTS.TRADING_SNAPSHOTS, {
|
|
330
|
+
params: params as Record<string, unknown> | undefined,
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
}
|