@fin.cx/opendata 3.1.0 → 3.2.2
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/classes.handelsregister.js +2 -2
- package/dist_ts/plugins.d.ts +1 -1
- package/dist_ts/plugins.js +2 -2
- package/dist_ts/stocks/classes.baseproviderservice.d.ts +129 -0
- package/dist_ts/stocks/classes.baseproviderservice.js +204 -0
- package/dist_ts/stocks/classes.stockdataservice.d.ts +121 -0
- package/dist_ts/stocks/classes.stockdataservice.js +495 -0
- package/dist_ts/stocks/index.d.ts +3 -0
- package/dist_ts/stocks/index.js +5 -1
- package/dist_ts/stocks/interfaces/stockdata.d.ts +57 -0
- package/dist_ts/stocks/interfaces/stockdata.js +2 -0
- package/dist_ts/stocks/providers/provider.secedgar.d.ts +3 -0
- package/dist_ts/stocks/providers/provider.secedgar.js +72 -41
- package/package.json +4 -4
- package/readme.md +133 -61
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.handelsregister.ts +1 -1
- package/ts/plugins.ts +1 -1
- package/ts/stocks/classes.baseproviderservice.ts +296 -0
- package/ts/stocks/classes.stockdataservice.ts +647 -0
- package/ts/stocks/index.ts +5 -0
- package/ts/stocks/interfaces/stockdata.ts +65 -0
- package/ts/stocks/providers/provider.secedgar.ts +81 -43
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { IStockPrice } from './stockprice.js';
|
|
2
|
+
import type { IStockFundamentals } from './fundamentals.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Combined stock data with price and fundamentals
|
|
6
|
+
* All calculated metrics (market cap, P/E, P/B) are automatically included
|
|
7
|
+
*/
|
|
8
|
+
export interface IStockData {
|
|
9
|
+
/** Stock ticker symbol */
|
|
10
|
+
ticker: string;
|
|
11
|
+
|
|
12
|
+
/** Price information */
|
|
13
|
+
price: IStockPrice;
|
|
14
|
+
|
|
15
|
+
/** Fundamental data (optional - may not be available for all stocks) */
|
|
16
|
+
fundamentals?: IStockFundamentals;
|
|
17
|
+
|
|
18
|
+
/** When this combined data was fetched */
|
|
19
|
+
fetchedAt: Date;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Configuration for StockDataService
|
|
24
|
+
*/
|
|
25
|
+
export interface IStockDataServiceConfig {
|
|
26
|
+
/** Cache configuration */
|
|
27
|
+
cache?: {
|
|
28
|
+
/** TTL for price data (default: 24 hours) */
|
|
29
|
+
priceTTL?: number;
|
|
30
|
+
/** TTL for fundamentals data (default: 90 days) */
|
|
31
|
+
fundamentalsTTL?: number;
|
|
32
|
+
/** Max cache entries (default: 10000) */
|
|
33
|
+
maxEntries?: number;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/** Provider timeouts */
|
|
37
|
+
timeout?: {
|
|
38
|
+
/** Timeout for price providers (default: 10000ms) */
|
|
39
|
+
price?: number;
|
|
40
|
+
/** Timeout for fundamentals providers (default: 30000ms) */
|
|
41
|
+
fundamentals?: number;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Request type for getting complete stock data
|
|
47
|
+
*/
|
|
48
|
+
export interface ICompleteStockDataRequest {
|
|
49
|
+
ticker: string;
|
|
50
|
+
/** Whether to include fundamentals (default: true) */
|
|
51
|
+
includeFundamentals?: boolean;
|
|
52
|
+
/** Whether to enrich fundamentals with price calculations (default: true) */
|
|
53
|
+
enrichFundamentals?: boolean;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Batch request for multiple stocks
|
|
58
|
+
*/
|
|
59
|
+
export interface ICompleteStockDataBatchRequest {
|
|
60
|
+
tickers: string[];
|
|
61
|
+
/** Whether to include fundamentals (default: true) */
|
|
62
|
+
includeFundamentals?: boolean;
|
|
63
|
+
/** Whether to enrich fundamentals with price calculations (default: true) */
|
|
64
|
+
enrichFundamentals?: boolean;
|
|
65
|
+
}
|
|
@@ -217,6 +217,7 @@ export class SecEdgarProvider implements IFundamentalsProvider {
|
|
|
217
217
|
/**
|
|
218
218
|
* Fetch the SEC ticker-to-CIK mapping list
|
|
219
219
|
* Cached for 24 hours (list updates daily)
|
|
220
|
+
* Uses native fetch for automatic gzip decompression
|
|
220
221
|
*/
|
|
221
222
|
private async fetchTickerList(): Promise<any> {
|
|
222
223
|
// Check cache
|
|
@@ -230,29 +231,44 @@ export class SecEdgarProvider implements IFundamentalsProvider {
|
|
|
230
231
|
// Wait for rate limit slot
|
|
231
232
|
await this.rateLimiter.waitForSlot();
|
|
232
233
|
|
|
233
|
-
// Fetch from SEC
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
234
|
+
// Fetch from SEC using native fetch (handles gzip automatically)
|
|
235
|
+
const controller = new AbortController();
|
|
236
|
+
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
237
|
+
|
|
238
|
+
try {
|
|
239
|
+
const response = await fetch(this.tickersUrl, {
|
|
240
|
+
headers: {
|
|
241
|
+
'User-Agent': this.userAgent,
|
|
242
|
+
'Accept': 'application/json'
|
|
243
|
+
// Note: Accept-Encoding is set automatically by fetch
|
|
244
|
+
},
|
|
245
|
+
signal: controller.signal
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
clearTimeout(timeoutId);
|
|
249
|
+
|
|
250
|
+
if (!response.ok) {
|
|
251
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const data = await response.json();
|
|
255
|
+
|
|
256
|
+
// Cache the list
|
|
257
|
+
this.tickerListCache = {
|
|
258
|
+
data,
|
|
259
|
+
timestamp: new Date()
|
|
260
|
+
};
|
|
250
261
|
|
|
251
|
-
|
|
262
|
+
return data;
|
|
263
|
+
} catch (error) {
|
|
264
|
+
clearTimeout(timeoutId);
|
|
265
|
+
throw error;
|
|
266
|
+
}
|
|
252
267
|
}
|
|
253
268
|
|
|
254
269
|
/**
|
|
255
270
|
* Fetch company facts from SEC EDGAR
|
|
271
|
+
* Uses native fetch for automatic gzip decompression
|
|
256
272
|
*/
|
|
257
273
|
private async fetchCompanyFacts(cik: string): Promise<any> {
|
|
258
274
|
// Pad CIK to 10 digits
|
|
@@ -262,26 +278,39 @@ export class SecEdgarProvider implements IFundamentalsProvider {
|
|
|
262
278
|
// Wait for rate limit slot
|
|
263
279
|
await this.rateLimiter.waitForSlot();
|
|
264
280
|
|
|
265
|
-
// Fetch from SEC
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
.headers({
|
|
269
|
-
'User-Agent': this.userAgent,
|
|
270
|
-
'Accept': 'application/json',
|
|
271
|
-
'Accept-Encoding': 'gzip, deflate',
|
|
272
|
-
'Host': 'data.sec.gov'
|
|
273
|
-
})
|
|
274
|
-
.timeout(this.config.timeout)
|
|
275
|
-
.get();
|
|
276
|
-
|
|
277
|
-
const data = await response.json();
|
|
278
|
-
|
|
279
|
-
// Validate response
|
|
280
|
-
if (!data || !data.facts) {
|
|
281
|
-
throw new Error('Invalid response from SEC EDGAR API');
|
|
282
|
-
}
|
|
281
|
+
// Fetch from SEC using native fetch (handles gzip automatically)
|
|
282
|
+
const controller = new AbortController();
|
|
283
|
+
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
283
284
|
|
|
284
|
-
|
|
285
|
+
try {
|
|
286
|
+
const response = await fetch(url, {
|
|
287
|
+
headers: {
|
|
288
|
+
'User-Agent': this.userAgent,
|
|
289
|
+
'Accept': 'application/json',
|
|
290
|
+
'Host': 'data.sec.gov'
|
|
291
|
+
// Note: Accept-Encoding is set automatically by fetch and gzip is handled transparently
|
|
292
|
+
},
|
|
293
|
+
signal: controller.signal
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
clearTimeout(timeoutId);
|
|
297
|
+
|
|
298
|
+
if (!response.ok) {
|
|
299
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const data = await response.json();
|
|
303
|
+
|
|
304
|
+
// Validate response
|
|
305
|
+
if (!data || !data.facts) {
|
|
306
|
+
throw new Error('Invalid response from SEC EDGAR API');
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return data;
|
|
310
|
+
} catch (error) {
|
|
311
|
+
clearTimeout(timeoutId);
|
|
312
|
+
throw error;
|
|
313
|
+
}
|
|
285
314
|
}
|
|
286
315
|
|
|
287
316
|
/**
|
|
@@ -382,20 +411,29 @@ export class SecEdgarProvider implements IFundamentalsProvider {
|
|
|
382
411
|
|
|
383
412
|
/**
|
|
384
413
|
* Check if SEC EDGAR API is available
|
|
414
|
+
* Uses native fetch for automatic gzip decompression
|
|
385
415
|
*/
|
|
386
416
|
public async isAvailable(): Promise<boolean> {
|
|
387
417
|
try {
|
|
388
418
|
// Test with Apple's well-known CIK
|
|
389
419
|
const url = `${this.baseUrl}/companyfacts/CIK0000320193.json`;
|
|
390
420
|
|
|
391
|
-
const
|
|
392
|
-
|
|
393
|
-
|
|
421
|
+
const controller = new AbortController();
|
|
422
|
+
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
|
423
|
+
|
|
424
|
+
const response = await fetch(url, {
|
|
425
|
+
headers: {
|
|
394
426
|
'User-Agent': this.userAgent,
|
|
395
427
|
'Accept': 'application/json'
|
|
396
|
-
}
|
|
397
|
-
.
|
|
398
|
-
|
|
428
|
+
},
|
|
429
|
+
signal: controller.signal
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
clearTimeout(timeoutId);
|
|
433
|
+
|
|
434
|
+
if (!response.ok) {
|
|
435
|
+
return false;
|
|
436
|
+
}
|
|
399
437
|
|
|
400
438
|
const data = await response.json();
|
|
401
439
|
return data && data.facts !== undefined;
|