tradelab 0.5.0 → 1.0.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 +89 -41
- package/bin/tradelab.js +276 -30
- package/dist/cjs/data.cjs +134 -104
- package/dist/cjs/index.cjs +378 -177
- package/dist/cjs/live.cjs +3350 -0
- package/docs/README.md +21 -9
- package/docs/api-reference.md +87 -29
- package/docs/backtest-engine.md +37 -53
- package/docs/data-reporting-cli.md +60 -34
- package/docs/examples.md +6 -12
- package/docs/live-trading.md +186 -0
- package/examples/yahooEmaCross.js +1 -6
- package/package.json +18 -3
- package/src/data/csv.js +24 -14
- package/src/data/index.js +1 -5
- package/src/data/yahoo.js +6 -19
- package/src/engine/backtest.js +137 -144
- package/src/engine/backtestTicks.js +89 -37
- package/src/engine/barSystemRunner.js +182 -118
- package/src/engine/execution.js +11 -39
- package/src/engine/portfolio.js +54 -6
- package/src/engine/walkForward.js +37 -14
- package/src/index.js +2 -11
- package/src/live/broker/alpaca.js +254 -0
- package/src/live/broker/binance.js +351 -0
- package/src/live/broker/coinbase.js +339 -0
- package/src/live/broker/interactiveBrokers.js +123 -0
- package/src/live/broker/interface.js +74 -0
- package/src/live/clock.js +56 -0
- package/src/live/engine/candleAggregator.js +154 -0
- package/src/live/engine/liveEngine.js +694 -0
- package/src/live/engine/paperEngine.js +453 -0
- package/src/live/engine/riskManager.js +185 -0
- package/src/live/engine/stateManager.js +112 -0
- package/src/live/events.js +48 -0
- package/src/live/feed/brokerFeed.js +35 -0
- package/src/live/feed/interface.js +28 -0
- package/src/live/feed/pollingFeed.js +105 -0
- package/src/live/index.js +27 -0
- package/src/live/logger.js +82 -0
- package/src/live/orchestrator.js +133 -0
- package/src/live/storage/interface.js +36 -0
- package/src/live/storage/jsonFileStorage.js +112 -0
- package/src/metrics/buildMetrics.js +18 -41
- package/src/reporting/exportBacktestArtifacts.js +1 -4
- package/src/reporting/exportTradesCsv.js +2 -7
- package/src/reporting/renderHtmlReport.js +8 -13
- package/src/utils/indicators.js +1 -2
- package/src/utils/positionSizing.js +16 -2
- package/src/utils/time.js +4 -12
- package/templates/report.html +23 -9
- package/templates/report.js +83 -69
- package/types/index.d.ts +21 -3
- package/types/live.d.ts +382 -0
package/docs/README.md
CHANGED
|
@@ -4,20 +4,23 @@
|
|
|
4
4
|
|
|
5
5
|
- [Backtest engine](backtest-engine.md)
|
|
6
6
|
- [Data, reporting, and CLI](data-reporting-cli.md)
|
|
7
|
+
- [Live trading](live-trading.md)
|
|
7
8
|
- [Strategy examples](examples.md)
|
|
8
9
|
- [API reference](api-reference.md)
|
|
9
10
|
|
|
10
11
|
## Choose a path
|
|
11
12
|
|
|
12
|
-
| Goal
|
|
13
|
-
|
|
|
14
|
-
| Run one strategy on one dataset
|
|
15
|
-
| Load Yahoo or CSV data
|
|
13
|
+
| Goal | Start here |
|
|
14
|
+
| ------------------------------------------ | ------------------------------------------------- |
|
|
15
|
+
| Run one strategy on one dataset | [Backtest engine](backtest-engine.md) |
|
|
16
|
+
| Load Yahoo or CSV data | [Data, reporting, and CLI](data-reporting-cli.md) |
|
|
16
17
|
| Export reports or machine-readable results | [Data, reporting, and CLI](data-reporting-cli.md) |
|
|
17
|
-
| Run multiple symbols together
|
|
18
|
-
| Run walk-forward validation
|
|
19
|
-
|
|
|
20
|
-
|
|
|
18
|
+
| Run multiple symbols together | [Backtest engine](backtest-engine.md) |
|
|
19
|
+
| Run walk-forward validation | [Backtest engine](backtest-engine.md) |
|
|
20
|
+
| Run one strategy live or in paper mode | [Live trading](live-trading.md) |
|
|
21
|
+
| Run multiple live systems together | [Live trading](live-trading.md) |
|
|
22
|
+
| See complete strategy patterns | [Strategy examples](examples.md) |
|
|
23
|
+
| Check the exact public exports | [API reference](api-reference.md) |
|
|
21
24
|
|
|
22
25
|
## Package scope
|
|
23
26
|
|
|
@@ -26,12 +29,12 @@ tradelab is built for:
|
|
|
26
29
|
- candle-based strategy research
|
|
27
30
|
- optional tick or quote replay with event-driven fills
|
|
28
31
|
- historical backtests with configurable fills and costs
|
|
32
|
+
- live and paper execution using broker adapters
|
|
29
33
|
- CSV and Yahoo-based data workflows
|
|
30
34
|
- exportable outputs for review or automation
|
|
31
35
|
|
|
32
36
|
tradelab is not built for:
|
|
33
37
|
|
|
34
|
-
- live broker execution
|
|
35
38
|
- exchange microstructure modeling
|
|
36
39
|
|
|
37
40
|
## Common workflows
|
|
@@ -56,10 +59,19 @@ tradelab is not built for:
|
|
|
56
59
|
3. Run `walkForwardOptimize()`
|
|
57
60
|
4. Review per-window winners before trusting the aggregate result
|
|
58
61
|
|
|
62
|
+
### Live execution workflow
|
|
63
|
+
|
|
64
|
+
1. Build a `signal()` used in backtest first
|
|
65
|
+
2. Wire it into `LiveEngine` with a broker or `PaperEngine`
|
|
66
|
+
3. Persist state with `JsonFileStorage`
|
|
67
|
+
4. Start with `tradelab paper` or `tradelab live --paper`
|
|
68
|
+
5. Inspect persisted state with `tradelab status`
|
|
69
|
+
|
|
59
70
|
## Documentation map
|
|
60
71
|
|
|
61
72
|
- [Backtest engine](backtest-engine.md): strategy inputs, engine options, result shape, portfolio mode, walk-forward mode
|
|
62
73
|
- [Data, reporting, and CLI](data-reporting-cli.md): data loading, cache behavior, exports, terminal usage
|
|
74
|
+
- [Live trading](live-trading.md): live engine, broker adapters, paper mode, orchestration, lifecycle, and state
|
|
63
75
|
- [Strategy examples](examples.md): mean reversion, breakout, sentiment, LLM, and portfolio research patterns
|
|
64
76
|
- [API reference](api-reference.md): compact export index
|
|
65
77
|
|
package/docs/api-reference.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
1
|
# API reference
|
|
2
|
+
|
|
3
3
|
<small>[Back to main page](README.md)</small>
|
|
4
4
|
|
|
5
5
|
This page is the compact index of public exports.
|
|
@@ -8,40 +8,95 @@ If you are learning the package, start with [backtest-engine.md](backtest-engine
|
|
|
8
8
|
|
|
9
9
|
## Backtesting
|
|
10
10
|
|
|
11
|
-
| Export
|
|
12
|
-
|
|
|
13
|
-
| `backtest(options)`
|
|
14
|
-
| `backtestTicks(options)`
|
|
15
|
-
| `backtestPortfolio(options)`
|
|
16
|
-
| `walkForwardOptimize(options)` | Run rolling or anchored train/test validation
|
|
17
|
-
| `buildMetrics(input)`
|
|
11
|
+
| Export | Summary |
|
|
12
|
+
| ------------------------------ | -------------------------------------------------------------- |
|
|
13
|
+
| `backtest(options)` | Run one strategy on one candle series |
|
|
14
|
+
| `backtestTicks(options)` | Run one strategy on tick or quote data |
|
|
15
|
+
| `backtestPortfolio(options)` | Run multiple systems through a shared-capital portfolio engine |
|
|
16
|
+
| `walkForwardOptimize(options)` | Run rolling or anchored train/test validation |
|
|
17
|
+
| `buildMetrics(input)` | Compute metrics from realized trades and equity data |
|
|
18
18
|
|
|
19
19
|
## Data
|
|
20
20
|
|
|
21
|
-
| Export
|
|
22
|
-
|
|
|
23
|
-
| `getHistoricalCandles(options)`
|
|
24
|
-
| `backtestHistorical({ data, backtestOptions })`
|
|
25
|
-
| `fetchHistorical(symbol, interval, period, options)`
|
|
26
|
-
| `fetchLatestCandle(symbol, interval, options)`
|
|
27
|
-
| `loadCandlesFromCSV(filePath, options)`
|
|
28
|
-
| `normalizeCandles(candles)`
|
|
29
|
-
| `mergeCandles(...arrays)`
|
|
30
|
-
| `candleStats(candles)`
|
|
31
|
-
| `saveCandlesToCache(candles, meta)`
|
|
32
|
-
| `loadCandlesFromCache(symbol, interval, period, outDir)` | Read normalized candles from the local cache
|
|
33
|
-
| `cachedCandlesPath(symbol, interval, period, outDir)`
|
|
21
|
+
| Export | Summary |
|
|
22
|
+
| -------------------------------------------------------- | --------------------------------------------- |
|
|
23
|
+
| `getHistoricalCandles(options)` | Load candles from Yahoo or CSV |
|
|
24
|
+
| `backtestHistorical({ data, backtestOptions })` | Load candles and immediately run `backtest()` |
|
|
25
|
+
| `fetchHistorical(symbol, interval, period, options)` | Call the Yahoo layer directly |
|
|
26
|
+
| `fetchLatestCandle(symbol, interval, options)` | Fetch the latest Yahoo candle |
|
|
27
|
+
| `loadCandlesFromCSV(filePath, options)` | Parse and normalize a CSV file |
|
|
28
|
+
| `normalizeCandles(candles)` | Normalize candle field names and sort/dedupe |
|
|
29
|
+
| `mergeCandles(...arrays)` | Merge multiple candle arrays |
|
|
30
|
+
| `candleStats(candles)` | Return summary stats for a candle array |
|
|
31
|
+
| `saveCandlesToCache(candles, meta)` | Write normalized candles to the local cache |
|
|
32
|
+
| `loadCandlesFromCache(symbol, interval, period, outDir)` | Read normalized candles from the local cache |
|
|
33
|
+
| `cachedCandlesPath(symbol, interval, period, outDir)` | Return the expected cache path |
|
|
34
34
|
|
|
35
35
|
## Reporting
|
|
36
36
|
|
|
37
|
-
| Export
|
|
38
|
-
|
|
|
39
|
-
| `renderHtmlReport(options)`
|
|
40
|
-
| `exportHtmlReport(options)`
|
|
41
|
-
| `exportTradesCsv(trades, options)` | Write a CSV ledger of trades or positions
|
|
42
|
-
| `exportMetricsJSON(options)`
|
|
37
|
+
| Export | Summary |
|
|
38
|
+
| ---------------------------------- | ------------------------------------------ |
|
|
39
|
+
| `renderHtmlReport(options)` | Return the HTML report as a string |
|
|
40
|
+
| `exportHtmlReport(options)` | Write the HTML report to disk |
|
|
41
|
+
| `exportTradesCsv(trades, options)` | Write a CSV ledger of trades or positions |
|
|
42
|
+
| `exportMetricsJSON(options)` | Write machine-readable metrics JSON |
|
|
43
43
|
| `exportBacktestArtifacts(options)` | Write HTML, CSV, and metrics JSON together |
|
|
44
44
|
|
|
45
|
+
## Live module (`tradelab/live`)
|
|
46
|
+
|
|
47
|
+
Live exports are under a separate entrypoint:
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
import { LiveEngine, PaperEngine } from "tradelab/live";
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Engine and orchestration
|
|
54
|
+
|
|
55
|
+
- `LiveEngine`
|
|
56
|
+
- `LiveOrchestrator`
|
|
57
|
+
- `PaperEngine`
|
|
58
|
+
- `CandleAggregator`
|
|
59
|
+
- `RiskManager`
|
|
60
|
+
- `StateManager`
|
|
61
|
+
|
|
62
|
+
### Broker and feed adapters
|
|
63
|
+
|
|
64
|
+
- `BrokerAdapter`
|
|
65
|
+
- `AlpacaBroker`
|
|
66
|
+
- `BinanceBroker`
|
|
67
|
+
- `CoinbaseBroker`
|
|
68
|
+
- `InteractiveBrokersBroker`
|
|
69
|
+
- `FeedProvider`
|
|
70
|
+
- `BrokerFeed`
|
|
71
|
+
- `PollingFeed`
|
|
72
|
+
|
|
73
|
+
### Storage and runtime utilities
|
|
74
|
+
|
|
75
|
+
- `StorageProvider`
|
|
76
|
+
- `JsonFileStorage`
|
|
77
|
+
- `EventBus`
|
|
78
|
+
- `LiveLogger`
|
|
79
|
+
- `BrokerClock`
|
|
80
|
+
|
|
81
|
+
### Factories
|
|
82
|
+
|
|
83
|
+
- `createLiveEngine(options)`
|
|
84
|
+
- `createLiveOrchestrator(options)`
|
|
85
|
+
- `createPaperEngine(options)`
|
|
86
|
+
- `createAlpacaBroker(options)`
|
|
87
|
+
- `createBinanceBroker(options)`
|
|
88
|
+
- `createCoinbaseBroker(options)`
|
|
89
|
+
- `createInteractiveBrokersBroker(options)`
|
|
90
|
+
- `createBrokerFeed(options)`
|
|
91
|
+
- `createPollingFeed(options)`
|
|
92
|
+
- `createJsonFileStorage(options)`
|
|
93
|
+
- `createCandleAggregator(options)`
|
|
94
|
+
- `createRiskManager(options)`
|
|
95
|
+
- `createStateManager(options)`
|
|
96
|
+
- `createEventBus()`
|
|
97
|
+
- `createLogger(options)`
|
|
98
|
+
- `createClock(options)`
|
|
99
|
+
|
|
45
100
|
## Indicators and utilities
|
|
46
101
|
|
|
47
102
|
### Indicators
|
|
@@ -70,6 +125,9 @@ If you are learning the package, start with [backtest-engine.md](backtest-engine
|
|
|
70
125
|
|
|
71
126
|
## Types
|
|
72
127
|
|
|
73
|
-
The package ships declarations in
|
|
128
|
+
The package ships declarations in:
|
|
74
129
|
|
|
75
|
-
|
|
130
|
+
- [../types/index.d.ts](../types/index.d.ts) for the main module
|
|
131
|
+
- [../types/live.d.ts](../types/live.d.ts) for `tradelab/live`
|
|
132
|
+
|
|
133
|
+
<small>[Back to main page](README.md)</small>
|
package/docs/backtest-engine.md
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
<small>[Back to main page](README.md)</small>
|
|
4
4
|
|
|
5
|
-
|
|
6
5
|
This page covers the simulation layer:
|
|
7
6
|
|
|
8
7
|
- `backtest(options)`
|
|
@@ -15,15 +14,17 @@ This page covers the simulation layer:
|
|
|
15
14
|
|
|
16
15
|
Use the engine layer when you already have candles and want to simulate strategy behavior, inspect the result, and export or post-process it.
|
|
17
16
|
|
|
17
|
+
The same `signal()` contract is used by `LiveEngine` in `tradelab/live`, so strategy logic can move from research to execution without rewriting signal inputs.
|
|
18
|
+
|
|
18
19
|
## Choose the right function
|
|
19
20
|
|
|
20
|
-
| Use case
|
|
21
|
-
|
|
|
22
|
-
| One strategy on one candle series
|
|
23
|
-
| One strategy on tick or quote data
|
|
24
|
-
| Multiple symbols with one combined result | `backtestPortfolio()`
|
|
21
|
+
| Use case | Function |
|
|
22
|
+
| ----------------------------------------- | ----------------------- |
|
|
23
|
+
| One strategy on one candle series | `backtest()` |
|
|
24
|
+
| One strategy on tick or quote data | `backtestTicks()` |
|
|
25
|
+
| Multiple symbols with one combined result | `backtestPortfolio()` |
|
|
25
26
|
| Rolling or anchored train/test validation | `walkForwardOptimize()` |
|
|
26
|
-
| Recompute metrics from realized trades
|
|
27
|
+
| Recompute metrics from realized trades | `buildMetrics()` |
|
|
27
28
|
|
|
28
29
|
## Candle input
|
|
29
30
|
|
|
@@ -76,16 +77,16 @@ const result = backtest({
|
|
|
76
77
|
|
|
77
78
|
### Core options
|
|
78
79
|
|
|
79
|
-
| Option
|
|
80
|
-
|
|
|
81
|
-
| `symbol`, `interval`, `range`
|
|
82
|
-
| `equity`
|
|
83
|
-
| `riskPct` or `riskFraction`
|
|
84
|
-
| `warmupBars`
|
|
85
|
-
| `flattenAtClose`
|
|
86
|
-
| `collectEqSeries`, `collectReplay` | Builds extra output for charts and exports
|
|
87
|
-
| `strict`
|
|
88
|
-
| `costs`
|
|
80
|
+
| Option | Purpose |
|
|
81
|
+
| ---------------------------------- | -------------------------------------------------------------- |
|
|
82
|
+
| `symbol`, `interval`, `range` | Labels carried into results and exports |
|
|
83
|
+
| `equity` | Starting equity, default `10000` |
|
|
84
|
+
| `riskPct` or `riskFraction` | Default risk per trade when `qty` is not provided |
|
|
85
|
+
| `warmupBars` | Bars skipped before signal evaluation starts |
|
|
86
|
+
| `flattenAtClose` | Forces end-of-day exit when enabled |
|
|
87
|
+
| `collectEqSeries`, `collectReplay` | Builds extra output for charts and exports |
|
|
88
|
+
| `strict` | Throws on direct lookahead access such as `candles[index + 1]` |
|
|
89
|
+
| `costs` | Slippage, spread, and commission model |
|
|
89
90
|
|
|
90
91
|
If you are starting from scratch, the most useful options to set explicitly are:
|
|
91
92
|
|
|
@@ -97,38 +98,31 @@ If you are starting from scratch, the most useful options to set explicitly are:
|
|
|
97
98
|
|
|
98
99
|
### Signal contract
|
|
99
100
|
|
|
100
|
-
The signal function receives:
|
|
101
|
+
The signal function receives a context object with these fields:
|
|
101
102
|
|
|
103
|
+
<!-- prettier-ignore -->
|
|
102
104
|
```js
|
|
103
|
-
{
|
|
104
|
-
candles,
|
|
105
|
-
index,
|
|
106
|
-
bar,
|
|
107
|
-
equity,
|
|
108
|
-
openPosition,
|
|
109
|
-
pendingOrder
|
|
110
|
-
}
|
|
105
|
+
{ candles, index, bar, equity, openPosition, pendingOrder }
|
|
111
106
|
```
|
|
112
107
|
|
|
113
108
|
Return `null` for no trade, or a signal object:
|
|
114
109
|
|
|
115
110
|
```js
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
111
|
+
// minimal
|
|
112
|
+
{ side: "long", stop: 99.75, rr: 2 }
|
|
113
|
+
|
|
114
|
+
// explicit targets
|
|
115
|
+
{ side: "long", entry: 101.25, stop: 99.75, takeProfit: 104.25 }
|
|
122
116
|
```
|
|
123
117
|
|
|
124
118
|
### Signal conveniences
|
|
125
119
|
|
|
126
|
-
| Field
|
|
127
|
-
|
|
|
128
|
-
| `side`
|
|
129
|
-
| `entry`
|
|
130
|
-
| `takeProfit`
|
|
131
|
-
| `qty` or `size`
|
|
120
|
+
| Field | Behavior |
|
|
121
|
+
| --------------------------- | ------------------------------------------------ |
|
|
122
|
+
| `side` | Accepts `long`, `short`, `buy`, or `sell` |
|
|
123
|
+
| `entry` | Defaults to the current close if omitted |
|
|
124
|
+
| `takeProfit` | Can be derived from `rr` or `_rr` |
|
|
125
|
+
| `qty` or `size` | Overrides risk-based sizing |
|
|
132
126
|
| `riskPct` or `riskFraction` | Overrides the global risk setting for that trade |
|
|
133
127
|
|
|
134
128
|
Practical rule: return the smallest signal object that expresses the trade clearly. In many strategies that is just `side`, `stop`, and `rr`.
|
|
@@ -207,19 +201,11 @@ Recommended order of adoption:
|
|
|
207
201
|
|
|
208
202
|
## Result shape
|
|
209
203
|
|
|
210
|
-
`backtest()` returns:
|
|
204
|
+
`backtest()` returns an object with these fields:
|
|
211
205
|
|
|
206
|
+
<!-- prettier-ignore -->
|
|
212
207
|
```js
|
|
213
|
-
{
|
|
214
|
-
symbol,
|
|
215
|
-
interval,
|
|
216
|
-
range,
|
|
217
|
-
trades,
|
|
218
|
-
positions,
|
|
219
|
-
metrics,
|
|
220
|
-
eqSeries,
|
|
221
|
-
replay
|
|
222
|
-
}
|
|
208
|
+
{ symbol, interval, range, trades, positions, openPositions, metrics, eqSeries, replay }
|
|
223
209
|
```
|
|
224
210
|
|
|
225
211
|
### `trades`
|
|
@@ -267,9 +253,7 @@ Useful first checks after any run:
|
|
|
267
253
|
Realized equity points:
|
|
268
254
|
|
|
269
255
|
```js
|
|
270
|
-
[
|
|
271
|
-
{ time, timestamp, equity }
|
|
272
|
-
]
|
|
256
|
+
[{ time, timestamp, equity }];
|
|
273
257
|
```
|
|
274
258
|
|
|
275
259
|
`time` and `timestamp` contain the same Unix-millisecond value.
|
|
@@ -390,4 +374,4 @@ Most users do not need this directly. Use it when:
|
|
|
390
374
|
- trusting one backtest without out-of-sample validation
|
|
391
375
|
- debugging a strategy with `strict: false` when lookahead is possible
|
|
392
376
|
|
|
393
|
-
<small>[Back to main page](README.md)</small>
|
|
377
|
+
<small>[Back to main page](README.md)</small>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# Data, reporting, and CLI
|
|
2
|
+
|
|
2
3
|
<small>[Back to main page](README.md)</small>
|
|
3
4
|
|
|
4
5
|
This page covers the parts of the package around the core engine:
|
|
@@ -6,7 +7,7 @@ This page covers the parts of the package around the core engine:
|
|
|
6
7
|
- historical data loading
|
|
7
8
|
- local cache helpers
|
|
8
9
|
- export helpers
|
|
9
|
-
- command-line usage
|
|
10
|
+
- command-line usage for backtest and live workflows
|
|
10
11
|
|
|
11
12
|
## Overview
|
|
12
13
|
|
|
@@ -14,13 +15,13 @@ If you are not bringing your own candles yet, start here.
|
|
|
14
15
|
|
|
15
16
|
## Choose the right entry point
|
|
16
17
|
|
|
17
|
-
| Use case
|
|
18
|
-
|
|
|
18
|
+
| Use case | Function |
|
|
19
|
+
| --------------------------------------------------------- | ------------------------ |
|
|
19
20
|
| Load data without caring about the source-specific helper | `getHistoricalCandles()` |
|
|
20
|
-
| Fetch directly from Yahoo
|
|
21
|
-
| Load a local CSV file
|
|
22
|
-
| Reuse saved normalized data
|
|
23
|
-
| Try the package from a terminal first
|
|
21
|
+
| Fetch directly from Yahoo | `fetchHistorical()` |
|
|
22
|
+
| Load a local CSV file | `loadCandlesFromCSV()` |
|
|
23
|
+
| Reuse saved normalized data | `loadCandlesFromCache()` |
|
|
24
|
+
| Try the package from a terminal first | `tradelab` CLI |
|
|
24
25
|
|
|
25
26
|
## Historical data
|
|
26
27
|
|
|
@@ -50,15 +51,15 @@ If you are writing application code, prefer `getHistoricalCandles()` over callin
|
|
|
50
51
|
|
|
51
52
|
### Yahoo options
|
|
52
53
|
|
|
53
|
-
| Option
|
|
54
|
-
|
|
|
55
|
-
| `symbol`
|
|
56
|
-
| `interval`
|
|
57
|
-
| `period`
|
|
54
|
+
| Option | Purpose |
|
|
55
|
+
| ---------------- | ----------------------------------------------------- |
|
|
56
|
+
| `symbol` | Ticker or Yahoo symbol |
|
|
57
|
+
| `interval` | Candle interval such as `1d` or `5m` |
|
|
58
|
+
| `period` | Lookback period such as `6mo` or `1y` |
|
|
58
59
|
| `includePrePost` | Includes premarket and postmarket data when supported |
|
|
59
|
-
| `cache`
|
|
60
|
-
| `refresh`
|
|
61
|
-
| `cacheDir`
|
|
60
|
+
| `cache` | Reuses saved normalized data |
|
|
61
|
+
| `refresh` | Forces a fresh download even if cache exists |
|
|
62
|
+
| `cacheDir` | Overrides the default cache directory |
|
|
62
63
|
|
|
63
64
|
The Yahoo layer retries transient failures with exponential backoff. If the endpoint still fails, the error message points users toward CSV or cached data.
|
|
64
65
|
|
|
@@ -149,12 +150,9 @@ The main bundle export. By default it writes:
|
|
|
149
150
|
|
|
150
151
|
Return value:
|
|
151
152
|
|
|
153
|
+
<!-- prettier-ignore -->
|
|
152
154
|
```js
|
|
153
|
-
{
|
|
154
|
-
csv,
|
|
155
|
-
html,
|
|
156
|
-
metrics
|
|
157
|
-
}
|
|
155
|
+
{ csv, html, metrics }
|
|
158
156
|
```
|
|
159
157
|
|
|
160
158
|
If you only need one output type, call the narrower helper directly.
|
|
@@ -184,13 +182,16 @@ The CLI is best for quick iteration, smoke tests, and trying the package before
|
|
|
184
182
|
|
|
185
183
|
## Commands
|
|
186
184
|
|
|
187
|
-
| Command
|
|
188
|
-
|
|
|
189
|
-
| `tradelab backtest`
|
|
190
|
-
| `tradelab portfolio`
|
|
185
|
+
| Command | Purpose |
|
|
186
|
+
| ----------------------- | ------------------------------------------------------------------------- |
|
|
187
|
+
| `tradelab backtest` | Run a single backtest from Yahoo or CSV |
|
|
188
|
+
| `tradelab portfolio` | Run a simple multi-file portfolio backtest |
|
|
191
189
|
| `tradelab walk-forward` | Run rolling or anchored validation with built-in or local strategy search |
|
|
192
|
-
| `tradelab
|
|
193
|
-
| `tradelab
|
|
190
|
+
| `tradelab live` | Run live engine or orchestrator mode |
|
|
191
|
+
| `tradelab paper` | Run live engine in paper broker mode |
|
|
192
|
+
| `tradelab status` | Inspect persisted live namespace state |
|
|
193
|
+
| `tradelab prefetch` | Download and cache Yahoo data |
|
|
194
|
+
| `tradelab import-csv` | Normalize and cache a CSV file |
|
|
194
195
|
|
|
195
196
|
### Backtest
|
|
196
197
|
|
|
@@ -238,6 +239,31 @@ tradelab walk-forward \
|
|
|
238
239
|
|
|
239
240
|
The CLI walk-forward command defaults to the built-in `ema-cross` search, but `--strategy ./path/to/module.mjs` can now load a local module that exports `signalFactory(params, args)` and either `parameterSets` or `createParameterSets(args)`. Inline JSON grids are also accepted through `--parameterSets`.
|
|
240
241
|
|
|
242
|
+
### Live and paper
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
tradelab paper --symbol AAPL --interval 1m --mode polling --once true
|
|
246
|
+
|
|
247
|
+
tradelab live \
|
|
248
|
+
--strategy ./mySignal.js \
|
|
249
|
+
--symbol AAPL \
|
|
250
|
+
--interval 1m \
|
|
251
|
+
--broker alpaca \
|
|
252
|
+
--apiKey $APCA_KEY \
|
|
253
|
+
--apiSecret $APCA_SECRET
|
|
254
|
+
|
|
255
|
+
tradelab live --config ./live-portfolio.json --paper --mode polling --once true
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
For full runtime details, see [live-trading.md](live-trading.md).
|
|
259
|
+
|
|
260
|
+
### Status
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
tradelab status --dir ./output/live-state
|
|
264
|
+
tradelab status --dir ./output/live-state --namespace my-system
|
|
265
|
+
```
|
|
266
|
+
|
|
241
267
|
### Cache utilities
|
|
242
268
|
|
|
243
269
|
```bash
|
|
@@ -247,12 +273,12 @@ tradelab import-csv --csvPath ./data/spy.csv --symbol SPY --interval 1d
|
|
|
247
273
|
|
|
248
274
|
## Troubleshooting
|
|
249
275
|
|
|
250
|
-
| Problem
|
|
251
|
-
|
|
|
252
|
-
| Yahoo request errors
|
|
253
|
-
| Unexpected trade count | `warmupBars`, `flattenAtClose`, and signal frequency
|
|
254
|
-
| Empty result
|
|
255
|
-
| Confusing CSV import
|
|
256
|
-
| Export confusion
|
|
276
|
+
| Problem | Check first |
|
|
277
|
+
| ---------------------- | ---------------------------------------------------------------------- |
|
|
278
|
+
| Yahoo request errors | enable cache, retry later, or fall back to CSV |
|
|
279
|
+
| Unexpected trade count | `warmupBars`, `flattenAtClose`, and signal frequency |
|
|
280
|
+
| Empty result | candle order, signal logic, and stop/target validity |
|
|
281
|
+
| Confusing CSV import | inspect normalized bars from `loadCandlesFromCSV()` before backtesting |
|
|
282
|
+
| Export confusion | use metrics JSON first if you need programmatic output |
|
|
257
283
|
|
|
258
|
-
<small>[Back to main page](README.md)</small>
|
|
284
|
+
<small>[Back to main page](README.md)</small>
|
package/docs/examples.md
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# Strategy examples
|
|
2
|
+
|
|
2
3
|
<small>[Back to main page](README.md)</small>
|
|
3
4
|
|
|
4
5
|
These are research templates. They show how to wire different kinds of data and execution assumptions into the engine without changing the output pipeline.
|
|
@@ -117,14 +118,13 @@ const candles = await getHistoricalCandles({
|
|
|
117
118
|
|
|
118
119
|
const sentimentByDay = new Map([
|
|
119
120
|
["2025-01-02", 0.75],
|
|
120
|
-
["2025-01-03", -0.
|
|
121
|
+
["2025-01-03", -0.1],
|
|
121
122
|
// ...
|
|
122
123
|
]);
|
|
123
124
|
|
|
124
125
|
const enriched = candles.map((bar) => ({
|
|
125
126
|
...bar,
|
|
126
|
-
sentiment:
|
|
127
|
-
sentimentByDay.get(new Date(bar.time).toISOString().slice(0, 10)) ?? 0,
|
|
127
|
+
sentiment: sentimentByDay.get(new Date(bar.time).toISOString().slice(0, 10)) ?? 0,
|
|
128
128
|
}));
|
|
129
129
|
|
|
130
130
|
const result = backtest({
|
|
@@ -137,11 +137,7 @@ const result = backtest({
|
|
|
137
137
|
const slow = ema(closes, 30);
|
|
138
138
|
const last = closes.length - 1;
|
|
139
139
|
|
|
140
|
-
if (
|
|
141
|
-
fast[last - 1] <= slow[last - 1] &&
|
|
142
|
-
fast[last] > slow[last] &&
|
|
143
|
-
bar.sentiment > 0.5
|
|
144
|
-
) {
|
|
140
|
+
if (fast[last - 1] <= slow[last - 1] && fast[last] > slow[last] && bar.sentiment > 0.5) {
|
|
145
141
|
return {
|
|
146
142
|
side: "long",
|
|
147
143
|
entry: bar.close,
|
|
@@ -180,9 +176,7 @@ const labeled = await Promise.all(
|
|
|
180
176
|
regime:
|
|
181
177
|
index < 20
|
|
182
178
|
? "neutral"
|
|
183
|
-
: await classifyRegime(
|
|
184
|
-
candles.slice(index - 20, index).map((c) => c.close)
|
|
185
|
-
),
|
|
179
|
+
: await classifyRegime(candles.slice(index - 20, index).map((c) => c.close)),
|
|
186
180
|
}))
|
|
187
181
|
);
|
|
188
182
|
|
|
@@ -278,4 +272,4 @@ const result = backtestPortfolio({
|
|
|
278
272
|
|
|
279
273
|
`result.eqSeries` includes `lockedCapital` and `availableCapital` at each realized equity point. Use those to see how often the portfolio was fully deployed versus sitting partially idle.
|
|
280
274
|
|
|
281
|
-
<small>[Back to main page](README.md)</small>
|
|
275
|
+
<small>[Back to main page](README.md)</small>
|