@backtest-kit/cli 5.10.0 → 5.10.1

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
@@ -450,9 +450,10 @@ For projects that compile to or use CommonJS. Loaded via `require()`:
450
450
  | `--limit` | string | Number of candles to fetch (default: `250`) |
451
451
  | `--when` | string | End date for candle window — ISO 8601 or Unix ms (default: now) |
452
452
  | `--exchange` | string | Exchange name (default: first registered, falls back to CCXT Binance) |
453
- | `--json` | string | Write plots as a JSON array to a file (e.g. `--json=./output.json`) |
454
- | `--jsonl` | string | Write plots as JSONL (one row per line) to a file (e.g. `--jsonl=./output.jsonl`) |
455
- | `--markdown` | string | Write Markdown table to a file (e.g. `--markdown=./output.md`) |
453
+ | `--output` | string | Output file base name without extension (default: `.pine` file name) |
454
+ | `--json` | boolean | Write plots as a JSON array to `<pine-dir>/dump/{output}.json` |
455
+ | `--jsonl` | boolean | Write plots as JSONL (one row per line) to `<pine-dir>/dump/{output}.jsonl` |
456
+ | `--markdown` | boolean | Write Markdown table to `<pine-dir>/dump/{output}.md` |
456
457
 
457
458
  **Important:** `limit` must cover indicator warmup bars — rows before warmup completes will show `N/A`
458
459
 
@@ -470,7 +471,7 @@ The CLI looks for `modules/pine.module` in two locations (first match wins):
470
471
  ```
471
472
  my-project/
472
473
  ├── math/
473
- │ ├── master_trend_15m.pine ← indicator
474
+ │ ├── impulse_trend_15m.pine ← indicator
474
475
  │ └── modules/
475
476
  │ └── pine.module.ts ← loaded first (next to .pine file)
476
477
  ├── modules/
@@ -507,7 +508,7 @@ Before loading `pine.module`, the CLI loads `.env` files in the same order as fo
507
508
  my-project/
508
509
  ├── math/
509
510
  │ ├── .env ← loaded second (overrides root)
510
- │ └── master_trend_15m.pine
511
+ │ └── impulse_trend_15m.pine
511
512
  ├── .env ← loaded first
512
513
  └── package.json
513
514
  ```
@@ -538,7 +539,7 @@ addExchangeSchema({
538
539
  Then run:
539
540
 
540
541
  ```bash
541
- npx @backtest-kit/cli --pine ./math/master_trend_15m.pine \
542
+ npx @backtest-kit/cli --pine ./math/impulse_trend_15m.pine \
542
543
  --exchange my-exchange \
543
544
  --symbol BTCUSDT \
544
545
  --timeframe 15m \
@@ -551,7 +552,7 @@ Or add it to `package.json`:
551
552
  ```json
552
553
  {
553
554
  "scripts": {
554
- "pine": "npx @backtest-kit/cli --pine ./math/master_trend_15m.pine --symbol BTCUSDT --timeframe 15m --limit 180"
555
+ "pine": "npx @backtest-kit/cli --pine ./math/impulse_trend_15m.pine --symbol BTCUSDT --timeframe 15m --limit 180"
555
556
  }
556
557
  }
557
558
  ```
@@ -593,10 +594,23 @@ The CLI prints a Markdown table to stdout:
593
594
  | 112653.90 | 1.0000 | 2025-09-22T22:15:00.000Z |
594
595
  ```
595
596
 
596
- Redirect to a file to save the report:
597
+ Save to `./math/dump/impulse_trend_15m.md` (uses `.pine` file name automatically, dump is created next to the `.pine` file):
597
598
 
598
599
  ```bash
599
- npm run pine > report.md
600
+ npx @backtest-kit/cli --pine ./math/impulse_trend_15m.pine --markdown
601
+ ```
602
+
603
+ Override the output name with `--output`:
604
+
605
+ ```bash
606
+ npx @backtest-kit/cli --pine ./math/impulse_trend_15m.pine --jsonl --output feb2026_bb
607
+ # → ./math/dump/feb2026_bb.jsonl
608
+ ```
609
+
610
+ Print to stdout (no flag):
611
+
612
+ ```bash
613
+ npx @backtest-kit/cli --pine ./math/impulse_trend_15m.pine
600
614
  ```
601
615
 
602
616
  ## 🌍 Environment Variables
package/build/index.cjs CHANGED
@@ -519,17 +519,21 @@ const getArgs = functoolsKit.singleshot(() => {
519
519
  type: "string",
520
520
  default: "",
521
521
  },
522
- json: {
522
+ output: {
523
523
  type: "string",
524
524
  default: "",
525
525
  },
526
+ json: {
527
+ type: "boolean",
528
+ default: false,
529
+ },
526
530
  jsonl: {
527
- type: "string",
528
- default: "",
531
+ type: "boolean",
532
+ default: false,
529
533
  },
530
534
  markdown: {
531
- type: "string",
532
- default: "",
535
+ type: "boolean",
536
+ default: false,
533
537
  },
534
538
  },
535
539
  strict: false,
@@ -2380,21 +2384,23 @@ const main = async () => {
2380
2384
  return true;
2381
2385
  }))
2382
2386
  .map((key) => [key, key]));
2383
- const jsonPath = values.json;
2384
- if (jsonPath) {
2387
+ const dumpName = values.output || path.basename(entryPoint, path.extname(entryPoint));
2388
+ const dumpDir = path.join(process.cwd(), "dump");
2389
+ if (values.json) {
2385
2390
  const rows = EXTRACT_ROWS_FN(plots, signalSchema);
2386
- await fs$1.writeFile(jsonPath, JSON.stringify(rows, null, 2), "utf-8");
2391
+ await fs$1.mkdir(dumpDir, { recursive: true });
2392
+ await fs$1.writeFile(path.join(dumpDir, `${dumpName}.json`), JSON.stringify(rows, null, 2), "utf-8");
2387
2393
  return;
2388
2394
  }
2389
- const jsonlPath = values.jsonl;
2390
- if (jsonlPath) {
2395
+ if (values.jsonl) {
2391
2396
  const rows = EXTRACT_ROWS_FN(plots, signalSchema);
2392
- await fs$1.writeFile(jsonlPath, rows.map((r) => JSON.stringify(r)).join("\n"), "utf-8");
2397
+ await fs$1.mkdir(dumpDir, { recursive: true });
2398
+ await fs$1.writeFile(path.join(dumpDir, `${dumpName}.jsonl`), rows.map((r) => JSON.stringify(r)).join("\n"), "utf-8");
2393
2399
  return;
2394
2400
  }
2395
- const markdownPath = values.markdown;
2396
- if (markdownPath) {
2397
- await fs$1.writeFile(markdownPath, await BacktestKitPinets.toMarkdown(signalId, plots, signalSchema), "utf-8");
2401
+ if (values.markdown) {
2402
+ await fs$1.mkdir(dumpDir, { recursive: true });
2403
+ await fs$1.writeFile(path.join(dumpDir, `${dumpName}.md`), await BacktestKitPinets.toMarkdown(signalId, plots, signalSchema), "utf-8");
2398
2404
  return;
2399
2405
  }
2400
2406
  console.log(await BacktestKitPinets.toMarkdown(signalId, plots, signalSchema));
package/build/index.mjs CHANGED
@@ -4,8 +4,8 @@ import { Storage, Notification, Markdown, Report, Dump, Memory, StorageLive, Sto
4
4
  import { getErrorMessage, errorData, singleshot, str, BehaviorSubject, compose, execpool, queued, sleep, randomString, createAwaiter, 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 from 'path';
8
- import fs$1, { access, readFile, writeFile } from 'fs/promises';
7
+ import path, { basename, extname, join } from 'path';
8
+ import fs$1, { access, readFile, mkdir, writeFile } from 'fs/promises';
9
9
  import dotenv from 'dotenv';
10
10
  import { createActivator } from 'di-kit';
11
11
  import { fileURLToPath } from 'url';
@@ -494,17 +494,21 @@ const getArgs = singleshot(() => {
494
494
  type: "string",
495
495
  default: "",
496
496
  },
497
- json: {
497
+ output: {
498
498
  type: "string",
499
499
  default: "",
500
500
  },
501
+ json: {
502
+ type: "boolean",
503
+ default: false,
504
+ },
501
505
  jsonl: {
502
- type: "string",
503
- default: "",
506
+ type: "boolean",
507
+ default: false,
504
508
  },
505
509
  markdown: {
506
- type: "string",
507
- default: "",
510
+ type: "boolean",
511
+ default: false,
508
512
  },
509
513
  },
510
514
  strict: false,
@@ -2351,21 +2355,23 @@ const main = async () => {
2351
2355
  return true;
2352
2356
  }))
2353
2357
  .map((key) => [key, key]));
2354
- const jsonPath = values.json;
2355
- if (jsonPath) {
2358
+ const dumpName = values.output || basename(entryPoint, extname(entryPoint));
2359
+ const dumpDir = join(process.cwd(), "dump");
2360
+ if (values.json) {
2356
2361
  const rows = EXTRACT_ROWS_FN(plots, signalSchema);
2357
- await writeFile(jsonPath, JSON.stringify(rows, null, 2), "utf-8");
2362
+ await mkdir(dumpDir, { recursive: true });
2363
+ await writeFile(join(dumpDir, `${dumpName}.json`), JSON.stringify(rows, null, 2), "utf-8");
2358
2364
  return;
2359
2365
  }
2360
- const jsonlPath = values.jsonl;
2361
- if (jsonlPath) {
2366
+ if (values.jsonl) {
2362
2367
  const rows = EXTRACT_ROWS_FN(plots, signalSchema);
2363
- await writeFile(jsonlPath, rows.map((r) => JSON.stringify(r)).join("\n"), "utf-8");
2368
+ await mkdir(dumpDir, { recursive: true });
2369
+ await writeFile(join(dumpDir, `${dumpName}.jsonl`), rows.map((r) => JSON.stringify(r)).join("\n"), "utf-8");
2364
2370
  return;
2365
2371
  }
2366
- const markdownPath = values.markdown;
2367
- if (markdownPath) {
2368
- await writeFile(markdownPath, await toMarkdown(signalId, plots, signalSchema), "utf-8");
2372
+ if (values.markdown) {
2373
+ await mkdir(dumpDir, { recursive: true });
2374
+ await writeFile(join(dumpDir, `${dumpName}.md`), await toMarkdown(signalId, plots, signalSchema), "utf-8");
2369
2375
  return;
2370
2376
  }
2371
2377
  console.log(await toMarkdown(signalId, plots, signalSchema));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backtest-kit/cli",
3
- "version": "5.10.0",
3
+ "version": "5.10.1",
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",