Skip to content

Commit 39c8015

Browse files
Merge pull request #77 from tripolskypetr/simulator2
Simulator2
2 parents 42c12ef + 7557663 commit 39c8015

90 files changed

Lines changed: 3556 additions & 182120 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
[![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue)]()
1212
[![Build](https://github.com/tripolskypetr/backtest-kit/actions/workflows/webpack.yml/badge.svg)](https://github.com/tripolskypetr/backtest-kit/actions/workflows/webpack.yml)
1313

14-
Most trading bots don't die because the strategy was wrong. They die because the backtest quietly read tomorrow's candle, because the process crashed mid-fill and opened the position twice, because the exchange rejected an order and the bot kept trading a ghost. The strategy was never the hard part — the *plumbing* was.
14+
Most trading bots don't die because the strategy was wrong. They die because the backtest quietly read tomorrow's candle, because the process crashed mid-fill and opened the position twice, because the exchange rejected an order and the bot kept trading a ghost. The strategy was never the hard part — the *infrastructure* was.
1515

16-
`backtest-kit` is that plumbing, closed off one failure at a time over a year of live trading and running real money in production at [TheOneTrade](https://theonetrade.github.io). This page walks the failures that kill bots and shows how each one is designed out of the default path — not "discouraged," not "documented," but structurally unavailable unless you go out of your way to defeat the engine. Every claim opens into **The Code / The Math / The Proof** so you (or the model reading this for you) can check the work instead of trusting the pitch.
16+
`backtest-kit` is that infrastructure, closed off one failure at a time over a year of live trading and running real money in production at [TheOneTrade](https://theonetrade.github.io). This page walks the failures that kill bots and shows how each one is designed out of the default path — not "discouraged," not "documented," but structurally unavailable unless you go out of your way to defeat the engine. Every claim opens into **The Code / The Math / The Proof** so you (or the model reading this for you) can check the work instead of trusting the pitch.
1717

1818
📚 **[API Reference](https://backtest-kit.github.io/documents/example_02_first_backtest.html)** · 🌟 **[Reference implementation](https://github.com/tripolskypetr/backtest-kit/tree/master/example)** · 📰 **[Article series](https://backtest-kit.github.io/documents/article_07_ai_news_trading_signals.html)**
1919

cli/README.md

Lines changed: 13 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,7 @@ Every invocation is **one mode** (a primary flag) + a positional strategy/entry
104104
| **Candle Dump** | `--dump` | Fetch & save raw OHLCV candles to a file |
105105
| **PnL Debug** | `--pnldebug` | Simulate per-minute PnL for a given entry price & direction |
106106
| **Broker Debug** | `--brokerdebug` | Fire a single broker commit against the live adapter |
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` |
107+
| **Sweep** | `--sweep` | Grid sweep over a crowd-ideas feed: profit-before-stop corridor + raw author tracks, axes from a positional JSON config |
109108
| **Flush** | `--flush` | Delete report/log/markdown/agent folders from a strategy dump dir |
110109
| **Init** | `--init` | Scaffold a new project |
111110
| **Docker** | `--docker` | Scaffold a self-contained Docker workspace |
@@ -273,7 +272,7 @@ Utilities that don't run a strategy. They share one convention, explained once h
273272
> **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.
274273
275274
<details>
276-
<summary>The shared <code>&lt;mode&gt;.module.ts</code> shape (pine / editor / dump / pnldebug / brokerdebug / simulator / tune)</summary>
275+
<summary>The shared <code>&lt;mode&gt;.module.ts</code> shape (pine / editor / dump / pnldebug / brokerdebug / sweep)</summary>
277276

278277
```typescript
279278
// modules/pine.module.ts (same shape for editor/dump/pnldebug.module; brokerdebug registers a Broker instead)
@@ -451,62 +450,32 @@ The CLI loads `./modules/brokerdebug.module`, fetches the last candle for `--sym
451450

452451
</details>
453452

454-
### 🎛️ Simulator (`--simulator`)
453+
### 🎛️ Sweep (`--sweep`)
455454

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.
455+
A **grid sweep** over a feed of crowd trading ideas: the grid axes come from a positional JSON config of the consumer — from a small feasibility probe to a full parameter search. Without a config the engine defaults apply. Authors are graded by ONE binary outcome — **profit-before-stop**: walking each point's own hold window candle by candle, an idea is a HIT when a fixation (the profit lock if lock > 0, OR the trailing arm level) fires BEFORE the hard stop, a MISS when the hard stop fires first, the window times out, or the candles run out. Prints a Markdown report with the corridor share, the ranking winners, and the **raw author tracks** (ideas/hits/hitRate per grading rule) — the engine grades every author but bans none; who to trust is userspace.
457456

458457
```bash
459-
npx @backtest-kit/cli --simulator --symbol BTCUSDT ./assets/tv-ideas.normalized.jsonl
458+
npx @backtest-kit/cli --sweep --symbol BTCUSDT ./assets/tv-ideas.normalized.jsonl
460459
# → 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+
npx @backtest-kit/cli --sweep --symbol BTCUSDT ./assets/tv-ideas.normalized.jsonl ./assets/probe.config.json
462461
```
463462

464463
<details>
465-
<summary>Simulator flags, input format & behavior</summary>
464+
<summary>Sweep flags, input format & behavior</summary>
466465

467466
| Flag | Type | Description |
468467
|------|------|-------------|
469-
| `--simulator` | boolean | Enable the grid sweep |
468+
| `--sweep` | boolean | Enable the grid sweep |
470469
| `--symbol` | string | Trading pair to simulate (default `"BTCUSDT"`) |
471470
| `--exchange` | string | Exchange (default: first registered, falls back to CCXT Binance) |
472-
| `--output` | string | Output base name (default `simulator_{SYMBOL}_{TIMESTAMP}`) |
473-
| `--json` | boolean | Save the full `ISimulatorResult` to `./dump/<output>.json` |
471+
| `--output` | string | Output base name (default `sweep_{SYMBOL}_{TIMESTAMP}`) |
472+
| `--json` | boolean | Save the full `ISweepResult` to `./dump/<output>.json` |
474473
| `--markdown` | boolean | Save the summary report to `./dump/<output>.md` |
475-
| `--verbose` | boolean | Log every simulator lifecycle callback to the console |
474+
| `--verbose` | boolean | Log every sweep lifecycle callback to the console |
476475

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+
**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"?: ISweepGridAxes, "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`.
478477

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+
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), EVERY author traded (the engine grades every author on the raw per-author track **inside each point's own hold window** and bans none — userspace filters on the continuous `hitRate`), production slot semantics (one open position per author), time-based Sharpe/Sortino over daily equity buckets. The result is a single report bucket — `result.reports.reports` (grid point reports, sorted by `reportOrder`), `result.reports.best` (the four ranking winners), and `result.reports.tracks` (author tracks). Each track line is self-contained (`{holdMinutes, profitLockPercent, hardStopPercent, trailingTakePercent, author, ideas, hits, hitRate}`) for grep/jq without a join. 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 `sweep.module` (see convention above).
510479

511480
</details>
512481

cli/src/helpers/getArgs.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,7 @@ export const getArgs = singleshot(() => {
157157
type: "boolean",
158158
default: false,
159159
},
160-
simulator: {
161-
type: "boolean",
162-
default: false,
163-
},
164-
tune: {
160+
sweep: {
165161
type: "boolean",
166162
default: false,
167163
},

cli/src/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ import "./main/editor";
2222
import "./main/dump";
2323
import "./main/pnldebug";
2424
import "./main/brokerdebug";
25-
import "./main/simulator";
26-
import "./main/tune";
25+
import "./main/sweep";
2726
import "./main/flush";
2827
import "./main/init";
2928
import "./main/docker";

0 commit comments

Comments
 (0)