@fin.cx/opendata 3.0.0 → 3.2.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.
@@ -0,0 +1,495 @@
1
+ import * as plugins from '../plugins.js';
2
+ /**
3
+ * Unified service for managing both stock prices and fundamentals
4
+ * Provides automatic enrichment and convenient combined data access
5
+ */
6
+ export class StockDataService {
7
+ constructor(config) {
8
+ this.priceProviders = new Map();
9
+ this.fundamentalsProviders = new Map();
10
+ this.priceCache = new Map();
11
+ this.fundamentalsCache = new Map();
12
+ this.logger = console;
13
+ this.config = {
14
+ cache: {
15
+ priceTTL: 24 * 60 * 60 * 1000, // 24 hours
16
+ fundamentalsTTL: 90 * 24 * 60 * 60 * 1000, // 90 days
17
+ maxEntries: 10000
18
+ },
19
+ timeout: {
20
+ price: 10000, // 10 seconds
21
+ fundamentals: 30000 // 30 seconds
22
+ }
23
+ };
24
+ if (config) {
25
+ this.config = {
26
+ cache: { ...this.config.cache, ...config.cache },
27
+ timeout: { ...this.config.timeout, ...config.timeout }
28
+ };
29
+ }
30
+ }
31
+ // ========== Provider Management ==========
32
+ /**
33
+ * Register a price provider
34
+ */
35
+ registerPriceProvider(provider, config) {
36
+ const defaultConfig = {
37
+ enabled: true,
38
+ priority: provider.priority,
39
+ timeout: this.config.timeout.price,
40
+ retryAttempts: 2,
41
+ retryDelay: 1000
42
+ };
43
+ const mergedConfig = { ...defaultConfig, ...config };
44
+ this.priceProviders.set(provider.name, {
45
+ provider,
46
+ config: mergedConfig,
47
+ successCount: 0,
48
+ errorCount: 0
49
+ });
50
+ console.log(`Registered price provider: ${provider.name}`);
51
+ }
52
+ /**
53
+ * Register a fundamentals provider
54
+ */
55
+ registerFundamentalsProvider(provider, config) {
56
+ const defaultConfig = {
57
+ enabled: true,
58
+ priority: provider.priority,
59
+ timeout: this.config.timeout.fundamentals,
60
+ retryAttempts: 2,
61
+ retryDelay: 1000,
62
+ cacheTTL: this.config.cache.fundamentalsTTL
63
+ };
64
+ const mergedConfig = { ...defaultConfig, ...config };
65
+ this.fundamentalsProviders.set(provider.name, {
66
+ provider,
67
+ config: mergedConfig,
68
+ successCount: 0,
69
+ errorCount: 0
70
+ });
71
+ console.log(`Registered fundamentals provider: ${provider.name}`);
72
+ }
73
+ /**
74
+ * Unregister a price provider
75
+ */
76
+ unregisterPriceProvider(providerName) {
77
+ this.priceProviders.delete(providerName);
78
+ console.log(`Unregistered price provider: ${providerName}`);
79
+ }
80
+ /**
81
+ * Unregister a fundamentals provider
82
+ */
83
+ unregisterFundamentalsProvider(providerName) {
84
+ this.fundamentalsProviders.delete(providerName);
85
+ console.log(`Unregistered fundamentals provider: ${providerName}`);
86
+ }
87
+ /**
88
+ * Get all registered price providers
89
+ */
90
+ getPriceProviders() {
91
+ return Array.from(this.priceProviders.values()).map(entry => entry.provider);
92
+ }
93
+ /**
94
+ * Get all registered fundamentals providers
95
+ */
96
+ getFundamentalsProviders() {
97
+ return Array.from(this.fundamentalsProviders.values()).map(entry => entry.provider);
98
+ }
99
+ /**
100
+ * Get enabled price providers sorted by priority
101
+ */
102
+ getEnabledPriceProviders() {
103
+ return Array.from(this.priceProviders.values())
104
+ .filter(entry => entry.config.enabled)
105
+ .sort((a, b) => (b.config.priority || 0) - (a.config.priority || 0))
106
+ .map(entry => entry.provider);
107
+ }
108
+ /**
109
+ * Get enabled fundamentals providers sorted by priority
110
+ */
111
+ getEnabledFundamentalsProviders() {
112
+ return Array.from(this.fundamentalsProviders.values())
113
+ .filter(entry => entry.config.enabled)
114
+ .sort((a, b) => (b.config.priority || 0) - (a.config.priority || 0))
115
+ .map(entry => entry.provider);
116
+ }
117
+ // ========== Data Fetching Methods ==========
118
+ /**
119
+ * Get current price for a single ticker
120
+ */
121
+ async getPrice(ticker) {
122
+ const cacheKey = `price:${ticker}`;
123
+ const cached = this.getFromCache(this.priceCache, cacheKey);
124
+ if (cached) {
125
+ console.log(`Cache hit for price: ${ticker}`);
126
+ return cached;
127
+ }
128
+ const providers = this.getEnabledPriceProviders();
129
+ if (providers.length === 0) {
130
+ throw new Error('No price providers available');
131
+ }
132
+ let lastError;
133
+ for (const provider of providers) {
134
+ const entry = this.priceProviders.get(provider.name);
135
+ try {
136
+ const result = await this.fetchWithRetry(() => provider.fetchData({ type: 'current', ticker }), entry.config);
137
+ entry.successCount++;
138
+ const price = result;
139
+ this.addToCache(this.priceCache, cacheKey, price, this.config.cache.priceTTL);
140
+ console.log(`Successfully fetched price for ${ticker} from ${provider.name}`);
141
+ return price;
142
+ }
143
+ catch (error) {
144
+ entry.errorCount++;
145
+ entry.lastError = error;
146
+ entry.lastErrorTime = new Date();
147
+ lastError = error;
148
+ console.warn(`Provider ${provider.name} failed for ${ticker}: ${error.message}`);
149
+ }
150
+ }
151
+ throw new Error(`Failed to fetch price for ${ticker} from all providers. Last error: ${lastError?.message}`);
152
+ }
153
+ /**
154
+ * Get current prices for multiple tickers
155
+ */
156
+ async getPrices(tickers) {
157
+ const cacheKey = `prices:${tickers.sort().join(',')}`;
158
+ const cached = this.getFromCache(this.priceCache, cacheKey);
159
+ if (cached) {
160
+ console.log(`Cache hit for prices: ${tickers.length} tickers`);
161
+ return cached;
162
+ }
163
+ const providers = this.getEnabledPriceProviders();
164
+ if (providers.length === 0) {
165
+ throw new Error('No price providers available');
166
+ }
167
+ let lastError;
168
+ for (const provider of providers) {
169
+ const entry = this.priceProviders.get(provider.name);
170
+ try {
171
+ const result = await this.fetchWithRetry(() => provider.fetchData({ type: 'batch', tickers }), entry.config);
172
+ entry.successCount++;
173
+ const prices = result;
174
+ this.addToCache(this.priceCache, cacheKey, prices, this.config.cache.priceTTL);
175
+ console.log(`Successfully fetched ${prices.length} prices from ${provider.name}`);
176
+ return prices;
177
+ }
178
+ catch (error) {
179
+ entry.errorCount++;
180
+ entry.lastError = error;
181
+ entry.lastErrorTime = new Date();
182
+ lastError = error;
183
+ console.warn(`Provider ${provider.name} failed for batch prices: ${error.message}`);
184
+ }
185
+ }
186
+ throw new Error(`Failed to fetch prices for ${tickers.length} tickers from all providers. Last error: ${lastError?.message}`);
187
+ }
188
+ /**
189
+ * Get fundamentals for a single ticker
190
+ */
191
+ async getFundamentals(ticker) {
192
+ const cacheKey = `fundamentals:${ticker}`;
193
+ const cached = this.getFromCache(this.fundamentalsCache, cacheKey);
194
+ if (cached) {
195
+ console.log(`Cache hit for fundamentals: ${ticker}`);
196
+ return cached;
197
+ }
198
+ const providers = this.getEnabledFundamentalsProviders();
199
+ if (providers.length === 0) {
200
+ throw new Error('No fundamentals providers available');
201
+ }
202
+ let lastError;
203
+ for (const provider of providers) {
204
+ const entry = this.fundamentalsProviders.get(provider.name);
205
+ try {
206
+ const result = await this.fetchWithRetry(() => provider.fetchData({ type: 'fundamentals-current', ticker }), entry.config);
207
+ entry.successCount++;
208
+ const fundamentals = result;
209
+ const ttl = entry.config.cacheTTL || this.config.cache.fundamentalsTTL;
210
+ this.addToCache(this.fundamentalsCache, cacheKey, fundamentals, ttl);
211
+ console.log(`Successfully fetched fundamentals for ${ticker} from ${provider.name}`);
212
+ return fundamentals;
213
+ }
214
+ catch (error) {
215
+ entry.errorCount++;
216
+ entry.lastError = error;
217
+ entry.lastErrorTime = new Date();
218
+ lastError = error;
219
+ console.warn(`Provider ${provider.name} failed for ${ticker} fundamentals: ${error.message}`);
220
+ }
221
+ }
222
+ throw new Error(`Failed to fetch fundamentals for ${ticker} from all providers. Last error: ${lastError?.message}`);
223
+ }
224
+ /**
225
+ * Get fundamentals for multiple tickers
226
+ */
227
+ async getBatchFundamentals(tickers) {
228
+ const cacheKey = `fundamentals-batch:${tickers.sort().join(',')}`;
229
+ const cached = this.getFromCache(this.fundamentalsCache, cacheKey);
230
+ if (cached) {
231
+ console.log(`Cache hit for batch fundamentals: ${tickers.length} tickers`);
232
+ return cached;
233
+ }
234
+ const providers = this.getEnabledFundamentalsProviders();
235
+ if (providers.length === 0) {
236
+ throw new Error('No fundamentals providers available');
237
+ }
238
+ let lastError;
239
+ for (const provider of providers) {
240
+ const entry = this.fundamentalsProviders.get(provider.name);
241
+ try {
242
+ const result = await this.fetchWithRetry(() => provider.fetchData({ type: 'fundamentals-batch', tickers }), entry.config);
243
+ entry.successCount++;
244
+ const fundamentals = result;
245
+ const ttl = entry.config.cacheTTL || this.config.cache.fundamentalsTTL;
246
+ this.addToCache(this.fundamentalsCache, cacheKey, fundamentals, ttl);
247
+ console.log(`Successfully fetched ${fundamentals.length} fundamentals from ${provider.name}`);
248
+ return fundamentals;
249
+ }
250
+ catch (error) {
251
+ entry.errorCount++;
252
+ entry.lastError = error;
253
+ entry.lastErrorTime = new Date();
254
+ lastError = error;
255
+ console.warn(`Provider ${provider.name} failed for batch fundamentals: ${error.message}`);
256
+ }
257
+ }
258
+ throw new Error(`Failed to fetch fundamentals for ${tickers.length} tickers from all providers. Last error: ${lastError?.message}`);
259
+ }
260
+ /**
261
+ * ✨ Get complete stock data (price + fundamentals) with automatic enrichment
262
+ */
263
+ async getStockData(request) {
264
+ const normalizedRequest = typeof request === 'string'
265
+ ? { ticker: request, includeFundamentals: true, enrichFundamentals: true }
266
+ : { includeFundamentals: true, enrichFundamentals: true, ...request };
267
+ const price = await this.getPrice(normalizedRequest.ticker);
268
+ let fundamentals;
269
+ if (normalizedRequest.includeFundamentals) {
270
+ try {
271
+ fundamentals = await this.getFundamentals(normalizedRequest.ticker);
272
+ // Enrich fundamentals with price calculations
273
+ if (normalizedRequest.enrichFundamentals && fundamentals) {
274
+ fundamentals = this.enrichWithPrice(fundamentals, price.price);
275
+ }
276
+ }
277
+ catch (error) {
278
+ console.warn(`Failed to fetch fundamentals for ${normalizedRequest.ticker}: ${error.message}`);
279
+ // Continue without fundamentals
280
+ }
281
+ }
282
+ return {
283
+ ticker: normalizedRequest.ticker,
284
+ price,
285
+ fundamentals,
286
+ fetchedAt: new Date()
287
+ };
288
+ }
289
+ /**
290
+ * ✨ Get complete stock data for multiple tickers with automatic enrichment
291
+ */
292
+ async getBatchStockData(request) {
293
+ const normalizedRequest = Array.isArray(request)
294
+ ? { tickers: request, includeFundamentals: true, enrichFundamentals: true }
295
+ : { includeFundamentals: true, enrichFundamentals: true, ...request };
296
+ const prices = await this.getPrices(normalizedRequest.tickers);
297
+ const priceMap = new Map(prices.map(p => [p.ticker, p]));
298
+ let fundamentalsMap = new Map();
299
+ if (normalizedRequest.includeFundamentals) {
300
+ try {
301
+ const fundamentals = await this.getBatchFundamentals(normalizedRequest.tickers);
302
+ // Enrich with prices if requested
303
+ if (normalizedRequest.enrichFundamentals) {
304
+ for (const fund of fundamentals) {
305
+ const price = priceMap.get(fund.ticker);
306
+ if (price) {
307
+ fundamentalsMap.set(fund.ticker, this.enrichWithPrice(fund, price.price));
308
+ }
309
+ else {
310
+ fundamentalsMap.set(fund.ticker, fund);
311
+ }
312
+ }
313
+ }
314
+ else {
315
+ fundamentalsMap = new Map(fundamentals.map(f => [f.ticker, f]));
316
+ }
317
+ }
318
+ catch (error) {
319
+ console.warn(`Failed to fetch batch fundamentals: ${error.message}`);
320
+ // Continue without fundamentals
321
+ }
322
+ }
323
+ return normalizedRequest.tickers.map(ticker => ({
324
+ ticker,
325
+ price: priceMap.get(ticker),
326
+ fundamentals: fundamentalsMap.get(ticker),
327
+ fetchedAt: new Date()
328
+ }));
329
+ }
330
+ // ========== Helper Methods ==========
331
+ /**
332
+ * Enrich fundamentals with calculated metrics using current price
333
+ */
334
+ enrichWithPrice(fundamentals, price) {
335
+ const enriched = { ...fundamentals };
336
+ // Calculate market cap: price × shares outstanding
337
+ if (fundamentals.sharesOutstanding) {
338
+ enriched.marketCap = price * fundamentals.sharesOutstanding;
339
+ }
340
+ // Calculate P/E ratio: price / EPS
341
+ if (fundamentals.earningsPerShareDiluted && fundamentals.earningsPerShareDiluted > 0) {
342
+ enriched.priceToEarnings = price / fundamentals.earningsPerShareDiluted;
343
+ }
344
+ // Calculate price-to-book: market cap / stockholders equity
345
+ if (enriched.marketCap && fundamentals.stockholdersEquity && fundamentals.stockholdersEquity > 0) {
346
+ enriched.priceToBook = enriched.marketCap / fundamentals.stockholdersEquity;
347
+ }
348
+ return enriched;
349
+ }
350
+ /**
351
+ * Fetch with retry logic
352
+ */
353
+ async fetchWithRetry(fetchFn, config) {
354
+ const maxAttempts = config.retryAttempts || 1;
355
+ let lastError;
356
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
357
+ try {
358
+ return await fetchFn();
359
+ }
360
+ catch (error) {
361
+ lastError = error;
362
+ if (attempt < maxAttempts) {
363
+ const delay = (config.retryDelay || 1000) * attempt;
364
+ console.log(`Retry attempt ${attempt} after ${delay}ms`);
365
+ await plugins.smartdelay.delayFor(delay);
366
+ }
367
+ }
368
+ }
369
+ throw lastError || new Error('Unknown error during fetch');
370
+ }
371
+ /**
372
+ * Get from cache if not expired
373
+ */
374
+ getFromCache(cache, key) {
375
+ const entry = cache.get(key);
376
+ if (!entry) {
377
+ return null;
378
+ }
379
+ // Check if cache entry has expired
380
+ const age = Date.now() - entry.timestamp.getTime();
381
+ if (entry.ttl !== Infinity && age > entry.ttl) {
382
+ cache.delete(key);
383
+ return null;
384
+ }
385
+ return entry.data;
386
+ }
387
+ /**
388
+ * Add to cache with TTL
389
+ */
390
+ addToCache(cache, key, data, ttl) {
391
+ // Enforce max entries limit
392
+ if (cache.size >= this.config.cache.maxEntries) {
393
+ // Remove oldest entry
394
+ const oldestKey = cache.keys().next().value;
395
+ if (oldestKey) {
396
+ cache.delete(oldestKey);
397
+ }
398
+ }
399
+ cache.set(key, {
400
+ data,
401
+ timestamp: new Date(),
402
+ ttl
403
+ });
404
+ }
405
+ // ========== Health & Statistics ==========
406
+ /**
407
+ * Check health of all providers (both price and fundamentals)
408
+ */
409
+ async checkProvidersHealth() {
410
+ const health = new Map();
411
+ // Check price providers
412
+ for (const [name, entry] of this.priceProviders) {
413
+ if (!entry.config.enabled) {
414
+ health.set(`${name} (price)`, false);
415
+ continue;
416
+ }
417
+ try {
418
+ const isAvailable = await entry.provider.isAvailable();
419
+ health.set(`${name} (price)`, isAvailable);
420
+ }
421
+ catch (error) {
422
+ health.set(`${name} (price)`, false);
423
+ console.error(`Health check failed for ${name}:`, error);
424
+ }
425
+ }
426
+ // Check fundamentals providers
427
+ for (const [name, entry] of this.fundamentalsProviders) {
428
+ if (!entry.config.enabled) {
429
+ health.set(`${name} (fundamentals)`, false);
430
+ continue;
431
+ }
432
+ try {
433
+ const isAvailable = await entry.provider.isAvailable();
434
+ health.set(`${name} (fundamentals)`, isAvailable);
435
+ }
436
+ catch (error) {
437
+ health.set(`${name} (fundamentals)`, false);
438
+ console.error(`Health check failed for ${name}:`, error);
439
+ }
440
+ }
441
+ return health;
442
+ }
443
+ /**
444
+ * Get statistics for all providers
445
+ */
446
+ getProviderStats() {
447
+ const stats = new Map();
448
+ // Price provider stats
449
+ for (const [name, entry] of this.priceProviders) {
450
+ stats.set(name, {
451
+ type: 'price',
452
+ successCount: entry.successCount,
453
+ errorCount: entry.errorCount,
454
+ lastError: entry.lastError?.message,
455
+ lastErrorTime: entry.lastErrorTime
456
+ });
457
+ }
458
+ // Fundamentals provider stats
459
+ for (const [name, entry] of this.fundamentalsProviders) {
460
+ stats.set(name, {
461
+ type: 'fundamentals',
462
+ successCount: entry.successCount,
463
+ errorCount: entry.errorCount,
464
+ lastError: entry.lastError?.message,
465
+ lastErrorTime: entry.lastErrorTime
466
+ });
467
+ }
468
+ return stats;
469
+ }
470
+ /**
471
+ * Clear all caches
472
+ */
473
+ clearCache() {
474
+ this.priceCache.clear();
475
+ this.fundamentalsCache.clear();
476
+ console.log('All caches cleared');
477
+ }
478
+ /**
479
+ * Get cache statistics
480
+ */
481
+ getCacheStats() {
482
+ return {
483
+ priceCache: {
484
+ size: this.priceCache.size,
485
+ ttl: this.config.cache.priceTTL
486
+ },
487
+ fundamentalsCache: {
488
+ size: this.fundamentalsCache.size,
489
+ ttl: this.config.cache.fundamentalsTTL
490
+ },
491
+ maxEntries: this.config.cache.maxEntries
492
+ };
493
+ }
494
+ }
495
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zdG9ja2RhdGFzZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvc3RvY2tzL2NsYXNzZXMuc3RvY2tkYXRhc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQXFCekM7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLGdCQUFnQjtJQXFCM0IsWUFBWSxNQUFnQztRQXBCcEMsbUJBQWMsR0FBRyxJQUFJLEdBQUcsRUFBMEMsQ0FBQztRQUNuRSwwQkFBcUIsR0FBRyxJQUFJLEdBQUcsRUFBaUQsQ0FBQztRQUVqRixlQUFVLEdBQUcsSUFBSSxHQUFHLEVBQW9ELENBQUM7UUFDekUsc0JBQWlCLEdBQUcsSUFBSSxHQUFHLEVBQWtFLENBQUM7UUFFOUYsV0FBTSxHQUFHLE9BQU8sQ0FBQztRQUVqQixXQUFNLEdBQXNDO1lBQ2xELEtBQUssRUFBRTtnQkFDTCxRQUFRLEVBQUUsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxFQUFFLFdBQVc7Z0JBQzFDLGVBQWUsRUFBRSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxFQUFFLFVBQVU7Z0JBQ3JELFVBQVUsRUFBRSxLQUFLO2FBQ2xCO1lBQ0QsT0FBTyxFQUFFO2dCQUNQLEtBQUssRUFBRSxLQUFLLEVBQUUsYUFBYTtnQkFDM0IsWUFBWSxFQUFFLEtBQUssQ0FBQyxhQUFhO2FBQ2xDO1NBQ0YsQ0FBQztRQUdBLElBQUksTUFBTSxFQUFFLENBQUM7WUFDWCxJQUFJLENBQUMsTUFBTSxHQUFHO2dCQUNaLEtBQUssRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsR0FBRyxNQUFNLENBQUMsS0FBSyxFQUFFO2dCQUNoRCxPQUFPLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLEdBQUcsTUFB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
@@ -1,5 +1,11 @@
1
1
  export * from './interfaces/stockprice.js';
2
2
  export * from './interfaces/provider.js';
3
+ export * from './interfaces/fundamentals.js';
4
+ export * from './interfaces/stockdata.js';
3
5
  export * from './classes.stockservice.js';
6
+ export * from './classes.fundamentalsservice.js';
7
+ export * from './classes.stockdataservice.js';
8
+ export * from './classes.baseproviderservice.js';
4
9
  export * from './providers/provider.yahoo.js';
5
10
  export * from './providers/provider.marketstack.js';
11
+ export * from './providers/provider.secedgar.js';
@@ -1,9 +1,16 @@
1
1
  // Export all interfaces
2
2
  export * from './interfaces/stockprice.js';
3
3
  export * from './interfaces/provider.js';
4
- // Export main service
4
+ export * from './interfaces/fundamentals.js';
5
+ export * from './interfaces/stockdata.js';
6
+ // Export main services
5
7
  export * from './classes.stockservice.js';
8
+ export * from './classes.fundamentalsservice.js';
9
+ export * from './classes.stockdataservice.js'; // ✨ New unified service
10
+ // Export base service (for advanced use cases)
11
+ export * from './classes.baseproviderservice.js';
6
12
  // Export providers
7
13
  export * from './providers/provider.yahoo.js';
8
14
  export * from './providers/provider.marketstack.js';
9
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9zdG9ja3MvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsd0JBQXdCO0FBQ3hCLGNBQWMsNEJBQTRCLENBQUM7QUFDM0MsY0FBYywwQkFBMEIsQ0FBQztBQUV6QyxzQkFBc0I7QUFDdEIsY0FBYywyQkFBMkIsQ0FBQztBQUUxQyxtQkFBbUI7QUFDbkIsY0FBYywrQkFBK0IsQ0FBQztBQUM5QyxjQUFjLHFDQUFxQyxDQUFDIn0=
15
+ export * from './providers/provider.secedgar.js';
16
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9zdG9ja3MvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsd0JBQXdCO0FBQ3hCLGNBQWMsNEJBQTRCLENBQUM7QUFDM0MsY0FBYywwQkFBMEIsQ0FBQztBQUN6QyxjQUFjLDhCQUE4QixDQUFDO0FBQzdDLGNBQWMsMkJBQTJCLENBQUM7QUFFMUMsdUJBQXVCO0FBQ3ZCLGNBQWMsMkJBQTJCLENBQUM7QUFDMUMsY0FBYyxrQ0FBa0MsQ0FBQztBQUNqRCxjQUFjLCtCQUErQixDQUFDLENBQUMsd0JBQXdCO0FBRXZFLCtDQUErQztBQUMvQyxjQUFjLGtDQUFrQyxDQUFDO0FBRWpELG1CQUFtQjtBQUNuQixjQUFjLCtCQUErQixDQUFDO0FBQzlDLGNBQWMscUNBQXFDLENBQUM7QUFDcEQsY0FBYyxrQ0FBa0MsQ0FBQyJ9
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Interfaces for stock fundamental data (financials from SEC filings)
3
+ * Separate from stock price data (OHLCV) to maintain clean architecture
4
+ */
5
+ export interface IFundamentalsCurrentRequest {
6
+ type: 'fundamentals-current';
7
+ ticker: string;
8
+ }
9
+ export interface IFundamentalsBatchRequest {
10
+ type: 'fundamentals-batch';
11
+ tickers: string[];
12
+ }
13
+ export type IFundamentalsRequest = IFundamentalsCurrentRequest | IFundamentalsBatchRequest;
14
+ /**
15
+ * Stock fundamental data from SEC filings (10-K, 10-Q)
16
+ * Contains financial metrics like EPS, Revenue, Assets, etc.
17
+ */
18
+ export interface IStockFundamentals {
19
+ ticker: string;
20
+ cik: string;
21
+ companyName: string;
22
+ provider: string;
23
+ timestamp: Date;
24
+ fetchedAt: Date;
25
+ earningsPerShareBasic?: number;
26
+ earningsPerShareDiluted?: number;
27
+ sharesOutstanding?: number;
28
+ weightedAverageSharesOutstanding?: number;
29
+ revenue?: number;
30
+ netIncome?: number;
31
+ operatingIncome?: number;
32
+ grossProfit?: number;
33
+ costOfRevenue?: number;
34
+ assets?: number;
35
+ liabilities?: number;
36
+ stockholdersEquity?: number;
37
+ cash?: number;
38
+ propertyPlantEquipment?: number;
39
+ marketCap?: number;
40
+ priceToEarnings?: number;
41
+ priceToBook?: number;
42
+ fiscalYear?: string;
43
+ fiscalQuarter?: string;
44
+ filingDate?: Date;
45
+ form?: '10-K' | '10-Q' | string;
46
+ }
47
+ /**
48
+ * Provider interface for fetching fundamental data
49
+ * Parallel to IStockProvider but for fundamentals instead of prices
50
+ */
51
+ export interface IFundamentalsProvider {
52
+ name: string;
53
+ priority: number;
54
+ fetchData(request: IFundamentalsRequest): Promise<IStockFundamentals | IStockFundamentals[]>;
55
+ isAvailable(): Promise<boolean>;
56
+ readonly requiresAuth: boolean;
57
+ readonly rateLimit?: {
58
+ requestsPerMinute: number;
59
+ requestsPerDay?: number;
60
+ };
61
+ }
62
+ /**
63
+ * Configuration for fundamentals providers
64
+ */
65
+ export interface IFundamentalsProviderConfig {
66
+ enabled: boolean;
67
+ priority?: number;
68
+ timeout?: number;
69
+ retryAttempts?: number;
70
+ retryDelay?: number;
71
+ cacheTTL?: number;
72
+ }
73
+ /**
74
+ * Registry for managing fundamental data providers
75
+ */
76
+ export interface IFundamentalsProviderRegistry {
77
+ register(provider: IFundamentalsProvider, config?: IFundamentalsProviderConfig): void;
78
+ unregister(providerName: string): void;
79
+ getProvider(name: string): IFundamentalsProvider | undefined;
80
+ getAllProviders(): IFundamentalsProvider[];
81
+ getEnabledProviders(): IFundamentalsProvider[];
82
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Interfaces for stock fundamental data (financials from SEC filings)
3
+ * Separate from stock price data (OHLCV) to maintain clean architecture
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnVuZGFtZW50YWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvc3RvY2tzL2ludGVyZmFjZXMvZnVuZGFtZW50YWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRyJ9