feat(StockDataService): Add unified StockDataService and BaseProviderService with new stockdata interfaces, provider integrations, tests and README updates
This commit is contained in:
200
readme.md
200
readme.md
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user