@backtest-kit/cli 0.0.2 → 0.0.4
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 +103 -20
- package/build/index.cjs +39 -14
- package/build/index.mjs +39 -14
- package/package.json +1 -1
- package/types.d.ts +3 -3
package/README.md
CHANGED
|
@@ -30,13 +30,13 @@ Point the CLI at your strategy file, choose a mode, and it handles exchange conn
|
|
|
30
30
|
|
|
31
31
|
`@backtest-kit/cli` wraps the `backtest-kit` engine and resolves all scaffolding automatically:
|
|
32
32
|
|
|
33
|
-
| Mode |
|
|
34
|
-
|
|
35
|
-
| **Backtest** | `--backtest`
|
|
36
|
-
| **Paper** | `--paper`
|
|
37
|
-
| **Live** | `--live`
|
|
38
|
-
| **UI Dashboard** | `--ui`
|
|
39
|
-
| **Telegram** | `--telegram`
|
|
33
|
+
| Mode | Command Line Args | Description |
|
|
34
|
+
|------------------|----------------------------|----------------------------------------------|
|
|
35
|
+
| **Backtest** | `--backtest` | Run strategy on historical candle data |
|
|
36
|
+
| **Paper** | `--paper` | Live prices, no real orders |
|
|
37
|
+
| **Live** | `--live` | Real trades via exchange API |
|
|
38
|
+
| **UI Dashboard** | `--ui` | Web dashboard at `http://localhost:60050` |
|
|
39
|
+
| **Telegram** | `--telegram` | Trade notifications with price charts |
|
|
40
40
|
|
|
41
41
|
## 🚀 Installation
|
|
42
42
|
|
|
@@ -129,19 +129,19 @@ npm start -- --symbol BTCUSDT --ui
|
|
|
129
129
|
|
|
130
130
|
## 🎛️ CLI Flags
|
|
131
131
|
|
|
132
|
-
|
|
|
133
|
-
|
|
134
|
-
| `--backtest`
|
|
135
|
-
| `--paper`
|
|
136
|
-
| `--live`
|
|
137
|
-
| `--ui`
|
|
138
|
-
| `--telegram`
|
|
139
|
-
| `--verbose`
|
|
140
|
-
| `--symbol`
|
|
141
|
-
| `--strategy`
|
|
142
|
-
| `--exchange`
|
|
143
|
-
| `--frame`
|
|
144
|
-
| `--cache`
|
|
132
|
+
| Command Line Args | Type | Description |
|
|
133
|
+
|---------------------------|---------|--------------------------------------------------------------------|
|
|
134
|
+
| `--backtest` | boolean | Run historical backtest (default: `false`) |
|
|
135
|
+
| `--paper` | boolean | Paper trading (live prices, no orders) (default: `false`) |
|
|
136
|
+
| `--live` | boolean | Run live trading (default: `false`) |
|
|
137
|
+
| `--ui` | boolean | Start web UI dashboard (default: `false`) |
|
|
138
|
+
| `--telegram` | boolean | Enable Telegram notifications (default: `false`) |
|
|
139
|
+
| `--verbose` | boolean | Log each candle fetch (default: `false`) |
|
|
140
|
+
| `--symbol` | string | Trading pair (default: `"BTCUSDT"`) |
|
|
141
|
+
| `--strategy` | string | Strategy name (default: first registered) |
|
|
142
|
+
| `--exchange` | string | Exchange name (default: first registered) |
|
|
143
|
+
| `--frame` | string | Backtest frame name (default: first registered) |
|
|
144
|
+
| `--cache` | string | Intervals to pre-cache before backtest (default: `"1m, 15m, 30m, 4h"`) |
|
|
145
145
|
|
|
146
146
|
**Positional argument (required):** path to your strategy entry point file (set once in `package.json` scripts).
|
|
147
147
|
|
|
@@ -393,6 +393,89 @@ When your strategy module does not register an exchange, frame, or strategy name
|
|
|
393
393
|
|
|
394
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
395
|
|
|
396
|
+
|
|
397
|
+
## 🔧 Programmatic API
|
|
398
|
+
|
|
399
|
+
In addition to the CLI, `@backtest-kit/cli` can be used as a library — call `run()` directly from your own script without spawning a child process or parsing CLI flags.
|
|
400
|
+
|
|
401
|
+
### `run(mode, args)`
|
|
402
|
+
|
|
403
|
+
```typescript
|
|
404
|
+
import { run } from '@backtest-kit/cli';
|
|
405
|
+
|
|
406
|
+
await run(mode, args);
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
| Parameter | Description |
|
|
410
|
+
|-----------|-------------|
|
|
411
|
+
| `mode` | `"backtest" \| "paper" \| "live"` — Execution mode |
|
|
412
|
+
| `args` | Mode-specific options (all optional — same defaults as CLI) |
|
|
413
|
+
|
|
414
|
+
`run()` can be called **only once per process**. A second call throws `"Should be called only once"`.
|
|
415
|
+
|
|
416
|
+
### Payload fields
|
|
417
|
+
|
|
418
|
+
**Backtest** (`mode: "backtest"`):
|
|
419
|
+
|
|
420
|
+
| Field | Type | Description |
|
|
421
|
+
|-------|------|-------------|
|
|
422
|
+
| `entryPoint` | `string` | Path to strategy entry point file |
|
|
423
|
+
| `symbol` | `string` | Trading pair (default: `"BTCUSDT"`) |
|
|
424
|
+
| `strategy` | `string` | Strategy name (default: first registered) |
|
|
425
|
+
| `exchange` | `string` | Exchange name (default: first registered) |
|
|
426
|
+
| `frame` | `string` | Frame name (default: first registered) |
|
|
427
|
+
| `cacheList` | `CandleInterval[]` | Intervals to pre-cache (default: `["1m","15m","30m","1h","4h"]`) |
|
|
428
|
+
| `verbose` | `boolean` | Log each candle fetch (default: `false`) |
|
|
429
|
+
|
|
430
|
+
**Paper** and **Live** (`mode: "paper"` / `mode: "live"`):
|
|
431
|
+
|
|
432
|
+
| Field | Type | Description |
|
|
433
|
+
|-------|------|-------------|
|
|
434
|
+
| `entryPoint` | `string` | Path to strategy entry point file |
|
|
435
|
+
| `symbol` | `string` | Trading pair (default: `"BTCUSDT"`) |
|
|
436
|
+
| `strategy` | `string` | Strategy name (default: first registered) |
|
|
437
|
+
| `exchange` | `string` | Exchange name (default: first registered) |
|
|
438
|
+
| `verbose` | `boolean` | Log each candle fetch (default: `false`) |
|
|
439
|
+
|
|
440
|
+
### Examples
|
|
441
|
+
|
|
442
|
+
**Backtest:**
|
|
443
|
+
|
|
444
|
+
```typescript
|
|
445
|
+
import { run } from '@backtest-kit/cli';
|
|
446
|
+
|
|
447
|
+
await run('backtest', {
|
|
448
|
+
entryPoint: './src/index.mjs',
|
|
449
|
+
symbol: 'ETHUSDT',
|
|
450
|
+
frame: 'feb-2024',
|
|
451
|
+
cacheList: ['1m', '15m', '1h'],
|
|
452
|
+
verbose: true,
|
|
453
|
+
});
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
**Paper trading:**
|
|
457
|
+
|
|
458
|
+
```typescript
|
|
459
|
+
import { run } from '@backtest-kit/cli';
|
|
460
|
+
|
|
461
|
+
await run('paper', {
|
|
462
|
+
entryPoint: './src/index.mjs',
|
|
463
|
+
symbol: 'BTCUSDT',
|
|
464
|
+
});
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
**Live trading:**
|
|
468
|
+
|
|
469
|
+
```typescript
|
|
470
|
+
import { run } from '@backtest-kit/cli';
|
|
471
|
+
|
|
472
|
+
await run('live', {
|
|
473
|
+
entryPoint: './src/index.mjs',
|
|
474
|
+
symbol: 'BTCUSDT',
|
|
475
|
+
verbose: true,
|
|
476
|
+
});
|
|
477
|
+
```
|
|
478
|
+
|
|
396
479
|
## 💡 Why Use @backtest-kit/cli?
|
|
397
480
|
|
|
398
481
|
Instead of writing infrastructure code for every project:
|
package/build/index.cjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
'use strict';
|
|
2
3
|
|
|
3
4
|
var backtestKit = require('backtest-kit');
|
|
@@ -536,8 +537,8 @@ class BacktestMainService {
|
|
|
536
537
|
});
|
|
537
538
|
notifyFinish();
|
|
538
539
|
});
|
|
539
|
-
this.
|
|
540
|
-
this.loggerService.log("backtestMainService
|
|
540
|
+
this.connect = functoolsKit.singleshot(async () => {
|
|
541
|
+
this.loggerService.log("backtestMainService connect");
|
|
541
542
|
if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
|
|
542
543
|
return;
|
|
543
544
|
}
|
|
@@ -613,8 +614,8 @@ class LiveMainService {
|
|
|
613
614
|
});
|
|
614
615
|
notifyFinish();
|
|
615
616
|
});
|
|
616
|
-
this.
|
|
617
|
-
this.loggerService.log("liveMainService
|
|
617
|
+
this.connect = functoolsKit.singleshot(async () => {
|
|
618
|
+
this.loggerService.log("liveMainService connect");
|
|
618
619
|
if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
|
|
619
620
|
return;
|
|
620
621
|
}
|
|
@@ -683,8 +684,8 @@ class PaperMainService {
|
|
|
683
684
|
});
|
|
684
685
|
notifyFinish();
|
|
685
686
|
});
|
|
686
|
-
this.
|
|
687
|
-
this.loggerService.log("paperMainService
|
|
687
|
+
this.connect = functoolsKit.singleshot(async () => {
|
|
688
|
+
this.loggerService.log("paperMainService connect");
|
|
688
689
|
if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
|
|
689
690
|
return;
|
|
690
691
|
}
|
|
@@ -1845,6 +1846,9 @@ const BEFORE_EXIT_FN$4 = functoolsKit.singleshot(async () => {
|
|
|
1845
1846
|
frameName,
|
|
1846
1847
|
});
|
|
1847
1848
|
});
|
|
1849
|
+
const listenGracefulShutdown$4 = functoolsKit.singleshot(() => {
|
|
1850
|
+
process.on("SIGINT", BEFORE_EXIT_FN$4);
|
|
1851
|
+
});
|
|
1848
1852
|
const main$4 = async () => {
|
|
1849
1853
|
if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
|
|
1850
1854
|
return;
|
|
@@ -1853,7 +1857,8 @@ const main$4 = async () => {
|
|
|
1853
1857
|
if (!values.backtest) {
|
|
1854
1858
|
return;
|
|
1855
1859
|
}
|
|
1856
|
-
|
|
1860
|
+
await cli.backtestMainService.connect();
|
|
1861
|
+
listenGracefulShutdown$4();
|
|
1857
1862
|
};
|
|
1858
1863
|
main$4();
|
|
1859
1864
|
|
|
@@ -1873,6 +1878,9 @@ const BEFORE_EXIT_FN$3 = functoolsKit.singleshot(async () => {
|
|
|
1873
1878
|
strategyName,
|
|
1874
1879
|
});
|
|
1875
1880
|
});
|
|
1881
|
+
const listenGracefulShutdown$3 = functoolsKit.singleshot(() => {
|
|
1882
|
+
process.on("SIGINT", BEFORE_EXIT_FN$3);
|
|
1883
|
+
});
|
|
1876
1884
|
const main$3 = async () => {
|
|
1877
1885
|
if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
|
|
1878
1886
|
return;
|
|
@@ -1881,7 +1889,8 @@ const main$3 = async () => {
|
|
|
1881
1889
|
if (!values.paper) {
|
|
1882
1890
|
return;
|
|
1883
1891
|
}
|
|
1884
|
-
|
|
1892
|
+
cli.paperMainService.connect();
|
|
1893
|
+
listenGracefulShutdown$3();
|
|
1885
1894
|
};
|
|
1886
1895
|
main$3();
|
|
1887
1896
|
|
|
@@ -1902,6 +1911,9 @@ const BEFORE_EXIT_FN$2 = functoolsKit.singleshot(async () => {
|
|
|
1902
1911
|
});
|
|
1903
1912
|
backtestKit.listenDoneLive(cli.liveProviderService.disable);
|
|
1904
1913
|
});
|
|
1914
|
+
const listenGracefulShutdown$2 = functoolsKit.singleshot(() => {
|
|
1915
|
+
process.on("SIGINT", BEFORE_EXIT_FN$2);
|
|
1916
|
+
});
|
|
1905
1917
|
const main$2 = async () => {
|
|
1906
1918
|
if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
|
|
1907
1919
|
return;
|
|
@@ -1910,7 +1922,8 @@ const main$2 = async () => {
|
|
|
1910
1922
|
if (!values.live) {
|
|
1911
1923
|
return;
|
|
1912
1924
|
}
|
|
1913
|
-
|
|
1925
|
+
await cli.liveMainService.connect();
|
|
1926
|
+
listenGracefulShutdown$2();
|
|
1914
1927
|
};
|
|
1915
1928
|
main$2();
|
|
1916
1929
|
|
|
@@ -1919,6 +1932,9 @@ const BEFORE_EXIT_FN$1 = functoolsKit.singleshot(async () => {
|
|
|
1919
1932
|
notifyShutdown();
|
|
1920
1933
|
cli.frontendProviderService.disable();
|
|
1921
1934
|
});
|
|
1935
|
+
const listenGracefulShutdown$1 = functoolsKit.singleshot(() => {
|
|
1936
|
+
process.on("SIGINT", BEFORE_EXIT_FN$1);
|
|
1937
|
+
});
|
|
1922
1938
|
const main$1 = async () => {
|
|
1923
1939
|
if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
|
|
1924
1940
|
return;
|
|
@@ -1927,7 +1943,7 @@ const main$1 = async () => {
|
|
|
1927
1943
|
if (!values.ui) {
|
|
1928
1944
|
return;
|
|
1929
1945
|
}
|
|
1930
|
-
|
|
1946
|
+
listenGracefulShutdown$1();
|
|
1931
1947
|
};
|
|
1932
1948
|
main$1();
|
|
1933
1949
|
|
|
@@ -1936,6 +1952,9 @@ const BEFORE_EXIT_FN = functoolsKit.singleshot(async () => {
|
|
|
1936
1952
|
notifyShutdown();
|
|
1937
1953
|
cli.telegramProviderService.disable();
|
|
1938
1954
|
});
|
|
1955
|
+
const listenGracefulShutdown = functoolsKit.singleshot(() => {
|
|
1956
|
+
process.on("SIGINT", BEFORE_EXIT_FN);
|
|
1957
|
+
});
|
|
1939
1958
|
const main = async () => {
|
|
1940
1959
|
if (!getEntry((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))) {
|
|
1941
1960
|
return;
|
|
@@ -1944,7 +1963,7 @@ const main = async () => {
|
|
|
1944
1963
|
if (!values.telegram) {
|
|
1945
1964
|
return;
|
|
1946
1965
|
}
|
|
1947
|
-
|
|
1966
|
+
listenGracefulShutdown();
|
|
1948
1967
|
};
|
|
1949
1968
|
main();
|
|
1950
1969
|
|
|
@@ -1961,13 +1980,19 @@ async function run(mode, args) {
|
|
|
1961
1980
|
_is_started = true;
|
|
1962
1981
|
}
|
|
1963
1982
|
if (mode === "backtest") {
|
|
1964
|
-
|
|
1983
|
+
await cli.backtestMainService.run(args);
|
|
1984
|
+
listenGracefulShutdown$4();
|
|
1985
|
+
return;
|
|
1965
1986
|
}
|
|
1966
1987
|
if (mode === "paper") {
|
|
1967
|
-
|
|
1988
|
+
await cli.paperMainService.run(args);
|
|
1989
|
+
listenGracefulShutdown$3();
|
|
1990
|
+
return;
|
|
1968
1991
|
}
|
|
1969
1992
|
if (mode === "live") {
|
|
1970
|
-
|
|
1993
|
+
await cli.liveMainService.run(args);
|
|
1994
|
+
listenGracefulShutdown$2();
|
|
1995
|
+
return;
|
|
1971
1996
|
}
|
|
1972
1997
|
throw new Error(`Invalid mode: ${mode}`);
|
|
1973
1998
|
}
|
package/build/index.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
import { Storage, Notification, Markdown, Report, StorageLive, StorageBacktest, NotificationLive, NotificationBacktest, listExchangeSchema, addExchangeSchema, roundTicks, listFrameSchema, addFrameSchema, listenDoneLive, listenDoneBacktest, listStrategySchema, overrideExchangeSchema, Backtest, Live, getCandles, checkCandles, warmCandles, listenRisk, listenSignal, listenStrategyCommit } from 'backtest-kit';
|
|
2
3
|
import { getErrorMessage, errorData, singleshot, str, BehaviorSubject, compose, execpool, queued, sleep, randomString, createAwaiter, TIMEOUT_SYMBOL, typo, retry, memoize, trycatch } from 'functools-kit';
|
|
3
4
|
import fs, { constants } from 'fs';
|
|
@@ -514,8 +515,8 @@ class BacktestMainService {
|
|
|
514
515
|
});
|
|
515
516
|
notifyFinish();
|
|
516
517
|
});
|
|
517
|
-
this.
|
|
518
|
-
this.loggerService.log("backtestMainService
|
|
518
|
+
this.connect = singleshot(async () => {
|
|
519
|
+
this.loggerService.log("backtestMainService connect");
|
|
519
520
|
if (!getEntry(import.meta.url)) {
|
|
520
521
|
return;
|
|
521
522
|
}
|
|
@@ -591,8 +592,8 @@ class LiveMainService {
|
|
|
591
592
|
});
|
|
592
593
|
notifyFinish();
|
|
593
594
|
});
|
|
594
|
-
this.
|
|
595
|
-
this.loggerService.log("liveMainService
|
|
595
|
+
this.connect = singleshot(async () => {
|
|
596
|
+
this.loggerService.log("liveMainService connect");
|
|
596
597
|
if (!getEntry(import.meta.url)) {
|
|
597
598
|
return;
|
|
598
599
|
}
|
|
@@ -661,8 +662,8 @@ class PaperMainService {
|
|
|
661
662
|
});
|
|
662
663
|
notifyFinish();
|
|
663
664
|
});
|
|
664
|
-
this.
|
|
665
|
-
this.loggerService.log("paperMainService
|
|
665
|
+
this.connect = singleshot(async () => {
|
|
666
|
+
this.loggerService.log("paperMainService connect");
|
|
666
667
|
if (!getEntry(import.meta.url)) {
|
|
667
668
|
return;
|
|
668
669
|
}
|
|
@@ -1823,6 +1824,9 @@ const BEFORE_EXIT_FN$4 = singleshot(async () => {
|
|
|
1823
1824
|
frameName,
|
|
1824
1825
|
});
|
|
1825
1826
|
});
|
|
1827
|
+
const listenGracefulShutdown$4 = singleshot(() => {
|
|
1828
|
+
process.on("SIGINT", BEFORE_EXIT_FN$4);
|
|
1829
|
+
});
|
|
1826
1830
|
const main$4 = async () => {
|
|
1827
1831
|
if (!getEntry(import.meta.url)) {
|
|
1828
1832
|
return;
|
|
@@ -1831,7 +1835,8 @@ const main$4 = async () => {
|
|
|
1831
1835
|
if (!values.backtest) {
|
|
1832
1836
|
return;
|
|
1833
1837
|
}
|
|
1834
|
-
|
|
1838
|
+
await cli.backtestMainService.connect();
|
|
1839
|
+
listenGracefulShutdown$4();
|
|
1835
1840
|
};
|
|
1836
1841
|
main$4();
|
|
1837
1842
|
|
|
@@ -1851,6 +1856,9 @@ const BEFORE_EXIT_FN$3 = singleshot(async () => {
|
|
|
1851
1856
|
strategyName,
|
|
1852
1857
|
});
|
|
1853
1858
|
});
|
|
1859
|
+
const listenGracefulShutdown$3 = singleshot(() => {
|
|
1860
|
+
process.on("SIGINT", BEFORE_EXIT_FN$3);
|
|
1861
|
+
});
|
|
1854
1862
|
const main$3 = async () => {
|
|
1855
1863
|
if (!getEntry(import.meta.url)) {
|
|
1856
1864
|
return;
|
|
@@ -1859,7 +1867,8 @@ const main$3 = async () => {
|
|
|
1859
1867
|
if (!values.paper) {
|
|
1860
1868
|
return;
|
|
1861
1869
|
}
|
|
1862
|
-
|
|
1870
|
+
cli.paperMainService.connect();
|
|
1871
|
+
listenGracefulShutdown$3();
|
|
1863
1872
|
};
|
|
1864
1873
|
main$3();
|
|
1865
1874
|
|
|
@@ -1880,6 +1889,9 @@ const BEFORE_EXIT_FN$2 = singleshot(async () => {
|
|
|
1880
1889
|
});
|
|
1881
1890
|
listenDoneLive(cli.liveProviderService.disable);
|
|
1882
1891
|
});
|
|
1892
|
+
const listenGracefulShutdown$2 = singleshot(() => {
|
|
1893
|
+
process.on("SIGINT", BEFORE_EXIT_FN$2);
|
|
1894
|
+
});
|
|
1883
1895
|
const main$2 = async () => {
|
|
1884
1896
|
if (!getEntry(import.meta.url)) {
|
|
1885
1897
|
return;
|
|
@@ -1888,7 +1900,8 @@ const main$2 = async () => {
|
|
|
1888
1900
|
if (!values.live) {
|
|
1889
1901
|
return;
|
|
1890
1902
|
}
|
|
1891
|
-
|
|
1903
|
+
await cli.liveMainService.connect();
|
|
1904
|
+
listenGracefulShutdown$2();
|
|
1892
1905
|
};
|
|
1893
1906
|
main$2();
|
|
1894
1907
|
|
|
@@ -1897,6 +1910,9 @@ const BEFORE_EXIT_FN$1 = singleshot(async () => {
|
|
|
1897
1910
|
notifyShutdown();
|
|
1898
1911
|
cli.frontendProviderService.disable();
|
|
1899
1912
|
});
|
|
1913
|
+
const listenGracefulShutdown$1 = singleshot(() => {
|
|
1914
|
+
process.on("SIGINT", BEFORE_EXIT_FN$1);
|
|
1915
|
+
});
|
|
1900
1916
|
const main$1 = async () => {
|
|
1901
1917
|
if (!getEntry(import.meta.url)) {
|
|
1902
1918
|
return;
|
|
@@ -1905,7 +1921,7 @@ const main$1 = async () => {
|
|
|
1905
1921
|
if (!values.ui) {
|
|
1906
1922
|
return;
|
|
1907
1923
|
}
|
|
1908
|
-
|
|
1924
|
+
listenGracefulShutdown$1();
|
|
1909
1925
|
};
|
|
1910
1926
|
main$1();
|
|
1911
1927
|
|
|
@@ -1914,6 +1930,9 @@ const BEFORE_EXIT_FN = singleshot(async () => {
|
|
|
1914
1930
|
notifyShutdown();
|
|
1915
1931
|
cli.telegramProviderService.disable();
|
|
1916
1932
|
});
|
|
1933
|
+
const listenGracefulShutdown = singleshot(() => {
|
|
1934
|
+
process.on("SIGINT", BEFORE_EXIT_FN);
|
|
1935
|
+
});
|
|
1917
1936
|
const main = async () => {
|
|
1918
1937
|
if (!getEntry(import.meta.url)) {
|
|
1919
1938
|
return;
|
|
@@ -1922,7 +1941,7 @@ const main = async () => {
|
|
|
1922
1941
|
if (!values.telegram) {
|
|
1923
1942
|
return;
|
|
1924
1943
|
}
|
|
1925
|
-
|
|
1944
|
+
listenGracefulShutdown();
|
|
1926
1945
|
};
|
|
1927
1946
|
main();
|
|
1928
1947
|
|
|
@@ -1939,13 +1958,19 @@ async function run(mode, args) {
|
|
|
1939
1958
|
_is_started = true;
|
|
1940
1959
|
}
|
|
1941
1960
|
if (mode === "backtest") {
|
|
1942
|
-
|
|
1961
|
+
await cli.backtestMainService.run(args);
|
|
1962
|
+
listenGracefulShutdown$4();
|
|
1963
|
+
return;
|
|
1943
1964
|
}
|
|
1944
1965
|
if (mode === "paper") {
|
|
1945
|
-
|
|
1966
|
+
await cli.paperMainService.run(args);
|
|
1967
|
+
listenGracefulShutdown$3();
|
|
1968
|
+
return;
|
|
1946
1969
|
}
|
|
1947
1970
|
if (mode === "live") {
|
|
1948
|
-
|
|
1971
|
+
await cli.liveMainService.run(args);
|
|
1972
|
+
listenGracefulShutdown$2();
|
|
1973
|
+
return;
|
|
1949
1974
|
}
|
|
1950
1975
|
throw new Error(`Invalid mode: ${mode}`);
|
|
1951
1976
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backtest-kit/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
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",
|
package/types.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ declare class PaperMainService {
|
|
|
32
32
|
exchange: string;
|
|
33
33
|
verbose: boolean;
|
|
34
34
|
}) => Promise<void>) & functools_kit.ISingleshotClearable;
|
|
35
|
-
|
|
35
|
+
connect: (() => Promise<void>) & functools_kit.ISingleshotClearable;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
declare class LiveMainService {
|
|
@@ -50,7 +50,7 @@ declare class LiveMainService {
|
|
|
50
50
|
exchange: string;
|
|
51
51
|
verbose: boolean;
|
|
52
52
|
}) => Promise<void>) & functools_kit.ISingleshotClearable;
|
|
53
|
-
|
|
53
|
+
connect: (() => Promise<void>) & functools_kit.ISingleshotClearable;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
declare class BacktestMainService {
|
|
@@ -71,7 +71,7 @@ declare class BacktestMainService {
|
|
|
71
71
|
cacheList: string[];
|
|
72
72
|
verbose: boolean;
|
|
73
73
|
}) => Promise<void>) & functools_kit.ISingleshotClearable;
|
|
74
|
-
|
|
74
|
+
connect: (() => Promise<void>) & functools_kit.ISingleshotClearable;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
declare class ExchangeSchemaService {
|