@livefolio/sdk 0.2.13 → 0.3.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/README.md +277 -84
- package/dist/index.d.ts +397 -23
- package/dist/index.js +1375 -51
- package/dist/index.js.map +1 -1
- package/package.json +36 -35
- package/dist/auth/client.d.ts +0 -4
- package/dist/auth/client.d.ts.map +0 -1
- package/dist/auth/client.js +0 -37
- package/dist/auth/client.js.map +0 -1
- package/dist/auth/index.d.ts +0 -3
- package/dist/auth/index.d.ts.map +0 -1
- package/dist/auth/index.js +0 -6
- package/dist/auth/index.js.map +0 -1
- package/dist/auth/types.d.ts +0 -9
- package/dist/auth/types.d.ts.map +0 -1
- package/dist/auth/types.js +0 -3
- package/dist/auth/types.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/market/client.d.ts +0 -4
- package/dist/market/client.d.ts.map +0 -1
- package/dist/market/client.js +0 -137
- package/dist/market/client.js.map +0 -1
- package/dist/market/index.d.ts +0 -5
- package/dist/market/index.d.ts.map +0 -1
- package/dist/market/index.js +0 -9
- package/dist/market/index.js.map +0 -1
- package/dist/market/trackedTickers.d.ts +0 -4
- package/dist/market/trackedTickers.d.ts.map +0 -1
- package/dist/market/trackedTickers.js +0 -256
- package/dist/market/trackedTickers.js.map +0 -1
- package/dist/market/types.d.ts +0 -29
- package/dist/market/types.d.ts.map +0 -1
- package/dist/market/types.js +0 -3
- package/dist/market/types.js.map +0 -1
- package/dist/portfolio/client.d.ts +0 -4
- package/dist/portfolio/client.d.ts.map +0 -1
- package/dist/portfolio/client.js +0 -13
- package/dist/portfolio/client.js.map +0 -1
- package/dist/portfolio/index.d.ts +0 -5
- package/dist/portfolio/index.d.ts.map +0 -1
- package/dist/portfolio/index.js +0 -26
- package/dist/portfolio/index.js.map +0 -1
- package/dist/portfolio/rebalance.d.ts +0 -62
- package/dist/portfolio/rebalance.d.ts.map +0 -1
- package/dist/portfolio/rebalance.js +0 -205
- package/dist/portfolio/rebalance.js.map +0 -1
- package/dist/portfolio/symbols.d.ts +0 -13
- package/dist/portfolio/symbols.d.ts.map +0 -1
- package/dist/portfolio/symbols.js +0 -112
- package/dist/portfolio/symbols.js.map +0 -1
- package/dist/portfolio/types.d.ts +0 -13
- package/dist/portfolio/types.d.ts.map +0 -1
- package/dist/portfolio/types.js +0 -3
- package/dist/portfolio/types.js.map +0 -1
- package/dist/strategy/backtest.d.ts +0 -6
- package/dist/strategy/backtest.d.ts.map +0 -1
- package/dist/strategy/backtest.js +0 -698
- package/dist/strategy/backtest.js.map +0 -1
- package/dist/strategy/cache.d.ts +0 -8
- package/dist/strategy/cache.d.ts.map +0 -1
- package/dist/strategy/cache.js +0 -336
- package/dist/strategy/cache.js.map +0 -1
- package/dist/strategy/client.d.ts +0 -4
- package/dist/strategy/client.d.ts.map +0 -1
- package/dist/strategy/client.js +0 -29
- package/dist/strategy/client.js.map +0 -1
- package/dist/strategy/evaluate.d.ts +0 -12
- package/dist/strategy/evaluate.d.ts.map +0 -1
- package/dist/strategy/evaluate.js +0 -562
- package/dist/strategy/evaluate.js.map +0 -1
- package/dist/strategy/get.d.ts +0 -5
- package/dist/strategy/get.d.ts.map +0 -1
- package/dist/strategy/get.js +0 -25
- package/dist/strategy/get.js.map +0 -1
- package/dist/strategy/index.d.ts +0 -14
- package/dist/strategy/index.d.ts.map +0 -1
- package/dist/strategy/index.js +0 -44
- package/dist/strategy/index.js.map +0 -1
- package/dist/strategy/livefolio.d.ts +0 -25
- package/dist/strategy/livefolio.d.ts.map +0 -1
- package/dist/strategy/livefolio.js +0 -67
- package/dist/strategy/livefolio.js.map +0 -1
- package/dist/strategy/performance.d.ts +0 -17
- package/dist/strategy/performance.d.ts.map +0 -1
- package/dist/strategy/performance.js +0 -57
- package/dist/strategy/performance.js.map +0 -1
- package/dist/strategy/rules.d.ts +0 -3
- package/dist/strategy/rules.d.ts.map +0 -1
- package/dist/strategy/rules.js +0 -95
- package/dist/strategy/rules.js.map +0 -1
- package/dist/strategy/stream.d.ts +0 -5
- package/dist/strategy/stream.d.ts.map +0 -1
- package/dist/strategy/stream.js +0 -58
- package/dist/strategy/stream.js.map +0 -1
- package/dist/strategy/symbols.d.ts +0 -4
- package/dist/strategy/symbols.d.ts.map +0 -1
- package/dist/strategy/symbols.js +0 -41
- package/dist/strategy/symbols.js.map +0 -1
- package/dist/strategy/time.d.ts +0 -10
- package/dist/strategy/time.d.ts.map +0 -1
- package/dist/strategy/time.js +0 -33
- package/dist/strategy/time.js.map +0 -1
- package/dist/strategy/types.d.ts +0 -200
- package/dist/strategy/types.d.ts.map +0 -1
- package/dist/strategy/types.js +0 -3
- package/dist/strategy/types.js.map +0 -1
- package/dist/types.d.ts +0 -4
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -3
- package/dist/types.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,140 +1,333 @@
|
|
|
1
1
|
# @livefolio/sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
TypeScript SDK for building and backtesting trading strategies. Provides lazy handles for tickers and indicators that automatically fetch market data from Yahoo Finance and FRED, compute derived indicators, and cache results in a Supabase database.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm install @livefolio/sdk
|
|
8
|
+
npm install @livefolio/sdk @supabase/supabase-js
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Quick Start
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
|
-
import {
|
|
15
|
-
import { createClient } from '@supabase/supabase-js';
|
|
14
|
+
import { createClient } from '@livefolio/sdk';
|
|
15
|
+
import { createClient as createSupabaseClient } from '@supabase/supabase-js';
|
|
16
16
|
|
|
17
|
-
const supabase =
|
|
18
|
-
|
|
17
|
+
const supabase = createSupabaseClient(SUPABASE_URL, SUPABASE_KEY);
|
|
18
|
+
|
|
19
|
+
const sdk = createClient({
|
|
20
|
+
supabase,
|
|
21
|
+
fredApiKey: 'your-fred-api-key', // optional, required for treasury indicators
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const spy = sdk.ticker('SPY');
|
|
25
|
+
const sma200 = sdk.sma(spy, 200);
|
|
26
|
+
|
|
27
|
+
// First call fetches SPY prices from Yahoo Finance, computes the 200-day SMA,
|
|
28
|
+
// stores everything in the database, and returns the result.
|
|
29
|
+
// Subsequent calls return cached data instantly.
|
|
30
|
+
const series = await sma200.series();
|
|
31
|
+
const latest = await sma200.value();
|
|
19
32
|
```
|
|
20
33
|
|
|
21
|
-
##
|
|
34
|
+
## Concepts
|
|
22
35
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
| `livefolio.market` | Historical series, real-time quotes, trading calendar |
|
|
27
|
-
| `livefolio.strategy` | Strategy retrieval, cached evaluation, live streaming |
|
|
28
|
-
| `livefolio.portfolio` | Brokerage account aggregation (stub) |
|
|
36
|
+
### Lazy Handles
|
|
37
|
+
|
|
38
|
+
Everything in the SDK is a **lazy handle** -- a lightweight object that describes *what* you want without hitting the database or any external API. Data is only fetched when you call `.series()` or `.value()`.
|
|
29
39
|
|
|
30
40
|
```ts
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
const spy = sdk.ticker('SPY'); // no DB call
|
|
42
|
+
const sma200 = sdk.sma(spy, 200); // no DB call
|
|
43
|
+
const series = await sma200.series(); // NOW: resolve -> fetch -> compute -> return
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Automatic Sync
|
|
47
|
+
|
|
48
|
+
Indicator series data is fetched and computed transparently. When you call `.series()` or `.value()`:
|
|
49
|
+
|
|
50
|
+
1. The indicator and its dependencies are resolved (upserted) in the database
|
|
51
|
+
2. If the series is stale or missing, raw data is fetched from the appropriate source
|
|
52
|
+
3. Derived indicators are computed from their dependencies
|
|
53
|
+
4. Results are upserted to the database and cached in memory
|
|
54
|
+
|
|
55
|
+
Since market data is daily closing prices, data is immutable once the trading day closes. The SDK takes advantage of this for aggressive caching.
|
|
56
|
+
|
|
57
|
+
## API Reference
|
|
58
|
+
|
|
59
|
+
### `createClient(options)`
|
|
37
60
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
61
|
+
```ts
|
|
62
|
+
createClient({
|
|
63
|
+
supabase: SupabaseClient, // required
|
|
64
|
+
fredApiKey?: string, // required for treasury indicators
|
|
65
|
+
})
|
|
41
66
|
```
|
|
42
67
|
|
|
43
|
-
|
|
68
|
+
Returns a `LivefolioClient` with the factory methods below.
|
|
69
|
+
|
|
70
|
+
### Tickers
|
|
44
71
|
|
|
45
72
|
```ts
|
|
46
|
-
|
|
47
|
-
import { createStrategy } from '@livefolio/sdk/strategy';
|
|
73
|
+
sdk.ticker(symbol: string, leverage?: number)
|
|
48
74
|
```
|
|
49
75
|
|
|
50
|
-
|
|
76
|
+
Creates a `TickerHandle`. Leverage defaults to `1`.
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
const spy = sdk.ticker('SPY');
|
|
80
|
+
const spxl = sdk.ticker('SPXL', 3);
|
|
81
|
+
```
|
|
51
82
|
|
|
52
|
-
|
|
83
|
+
### Ticker-Bound Indicators
|
|
53
84
|
|
|
54
|
-
|
|
85
|
+
These require a `TickerHandle` and compute from that ticker's price history.
|
|
55
86
|
|
|
56
|
-
|
|
87
|
+
```ts
|
|
88
|
+
sdk.sma(ticker, lookback, opts?) // Simple Moving Average
|
|
89
|
+
sdk.ema(ticker, lookback, opts?) // Exponential Moving Average
|
|
90
|
+
sdk.rsi(ticker, lookback, opts?) // Relative Strength Index
|
|
91
|
+
sdk.price(ticker, opts?) // Raw closing price
|
|
92
|
+
sdk.returns(ticker, lookback, opts?) // Period returns
|
|
93
|
+
sdk.volatility(ticker, lookback, opts?) // Rolling standard deviation
|
|
94
|
+
sdk.drawdown(ticker, lookback, opts?) // Drawdown from rolling max
|
|
95
|
+
```
|
|
57
96
|
|
|
58
|
-
|
|
59
|
-
- Strategy engine: strategy retrieval, deterministic evaluation, pure evaluation helpers, live streaming updates, and rules compilation
|
|
60
|
-
- Backtesting: DB-backed historical backtests plus performance metric helpers
|
|
61
|
-
- Portfolio tooling: drift calculations, rebalance planning, and ticker-to-tradable mapping
|
|
97
|
+
`opts` is `{ delay?: number }` -- defaults to `0`.
|
|
62
98
|
|
|
63
|
-
|
|
99
|
+
```ts
|
|
100
|
+
const spy = sdk.ticker('SPY');
|
|
101
|
+
const sma200 = sdk.sma(spy, 200);
|
|
102
|
+
const rsi14 = sdk.rsi(spy, 14);
|
|
103
|
+
const delayed = sdk.sma(spy, 50, { delay: 1 });
|
|
104
|
+
```
|
|
64
105
|
|
|
65
|
-
|
|
106
|
+
### Standalone Indicators
|
|
66
107
|
|
|
67
|
-
|
|
108
|
+
No ticker required. Data comes directly from external APIs.
|
|
68
109
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
110
|
+
```ts
|
|
111
|
+
sdk.vix(opts?) // CBOE Volatility Index
|
|
112
|
+
sdk.vix3m(opts?) // CBOE 3-Month Volatility Index
|
|
113
|
+
sdk.treasury(tenor, opts?) // Treasury rates (requires fredApiKey)
|
|
114
|
+
sdk.calendar(period, opts?) // Date components from trading calendar
|
|
115
|
+
sdk.threshold(value, unit?) // Constant value
|
|
116
|
+
```
|
|
76
117
|
|
|
77
|
-
|
|
118
|
+
Treasury tenors: `'T3M'`, `'T6M'`, `'T1Y'`, `'T2Y'`, `'T3Y'`, `'T5Y'`, `'T7Y'`, `'T10Y'`, `'T20Y'`, `'T30Y'`
|
|
78
119
|
|
|
79
|
-
|
|
120
|
+
Calendar periods: `'Month'`, `'Day of Week'`, `'Day of Month'`, `'Day of Year'`
|
|
80
121
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
122
|
+
Threshold units: `'%'`, `'$'`, or omit for unitless.
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
const vix = sdk.vix();
|
|
126
|
+
const t10y = sdk.treasury('T10Y');
|
|
127
|
+
const month = sdk.calendar('Month');
|
|
128
|
+
const half = sdk.threshold(0.5);
|
|
88
129
|
```
|
|
89
130
|
|
|
90
|
-
|
|
131
|
+
### Signals
|
|
91
132
|
|
|
92
|
-
|
|
133
|
+
Compare two indicators to create a boolean signal. Supports hysteresis via tolerance to reduce whipsawing.
|
|
93
134
|
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
npm run build
|
|
99
|
-
npm test
|
|
135
|
+
```ts
|
|
136
|
+
sdk.gt(ind1, ind2, tolerance?) // ind1 > ind2
|
|
137
|
+
sdk.lt(ind1, ind2, tolerance?) // ind1 < ind2
|
|
138
|
+
sdk.eq(ind1, ind2, tolerance?) // ind1 within tolerance range of ind2
|
|
100
139
|
```
|
|
101
140
|
|
|
102
|
-
|
|
141
|
+
Tolerance defaults to `0` (no hysteresis). When set, a buffer zone prevents the signal from flipping until the indicator moves fully through the buffer.
|
|
103
142
|
|
|
104
|
-
|
|
143
|
+
- **Relative tolerance** (Price, SMA, EMA, RSI, Threshold, Calendar): buffer = `ind2 * (1 +/- tolerance/100)`
|
|
144
|
+
- **Absolute tolerance** (Return, Volatility, Drawdown, VIX, VIX3M, Treasury): buffer = `ind2 +/- tolerance`
|
|
105
145
|
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
146
|
+
```ts
|
|
147
|
+
const spy = sdk.ticker('SPY');
|
|
148
|
+
const price = sdk.price(spy);
|
|
149
|
+
const sma200 = sdk.sma(spy, 200);
|
|
150
|
+
|
|
151
|
+
const bullish = sdk.gt(price, sma200, 5); // 5% tolerance
|
|
152
|
+
|
|
153
|
+
const series = await bullish.series(); // DailyBar[] with value 0 or 1
|
|
154
|
+
const current = await bullish.value(); // 0 or 1
|
|
110
155
|
```
|
|
111
156
|
|
|
112
|
-
|
|
157
|
+
Signal handles support the same `.series(range?)`, `.value(date?)`, and `.resolve()` methods as indicator handles. Data is automatically synced -- both underlying indicators are refreshed before computing the signal.
|
|
113
158
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
159
|
+
### Allocations
|
|
160
|
+
|
|
161
|
+
Define portfolio holdings as weighted ticker pairs.
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
sdk.allocation(...holdings: [TickerHandle, number][])
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Weights must sum to 1. Allocations are deduplicated by holdings -- creating the same allocation twice returns the same database row.
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
const aggressive = sdk.allocation([spy, 0.75], [gld, 0.25]);
|
|
171
|
+
const defensive = sdk.allocation([shy, 1.0]);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Strategies
|
|
175
|
+
|
|
176
|
+
Compose signals and allocations into a priority-ordered rule list evaluated on a rebalancing schedule.
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
// Create a new strategy
|
|
180
|
+
sdk.strategy(options: StrategyOptions)
|
|
181
|
+
|
|
182
|
+
// Reference an existing strategy by link ID
|
|
183
|
+
sdk.strategy(linkId: string)
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Each rule's `when` array is AND-ed together. OR is expressed by having multiple rules point to the same allocation. The last rule must be a fallback with no `when` clause. Rules are evaluated top-to-bottom; first match wins.
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
const spy = sdk.ticker('SPY');
|
|
190
|
+
const shy = sdk.ticker('SHY');
|
|
191
|
+
const price = sdk.price(spy);
|
|
192
|
+
const sma200 = sdk.sma(spy, 200);
|
|
193
|
+
|
|
194
|
+
const bullish = sdk.gt(price, sma200, 5);
|
|
195
|
+
|
|
196
|
+
const aggressive = sdk.allocation([spy, 1.0]);
|
|
197
|
+
const defensive = sdk.allocation([shy, 1.0]);
|
|
198
|
+
|
|
199
|
+
const strategy = sdk.strategy({
|
|
200
|
+
name: 'Tactical SPY/SHY',
|
|
201
|
+
freq: 'Monthly', // rebalance on last trading day of each month
|
|
202
|
+
offset: 0, // positive = earlier, negative = later
|
|
203
|
+
rules: [
|
|
204
|
+
{ when: [bullish], hold: aggressive },
|
|
205
|
+
{ hold: defensive }, // fallback
|
|
206
|
+
],
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
const history = await strategy.series();
|
|
210
|
+
// StrategyBar[] — { date: string, allocation: AllocationHandle }
|
|
211
|
+
|
|
212
|
+
const current = await strategy.value();
|
|
213
|
+
// AllocationHandle for the latest trading day
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Trading frequencies: `'Daily'`, `'Weekly'`, `'Monthly'`, `'Bi-monthly'`, `'Quarterly'`, `'Every 4 Months'`, `'Semiannually'`, `'Yearly'`.
|
|
217
|
+
|
|
218
|
+
Strategy series are **dense** -- one row per trading day. On rebalance dates the rules are evaluated; on other days the previous allocation carries forward.
|
|
219
|
+
|
|
220
|
+
Each strategy gets a unique `link_id` (nanoid) on creation. Reference an existing strategy by its link ID to reload it without recreating.
|
|
221
|
+
|
|
222
|
+
### Simulation
|
|
223
|
+
|
|
224
|
+
Run a portfolio simulation over a date range. Returns a `SimulationHandle` with the equity curve and trade history.
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
const spy = sdk.ticker('SPY');
|
|
228
|
+
const cashx = sdk.ticker('CASHX');
|
|
229
|
+
|
|
230
|
+
const startingPortfolio = sdk.portfolio([cashx, 100_000]);
|
|
231
|
+
|
|
232
|
+
const sim = await strategy.simulate({ from: '2020-01-01', to: '2025-12-31', portfolio: startingPortfolio });
|
|
233
|
+
|
|
234
|
+
sim.series // DailyBar[] — portfolio value per trading day
|
|
235
|
+
sim.trades // Trade[] — every buy/sell event
|
|
236
|
+
sim.startingPortfolio // PortfolioHandle — starting positions
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
You can also start from existing positions:
|
|
240
|
+
|
|
241
|
+
```ts
|
|
242
|
+
const existingPortfolio = sdk.portfolio([spy, 100], [cashx, 5000]);
|
|
243
|
+
const sim = await strategy.simulate({ from: '2024-01-01', to: '2025-12-31', portfolio: existingPortfolio });
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
The simulator rebalances at the strategy's `freq` cadence, fetches price data for all tickers in all allocations automatically, and tracks positions and cash through each trading day.
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
interface Trade {
|
|
250
|
+
date: string;
|
|
251
|
+
symbol: string;
|
|
252
|
+
quantity: number; // number of shares traded
|
|
253
|
+
price: number;
|
|
254
|
+
action: 'buy' | 'sell';
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Agents compute whatever derived metrics they need (CAGR, Sharpe, drawdown, etc.) from the raw data:
|
|
259
|
+
|
|
260
|
+
```ts
|
|
261
|
+
const values = sim.series.map(b => b.value);
|
|
262
|
+
const dailyReturns = values.slice(1).map((v, i) => (v - values[i]) / values[i]);
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Handle Methods
|
|
266
|
+
|
|
267
|
+
Every `IndicatorHandle`, `SignalHandle`, and `StrategyHandle` exposes:
|
|
268
|
+
|
|
269
|
+
#### `.series(range?)`
|
|
270
|
+
|
|
271
|
+
Returns the full time series. For indicators and signals this is `DailyBar[]`; for strategies it is `StrategyBar[]`.
|
|
272
|
+
|
|
273
|
+
```ts
|
|
274
|
+
interface DailyBar {
|
|
275
|
+
date: string; // 'YYYY-MM-DD'
|
|
276
|
+
value: number;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
interface StrategyBar {
|
|
280
|
+
date: string;
|
|
281
|
+
allocation: AllocationHandle;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const all = await sma200.series();
|
|
285
|
+
const subset = await sma200.series({ from: '2024-01-01', to: '2024-12-31' });
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
#### `.value(date?)`
|
|
289
|
+
|
|
290
|
+
Returns the latest value, or the value for a specific date. Returns `null` if no data exists. For strategies, returns `AllocationHandle | null`.
|
|
291
|
+
|
|
292
|
+
```ts
|
|
293
|
+
const latest = await sma200.value();
|
|
294
|
+
const specific = await sma200.value('2024-06-15');
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
#### `.resolve()`
|
|
298
|
+
|
|
299
|
+
Explicitly upserts the indicator to the database and returns the row. Normally you don't need to call this -- `.series()` and `.value()` call it automatically.
|
|
300
|
+
|
|
301
|
+
```ts
|
|
302
|
+
const row = await sma200.resolve();
|
|
303
|
+
console.log(row.id); // database ID
|
|
118
304
|
```
|
|
119
305
|
|
|
120
|
-
|
|
306
|
+
## Data Sources
|
|
121
307
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
308
|
+
| Indicator Type | Source |
|
|
309
|
+
|---|---|
|
|
310
|
+
| Price, VIX, VIX3M | Yahoo Finance |
|
|
311
|
+
| Treasury rates (T3M--T30Y) | FRED API |
|
|
312
|
+
| SMA, EMA, RSI, Returns, Volatility, Drawdown | Computed from Price |
|
|
313
|
+
| Calendar (Month, Day of Week, etc.) | Computed from trading days |
|
|
314
|
+
| Threshold | Constant (no external data) |
|
|
126
315
|
|
|
127
|
-
##
|
|
316
|
+
## Database
|
|
128
317
|
|
|
129
|
-
The SDK
|
|
318
|
+
The SDK uses Supabase as its backing store. Schema files are in `supabase/schemas/`. Key tables:
|
|
130
319
|
|
|
131
|
-
-
|
|
132
|
-
-
|
|
133
|
-
-
|
|
134
|
-
-
|
|
135
|
-
-
|
|
320
|
+
- `trading_days` -- market calendar with session timestamps
|
|
321
|
+
- `tickers` -- symbols with leverage multiplier
|
|
322
|
+
- `indicators` -- indicator definitions (type, params, ticker reference)
|
|
323
|
+
- `indicators_series` -- daily indicator values linked to trading days
|
|
324
|
+
- `signals` -- signal definitions (two indicators, comparison, tolerance)
|
|
325
|
+
- `signals_series` -- daily boolean signal values linked to trading days
|
|
326
|
+
- `allocations` -- portfolio holdings as JSONB (deduplicated)
|
|
327
|
+
- `strategies` -- strategy definitions with rebalance frequency and rule JSONB
|
|
328
|
+
- `strategies_series` -- active allocation per trading day per strategy (dense)
|
|
136
329
|
|
|
137
|
-
|
|
330
|
+
Run `supabase db reset` to set up the local database from the schema and seed files.
|
|
138
331
|
|
|
139
332
|
## License
|
|
140
333
|
|