@backtest-kit/cli 7.3.1 → 7.5.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
@@ -44,6 +44,7 @@ Point the CLI at your strategy file, choose a mode, and it handles exchange conn
44
44
  | **PineScript** | `--pine` | Run a local `.pine` indicator against exchange data |
45
45
  | **Pine Editor** | `--editor` | Open the visual Pine Script editor in the browser |
46
46
  | **Candle Dump** | `--dump` | Fetch and save raw OHLCV candles to a file |
47
+ | **PnL Debug** | `--pnldebug` | Simulate per-minute PnL for a given entry price and direction |
47
48
  | **Flush** | `--flush` | Delete report/log/markdown/agent folders from strategy dump dir |
48
49
  | **Init Project** | `--init` | Scaffold a new backtest-kit project |
49
50
 
@@ -509,6 +510,54 @@ Sends formatted HTML messages with 1m / 15m / 1h price charts to your Telegram c
509
510
 
510
511
  Requires `CC_TELEGRAM_TOKEN` and `CC_TELEGRAM_CHANNEL` in your environment.
511
512
 
513
+ #### Telegram Message Adapter (`telegram.config`)
514
+
515
+ By default messages are rendered from Mustache templates (`template/*.mustache`). To override rendering programmatically, create a `config/telegram.config` file and export an object with any subset of `get*Markdown` methods. Each method receives the event payload and must return a `Promise<string>` with the Markdown message body.
516
+
517
+ Resolution order is the same as other configs (strategy dir → project root → package default).
518
+
519
+ ```ts
520
+ // config/telegram.config.ts
521
+ import {
522
+ IStrategyTickResultOpened,
523
+ IStrategyTickResultClosed,
524
+ RiskContract,
525
+ } from "backtest-kit";
526
+
527
+ export default {
528
+ async getOpenedMarkdown(event: IStrategyTickResultOpened): Promise<string> {
529
+ return `**Opened** ${event.symbol} at ${event.priceOpen}`;
530
+ },
531
+ async getClosedMarkdown(event: IStrategyTickResultClosed): Promise<string> {
532
+ return `**Closed** ${event.symbol} at ${event.priceClosed}`;
533
+ },
534
+ async getRiskMarkdown(event: RiskContract): Promise<string> {
535
+ return `**Risk rejected** ${event.symbol}`;
536
+ },
537
+ };
538
+ ```
539
+
540
+ All methods are optional — unimplemented ones fall back to the Mustache template.
541
+
542
+ | Method | Event type |
543
+ |--------|------------|
544
+ | `getOpenedMarkdown` | `IStrategyTickResultOpened` |
545
+ | `getClosedMarkdown` | `IStrategyTickResultClosed` |
546
+ | `getScheduledMarkdown` | `IStrategyTickResultScheduled` |
547
+ | `getCancelledMarkdown` | `IStrategyTickResultCancelled` |
548
+ | `getRiskMarkdown` | `RiskContract` |
549
+ | `getPartialProfitMarkdown` | `PartialProfitCommit` |
550
+ | `getPartialLossMarkdown` | `PartialLossCommit` |
551
+ | `getBreakevenMarkdown` | `BreakevenCommit` |
552
+ | `getTrailingTakeMarkdown` | `TrailingTakeCommit` |
553
+ | `getTrailingStopMarkdown` | `TrailingStopCommit` |
554
+ | `getAverageBuyMarkdown` | `AverageBuyCommit` |
555
+ | `getSignalOpenMarkdown` | `SignalOpenContract` |
556
+ | `getSignalCloseMarkdown` | `SignalCloseContract` |
557
+ | `getCancelScheduledMarkdown` | `CancelScheduledCommit` |
558
+ | `getClosePendingMarkdown` | `ClosePendingCommit` |
559
+ | `getSignalInfoMarkdown` | `SignalInfoContract` |
560
+
512
561
  ## 🧩 Module Hooks (Broker Adapter)
513
562
 
514
563
  The CLI supports **mode-specific module files** that are loaded as side-effect imports before the strategy starts. Each file is expected to call `Broker.useBrokerAdapter()` from `backtest-kit` to register a broker adapter.
@@ -1017,6 +1066,110 @@ Or add it to `package.json`:
1017
1066
  npx @backtest-kit/cli --dump --symbol BTCUSDT --timeframe 15m --limit 500 --jsonl
1018
1067
  ```
1019
1068
 
1069
+ ## 🐞 PnL Debug (`--pnldebug`)
1070
+
1071
+ `@backtest-kit/cli` can simulate a hypothetical position minute by minute and print running PnL, peak profit, and maximum drawdown for each candle — without placing any trades or loading a strategy file.
1072
+
1073
+ ### CLI Flags
1074
+
1075
+ | Flag | Type | Description |
1076
+ |------|------|-------------|
1077
+ | `--pnldebug` | boolean | Enable PnL debug mode |
1078
+ | `--priceopen` | number | Entry price (required) |
1079
+ | `--direction` | string | `long` or `short` (default: `long`) |
1080
+ | `--when` | string | Start timestamp — ISO 8601 or Unix ms (default: now) |
1081
+ | `--minutes` | string | Number of 1m candles to simulate (default: `60`) |
1082
+ | `--symbol` | string | Trading pair (default: `"BTCUSDT"`) |
1083
+ | `--exchange` | string | Exchange name (default: first registered, falls back to CCXT Binance) |
1084
+ | `--output` | string | Output file base name (default: `{SYMBOL}_{DIRECTION}_{PRICEOPEN}_{TIMESTAMP}`) |
1085
+ | `--json` | boolean | Save results as JSON array to `./dump/<output>.json` |
1086
+ | `--jsonl` | boolean | Save results as JSONL to `./dump/<output>.jsonl` |
1087
+ | `--markdown` | boolean | Save results as Markdown table to `./dump/<output>.md` |
1088
+
1089
+ ### Output columns
1090
+
1091
+ | Column | Description |
1092
+ |--------|-------------|
1093
+ | `min` | Minute offset from start (1-based) |
1094
+ | `timestamp` | Candle timestamp (ISO 8601) |
1095
+ | `close` | Candle close price |
1096
+ | `pnl%` | Running PnL vs entry price (signed %) |
1097
+ | `peak%` | Highest PnL reached so far (always ≥ 0) |
1098
+ | `drawdown%` | Lowest PnL reached so far (always ≤ 0) |
1099
+
1100
+ ### Exchange via `pnldebug.module`
1101
+
1102
+ By default the CLI registers CCXT Binance automatically. To use a different exchange, create a `modules/pnldebug.module.ts` file in the current working directory — the CLI loads it automatically before fetching candles.
1103
+
1104
+ ```typescript
1105
+ // modules/pnldebug.module.ts
1106
+ import { addExchangeSchema } from "backtest-kit";
1107
+ import ccxt from "ccxt";
1108
+
1109
+ addExchangeSchema({
1110
+ exchangeName: "my-exchange",
1111
+ getCandles: async (symbol, interval, since, limit) => {
1112
+ const exchange = new ccxt.bybit({ enableRateLimit: true });
1113
+ const ohlcv = await exchange.fetchOHLCV(symbol, interval, since.getTime(), limit);
1114
+ return ohlcv.map(([timestamp, open, high, low, close, volume]) => ({
1115
+ timestamp, open, high, low, close, volume,
1116
+ }));
1117
+ },
1118
+ formatPrice: (symbol, price) => price.toFixed(2),
1119
+ formatQuantity: (symbol, quantity) => quantity.toFixed(8),
1120
+ });
1121
+ ```
1122
+
1123
+ ### Usage
1124
+
1125
+ Print to stdout (default table format):
1126
+
1127
+ ```bash
1128
+ npx @backtest-kit/cli --pnldebug --symbol BTCUSDT --priceopen 64069.50 --direction short --when "2025-02-25" --minutes 120
1129
+ ```
1130
+
1131
+ Save as Markdown:
1132
+
1133
+ ```bash
1134
+ npx @backtest-kit/cli --pnldebug --priceopen 67956.73 --direction long --when 1772064000000 --minutes 60 --markdown
1135
+ # → ./dump/BTCUSDT_long_67956.73_{timestamp}.md
1136
+ ```
1137
+
1138
+ Override the output file name with `--output`:
1139
+
1140
+ ```bash
1141
+ npx @backtest-kit/cli --pnldebug --priceopen 64069.50 --direction short --when "2025-02-25" --minutes 120 \
1142
+ --jsonl --output feb25_short_debug
1143
+ # → ./dump/feb25_short_debug.jsonl
1144
+ ```
1145
+
1146
+ Or add it to `package.json`:
1147
+
1148
+ ```json
1149
+ {
1150
+ "scripts": {
1151
+ "pnldebug": "npx @backtest-kit/cli --pnldebug --symbol BTCUSDT --priceopen 64069.50 --direction short --when \"2025-02-25\" --minutes 120"
1152
+ }
1153
+ }
1154
+ ```
1155
+
1156
+ ```bash
1157
+ npm run pnldebug
1158
+ ```
1159
+
1160
+ ### Example stdout output
1161
+
1162
+ ```
1163
+ Symbol: BTCUSDT | Direction: short | PriceOpen: 64069.50 | From: 2025-02-25T00:00:00.000Z | Minutes: 120
1164
+
1165
+ min | timestamp | close | pnl% | peak% | drawdown%
1166
+ -----------------------------------------------------------------------------------
1167
+ 1 | 2025-02-25T00:01:00.000Z | 64020.10 | +0.08% | +0.08% | 0.00%
1168
+ 2 | 2025-02-25T00:02:00.000Z | 64105.30 | -0.06% | +0.08% | -0.06%
1169
+ ...
1170
+ 120 | 2025-02-25T02:00:00.000Z | 63200.00 | +1.36% | +1.36% | -0.06%
1171
+ ```
1172
+
1020
1173
  ## 🗑️ Flushing Strategy Output (`--flush`)
1021
1174
 
1022
1175
  `@backtest-kit/cli` can delete generated output folders from one or more strategy dump directories without touching cached candle data.