@fin.cx/opendata 3.2.2 → 3.4.0
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/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/stocks/index.d.ts +1 -0
- package/dist_ts/stocks/index.js +2 -1
- package/dist_ts/stocks/providers/provider.coingecko.d.ts +101 -0
- package/dist_ts/stocks/providers/provider.coingecko.js +596 -0
- package/dist_ts/stocks/providers/provider.marketstack.d.ts +73 -12
- package/dist_ts/stocks/providers/provider.marketstack.js +336 -63
- package/package.json +1 -1
- package/readme.hints.md +45 -1
- package/readme.md +62 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/stocks/index.ts +2 -1
- package/ts/stocks/providers/provider.coingecko.ts +757 -0
- package/ts/stocks/providers/provider.marketstack.ts +386 -69
|
@@ -1,33 +1,40 @@
|
|
|
1
1
|
import * as plugins from '../../plugins.js';
|
|
2
2
|
/**
|
|
3
|
-
* Marketstack API v2 Provider -
|
|
3
|
+
* Marketstack API v2 Provider - Professional Plan with Intelligent Intraday Support
|
|
4
4
|
* Documentation: https://docs.apilayer.com/marketstack/docs/marketstack-api-v2-v-2-0-0
|
|
5
5
|
*
|
|
6
6
|
* Features:
|
|
7
|
+
* - Intelligent endpoint selection based on market hours
|
|
8
|
+
* - Real-time intraday pricing with multiple intervals (1min, 5min, 10min, 15min, 30min, 1hour)
|
|
7
9
|
* - End-of-Day (EOD) stock prices with historical data
|
|
8
|
-
* -
|
|
10
|
+
* - Market state detection (PRE, REGULAR, POST, CLOSED)
|
|
9
11
|
* - Exchange filtering via MIC codes (XNAS, XNYS, XLON, etc.)
|
|
10
12
|
* - Supports 500,000+ tickers across 72+ exchanges worldwide
|
|
11
13
|
* - OHLCV data (Open, High, Low, Close, Volume)
|
|
12
14
|
* - Pagination for large datasets
|
|
15
|
+
* - Automatic fallback from intraday to EOD on errors
|
|
13
16
|
* - Requires API key authentication
|
|
14
17
|
*
|
|
18
|
+
* Intelligent Endpoint Selection:
|
|
19
|
+
* - During market hours (PRE/REGULAR/POST): Uses intraday endpoints for fresh data
|
|
20
|
+
* - After market close (CLOSED): Uses EOD endpoints to save API credits
|
|
21
|
+
* - Automatic fallback to EOD if intraday fails (rate limits, plan restrictions, etc.)
|
|
22
|
+
*
|
|
15
23
|
* Rate Limits:
|
|
16
24
|
* - Free Plan: 100 requests/month (EOD only)
|
|
17
|
-
* - Basic Plan: 10,000 requests/month
|
|
18
|
-
* - Professional Plan: 100,000 requests/month (intraday
|
|
25
|
+
* - Basic Plan: 10,000 requests/month (EOD only)
|
|
26
|
+
* - Professional Plan: 100,000 requests/month (intraday + EOD)
|
|
19
27
|
*
|
|
20
|
-
*
|
|
21
|
-
* -
|
|
22
|
-
* - Exchange
|
|
23
|
-
* -
|
|
24
|
-
* - Pagination handling
|
|
28
|
+
* Intraday Access:
|
|
29
|
+
* - Intervals below 15min (1min, 5min, 10min) require Professional Plan or higher
|
|
30
|
+
* - Real-time data from IEX Exchange for US tickers
|
|
31
|
+
* - Symbol formatting: Periods replaced with hyphens for intraday (BRK.B → BRK-B)
|
|
25
32
|
*/
|
|
26
33
|
export class MarketstackProvider {
|
|
27
34
|
constructor(apiKey, config) {
|
|
28
35
|
this.config = config;
|
|
29
36
|
this.name = 'Marketstack';
|
|
30
|
-
this.priority =
|
|
37
|
+
this.priority = 90; // Increased from 80 - now supports real-time intraday data during market hours
|
|
31
38
|
this.requiresAuth = true;
|
|
32
39
|
this.rateLimit = {
|
|
33
40
|
requestsPerMinute: undefined, // No per-minute limit specified
|
|
@@ -58,35 +65,89 @@ export class MarketstackProvider {
|
|
|
58
65
|
}
|
|
59
66
|
}
|
|
60
67
|
/**
|
|
61
|
-
* Fetch current/latest
|
|
68
|
+
* Fetch current/latest price with intelligent endpoint selection
|
|
69
|
+
* Uses intraday during market hours (PRE, REGULAR, POST) for fresh data
|
|
70
|
+
* Uses EOD after market close (CLOSED) to save API credits
|
|
62
71
|
*/
|
|
63
72
|
async fetchCurrentPrice(request) {
|
|
64
73
|
try {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
74
|
+
// Determine current market state
|
|
75
|
+
const marketState = this.getUsMarketState();
|
|
76
|
+
const useIntraday = this.shouldUseIntradayEndpoint(marketState);
|
|
77
|
+
if (useIntraday) {
|
|
78
|
+
// Use intraday endpoint for fresh data during market hours
|
|
79
|
+
return await this.fetchCurrentPriceIntraday(request, marketState);
|
|
69
80
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
.
|
|
73
|
-
.get();
|
|
74
|
-
const responseData = await response.json();
|
|
75
|
-
// Check for API errors
|
|
76
|
-
if (responseData.error) {
|
|
77
|
-
throw new Error(`Marketstack API error: ${responseData.error.message || JSON.stringify(responseData.error)}`);
|
|
78
|
-
}
|
|
79
|
-
// For single ticker endpoint, response is direct object (not wrapped in data field)
|
|
80
|
-
if (!responseData || !responseData.close) {
|
|
81
|
-
throw new Error(`No data found for ticker ${request.ticker}`);
|
|
81
|
+
else {
|
|
82
|
+
// Use EOD endpoint for after-close data
|
|
83
|
+
return await this.fetchCurrentPriceEod(request);
|
|
82
84
|
}
|
|
83
|
-
return this.mapToStockPrice(responseData, 'eod');
|
|
84
85
|
}
|
|
85
86
|
catch (error) {
|
|
86
|
-
|
|
87
|
-
|
|
87
|
+
// If intraday fails, fallback to EOD with warning
|
|
88
|
+
if (error.message?.includes('intraday') || error.message?.includes('Marketstack API error')) {
|
|
89
|
+
this.logger.warn(`Intraday endpoint failed for ${request.ticker}, falling back to EOD:`, error.message);
|
|
90
|
+
try {
|
|
91
|
+
return await this.fetchCurrentPriceEod(request);
|
|
92
|
+
}
|
|
93
|
+
catch (eodError) {
|
|
94
|
+
// Both failed, throw original error
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
throw error;
|
|
88
99
|
}
|
|
89
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Fetch current price using intraday endpoint (during market hours)
|
|
103
|
+
* Uses 1min interval for most recent data
|
|
104
|
+
*/
|
|
105
|
+
async fetchCurrentPriceIntraday(request, marketState) {
|
|
106
|
+
const formattedSymbol = this.formatSymbolForIntraday(request.ticker);
|
|
107
|
+
let url = `${this.baseUrl}/tickers/${formattedSymbol}/intraday/latest?access_key=${this.apiKey}`;
|
|
108
|
+
url += `&interval=1min`; // Use 1min for most recent data
|
|
109
|
+
// Add exchange filter if specified
|
|
110
|
+
if (request.exchange) {
|
|
111
|
+
url += `&exchange=${request.exchange}`;
|
|
112
|
+
}
|
|
113
|
+
const response = await plugins.smartrequest.SmartRequest.create()
|
|
114
|
+
.url(url)
|
|
115
|
+
.timeout(this.config?.timeout || 10000)
|
|
116
|
+
.get();
|
|
117
|
+
const responseData = await response.json();
|
|
118
|
+
// Check for API errors
|
|
119
|
+
if (responseData.error) {
|
|
120
|
+
throw new Error(`Marketstack API error: ${responseData.error.message || JSON.stringify(responseData.error)}`);
|
|
121
|
+
}
|
|
122
|
+
if (!responseData || !responseData.close) {
|
|
123
|
+
throw new Error(`No intraday data found for ticker ${request.ticker}`);
|
|
124
|
+
}
|
|
125
|
+
return this.mapToStockPrice(responseData, 'intraday', marketState);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Fetch current price using EOD endpoint (after market close)
|
|
129
|
+
*/
|
|
130
|
+
async fetchCurrentPriceEod(request) {
|
|
131
|
+
let url = `${this.baseUrl}/tickers/${request.ticker}/eod/latest?access_key=${this.apiKey}`;
|
|
132
|
+
// Add exchange filter if specified
|
|
133
|
+
if (request.exchange) {
|
|
134
|
+
url += `&exchange=${request.exchange}`;
|
|
135
|
+
}
|
|
136
|
+
const response = await plugins.smartrequest.SmartRequest.create()
|
|
137
|
+
.url(url)
|
|
138
|
+
.timeout(this.config?.timeout || 10000)
|
|
139
|
+
.get();
|
|
140
|
+
const responseData = await response.json();
|
|
141
|
+
// Check for API errors
|
|
142
|
+
if (responseData.error) {
|
|
143
|
+
throw new Error(`Marketstack API error: ${responseData.error.message || JSON.stringify(responseData.error)}`);
|
|
144
|
+
}
|
|
145
|
+
// For single ticker endpoint, response is direct object (not wrapped in data field)
|
|
146
|
+
if (!responseData || !responseData.close) {
|
|
147
|
+
throw new Error(`No data found for ticker ${request.ticker}`);
|
|
148
|
+
}
|
|
149
|
+
return this.mapToStockPrice(responseData, 'eod');
|
|
150
|
+
}
|
|
90
151
|
/**
|
|
91
152
|
* Fetch historical EOD prices for a ticker with date range
|
|
92
153
|
*/
|
|
@@ -147,52 +208,177 @@ export class MarketstackProvider {
|
|
|
147
208
|
}
|
|
148
209
|
}
|
|
149
210
|
/**
|
|
150
|
-
* Fetch intraday prices with specified interval
|
|
211
|
+
* Fetch intraday prices with specified interval
|
|
212
|
+
* Supports intervals: 1min, 5min, 10min, 15min, 30min, 1hour
|
|
213
|
+
* Note: Intervals below 15min require Professional Plan or higher
|
|
151
214
|
*/
|
|
152
215
|
async fetchIntradayPrices(request) {
|
|
153
|
-
|
|
216
|
+
try {
|
|
217
|
+
const allPrices = [];
|
|
218
|
+
let offset = 0;
|
|
219
|
+
const limit = 1000; // Max per page for intraday
|
|
220
|
+
const maxRecords = 10000; // Safety limit
|
|
221
|
+
// Format symbol for intraday endpoint (replace . with -)
|
|
222
|
+
const formattedSymbol = this.formatSymbolForIntraday(request.ticker);
|
|
223
|
+
while (true) {
|
|
224
|
+
let url = `${this.baseUrl}/tickers/${formattedSymbol}/intraday?access_key=${this.apiKey}`;
|
|
225
|
+
url += `&interval=${request.interval}`;
|
|
226
|
+
url += `&limit=${limit}`;
|
|
227
|
+
url += `&offset=${offset}`;
|
|
228
|
+
// Add date filter if specified
|
|
229
|
+
if (request.date) {
|
|
230
|
+
url += `&date_from=${this.formatDate(request.date)}`;
|
|
231
|
+
url += `&date_to=${this.formatDate(request.date)}`;
|
|
232
|
+
}
|
|
233
|
+
// Add exchange filter if specified
|
|
234
|
+
if (request.exchange) {
|
|
235
|
+
url += `&exchange=${request.exchange}`;
|
|
236
|
+
}
|
|
237
|
+
const response = await plugins.smartrequest.SmartRequest.create()
|
|
238
|
+
.url(url)
|
|
239
|
+
.timeout(this.config?.timeout || 15000)
|
|
240
|
+
.get();
|
|
241
|
+
const responseData = await response.json();
|
|
242
|
+
// Check for API errors
|
|
243
|
+
if (responseData.error) {
|
|
244
|
+
throw new Error(`Marketstack API error: ${responseData.error.message || JSON.stringify(responseData.error)}`);
|
|
245
|
+
}
|
|
246
|
+
if (!responseData?.data || !Array.isArray(responseData.data)) {
|
|
247
|
+
throw new Error('Invalid response format from Marketstack API');
|
|
248
|
+
}
|
|
249
|
+
// Map data to stock prices
|
|
250
|
+
for (const data of responseData.data) {
|
|
251
|
+
try {
|
|
252
|
+
allPrices.push(this.mapToStockPrice(data, 'intraday'));
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
this.logger.warn(`Failed to parse intraday data for ${data.symbol}:`, error);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// Check if we have more pages
|
|
259
|
+
const pagination = responseData.pagination;
|
|
260
|
+
const hasMore = pagination && offset + limit < pagination.total;
|
|
261
|
+
// Honor limit from request if specified, or safety limit
|
|
262
|
+
if (!hasMore || (request.limit && allPrices.length >= request.limit) || allPrices.length >= maxRecords) {
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
offset += limit;
|
|
266
|
+
}
|
|
267
|
+
// Apply limit if specified
|
|
268
|
+
if (request.limit && allPrices.length > request.limit) {
|
|
269
|
+
return allPrices.slice(0, request.limit);
|
|
270
|
+
}
|
|
271
|
+
return allPrices;
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
this.logger.error(`Failed to fetch intraday prices for ${request.ticker}:`, error);
|
|
275
|
+
throw new Error(`Marketstack: Failed to fetch intraday prices for ${request.ticker}: ${error.message}`);
|
|
276
|
+
}
|
|
154
277
|
}
|
|
155
278
|
/**
|
|
156
|
-
* Fetch current prices for multiple tickers
|
|
279
|
+
* Fetch current prices for multiple tickers with intelligent endpoint selection
|
|
280
|
+
* Uses intraday during market hours (PRE, REGULAR, POST) for fresh data
|
|
281
|
+
* Uses EOD after market close (CLOSED) to save API credits
|
|
157
282
|
*/
|
|
158
283
|
async fetchBatchCurrentPrices(request) {
|
|
159
284
|
try {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const response = await plugins.smartrequest.SmartRequest.create()
|
|
166
|
-
.url(url)
|
|
167
|
-
.timeout(this.config?.timeout || 15000)
|
|
168
|
-
.get();
|
|
169
|
-
const responseData = await response.json();
|
|
170
|
-
// Check for API errors
|
|
171
|
-
if (responseData.error) {
|
|
172
|
-
throw new Error(`Marketstack API error: ${responseData.error.message || JSON.stringify(responseData.error)}`);
|
|
285
|
+
// Determine current market state
|
|
286
|
+
const marketState = this.getUsMarketState();
|
|
287
|
+
const useIntraday = this.shouldUseIntradayEndpoint(marketState);
|
|
288
|
+
if (useIntraday) {
|
|
289
|
+
return await this.fetchBatchCurrentPricesIntraday(request, marketState);
|
|
173
290
|
}
|
|
174
|
-
|
|
175
|
-
|
|
291
|
+
else {
|
|
292
|
+
return await this.fetchBatchCurrentPricesEod(request);
|
|
176
293
|
}
|
|
177
|
-
|
|
178
|
-
|
|
294
|
+
}
|
|
295
|
+
catch (error) {
|
|
296
|
+
// Fallback to EOD if intraday fails
|
|
297
|
+
if (error.message?.includes('intraday') || error.message?.includes('Marketstack API error')) {
|
|
298
|
+
this.logger.warn(`Intraday batch endpoint failed, falling back to EOD:`, error.message);
|
|
179
299
|
try {
|
|
180
|
-
|
|
300
|
+
return await this.fetchBatchCurrentPricesEod(request);
|
|
181
301
|
}
|
|
182
|
-
catch (
|
|
183
|
-
|
|
184
|
-
|
|
302
|
+
catch (eodError) {
|
|
303
|
+
// Both failed, throw original error
|
|
304
|
+
throw error;
|
|
185
305
|
}
|
|
186
306
|
}
|
|
187
|
-
|
|
188
|
-
|
|
307
|
+
throw error;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Fetch batch current prices using intraday endpoint
|
|
312
|
+
*/
|
|
313
|
+
async fetchBatchCurrentPricesIntraday(request, marketState) {
|
|
314
|
+
// Format symbols for intraday (replace . with -)
|
|
315
|
+
const formattedSymbols = request.tickers.map(t => this.formatSymbolForIntraday(t)).join(',');
|
|
316
|
+
let url = `${this.baseUrl}/intraday/latest?access_key=${this.apiKey}`;
|
|
317
|
+
url += `&symbols=${formattedSymbols}`;
|
|
318
|
+
url += `&interval=1min`; // Use 1min for most recent data
|
|
319
|
+
if (request.exchange) {
|
|
320
|
+
url += `&exchange=${request.exchange}`;
|
|
321
|
+
}
|
|
322
|
+
const response = await plugins.smartrequest.SmartRequest.create()
|
|
323
|
+
.url(url)
|
|
324
|
+
.timeout(this.config?.timeout || 15000)
|
|
325
|
+
.get();
|
|
326
|
+
const responseData = await response.json();
|
|
327
|
+
if (responseData.error) {
|
|
328
|
+
throw new Error(`Marketstack API error: ${responseData.error.message || JSON.stringify(responseData.error)}`);
|
|
329
|
+
}
|
|
330
|
+
if (!responseData?.data || !Array.isArray(responseData.data)) {
|
|
331
|
+
throw new Error('Invalid response format from Marketstack API');
|
|
332
|
+
}
|
|
333
|
+
const prices = [];
|
|
334
|
+
for (const data of responseData.data) {
|
|
335
|
+
try {
|
|
336
|
+
prices.push(this.mapToStockPrice(data, 'intraday', marketState));
|
|
337
|
+
}
|
|
338
|
+
catch (error) {
|
|
339
|
+
this.logger.warn(`Failed to parse intraday data for ${data.symbol}:`, error);
|
|
189
340
|
}
|
|
190
|
-
return prices;
|
|
191
341
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
throw new Error(`Marketstack: Failed to fetch batch current prices: ${error.message}`);
|
|
342
|
+
if (prices.length === 0) {
|
|
343
|
+
throw new Error('No valid price data received from batch intraday request');
|
|
195
344
|
}
|
|
345
|
+
return prices;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Fetch batch current prices using EOD endpoint
|
|
349
|
+
*/
|
|
350
|
+
async fetchBatchCurrentPricesEod(request) {
|
|
351
|
+
const symbols = request.tickers.join(',');
|
|
352
|
+
let url = `${this.baseUrl}/eod/latest?access_key=${this.apiKey}&symbols=${symbols}`;
|
|
353
|
+
if (request.exchange) {
|
|
354
|
+
url += `&exchange=${request.exchange}`;
|
|
355
|
+
}
|
|
356
|
+
const response = await plugins.smartrequest.SmartRequest.create()
|
|
357
|
+
.url(url)
|
|
358
|
+
.timeout(this.config?.timeout || 15000)
|
|
359
|
+
.get();
|
|
360
|
+
const responseData = await response.json();
|
|
361
|
+
// Check for API errors
|
|
362
|
+
if (responseData.error) {
|
|
363
|
+
throw new Error(`Marketstack API error: ${responseData.error.message || JSON.stringify(responseData.error)}`);
|
|
364
|
+
}
|
|
365
|
+
if (!responseData?.data || !Array.isArray(responseData.data)) {
|
|
366
|
+
throw new Error('Invalid response format from Marketstack API');
|
|
367
|
+
}
|
|
368
|
+
const prices = [];
|
|
369
|
+
for (const data of responseData.data) {
|
|
370
|
+
try {
|
|
371
|
+
prices.push(this.mapToStockPrice(data, 'eod'));
|
|
372
|
+
}
|
|
373
|
+
catch (error) {
|
|
374
|
+
this.logger.warn(`Failed to parse data for ${data.symbol}:`, error);
|
|
375
|
+
// Continue processing other tickers
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
if (prices.length === 0) {
|
|
379
|
+
throw new Error('No valid price data received from batch request');
|
|
380
|
+
}
|
|
381
|
+
return prices;
|
|
196
382
|
}
|
|
197
383
|
/**
|
|
198
384
|
* Check if the Marketstack API is available and accessible
|
|
@@ -237,8 +423,11 @@ export class MarketstackProvider {
|
|
|
237
423
|
}
|
|
238
424
|
/**
|
|
239
425
|
* Map Marketstack API response to IStockPrice interface
|
|
426
|
+
* @param data - API response data
|
|
427
|
+
* @param dataType - Type of data (eod, intraday, live)
|
|
428
|
+
* @param explicitMarketState - Override market state (used for intraday data fetched during known market hours)
|
|
240
429
|
*/
|
|
241
|
-
mapToStockPrice(data, dataType = 'eod') {
|
|
430
|
+
mapToStockPrice(data, dataType = 'eod', explicitMarketState) {
|
|
242
431
|
if (!data.close) {
|
|
243
432
|
throw new Error('Missing required price data');
|
|
244
433
|
}
|
|
@@ -252,6 +441,24 @@ export class MarketstackProvider {
|
|
|
252
441
|
// Parse timestamp
|
|
253
442
|
const timestamp = data.date ? new Date(data.date) : new Date();
|
|
254
443
|
const fetchedAt = new Date();
|
|
444
|
+
// Determine market state intelligently
|
|
445
|
+
let marketState;
|
|
446
|
+
if (explicitMarketState) {
|
|
447
|
+
// Use provided market state (for intraday data fetched during known market hours)
|
|
448
|
+
marketState = explicitMarketState;
|
|
449
|
+
}
|
|
450
|
+
else if (dataType === 'eod') {
|
|
451
|
+
// EOD data is always for closed markets
|
|
452
|
+
marketState = 'CLOSED';
|
|
453
|
+
}
|
|
454
|
+
else if (dataType === 'intraday') {
|
|
455
|
+
// For intraday data without explicit state, determine from timestamp
|
|
456
|
+
marketState = this.getUsMarketState(timestamp.getTime());
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
// Default fallback
|
|
460
|
+
marketState = 'CLOSED';
|
|
461
|
+
}
|
|
255
462
|
const stockPrice = {
|
|
256
463
|
ticker: data.symbol.toUpperCase(),
|
|
257
464
|
price: currentPrice,
|
|
@@ -261,7 +468,7 @@ export class MarketstackProvider {
|
|
|
261
468
|
previousClose: previousClose,
|
|
262
469
|
timestamp: timestamp,
|
|
263
470
|
provider: this.name,
|
|
264
|
-
marketState:
|
|
471
|
+
marketState: marketState, // Now dynamic based on data type, timestamp, and explicit state
|
|
265
472
|
exchange: data.exchange,
|
|
266
473
|
exchangeName: data.exchange_code || data.name,
|
|
267
474
|
// Phase 1 enhancements: OHLCV data
|
|
@@ -314,5 +521,71 @@ export class MarketstackProvider {
|
|
|
314
521
|
const day = String(date.getDate()).padStart(2, '0');
|
|
315
522
|
return `${year}-${month}-${day}`;
|
|
316
523
|
}
|
|
524
|
+
/**
|
|
525
|
+
* Get US market state based on Eastern Time
|
|
526
|
+
* Regular hours: 9:30 AM - 4:00 PM ET
|
|
527
|
+
* Pre-market: 4:00 AM - 9:30 AM ET
|
|
528
|
+
* After-hours: 4:00 PM - 8:00 PM ET
|
|
529
|
+
*
|
|
530
|
+
* @param timestampMs - Optional timestamp in milliseconds (defaults to current time)
|
|
531
|
+
* @returns Market state: PRE, REGULAR, POST, or CLOSED
|
|
532
|
+
*/
|
|
533
|
+
getUsMarketState(timestampMs) {
|
|
534
|
+
const now = timestampMs ? new Date(timestampMs) : new Date();
|
|
535
|
+
// Convert to ET (UTC-5 or UTC-4 depending on DST)
|
|
536
|
+
// For simplicity, we'll use a rough approximation
|
|
537
|
+
// TODO: Add proper timezone library for production use
|
|
538
|
+
const etOffset = -5; // Standard time, adjust for DST if needed
|
|
539
|
+
const etTime = new Date(now.getTime() + (etOffset * 60 * 60 * 1000));
|
|
540
|
+
// Get day of week (0 = Sunday, 6 = Saturday)
|
|
541
|
+
const dayOfWeek = etTime.getUTCDay();
|
|
542
|
+
// Check if weekend
|
|
543
|
+
if (dayOfWeek === 0 || dayOfWeek === 6) {
|
|
544
|
+
return 'CLOSED';
|
|
545
|
+
}
|
|
546
|
+
// Get hour and minute in ET
|
|
547
|
+
const hours = etTime.getUTCHours();
|
|
548
|
+
const minutes = etTime.getUTCMinutes();
|
|
549
|
+
const timeInMinutes = hours * 60 + minutes;
|
|
550
|
+
// Define market hours in minutes
|
|
551
|
+
const preMarketStart = 4 * 60; // 4:00 AM
|
|
552
|
+
const regularMarketStart = 9 * 60 + 30; // 9:30 AM
|
|
553
|
+
const regularMarketEnd = 16 * 60; // 4:00 PM
|
|
554
|
+
const afterHoursEnd = 20 * 60; // 8:00 PM
|
|
555
|
+
if (timeInMinutes >= preMarketStart && timeInMinutes < regularMarketStart) {
|
|
556
|
+
return 'PRE';
|
|
557
|
+
}
|
|
558
|
+
else if (timeInMinutes >= regularMarketStart && timeInMinutes < regularMarketEnd) {
|
|
559
|
+
return 'REGULAR';
|
|
560
|
+
}
|
|
561
|
+
else if (timeInMinutes >= regularMarketEnd && timeInMinutes < afterHoursEnd) {
|
|
562
|
+
return 'POST';
|
|
563
|
+
}
|
|
564
|
+
else {
|
|
565
|
+
return 'CLOSED';
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Determine if intraday endpoint should be used based on market state
|
|
570
|
+
* Uses intraday for PRE, REGULAR, and POST market states
|
|
571
|
+
* Uses EOD for CLOSED state to save API credits
|
|
572
|
+
*
|
|
573
|
+
* @param marketState - Current market state
|
|
574
|
+
* @returns true if intraday endpoint should be used
|
|
575
|
+
*/
|
|
576
|
+
shouldUseIntradayEndpoint(marketState) {
|
|
577
|
+
return marketState !== 'CLOSED';
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Format ticker symbol for intraday endpoints
|
|
581
|
+
* Marketstack intraday API requires periods to be replaced with hyphens
|
|
582
|
+
* Example: BRK.B → BRK-B
|
|
583
|
+
*
|
|
584
|
+
* @param symbol - Original ticker symbol
|
|
585
|
+
* @returns Formatted symbol for intraday endpoints
|
|
586
|
+
*/
|
|
587
|
+
formatSymbolForIntraday(symbol) {
|
|
588
|
+
return symbol.replace(/\./g, '-');
|
|
589
|
+
}
|
|
317
590
|
}
|
|
318
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZXIubWFya2V0c3RhY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9zdG9ja3MvcHJvdmlkZXJzL3Byb3ZpZGVyLm1hcmtldHN0YWNrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFXNUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBdUJHO0FBQ0gsTUFBTSxPQUFPLG1CQUFtQjtJQWE5QixZQUFZLE1BQWMsRUFBVSxNQUF3QjtRQUF4QixXQUFNLEdBQU4sTUFBTSxDQUFrQjtRQVpyRCxTQUFJLEdBQUcsYUFBYSxDQUFDO1FBQ3JCLGFBQVEsR0FBRyxFQUFFLENBQUMsQ0FBQyw4REFBOEQ7UUFDcEUsaUJBQVksR0FBRyxJQUFJLENBQUM7UUFDcEIsY0FBUyxHQUFHO1lBQzFCLGlCQUFpQixFQUFFLFNBQVMsRUFBRSxnQ0FBZ0M7WUFDOUQsY0FBYyxFQUFFLFNBQVMsQ0FBQyxpQkFBaUI7U0FDNUMsQ0FBQztRQUVNLFdBQU0sR0FBRyxPQUFPLENBQUM7UUFDakIsWUFBTyxHQUFHLGdDQUFnQyxDQUFDO1FBSWpELElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNaLE1BQU0sSUFBSSxLQUFLLENBQUMsOENBQThDLENBQUMsQ0FBQztRQUNsRSxDQUFDO1FBRUQsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7SUFDdkIsQ0FBQztJQUVEOztPQUVHO0lBQ0ksS0FBSyxDQUFDLFNBQVMsQ0FBQyxPQUEwQjtRQUMvQyxRQUFRLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNyQixLQUFLLFNBQVM7Z0JBQ1osT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDekMsS0FBSyxZQUFZO2dCQUNmLE9BQU8sSUFBSSxDQUFDLHFCQUFxQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzdDLEtBQUssVUFBVTtnQkFDYixPQUFP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
|
|
591
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZXIubWFya2V0c3RhY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9zdG9ja3MvcHJvdmlkZXJzL3Byb3ZpZGVyLm1hcmtldHN0YWNrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFXNUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQThCRztBQUNILE1BQU0sT0FBTyxtQkFBbUI7SUFhOUIsWUFBWSxNQUFjLEVBQVUsTUFBd0I7UUFBeEIsV0FBTSxHQUFOLE1BQU0sQ0FBa0I7UUFackQsU0FBSSxHQUFHLGFBQWEsQ0FBQztRQUNyQixhQUFRLEdBQUcsRUFBRSxDQUFDLENBQUMsK0VBQStFO1FBQ3JGLGlCQUFZLEdBQUcsSUFBSSxDQUFDO1FBQ3BCLGNBQVMsR0FBRztZQUMxQixpQkFBaUIsRUFBRSxTQUFTLEVBQUUsZ0NBQWdDO1lBQzlELGNBQWMsRUFBRSxTQUFTLENBQUMsaUJBQWlCO1NBQzVDLENBQUM7UUFFTSxXQUFNLEdBQUcsT0FBTyxDQUFDO1FBQ2pCLFlBQU8sR0FBRyxnQ0FBZ0MsQ0FBQztRQUlqRCxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDWixNQUFNLElBQUksS0FBSyxDQUFDLDhDQUE4QyxDQUFDLENBQUM7UUFDbEUsQ0FBQztRQUVELElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0lBQ3ZCLENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxTQUFTLENBQUMsT0FBMEI7UUFDL0MsUUFBUSxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDckIsS0FBSyxTQUFTO2dCQUNaLE9BQU8sSUFBSSxDQUFDLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3pDLEtBQUssWUFBWTtnQkFDZixPQUFPLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUM3QyxLQUFLLFVBQVU7Z0JB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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fin.cx/opendata",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A comprehensive TypeScript library for accessing business data and real-time financial information. Features include German company data management with MongoDB integration, JSONL bulk processing, automated Handelsregister interactions, and real-time stock market data from multiple providers.",
|
|
6
6
|
"main": "dist_ts/index.js",
|
package/readme.hints.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
## Stocks Module
|
|
4
4
|
|
|
5
5
|
### Overview
|
|
6
|
-
The stocks module provides real-time stock price data through various provider implementations. Currently supports Yahoo Finance with an extensible architecture for additional providers.
|
|
6
|
+
The stocks module provides real-time stock price data and cryptocurrency prices through various provider implementations. Currently supports Yahoo Finance, Marketstack, and CoinGecko with an extensible architecture for additional providers.
|
|
7
7
|
|
|
8
8
|
### Architecture
|
|
9
9
|
- **Provider Pattern**: Each stock data source implements the `IStockProvider` interface
|
|
@@ -31,11 +31,55 @@ const price = await stockService.getPrice({ ticker: 'AAPL' });
|
|
|
31
31
|
console.log(`${price.ticker}: $${price.price}`);
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
+
### CoinGecko Provider Notes
|
|
35
|
+
- Cryptocurrency price provider supporting 13M+ tokens
|
|
36
|
+
- Three main endpoints:
|
|
37
|
+
- `/simple/price` - Current prices with market data (batch supported)
|
|
38
|
+
- `/coins/{id}/market_chart` - Historical and intraday prices with OHLCV
|
|
39
|
+
- `/coins/list` - Complete coin list for ticker-to-ID mapping
|
|
40
|
+
- **Rate Limiting**:
|
|
41
|
+
- Free tier: 5-15 calls/minute (no registration)
|
|
42
|
+
- Demo plan: 30 calls/minute, 10,000/month (free with registration)
|
|
43
|
+
- Custom rate limiter tracks requests per minute
|
|
44
|
+
- **Ticker Resolution**:
|
|
45
|
+
- Accepts both ticker symbols (BTC, ETH) and CoinGecko IDs (bitcoin, ethereum)
|
|
46
|
+
- Lazy-loads coin list on first ticker resolution
|
|
47
|
+
- Caches coin mappings for 24 hours
|
|
48
|
+
- IDs with hyphens (wrapped-bitcoin) assumed to be CoinGecko IDs
|
|
49
|
+
- **24/7 Markets**: Crypto markets always return `marketState: 'REGULAR'`
|
|
50
|
+
- **Optional API Key**: Pass key to constructor for higher rate limits
|
|
51
|
+
- Demo plan: `x-cg-demo-api-key` header
|
|
52
|
+
- Paid plans: `x-cg-pro-api-key` header
|
|
53
|
+
- **Data Granularity**:
|
|
54
|
+
- Historical: Daily data for date ranges
|
|
55
|
+
- Intraday: Hourly data only (1-90 days based on `days` param)
|
|
56
|
+
- Current: Real-time prices with 24h change and volume
|
|
57
|
+
|
|
58
|
+
### Usage Example (Crypto)
|
|
59
|
+
```typescript
|
|
60
|
+
import { StockPriceService, CoinGeckoProvider } from '@fin.cx/opendata';
|
|
61
|
+
|
|
62
|
+
const stockService = new StockPriceService({ ttl: 30000 });
|
|
63
|
+
const coingeckoProvider = new CoinGeckoProvider(); // or new CoinGeckoProvider('api-key')
|
|
64
|
+
stockService.register(coingeckoProvider);
|
|
65
|
+
|
|
66
|
+
// Using ticker symbol
|
|
67
|
+
const btc = await stockService.getPrice({ ticker: 'BTC' });
|
|
68
|
+
console.log(`${btc.ticker}: $${btc.price}`);
|
|
69
|
+
|
|
70
|
+
// Using CoinGecko ID
|
|
71
|
+
const ethereum = await stockService.getPrice({ ticker: 'ethereum' });
|
|
72
|
+
|
|
73
|
+
// Batch fetch
|
|
74
|
+
const cryptos = await stockService.getPrices({ tickers: ['BTC', 'ETH', 'USDT'] });
|
|
75
|
+
```
|
|
76
|
+
|
|
34
77
|
### Testing
|
|
35
78
|
- Tests use real API calls (be mindful of rate limits)
|
|
36
79
|
- Mock invalid ticker 'INVALID_TICKER_XYZ' for error testing
|
|
37
80
|
- Clear cache between tests to ensure fresh data
|
|
38
81
|
- The spark endpoint may return fewer results than requested
|
|
82
|
+
- CoinGecko tests may take longer due to rate limiting (wait between requests)
|
|
39
83
|
|
|
40
84
|
### Future Providers
|
|
41
85
|
To add a new provider:
|