@backtest-kit/cli 0.0.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 +447 -0
- package/build/index.cjs +1872 -0
- package/build/index.mjs +1849 -0
- package/package.json +89 -0
- package/template/breakeven.mustache +14 -0
- package/template/cancelled.mustache +14 -0
- package/template/closed.mustache +15 -0
- package/template/opened.mustache +15 -0
- package/template/partial-loss.mustache +15 -0
- package/template/partial-profit.mustache +15 -0
- package/template/risk.mustache +18 -0
- package/template/scheduled.mustache +15 -0
- package/template/trailing-stop.mustache +15 -0
- package/template/trailing-take.mustache +15 -0
- package/types.d.ts +228 -0
package/README.md
ADDED
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
<img src="https://github.com/tripolskypetr/backtest-kit/raw/refs/heads/master/assets/square_compasses.svg" height="45px" align="right">
|
|
2
|
+
|
|
3
|
+
# 🧿 @backtest-kit/cli
|
|
4
|
+
|
|
5
|
+
> Zero-boilerplate CLI for launching backtests, paper trading, and live trading. Run any backtest-kit strategy from the command line — no setup code required.
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
[](https://deepwiki.com/tripolskypetr/backtest-kit)
|
|
10
|
+
[](https://npmjs.org/package/@backtest-kit/cli)
|
|
11
|
+
[]()
|
|
12
|
+
|
|
13
|
+
Point the CLI at your strategy file, choose a mode, and it handles exchange connectivity, candle caching, UI dashboard, and Telegram notifications for you.
|
|
14
|
+
|
|
15
|
+
📚 **[Backtest Kit Docs](https://backtest-kit.github.io/documents/example_02_first_backtest.html)** | 🌟 **[GitHub](https://github.com/tripolskypetr/backtest-kit)**
|
|
16
|
+
|
|
17
|
+
## ✨ Features
|
|
18
|
+
|
|
19
|
+
- 🚀 **Zero Config**: Run `npx @backtest-kit/cli --backtest ./strategy.mjs` — no boilerplate needed
|
|
20
|
+
- 🔄 **Three Modes**: Backtest on historical data, paper trade on live prices, or deploy live bots
|
|
21
|
+
- 💾 **Auto Candle Cache**: Warms OHLCV cache for all required intervals before backtest starts
|
|
22
|
+
- 🌐 **Web Dashboard**: Launch `@backtest-kit/ui` with a single `--ui` flag
|
|
23
|
+
- 📬 **Telegram Alerts**: Send formatted trade notifications with charts via `--telegram`
|
|
24
|
+
- 🔌 **Default Binance**: CCXT Binance exchange schema registered automatically when none is provided
|
|
25
|
+
- 🧩 **Module Hooks**: Drop a `modules/live.module.mjs` file to handle every position lifecycle event
|
|
26
|
+
- 🔑 **Pluggable Logger**: Override the built-in logger with `setLogger()` from your strategy module
|
|
27
|
+
- 🛑 **Graceful Shutdown**: SIGINT stops the active run and cleans up all subscriptions safely
|
|
28
|
+
|
|
29
|
+
## 📋 What It Does
|
|
30
|
+
|
|
31
|
+
`@backtest-kit/cli` wraps the `backtest-kit` engine and resolves all scaffolding automatically:
|
|
32
|
+
|
|
33
|
+
| Mode | Flag | Description |
|
|
34
|
+
|------|------|-------------|
|
|
35
|
+
| **Backtest** | `--backtest` | Run strategy against historical candle data |
|
|
36
|
+
| **Paper** | `--paper` | Simulate live trading using real-time prices (no real orders) |
|
|
37
|
+
| **Live** | `--live` | Execute real trades via exchange API |
|
|
38
|
+
| **UI Dashboard** | `--ui` | Launch interactive web dashboard at `http://localhost:60050` |
|
|
39
|
+
| **Telegram** | `--telegram` | Send signal notifications with price charts to a Telegram channel |
|
|
40
|
+
|
|
41
|
+
## 🚀 Installation
|
|
42
|
+
|
|
43
|
+
Add `@backtest-kit/cli` to your project and wire it up in `package.json` scripts:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm install @backtest-kit/cli
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"scripts": {
|
|
52
|
+
"backtest": "@backtest-kit/cli --backtest ./src/index.mjs",
|
|
53
|
+
"paper": "@backtest-kit/cli --paper ./src/index.mjs",
|
|
54
|
+
"start": "@backtest-kit/cli --live ./src/index.mjs"
|
|
55
|
+
},
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"@backtest-kit/cli": "latest",
|
|
58
|
+
"backtest-kit": "latest",
|
|
59
|
+
"ccxt": "latest"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Or run once without installing:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npx @backtest-kit/cli --backtest ./src/index.mjs
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## 📖 Quick Start
|
|
71
|
+
|
|
72
|
+
Create your strategy entry point (`src/index.mjs`). The file registers schemas via `backtest-kit` — `@backtest-kit/cli` is only the runner:
|
|
73
|
+
|
|
74
|
+
```javascript
|
|
75
|
+
// src/index.mjs
|
|
76
|
+
import { addStrategySchema, addExchangeSchema, addFrameSchema } from 'backtest-kit';
|
|
77
|
+
import ccxt from 'ccxt';
|
|
78
|
+
|
|
79
|
+
// Register exchange
|
|
80
|
+
addExchangeSchema({
|
|
81
|
+
exchangeName: 'binance',
|
|
82
|
+
getCandles: async (symbol, interval, since, limit) => {
|
|
83
|
+
const exchange = new ccxt.binance();
|
|
84
|
+
const ohlcv = await exchange.fetchOHLCV(symbol, interval, since.getTime(), limit);
|
|
85
|
+
return ohlcv.map(([timestamp, open, high, low, close, volume]) => ({
|
|
86
|
+
timestamp, open, high, low, close, volume,
|
|
87
|
+
}));
|
|
88
|
+
},
|
|
89
|
+
formatPrice: (symbol, price) => price.toFixed(2),
|
|
90
|
+
formatQuantity: (symbol, quantity) => quantity.toFixed(8),
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Register frame (backtest only)
|
|
94
|
+
addFrameSchema({
|
|
95
|
+
frameName: 'feb-2024',
|
|
96
|
+
interval: '1m',
|
|
97
|
+
startDate: new Date('2024-02-01'),
|
|
98
|
+
endDate: new Date('2024-02-29'),
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Register strategy
|
|
102
|
+
addStrategySchema({
|
|
103
|
+
strategyName: 'my-strategy',
|
|
104
|
+
interval: '15m',
|
|
105
|
+
getSignal: async (symbol) => {
|
|
106
|
+
// return signal or null
|
|
107
|
+
return null;
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Run a backtest:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
npm run backtest -- --symbol BTCUSDT
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Run with UI dashboard and Telegram:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
npm run backtest -- --symbol BTCUSDT --ui --telegram
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Run live trading:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
npm start -- --symbol BTCUSDT --ui
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## 🎛️ CLI Flags
|
|
131
|
+
|
|
132
|
+
| Flag | Type | Default | Description |
|
|
133
|
+
|------|------|---------|-------------|
|
|
134
|
+
| `--backtest` | boolean | `false` | Run historical backtest |
|
|
135
|
+
| `--paper` | boolean | `false` | Run paper trading (live prices, no real orders) |
|
|
136
|
+
| `--live` | boolean | `false` | Run live trading |
|
|
137
|
+
| `--ui` | boolean | `false` | Start web UI dashboard |
|
|
138
|
+
| `--telegram` | boolean | `false` | Enable Telegram notifications |
|
|
139
|
+
| `--verbose` | boolean | `false` | Log each candle fetch (symbol, interval, since) |
|
|
140
|
+
| `--symbol` | string | `"BTCUSDT"` | Trading pair to run |
|
|
141
|
+
| `--strategy` | string | first registered | Strategy name to use |
|
|
142
|
+
| `--exchange` | string | first registered | Exchange name to use |
|
|
143
|
+
| `--frame` | string | first registered | Backtest frame name |
|
|
144
|
+
| `--cache` | string | `"1m, 15m, 30m, 4h"` | Comma-separated intervals to pre-cache before backtest |
|
|
145
|
+
|
|
146
|
+
**Positional argument (required):** path to your strategy entry point file (set once in `package.json` scripts).
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"scripts": {
|
|
151
|
+
"backtest": "@backtest-kit/cli --backtest ./src/index.mjs"
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## 🏃 Execution Modes
|
|
157
|
+
|
|
158
|
+
### Backtest
|
|
159
|
+
|
|
160
|
+
Runs the strategy against historical candle data using a registered `FrameSchema`.
|
|
161
|
+
|
|
162
|
+
```json
|
|
163
|
+
{
|
|
164
|
+
"scripts": {
|
|
165
|
+
"backtest": "@backtest-kit/cli --backtest --symbol ETHUSDT --strategy my-strategy --exchange binance --frame feb-2024 --cache \"1m, 15m, 1h, 4h\" ./src/index.mjs"
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
npm run backtest
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Before running, the CLI warms the candle cache for every interval in `--cache`. On the next run, cached data is used directly — no API calls needed.
|
|
175
|
+
|
|
176
|
+
### Paper Trading
|
|
177
|
+
|
|
178
|
+
Connects to the live exchange but does not place real orders. Identical code path to live — safe for strategy validation.
|
|
179
|
+
|
|
180
|
+
```json
|
|
181
|
+
{
|
|
182
|
+
"scripts": {
|
|
183
|
+
"paper": "@backtest-kit/cli --paper --symbol BTCUSDT ./src/index.mjs"
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
npm run paper
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Live Trading
|
|
193
|
+
|
|
194
|
+
Deploys a real trading bot. Requires exchange API keys configured in your `.env` or environment.
|
|
195
|
+
|
|
196
|
+
```json
|
|
197
|
+
{
|
|
198
|
+
"scripts": {
|
|
199
|
+
"start": "@backtest-kit/cli --live --ui --telegram --symbol BTCUSDT ./src/index.mjs"
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
npm start
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## 🗂️ Monorepo Usage
|
|
209
|
+
|
|
210
|
+
`@backtest-kit/cli` works out of the box in a monorepo where each strategy lives in its own subdirectory. When the CLI loads your entry point file, it automatically changes the working directory to the file's location — so all relative paths (`dump/`, `modules/`, `template/`) resolve inside that strategy's folder, not the project root.
|
|
211
|
+
|
|
212
|
+
### How It Works
|
|
213
|
+
|
|
214
|
+
Internally, `ResolveService` does the following before executing your entry point:
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
process.chdir(path.dirname(entryPoint)) // cwd → strategy directory
|
|
218
|
+
dotenv.config({ path: rootDir + '/.env' }) // load root .env first
|
|
219
|
+
dotenv.config({ path: strategyDir + '/.env', override: true }) // strategy .env overrides
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Everything that follows — candle cache warming, report generation, module loading, template resolution — uses the new cwd automatically.
|
|
223
|
+
|
|
224
|
+
### Project Structure
|
|
225
|
+
|
|
226
|
+
```
|
|
227
|
+
monorepo/
|
|
228
|
+
├── package.json # root scripts (one per strategy)
|
|
229
|
+
├── .env # shared API keys (exchange, Telegram, etc.)
|
|
230
|
+
└── strategies/
|
|
231
|
+
├── oct_2025/
|
|
232
|
+
│ ├── index.mjs # entry point — registers exchange/frame/strategy schemas
|
|
233
|
+
│ ├── .env # overrides root .env for this strategy (optional)
|
|
234
|
+
│ ├── modules/ # live.module.mjs specific to this strategy
|
|
235
|
+
│ ├── template/ # custom Mustache templates (optional)
|
|
236
|
+
│ └── dump/ # auto-created: candle cache + backtest reports
|
|
237
|
+
└── dec_2025/
|
|
238
|
+
├── index.mjs
|
|
239
|
+
├── .env
|
|
240
|
+
└── dump/
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Root `package.json`
|
|
244
|
+
|
|
245
|
+
```json
|
|
246
|
+
{
|
|
247
|
+
"scripts": {
|
|
248
|
+
"backtest:oct": "@backtest-kit/cli --backtest ./strategies/oct_2025/index.mjs",
|
|
249
|
+
"backtest:dec": "@backtest-kit/cli --backtest ./strategies/dec_2025/index.mjs"
|
|
250
|
+
},
|
|
251
|
+
"dependencies": {
|
|
252
|
+
"@backtest-kit/cli": "latest",
|
|
253
|
+
"backtest-kit": "latest",
|
|
254
|
+
"ccxt": "latest"
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
npm run backtest:oct
|
|
261
|
+
npm run backtest:dec
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Isolated Resources Per Strategy
|
|
265
|
+
|
|
266
|
+
| Resource | Path (relative to strategy dir) | Isolated |
|
|
267
|
+
|----------|----------------------------------|---------|
|
|
268
|
+
| Candle cache | `./dump/data/candle/` | ✅ per-strategy |
|
|
269
|
+
| Backtest reports | `./dump/` | ✅ per-strategy |
|
|
270
|
+
| Live module | `./modules/live.module.mjs` | ✅ per-strategy |
|
|
271
|
+
| Telegram templates | `./template/*.mustache` | ✅ per-strategy |
|
|
272
|
+
| Environment variables | `./.env` (overrides root) | ✅ per-strategy |
|
|
273
|
+
|
|
274
|
+
Each strategy run produces its own `dump/` directory, making it straightforward to compare results across time periods — both by inspection and by pointing an AI agent at a specific strategy folder.
|
|
275
|
+
|
|
276
|
+
## 🔔 Integrations
|
|
277
|
+
|
|
278
|
+
### Web Dashboard (`--ui`)
|
|
279
|
+
|
|
280
|
+
Starts `@backtest-kit/ui` server. Access the interactive dashboard at:
|
|
281
|
+
|
|
282
|
+
```
|
|
283
|
+
http://localhost:60050
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Customize host/port via environment variables `CC_WWWROOT_HOST` and `CC_WWWROOT_PORT`.
|
|
287
|
+
|
|
288
|
+
### Telegram Notifications (`--telegram`)
|
|
289
|
+
|
|
290
|
+
Sends formatted HTML messages with 1m / 15m / 1h price charts to your Telegram channel for every position event: opened, closed, scheduled, cancelled, risk rejection, partial profit/loss, trailing stop/take, and breakeven.
|
|
291
|
+
|
|
292
|
+
Requires `CC_TELEGRAM_TOKEN` and `CC_TELEGRAM_CHANNEL` in your environment.
|
|
293
|
+
|
|
294
|
+
## 🧩 Live Module Hooks
|
|
295
|
+
|
|
296
|
+
Create a `modules/live.module.mjs` file in your **project root** to receive lifecycle callbacks for every trading event:
|
|
297
|
+
|
|
298
|
+
```javascript
|
|
299
|
+
// modules/live.module.mjs
|
|
300
|
+
|
|
301
|
+
export default class {
|
|
302
|
+
|
|
303
|
+
onOpened(event) {
|
|
304
|
+
console.log('Position opened', event.symbol, event.priceOpen);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
onClosed(event) {
|
|
308
|
+
console.log('Position closed', event.symbol, event.priceClosed);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
onScheduled(event) {
|
|
312
|
+
console.log('Signal scheduled', event.id);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
onCancelled(event) {
|
|
316
|
+
console.log('Signal cancelled', event.id);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
onRisk(event) {
|
|
320
|
+
console.warn('Risk rejection', event.reason);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
onPartialProfit(event) {
|
|
324
|
+
console.log('Partial profit taken', event.symbol);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
onPartialLoss(event) {
|
|
328
|
+
console.log('Partial loss taken', event.symbol);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
onTrailingTake(event) {
|
|
332
|
+
console.log('Trailing take adjusted', event.symbol);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
onTrailingStop(event) {
|
|
336
|
+
console.log('Trailing stop adjusted', event.symbol);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
onBreakeven(event) {
|
|
340
|
+
console.log('Breakeven triggered', event.symbol);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
All methods are optional — implement only the events you care about. The module is loaded dynamically from `{cwd}/modules/live.module.mjs` (supports `.cjs` and `.mjs` extensions).
|
|
346
|
+
|
|
347
|
+
### TypeScript Interface
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
import type { ILiveModule } from '@backtest-kit/cli';
|
|
351
|
+
|
|
352
|
+
export default class MyModule implements ILiveModule {
|
|
353
|
+
onOpened(event) { /* ... */ }
|
|
354
|
+
onClosed(event) { /* ... */ }
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## 🌍 Environment Variables
|
|
359
|
+
|
|
360
|
+
Create a `.env` file in your project root:
|
|
361
|
+
|
|
362
|
+
```env
|
|
363
|
+
# Telegram notifications (required for --telegram)
|
|
364
|
+
CC_TELEGRAM_TOKEN=your_bot_token_here
|
|
365
|
+
CC_TELEGRAM_CHANNEL=-100123456789
|
|
366
|
+
|
|
367
|
+
# Web UI server (optional, defaults shown)
|
|
368
|
+
CC_WWWROOT_HOST=0.0.0.0
|
|
369
|
+
CC_WWWROOT_PORT=60050
|
|
370
|
+
|
|
371
|
+
# Custom QuickChart service URL (optional)
|
|
372
|
+
CC_QUICKCHART_HOST=
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
| Variable | Default | Description |
|
|
376
|
+
|----------|---------|-------------|
|
|
377
|
+
| `CC_TELEGRAM_TOKEN` | — | Telegram bot token (from @BotFather) |
|
|
378
|
+
| `CC_TELEGRAM_CHANNEL` | — | Telegram channel or chat ID |
|
|
379
|
+
| `CC_WWWROOT_HOST` | `0.0.0.0` | UI server bind address |
|
|
380
|
+
| `CC_WWWROOT_PORT` | `60050` | UI server port |
|
|
381
|
+
| `CC_QUICKCHART_HOST` | — | Self-hosted QuickChart instance URL |
|
|
382
|
+
|
|
383
|
+
## ⚙️ Default Behaviors
|
|
384
|
+
|
|
385
|
+
When your strategy module does not register an exchange, frame, or strategy name, the CLI falls back to built-in defaults and prints a console warning:
|
|
386
|
+
|
|
387
|
+
| Component | Default | Warning |
|
|
388
|
+
|-----------|---------|---------|
|
|
389
|
+
| **Exchange** | CCXT Binance (`default_exchange`) | `Warning: The default exchange schema is set to CCXT Binance...` |
|
|
390
|
+
| **Frame** | February 2024 (`default_frame`) | `Warning: The default frame schema is set to February 2024...` |
|
|
391
|
+
| **Symbol** | `BTCUSDT` | — |
|
|
392
|
+
| **Cache intervals** | `1m, 15m, 30m, 4h` | Shown if `--cache` not provided |
|
|
393
|
+
|
|
394
|
+
> **Note:** The default exchange schema **does not support order book fetching in backtest mode**. If your strategy calls `getOrderBook()` during backtest, you must register a custom exchange schema with your own snapshot storage.
|
|
395
|
+
|
|
396
|
+
## 💡 Why Use @backtest-kit/cli?
|
|
397
|
+
|
|
398
|
+
Instead of writing infrastructure code for every project:
|
|
399
|
+
|
|
400
|
+
**❌ Without @backtest-kit/cli (manual setup)**
|
|
401
|
+
|
|
402
|
+
```typescript
|
|
403
|
+
// index.ts
|
|
404
|
+
import { setLogger, setConfig, Storage, Notification, Report, Markdown } from 'backtest-kit';
|
|
405
|
+
import { serve } from '@backtest-kit/ui';
|
|
406
|
+
|
|
407
|
+
setLogger({ log: console.log, ... });
|
|
408
|
+
Storage.enable();
|
|
409
|
+
Notification.enable();
|
|
410
|
+
Report.enable();
|
|
411
|
+
Markdown.disable();
|
|
412
|
+
|
|
413
|
+
// ... parse CLI args manually
|
|
414
|
+
// ... register exchange schema
|
|
415
|
+
// ... warm candle cache
|
|
416
|
+
// ... set up Telegram bot
|
|
417
|
+
// ... handle SIGINT gracefully
|
|
418
|
+
// ... load and run backtest
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
**✅ With @backtest-kit/cli (one script)**
|
|
422
|
+
|
|
423
|
+
```json
|
|
424
|
+
{ "scripts": { "backtest": "@backtest-kit/cli --backtest --ui --telegram ./src/index.mjs" } }
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
```bash
|
|
428
|
+
npm run backtest
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
**Benefits:**
|
|
432
|
+
|
|
433
|
+
- 🚀 From zero to running backtest in seconds
|
|
434
|
+
- 💾 Automatic candle cache warming with retry logic
|
|
435
|
+
- 🌐 Production-ready web dashboard out of the box
|
|
436
|
+
- 📬 Telegram notifications with price charts — no chart code needed
|
|
437
|
+
- 🛑 Graceful shutdown on SIGINT — no hanging processes
|
|
438
|
+
- 🔌 Works with any `backtest-kit` strategy file as-is
|
|
439
|
+
- 🧩 Module hooks for custom logic without touching the CLI internals
|
|
440
|
+
|
|
441
|
+
## 🤝 Contribute
|
|
442
|
+
|
|
443
|
+
Fork/PR on [GitHub](https://github.com/tripolskypetr/backtest-kit).
|
|
444
|
+
|
|
445
|
+
## 📜 License
|
|
446
|
+
|
|
447
|
+
MIT © [tripolskypetr](https://github.com/tripolskypetr)
|