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.
Files changed (54) hide show
  1. package/README.md +121 -52
  2. package/bin/tradelab.js +340 -49
  3. package/dist/cjs/data.cjs +210 -155
  4. package/dist/cjs/index.cjs +1782 -274
  5. package/dist/cjs/live.cjs +3350 -0
  6. package/docs/README.md +26 -9
  7. package/docs/api-reference.md +89 -26
  8. package/docs/backtest-engine.md +74 -60
  9. package/docs/data-reporting-cli.md +66 -36
  10. package/docs/examples.md +275 -0
  11. package/docs/live-trading.md +186 -0
  12. package/examples/yahooEmaCross.js +1 -6
  13. package/package.json +18 -3
  14. package/src/data/csv.js +24 -14
  15. package/src/data/index.js +1 -5
  16. package/src/data/yahoo.js +6 -19
  17. package/src/engine/backtest.js +137 -144
  18. package/src/engine/backtestTicks.js +481 -0
  19. package/src/engine/barSystemRunner.js +1027 -0
  20. package/src/engine/execution.js +11 -39
  21. package/src/engine/portfolio.js +237 -66
  22. package/src/engine/walkForward.js +132 -13
  23. package/src/index.js +3 -11
  24. package/src/live/broker/alpaca.js +254 -0
  25. package/src/live/broker/binance.js +351 -0
  26. package/src/live/broker/coinbase.js +339 -0
  27. package/src/live/broker/interactiveBrokers.js +123 -0
  28. package/src/live/broker/interface.js +74 -0
  29. package/src/live/clock.js +56 -0
  30. package/src/live/engine/candleAggregator.js +154 -0
  31. package/src/live/engine/liveEngine.js +694 -0
  32. package/src/live/engine/paperEngine.js +453 -0
  33. package/src/live/engine/riskManager.js +185 -0
  34. package/src/live/engine/stateManager.js +112 -0
  35. package/src/live/events.js +48 -0
  36. package/src/live/feed/brokerFeed.js +35 -0
  37. package/src/live/feed/interface.js +28 -0
  38. package/src/live/feed/pollingFeed.js +105 -0
  39. package/src/live/index.js +27 -0
  40. package/src/live/logger.js +82 -0
  41. package/src/live/orchestrator.js +133 -0
  42. package/src/live/storage/interface.js +36 -0
  43. package/src/live/storage/jsonFileStorage.js +112 -0
  44. package/src/metrics/buildMetrics.js +103 -100
  45. package/src/reporting/exportBacktestArtifacts.js +1 -4
  46. package/src/reporting/exportTradesCsv.js +2 -7
  47. package/src/reporting/renderHtmlReport.js +8 -13
  48. package/src/utils/indicators.js +1 -2
  49. package/src/utils/positionSizing.js +16 -2
  50. package/src/utils/time.js +4 -12
  51. package/templates/report.html +23 -9
  52. package/templates/report.js +83 -69
  53. package/types/index.d.ts +98 -4
  54. 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 | Start here |
12
- | --- | --- |
13
- | Run one strategy on one dataset | [Backtest engine](backtest-engine.md) |
14
- | Load Yahoo or CSV data | [Data, reporting, and CLI](data-reporting-cli.md) |
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 | [Backtest engine](backtest-engine.md) |
17
- | Run walk-forward validation | [Backtest engine](backtest-engine.md) |
18
- | Check the exact public exports | [API reference](api-reference.md) |
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>
@@ -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 | Summary |
10
- | --- | --- |
11
- | `backtest(options)` | Run one strategy on one candle series |
12
- | `backtestPortfolio(options)` | Run multiple systems and merge the result |
13
- | `walkForwardOptimize(options)` | Run rolling train/test validation |
14
- | `buildMetrics(input)` | Compute metrics from realized trades and equity data |
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 | Summary |
19
- | --- | --- |
20
- | `getHistoricalCandles(options)` | Load candles from Yahoo or CSV |
21
- | `backtestHistorical({ data, backtestOptions })` | Load candles and immediately run `backtest()` |
22
- | `fetchHistorical(symbol, interval, period, options)` | Call the Yahoo layer directly |
23
- | `fetchLatestCandle(symbol, interval, options)` | Fetch the latest Yahoo candle |
24
- | `loadCandlesFromCSV(filePath, options)` | Parse and normalize a CSV file |
25
- | `normalizeCandles(candles)` | Normalize candle field names and sort/dedupe |
26
- | `mergeCandles(...arrays)` | Merge multiple candle arrays |
27
- | `candleStats(candles)` | Return summary stats for a candle array |
28
- | `saveCandlesToCache(candles, meta)` | Write normalized candles to the local cache |
29
- | `loadCandlesFromCache(symbol, interval, period, outDir)` | Read normalized candles from the local cache |
30
- | `cachedCandlesPath(symbol, interval, period, outDir)` | Return the expected cache path |
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 | Summary |
35
- | --- | --- |
36
- | `renderHtmlReport(options)` | Return the HTML report as a string |
37
- | `exportHtmlReport(options)` | Write the HTML report to disk |
38
- | `exportTradesCsv(trades, options)` | Write a CSV ledger of trades or positions |
39
- | `exportMetricsJSON(options)` | Write machine-readable metrics JSON |
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 [../types/index.d.ts](../types/index.d.ts). Use that file when you need the exact option and result contracts in TypeScript or editor IntelliSense.
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>
@@ -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 | Function |
17
- | --- | --- |
18
- | One strategy on one candle series | `backtest()` |
19
- | Multiple symbols with one combined result | `backtestPortfolio()` |
20
- | Rolling train/test validation | `walkForwardOptimize()` |
21
- | Recompute metrics from realized trades | `buildMetrics()` |
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 | Purpose |
75
- | --- | --- |
76
- | `symbol`, `interval`, `range` | Labels carried into results and exports |
77
- | `equity` | Starting equity, default `10000` |
78
- | `riskPct` or `riskFraction` | Default risk per trade when `qty` is not provided |
79
- | `warmupBars` | Bars skipped before signal evaluation starts |
80
- | `flattenAtClose` | Forces end-of-day exit when enabled |
81
- | `collectEqSeries`, `collectReplay` | Builds extra output for charts and exports |
82
- | `strict` | Throws on direct lookahead access such as `candles[index + 1]` |
83
- | `costs` | Slippage, spread, and commission model |
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
- side: "long" | "short",
113
- entry: 101.25,
114
- stop: 99.75,
115
- takeProfit: 104.25
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 | Behavior |
122
- | --- | --- |
123
- | `side` | Accepts `long`, `short`, `buy`, or `sell` |
124
- | `entry` | Defaults to the current close if omitted |
125
- | `takeProfit` | Can be derived from `rr` or `_rr` |
126
- | `qty` or `size` | Overrides risk-based sizing |
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
- - capital is allocated up front by weight
302
- - each system runs through the normal single-symbol engine
303
- - the portfolio result merges trades, positions, replay events, and equity series
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 portfolio-level fill arbiter
309
- - a shared capital-locking engine
299
+ - a prime-broker margin model
300
+ - a full portfolio optimizer
310
301
 
311
- If you need shared real-time portfolio constraints, this is not that tool yet.
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 | Function |
17
- | --- | --- |
18
+ | Use case | Function |
19
+ | --------------------------------------------------------- | ------------------------ |
18
20
  | Load data without caring about the source-specific helper | `getHistoricalCandles()` |
19
- | Fetch directly from Yahoo | `fetchHistorical()` |
20
- | Load a local CSV file | `loadCandlesFromCSV()` |
21
- | Reuse saved normalized data | `loadCandlesFromCache()` |
22
- | Try the package from a terminal first | `tradelab` CLI |
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 | Purpose |
53
- | --- | --- |
54
- | `symbol` | Ticker or Yahoo symbol |
55
- | `interval` | Candle interval such as `1d` or `5m` |
56
- | `period` | Lookback period such as `6mo` or `1y` |
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` | Reuses saved normalized data |
59
- | `refresh` | Forces a fresh download even if cache exists |
60
- | `cacheDir` | Overrides the default cache directory |
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 | Purpose |
187
- | --- | --- |
188
- | `tradelab backtest` | Run a single backtest from Yahoo or CSV |
189
- | `tradelab portfolio` | Run a simple multi-file portfolio backtest |
190
- | `tradelab walk-forward` | Run rolling validation with the built-in search |
191
- | `tradelab prefetch` | Download and cache Yahoo data |
192
- | `tradelab import-csv` | Normalize and cache a CSV file |
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 currently uses the built-in `ema-cross` parameter search.
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 | Check first |
249
- | --- | --- |
250
- | Yahoo request errors | enable cache, retry later, or fall back to CSV |
251
- | Unexpected trade count | `warmupBars`, `flattenAtClose`, and signal frequency |
252
- | Empty result | candle order, signal logic, and stop/target validity |
253
- | Confusing CSV import | inspect normalized bars from `loadCandlesFromCSV()` before backtesting |
254
- | Export confusion | use metrics JSON first if you need programmatic output |
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>