@backtest-kit/cli 16.6.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,8 +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` | Feasibility probe over a crowd-ideas feed: is there a profitable corridor at all |
108
- | **Tune** | `--tune` | Walk-forward parameter search over a crowd-ideas feed: train on the head, one frozen shot on the tail |
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` |
109
109
  | **Flush** | `--flush` | Delete report/log/markdown/agent folders from a strategy dump dir |
110
110
  | **Init** | `--init` | Scaffold a new project |
111
111
  | **Docker** | `--docker` | Scaffold a self-contained Docker workspace |
@@ -453,11 +453,12 @@ The CLI loads `./modules/brokerdebug.module`, fetches the last candle for `--sym
453
453
 
454
454
  ### 🎛️ Simulator (`--simulator`)
455
455
 
456
- A **feasibility probe** over a feed of crowd trading ideas: does the feed contain a profitable corridor at all, or is there nothing to search? The probe deliberately does NOT try to earn — the profit-harvesting machinery is off (no profit lock, inert trailing take, no weighted consensus), and a fast **48-point grid** of hard stop × hold × ban rule is evaluated from one candle pass per idea. The parameter search itself is `--tune`'s job. Prints a Markdown report with the corridor share, four ranking winners as evidence, and the whitelist of the sharpe winner's ban rule.
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.
457
457
 
458
458
  ```bash
459
459
  npx @backtest-kit/cli --simulator --symbol BTCUSDT ./assets/tv-ideas.normalized.jsonl
460
- # → verdict 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
461
462
  ```
462
463
 
463
464
  <details>
@@ -465,7 +466,7 @@ npx @backtest-kit/cli --simulator --symbol BTCUSDT ./assets/tv-ideas.normalized.
465
466
 
466
467
  | Flag | Type | Description |
467
468
  |------|------|-------------|
468
- | `--simulator` | boolean | Enable the feasibility probe |
469
+ | `--simulator` | boolean | Enable the grid sweep |
469
470
  | `--symbol` | string | Trading pair to simulate (default `"BTCUSDT"`) |
470
471
  | `--exchange` | string | Exchange (default: first registered, falls back to CCXT Binance) |
471
472
  | `--output` | string | Output base name (default `simulator_{SYMBOL}_{TIMESTAMP}`) |
@@ -473,19 +474,19 @@ npx @backtest-kit/cli --simulator --symbol BTCUSDT ./assets/tv-ideas.normalized.
473
474
  | `--markdown` | boolean | Save the summary report to `./dump/<output>.md` |
474
475
  | `--verbose` | boolean | Log every simulator lifecycle callback to the console |
475
476
 
476
- **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`.
477
478
 
478
- 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), default-ban author filter (track/hit-rate thresholds swept — unproven author = banned), production slot semantics, time-based Sharpe/Sortino over daily equity buckets. A position is entered on a proven author's idea and exits by time or catastrophe stop, nothing else — if even this primitive corridor is unprofitable on its own training range, the feed carries no extractable signal. 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).
479
480
 
480
481
  </details>
481
482
 
482
483
  ### 🔧 Tune (`--tune`)
483
484
 
484
- The **parameter search** counterpart of the `--simulator` probe: a walk-forward sweep of the full grid with the profit-harvesting machinery ON — profit lock, trailing take, weighted consensus, Wilson-bound ban, both author-hit metrics (close/reach). Honesty is structural: training sees only the head of the feed (`--split` of its time range, default 70%), then the sharpe winner is frozen — point and raw author track record — and fired **exactly once** on the tail via `Simulator.test`. Nothing is trained on the tail; authors unseen in training are banned by default.
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.
485
486
 
486
487
  ```bash
487
- npx @backtest-kit/cli --tune --symbol BTCUSDT ./assets/tv-ideas.normalized.jsonl
488
- # → train winners + one out-of-sample shot; add --json / --markdown to save into ./dump/
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/
489
490
  ```
490
491
 
491
492
  <details>
@@ -493,20 +494,19 @@ npx @backtest-kit/cli --tune --symbol BTCUSDT ./assets/tv-ideas.normalized.jsonl
493
494
 
494
495
  | Flag | Type | Description |
495
496
  |------|------|-------------|
496
- | `--tune` | boolean | Enable the walk-forward parameter search |
497
- | `--symbol` | string | Trading pair to tune (default `"BTCUSDT"`) |
497
+ | `--tune` | boolean | Enable the out-of-sample shot |
498
+ | `--symbol` | string | Trading pair to test (default `"BTCUSDT"`) |
498
499
  | `--exchange` | string | Exchange (default: first registered, falls back to CCXT Binance) |
499
- | `--split` | string | Train share of the feed time range, 0..1 (default `0.7`) |
500
500
  | `--output` | string | Output base name (default `tune_{SYMBOL}_{TIMESTAMP}`) |
501
- | `--json` | boolean | Save `{ trainSplit, train, test }` to `./dump/<output>.json` |
502
- | `--markdown` | boolean | Save the walk-forward report to `./dump/<output>.md` |
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
503
  | `--verbose` | boolean | Log simulator lifecycle callbacks to the console |
504
504
 
505
- **Positional (required):** path to an ideas `.jsonl` file — same shape and validation as `--simulator`.
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
506
 
507
- The report carries the train winners of all four ranking criteria (full point labels including lock, Wilson bound and the author-hit metric), the out-of-sample result of the frozen sharpe winner with its trade list, and the **frozen author track record** — the raw `author/ideas/hits` numbers to hardcode for production `Simulator.test`: banned flags and vote weights are re-derived from them under the frozen point's rule, and an author absent from the list is banned by default. Exchange via `tune.module` (see convention above).
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
508
 
509
- A train-on-train winner is a ceiling, never a promise: the out-of-sample section is the honest number, and the final arbiter for any point picked here is a real engine backtest (`Backtest.run`).
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`).
510
510
 
511
511
  </details>
512
512