@backtest-kit/cli 16.5.0 → 17.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 CHANGED
@@ -104,7 +104,8 @@ Every invocation is **one mode** (a primary flag) + a positional strategy/entry
104
104
  | **Candle Dump** | `--dump` | Fetch & save raw OHLCV candles to a file |
105
105
  | **PnL Debug** | `--pnldebug` | Simulate per-minute PnL for a given entry price & direction |
106
106
  | **Broker Debug** | `--brokerdebug` | Fire a single broker commit against the live adapter |
107
- | **Simulator** | `--simulator` | Sweep exit/entry parameters over a crowd-ideas feed, train an author whitelist |
107
+ | **Simulator** | `--simulator` | Grid sweep over a crowd-ideas feed: axes from a positional JSON config, engine defaults without one |
108
+ | **Tune** | `--tune` | ONE out-of-sample shot of a frozen training artifact (point + author track record) via `Simulator.test` |
108
109
  | **Flush** | `--flush` | Delete report/log/markdown/agent folders from a strategy dump dir |
109
110
  | **Init** | `--init` | Scaffold a new project |
110
111
  | **Docker** | `--docker` | Scaffold a self-contained Docker workspace |
@@ -267,12 +268,12 @@ The same shape works for `--live --entry` / `--paper --entry` (call `Live.backgr
267
268
 
268
269
  ## 🛠️ Tooling modes
269
270
 
270
- Six utilities that don't run a strategy. They share one convention, explained once here and referenced below.
271
+ Utilities that don't run a strategy. They share one convention, explained once here and referenced below.
271
272
 
272
273
  > **The `<mode>.module` convention.** By default the CLI auto-registers CCXT Binance. To use a different exchange (custom API keys, rate limits, a non-spot market), drop a `modules/<mode>.module.ts` that calls `addExchangeSchema` from `backtest-kit`. The CLI loads it automatically before running, trying `.ts`/`.mjs`/`.cjs`; it's searched **next to the target file first, then in the project root**. `.env` is loaded root-first then the target-file dir (override), so API keys stay out of code.
273
274
 
274
275
  <details>
275
- <summary>The shared <code>&lt;mode&gt;.module.ts</code> shape (pine / editor / dump / pnldebug / brokerdebug / simulator)</summary>
276
+ <summary>The shared <code>&lt;mode&gt;.module.ts</code> shape (pine / editor / dump / pnldebug / brokerdebug / simulator / tune)</summary>
276
277
 
277
278
  ```typescript
278
279
  // modules/pine.module.ts (same shape for editor/dump/pnldebug.module; brokerdebug registers a Broker instead)
@@ -452,11 +453,12 @@ The CLI loads `./modules/brokerdebug.module`, fetches the last candle for `--sym
452
453
 
453
454
  ### 🎛️ Simulator (`--simulator`)
454
455
 
455
- Sweep exit/entry parameters over a feed of crowd trading ideas using the `Simulator` entity — one candle pass per idea, a full parameter grid evaluated arithmetically, an author whitelist trained with default-ban semantics. Prints a Markdown report with four ranking winners (time-based Sharpe, Sortino, PnL, recovery factor) and the production whitelist.
456
+ A **grid sweep** over a feed of crowd trading ideas: the grid axes come from a positional JSON config of the consumer — from a lock-free feasibility probe to a full parameter search. Without a config the engine defaults apply (the full default axes of the connection service with all five author metrics, ordered by sharpe). Prints a Markdown report with the corridor share and, per metric bucket, the ranking winners and the whitelist of the sharpe winner's ban rule.
456
457
 
457
458
  ```bash
458
459
  npx @backtest-kit/cli --simulator --symbol BTCUSDT ./assets/tv-ideas.normalized.jsonl
459
- # → summary to stdout; add --json / --markdown to save into ./dump/
460
+ # → engine-default grid; add a config to shape the sweep:
461
+ npx @backtest-kit/cli --simulator --symbol BTCUSDT ./assets/tv-ideas.normalized.jsonl ./assets/probe.config.json
460
462
  ```
461
463
 
462
464
  <details>
@@ -464,7 +466,7 @@ npx @backtest-kit/cli --simulator --symbol BTCUSDT ./assets/tv-ideas.normalized.
464
466
 
465
467
  | Flag | Type | Description |
466
468
  |------|------|-------------|
467
- | `--simulator` | boolean | Enable simulator mode |
469
+ | `--simulator` | boolean | Enable the grid sweep |
468
470
  | `--symbol` | string | Trading pair to simulate (default `"BTCUSDT"`) |
469
471
  | `--exchange` | string | Exchange (default: first registered, falls back to CCXT Binance) |
470
472
  | `--output` | string | Output base name (default `simulator_{SYMBOL}_{TIMESTAMP}`) |
@@ -472,9 +474,39 @@ npx @backtest-kit/cli --simulator --symbol BTCUSDT ./assets/tv-ideas.normalized.
472
474
  | `--markdown` | boolean | Save the summary report to `./dump/<output>.md` |
473
475
  | `--verbose` | boolean | Log every simulator lifecycle callback to the console |
474
476
 
475
- **Positional (required):** path to an ideas `.jsonl` file — one idea per line, exact shape `{ "id": number, "ts": number, "symbol": string, "direction": "LONG"|"SHORT"|"NEUTRAL", "author": string }`. The file is validated **before any work starts** — the first line that does not match the structure aborts the run with an error naming the line and the field. Ideas of other symbols are filtered out by the engine, so one shared feed serves any `--symbol`.
477
+ **Positionals:** path to an ideas `.jsonl` file (required) — one idea per line, exact shape `{ "id": number, "ts": number, "symbol": string, "direction": "LONG"|"SHORT"|"NEUTRAL", "author": string }` — and an **optional config `.json`** with the shape `{ "gridAxes"?: ISimulatorGridAxes, "reportOrder"?: "sharpe"|"sortino"|"pnl"|"recovery" }`. Both files are validated **before any work starts** — a structure mismatch (including an unknown config key) aborts the run with an error naming the field. No config → an empty object → the engine defaults. Ideas of other symbols are filtered out by the engine, so one shared feed serves any `--symbol`.
476
478
 
477
- Under the hood: 5-day candle horizon per idea (lazy chunked fetch through the exchange, persist cache first), flood dedupe (one idea per author per direction per 8h), author ban thresholds swept as grid axes (unproven author = banned by default), production slot semantics, time-based Sharpe/Sortino over daily equity buckets. With `--verbose` every lifecycle callback (`onIdeas`, `onProfiles`, `onAuthorsTrained`, `onGridPoint`, `onRanking`, `onDone`) is logged to the console as it fires, so long runs show progress. Exchange via `simulator.module` (see convention above).
479
+ Under the hood: one candle pass per idea to the grid's longest hold (lazy chunked fetch through the exchange, persist cache first), flood dedupe (one idea per author per direction per 8h), default-ban author filter graded **inside each point's own hold window** (track/hit-rate thresholds swept — unproven author = banned), production slot semantics, time-based Sharpe/Sortino over daily equity buckets, per-metric buckets with their own winners and ban dictionaries — nothing is aggregated across metrics. With `--verbose` every lifecycle callback (`onIdeas`, `onProfiles`, `onAuthorsTrained`, `onGridPoint`, `onRanking`, `onDone`) is logged to the console as it fires, so long runs show progress. Exchange via `simulator.module` (see convention above).
480
+
481
+ </details>
482
+
483
+ ### 🔧 Tune (`--tune`)
484
+
485
+ **ONE out-of-sample shot of a frozen training artifact — no training happens here.** Pick your candidate elsewhere (a `Simulator.run` sweep of your own), freeze its point and raw author track record into a JSON config, and fire it exactly once on an unseen feed via `Simulator.test`. Bans are re-derived from the frozen numbers under the point's rule; authors unseen in the config are banned by default.
486
+
487
+ ```bash
488
+ npx @backtest-kit/cli --tune --symbol BTCUSDT ./assets/tail.jsonl ./assets/tune.config.json
489
+ # → one out-of-sample shot; add --json / --markdown to save into ./dump/
490
+ ```
491
+
492
+ <details>
493
+ <summary>Tune flags, input format & behavior</summary>
494
+
495
+ | Flag | Type | Description |
496
+ |------|------|-------------|
497
+ | `--tune` | boolean | Enable the out-of-sample shot |
498
+ | `--symbol` | string | Trading pair to test (default `"BTCUSDT"`) |
499
+ | `--exchange` | string | Exchange (default: first registered, falls back to CCXT Binance) |
500
+ | `--output` | string | Output base name (default `tune_{SYMBOL}_{TIMESTAMP}`) |
501
+ | `--json` | boolean | Save the full `ISimulatorTestResult` to `./dump/<output>.json` |
502
+ | `--markdown` | boolean | Save the out-of-sample report to `./dump/<output>.md` |
503
+ | `--verbose` | boolean | Log simulator lifecycle callbacks to the console |
504
+
505
+ **Positionals:** path to an ideas `.jsonl` file (same shape and validation as `--simulator`) and a config `.json` carrying the **frozen training artifact**: `{ "point": ISimulatorGridPoint, "authorStats": [{ "author", "ideas", "hits" }], "gridAxes"?, "reportOrder"? }`. The `point` and `authorStats` are REQUIRED — without them there is nothing to test and the run aborts with an error. `gridAxes` are optional: by default they mirror the frozen point one value per axis (the grid is inert for a test).
506
+
507
+ The report carries the out-of-sample result with the trade list and the **frozen author track record** with ban flags re-derived under the point's rule. Feed it the tail your training never saw — the honesty of the shot is YOUR split discipline, the CLI just refuses to train. Exchange via `tune.module` (see convention above).
508
+
509
+ A train-on-train winner is a ceiling, never a promise: this shot is the honest number, and the final arbiter for any point tested here is a real engine backtest (`Backtest.run`).
478
510
 
479
511
  </details>
480
512