tradelab 1.0.1 → 1.2.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 (66) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/README.md +188 -328
  3. package/bin/tradelab-mcp.js +7 -0
  4. package/bin/tradelab.js +29 -0
  5. package/dist/cjs/data.cjs +149 -26
  6. package/dist/cjs/index.cjs +1917 -1005
  7. package/dist/cjs/live.cjs +536 -25
  8. package/dist/cjs/ta.cjs +339 -0
  9. package/docs/README.md +32 -66
  10. package/docs/api-reference.md +283 -112
  11. package/docs/backtest-engine.md +210 -252
  12. package/docs/data-reporting-cli.md +114 -156
  13. package/docs/examples.md +6 -6
  14. package/docs/live-trading.md +263 -92
  15. package/docs/mcp.md +285 -0
  16. package/docs/research.md +157 -0
  17. package/examples/liveDashboard.js +33 -0
  18. package/examples/llmSignal.js +33 -0
  19. package/examples/mcpLiveTrading.js +77 -0
  20. package/examples/optimize.js +25 -0
  21. package/package.json +26 -4
  22. package/src/engine/asyncSignal.js +28 -0
  23. package/src/engine/backtest.js +13 -1
  24. package/src/engine/backtestAsync.js +27 -0
  25. package/src/engine/backtestTicks.js +13 -2
  26. package/src/engine/barSystemRunner.js +96 -41
  27. package/src/engine/execution.js +39 -0
  28. package/src/engine/grid.js +15 -0
  29. package/src/engine/llmSignal.js +84 -0
  30. package/src/engine/optimize.js +110 -0
  31. package/src/engine/optimizeWorker.js +67 -0
  32. package/src/engine/portfolio.js +4 -1
  33. package/src/engine/walkForward.js +1 -0
  34. package/src/index.js +9 -0
  35. package/src/live/dashboard/server.js +179 -0
  36. package/src/live/engine/liveEngine.js +2 -2
  37. package/src/live/engine/paperEngine.js +5 -0
  38. package/src/live/index.js +3 -0
  39. package/src/live/session.js +402 -0
  40. package/src/mcp/liveTools.js +179 -0
  41. package/src/mcp/schemas.js +167 -0
  42. package/src/mcp/server.js +35 -0
  43. package/src/mcp/tools.js +265 -0
  44. package/src/metrics/annualize.js +32 -0
  45. package/src/metrics/benchmark.js +55 -0
  46. package/src/metrics/buildMetrics.js +34 -13
  47. package/src/metrics/finite.js +17 -0
  48. package/src/research/combinations.js +18 -0
  49. package/src/research/cpcv.js +47 -0
  50. package/src/research/deflatedSharpe.js +35 -0
  51. package/src/research/index.js +6 -0
  52. package/src/research/monteCarlo.js +88 -0
  53. package/src/research/pbo.js +69 -0
  54. package/src/research/stats.js +78 -0
  55. package/src/strategies/builtins.js +96 -0
  56. package/src/strategies/index.js +30 -0
  57. package/src/ta/channels.js +67 -0
  58. package/src/ta/index.js +16 -0
  59. package/src/ta/oscillators.js +70 -0
  60. package/src/ta/trend.js +78 -0
  61. package/src/utils/random.js +33 -0
  62. package/templates/dashboard.html +661 -0
  63. package/types/index.d.ts +179 -0
  64. package/types/live.d.ts +114 -0
  65. package/types/mcp.d.ts +17 -0
  66. package/types/ta.d.ts +45 -0
@@ -1,133 +1,304 @@
1
1
  # API reference
2
2
 
3
- <small>[Back to main page](README.md)</small>
3
+ <small>[Back to docs](README.md)</small>
4
4
 
5
- This page is the compact index of public exports.
5
+ This is the import index for the public package surface. For explanations and longer examples, start with the guides linked from [docs/README.md](README.md).
6
6
 
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.
7
+ ## Entry Points
8
8
 
9
- ## Backtesting
9
+ | Import path | Use it for |
10
+ | --------------- | ---------------------------------------------- |
11
+ | `tradelab` | Backtests, data, reports, research, indicators |
12
+ | `tradelab/data` | Data helpers only |
13
+ | `tradelab/live` | Paper/live engines, broker adapters, dashboard |
14
+ | `tradelab/ta` | Technical indicators |
15
+ | `tradelab/mcp` | Programmatic MCP server creation |
10
16
 
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 |
17
+ CLI binaries:
18
18
 
19
- ## Data
19
+ | Binary | Use it for |
20
+ | -------------- | ------------------------------- |
21
+ | `tradelab` | Backtests, reports, live, paper |
22
+ | `tradelab-mcp` | stdio MCP server |
20
23
 
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 |
24
+ ## Main Module: `tradelab`
34
25
 
35
- ## Reporting
26
+ ```js
27
+ import { backtest, getHistoricalCandles, ema } from "tradelab";
28
+ ```
29
+
30
+ ### Backtesting
31
+
32
+ | Export | Summary |
33
+ | ------------------------------ | ------------------------------------------------------------------------------- |
34
+ | `backtest(options)` | Run one synchronous signal over one candle series |
35
+ | `backtestAsync(options)` | Run one async signal over one candle series |
36
+ | `backtestTicks(options)` | Run one signal on tick-like data with tick-level fill handling |
37
+ | `backtestPortfolio(options)` | Run multiple systems through shared capital |
38
+ | `walkForwardOptimize(options)` | Run rolling or anchored train/test validation |
39
+ | `grid(spec)` | Expand scalar/array parameter specs into parameter sets |
40
+ | `optimize(options)` | Run parameter sets in worker threads with a strategy module |
41
+ | `LlmSignal` | Async signal wrapper with timeout, one-decision-per-bar cache, and decision log |
42
+
43
+ `backtest()` returns:
44
+
45
+ | Field | Meaning |
46
+ | --------------- | ---------------------------------------------- |
47
+ | `trades` | Realized legs, including partial exits |
48
+ | `positions` | Completed positions |
49
+ | `openPositions` | Positions still open at the end of the data |
50
+ | `metrics` | Aggregate performance statistics |
51
+ | `eqSeries` | Realized equity points for charts and exports |
52
+ | `replay` | Lightweight chart frames and entry/exit events |
53
+
54
+ ### Metrics
55
+
56
+ | Export | Summary |
57
+ | ----------------------- | ----------------------------------------------------- |
58
+ | `buildMetrics(input)` | Compute aggregate metrics from trades/equity |
59
+ | `benchmarkStats(input)` | Compute benchmark comparison stats |
60
+ | `periodsPerYear(value)` | Convert interval/bar spacing to annualization periods |
61
+ | `clampFinite(value)` | Clamp non-finite numbers for report output |
62
+ | `BIG_NUMBER` | Large finite sentinel used by metrics |
63
+
64
+ ### Strategy Registry
65
+
66
+ | Export | Summary |
67
+ | ----------------------------- | ------------------------------------------- |
68
+ | `listStrategies()` | List built-in and registered strategy names |
69
+ | `getStrategy(name)` | Get a registered strategy factory |
70
+ | `registerStrategy(name, def)` | Register a named strategy at runtime |
71
+
72
+ Strategy definitions use:
73
+
74
+ ```js
75
+ registerStrategy("my-strategy", {
76
+ description: "Readable description",
77
+ params: {
78
+ lookback: { type: "number", default: 20 },
79
+ },
80
+ factory(params) {
81
+ return (context) => null;
82
+ },
83
+ });
84
+ ```
85
+
86
+ ### Data
87
+
88
+ | Export | Summary |
89
+ | -------------------------------------------------------- | ------------------------------------------ |
90
+ | `getHistoricalCandles(options)` | Load candles from Yahoo or CSV |
91
+ | `backtestHistorical({ data, backtestOptions })` | Load data and immediately run `backtest()` |
92
+ | `fetchHistorical(symbol, interval, period, options)` | Fetch Yahoo candles directly |
93
+ | `fetchLatestCandle(symbol, interval, options)` | Fetch the latest Yahoo candle |
94
+ | `loadCandlesFromCSV(filePath, options)` | Parse and normalize a CSV file |
95
+ | `normalizeCandles(candles)` | Normalize field names, sort, and dedupe |
96
+ | `mergeCandles(...arrays)` | Merge candle arrays, sort, and dedupe |
97
+ | `candleStats(candles)` | Summarize count, range, duration, interval |
98
+ | `saveCandlesToCache(candles, meta)` | Write candles to the local cache |
99
+ | `loadCandlesFromCache(symbol, interval, period, outDir)` | Read candles from the local cache |
100
+ | `cachedCandlesPath(symbol, interval, period, outDir)` | Return the expected cache path |
101
+
102
+ ### Reporting
103
+
104
+ | Export | Summary |
105
+ | ---------------------------------- | -------------------------------------------- |
106
+ | `renderHtmlReport(options)` | Return the HTML report as a string |
107
+ | `exportHtmlReport(options)` | Write an HTML report |
108
+ | `exportTradesCsv(trades, options)` | Write a trade or position CSV ledger |
109
+ | `exportMetricsJSON(options)` | Write machine-readable metrics JSON |
110
+ | `exportBacktestArtifacts(options)` | Write HTML, CSV, and JSON artifacts together |
111
+
112
+ ### Research
113
+
114
+ ```js
115
+ import { research } from "tradelab";
116
+ ```
117
+
118
+ | Export | Summary |
119
+ | ------------------------------------------------------------ | ---------------------------------------------------------- |
120
+ | `research.monteCarlo(options)` | Bootstrap trade PnLs into alternate equity paths |
121
+ | `research.deflatedSharpe(options)` | Penalize Sharpe for sample size, non-normality, and trials |
122
+ | `research.sweepHaircut(options)` | Estimate the Sharpe hurdle from many trials |
123
+ | `research.probabilityOfBacktestOverfitting(matrix, options)` | Estimate PBO from a performance matrix |
124
+ | `research.combinatorialPurgedSplits(options)` | Build purged train/test splits |
125
+ | `research.combinations(n, k)` | Generate combinations |
126
+ | `research.normalCdf(x)` | Standard normal CDF |
127
+ | `research.normalPpf(p)` | Standard normal inverse CDF |
128
+ | `research.moments(values)` | Mean, standard deviation, skew, kurtosis |
129
+
130
+ ### Indicators And Helpers
131
+
132
+ | Export | Summary |
133
+ | ------------------------------------- | -------------------------------------------- |
134
+ | `ema(values, period)` | Exponential moving average |
135
+ | `atr(bars, period)` | Average True Range |
136
+ | `swingHigh(bars, index, left, right)` | Detect a swing high at an index |
137
+ | `swingLow(bars, index, left, right)` | Detect a swing low at an index |
138
+ | `detectFVG(bars, index)` | Detect a Fair Value Gap |
139
+ | `lastSwing(bars, index, direction)` | Find the last swing in a direction |
140
+ | `structureState(bars, index)` | Return latest swing high/low state |
141
+ | `bpsOf(price, bps)` | Convert basis points to price distance |
142
+ | `pct(a, b)` | Percent difference helper |
143
+ | `calculatePositionSize(input)` | Risk-based quantity calculation |
144
+ | `offsetET(timeMs)` | Eastern Time offset helper |
145
+ | `minutesET(timeMs)` | Minutes since midnight Eastern Time |
146
+ | `isSession(timeMs, session)` | Check known trading sessions |
147
+ | `parseWindowsCSV(csv)` | Parse windows like `09:30-11:30,13:00-15:30` |
148
+ | `inWindowsET(timeMs, windows)` | Check whether a timestamp is inside windows |
149
+
150
+ ## Data Module: `tradelab/data`
151
+
152
+ ```js
153
+ import { getHistoricalCandles, loadCandlesFromCSV } from "tradelab/data";
154
+ ```
36
155
 
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
- | `exportBacktestArtifacts(options)` | Write HTML, CSV, and metrics JSON together |
156
+ This entry point exports the data helpers from the main module:
44
157
 
45
- ## Live module (`tradelab/live`)
158
+ - `getHistoricalCandles`
159
+ - `backtestHistorical`
160
+ - `fetchHistorical`
161
+ - `fetchLatestCandle`
162
+ - `loadCandlesFromCSV`
163
+ - `normalizeCandles`
164
+ - `mergeCandles`
165
+ - `candleStats`
166
+ - `saveCandlesToCache`
167
+ - `loadCandlesFromCache`
168
+ - `cachedCandlesPath`
46
169
 
47
- Live exports are under a separate entrypoint:
170
+ ## Live Module: `tradelab/live`
48
171
 
49
172
  ```js
50
- import { LiveEngine, PaperEngine } from "tradelab/live";
173
+ import { LiveEngine, PaperEngine, createDashboardServer } from "tradelab/live";
51
174
  ```
52
175
 
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
-
100
- ## Indicators and utilities
101
-
102
- ### Indicators
103
-
104
- - `ema(values, period)`
105
- - `atr(bars, period)`
106
- - `swingHigh(bars, index, left, right)`
107
- - `swingLow(bars, index, left, right)`
108
- - `detectFVG(bars, index)`
109
- - `lastSwing(bars, index, direction)`
110
- - `structureState(bars, index)`
111
- - `bpsOf(price, bps)`
112
- - `pct(a, b)`
113
-
114
- ### Position sizing
115
-
116
- - `calculatePositionSize(input)`
117
-
118
- ### Time helpers
119
-
120
- - `offsetET(timeMs)`
121
- - `minutesET(timeMs)`
122
- - `isSession(timeMs, session)`
123
- - `parseWindowsCSV(csv)`
124
- - `inWindowsET(timeMs, windows)`
176
+ ### Engines
177
+
178
+ | Export | Summary |
179
+ | --------------------------------- | -------------------------------------------- |
180
+ | `LiveEngine` | Single-system live or paper execution engine |
181
+ | `createLiveEngine(options)` | Factory for `LiveEngine` |
182
+ | `LiveOrchestrator` | Multi-system engine sharing one broker |
183
+ | `createLiveOrchestrator(options)` | Factory for `LiveOrchestrator` |
184
+ | `PaperEngine` | In-process broker simulator |
185
+ | `createPaperEngine(options)` | Factory for `PaperEngine` |
186
+
187
+ ### Broker Adapters
188
+
189
+ | Export | Summary |
190
+ | ------------------------------------------------------------- | --------------------------------------- |
191
+ | `BrokerAdapter` | Base broker interface |
192
+ | `AlpacaBroker` / `createAlpacaBroker` | Alpaca adapter and factory |
193
+ | `BinanceBroker` / `createBinanceBroker` | Binance adapter and factory |
194
+ | `CoinbaseBroker` / `createCoinbaseBroker` | Coinbase adapter and factory |
195
+ | `InteractiveBrokersBroker` / `createInteractiveBrokersBroker` | Interactive Brokers adapter and factory |
196
+
197
+ ### Feeds
198
+
199
+ | Export | Summary |
200
+ | --------------------------------- | ------------------------------------------- |
201
+ | `FeedProvider` | Base feed interface |
202
+ | `BrokerFeed` | Feed backed by broker subscriptions |
203
+ | `createBrokerFeed(options)` | Factory for `BrokerFeed` |
204
+ | `PollingFeed` | Polling feed backed by broker history calls |
205
+ | `createPollingFeed(options)` | Factory for `PollingFeed` |
206
+ | `CandleAggregator` | Aggregate ticks/polled bars into candles |
207
+ | `createCandleAggregator(options)` | Factory for `CandleAggregator` |
208
+
209
+ ### State, Risk, Events
210
+
211
+ | Export | Summary |
212
+ | -------------------------------- | ------------------------------------------------- |
213
+ | `StorageProvider` | Base persistence interface |
214
+ | `JsonFileStorage` | JSON/JSONL file storage |
215
+ | `createJsonFileStorage(options)` | Factory for `JsonFileStorage` |
216
+ | `StateManager` | Load, save, append, and reconcile state |
217
+ | `createStateManager(options)` | Factory for `StateManager` |
218
+ | `RiskManager` | Daily loss, drawdown, session, and position gates |
219
+ | `createRiskManager(options)` | Factory for `RiskManager` |
220
+ | `EventBus` | Event emitter with `emitEvent()` and `onAny()` |
221
+ | `LIVE_EVENTS` | Named live event constants |
222
+ | `createEventBus()` | Factory for `EventBus` |
223
+ | `LiveLogger` | Structured event logger |
224
+ | `createLogger(options)` | Factory for `LiveLogger` |
225
+ | `BrokerClock` | Broker/local clock offset helper |
226
+ | `createClock(options)` | Factory for `BrokerClock` |
227
+
228
+ ### Dashboard
229
+
230
+ | Export | Summary |
231
+ | -------------------------------- | ------------------------------------------------------ |
232
+ | `createDashboardServer(options)` | Local HTTP dashboard for an engine/orchestrator source |
233
+
234
+ The dashboard source must expose `eventBus` and may expose `getStatus()`.
235
+
236
+ ## Technical Analysis Module: `tradelab/ta`
237
+
238
+ ```js
239
+ import { rsi, macd, bollinger, vwap, supertrend } from "tradelab/ta";
240
+ ```
241
+
242
+ TA functions return arrays aligned to the input. Warmup positions are `undefined` where a value cannot be computed yet.
243
+
244
+ ### Re-exported Core Indicators
245
+
246
+ | Export | Input | Returns |
247
+ | --------------------------------------- | ---------- | -------------------------- |
248
+ | `ema(values, period?)` | `number[]` | `number[]` |
249
+ | `atr(bars, period?)` | candles | `(number \| undefined)[]` |
250
+ | `swingHigh(bars, index, left?, right?)` | candles | `boolean` |
251
+ | `swingLow(bars, index, left?, right?)` | candles | `boolean` |
252
+ | `detectFVG(bars, index)` | candles | gap object or `null` |
253
+ | `lastSwing(bars, index, direction)` | candles | `{ idx, price }` or `null` |
254
+ | `structureState(bars, index)` | candles | latest swing state |
255
+
256
+ ### Oscillators
257
+
258
+ | Export | Input | Returns |
259
+ | ------------------------------------------- | ---------- | ----------------------------- |
260
+ | `rsi(closes, period?)` | `number[]` | `(number \| undefined)[]` |
261
+ | `macd(closes, fast?, slow?, signalPeriod?)` | `number[]` | `{ macd, signal, histogram }` |
262
+ | `stochastic(bars, kPeriod?, dPeriod?)` | candles | `{ k, d }` |
263
+
264
+ ### Bands And Channels
265
+
266
+ | Export | Input | Returns |
267
+ | ---------------------------------------------- | ---------- | -------------------------- |
268
+ | `bollinger(closes, period?, mult?)` | `number[]` | `{ middle, upper, lower }` |
269
+ | `donchian(bars, period?)` | candles | `{ upper, lower, middle }` |
270
+ | `keltner(bars, emaPeriod?, atrPeriod?, mult?)` | candles | `{ upper, lower, middle }` |
271
+
272
+ ### Trend And Volume
273
+
274
+ | Export | Input | Returns |
275
+ | ---------------------------------- | ------- | ------------------------- |
276
+ | `supertrend(bars, period?, mult?)` | candles | `{ line, direction }` |
277
+ | `vwap(bars)` | candles | `(number \| undefined)[]` |
278
+
279
+ ## MCP Module: `tradelab/mcp`
280
+
281
+ ```js
282
+ import { createServer, startStdioServer } from "tradelab/mcp";
283
+ ```
284
+
285
+ | Export | Summary |
286
+ | -------------------- | --------------------------------------- |
287
+ | `createServer()` | Build an MCP server with tradelab tools |
288
+ | `startStdioServer()` | Start the MCP server on stdio |
289
+
290
+ See [mcp.md](mcp.md) for client configuration and tool payload examples.
125
291
 
126
292
  ## Types
127
293
 
128
- The package ships declarations in:
294
+ The package ships TypeScript declarations:
129
295
 
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`
296
+ | File | Covers |
297
+ | ------------------ | --------------- |
298
+ | `types/index.d.ts` | `tradelab` |
299
+ | `types/data.d.ts` | `tradelab/data` |
300
+ | `types/live.d.ts` | `tradelab/live` |
301
+ | `types/ta.d.ts` | `tradelab/ta` |
302
+ | `types/mcp.d.ts` | `tradelab/mcp` |
132
303
 
133
- <small>[Back to main page](README.md)</small>
304
+ <small>[Back to docs](README.md)</small>