market-feed 0.9.0 → 1.1.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/CHANGELOG.md +145 -0
- package/README.md +226 -6
- package/dist/alerts.d.cts +3 -41
- package/dist/alerts.d.ts +3 -41
- package/dist/cli.js +306 -7
- package/dist/cli.js.map +1 -1
- package/dist/{client-ADDEqqP4.d.cts → client-CRK3kKjp.d.cts} +4 -2
- package/dist/{client-B_oIoAtz.d.ts → client-CX5RGcWX.d.ts} +4 -2
- package/dist/consensus.d.cts +2 -1
- package/dist/consensus.d.ts +2 -1
- package/dist/index.cjs +306 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -4
- package/dist/index.d.ts +14 -4
- package/dist/index.js +306 -7
- package/dist/index.js.map +1 -1
- package/dist/macro.cjs +233 -0
- package/dist/macro.cjs.map +1 -0
- package/dist/macro.d.cts +126 -0
- package/dist/macro.d.ts +126 -0
- package/dist/macro.js +229 -0
- package/dist/macro.js.map +1 -0
- package/dist/options-CyRqRiFk.d.cts +59 -0
- package/dist/options-CyRqRiFk.d.ts +59 -0
- package/dist/options.cjs +13 -0
- package/dist/options.cjs.map +1 -0
- package/dist/options.d.cts +45 -0
- package/dist/options.d.ts +45 -0
- package/dist/options.js +11 -0
- package/dist/options.js.map +1 -0
- package/dist/{provider-CnWUOTf9.d.ts → provider-B3PfcWLV.d.ts} +5 -0
- package/dist/{provider-DC4ydTdu.d.cts → provider-DROKdbpH.d.cts} +5 -0
- package/dist/react.cjs +735 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +104 -0
- package/dist/react.d.ts +104 -0
- package/dist/react.js +731 -0
- package/dist/react.js.map +1 -0
- package/dist/screener.cjs +6 -0
- package/dist/screener.cjs.map +1 -1
- package/dist/screener.d.cts +6 -0
- package/dist/screener.d.ts +6 -0
- package/dist/screener.js +6 -0
- package/dist/screener.js.map +1 -1
- package/dist/stream.d.cts +10 -86
- package/dist/stream.d.ts +10 -86
- package/dist/types-B5oHwrPy.d.ts +85 -0
- package/dist/types-C8OPQ-Yj.d.cts +85 -0
- package/dist/types-D90J5xwU.d.ts +43 -0
- package/dist/types-hzOO9Cst.d.cts +43 -0
- package/dist/ws.d.cts +2 -1
- package/dist/ws.d.ts +2 -1
- package/package.json +59 -18
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,150 @@
|
|
|
1
1
|
# market-feed Changelog
|
|
2
2
|
|
|
3
|
+
## 1.1.0 — 2026-03-12
|
|
4
|
+
|
|
5
|
+
### New modules
|
|
6
|
+
|
|
7
|
+
**`market-feed/options`** — Options chains with full Greeks from Polygon.io.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { getOptionChain } from "market-feed/options";
|
|
11
|
+
import { PolygonProvider } from "market-feed";
|
|
12
|
+
|
|
13
|
+
const polygon = new PolygonProvider({ apiKey: process.env.POLYGON_KEY! });
|
|
14
|
+
const chain = await getOptionChain(polygon, "AAPL", {
|
|
15
|
+
expiry: "2024-07-19",
|
|
16
|
+
type: "call",
|
|
17
|
+
strikeLow: 170,
|
|
18
|
+
strikeHigh: 210,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
for (const c of chain.calls) {
|
|
22
|
+
console.log(`Strike $${c.strike} IV ${(c.impliedVolatility! * 100).toFixed(1)}% Δ ${c.delta?.toFixed(3)}`);
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Fields: `ticker`, `type`, `strike`, `expiry`, `style`, `sharesPerContract`, `bid`, `ask`, `midpoint`, `lastPrice`, `volume`, `openInterest`, `impliedVolatility`, `delta`, `gamma`, `theta`, `vega`, OHLCV.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
**`market-feed/macro`** — Macroeconomic time-series data from the [FRED API](https://fred.stlouisfed.org/).
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { FredProvider, getIndicator, INDICATORS } from "market-feed/macro";
|
|
34
|
+
|
|
35
|
+
const fred = new FredProvider({ apiKey: process.env.FRED_KEY! });
|
|
36
|
+
const cpi = await getIndicator(fred, INDICATORS.CPI, { limit: 12 });
|
|
37
|
+
|
|
38
|
+
for (const obs of cpi.observations) {
|
|
39
|
+
console.log(`${obs.date.toISOString().slice(0, 7)}: ${obs.value}`);
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
15 named constants in `INDICATORS`: `CPI`, `FED_FUNDS`, `UNEMPLOYMENT`, `GDP`, `M2`, `T10Y`, `T2Y`, `MORTGAGE_30Y`, `PCE`, `PPI`, `INDUSTRIAL_PRODUCTION`, `RETAIL_SALES`, `OIL_WTI`, `HOUSING_STARTS`, `CONSUMER_SENTIMENT`. Any FRED series ID string also accepted.
|
|
44
|
+
|
|
45
|
+
### Provider enhancements
|
|
46
|
+
|
|
47
|
+
**Polygon.io** — added `incomeStatements()`, `balanceSheets()`, `cashFlows()` via `/vX/reference/financials`.
|
|
48
|
+
|
|
49
|
+
**Tiingo** — added `incomeStatements()`, `balanceSheets()`, `cashFlows()` via `/tiingo/fundamentals/{ticker}/statements`.
|
|
50
|
+
|
|
51
|
+
### Screener additions
|
|
52
|
+
|
|
53
|
+
Two new criteria in `market-feed/screener`:
|
|
54
|
+
|
|
55
|
+
| Criterion | Passes when |
|
|
56
|
+
|-----------|-------------|
|
|
57
|
+
| `volume_vs_avg_above` | `quote.volume > quote.avgVolume * value` — e.g. `value: 2` = 2× average volume |
|
|
58
|
+
| `volume_vs_avg_below` | `quote.volume < quote.avgVolume * value` |
|
|
59
|
+
|
|
60
|
+
Both pass-through when `avgVolume` is `undefined` (consistent with 52-week criteria).
|
|
61
|
+
|
|
62
|
+
### Client
|
|
63
|
+
|
|
64
|
+
- `MarketFeed.optionChain(symbol, options?)` — delegates to first provider supporting `optionChain`. Cache TTL: 60s.
|
|
65
|
+
- `CacheMethod` union extended with `"optionChain"`.
|
|
66
|
+
|
|
67
|
+
### Package
|
|
68
|
+
|
|
69
|
+
- `market-feed/options` and `market-feed/macro` added to `exports` and `keywords`.
|
|
70
|
+
- Total subpath modules: **14** (`market-feed`, `/calendar`, `/stream`, `/ws`, `/consensus`, `/indicators`, `/portfolio`, `/backtest`, `/alerts`, `/fundamentals`, `/screener`, `/options`, `/macro`, `/react`).
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 1.0.0 — 2026-03-12
|
|
75
|
+
|
|
76
|
+
### New module
|
|
77
|
+
|
|
78
|
+
**`market-feed/react`** — React hooks for live market data. Requires React ≥ 18.
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
import { useQuote, useStream, useAlerts } from "market-feed/react";
|
|
82
|
+
import { MarketFeed } from "market-feed";
|
|
83
|
+
|
|
84
|
+
const feed = new MarketFeed();
|
|
85
|
+
|
|
86
|
+
// Poll a single quote
|
|
87
|
+
function StockPrice({ symbol }: { symbol: string }) {
|
|
88
|
+
const { data, loading, error } = useQuote(feed, symbol);
|
|
89
|
+
if (loading) return <span>…</span>;
|
|
90
|
+
if (error) return <span>Error: {error.message}</span>;
|
|
91
|
+
return <span>{symbol}: ${data?.price.toFixed(2)}</span>;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Subscribe to a live stream
|
|
95
|
+
function LiveFeed() {
|
|
96
|
+
const { event } = useStream(feed, ["AAPL", "MSFT", "GOOGL"]);
|
|
97
|
+
if (!event || event.type !== "quote") return null;
|
|
98
|
+
return <p>{event.symbol}: ${event.quote.price}</p>;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Collect price alerts
|
|
102
|
+
function AlertLog() {
|
|
103
|
+
const { events, clearEvents } = useAlerts(feed, [
|
|
104
|
+
{ symbol: "AAPL", condition: { type: "price_above", threshold: 200 }, once: false },
|
|
105
|
+
]);
|
|
106
|
+
return (
|
|
107
|
+
<ul>
|
|
108
|
+
{events.map((e, i) => <li key={i}>{e.alert.symbol} triggered @ ${e.quote.price}</li>)}
|
|
109
|
+
<button onClick={clearEvents}>Clear</button>
|
|
110
|
+
</ul>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
#### Hook reference
|
|
116
|
+
|
|
117
|
+
**`useQuote(source, symbol, options?)`**
|
|
118
|
+
|
|
119
|
+
| Option | Default | Description |
|
|
120
|
+
|--------|---------|-------------|
|
|
121
|
+
| `intervalMs` | `5000` | Poll interval in milliseconds |
|
|
122
|
+
| `enabled` | `true` | Set to `false` to suspend polling |
|
|
123
|
+
|
|
124
|
+
Returns `{ data: Quote \| null, loading: boolean, error: Error \| null, refetch() }`.
|
|
125
|
+
|
|
126
|
+
**`useStream(feed, symbols, options?)`**
|
|
127
|
+
|
|
128
|
+
Drives a `watch()` async generator. Restarts automatically when `symbols` changes. Stops on unmount via an internal `AbortSignal`.
|
|
129
|
+
|
|
130
|
+
Returns `{ event: StreamEvent \| null, error: Error \| null }`.
|
|
131
|
+
|
|
132
|
+
**`useAlerts(feed, alerts, options?)`**
|
|
133
|
+
|
|
134
|
+
Drives a `watchAlerts()` async generator. Restarts when alert definitions (symbol + condition type + threshold) change.
|
|
135
|
+
|
|
136
|
+
Returns `{ events: AlertEvent[], error: Error \| null, clearEvents() }`.
|
|
137
|
+
|
|
138
|
+
#### Note on peer dependency
|
|
139
|
+
|
|
140
|
+
`react` is a peer dependency — install it separately in your project:
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
npm install react
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
3
148
|
## 0.9.0 — 2026-03-12
|
|
4
149
|
|
|
5
150
|
### New module
|
package/README.md
CHANGED
|
@@ -62,6 +62,9 @@ One interface. Six providers. Zero API key required for Yahoo Finance.
|
|
|
62
62
|
- **Backtesting** — pure-function engine: total return, CAGR, Sharpe ratio, max drawdown, win rate, profit factor
|
|
63
63
|
- **Price alerts** — async generator that fires `AlertEvent` on price/volume/change conditions, with debounce
|
|
64
64
|
- **Earnings, dividends, splits** — structured historical corporate action data from Yahoo, Polygon, and Finnhub
|
|
65
|
+
- **Financial statements** — income statement, balance sheet, and cash flow statement via `market-feed/fundamentals`
|
|
66
|
+
- **Stock screener** — filter a universe of symbols by price, volume, market cap, 52-week range, or any custom predicate via `market-feed/screener`
|
|
67
|
+
- **React hooks** — `useQuote`, `useStream`, `useAlerts` for React ≥ 18 via `market-feed/react`
|
|
65
68
|
- **CLI** — `npx market-feed quote AAPL` — no install required
|
|
66
69
|
- **Crypto & Forex** — `isCrypto()` / `isForex()` helpers, CRYPTO calendar exchange (always open)
|
|
67
70
|
|
|
@@ -69,7 +72,7 @@ One interface. Six providers. Zero API key required for Yahoo Finance.
|
|
|
69
72
|
|
|
70
73
|
## Subpath modules
|
|
71
74
|
|
|
72
|
-
`market-feed` ships
|
|
75
|
+
`market-feed` ships eleven optional subpath modules alongside the core client.
|
|
73
76
|
|
|
74
77
|
### `market-feed/ws`
|
|
75
78
|
|
|
@@ -518,6 +521,199 @@ When all `once` alerts have fired, the generator terminates automatically. Perma
|
|
|
518
521
|
|
|
519
522
|
---
|
|
520
523
|
|
|
524
|
+
### `market-feed/fundamentals`
|
|
525
|
+
|
|
526
|
+
Fetch income statements, balance sheets, and cash flow statements for any public company.
|
|
527
|
+
|
|
528
|
+
```ts
|
|
529
|
+
import { getFundamentals } from "market-feed/fundamentals";
|
|
530
|
+
import { MarketFeed } from "market-feed";
|
|
531
|
+
|
|
532
|
+
const feed = new MarketFeed();
|
|
533
|
+
|
|
534
|
+
// Fetch all three statements in parallel — partial failure is OK
|
|
535
|
+
const { incomeStatements, balanceSheets, cashFlows } = await getFundamentals(feed, "AAPL");
|
|
536
|
+
|
|
537
|
+
const latest = incomeStatements[0]!;
|
|
538
|
+
console.log(`Revenue: $${(latest.revenue! / 1e9).toFixed(1)}B`);
|
|
539
|
+
console.log(`Net income: $${(latest.netIncome! / 1e9).toFixed(1)}B`);
|
|
540
|
+
console.log(`Diluted EPS: $${latest.dilutedEps?.toFixed(2)}`);
|
|
541
|
+
|
|
542
|
+
// Quarterly statements
|
|
543
|
+
const { incomeStatements: quarterly } = await getFundamentals(feed, "AAPL", {
|
|
544
|
+
quarterly: true,
|
|
545
|
+
limit: 4,
|
|
546
|
+
});
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
`getFundamentals()` fires all three queries with `Promise.allSettled` — if one statement type fails, the others still return.
|
|
550
|
+
|
|
551
|
+
#### `IncomeStatement`
|
|
552
|
+
|
|
553
|
+
| Field | Description |
|
|
554
|
+
|-------|-------------|
|
|
555
|
+
| `revenue` | Total revenue |
|
|
556
|
+
| `grossProfit` | Revenue − cost of revenue |
|
|
557
|
+
| `operatingIncome` | Operating income (EBIT) |
|
|
558
|
+
| `netIncome` | Bottom-line net income |
|
|
559
|
+
| `ebitda` | EBITDA |
|
|
560
|
+
| `dilutedEps` | Diluted EPS |
|
|
561
|
+
|
|
562
|
+
#### `BalanceSheet`
|
|
563
|
+
|
|
564
|
+
| Field | Description |
|
|
565
|
+
|-------|-------------|
|
|
566
|
+
| `totalAssets` | Total assets |
|
|
567
|
+
| `totalLiabilities` | Total liabilities |
|
|
568
|
+
| `totalStockholdersEquity` | Book value of equity |
|
|
569
|
+
| `cashAndCashEquivalents` | Cash + equivalents |
|
|
570
|
+
| `totalDebt` | Short + long-term debt |
|
|
571
|
+
|
|
572
|
+
#### `CashFlowStatement`
|
|
573
|
+
|
|
574
|
+
| Field | Description |
|
|
575
|
+
|-------|-------------|
|
|
576
|
+
| `operatingCashFlow` | Cash from operations |
|
|
577
|
+
| `capitalExpenditures` | CapEx (negative = outflow) |
|
|
578
|
+
| `freeCashFlow` | `operatingCashFlow + capitalExpenditures` |
|
|
579
|
+
| `investingCashFlow` | Cash from investing |
|
|
580
|
+
| `financingCashFlow` | Cash from financing |
|
|
581
|
+
|
|
582
|
+
All three types include `symbol`, `date` (period end date), `periodType` (`"annual"` | `"quarterly"`), and `provider`.
|
|
583
|
+
|
|
584
|
+
#### `MarketFeed` methods
|
|
585
|
+
|
|
586
|
+
```ts
|
|
587
|
+
feed.incomeStatements(symbol, options?) // Promise<IncomeStatement[]>
|
|
588
|
+
feed.balanceSheets(symbol, options?) // Promise<BalanceSheet[]>
|
|
589
|
+
feed.cashFlows(symbol, options?) // Promise<CashFlowStatement[]>
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
| `FundamentalsOptions` | Default | Description |
|
|
593
|
+
|-----------------------|---------|-------------|
|
|
594
|
+
| `quarterly` | `false` | Return quarterly instead of annual periods |
|
|
595
|
+
| `limit` | unlimited | Max number of periods to return |
|
|
596
|
+
| `raw` | `false` | Include raw provider response on each object |
|
|
597
|
+
|
|
598
|
+
---
|
|
599
|
+
|
|
600
|
+
### `market-feed/screener`
|
|
601
|
+
|
|
602
|
+
Filter a list of symbols against a set of criteria using live quote data.
|
|
603
|
+
|
|
604
|
+
```ts
|
|
605
|
+
import { screen } from "market-feed/screener";
|
|
606
|
+
import { MarketFeed } from "market-feed";
|
|
607
|
+
|
|
608
|
+
const feed = new MarketFeed();
|
|
609
|
+
|
|
610
|
+
// Find large-caps that gained > 1.5% today on high volume
|
|
611
|
+
const results = await screen(feed, ["AAPL", "MSFT", "GOOGL", "TSLA", "NVDA", "META"], {
|
|
612
|
+
criteria: [
|
|
613
|
+
{ type: "market_cap_above", value: 100_000_000_000 },
|
|
614
|
+
{ type: "change_pct_above", value: 1.5 },
|
|
615
|
+
{ type: "volume_above", value: 10_000_000 },
|
|
616
|
+
],
|
|
617
|
+
limit: 5,
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
for (const r of results) {
|
|
621
|
+
console.log(`${r.symbol}: $${r.quote.price.toFixed(2)} (+${r.quote.changePercent.toFixed(2)}%)`);
|
|
622
|
+
}
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
All criteria are evaluated with **AND logic** — a symbol must pass every criterion to be included.
|
|
626
|
+
|
|
627
|
+
#### Criterion types
|
|
628
|
+
|
|
629
|
+
| Type | Passes when |
|
|
630
|
+
|------|-------------|
|
|
631
|
+
| `price_above` / `price_below` | `quote.price > / < value` |
|
|
632
|
+
| `change_pct_above` / `change_pct_below` | `quote.changePercent > / < value` |
|
|
633
|
+
| `volume_above` / `volume_below` | `quote.volume > / < value` |
|
|
634
|
+
| `market_cap_above` / `market_cap_below` | `quote.marketCap > / < value` (skips if undefined) |
|
|
635
|
+
| `52w_high_pct_below` | Price is within N% of the 52-week high |
|
|
636
|
+
| `52w_low_pct_above` | Price is at least N% above the 52-week low |
|
|
637
|
+
| `custom` | `{ type: "custom", fn: (quote: Quote) => boolean }` |
|
|
638
|
+
|
|
639
|
+
#### `ScreenerOptions`
|
|
640
|
+
|
|
641
|
+
| Option | Default | Description |
|
|
642
|
+
|--------|---------|-------------|
|
|
643
|
+
| `criteria` | required | Array of `ScreenerCriterion` |
|
|
644
|
+
| `batchSize` | all at once | Max symbols per `quote()` call |
|
|
645
|
+
| `limit` | unlimited | Max results to return |
|
|
646
|
+
|
|
647
|
+
`screen()` accepts any object with a `quote(symbols[]) → Quote[]` method — works with `MarketFeed`, individual providers, or a test mock.
|
|
648
|
+
|
|
649
|
+
---
|
|
650
|
+
|
|
651
|
+
### `market-feed/react`
|
|
652
|
+
|
|
653
|
+
React hooks for live market data. Requires React ≥ 18 (peer dependency).
|
|
654
|
+
|
|
655
|
+
```bash
|
|
656
|
+
npm install market-feed react
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
```tsx
|
|
660
|
+
import { useQuote, useStream, useAlerts } from "market-feed/react";
|
|
661
|
+
import { MarketFeed } from "market-feed";
|
|
662
|
+
|
|
663
|
+
const feed = new MarketFeed();
|
|
664
|
+
|
|
665
|
+
// Poll a quote every 5 seconds
|
|
666
|
+
function StockPrice({ symbol }: { symbol: string }) {
|
|
667
|
+
const { data, loading, error } = useQuote(feed, symbol);
|
|
668
|
+
if (loading) return <span>Loading…</span>;
|
|
669
|
+
if (error) return <span>Error: {error.message}</span>;
|
|
670
|
+
return <span>{symbol}: ${data?.price.toFixed(2)}</span>;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// Subscribe to a live watch() stream
|
|
674
|
+
function LiveFeed() {
|
|
675
|
+
const { event } = useStream(feed, ["AAPL", "MSFT", "GOOGL"]);
|
|
676
|
+
if (!event || event.type !== "quote") return null;
|
|
677
|
+
return <p>{event.symbol}: ${event.quote.price.toFixed(2)}</p>;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
// Collect price alerts
|
|
681
|
+
function AlertLog() {
|
|
682
|
+
const { events, clearEvents } = useAlerts(feed, [
|
|
683
|
+
{ symbol: "AAPL", condition: { type: "price_above", threshold: 200 }, once: false },
|
|
684
|
+
]);
|
|
685
|
+
return (
|
|
686
|
+
<ul>
|
|
687
|
+
{events.map((e, i) => (
|
|
688
|
+
<li key={i}>{e.alert.symbol} triggered @ ${e.quote.price.toFixed(2)}</li>
|
|
689
|
+
))}
|
|
690
|
+
<button onClick={clearEvents}>Clear</button>
|
|
691
|
+
</ul>
|
|
692
|
+
);
|
|
693
|
+
}
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
#### Hook reference
|
|
697
|
+
|
|
698
|
+
**`useQuote(source, symbol, options?)`** — polls a quote at a regular interval.
|
|
699
|
+
|
|
700
|
+
| Option | Default | Description |
|
|
701
|
+
|--------|---------|-------------|
|
|
702
|
+
| `intervalMs` | `5000` | Poll interval in milliseconds |
|
|
703
|
+
| `enabled` | `true` | Set to `false` to suspend polling |
|
|
704
|
+
|
|
705
|
+
Returns `{ data: Quote \| null, loading: boolean, error: Error \| null, refetch() }`.
|
|
706
|
+
|
|
707
|
+
**`useStream(feed, symbols, options?)`** — drives a `watch()` async generator. Restarts automatically when `symbols` changes; stops on unmount via an internal `AbortSignal`.
|
|
708
|
+
|
|
709
|
+
Returns `{ event: StreamEvent \| null, error: Error \| null }`.
|
|
710
|
+
|
|
711
|
+
**`useAlerts(feed, alerts, options?)`** — drives a `watchAlerts()` async generator. Accumulates triggered events; restarts when alert definitions change.
|
|
712
|
+
|
|
713
|
+
Returns `{ events: AlertEvent[], error: Error \| null, clearEvents() }`.
|
|
714
|
+
|
|
715
|
+
---
|
|
716
|
+
|
|
521
717
|
### CLI (`npx market-feed`)
|
|
522
718
|
|
|
523
719
|
A zero-config CLI powered by Yahoo Finance (no API key needed). Add keys to unlock more providers.
|
|
@@ -537,6 +733,11 @@ npx market-feed company AAPL
|
|
|
537
733
|
|
|
538
734
|
# News (JSON output)
|
|
539
735
|
npx market-feed news AAPL --limit 5 --json
|
|
736
|
+
|
|
737
|
+
# Corporate actions
|
|
738
|
+
npx market-feed earnings AAPL
|
|
739
|
+
npx market-feed dividends AAPL
|
|
740
|
+
npx market-feed splits AAPL
|
|
540
741
|
```
|
|
541
742
|
|
|
542
743
|
#### Options
|
|
@@ -546,6 +747,8 @@ npx market-feed news AAPL --limit 5 --json
|
|
|
546
747
|
| `--av-key <key>` | Alpha Vantage API key |
|
|
547
748
|
| `--polygon-key <key>` | Polygon.io API key |
|
|
548
749
|
| `--finnhub-key <key>` | Finnhub API key |
|
|
750
|
+
| `--td-key <key>` | Twelve Data API key |
|
|
751
|
+
| `--tiingo-key <key>` | Tiingo API key |
|
|
549
752
|
| `--json` | Output raw JSON instead of formatted tables |
|
|
550
753
|
| `--limit <n>` | Limit results (default: 10) |
|
|
551
754
|
| `--interval <i>` | Historical interval: `1m` `5m` `15m` `30m` `1h` `1d` `1wk` `1mo` (default: `1d`) |
|
|
@@ -601,14 +804,16 @@ console.log(profile.sector); // "Technology"
|
|
|
601
804
|
|
|
602
805
|
## Providers
|
|
603
806
|
|
|
604
|
-
| Provider | API Key | Quote | Historical | Search | Company | News |
|
|
605
|
-
|
|
606
|
-
| **Yahoo Finance** | Not required | ✓ | ✓ | ✓ | ✓ | — |
|
|
807
|
+
| Provider | API Key | Quote | Historical | Search | Company | News | Fundamentals |
|
|
808
|
+
|----------|---------|:-----:|:----------:|:------:|:-------:|:----:|:------------:|
|
|
809
|
+
| **Yahoo Finance** | Not required | ✓ | ✓ | ✓ | ✓ | — | ✓ |
|
|
607
810
|
| **Alpha Vantage** | Free (25/day) | ✓ | ✓ | ✓ | ✓ | — | — |
|
|
608
811
|
| **Polygon.io** | Free (delayed) | ✓ | ✓ | ✓ | ✓ | ✓ | — |
|
|
609
812
|
| **Finnhub** | Free (60/min) | ✓ | ✓ | ✓ | ✓ | ✓ | — |
|
|
813
|
+
| **Twelve Data** | Free (800/day) | ✓ | ✓ | ✓ | ✓ | — | — |
|
|
814
|
+
| **Tiingo** | Free (1000/day) | ✓ | ✓ | ✓ | ✓ | ✓ | — |
|
|
610
815
|
|
|
611
|
-
Get free keys: [Alpha Vantage](https://www.alphavantage.co/support/#api-key) · [Polygon.io](https://polygon.io/) · [Finnhub](https://finnhub.io/)
|
|
816
|
+
Get free keys: [Alpha Vantage](https://www.alphavantage.co/support/#api-key) · [Polygon.io](https://polygon.io/) · [Finnhub](https://finnhub.io/) · [Twelve Data](https://twelvedata.com/) · [Tiingo](https://www.tiingo.com/)
|
|
612
817
|
|
|
613
818
|
### Using multiple providers
|
|
614
819
|
|
|
@@ -619,6 +824,8 @@ import {
|
|
|
619
824
|
AlphaVantageProvider,
|
|
620
825
|
PolygonProvider,
|
|
621
826
|
FinnhubProvider,
|
|
827
|
+
TwelveDataProvider,
|
|
828
|
+
TiingoProvider,
|
|
622
829
|
} from "market-feed";
|
|
623
830
|
|
|
624
831
|
const feed = new MarketFeed({
|
|
@@ -627,6 +834,8 @@ const feed = new MarketFeed({
|
|
|
627
834
|
new AlphaVantageProvider({ apiKey: process.env.AV_KEY }),
|
|
628
835
|
new PolygonProvider({ apiKey: process.env.POLYGON_KEY }),
|
|
629
836
|
new FinnhubProvider({ apiKey: process.env.FINNHUB_KEY }),
|
|
837
|
+
new TwelveDataProvider({ apiKey: process.env.TD_KEY }),
|
|
838
|
+
new TiingoProvider({ apiKey: process.env.TIINGO_KEY }),
|
|
630
839
|
],
|
|
631
840
|
fallback: true, // auto-try next provider on failure
|
|
632
841
|
});
|
|
@@ -646,6 +855,12 @@ The default LRU cache stores responses in memory with sensible TTLs:
|
|
|
646
855
|
| `news` | 5 minutes |
|
|
647
856
|
| `search` | 10 minutes |
|
|
648
857
|
| `marketStatus` | 60s |
|
|
858
|
+
| `earnings` | 1 hour |
|
|
859
|
+
| `dividends` | 24 hours |
|
|
860
|
+
| `splits` | 24 hours |
|
|
861
|
+
| `incomeStatements` | 24 hours |
|
|
862
|
+
| `balanceSheets` | 24 hours |
|
|
863
|
+
| `cashFlows` | 24 hours |
|
|
649
864
|
|
|
650
865
|
### Override TTLs
|
|
651
866
|
|
|
@@ -735,6 +950,11 @@ feed.dividends(symbol: string, options?: DividendOptions): Promise<DividendEvent
|
|
|
735
950
|
// Stock split history
|
|
736
951
|
feed.splits(symbol: string, options?: SplitOptions): Promise<SplitEvent[]>
|
|
737
952
|
|
|
953
|
+
// Financial statements
|
|
954
|
+
feed.incomeStatements(symbol: string, options?: FundamentalsOptions): Promise<IncomeStatement[]>
|
|
955
|
+
feed.balanceSheets(symbol: string, options?: FundamentalsOptions): Promise<BalanceSheet[]>
|
|
956
|
+
feed.cashFlows(symbol: string, options?: FundamentalsOptions): Promise<CashFlowStatement[]>
|
|
957
|
+
|
|
738
958
|
// Cache management
|
|
739
959
|
feed.clearCache(): Promise<void>
|
|
740
960
|
feed.invalidate(key: string): Promise<void>
|
|
@@ -834,7 +1054,7 @@ pnpm test
|
|
|
834
1054
|
|
|
835
1055
|
## Disclaimer
|
|
836
1056
|
|
|
837
|
-
This library is not affiliated with or endorsed by Yahoo Finance, Alpha Vantage, Polygon.io, or
|
|
1057
|
+
This library is not affiliated with or endorsed by Yahoo Finance, Alpha Vantage, Polygon.io, Finnhub, Twelve Data, or Tiingo. Data is provided for informational purposes only and should not be used as the sole basis for investment decisions.
|
|
838
1058
|
|
|
839
1059
|
---
|
|
840
1060
|
|
package/dist/alerts.d.cts
CHANGED
|
@@ -1,44 +1,6 @@
|
|
|
1
1
|
import { a as Quote } from './quote-Cfh_7Cgg.cjs';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
type: "price_above";
|
|
5
|
-
threshold: number;
|
|
6
|
-
} | {
|
|
7
|
-
type: "price_below";
|
|
8
|
-
threshold: number;
|
|
9
|
-
} | {
|
|
10
|
-
type: "change_pct_above";
|
|
11
|
-
threshold: number;
|
|
12
|
-
} | {
|
|
13
|
-
type: "change_pct_below";
|
|
14
|
-
threshold: number;
|
|
15
|
-
} | {
|
|
16
|
-
type: "volume_above";
|
|
17
|
-
threshold: number;
|
|
18
|
-
};
|
|
19
|
-
interface AlertConfig {
|
|
20
|
-
symbol: string;
|
|
21
|
-
condition: AlertCondition;
|
|
22
|
-
/** Emit this alert at most once, then stop watching it. Defaults to false. */
|
|
23
|
-
once?: boolean;
|
|
24
|
-
/**
|
|
25
|
-
* Suppress re-fires within this many milliseconds after the last trigger.
|
|
26
|
-
* Defaults to 0 (no debounce).
|
|
27
|
-
*/
|
|
28
|
-
debounceMs?: number;
|
|
29
|
-
}
|
|
30
|
-
interface AlertEvent {
|
|
31
|
-
type: "triggered";
|
|
32
|
-
alert: AlertConfig;
|
|
33
|
-
quote: Quote;
|
|
34
|
-
triggeredAt: Date;
|
|
35
|
-
}
|
|
36
|
-
interface AlertsOptions {
|
|
37
|
-
/** Poll interval in milliseconds. Defaults to 5 000. */
|
|
38
|
-
intervalMs?: number;
|
|
39
|
-
/** AbortSignal to stop the generator. */
|
|
40
|
-
signal?: AbortSignal;
|
|
41
|
-
}
|
|
2
|
+
import { A as AlertConfig, a as AlertsOptions, b as AlertEvent } from './types-hzOO9Cst.cjs';
|
|
3
|
+
export { c as AlertCondition } from './types-hzOO9Cst.cjs';
|
|
42
4
|
|
|
43
5
|
interface QuoteFetcher {
|
|
44
6
|
quote(symbols: string[]): Promise<Quote[]>;
|
|
@@ -67,4 +29,4 @@ interface QuoteFetcher {
|
|
|
67
29
|
*/
|
|
68
30
|
declare function watchAlerts(feed: QuoteFetcher, alerts: AlertConfig[], options?: AlertsOptions): AsyncGenerator<AlertEvent>;
|
|
69
31
|
|
|
70
|
-
export {
|
|
32
|
+
export { AlertConfig, AlertEvent, AlertsOptions, watchAlerts };
|
package/dist/alerts.d.ts
CHANGED
|
@@ -1,44 +1,6 @@
|
|
|
1
1
|
import { a as Quote } from './quote-Cfh_7Cgg.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
type: "price_above";
|
|
5
|
-
threshold: number;
|
|
6
|
-
} | {
|
|
7
|
-
type: "price_below";
|
|
8
|
-
threshold: number;
|
|
9
|
-
} | {
|
|
10
|
-
type: "change_pct_above";
|
|
11
|
-
threshold: number;
|
|
12
|
-
} | {
|
|
13
|
-
type: "change_pct_below";
|
|
14
|
-
threshold: number;
|
|
15
|
-
} | {
|
|
16
|
-
type: "volume_above";
|
|
17
|
-
threshold: number;
|
|
18
|
-
};
|
|
19
|
-
interface AlertConfig {
|
|
20
|
-
symbol: string;
|
|
21
|
-
condition: AlertCondition;
|
|
22
|
-
/** Emit this alert at most once, then stop watching it. Defaults to false. */
|
|
23
|
-
once?: boolean;
|
|
24
|
-
/**
|
|
25
|
-
* Suppress re-fires within this many milliseconds after the last trigger.
|
|
26
|
-
* Defaults to 0 (no debounce).
|
|
27
|
-
*/
|
|
28
|
-
debounceMs?: number;
|
|
29
|
-
}
|
|
30
|
-
interface AlertEvent {
|
|
31
|
-
type: "triggered";
|
|
32
|
-
alert: AlertConfig;
|
|
33
|
-
quote: Quote;
|
|
34
|
-
triggeredAt: Date;
|
|
35
|
-
}
|
|
36
|
-
interface AlertsOptions {
|
|
37
|
-
/** Poll interval in milliseconds. Defaults to 5 000. */
|
|
38
|
-
intervalMs?: number;
|
|
39
|
-
/** AbortSignal to stop the generator. */
|
|
40
|
-
signal?: AbortSignal;
|
|
41
|
-
}
|
|
2
|
+
import { A as AlertConfig, a as AlertsOptions, b as AlertEvent } from './types-D90J5xwU.js';
|
|
3
|
+
export { c as AlertCondition } from './types-D90J5xwU.js';
|
|
42
4
|
|
|
43
5
|
interface QuoteFetcher {
|
|
44
6
|
quote(symbols: string[]): Promise<Quote[]>;
|
|
@@ -67,4 +29,4 @@ interface QuoteFetcher {
|
|
|
67
29
|
*/
|
|
68
30
|
declare function watchAlerts(feed: QuoteFetcher, alerts: AlertConfig[], options?: AlertsOptions): AsyncGenerator<AlertEvent>;
|
|
69
31
|
|
|
70
|
-
export {
|
|
32
|
+
export { AlertConfig, AlertEvent, AlertsOptions, watchAlerts };
|