@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@startsimpli/api",
3
- "version": "0.5.14",
3
+ "version": "0.5.16",
4
4
  "description": "Type-safe Django REST API client for StartSimpli apps",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -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
+ }