feat(StockDataService): Add unified StockDataService and BaseProviderService with new stockdata interfaces, provider integrations, tests and README updates

This commit is contained in:
2025-11-01 12:35:53 +00:00
parent d33c7e0f52
commit 6273faa2f9
8 changed files with 1580 additions and 65 deletions

200
readme.md
View File

@@ -14,64 +14,110 @@ pnpm add @fin.cx/opendata
## Quick Start
### 📈 Stock Market Data
### ✨ Unified Stock Data API (Recommended)
Get real-time prices with company information included automatically:
Get complete stock data with automatic enrichment - the elegant way:
```typescript
import { StockPriceService, MarketstackProvider } from '@fin.cx/opendata';
import { StockDataService, YahooFinanceProvider, SecEdgarProvider } from '@fin.cx/opendata';
// Initialize service with smart caching
const stockService = new StockPriceService({
ttl: 60000, // Cache TTL (historical cached forever)
maxEntries: 10000
// Initialize unified service
const stockData = new StockDataService();
// Register providers
stockData.registerPriceProvider(new YahooFinanceProvider());
stockData.registerFundamentalsProvider(new SecEdgarProvider({
userAgent: 'YourCompany youremail@example.com'
}));
// ✨ Get complete stock data with ONE method call
const apple = await stockData.getStockData('AAPL');
console.log({
company: apple.fundamentals.companyName, // "Apple Inc."
price: apple.price.price, // $270.37
marketCap: apple.fundamentals.marketCap, // $4.13T (auto-calculated!)
peRatio: apple.fundamentals.priceToEarnings, // 28.42 (auto-calculated!)
pbRatio: apple.fundamentals.priceToBook, // 45.12 (auto-calculated!)
eps: apple.fundamentals.earningsPerShareDiluted, // $6.13
revenue: apple.fundamentals.revenue // $385.6B
});
// Register provider with API key
stockService.register(new MarketstackProvider('YOUR_API_KEY'));
// Batch fetch with automatic enrichment
const stocks = await stockData.getBatchStockData(['AAPL', 'MSFT', 'GOOGL']);
// Get current price with company name (zero extra API calls!)
const apple = await stockService.getData({ type: 'current', ticker: 'AAPL' });
console.log(`${apple.companyFullName}: $${apple.price}`);
// Output: "Apple Inc (NASDAQ:AAPL): $270.37"
stocks.forEach(stock => {
console.log(`${stock.ticker}: $${stock.price.price.toFixed(2)}, ` +
`P/E ${stock.fundamentals?.priceToEarnings?.toFixed(2)}`);
});
// Output:
// AAPL: $270.37, P/E 28.42
// MSFT: $425.50, P/E 34.21
// GOOGL: $142.15, P/E 25.63
```
### 💰 Fundamental Financial Data
**Why use the unified API?**
-**Single service** for both prices and fundamentals
-**Automatic enrichment** - Market cap, P/E, P/B calculated automatically
-**One method call** - No manual `enrichWithPrice()` calls
-**Simplified code** - Less boilerplate, more readable
-**Type-safe** - Full TypeScript support
Access comprehensive financial metrics from SEC filings - completely FREE:
### 📈 Price-Only Data (Alternative)
If you only need prices without fundamentals:
```typescript
import { SecEdgarProvider, FundamentalsService } from '@fin.cx/opendata';
import { StockDataService, YahooFinanceProvider } from '@fin.cx/opendata';
// Setup SEC EDGAR provider (no API key required!)
const secEdgar = new SecEdgarProvider({
const stockData = new StockDataService();
stockData.registerPriceProvider(new YahooFinanceProvider());
// Get just the price
const price = await stockData.getPrice('AAPL');
console.log(`${price.ticker}: $${price.price}`);
// Or use StockPriceService directly for more control
import { StockPriceService } from '@fin.cx/opendata';
const stockService = new StockPriceService({ ttl: 60000 });
stockService.register(new YahooFinanceProvider());
const apple = await stockService.getData({ type: 'current', ticker: 'AAPL' });
console.log(`${apple.companyFullName}: $${apple.price}`);
```
### 💰 Fundamentals-Only Data (Alternative)
If you only need fundamentals without prices:
```typescript
import { StockDataService, SecEdgarProvider } from '@fin.cx/opendata';
const stockData = new StockDataService();
stockData.registerFundamentalsProvider(new SecEdgarProvider({
userAgent: 'YourCompany youremail@example.com'
}));
// Get just fundamentals
const fundamentals = await stockData.getFundamentals('AAPL');
console.log({
company: fundamentals.companyName,
eps: fundamentals.earningsPerShareDiluted,
revenue: fundamentals.revenue,
sharesOutstanding: fundamentals.sharesOutstanding
});
// Or use FundamentalsService directly
import { FundamentalsService } from '@fin.cx/opendata';
const fundamentalsService = new FundamentalsService();
fundamentalsService.register(secEdgar);
fundamentalsService.register(new SecEdgarProvider({
userAgent: 'YourCompany youremail@example.com'
}));
// Fetch fundamentals for Apple
const fundamentals = await fundamentalsService.getFundamentals('AAPL');
console.log({
company: fundamentals.companyName, // "Apple Inc."
eps: fundamentals.earningsPerShareDiluted, // $6.13
revenue: fundamentals.revenue, // $385.6B
sharesOutstanding: fundamentals.sharesOutstanding // 15.3B
});
// Calculate market cap and P/E ratio
const price = await stockService.getData({ type: 'current', ticker: 'AAPL' });
const enriched = await fundamentalsService.enrichWithPrice(fundamentals, price.price);
console.log({
marketCap: `$${(enriched.marketCap! / 1_000_000_000_000).toFixed(2)}T`,
peRatio: enriched.priceToEarnings!.toFixed(2),
pbRatio: enriched.priceToBook?.toFixed(2)
});
// Output: { marketCap: "$2.65T", peRatio: "28.42", pbRatio: "45.12" }
const data = await fundamentalsService.getFundamentals('AAPL');
```
### 🏢 German Business Intelligence
@@ -136,44 +182,70 @@ const details = await openData.handelsregister.getSpecificCompany({
## Advanced Examples
### Combined Market Analysis
### Combined Market Analysis (Unified API)
Combine price data with fundamentals for comprehensive analysis:
Analyze multiple companies with automatic enrichment:
```typescript
import { StockPriceService, MarketstackProvider, SecEdgarProvider, FundamentalsService } from '@fin.cx/opendata';
import { StockDataService, YahooFinanceProvider, SecEdgarProvider } from '@fin.cx/opendata';
// Setup services
const stockService = new StockPriceService({ ttl: 60000 });
stockService.register(new MarketstackProvider('YOUR_API_KEY'));
const fundamentalsService = new FundamentalsService();
fundamentalsService.register(new SecEdgarProvider({
// Setup unified service
const stockData = new StockDataService();
stockData.registerPriceProvider(new YahooFinanceProvider());
stockData.registerFundamentalsProvider(new SecEdgarProvider({
userAgent: 'YourCompany youremail@example.com'
}));
// Analyze multiple companies
// Analyze multiple companies with ONE call
const tickers = ['AAPL', 'MSFT', 'GOOGL', 'AMZN'];
const stocks = await stockData.getBatchStockData(tickers);
// All metrics are automatically calculated!
stocks.forEach(stock => {
if (stock.fundamentals) {
console.log(`\n${stock.fundamentals.companyName} (${stock.ticker})`);
console.log(` Price: $${stock.price.price.toFixed(2)}`);
console.log(` Market Cap: $${(stock.fundamentals.marketCap! / 1e9).toFixed(2)}B`);
console.log(` P/E Ratio: ${stock.fundamentals.priceToEarnings!.toFixed(2)}`);
console.log(` Revenue: $${(stock.fundamentals.revenue! / 1e9).toFixed(2)}B`);
console.log(` EPS: $${stock.fundamentals.earningsPerShareDiluted!.toFixed(2)}`);
}
});
// Or analyze one-by-one with automatic enrichment
for (const ticker of tickers) {
// Get price and fundamentals in parallel
const [price, fundamentals] = await Promise.all([
stockService.getData({ type: 'current', ticker }),
fundamentalsService.getFundamentals(ticker)
]);
const stock = await stockData.getStockData(ticker);
// Calculate metrics
const enriched = await fundamentalsService.enrichWithPrice(fundamentals, price.price);
console.log(`\n${fundamentals.companyName} (${ticker})`);
console.log(` Price: $${price.price.toFixed(2)}`);
console.log(` Market Cap: $${(enriched.marketCap! / 1e9).toFixed(2)}B`);
console.log(` P/E Ratio: ${enriched.priceToEarnings!.toFixed(2)}`);
console.log(` Revenue: $${(fundamentals.revenue! / 1e9).toFixed(2)}B`);
console.log(` EPS: $${fundamentals.earningsPerShareDiluted!.toFixed(2)}`);
// Everything is already enriched - no manual calculations needed!
console.log(`${ticker}: P/E ${stock.fundamentals?.priceToEarnings?.toFixed(2)}`);
}
```
### Fundamental Data Screening
Screen stocks by financial metrics:
```typescript
// Fetch data for multiple tickers
const tickers = ['AAPL', 'MSFT', 'GOOGL', 'AMZN', 'META', 'NVDA', 'TSLA'];
const stocks = await stockData.getBatchStockData(tickers);
// Filter by criteria (all metrics auto-calculated!)
const valueStocks = stocks.filter(stock => {
const f = stock.fundamentals;
return f &&
f.priceToEarnings! < 30 && // P/E under 30
f.priceToBook! < 10 && // P/B under 10
f.revenue! > 100_000_000_000; // Revenue > $100B
});
console.log('\n💎 Value Stocks:');
valueStocks.forEach(stock => {
console.log(`${stock.ticker}: P/E ${stock.fundamentals!.priceToEarnings!.toFixed(2)}, ` +
`P/B ${stock.fundamentals!.priceToBook!.toFixed(2)}`);
});
```
### Historical Data Analysis
Fetch and analyze historical price trends: