@backtest-kit/cli 6.13.0 → 6.15.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
@@ -41,6 +41,7 @@ Point the CLI at your strategy file, choose a mode, and it handles exchange conn
41
41
  | **Telegram** | `--telegram` | Trade notifications with price charts |
42
42
  | **PineScript** | `--pine` | Run a local `.pine` indicator against exchange data |
43
43
  | **Candle Dump** | `--dump` | Fetch and save raw OHLCV candles to a file |
44
+ | **Flush** | `--flush` | Delete report/log/markdown/agent folders from strategy dump dir |
44
45
  | **Init Project** | `--init` | Scaffold a new backtest-kit project |
45
46
 
46
47
  ## 🚀 Installation
@@ -144,6 +145,7 @@ npm start -- --symbol BTCUSDT --ui
144
145
  | `--telegram` | boolean | Enable Telegram notifications (default: `false`) |
145
146
  | `--verbose` | boolean | Log each candle fetch (default: `false`) |
146
147
  | `--noCache` | boolean | Skip candle cache warming before backtest (default: `false`) |
148
+ | `--noFlush` | boolean | Skip removing report/log/markdown/agent folders before backtest run (default: `false`) |
147
149
  | `--symbol` | string | Trading pair (default: `"BTCUSDT"`) |
148
150
  | `--strategy` | string | Strategy name (default: first registered) |
149
151
  | `--exchange` | string | Exchange name (default: first registered) |
@@ -178,7 +180,7 @@ Runs the strategy against historical candle data using a registered `FrameSchema
178
180
  npm run backtest
179
181
  ```
180
182
 
181
- Before running, the CLI warms the candle cache for every interval in `--cacheInterval`. On the next run, cached data is used directly — no API calls needed. Pass `--noCache` to skip this step entirely.
183
+ Before running, the CLI removes the `report`, `log`, `markdown`, and `agent` folders from the strategy's `dump/` directory, then warms the candle cache for every interval in `--cacheInterval`. On the next run, cached data is used directly — no API calls needed. Pass `--noCache` to skip cache warming, `--noFlush` to keep existing output folders.
182
184
 
183
185
  ### Paper Trading
184
186
 
@@ -228,7 +230,7 @@ Runs the same historical period against multiple strategy files and prints a ran
228
230
  npm run walker
229
231
  ```
230
232
 
231
- Each positional argument is a separate strategy entry point. All files are loaded without changing `process.cwd()` — `.env` is read from the working directory only. After loading, `addWalkerSchema` is called automatically using the exchange and frame registered by the strategy files.
233
+ Each positional argument is a separate strategy entry point. Before loading them, the CLI removes the `report`, `log`, `markdown`, and `agent` folders from each entry point's `dump/` directory. Pass `--noFlush` to keep existing output. All files are loaded without changing `process.cwd()` — `.env` is read from the working directory only. After loading, `addWalkerSchema` is called automatically using the exchange and frame registered by the strategy files.
232
234
 
233
235
  If no frame is registered, the CLI falls back to the last 31 days from `Date.now()` with a console warning.
234
236
 
@@ -240,6 +242,7 @@ If no frame is registered, the CLI falls back to the last 31 days from `Date.now
240
242
  | `--symbol` | string | Trading pair (default: `"BTCUSDT"`) |
241
243
  | `--cacheInterval` | string | Intervals to pre-cache (default: `"1m, 15m, 30m, 4h"`) |
242
244
  | `--noCache` | boolean | Skip candle cache warming (default: `false`) |
245
+ | `--noFlush` | boolean | Skip removing report/log/markdown/agent folders before walker run (default: `false`) |
243
246
  | `--verbose` | boolean | Log each candle fetch and strategy progress (default: `false`) |
244
247
  | `--output` | string | Output file base name (default: `walker_{SYMBOL}_{TIMESTAMP}`) |
245
248
  | `--json` | boolean | Save results as JSON to `./dump/<output>.json` |
@@ -828,6 +831,57 @@ Or add it to `package.json`:
828
831
  npx @backtest-kit/cli --dump --symbol BTCUSDT --timeframe 15m --limit 500 --jsonl
829
832
  ```
830
833
 
834
+ ## 🗑️ Flushing Strategy Output (`--flush`)
835
+
836
+ `@backtest-kit/cli` can delete generated output folders from one or more strategy dump directories without touching cached candle data.
837
+
838
+ ### CLI Flags
839
+
840
+ | Flag | Type | Description |
841
+ |------|------|-------------|
842
+ | `--flush` | boolean | Enable flush mode |
843
+
844
+ **Positional arguments (required):** one or more strategy entry point files. For each entry point the CLI resolves its directory and removes the following subdirectories from `<entry-dir>/dump/`:
845
+
846
+ | Folder | Contents |
847
+ |--------|----------|
848
+ | `report` | Backtest report files (`.jsonl`) |
849
+ | `log` | Run logs (`log.jsonl`) |
850
+ | `markdown` | Exported Markdown reports |
851
+ | `agent` | Agent outline files |
852
+
853
+ Candle cache (`dump/data/`) and AI forecast outlines (`dump/outline/`) are **not** removed.
854
+
855
+ ### Usage
856
+
857
+ Flush a single strategy:
858
+
859
+ ```bash
860
+ npx @backtest-kit/cli --flush ./content/feb_2026.strategy/modules/backtest.module.ts
861
+ ```
862
+
863
+ Flush multiple strategies at once:
864
+
865
+ ```bash
866
+ npx @backtest-kit/cli --flush \
867
+ ./content/feb_2026.strategy/modules/backtest.module.ts \
868
+ ./content/mar_2026.strategy/modules/backtest.module.ts
869
+ ```
870
+
871
+ Or add it to `package.json`:
872
+
873
+ ```json
874
+ {
875
+ "scripts": {
876
+ "flush": "npx @backtest-kit/cli --flush ./content/feb_2026.strategy/modules/backtest.module.ts"
877
+ }
878
+ }
879
+ ```
880
+
881
+ ```bash
882
+ npm run flush
883
+ ```
884
+
831
885
  ## 🗂️ Scaffolding a New Project (`--init`)
832
886
 
833
887
  `@backtest-kit/cli` can bootstrap a ready-to-use project directory with a pre-configured layout, example strategy files, and all documentation fetched automatically.
@@ -985,6 +1039,7 @@ await run(mode, args);
985
1039
  | `frame` | `string` | Frame name (default: first registered) |
986
1040
  | `cacheInterval` | `CandleInterval[]` | Intervals to pre-cache (default: `["1m","15m","30m","1h","4h"]`) |
987
1041
  | `noCache` | `boolean` | Skip candle cache warming (default: `false`) |
1042
+ | `noFlush` | `boolean` | Skip removing report/log/markdown/agent folders before the run (default: `false`) |
988
1043
  | `verbose` | `boolean` | Log each candle fetch (default: `false`) |
989
1044
 
990
1045
  **Paper** and **Live** (`mode: "paper"` / `mode: "live"`):
package/build/index.cjs CHANGED
@@ -473,6 +473,10 @@ const getArgs = functoolsKit.singleshot(() => {
473
473
  type: "boolean",
474
474
  default: false,
475
475
  },
476
+ noFlush: {
477
+ type: "boolean",
478
+ default: false,
479
+ },
476
480
  cacheInterval: {
477
481
  type: "string",
478
482
  default: "1m, 15m, 30m, 4h",
@@ -486,6 +490,10 @@ const getArgs = functoolsKit.singleshot(() => {
486
490
  type: "boolean",
487
491
  default: false,
488
492
  },
493
+ flush: {
494
+ type: "boolean",
495
+ default: false,
496
+ },
489
497
  timeframe: {
490
498
  type: "string",
491
499
  default: "",
@@ -2461,14 +2469,27 @@ const cli = {
2461
2469
  };
2462
2470
  init();
2463
2471
 
2472
+ const NOTIFICATION_CONFIG = {
2473
+ signal: true,
2474
+ risk: true,
2475
+ info: true,
2476
+ breakeven: true,
2477
+ common_error: true,
2478
+ critical_error: true,
2479
+ validation_error: true,
2480
+ partial_loss: false,
2481
+ partial_profit: false,
2482
+ signal_sync: false,
2483
+ strategy_commit: true,
2484
+ };
2464
2485
  class SetupUtils {
2465
2486
  constructor() {
2466
2487
  this.enable = functoolsKit.singleshot(() => {
2467
2488
  cli.loggerService.debug("SetupUtils enable");
2489
+ BacktestKit.Notification.enable(NOTIFICATION_CONFIG);
2468
2490
  {
2469
2491
  BacktestKit.Recent.enable();
2470
2492
  BacktestKit.Storage.enable();
2471
- BacktestKit.Notification.enable();
2472
2493
  }
2473
2494
  {
2474
2495
  BacktestKit.Markdown.enable();
@@ -2503,6 +2524,23 @@ class SetupUtils {
2503
2524
  return;
2504
2525
  }
2505
2526
  this.enable.clear();
2527
+ {
2528
+ BacktestKit.Recent.disable();
2529
+ BacktestKit.Storage.disable();
2530
+ BacktestKit.Notification.disable();
2531
+ }
2532
+ {
2533
+ BacktestKit.Markdown.disable();
2534
+ BacktestKit.Report.disable();
2535
+ BacktestKit.Dump.disable();
2536
+ BacktestKit.Memory.disable();
2537
+ }
2538
+ {
2539
+ BacktestKit.Markdown.clear();
2540
+ BacktestKit.Report.clear();
2541
+ BacktestKit.MarkdownWriter.clear();
2542
+ BacktestKit.ReportWriter.clear();
2543
+ }
2506
2544
  {
2507
2545
  BacktestKit.PersistSignalAdapter.clear();
2508
2546
  BacktestKit.PersistRiskAdapter.clear();
@@ -2522,8 +2560,6 @@ class SetupUtils {
2522
2560
  BacktestKit.Dump.clear();
2523
2561
  BacktestKit.Log.clear();
2524
2562
  BacktestKit.Markdown.clear();
2525
- BacktestKit.Memory.clear();
2526
- BacktestKit.Report.clear();
2527
2563
  }
2528
2564
  {
2529
2565
  BacktestKit.StorageLive.clear();
@@ -2575,14 +2611,14 @@ BacktestKit.setConfig({
2575
2611
  CC_WALKER_MARKDOWN_TOP_N: 10,
2576
2612
  });
2577
2613
 
2578
- const MODES = ["backtest", "walker", "paper", "live", "pine", "dump", "init", "help", "version"];
2614
+ const MODES = ["backtest", "walker", "paper", "live", "pine", "dump", "flush", "init", "help", "version"];
2579
2615
  const ENTRY_PATH$1 = "./node_modules/@backtest-kit/cli/build/index.mjs";
2580
2616
  const HELP_TEXT$1 = `
2581
2617
  Example:
2582
2618
 
2583
2619
  node ${ENTRY_PATH$1} --help
2584
2620
  `.trimStart();
2585
- const main$b = async () => {
2621
+ const main$c = async () => {
2586
2622
  if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
2587
2623
  return;
2588
2624
  }
@@ -2590,19 +2626,48 @@ const main$b = async () => {
2590
2626
  if (MODES.some((mode) => values[mode])) {
2591
2627
  return;
2592
2628
  }
2593
- process.stdout.write(`@backtest-kit/cli ${"6.13.0"}\n`);
2629
+ process.stdout.write(`@backtest-kit/cli ${"6.15.0"}\n`);
2594
2630
  process.stdout.write("\n");
2595
2631
  process.stdout.write(`Run with --help to see available commands.\n`);
2596
2632
  process.stdout.write("\n");
2597
2633
  process.stdout.write(HELP_TEXT$1);
2598
2634
  process.exit(0);
2599
2635
  };
2600
- main$b();
2636
+ main$c();
2601
2637
 
2602
2638
  const notifyShutdown = functoolsKit.singleshot(async () => {
2603
2639
  console.log("Graceful shutdown initiated. Press Ctrl+C again to force quit.");
2604
2640
  });
2605
2641
 
2642
+ const FLUSH_DIRS = ["report", "log", "markdown", "agent"];
2643
+ const flush = async (entryPoint) => {
2644
+ const moduleRoot = path.dirname(path.resolve(process.cwd(), entryPoint));
2645
+ const dumpDir = path.join(moduleRoot, "dump");
2646
+ for (const dir of FLUSH_DIRS) {
2647
+ const target = path.join(dumpDir, dir);
2648
+ await fs$1.rm(target, { recursive: true, force: true });
2649
+ console.log(`Removed: ${target}`);
2650
+ }
2651
+ };
2652
+ const main$b = async () => {
2653
+ if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
2654
+ return;
2655
+ }
2656
+ const { values } = getArgs();
2657
+ if (!values.flush) {
2658
+ return;
2659
+ }
2660
+ const entryPoints = getPositionals();
2661
+ if (!entryPoints.length) {
2662
+ throw new Error("Entry point is required");
2663
+ }
2664
+ for (const entryPoint of entryPoints) {
2665
+ await flush(entryPoint);
2666
+ }
2667
+ process.exit(0);
2668
+ };
2669
+ main$b();
2670
+
2606
2671
  const BEFORE_EXIT_FN$5 = functoolsKit.singleshot(async () => {
2607
2672
  process.off("SIGINT", BEFORE_EXIT_FN$5);
2608
2673
  const [running = null] = await BacktestKit.Backtest.list();
@@ -2631,6 +2696,10 @@ const main$a = async () => {
2631
2696
  if (!values.backtest) {
2632
2697
  return;
2633
2698
  }
2699
+ if (!values.noFlush) {
2700
+ const [entryPoint = null] = getPositionals();
2701
+ entryPoint && await flush(entryPoint);
2702
+ }
2634
2703
  await cli.backtestMainService.connect();
2635
2704
  listenGracefulShutdown$5();
2636
2705
  };
@@ -2660,6 +2729,11 @@ const main$9 = async () => {
2660
2729
  if (!values.walker) {
2661
2730
  return;
2662
2731
  }
2732
+ if (!values.noFlush) {
2733
+ for (const entryPoint of getPositionals()) {
2734
+ await flush(entryPoint);
2735
+ }
2736
+ }
2663
2737
  listenGracefulShutdown$4();
2664
2738
  await cli.walkerMainService.connect();
2665
2739
  };
@@ -3045,6 +3119,7 @@ Modes:
3045
3119
  --live <entry> Live trading with real orders
3046
3120
  --pine <entry> Execute a local .pine indicator file
3047
3121
  --dump Fetch and save raw OHLCV candles
3122
+ --flush <entry...> Delete report/log/markdown/agent folders from strategy dump dir
3048
3123
  --init Scaffold a new project in the current directory
3049
3124
  --help Print this help message
3050
3125
 
@@ -3056,6 +3131,7 @@ Backtest flags:
3056
3131
  --frame <string> Frame name from addFrameSchema (default: first registered)
3057
3132
  --cacheInterval <string> Comma-separated intervals to pre-cache (default: "1m, 15m, 30m, 4h")
3058
3133
  --noCache Skip candle cache warming before the run
3134
+ --noFlush Skip removing report/log/markdown/agent folders before backtest run
3059
3135
  --verbose Log every candle fetch to stdout
3060
3136
  --ui Start web dashboard at http://localhost:60050
3061
3137
  --telegram Send trade notifications to Telegram
@@ -3065,6 +3141,7 @@ Walker flags (--walker):
3065
3141
  --symbol <string> Trading pair (default: BTCUSDT)
3066
3142
  --cacheInterval <string> Comma-separated intervals to pre-cache (default: "1m, 15m, 30m, 4h")
3067
3143
  --noCache Skip candle cache warming before the run
3144
+ --noFlush Skip removing report/log/markdown/agent folders before walker run
3068
3145
  --verbose Log every candle fetch to stdout
3069
3146
  --output <string> Output file base name (default: walker_{SYMBOL}_{TIMESTAMP})
3070
3147
  --json Save results as JSON to ./dump/<output>.json
@@ -3114,6 +3191,13 @@ Candle dump flags (--dump):
3114
3191
 
3115
3192
  Module file ./modules/dump.module is loaded automatically if it exists.
3116
3193
 
3194
+ Flush flags (--flush):
3195
+
3196
+ One or more positional entry points. For each entry point the following
3197
+ subdirectories are removed from <entry-dir>/dump/:
3198
+
3199
+ report log markdown agent
3200
+
3117
3201
  Init flags (--init):
3118
3202
 
3119
3203
  --output <string> Target directory name (default: backtest-kit-project)
@@ -3129,6 +3213,8 @@ Module hooks (loaded automatically by each mode):
3129
3213
  modules/pine.module --pine Exchange schema for PineScript runs
3130
3214
  modules/dump.module --dump Exchange schema for candle dumps
3131
3215
 
3216
+ --flush has no associated module. It only removes dump subdirectories.
3217
+
3132
3218
  Extensions .ts, .mjs, .cjs are tried automatically. Missing module = soft warning.
3133
3219
 
3134
3220
  Environment variables:
@@ -3141,13 +3227,15 @@ Environment variables:
3141
3227
  Examples:
3142
3228
 
3143
3229
  node ${ENTRY_PATH} --backtest ./content/feb_2026.strategy.ts
3144
- node ${ENTRY_PATH} --backtest --symbol BTCUSDT --noCache --ui ./content/feb_2026.strategy.ts
3230
+ node ${ENTRY_PATH} --backtest --symbol BTCUSDT --noCache --noFlush --ui ./content/feb_2026.strategy.ts
3145
3231
  node ${ENTRY_PATH} --walker ./content/feb_2026_v1.strategy.ts ./content/feb_2026_v2.strategy.ts ./content/feb_2026_v3.strategy.ts
3146
- node ${ENTRY_PATH} --walker --symbol BTCUSDT --noCache --markdown ./content/feb_2026_v1.ts ./content/feb_2026_v2.ts
3232
+ node ${ENTRY_PATH} --walker --symbol BTCUSDT --noCache --noFlush --markdown ./content/feb_2026_v1.ts ./content/feb_2026_v2.ts
3147
3233
  node ${ENTRY_PATH} --paper --symbol ETHUSDT ./content/feb_2026.strategy.ts
3148
3234
  node ${ENTRY_PATH} --live --ui --telegram ./content/feb_2026.strategy.ts
3149
3235
  node ${ENTRY_PATH} --pine ./math/feb_2026.pine --timeframe 15m --limit 500 --jsonl
3150
3236
  node ${ENTRY_PATH} --dump --symbol BTCUSDT --timeframe 15m --limit 500 --jsonl
3237
+ node ${ENTRY_PATH} --flush ./content/feb_2026.strategy/feb_2026.strategy.ts
3238
+ node ${ENTRY_PATH} --flush ./content/feb_2026.strategy/feb_2026.strategy.ts ./content/feb_2026.strategy/feb_2026.test.ts
3151
3239
  node ${ENTRY_PATH} --init --output my-trading-bot
3152
3240
  `.trimStart();
3153
3241
  const main$1 = async () => {
@@ -3158,7 +3246,7 @@ const main$1 = async () => {
3158
3246
  if (!values.help) {
3159
3247
  return;
3160
3248
  }
3161
- process.stdout.write(`@backtest-kit/cli ${"6.13.0"}\n\n`);
3249
+ process.stdout.write(`@backtest-kit/cli ${"6.15.0"}\n\n`);
3162
3250
  process.stdout.write(HELP_TEXT);
3163
3251
  process.exit(0);
3164
3252
  };
@@ -3172,7 +3260,7 @@ const main = async () => {
3172
3260
  if (!values.version) {
3173
3261
  return;
3174
3262
  }
3175
- process.stdout.write(`@backtest-kit/cli ${"6.13.0"}\n`);
3263
+ process.stdout.write(`@backtest-kit/cli ${"6.15.0"}\n`);
3176
3264
  process.exit(0);
3177
3265
  };
3178
3266
  main();
package/build/index.mjs CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import * as BacktestKit from 'backtest-kit';
3
- import { Log, listExchangeSchema, addExchangeSchema, roundTicks, listFrameSchema, addFrameSchema, listenDoneLive, listenDoneBacktest, shutdown, listenSignal, listStrategySchema, overrideExchangeSchema, Backtest, Session, Cache, Interval, alignToInterval, addWalkerSchema, overrideWalkerSchema, Walker, listenDoneWalker, Live, getCandles, checkCandles, warmCandles, listenRisk, listenStrategyCommit, listenSync, Recent, Storage, Notification, Markdown, Report, Dump, Memory, StorageLive, StorageBacktest, RecentLive, RecentBacktest, NotificationLive, NotificationBacktest, PersistSignalAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistPartialAdapter, PersistBreakevenAdapter, PersistCandleAdapter, PersistStorageAdapter, PersistNotificationAdapter, PersistLogAdapter, PersistMeasureAdapter, PersistIntervalAdapter, PersistMemoryAdapter, PersistRecentAdapter, setConfig, Exchange } from 'backtest-kit';
3
+ import { Log, listExchangeSchema, addExchangeSchema, roundTicks, listFrameSchema, addFrameSchema, listenDoneLive, listenDoneBacktest, shutdown, listenSignal, listStrategySchema, overrideExchangeSchema, Backtest, Session, Cache, Interval, alignToInterval, addWalkerSchema, overrideWalkerSchema, Walker, listenDoneWalker, Live, getCandles, checkCandles, warmCandles, listenRisk, listenStrategyCommit, listenSync, Notification, Recent, Storage, Markdown, Report, Dump, Memory, StorageLive, StorageBacktest, RecentLive, RecentBacktest, NotificationLive, NotificationBacktest, MarkdownWriter, ReportWriter, PersistSignalAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistPartialAdapter, PersistBreakevenAdapter, PersistCandleAdapter, PersistStorageAdapter, PersistNotificationAdapter, PersistLogAdapter, PersistMeasureAdapter, PersistIntervalAdapter, PersistMemoryAdapter, PersistRecentAdapter, setConfig, Exchange } from 'backtest-kit';
4
4
  import { getErrorMessage, errorData, singleshot, str, BehaviorSubject, compose, createAwaiter, execpool, queued, sleep, randomString, TIMEOUT_SYMBOL, typo, retry, trycatch, memoize } from 'functools-kit';
5
5
  import fs, { constants } from 'fs';
6
6
  import * as stackTrace from 'stack-trace';
7
- import path, { join, resolve, basename, extname, dirname } from 'path';
8
- import fs$1, { access, readFile, mkdir, writeFile, readdir, copyFile } from 'fs/promises';
7
+ import path, { join, resolve, dirname, basename, extname } from 'path';
8
+ import fs$1, { access, readFile, mkdir, writeFile, rm, readdir, copyFile } from 'fs/promises';
9
9
  import dotenv from 'dotenv';
10
10
  import { createActivator } from 'di-kit';
11
11
  import { fileURLToPath } from 'url';
@@ -448,6 +448,10 @@ const getArgs = singleshot(() => {
448
448
  type: "boolean",
449
449
  default: false,
450
450
  },
451
+ noFlush: {
452
+ type: "boolean",
453
+ default: false,
454
+ },
451
455
  cacheInterval: {
452
456
  type: "string",
453
457
  default: "1m, 15m, 30m, 4h",
@@ -461,6 +465,10 @@ const getArgs = singleshot(() => {
461
465
  type: "boolean",
462
466
  default: false,
463
467
  },
468
+ flush: {
469
+ type: "boolean",
470
+ default: false,
471
+ },
464
472
  timeframe: {
465
473
  type: "string",
466
474
  default: "",
@@ -2432,14 +2440,27 @@ const cli = {
2432
2440
  };
2433
2441
  init();
2434
2442
 
2443
+ const NOTIFICATION_CONFIG = {
2444
+ signal: true,
2445
+ risk: true,
2446
+ info: true,
2447
+ breakeven: true,
2448
+ common_error: true,
2449
+ critical_error: true,
2450
+ validation_error: true,
2451
+ partial_loss: false,
2452
+ partial_profit: false,
2453
+ signal_sync: false,
2454
+ strategy_commit: true,
2455
+ };
2435
2456
  class SetupUtils {
2436
2457
  constructor() {
2437
2458
  this.enable = singleshot(() => {
2438
2459
  cli.loggerService.debug("SetupUtils enable");
2460
+ Notification.enable(NOTIFICATION_CONFIG);
2439
2461
  {
2440
2462
  Recent.enable();
2441
2463
  Storage.enable();
2442
- Notification.enable();
2443
2464
  }
2444
2465
  {
2445
2466
  Markdown.enable();
@@ -2474,6 +2495,23 @@ class SetupUtils {
2474
2495
  return;
2475
2496
  }
2476
2497
  this.enable.clear();
2498
+ {
2499
+ Recent.disable();
2500
+ Storage.disable();
2501
+ Notification.disable();
2502
+ }
2503
+ {
2504
+ Markdown.disable();
2505
+ Report.disable();
2506
+ Dump.disable();
2507
+ Memory.disable();
2508
+ }
2509
+ {
2510
+ Markdown.clear();
2511
+ Report.clear();
2512
+ MarkdownWriter.clear();
2513
+ ReportWriter.clear();
2514
+ }
2477
2515
  {
2478
2516
  PersistSignalAdapter.clear();
2479
2517
  PersistRiskAdapter.clear();
@@ -2493,8 +2531,6 @@ class SetupUtils {
2493
2531
  Dump.clear();
2494
2532
  Log.clear();
2495
2533
  Markdown.clear();
2496
- Memory.clear();
2497
- Report.clear();
2498
2534
  }
2499
2535
  {
2500
2536
  StorageLive.clear();
@@ -2546,14 +2582,14 @@ setConfig({
2546
2582
  CC_WALKER_MARKDOWN_TOP_N: 10,
2547
2583
  });
2548
2584
 
2549
- const MODES = ["backtest", "walker", "paper", "live", "pine", "dump", "init", "help", "version"];
2585
+ const MODES = ["backtest", "walker", "paper", "live", "pine", "dump", "flush", "init", "help", "version"];
2550
2586
  const ENTRY_PATH$1 = "./node_modules/@backtest-kit/cli/build/index.mjs";
2551
2587
  const HELP_TEXT$1 = `
2552
2588
  Example:
2553
2589
 
2554
2590
  node ${ENTRY_PATH$1} --help
2555
2591
  `.trimStart();
2556
- const main$b = async () => {
2592
+ const main$c = async () => {
2557
2593
  if (!getEntry(import.meta.url)) {
2558
2594
  return;
2559
2595
  }
@@ -2561,19 +2597,48 @@ const main$b = async () => {
2561
2597
  if (MODES.some((mode) => values[mode])) {
2562
2598
  return;
2563
2599
  }
2564
- process.stdout.write(`@backtest-kit/cli ${"6.13.0"}\n`);
2600
+ process.stdout.write(`@backtest-kit/cli ${"6.15.0"}\n`);
2565
2601
  process.stdout.write("\n");
2566
2602
  process.stdout.write(`Run with --help to see available commands.\n`);
2567
2603
  process.stdout.write("\n");
2568
2604
  process.stdout.write(HELP_TEXT$1);
2569
2605
  process.exit(0);
2570
2606
  };
2571
- main$b();
2607
+ main$c();
2572
2608
 
2573
2609
  const notifyShutdown = singleshot(async () => {
2574
2610
  console.log("Graceful shutdown initiated. Press Ctrl+C again to force quit.");
2575
2611
  });
2576
2612
 
2613
+ const FLUSH_DIRS = ["report", "log", "markdown", "agent"];
2614
+ const flush = async (entryPoint) => {
2615
+ const moduleRoot = dirname(resolve(process.cwd(), entryPoint));
2616
+ const dumpDir = join(moduleRoot, "dump");
2617
+ for (const dir of FLUSH_DIRS) {
2618
+ const target = join(dumpDir, dir);
2619
+ await rm(target, { recursive: true, force: true });
2620
+ console.log(`Removed: ${target}`);
2621
+ }
2622
+ };
2623
+ const main$b = async () => {
2624
+ if (!getEntry(import.meta.url)) {
2625
+ return;
2626
+ }
2627
+ const { values } = getArgs();
2628
+ if (!values.flush) {
2629
+ return;
2630
+ }
2631
+ const entryPoints = getPositionals();
2632
+ if (!entryPoints.length) {
2633
+ throw new Error("Entry point is required");
2634
+ }
2635
+ for (const entryPoint of entryPoints) {
2636
+ await flush(entryPoint);
2637
+ }
2638
+ process.exit(0);
2639
+ };
2640
+ main$b();
2641
+
2577
2642
  const BEFORE_EXIT_FN$5 = singleshot(async () => {
2578
2643
  process.off("SIGINT", BEFORE_EXIT_FN$5);
2579
2644
  const [running = null] = await Backtest.list();
@@ -2602,6 +2667,10 @@ const main$a = async () => {
2602
2667
  if (!values.backtest) {
2603
2668
  return;
2604
2669
  }
2670
+ if (!values.noFlush) {
2671
+ const [entryPoint = null] = getPositionals();
2672
+ entryPoint && await flush(entryPoint);
2673
+ }
2605
2674
  await cli.backtestMainService.connect();
2606
2675
  listenGracefulShutdown$5();
2607
2676
  };
@@ -2631,6 +2700,11 @@ const main$9 = async () => {
2631
2700
  if (!values.walker) {
2632
2701
  return;
2633
2702
  }
2703
+ if (!values.noFlush) {
2704
+ for (const entryPoint of getPositionals()) {
2705
+ await flush(entryPoint);
2706
+ }
2707
+ }
2634
2708
  listenGracefulShutdown$4();
2635
2709
  await cli.walkerMainService.connect();
2636
2710
  };
@@ -3016,6 +3090,7 @@ Modes:
3016
3090
  --live <entry> Live trading with real orders
3017
3091
  --pine <entry> Execute a local .pine indicator file
3018
3092
  --dump Fetch and save raw OHLCV candles
3093
+ --flush <entry...> Delete report/log/markdown/agent folders from strategy dump dir
3019
3094
  --init Scaffold a new project in the current directory
3020
3095
  --help Print this help message
3021
3096
 
@@ -3027,6 +3102,7 @@ Backtest flags:
3027
3102
  --frame <string> Frame name from addFrameSchema (default: first registered)
3028
3103
  --cacheInterval <string> Comma-separated intervals to pre-cache (default: "1m, 15m, 30m, 4h")
3029
3104
  --noCache Skip candle cache warming before the run
3105
+ --noFlush Skip removing report/log/markdown/agent folders before backtest run
3030
3106
  --verbose Log every candle fetch to stdout
3031
3107
  --ui Start web dashboard at http://localhost:60050
3032
3108
  --telegram Send trade notifications to Telegram
@@ -3036,6 +3112,7 @@ Walker flags (--walker):
3036
3112
  --symbol <string> Trading pair (default: BTCUSDT)
3037
3113
  --cacheInterval <string> Comma-separated intervals to pre-cache (default: "1m, 15m, 30m, 4h")
3038
3114
  --noCache Skip candle cache warming before the run
3115
+ --noFlush Skip removing report/log/markdown/agent folders before walker run
3039
3116
  --verbose Log every candle fetch to stdout
3040
3117
  --output <string> Output file base name (default: walker_{SYMBOL}_{TIMESTAMP})
3041
3118
  --json Save results as JSON to ./dump/<output>.json
@@ -3085,6 +3162,13 @@ Candle dump flags (--dump):
3085
3162
 
3086
3163
  Module file ./modules/dump.module is loaded automatically if it exists.
3087
3164
 
3165
+ Flush flags (--flush):
3166
+
3167
+ One or more positional entry points. For each entry point the following
3168
+ subdirectories are removed from <entry-dir>/dump/:
3169
+
3170
+ report log markdown agent
3171
+
3088
3172
  Init flags (--init):
3089
3173
 
3090
3174
  --output <string> Target directory name (default: backtest-kit-project)
@@ -3100,6 +3184,8 @@ Module hooks (loaded automatically by each mode):
3100
3184
  modules/pine.module --pine Exchange schema for PineScript runs
3101
3185
  modules/dump.module --dump Exchange schema for candle dumps
3102
3186
 
3187
+ --flush has no associated module. It only removes dump subdirectories.
3188
+
3103
3189
  Extensions .ts, .mjs, .cjs are tried automatically. Missing module = soft warning.
3104
3190
 
3105
3191
  Environment variables:
@@ -3112,13 +3198,15 @@ Environment variables:
3112
3198
  Examples:
3113
3199
 
3114
3200
  node ${ENTRY_PATH} --backtest ./content/feb_2026.strategy.ts
3115
- node ${ENTRY_PATH} --backtest --symbol BTCUSDT --noCache --ui ./content/feb_2026.strategy.ts
3201
+ node ${ENTRY_PATH} --backtest --symbol BTCUSDT --noCache --noFlush --ui ./content/feb_2026.strategy.ts
3116
3202
  node ${ENTRY_PATH} --walker ./content/feb_2026_v1.strategy.ts ./content/feb_2026_v2.strategy.ts ./content/feb_2026_v3.strategy.ts
3117
- node ${ENTRY_PATH} --walker --symbol BTCUSDT --noCache --markdown ./content/feb_2026_v1.ts ./content/feb_2026_v2.ts
3203
+ node ${ENTRY_PATH} --walker --symbol BTCUSDT --noCache --noFlush --markdown ./content/feb_2026_v1.ts ./content/feb_2026_v2.ts
3118
3204
  node ${ENTRY_PATH} --paper --symbol ETHUSDT ./content/feb_2026.strategy.ts
3119
3205
  node ${ENTRY_PATH} --live --ui --telegram ./content/feb_2026.strategy.ts
3120
3206
  node ${ENTRY_PATH} --pine ./math/feb_2026.pine --timeframe 15m --limit 500 --jsonl
3121
3207
  node ${ENTRY_PATH} --dump --symbol BTCUSDT --timeframe 15m --limit 500 --jsonl
3208
+ node ${ENTRY_PATH} --flush ./content/feb_2026.strategy/feb_2026.strategy.ts
3209
+ node ${ENTRY_PATH} --flush ./content/feb_2026.strategy/feb_2026.strategy.ts ./content/feb_2026.strategy/feb_2026.test.ts
3122
3210
  node ${ENTRY_PATH} --init --output my-trading-bot
3123
3211
  `.trimStart();
3124
3212
  const main$1 = async () => {
@@ -3129,7 +3217,7 @@ const main$1 = async () => {
3129
3217
  if (!values.help) {
3130
3218
  return;
3131
3219
  }
3132
- process.stdout.write(`@backtest-kit/cli ${"6.13.0"}\n\n`);
3220
+ process.stdout.write(`@backtest-kit/cli ${"6.15.0"}\n\n`);
3133
3221
  process.stdout.write(HELP_TEXT);
3134
3222
  process.exit(0);
3135
3223
  };
@@ -3143,7 +3231,7 @@ const main = async () => {
3143
3231
  if (!values.version) {
3144
3232
  return;
3145
3233
  }
3146
- process.stdout.write(`@backtest-kit/cli ${"6.13.0"}\n`);
3234
+ process.stdout.write(`@backtest-kit/cli ${"6.15.0"}\n`);
3147
3235
  process.exit(0);
3148
3236
  };
3149
3237
  main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backtest-kit/cli",
3
- "version": "6.13.0",
3
+ "version": "6.15.0",
4
4
  "description": "Zero-boilerplate CLI runner for backtest-kit strategies. Run backtests, paper trading, and live bots with candle cache warming, web dashboard, and Telegram notifications — no setup code required.",
5
5
  "author": {
6
6
  "name": "Petr Tripolsky",
@@ -61,11 +61,11 @@
61
61
  "devDependencies": {
62
62
  "@babel/plugin-transform-modules-umd": "7.27.1",
63
63
  "@babel/standalone": "7.29.1",
64
- "@backtest-kit/ui": "6.13.0",
65
- "@backtest-kit/graph": "6.13.0",
66
- "@backtest-kit/ollama": "6.13.0",
67
- "@backtest-kit/pinets": "6.13.0",
68
- "@backtest-kit/signals": "6.13.0",
64
+ "@backtest-kit/ui": "6.15.0",
65
+ "@backtest-kit/graph": "6.15.0",
66
+ "@backtest-kit/ollama": "6.15.0",
67
+ "@backtest-kit/pinets": "6.15.0",
68
+ "@backtest-kit/signals": "6.15.0",
69
69
  "@rollup/plugin-replace": "6.0.3",
70
70
  "@rollup/plugin-typescript": "11.1.6",
71
71
  "@types/image-size": "0.7.0",
@@ -73,7 +73,7 @@
73
73
  "@types/mustache": "4.2.6",
74
74
  "@types/node": "22.9.0",
75
75
  "@types/stack-trace": "0.0.33",
76
- "backtest-kit": "6.13.0",
76
+ "backtest-kit": "6.15.0",
77
77
  "glob": "11.0.1",
78
78
  "markdown-it": "14.1.1",
79
79
  "rimraf": "6.0.1",
@@ -88,12 +88,12 @@
88
88
  "peerDependencies": {
89
89
  "@babel/plugin-transform-modules-umd": "^7.27.1",
90
90
  "@babel/standalone": "^7.29.1",
91
- "@backtest-kit/ui": "^6.13.0",
92
- "@backtest-kit/graph": "^6.13.0",
93
- "@backtest-kit/ollama": "^6.13.0",
94
- "@backtest-kit/pinets": "^6.13.0",
95
- "@backtest-kit/signals": "^6.13.0",
96
- "backtest-kit": "^6.13.0",
91
+ "@backtest-kit/ui": "^6.15.0",
92
+ "@backtest-kit/graph": "^6.15.0",
93
+ "@backtest-kit/ollama": "^6.15.0",
94
+ "@backtest-kit/pinets": "^6.15.0",
95
+ "@backtest-kit/signals": "^6.15.0",
96
+ "backtest-kit": "^6.15.0",
97
97
  "markdown-it": "^14.1.1",
98
98
  "typescript": "^5.0.0"
99
99
  },
@@ -102,7 +102,7 @@
102
102
  "di-kit": "1.1.1",
103
103
  "di-scoped": "1.0.21",
104
104
  "dotenv": "17.3.1",
105
- "functools-kit": "2.0.2",
105
+ "functools-kit": "2.2.0",
106
106
  "get-moment-stamp": "1.1.2",
107
107
  "image-size": "1.1.1",
108
108
  "jsdom": "26.1.0",
@@ -12,13 +12,13 @@
12
12
  "license": "ISC",
13
13
  "type": "commonjs",
14
14
  "dependencies": {
15
- "@backtest-kit/cli": "^6.13.0",
16
- "@backtest-kit/graph": "^6.13.0",
17
- "@backtest-kit/pinets": "^6.13.0",
18
- "@backtest-kit/ui": "^6.13.0",
19
- "agent-swarm-kit": "^2.2.0",
20
- "backtest-kit": "^6.13.0",
21
- "functools-kit": "^2.0.2",
15
+ "@backtest-kit/cli": "^6.15.0",
16
+ "@backtest-kit/graph": "^6.15.0",
17
+ "@backtest-kit/pinets": "^6.15.0",
18
+ "@backtest-kit/ui": "^6.15.0",
19
+ "agent-swarm-kit": "^2.5.0",
20
+ "backtest-kit": "^6.15.0",
21
+ "functools-kit": "^2.2.0",
22
22
  "garch": "^1.2.3",
23
23
  "get-moment-stamp": "^1.1.2",
24
24
  "ollama": "^0.6.3",