tradelab 0.4.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 +121 -52
- package/bin/tradelab.js +340 -49
- package/dist/cjs/data.cjs +210 -155
- package/dist/cjs/index.cjs +1782 -274
- package/dist/cjs/live.cjs +3350 -0
- package/docs/README.md +26 -9
- package/docs/api-reference.md +89 -26
- package/docs/backtest-engine.md +74 -60
- package/docs/data-reporting-cli.md +66 -36
- package/docs/examples.md +275 -0
- 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 +481 -0
- package/src/engine/barSystemRunner.js +1027 -0
- package/src/engine/execution.js +11 -39
- package/src/engine/portfolio.js +237 -66
- package/src/engine/walkForward.js +132 -13
- package/src/index.js +3 -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 +103 -100
- 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 +98 -4
- package/types/live.d.ts +382 -0
package/docs/README.md
CHANGED
|
@@ -4,32 +4,37 @@
|
|
|
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)
|
|
8
|
+
- [Strategy examples](examples.md)
|
|
7
9
|
- [API reference](api-reference.md)
|
|
8
10
|
|
|
9
11
|
## Choose a path
|
|
10
12
|
|
|
11
|
-
| Goal
|
|
12
|
-
|
|
|
13
|
-
| Run one strategy on one dataset
|
|
14
|
-
| 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) |
|
|
15
17
|
| Export reports or machine-readable results | [Data, reporting, and CLI](data-reporting-cli.md) |
|
|
16
|
-
| Run multiple symbols together
|
|
17
|
-
| Run walk-forward validation
|
|
18
|
-
|
|
|
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) |
|
|
19
24
|
|
|
20
25
|
## Package scope
|
|
21
26
|
|
|
22
27
|
tradelab is built for:
|
|
23
28
|
|
|
24
29
|
- candle-based strategy research
|
|
30
|
+
- optional tick or quote replay with event-driven fills
|
|
25
31
|
- historical backtests with configurable fills and costs
|
|
32
|
+
- live and paper execution using broker adapters
|
|
26
33
|
- CSV and Yahoo-based data workflows
|
|
27
34
|
- exportable outputs for review or automation
|
|
28
35
|
|
|
29
36
|
tradelab is not built for:
|
|
30
37
|
|
|
31
|
-
- live broker execution
|
|
32
|
-
- tick-level simulation
|
|
33
38
|
- exchange microstructure modeling
|
|
34
39
|
|
|
35
40
|
## Common workflows
|
|
@@ -54,8 +59,20 @@ tradelab is not built for:
|
|
|
54
59
|
3. Run `walkForwardOptimize()`
|
|
55
60
|
4. Review per-window winners before trusting the aggregate result
|
|
56
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
|
+
|
|
57
70
|
## Documentation map
|
|
58
71
|
|
|
59
72
|
- [Backtest engine](backtest-engine.md): strategy inputs, engine options, result shape, portfolio mode, walk-forward mode
|
|
60
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
|
|
75
|
+
- [Strategy examples](examples.md): mean reversion, breakout, sentiment, LLM, and portfolio research patterns
|
|
61
76
|
- [API reference](api-reference.md): compact export index
|
|
77
|
+
|
|
78
|
+
<small>[Back to README.md](../README.md)</small>
|
package/docs/api-reference.md
CHANGED
|
@@ -1,44 +1,102 @@
|
|
|
1
1
|
# API reference
|
|
2
2
|
|
|
3
|
+
<small>[Back to main page](README.md)</small>
|
|
4
|
+
|
|
3
5
|
This page is the compact index of public exports.
|
|
4
6
|
|
|
5
7
|
If you are learning the package, start with [backtest-engine.md](backtest-engine.md) or [data-reporting-cli.md](data-reporting-cli.md). This page is for quick lookup.
|
|
6
8
|
|
|
7
9
|
## Backtesting
|
|
8
10
|
|
|
9
|
-
| Export
|
|
10
|
-
|
|
|
11
|
-
| `backtest(options)`
|
|
12
|
-
| `
|
|
13
|
-
| `
|
|
14
|
-
| `
|
|
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 |
|
|
15
18
|
|
|
16
19
|
## Data
|
|
17
20
|
|
|
18
|
-
| Export
|
|
19
|
-
|
|
|
20
|
-
| `getHistoricalCandles(options)`
|
|
21
|
-
| `backtestHistorical({ data, backtestOptions })`
|
|
22
|
-
| `fetchHistorical(symbol, interval, period, options)`
|
|
23
|
-
| `fetchLatestCandle(symbol, interval, options)`
|
|
24
|
-
| `loadCandlesFromCSV(filePath, options)`
|
|
25
|
-
| `normalizeCandles(candles)`
|
|
26
|
-
| `mergeCandles(...arrays)`
|
|
27
|
-
| `candleStats(candles)`
|
|
28
|
-
| `saveCandlesToCache(candles, meta)`
|
|
29
|
-
| `loadCandlesFromCache(symbol, interval, period, outDir)` | Read normalized candles from the local cache
|
|
30
|
-
| `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 |
|
|
31
34
|
|
|
32
35
|
## Reporting
|
|
33
36
|
|
|
34
|
-
| Export
|
|
35
|
-
|
|
|
36
|
-
| `renderHtmlReport(options)`
|
|
37
|
-
| `exportHtmlReport(options)`
|
|
38
|
-
| `exportTradesCsv(trades, options)` | Write a CSV ledger of trades or positions
|
|
39
|
-
| `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 |
|
|
40
43
|
| `exportBacktestArtifacts(options)` | Write HTML, CSV, and metrics JSON together |
|
|
41
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
|
+
|
|
42
100
|
## Indicators and utilities
|
|
43
101
|
|
|
44
102
|
### Indicators
|
|
@@ -67,4 +125,9 @@ If you are learning the package, start with [backtest-engine.md](backtest-engine
|
|
|
67
125
|
|
|
68
126
|
## Types
|
|
69
127
|
|
|
70
|
-
The package ships declarations in
|
|
128
|
+
The package ships declarations in:
|
|
129
|
+
|
|
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
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
# Backtest engine
|
|
2
2
|
|
|
3
|
+
<small>[Back to main page](README.md)</small>
|
|
4
|
+
|
|
3
5
|
This page covers the simulation layer:
|
|
4
6
|
|
|
5
7
|
- `backtest(options)`
|
|
8
|
+
- `backtestTicks(options)`
|
|
6
9
|
- `backtestPortfolio(options)`
|
|
7
10
|
- `walkForwardOptimize(options)`
|
|
8
11
|
- `buildMetrics(input)`
|
|
@@ -11,14 +14,17 @@ This page covers the simulation layer:
|
|
|
11
14
|
|
|
12
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.
|
|
13
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
|
+
|
|
14
19
|
## Choose the right function
|
|
15
20
|
|
|
16
|
-
| Use case
|
|
17
|
-
|
|
|
18
|
-
| One strategy on one candle series
|
|
19
|
-
|
|
|
20
|
-
|
|
|
21
|
-
|
|
|
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()` |
|
|
26
|
+
| Rolling or anchored train/test validation | `walkForwardOptimize()` |
|
|
27
|
+
| Recompute metrics from realized trades | `buildMetrics()` |
|
|
22
28
|
|
|
23
29
|
## Candle input
|
|
24
30
|
|
|
@@ -71,16 +77,16 @@ const result = backtest({
|
|
|
71
77
|
|
|
72
78
|
### Core options
|
|
73
79
|
|
|
74
|
-
| Option
|
|
75
|
-
|
|
|
76
|
-
| `symbol`, `interval`, `range`
|
|
77
|
-
| `equity`
|
|
78
|
-
| `riskPct` or `riskFraction`
|
|
79
|
-
| `warmupBars`
|
|
80
|
-
| `flattenAtClose`
|
|
81
|
-
| `collectEqSeries`, `collectReplay` | Builds extra output for charts and exports
|
|
82
|
-
| `strict`
|
|
83
|
-
| `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 |
|
|
84
90
|
|
|
85
91
|
If you are starting from scratch, the most useful options to set explicitly are:
|
|
86
92
|
|
|
@@ -92,38 +98,31 @@ If you are starting from scratch, the most useful options to set explicitly are:
|
|
|
92
98
|
|
|
93
99
|
### Signal contract
|
|
94
100
|
|
|
95
|
-
The signal function receives:
|
|
101
|
+
The signal function receives a context object with these fields:
|
|
96
102
|
|
|
103
|
+
<!-- prettier-ignore -->
|
|
97
104
|
```js
|
|
98
|
-
{
|
|
99
|
-
candles,
|
|
100
|
-
index,
|
|
101
|
-
bar,
|
|
102
|
-
equity,
|
|
103
|
-
openPosition,
|
|
104
|
-
pendingOrder
|
|
105
|
-
}
|
|
105
|
+
{ candles, index, bar, equity, openPosition, pendingOrder }
|
|
106
106
|
```
|
|
107
107
|
|
|
108
108
|
Return `null` for no trade, or a signal object:
|
|
109
109
|
|
|
110
110
|
```js
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
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 }
|
|
117
116
|
```
|
|
118
117
|
|
|
119
118
|
### Signal conveniences
|
|
120
119
|
|
|
121
|
-
| Field
|
|
122
|
-
|
|
|
123
|
-
| `side`
|
|
124
|
-
| `entry`
|
|
125
|
-
| `takeProfit`
|
|
126
|
-
| `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 |
|
|
127
126
|
| `riskPct` or `riskFraction` | Overrides the global risk setting for that trade |
|
|
128
127
|
|
|
129
128
|
Practical rule: return the smallest signal object that expresses the trade clearly. In many strategies that is just `side`, `stop`, and `rr`.
|
|
@@ -202,19 +201,11 @@ Recommended order of adoption:
|
|
|
202
201
|
|
|
203
202
|
## Result shape
|
|
204
203
|
|
|
205
|
-
`backtest()` returns:
|
|
204
|
+
`backtest()` returns an object with these fields:
|
|
206
205
|
|
|
206
|
+
<!-- prettier-ignore -->
|
|
207
207
|
```js
|
|
208
|
-
{
|
|
209
|
-
symbol,
|
|
210
|
-
interval,
|
|
211
|
-
range,
|
|
212
|
-
trades,
|
|
213
|
-
positions,
|
|
214
|
-
metrics,
|
|
215
|
-
eqSeries,
|
|
216
|
-
replay
|
|
217
|
-
}
|
|
208
|
+
{ symbol, interval, range, trades, positions, openPositions, metrics, eqSeries, replay }
|
|
218
209
|
```
|
|
219
210
|
|
|
220
211
|
### `trades`
|
|
@@ -262,9 +253,7 @@ Useful first checks after any run:
|
|
|
262
253
|
Realized equity points:
|
|
263
254
|
|
|
264
255
|
```js
|
|
265
|
-
[
|
|
266
|
-
{ time, timestamp, equity }
|
|
267
|
-
]
|
|
256
|
+
[{ time, timestamp, equity }];
|
|
268
257
|
```
|
|
269
258
|
|
|
270
259
|
`time` and `timestamp` contain the same Unix-millisecond value.
|
|
@@ -298,25 +287,47 @@ const result = backtestPortfolio({
|
|
|
298
287
|
|
|
299
288
|
### How it works
|
|
300
289
|
|
|
301
|
-
-
|
|
302
|
-
-
|
|
303
|
-
-
|
|
290
|
+
- systems share one live capital pool
|
|
291
|
+
- `weight` or `allocation: "equal" | "weight"` defines the default per-system cap, not a pre-funded sleeve
|
|
292
|
+
- fills lock capital immediately, later fills size against remaining available capital
|
|
293
|
+
- `eqSeries` points include `lockedCapital` and `availableCapital`
|
|
294
|
+
- `maxDailyLossPct` can halt all systems for the rest of the day once breached
|
|
304
295
|
|
|
305
296
|
### What it is not
|
|
306
297
|
|
|
307
298
|
- a cross-margin broker simulator
|
|
308
|
-
- a
|
|
309
|
-
- a
|
|
299
|
+
- a prime-broker margin model
|
|
300
|
+
- a full portfolio optimizer
|
|
310
301
|
|
|
311
|
-
|
|
302
|
+
This mode now does enforce shared capital and cross-system sizing, but it still uses the library's research-oriented execution assumptions rather than full broker accounting.
|
|
303
|
+
|
|
304
|
+
## `backtestTicks(options)`
|
|
305
|
+
|
|
306
|
+
Use tick mode when you want event-driven fills while keeping the same result shape as `backtest()`.
|
|
307
|
+
|
|
308
|
+
```js
|
|
309
|
+
const result = backtestTicks({
|
|
310
|
+
ticks,
|
|
311
|
+
queueFillProbability: 0.5,
|
|
312
|
+
signal,
|
|
313
|
+
});
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### How it works
|
|
317
|
+
|
|
318
|
+
- market entries fill on the next tick
|
|
319
|
+
- limit orders can fill at the touch based on `queueFillProbability`
|
|
320
|
+
- stop exits fill at the stop and use the normal stop slippage model from `costs.slippageByKind.stop`
|
|
321
|
+
- results still come back as `trades`, `positions`, `metrics`, `eqSeries`, and `replay`
|
|
312
322
|
|
|
313
323
|
## `walkForwardOptimize(options)`
|
|
314
324
|
|
|
315
|
-
Use walk-forward mode when one in-sample backtest is not enough and you want rolling train/test validation.
|
|
325
|
+
Use walk-forward mode when one in-sample backtest is not enough and you want rolling or anchored train/test validation.
|
|
316
326
|
|
|
317
327
|
```js
|
|
318
328
|
const wf = walkForwardOptimize({
|
|
319
329
|
candles,
|
|
330
|
+
mode: "anchored",
|
|
320
331
|
trainBars: 180,
|
|
321
332
|
testBars: 60,
|
|
322
333
|
stepBars: 60,
|
|
@@ -336,13 +347,14 @@ const wf = walkForwardOptimize({
|
|
|
336
347
|
1. Evaluate every parameter set on the training slice
|
|
337
348
|
2. Pick the best one by `scoreBy`
|
|
338
349
|
3. Run that parameter set on the next test slice
|
|
339
|
-
4. Repeat for each window
|
|
350
|
+
4. Repeat for each window using either rolling or anchored training windows
|
|
340
351
|
|
|
341
352
|
### Return value
|
|
342
353
|
|
|
343
354
|
- `windows`: per-window summaries and chosen parameters
|
|
344
355
|
- `trades`, `positions`, `metrics`, `eqSeries`
|
|
345
|
-
- `bestParams`: chosen parameters for each window
|
|
356
|
+
- `bestParams`: chosen parameters for each window plus a stability summary
|
|
357
|
+
- `bestParamsSummary`: adjacent repeat rate, dominant winner, and winner leaderboard
|
|
346
358
|
|
|
347
359
|
In practice, the per-window output matters more than the aggregate headline. If the winning parameters swing wildly from one window to the next, treat that as a real signal.
|
|
348
360
|
|
|
@@ -361,3 +373,5 @@ Most users do not need this directly. Use it when:
|
|
|
361
373
|
- leaving costs at zero and overestimating edge
|
|
362
374
|
- trusting one backtest without out-of-sample validation
|
|
363
375
|
- debugging a strategy with `strict: false` when lookahead is possible
|
|
376
|
+
|
|
377
|
+
<small>[Back to main page](README.md)</small>
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# Data, reporting, and CLI
|
|
2
2
|
|
|
3
|
+
<small>[Back to main page](README.md)</small>
|
|
4
|
+
|
|
3
5
|
This page covers the parts of the package around the core engine:
|
|
4
6
|
|
|
5
7
|
- historical data loading
|
|
6
8
|
- local cache helpers
|
|
7
9
|
- export helpers
|
|
8
|
-
- command-line usage
|
|
10
|
+
- command-line usage for backtest and live workflows
|
|
9
11
|
|
|
10
12
|
## Overview
|
|
11
13
|
|
|
@@ -13,13 +15,13 @@ If you are not bringing your own candles yet, start here.
|
|
|
13
15
|
|
|
14
16
|
## Choose the right entry point
|
|
15
17
|
|
|
16
|
-
| Use case
|
|
17
|
-
|
|
|
18
|
+
| Use case | Function |
|
|
19
|
+
| --------------------------------------------------------- | ------------------------ |
|
|
18
20
|
| Load data without caring about the source-specific helper | `getHistoricalCandles()` |
|
|
19
|
-
| Fetch directly from Yahoo
|
|
20
|
-
| Load a local CSV file
|
|
21
|
-
| Reuse saved normalized data
|
|
22
|
-
| 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 |
|
|
23
25
|
|
|
24
26
|
## Historical data
|
|
25
27
|
|
|
@@ -49,15 +51,15 @@ If you are writing application code, prefer `getHistoricalCandles()` over callin
|
|
|
49
51
|
|
|
50
52
|
### Yahoo options
|
|
51
53
|
|
|
52
|
-
| Option
|
|
53
|
-
|
|
|
54
|
-
| `symbol`
|
|
55
|
-
| `interval`
|
|
56
|
-
| `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` |
|
|
57
59
|
| `includePrePost` | Includes premarket and postmarket data when supported |
|
|
58
|
-
| `cache`
|
|
59
|
-
| `refresh`
|
|
60
|
-
| `cacheDir`
|
|
60
|
+
| `cache` | Reuses saved normalized data |
|
|
61
|
+
| `refresh` | Forces a fresh download even if cache exists |
|
|
62
|
+
| `cacheDir` | Overrides the default cache directory |
|
|
61
63
|
|
|
62
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.
|
|
63
65
|
|
|
@@ -148,12 +150,9 @@ The main bundle export. By default it writes:
|
|
|
148
150
|
|
|
149
151
|
Return value:
|
|
150
152
|
|
|
153
|
+
<!-- prettier-ignore -->
|
|
151
154
|
```js
|
|
152
|
-
{
|
|
153
|
-
csv,
|
|
154
|
-
html,
|
|
155
|
-
metrics
|
|
156
|
-
}
|
|
155
|
+
{ csv, html, metrics }
|
|
157
156
|
```
|
|
158
157
|
|
|
159
158
|
If you only need one output type, call the narrower helper directly.
|
|
@@ -183,13 +182,16 @@ The CLI is best for quick iteration, smoke tests, and trying the package before
|
|
|
183
182
|
|
|
184
183
|
## Commands
|
|
185
184
|
|
|
186
|
-
| Command
|
|
187
|
-
|
|
|
188
|
-
| `tradelab backtest`
|
|
189
|
-
| `tradelab portfolio`
|
|
190
|
-
| `tradelab walk-forward` | Run rolling validation with
|
|
191
|
-
| `tradelab
|
|
192
|
-
| `tradelab
|
|
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 |
|
|
189
|
+
| `tradelab walk-forward` | Run rolling or anchored validation with built-in or local strategy search |
|
|
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 |
|
|
193
195
|
|
|
194
196
|
### Backtest
|
|
195
197
|
|
|
@@ -231,10 +233,36 @@ tradelab walk-forward \
|
|
|
231
233
|
--interval 1d \
|
|
232
234
|
--period 2y \
|
|
233
235
|
--trainBars 180 \
|
|
234
|
-
--testBars 60
|
|
236
|
+
--testBars 60 \
|
|
237
|
+
--mode anchored
|
|
235
238
|
```
|
|
236
239
|
|
|
237
|
-
The CLI walk-forward command
|
|
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`.
|
|
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
|
+
```
|
|
238
266
|
|
|
239
267
|
### Cache utilities
|
|
240
268
|
|
|
@@ -245,10 +273,12 @@ tradelab import-csv --csvPath ./data/spy.csv --symbol SPY --interval 1d
|
|
|
245
273
|
|
|
246
274
|
## Troubleshooting
|
|
247
275
|
|
|
248
|
-
| Problem
|
|
249
|
-
|
|
|
250
|
-
| Yahoo request errors
|
|
251
|
-
| Unexpected trade count | `warmupBars`, `flattenAtClose`, and signal frequency
|
|
252
|
-
| Empty result
|
|
253
|
-
| Confusing CSV import
|
|
254
|
-
| 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 |
|
|
283
|
+
|
|
284
|
+
<small>[Back to main page](README.md)</small>
|