@fin.cx/opendata 3.1.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.
- package/dist_ts/00_commitinfo_data.js +1 -1
- 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/package.json +1 -1
- package/readme.md +133 -61
- package/ts/00_commitinfo_data.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
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@fin.cx/opendata',
|
|
6
|
-
version: '3.
|
|
6
|
+
version: '3.2.0',
|
|
7
7
|
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.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxrQkFBa0I7SUFDeEIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHVTQUF1UztDQUNyVCxDQUFBIn0=
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base provider entry for tracking provider state
|
|
3
|
+
*/
|
|
4
|
+
export interface IBaseProviderEntry<TProvider> {
|
|
5
|
+
provider: TProvider;
|
|
6
|
+
config: IBaseProviderConfig;
|
|
7
|
+
lastError?: Error;
|
|
8
|
+
lastErrorTime?: Date;
|
|
9
|
+
successCount: number;
|
|
10
|
+
errorCount: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Base provider configuration
|
|
14
|
+
*/
|
|
15
|
+
export interface IBaseProviderConfig {
|
|
16
|
+
enabled: boolean;
|
|
17
|
+
priority: number;
|
|
18
|
+
timeout?: number;
|
|
19
|
+
retryAttempts?: number;
|
|
20
|
+
retryDelay?: number;
|
|
21
|
+
cacheTTL?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Base provider interface
|
|
25
|
+
*/
|
|
26
|
+
export interface IBaseProvider {
|
|
27
|
+
name: string;
|
|
28
|
+
priority: number;
|
|
29
|
+
isAvailable(): Promise<boolean>;
|
|
30
|
+
readonly requiresAuth: boolean;
|
|
31
|
+
readonly rateLimit?: {
|
|
32
|
+
requestsPerMinute: number;
|
|
33
|
+
requestsPerDay?: number;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Cache entry for any data type
|
|
38
|
+
*/
|
|
39
|
+
export interface IBaseCacheEntry<TData> {
|
|
40
|
+
data: TData;
|
|
41
|
+
timestamp: Date;
|
|
42
|
+
ttl: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Base service for managing data providers with caching
|
|
46
|
+
* Shared logic extracted from StockPriceService and FundamentalsService
|
|
47
|
+
*/
|
|
48
|
+
export declare abstract class BaseProviderService<TProvider extends IBaseProvider, TData> {
|
|
49
|
+
protected providers: Map<string, IBaseProviderEntry<TProvider>>;
|
|
50
|
+
protected cache: Map<string, IBaseCacheEntry<TData>>;
|
|
51
|
+
protected logger: Console;
|
|
52
|
+
protected cacheConfig: {
|
|
53
|
+
ttl: number;
|
|
54
|
+
maxEntries: number;
|
|
55
|
+
};
|
|
56
|
+
constructor(cacheConfig?: {
|
|
57
|
+
ttl?: number;
|
|
58
|
+
maxEntries?: number;
|
|
59
|
+
});
|
|
60
|
+
/**
|
|
61
|
+
* Register a provider
|
|
62
|
+
*/
|
|
63
|
+
register(provider: TProvider, config?: Partial<IBaseProviderConfig>): void;
|
|
64
|
+
/**
|
|
65
|
+
* Unregister a provider
|
|
66
|
+
*/
|
|
67
|
+
unregister(providerName: string): void;
|
|
68
|
+
/**
|
|
69
|
+
* Get a specific provider by name
|
|
70
|
+
*/
|
|
71
|
+
getProvider(name: string): TProvider | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* Get all registered providers
|
|
74
|
+
*/
|
|
75
|
+
getAllProviders(): TProvider[];
|
|
76
|
+
/**
|
|
77
|
+
* Get enabled providers sorted by priority
|
|
78
|
+
*/
|
|
79
|
+
getEnabledProviders(): TProvider[];
|
|
80
|
+
/**
|
|
81
|
+
* Check health of all providers
|
|
82
|
+
*/
|
|
83
|
+
checkProvidersHealth(): Promise<Map<string, boolean>>;
|
|
84
|
+
/**
|
|
85
|
+
* Get provider statistics
|
|
86
|
+
*/
|
|
87
|
+
getProviderStats(): Map<string, {
|
|
88
|
+
successCount: number;
|
|
89
|
+
errorCount: number;
|
|
90
|
+
lastError?: string;
|
|
91
|
+
lastErrorTime?: Date;
|
|
92
|
+
}>;
|
|
93
|
+
/**
|
|
94
|
+
* Clear all cached data
|
|
95
|
+
*/
|
|
96
|
+
clearCache(): void;
|
|
97
|
+
/**
|
|
98
|
+
* Set cache TTL
|
|
99
|
+
*/
|
|
100
|
+
setCacheTTL(ttl: number): void;
|
|
101
|
+
/**
|
|
102
|
+
* Get cache statistics
|
|
103
|
+
*/
|
|
104
|
+
getCacheStats(): {
|
|
105
|
+
size: number;
|
|
106
|
+
maxEntries: number;
|
|
107
|
+
ttl: number;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Fetch with retry logic
|
|
111
|
+
*/
|
|
112
|
+
protected fetchWithRetry<T>(fetchFn: () => Promise<T>, config: IBaseProviderConfig): Promise<T>;
|
|
113
|
+
/**
|
|
114
|
+
* Get from cache if not expired
|
|
115
|
+
*/
|
|
116
|
+
protected getFromCache(key: string): TData | null;
|
|
117
|
+
/**
|
|
118
|
+
* Add to cache with TTL
|
|
119
|
+
*/
|
|
120
|
+
protected addToCache(key: string, data: TData, ttl?: number): void;
|
|
121
|
+
/**
|
|
122
|
+
* Track successful fetch for provider
|
|
123
|
+
*/
|
|
124
|
+
protected trackSuccess(providerName: string): void;
|
|
125
|
+
/**
|
|
126
|
+
* Track failed fetch for provider
|
|
127
|
+
*/
|
|
128
|
+
protected trackError(providerName: string, error: Error): void;
|
|
129
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
/**
|
|
3
|
+
* Base service for managing data providers with caching
|
|
4
|
+
* Shared logic extracted from StockPriceService and FundamentalsService
|
|
5
|
+
*/
|
|
6
|
+
export class BaseProviderService {
|
|
7
|
+
constructor(cacheConfig) {
|
|
8
|
+
this.providers = new Map();
|
|
9
|
+
this.cache = new Map();
|
|
10
|
+
this.logger = console;
|
|
11
|
+
this.cacheConfig = {
|
|
12
|
+
ttl: 60000, // Default 60 seconds
|
|
13
|
+
maxEntries: 10000
|
|
14
|
+
};
|
|
15
|
+
if (cacheConfig) {
|
|
16
|
+
this.cacheConfig = { ...this.cacheConfig, ...cacheConfig };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Register a provider
|
|
21
|
+
*/
|
|
22
|
+
register(provider, config) {
|
|
23
|
+
const defaultConfig = {
|
|
24
|
+
enabled: true,
|
|
25
|
+
priority: provider.priority,
|
|
26
|
+
timeout: 30000,
|
|
27
|
+
retryAttempts: 2,
|
|
28
|
+
retryDelay: 1000,
|
|
29
|
+
cacheTTL: this.cacheConfig.ttl
|
|
30
|
+
};
|
|
31
|
+
const mergedConfig = { ...defaultConfig, ...config };
|
|
32
|
+
this.providers.set(provider.name, {
|
|
33
|
+
provider,
|
|
34
|
+
config: mergedConfig,
|
|
35
|
+
successCount: 0,
|
|
36
|
+
errorCount: 0
|
|
37
|
+
});
|
|
38
|
+
console.log(`Registered provider: ${provider.name}`);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Unregister a provider
|
|
42
|
+
*/
|
|
43
|
+
unregister(providerName) {
|
|
44
|
+
this.providers.delete(providerName);
|
|
45
|
+
console.log(`Unregistered provider: ${providerName}`);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get a specific provider by name
|
|
49
|
+
*/
|
|
50
|
+
getProvider(name) {
|
|
51
|
+
return this.providers.get(name)?.provider;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get all registered providers
|
|
55
|
+
*/
|
|
56
|
+
getAllProviders() {
|
|
57
|
+
return Array.from(this.providers.values()).map(entry => entry.provider);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get enabled providers sorted by priority
|
|
61
|
+
*/
|
|
62
|
+
getEnabledProviders() {
|
|
63
|
+
return Array.from(this.providers.values())
|
|
64
|
+
.filter(entry => entry.config.enabled)
|
|
65
|
+
.sort((a, b) => (b.config.priority || 0) - (a.config.priority || 0))
|
|
66
|
+
.map(entry => entry.provider);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Check health of all providers
|
|
70
|
+
*/
|
|
71
|
+
async checkProvidersHealth() {
|
|
72
|
+
const health = new Map();
|
|
73
|
+
for (const [name, entry] of this.providers) {
|
|
74
|
+
if (!entry.config.enabled) {
|
|
75
|
+
health.set(name, false);
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
const isAvailable = await entry.provider.isAvailable();
|
|
80
|
+
health.set(name, isAvailable);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
health.set(name, false);
|
|
84
|
+
console.error(`Health check failed for ${name}:`, error);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return health;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Get provider statistics
|
|
91
|
+
*/
|
|
92
|
+
getProviderStats() {
|
|
93
|
+
const stats = new Map();
|
|
94
|
+
for (const [name, entry] of this.providers) {
|
|
95
|
+
stats.set(name, {
|
|
96
|
+
successCount: entry.successCount,
|
|
97
|
+
errorCount: entry.errorCount,
|
|
98
|
+
lastError: entry.lastError?.message,
|
|
99
|
+
lastErrorTime: entry.lastErrorTime
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return stats;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Clear all cached data
|
|
106
|
+
*/
|
|
107
|
+
clearCache() {
|
|
108
|
+
this.cache.clear();
|
|
109
|
+
console.log('Cache cleared');
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Set cache TTL
|
|
113
|
+
*/
|
|
114
|
+
setCacheTTL(ttl) {
|
|
115
|
+
this.cacheConfig.ttl = ttl;
|
|
116
|
+
console.log(`Cache TTL set to ${ttl}ms`);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Get cache statistics
|
|
120
|
+
*/
|
|
121
|
+
getCacheStats() {
|
|
122
|
+
return {
|
|
123
|
+
size: this.cache.size,
|
|
124
|
+
maxEntries: this.cacheConfig.maxEntries,
|
|
125
|
+
ttl: this.cacheConfig.ttl
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Fetch with retry logic
|
|
130
|
+
*/
|
|
131
|
+
async fetchWithRetry(fetchFn, config) {
|
|
132
|
+
const maxAttempts = config.retryAttempts || 1;
|
|
133
|
+
let lastError;
|
|
134
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
135
|
+
try {
|
|
136
|
+
return await fetchFn();
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
lastError = error;
|
|
140
|
+
if (attempt < maxAttempts) {
|
|
141
|
+
const delay = (config.retryDelay || 1000) * attempt;
|
|
142
|
+
console.log(`Retry attempt ${attempt} after ${delay}ms`);
|
|
143
|
+
await plugins.smartdelay.delayFor(delay);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
throw lastError || new Error('Unknown error during fetch');
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Get from cache if not expired
|
|
151
|
+
*/
|
|
152
|
+
getFromCache(key) {
|
|
153
|
+
const entry = this.cache.get(key);
|
|
154
|
+
if (!entry) {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
// Check if cache entry has expired
|
|
158
|
+
const age = Date.now() - entry.timestamp.getTime();
|
|
159
|
+
if (entry.ttl !== Infinity && age > entry.ttl) {
|
|
160
|
+
this.cache.delete(key);
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
return entry.data;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Add to cache with TTL
|
|
167
|
+
*/
|
|
168
|
+
addToCache(key, data, ttl) {
|
|
169
|
+
// Enforce max entries limit
|
|
170
|
+
if (this.cache.size >= this.cacheConfig.maxEntries) {
|
|
171
|
+
// Remove oldest entry
|
|
172
|
+
const oldestKey = this.cache.keys().next().value;
|
|
173
|
+
if (oldestKey) {
|
|
174
|
+
this.cache.delete(oldestKey);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
this.cache.set(key, {
|
|
178
|
+
data,
|
|
179
|
+
timestamp: new Date(),
|
|
180
|
+
ttl: ttl || this.cacheConfig.ttl
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Track successful fetch for provider
|
|
185
|
+
*/
|
|
186
|
+
trackSuccess(providerName) {
|
|
187
|
+
const entry = this.providers.get(providerName);
|
|
188
|
+
if (entry) {
|
|
189
|
+
entry.successCount++;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Track failed fetch for provider
|
|
194
|
+
*/
|
|
195
|
+
trackError(providerName, error) {
|
|
196
|
+
const entry = this.providers.get(providerName);
|
|
197
|
+
if (entry) {
|
|
198
|
+
entry.errorCount++;
|
|
199
|
+
entry.lastError = error;
|
|
200
|
+
entry.lastErrorTime = new Date();
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5iYXNlcHJvdmlkZXJzZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvc3RvY2tzL2NsYXNzZXMuYmFzZXByb3ZpZGVyc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQWlEekM7OztHQUdHO0FBQ0gsTUFBTSxPQUFnQixtQkFBbUI7SUFVdkMsWUFBWSxXQUFtRDtRQVRyRCxjQUFTLEdBQUcsSUFBSSxHQUFHLEVBQXlDLENBQUM7UUFDN0QsVUFBSyxHQUFHLElBQUksR0FBRyxFQUFrQyxDQUFDO1FBQ2xELFdBQU0sR0FBRyxPQUFPLENBQUM7UUFFakIsZ0JBQVcsR0FBRztZQUN0QixHQUFHLEVBQUUsS0FBSyxFQUFFLHFCQUFxQjtZQUNqQyxVQUFVLEVBQUUsS0FBSztTQUNsQixDQUFDO1FBR0EsSUFBSSxXQUFXLEVBQUUsQ0FBQztZQUNoQixJQUFJLENBQUMsV0FBVyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLEdBQUcsV0FBVyxFQUFFLENBQUM7UUFDN0QsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNJLFFBQVEsQ0FBQyxRQUFtQixFQUFFLE1BQXFDO1FBQ3hFLE1BQU0sYUFBYSxHQUF3QjtZQUN6QyxPQUFPLEVBQUUsSUFBSTtZQUNiLFFBQVEsRUFBRSxRQUFRLENBQUMsUUFBUTtZQUMzQixPQUFPLEVBQUUsS0FBSztZQUNkLGFBQWEsRUFBRSxDQUFDO1lBQ2hCLFVBQVUsRUFBRSxJQUFJO1lBQ2hCLFFBQVEsRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUc7U0FDL0IsQ0FBQztRQUVGLE1BQU0sWUFBWSxHQUFHLEVBQUUsR0FBRyxhQUFhLEVBQUUsR0FBRyxNQUFNLEVBQUUsQ0FBQztRQUVyRCxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFO1lBQ2hDLFFB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
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { IStockProvider, IProviderConfig } from './interfaces/provider.js';
|
|
2
|
+
import type { IFundamentalsProvider, IFundamentalsProviderConfig, IStockFundamentals } from './interfaces/fundamentals.js';
|
|
3
|
+
import type { IStockPrice } from './interfaces/stockprice.js';
|
|
4
|
+
import type { IStockData, IStockDataServiceConfig, ICompleteStockDataRequest, ICompleteStockDataBatchRequest } from './interfaces/stockdata.js';
|
|
5
|
+
/**
|
|
6
|
+
* Unified service for managing both stock prices and fundamentals
|
|
7
|
+
* Provides automatic enrichment and convenient combined data access
|
|
8
|
+
*/
|
|
9
|
+
export declare class StockDataService {
|
|
10
|
+
private priceProviders;
|
|
11
|
+
private fundamentalsProviders;
|
|
12
|
+
private priceCache;
|
|
13
|
+
private fundamentalsCache;
|
|
14
|
+
private logger;
|
|
15
|
+
private config;
|
|
16
|
+
constructor(config?: IStockDataServiceConfig);
|
|
17
|
+
/**
|
|
18
|
+
* Register a price provider
|
|
19
|
+
*/
|
|
20
|
+
registerPriceProvider(provider: IStockProvider, config?: IProviderConfig): void;
|
|
21
|
+
/**
|
|
22
|
+
* Register a fundamentals provider
|
|
23
|
+
*/
|
|
24
|
+
registerFundamentalsProvider(provider: IFundamentalsProvider, config?: IFundamentalsProviderConfig): void;
|
|
25
|
+
/**
|
|
26
|
+
* Unregister a price provider
|
|
27
|
+
*/
|
|
28
|
+
unregisterPriceProvider(providerName: string): void;
|
|
29
|
+
/**
|
|
30
|
+
* Unregister a fundamentals provider
|
|
31
|
+
*/
|
|
32
|
+
unregisterFundamentalsProvider(providerName: string): void;
|
|
33
|
+
/**
|
|
34
|
+
* Get all registered price providers
|
|
35
|
+
*/
|
|
36
|
+
getPriceProviders(): IStockProvider[];
|
|
37
|
+
/**
|
|
38
|
+
* Get all registered fundamentals providers
|
|
39
|
+
*/
|
|
40
|
+
getFundamentalsProviders(): IFundamentalsProvider[];
|
|
41
|
+
/**
|
|
42
|
+
* Get enabled price providers sorted by priority
|
|
43
|
+
*/
|
|
44
|
+
private getEnabledPriceProviders;
|
|
45
|
+
/**
|
|
46
|
+
* Get enabled fundamentals providers sorted by priority
|
|
47
|
+
*/
|
|
48
|
+
private getEnabledFundamentalsProviders;
|
|
49
|
+
/**
|
|
50
|
+
* Get current price for a single ticker
|
|
51
|
+
*/
|
|
52
|
+
getPrice(ticker: string): Promise<IStockPrice>;
|
|
53
|
+
/**
|
|
54
|
+
* Get current prices for multiple tickers
|
|
55
|
+
*/
|
|
56
|
+
getPrices(tickers: string[]): Promise<IStockPrice[]>;
|
|
57
|
+
/**
|
|
58
|
+
* Get fundamentals for a single ticker
|
|
59
|
+
*/
|
|
60
|
+
getFundamentals(ticker: string): Promise<IStockFundamentals>;
|
|
61
|
+
/**
|
|
62
|
+
* Get fundamentals for multiple tickers
|
|
63
|
+
*/
|
|
64
|
+
getBatchFundamentals(tickers: string[]): Promise<IStockFundamentals[]>;
|
|
65
|
+
/**
|
|
66
|
+
* ✨ Get complete stock data (price + fundamentals) with automatic enrichment
|
|
67
|
+
*/
|
|
68
|
+
getStockData(request: string | ICompleteStockDataRequest): Promise<IStockData>;
|
|
69
|
+
/**
|
|
70
|
+
* ✨ Get complete stock data for multiple tickers with automatic enrichment
|
|
71
|
+
*/
|
|
72
|
+
getBatchStockData(request: string[] | ICompleteStockDataBatchRequest): Promise<IStockData[]>;
|
|
73
|
+
/**
|
|
74
|
+
* Enrich fundamentals with calculated metrics using current price
|
|
75
|
+
*/
|
|
76
|
+
private enrichWithPrice;
|
|
77
|
+
/**
|
|
78
|
+
* Fetch with retry logic
|
|
79
|
+
*/
|
|
80
|
+
private fetchWithRetry;
|
|
81
|
+
/**
|
|
82
|
+
* Get from cache if not expired
|
|
83
|
+
*/
|
|
84
|
+
private getFromCache;
|
|
85
|
+
/**
|
|
86
|
+
* Add to cache with TTL
|
|
87
|
+
*/
|
|
88
|
+
private addToCache;
|
|
89
|
+
/**
|
|
90
|
+
* Check health of all providers (both price and fundamentals)
|
|
91
|
+
*/
|
|
92
|
+
checkProvidersHealth(): Promise<Map<string, boolean>>;
|
|
93
|
+
/**
|
|
94
|
+
* Get statistics for all providers
|
|
95
|
+
*/
|
|
96
|
+
getProviderStats(): Map<string, {
|
|
97
|
+
type: 'price' | 'fundamentals';
|
|
98
|
+
successCount: number;
|
|
99
|
+
errorCount: number;
|
|
100
|
+
lastError?: string;
|
|
101
|
+
lastErrorTime?: Date;
|
|
102
|
+
}>;
|
|
103
|
+
/**
|
|
104
|
+
* Clear all caches
|
|
105
|
+
*/
|
|
106
|
+
clearCache(): void;
|
|
107
|
+
/**
|
|
108
|
+
* Get cache statistics
|
|
109
|
+
*/
|
|
110
|
+
getCacheStats(): {
|
|
111
|
+
priceCache: {
|
|
112
|
+
size: number;
|
|
113
|
+
ttl: number;
|
|
114
|
+
};
|
|
115
|
+
fundamentalsCache: {
|
|
116
|
+
size: number;
|
|
117
|
+
ttl: number;
|
|
118
|
+
};
|
|
119
|
+
maxEntries: number;
|
|
120
|
+
};
|
|
121
|
+
}
|