@backtest-kit/cli 5.6.0 → 5.9.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 +5 -5
- package/build/index.cjs +58 -16
- package/build/index.mjs +59 -17
- package/package.json +13 -13
- package/types.d.ts +2 -0
package/README.md
CHANGED
|
@@ -302,11 +302,11 @@ Requires `CC_TELEGRAM_TOKEN` and `CC_TELEGRAM_CHANNEL` in your environment.
|
|
|
302
302
|
|
|
303
303
|
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.
|
|
304
304
|
|
|
305
|
-
|
|
|
306
|
-
|
|
307
|
-
| `--live`
|
|
308
|
-
| `--paper`
|
|
309
|
-
| `--backtest`
|
|
305
|
+
| Command Line Args | Module file | Loaded before |
|
|
306
|
+
|-------------------|---------------------------------|-----------------------------|
|
|
307
|
+
| `--live` | `./modules/live.module.mjs` | `Live.background()` |
|
|
308
|
+
| `--paper` | `./modules/paper.module.mjs` | `Live.background()` (paper) |
|
|
309
|
+
| `--backtest` | `./modules/backtest.module.mjs` | `Backtest.background()` |
|
|
310
310
|
|
|
311
311
|
> File is resolved relative to `cwd` (the strategy directory). All of `.mjs`, `.cjs`, `.ts` extensions are tried automatically. Missing module is a soft warning — not an error.
|
|
312
312
|
|
package/build/index.cjs
CHANGED
|
@@ -94,6 +94,10 @@ var BacktestKitSignals__namespace = /*#__PURE__*/_interopNamespaceDefault(Backte
|
|
|
94
94
|
BacktestKit.Markdown.enable();
|
|
95
95
|
BacktestKit.Report.enable();
|
|
96
96
|
}
|
|
97
|
+
{
|
|
98
|
+
BacktestKit.Dump.useMarkdown();
|
|
99
|
+
BacktestKit.Memory.usePersist();
|
|
100
|
+
}
|
|
97
101
|
{
|
|
98
102
|
BacktestKit.StorageLive.usePersist();
|
|
99
103
|
BacktestKit.StorageBacktest.useMemory();
|
|
@@ -116,6 +120,25 @@ BacktestKit.setConfig({
|
|
|
116
120
|
BacktestKit.setConfig({
|
|
117
121
|
CC_MAX_SIGNAL_GENERATION_SECONDS: 15 * 60,
|
|
118
122
|
});
|
|
123
|
+
BacktestKit.setConfig({
|
|
124
|
+
CC_MAX_BACKTEST_MARKDOWN_ROWS: 1000,
|
|
125
|
+
CC_MAX_BREAKEVEN_MARKDOWN_ROWS: 1000,
|
|
126
|
+
CC_MAX_HEATMAP_MARKDOWN_ROWS: 1000,
|
|
127
|
+
CC_MAX_HIGHEST_PROFIT_MARKDOWN_ROWS: 1000,
|
|
128
|
+
CC_MAX_LIVE_MARKDOWN_ROWS: 1000,
|
|
129
|
+
CC_MAX_PARTIAL_MARKDOWN_ROWS: 1000,
|
|
130
|
+
CC_MAX_RISK_MARKDOWN_ROWS: 1000,
|
|
131
|
+
CC_MAX_SCHEDULE_MARKDOWN_ROWS: 1000,
|
|
132
|
+
CC_MAX_STRATEGY_MARKDOWN_ROWS: 1000,
|
|
133
|
+
CC_MAX_SYNC_MARKDOWN_ROWS: 1000,
|
|
134
|
+
CC_MAX_PERFORMANCE_MARKDOWN_ROWS: 1000,
|
|
135
|
+
});
|
|
136
|
+
BacktestKit.setConfig({
|
|
137
|
+
CC_MAX_SIGNAL_LIFETIME_MINUTES: Infinity,
|
|
138
|
+
});
|
|
139
|
+
BacktestKit.setConfig({
|
|
140
|
+
CC_WALKER_MARKDOWN_TOP_N: 10,
|
|
141
|
+
});
|
|
119
142
|
BacktestKit.Log.useJsonl();
|
|
120
143
|
|
|
121
144
|
const ERROR_HANDLER_INSTALLED = Symbol.for("error-handler-installed");
|
|
@@ -266,8 +289,13 @@ class ResolveService {
|
|
|
266
289
|
this.loggerService = inject(TYPES.loggerService);
|
|
267
290
|
this.loaderService = inject(TYPES.loaderService);
|
|
268
291
|
this.DEFAULT_TEMPLATE_DIR = path.resolve(__dirname$1, '..', 'template');
|
|
292
|
+
this.DEFAULT_MODULES_DIR = path.resolve(__dirname$1, '..', 'modules');
|
|
269
293
|
this.OVERRIDE_TEMPLATE_DIR = path.resolve(process.cwd(), 'template');
|
|
270
294
|
this.OVERRIDE_MODULES_DIR = path.resolve(process.cwd(), 'modules');
|
|
295
|
+
this.getIsLaunched = () => {
|
|
296
|
+
this.loggerService.log("resolveService getIsLaunched");
|
|
297
|
+
return _is_launched;
|
|
298
|
+
};
|
|
271
299
|
this.attachEntryPoint = async (entryPoint) => {
|
|
272
300
|
this.loggerService.log("resolveService attachEntryPoint");
|
|
273
301
|
if (_is_launched) {
|
|
@@ -1719,25 +1747,36 @@ class TelegramTemplateService {
|
|
|
1719
1747
|
}
|
|
1720
1748
|
}
|
|
1721
1749
|
|
|
1750
|
+
const GET_MODULE_VARIANTS_FN = (fileName, self) => {
|
|
1751
|
+
const result = [];
|
|
1752
|
+
result.push({
|
|
1753
|
+
filePath: path.join(process.cwd(), "modules", fileName),
|
|
1754
|
+
baseDir: path.join(process.cwd(), "modules")
|
|
1755
|
+
});
|
|
1756
|
+
result.push({
|
|
1757
|
+
filePath: path.join(self.resolveService.OVERRIDE_MODULES_DIR, fileName),
|
|
1758
|
+
baseDir: self.resolveService.OVERRIDE_MODULES_DIR,
|
|
1759
|
+
});
|
|
1760
|
+
result.push({
|
|
1761
|
+
filePath: path.join(self.resolveService.DEFAULT_MODULES_DIR, fileName),
|
|
1762
|
+
baseDir: self.resolveService.DEFAULT_MODULES_DIR,
|
|
1763
|
+
});
|
|
1764
|
+
return result;
|
|
1765
|
+
};
|
|
1722
1766
|
const LOAD_MODULE_MODULE_FN = async (fileName, self) => {
|
|
1723
|
-
const
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
return true;
|
|
1767
|
+
for (const { filePath, baseDir } of GET_MODULE_VARIANTS_FN(fileName, self)) {
|
|
1768
|
+
try {
|
|
1769
|
+
if (await self.loaderService.check(filePath, baseDir)) {
|
|
1770
|
+
self.loaderService.import(filePath, baseDir);
|
|
1771
|
+
return true;
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1774
|
+
catch {
|
|
1775
|
+
console.warn(`Module module import failed filePath=${filePath} baseDir=${baseDir}`);
|
|
1776
|
+
process.exit(-1);
|
|
1734
1777
|
}
|
|
1735
|
-
return false;
|
|
1736
|
-
}
|
|
1737
|
-
catch {
|
|
1738
|
-
console.warn(`Module module import failed for file: ${resolvedFile}`);
|
|
1739
|
-
return false;
|
|
1740
1778
|
}
|
|
1779
|
+
return false;
|
|
1741
1780
|
};
|
|
1742
1781
|
class ModuleConnectionService {
|
|
1743
1782
|
constructor() {
|
|
@@ -2231,6 +2270,9 @@ function setLogger(logger) {
|
|
|
2231
2270
|
|
|
2232
2271
|
let _is_started = false;
|
|
2233
2272
|
async function run(mode, args) {
|
|
2273
|
+
if (cli.resolveService.getIsLaunched()) {
|
|
2274
|
+
throw new Error("Entry point is already attached. Multiple entry points are not allowed.");
|
|
2275
|
+
}
|
|
2234
2276
|
{
|
|
2235
2277
|
if (_is_started) {
|
|
2236
2278
|
throw new Error("Should be called only once");
|
package/build/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import * as BacktestKit from 'backtest-kit';
|
|
3
|
-
import { Storage, Notification, Markdown, Report, StorageLive, StorageBacktest, NotificationLive, NotificationBacktest, setConfig, Log, listExchangeSchema, addExchangeSchema, roundTicks, listFrameSchema, addFrameSchema, listenDoneLive, listenDoneBacktest, shutdown, listenSignal, listStrategySchema, overrideExchangeSchema, Backtest, Live, getCandles, checkCandles, warmCandles, listenRisk, listenStrategyCommit, listenSync } from 'backtest-kit';
|
|
3
|
+
import { Storage, Notification, Markdown, Report, Dump, Memory, StorageLive, StorageBacktest, NotificationLive, NotificationBacktest, setConfig, Log, listExchangeSchema, addExchangeSchema, roundTicks, listFrameSchema, addFrameSchema, listenDoneLive, listenDoneBacktest, shutdown, listenSignal, listStrategySchema, overrideExchangeSchema, Backtest, Live, getCandles, checkCandles, warmCandles, listenRisk, listenStrategyCommit, listenSync } from 'backtest-kit';
|
|
4
4
|
import { getErrorMessage, errorData, singleshot, str, BehaviorSubject, compose, execpool, queued, sleep, randomString, createAwaiter, TIMEOUT_SYMBOL, typo, retry, trycatch, memoize } from 'functools-kit';
|
|
5
5
|
import fs, { constants } from 'fs';
|
|
6
6
|
import * as stackTrace from 'stack-trace';
|
|
@@ -68,6 +68,10 @@ import * as BacktestKitSignals from '@backtest-kit/signals';
|
|
|
68
68
|
Markdown.enable();
|
|
69
69
|
Report.enable();
|
|
70
70
|
}
|
|
71
|
+
{
|
|
72
|
+
Dump.useMarkdown();
|
|
73
|
+
Memory.usePersist();
|
|
74
|
+
}
|
|
71
75
|
{
|
|
72
76
|
StorageLive.usePersist();
|
|
73
77
|
StorageBacktest.useMemory();
|
|
@@ -90,6 +94,25 @@ setConfig({
|
|
|
90
94
|
setConfig({
|
|
91
95
|
CC_MAX_SIGNAL_GENERATION_SECONDS: 15 * 60,
|
|
92
96
|
});
|
|
97
|
+
setConfig({
|
|
98
|
+
CC_MAX_BACKTEST_MARKDOWN_ROWS: 1000,
|
|
99
|
+
CC_MAX_BREAKEVEN_MARKDOWN_ROWS: 1000,
|
|
100
|
+
CC_MAX_HEATMAP_MARKDOWN_ROWS: 1000,
|
|
101
|
+
CC_MAX_HIGHEST_PROFIT_MARKDOWN_ROWS: 1000,
|
|
102
|
+
CC_MAX_LIVE_MARKDOWN_ROWS: 1000,
|
|
103
|
+
CC_MAX_PARTIAL_MARKDOWN_ROWS: 1000,
|
|
104
|
+
CC_MAX_RISK_MARKDOWN_ROWS: 1000,
|
|
105
|
+
CC_MAX_SCHEDULE_MARKDOWN_ROWS: 1000,
|
|
106
|
+
CC_MAX_STRATEGY_MARKDOWN_ROWS: 1000,
|
|
107
|
+
CC_MAX_SYNC_MARKDOWN_ROWS: 1000,
|
|
108
|
+
CC_MAX_PERFORMANCE_MARKDOWN_ROWS: 1000,
|
|
109
|
+
});
|
|
110
|
+
setConfig({
|
|
111
|
+
CC_MAX_SIGNAL_LIFETIME_MINUTES: Infinity,
|
|
112
|
+
});
|
|
113
|
+
setConfig({
|
|
114
|
+
CC_WALKER_MARKDOWN_TOP_N: 10,
|
|
115
|
+
});
|
|
93
116
|
Log.useJsonl();
|
|
94
117
|
|
|
95
118
|
const ERROR_HANDLER_INSTALLED = Symbol.for("error-handler-installed");
|
|
@@ -240,8 +263,13 @@ class ResolveService {
|
|
|
240
263
|
this.loggerService = inject(TYPES.loggerService);
|
|
241
264
|
this.loaderService = inject(TYPES.loaderService);
|
|
242
265
|
this.DEFAULT_TEMPLATE_DIR = path.resolve(__dirname, '..', 'template');
|
|
266
|
+
this.DEFAULT_MODULES_DIR = path.resolve(__dirname, '..', 'modules');
|
|
243
267
|
this.OVERRIDE_TEMPLATE_DIR = path.resolve(process.cwd(), 'template');
|
|
244
268
|
this.OVERRIDE_MODULES_DIR = path.resolve(process.cwd(), 'modules');
|
|
269
|
+
this.getIsLaunched = () => {
|
|
270
|
+
this.loggerService.log("resolveService getIsLaunched");
|
|
271
|
+
return _is_launched;
|
|
272
|
+
};
|
|
245
273
|
this.attachEntryPoint = async (entryPoint) => {
|
|
246
274
|
this.loggerService.log("resolveService attachEntryPoint");
|
|
247
275
|
if (_is_launched) {
|
|
@@ -1693,25 +1721,36 @@ class TelegramTemplateService {
|
|
|
1693
1721
|
}
|
|
1694
1722
|
}
|
|
1695
1723
|
|
|
1724
|
+
const GET_MODULE_VARIANTS_FN = (fileName, self) => {
|
|
1725
|
+
const result = [];
|
|
1726
|
+
result.push({
|
|
1727
|
+
filePath: path.join(process.cwd(), "modules", fileName),
|
|
1728
|
+
baseDir: path.join(process.cwd(), "modules")
|
|
1729
|
+
});
|
|
1730
|
+
result.push({
|
|
1731
|
+
filePath: path.join(self.resolveService.OVERRIDE_MODULES_DIR, fileName),
|
|
1732
|
+
baseDir: self.resolveService.OVERRIDE_MODULES_DIR,
|
|
1733
|
+
});
|
|
1734
|
+
result.push({
|
|
1735
|
+
filePath: path.join(self.resolveService.DEFAULT_MODULES_DIR, fileName),
|
|
1736
|
+
baseDir: self.resolveService.DEFAULT_MODULES_DIR,
|
|
1737
|
+
});
|
|
1738
|
+
return result;
|
|
1739
|
+
};
|
|
1696
1740
|
const LOAD_MODULE_MODULE_FN = async (fileName, self) => {
|
|
1697
|
-
const
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
return true;
|
|
1741
|
+
for (const { filePath, baseDir } of GET_MODULE_VARIANTS_FN(fileName, self)) {
|
|
1742
|
+
try {
|
|
1743
|
+
if (await self.loaderService.check(filePath, baseDir)) {
|
|
1744
|
+
self.loaderService.import(filePath, baseDir);
|
|
1745
|
+
return true;
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
catch {
|
|
1749
|
+
console.warn(`Module module import failed filePath=${filePath} baseDir=${baseDir}`);
|
|
1750
|
+
process.exit(-1);
|
|
1708
1751
|
}
|
|
1709
|
-
return false;
|
|
1710
|
-
}
|
|
1711
|
-
catch {
|
|
1712
|
-
console.warn(`Module module import failed for file: ${resolvedFile}`);
|
|
1713
|
-
return false;
|
|
1714
1752
|
}
|
|
1753
|
+
return false;
|
|
1715
1754
|
};
|
|
1716
1755
|
class ModuleConnectionService {
|
|
1717
1756
|
constructor() {
|
|
@@ -2201,6 +2240,9 @@ function setLogger(logger) {
|
|
|
2201
2240
|
|
|
2202
2241
|
let _is_started = false;
|
|
2203
2242
|
async function run(mode, args) {
|
|
2243
|
+
if (cli.resolveService.getIsLaunched()) {
|
|
2244
|
+
throw new Error("Entry point is already attached. Multiple entry points are not allowed.");
|
|
2245
|
+
}
|
|
2204
2246
|
{
|
|
2205
2247
|
if (_is_started) {
|
|
2206
2248
|
throw new Error("Should be called only once");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backtest-kit/cli",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.9.0",
|
|
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",
|
|
@@ -60,11 +60,11 @@
|
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@babel/plugin-transform-modules-umd": "7.27.1",
|
|
62
62
|
"@babel/standalone": "7.29.1",
|
|
63
|
-
"@backtest-kit/ui": "5.
|
|
64
|
-
"@backtest-kit/graph": "5.
|
|
65
|
-
"@backtest-kit/ollama": "5.
|
|
66
|
-
"@backtest-kit/pinets": "5.
|
|
67
|
-
"@backtest-kit/signals": "5.
|
|
63
|
+
"@backtest-kit/ui": "5.9.0",
|
|
64
|
+
"@backtest-kit/graph": "5.9.0",
|
|
65
|
+
"@backtest-kit/ollama": "5.9.0",
|
|
66
|
+
"@backtest-kit/pinets": "5.9.0",
|
|
67
|
+
"@backtest-kit/signals": "5.9.0",
|
|
68
68
|
"@rollup/plugin-replace": "6.0.3",
|
|
69
69
|
"@rollup/plugin-typescript": "11.1.6",
|
|
70
70
|
"@types/image-size": "0.7.0",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"@types/mustache": "4.2.6",
|
|
73
73
|
"@types/node": "22.9.0",
|
|
74
74
|
"@types/stack-trace": "0.0.33",
|
|
75
|
-
"backtest-kit": "5.
|
|
75
|
+
"backtest-kit": "5.9.0",
|
|
76
76
|
"glob": "11.0.1",
|
|
77
77
|
"markdown-it": "14.1.1",
|
|
78
78
|
"rimraf": "6.0.1",
|
|
@@ -87,12 +87,12 @@
|
|
|
87
87
|
"peerDependencies": {
|
|
88
88
|
"@babel/plugin-transform-modules-umd": "^7.27.1",
|
|
89
89
|
"@babel/standalone": "^7.29.1",
|
|
90
|
-
"@backtest-kit/ui": "^5.
|
|
91
|
-
"@backtest-kit/graph": "^5.
|
|
92
|
-
"@backtest-kit/ollama": "^5.
|
|
93
|
-
"@backtest-kit/pinets": "^5.
|
|
94
|
-
"@backtest-kit/signals": "^5.
|
|
95
|
-
"backtest-kit": "^5.
|
|
90
|
+
"@backtest-kit/ui": "^5.9.0",
|
|
91
|
+
"@backtest-kit/graph": "^5.9.0",
|
|
92
|
+
"@backtest-kit/ollama": "^5.9.0",
|
|
93
|
+
"@backtest-kit/pinets": "^5.9.0",
|
|
94
|
+
"@backtest-kit/signals": "^5.9.0",
|
|
95
|
+
"backtest-kit": "^5.9.0",
|
|
96
96
|
"markdown-it": "^14.1.1",
|
|
97
97
|
"typescript": "^5.0.0"
|
|
98
98
|
},
|
package/types.d.ts
CHANGED
|
@@ -99,8 +99,10 @@ declare class ResolveService {
|
|
|
99
99
|
readonly loggerService: LoggerService;
|
|
100
100
|
readonly loaderService: LoaderService;
|
|
101
101
|
readonly DEFAULT_TEMPLATE_DIR: string;
|
|
102
|
+
readonly DEFAULT_MODULES_DIR: string;
|
|
102
103
|
readonly OVERRIDE_TEMPLATE_DIR: string;
|
|
103
104
|
readonly OVERRIDE_MODULES_DIR: string;
|
|
105
|
+
getIsLaunched: () => boolean;
|
|
104
106
|
attachEntryPoint: (entryPoint: string) => Promise<void>;
|
|
105
107
|
}
|
|
106
108
|
|