@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 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
+ ![screenshot](https://raw.githubusercontent.com/tripolskypetr/backtest-kit/HEAD/assets/screenshots/screenshot8.png)
8
+
9
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/tripolskypetr/backtest-kit)
10
+ [![npm](https://img.shields.io/npm/v/@backtest-kit/cli.svg?style=flat-square)](https://npmjs.org/package/@backtest-kit/cli)
11
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue)]()
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)