@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 +153 -0
- package/build/index.cjs +296 -26
- package/build/index.mjs +297 -27
- package/package.json +13 -13
- package/template/project/package.mustache +5 -5
- package/template/signal-info.mustache +20 -20
- package/types.d.ts +35 -15
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.
|