@backtest-kit/cli 3.3.4 → 3.3.5
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/build/index.cjs +141 -63
- package/build/index.mjs +99 -21
- package/package.json +8 -5
- package/types.d.ts +18 -1
package/build/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var BacktestKit = require('backtest-kit');
|
|
5
5
|
var functoolsKit = require('functools-kit');
|
|
6
6
|
var fs = require('fs');
|
|
7
7
|
var stackTrace = require('stack-trace');
|
|
@@ -23,6 +23,8 @@ var MarkdownIt = require('markdown-it');
|
|
|
23
23
|
var sanitizeHtml = require('sanitize-html');
|
|
24
24
|
var jsdom = require('jsdom');
|
|
25
25
|
var Mustache = require('mustache');
|
|
26
|
+
var standalone = require('@babel/standalone');
|
|
27
|
+
var pluginUMD = require('@babel/plugin-transform-modules-umd');
|
|
26
28
|
|
|
27
29
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
28
30
|
function _interopNamespaceDefault(e) {
|
|
@@ -42,6 +44,7 @@ function _interopNamespaceDefault(e) {
|
|
|
42
44
|
return Object.freeze(n);
|
|
43
45
|
}
|
|
44
46
|
|
|
47
|
+
var BacktestKit__namespace = /*#__PURE__*/_interopNamespaceDefault(BacktestKit);
|
|
45
48
|
var stackTrace__namespace = /*#__PURE__*/_interopNamespaceDefault(stackTrace);
|
|
46
49
|
|
|
47
50
|
/**
|
|
@@ -75,22 +78,22 @@ var stackTrace__namespace = /*#__PURE__*/_interopNamespaceDefault(stackTrace);
|
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
{
|
|
78
|
-
|
|
79
|
-
|
|
81
|
+
BacktestKit.Storage.enable();
|
|
82
|
+
BacktestKit.Notification.enable();
|
|
80
83
|
}
|
|
81
84
|
{
|
|
82
|
-
|
|
83
|
-
|
|
85
|
+
BacktestKit.Markdown.disable();
|
|
86
|
+
BacktestKit.Report.enable();
|
|
84
87
|
}
|
|
85
88
|
{
|
|
86
|
-
|
|
87
|
-
|
|
89
|
+
BacktestKit.StorageLive.usePersist();
|
|
90
|
+
BacktestKit.StorageBacktest.useMemory();
|
|
88
91
|
}
|
|
89
92
|
{
|
|
90
|
-
|
|
91
|
-
|
|
93
|
+
BacktestKit.NotificationLive.usePersist();
|
|
94
|
+
BacktestKit.NotificationBacktest.useMemory();
|
|
92
95
|
}
|
|
93
|
-
|
|
96
|
+
BacktestKit.setConfig({
|
|
94
97
|
CC_MAX_NOTIFICATIONS: 5000,
|
|
95
98
|
CC_MAX_SIGNALS: 750,
|
|
96
99
|
});
|
|
@@ -191,6 +194,7 @@ const baseServices$1 = {
|
|
|
191
194
|
errorService: Symbol('errorService'),
|
|
192
195
|
loggerService: Symbol('loggerService'),
|
|
193
196
|
resolveService: Symbol('resolveService'),
|
|
197
|
+
babelService: Symbol('babelService'),
|
|
194
198
|
};
|
|
195
199
|
const connectionServices$1 = {
|
|
196
200
|
moduleConnectionService: Symbol('moduleConnectionService'),
|
|
@@ -234,8 +238,8 @@ const TYPES = {
|
|
|
234
238
|
|
|
235
239
|
const entrySubject = new functoolsKit.BehaviorSubject();
|
|
236
240
|
|
|
237
|
-
const __filename$
|
|
238
|
-
const __dirname$1 = path.dirname(__filename$
|
|
241
|
+
const __filename$2 = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
|
|
242
|
+
const __dirname$1 = path.dirname(__filename$2);
|
|
239
243
|
const require$2 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
|
|
240
244
|
const REQUIRE_ENTRY_FACTORY = (filePath) => {
|
|
241
245
|
try {
|
|
@@ -247,25 +251,37 @@ const REQUIRE_ENTRY_FACTORY = (filePath) => {
|
|
|
247
251
|
}
|
|
248
252
|
};
|
|
249
253
|
const IMPORT_ENTRY_FACTORY = async (filePath) => {
|
|
250
|
-
|
|
254
|
+
{
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
251
257
|
};
|
|
252
|
-
const
|
|
253
|
-
const
|
|
254
|
-
|
|
258
|
+
const BABEL_ENTRY_FACTORY = async (filePath, self) => {
|
|
259
|
+
const code = await fs$1.readFile(filePath, "utf-8");
|
|
260
|
+
try {
|
|
261
|
+
await self.babelService.transpileAndRun(code);
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
255
267
|
};
|
|
256
|
-
const LOAD_ENTRY_FN = async (filePath) => {
|
|
257
|
-
if (
|
|
258
|
-
|
|
268
|
+
const LOAD_ENTRY_FN = async (filePath, self) => {
|
|
269
|
+
if (REQUIRE_ENTRY_FACTORY(filePath)) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
if (await IMPORT_ENTRY_FACTORY()) {
|
|
259
273
|
return;
|
|
260
274
|
}
|
|
261
|
-
if (
|
|
262
|
-
|
|
275
|
+
if (await BABEL_ENTRY_FACTORY(filePath, self)) {
|
|
276
|
+
return;
|
|
263
277
|
}
|
|
278
|
+
throw new Error(`Failed to load entry point: ${filePath}`);
|
|
264
279
|
};
|
|
265
280
|
let _is_launched = false;
|
|
266
281
|
class ResolveService {
|
|
267
282
|
constructor() {
|
|
268
283
|
this.loggerService = inject(TYPES.loggerService);
|
|
284
|
+
this.babelService = inject(TYPES.babelService);
|
|
269
285
|
this.DEFAULT_TEMPLATE_DIR = path.resolve(__dirname$1, '..', 'template');
|
|
270
286
|
this.OVERRIDE_TEMPLATE_DIR = path.resolve(process.cwd(), 'template');
|
|
271
287
|
this.OVERRIDE_MODULES_DIR = path.resolve(process.cwd(), 'modules');
|
|
@@ -282,7 +298,7 @@ class ResolveService {
|
|
|
282
298
|
process.chdir(moduleRoot);
|
|
283
299
|
dotenv.config({ path: path.join(cwd, '.env'), override: true, quiet: true });
|
|
284
300
|
dotenv.config({ path: path.join(moduleRoot, '.env'), override: true, quiet: true });
|
|
285
|
-
await LOAD_ENTRY_FN(absolutePath);
|
|
301
|
+
await LOAD_ENTRY_FN(absolutePath, this);
|
|
286
302
|
await entrySubject.next(absolutePath);
|
|
287
303
|
}
|
|
288
304
|
_is_launched = true;
|
|
@@ -312,7 +328,7 @@ var ExchangeName$1 = ExchangeName;
|
|
|
312
328
|
const ADD_EXCHANGE_FN = (self) => {
|
|
313
329
|
self.loggerService.log("Adding CCXT Binance as a default exchange schema");
|
|
314
330
|
console.warn("Warning: The default exchange schema is set to CCXT Binance. Please make sure to update it according to your needs using --exchange cli param.");
|
|
315
|
-
|
|
331
|
+
BacktestKit.addExchangeSchema({
|
|
316
332
|
exchangeName: ExchangeName$1.DefaultExchange,
|
|
317
333
|
getCandles: async (symbol, interval, since, limit) => {
|
|
318
334
|
const exchange = await getExchange();
|
|
@@ -331,7 +347,7 @@ const ADD_EXCHANGE_FN = (self) => {
|
|
|
331
347
|
const market = exchange.market(symbol);
|
|
332
348
|
const tickSize = market.limits?.price?.min || market.precision?.price;
|
|
333
349
|
if (tickSize !== undefined) {
|
|
334
|
-
return
|
|
350
|
+
return BacktestKit.roundTicks(price, tickSize);
|
|
335
351
|
}
|
|
336
352
|
return exchange.priceToPrecision(symbol, price);
|
|
337
353
|
},
|
|
@@ -340,7 +356,7 @@ const ADD_EXCHANGE_FN = (self) => {
|
|
|
340
356
|
const market = exchange.market(symbol);
|
|
341
357
|
const stepSize = market.limits?.amount?.min || market.precision?.amount;
|
|
342
358
|
if (stepSize !== undefined) {
|
|
343
|
-
return
|
|
359
|
+
return BacktestKit.roundTicks(quantity, stepSize);
|
|
344
360
|
}
|
|
345
361
|
return exchange.amountToPrecision(symbol, quantity);
|
|
346
362
|
},
|
|
@@ -369,7 +385,7 @@ class ExchangeSchemaService {
|
|
|
369
385
|
this.loggerService = inject(TYPES.loggerService);
|
|
370
386
|
this.addSchema = functoolsKit.singleshot(async () => {
|
|
371
387
|
this.loggerService.log("exchangeSchemaService addSchema");
|
|
372
|
-
const { length } = await
|
|
388
|
+
const { length } = await BacktestKit.listExchangeSchema();
|
|
373
389
|
!length && ADD_EXCHANGE_FN(this);
|
|
374
390
|
});
|
|
375
391
|
}
|
|
@@ -446,7 +462,7 @@ const getArgs = functoolsKit.singleshot(() => {
|
|
|
446
462
|
const ADD_FRAME_FN = (self) => {
|
|
447
463
|
self.loggerService.log("Adding February 2024 as a default frame schema");
|
|
448
464
|
console.warn("Warning: The default frame schema is set to February 2024. Please make sure to update it according to your needs using --frame cli param.");
|
|
449
|
-
|
|
465
|
+
BacktestKit.addFrameSchema({
|
|
450
466
|
frameName: FrameName$1.DefaultFrame,
|
|
451
467
|
interval: "1m",
|
|
452
468
|
startDate: new Date("2024-02-01T00:00:00Z"),
|
|
@@ -461,7 +477,7 @@ class FrameSchemaService {
|
|
|
461
477
|
if (!getArgs().values.backtest) {
|
|
462
478
|
return;
|
|
463
479
|
}
|
|
464
|
-
const { length } = await
|
|
480
|
+
const { length } = await BacktestKit.listFrameSchema();
|
|
465
481
|
!length && ADD_FRAME_FN(this);
|
|
466
482
|
});
|
|
467
483
|
}
|
|
@@ -481,11 +497,11 @@ class SymbolSchemaService {
|
|
|
481
497
|
|
|
482
498
|
const notifyFinish = functoolsKit.singleshot(() => {
|
|
483
499
|
let disposeRef;
|
|
484
|
-
const unLive =
|
|
500
|
+
const unLive = BacktestKit.listenDoneLive(() => {
|
|
485
501
|
console.log("Live trading finished");
|
|
486
502
|
disposeRef && disposeRef();
|
|
487
503
|
});
|
|
488
|
-
const unBacktest =
|
|
504
|
+
const unBacktest = BacktestKit.listenDoneBacktest(() => {
|
|
489
505
|
console.log("Backtest trading finished");
|
|
490
506
|
disposeRef && disposeRef();
|
|
491
507
|
});
|
|
@@ -499,7 +515,7 @@ const getEntry = (metaUrl) => {
|
|
|
499
515
|
|
|
500
516
|
const notifyVerbose = functoolsKit.singleshot(() => {
|
|
501
517
|
console.log("Using verbose logging...");
|
|
502
|
-
|
|
518
|
+
BacktestKit.listenSignal((event) => {
|
|
503
519
|
if (event.action === "scheduled") {
|
|
504
520
|
console.log(`[POSITION SCHEDULED] ${event.symbol}`);
|
|
505
521
|
console.log(` Strategy: ${event.strategyName}`);
|
|
@@ -579,9 +595,9 @@ class BacktestMainService {
|
|
|
579
595
|
this.frameSchemaService.addSchema();
|
|
580
596
|
}
|
|
581
597
|
const symbol = payload.symbol || "BTCUSDT";
|
|
582
|
-
const [defaultStrategyName = null] = await
|
|
583
|
-
const [defaultExchangeName = null] = await
|
|
584
|
-
const [defaultFrameName = null] = await
|
|
598
|
+
const [defaultStrategyName = null] = await BacktestKit.listStrategySchema();
|
|
599
|
+
const [defaultExchangeName = null] = await BacktestKit.listExchangeSchema();
|
|
600
|
+
const [defaultFrameName = null] = await BacktestKit.listFrameSchema();
|
|
585
601
|
const strategyName = payload.strategy || defaultStrategyName?.strategyName;
|
|
586
602
|
if (!strategyName) {
|
|
587
603
|
throw new Error("Strategy name is required");
|
|
@@ -602,7 +618,7 @@ class BacktestMainService {
|
|
|
602
618
|
});
|
|
603
619
|
}
|
|
604
620
|
if (payload.verbose) {
|
|
605
|
-
|
|
621
|
+
BacktestKit.overrideExchangeSchema({
|
|
606
622
|
exchangeName,
|
|
607
623
|
callbacks: {
|
|
608
624
|
onCandleData(symbol, interval, since) {
|
|
@@ -612,7 +628,7 @@ class BacktestMainService {
|
|
|
612
628
|
});
|
|
613
629
|
notifyVerbose();
|
|
614
630
|
}
|
|
615
|
-
|
|
631
|
+
BacktestKit.Backtest.background(symbol, {
|
|
616
632
|
strategyName,
|
|
617
633
|
frameName,
|
|
618
634
|
exchangeName,
|
|
@@ -671,8 +687,8 @@ class LiveMainService {
|
|
|
671
687
|
this.symbolSchemaService.addSchema();
|
|
672
688
|
}
|
|
673
689
|
const symbol = payload.symbol || "BTCUSDT";
|
|
674
|
-
const [defaultStrategyName = null] = await
|
|
675
|
-
const [defaultExchangeName = null] = await
|
|
690
|
+
const [defaultStrategyName = null] = await BacktestKit.listStrategySchema();
|
|
691
|
+
const [defaultExchangeName = null] = await BacktestKit.listExchangeSchema();
|
|
676
692
|
const strategyName = payload.strategy || defaultStrategyName?.strategyName;
|
|
677
693
|
if (!strategyName) {
|
|
678
694
|
throw new Error("Strategy name is required");
|
|
@@ -682,7 +698,7 @@ class LiveMainService {
|
|
|
682
698
|
throw new Error("Exchange name is required");
|
|
683
699
|
}
|
|
684
700
|
if (payload.verbose) {
|
|
685
|
-
|
|
701
|
+
BacktestKit.overrideExchangeSchema({
|
|
686
702
|
exchangeName,
|
|
687
703
|
callbacks: {
|
|
688
704
|
onCandleData(symbol, interval, since) {
|
|
@@ -692,7 +708,7 @@ class LiveMainService {
|
|
|
692
708
|
});
|
|
693
709
|
notifyVerbose();
|
|
694
710
|
}
|
|
695
|
-
|
|
711
|
+
BacktestKit.Live.background(symbol, {
|
|
696
712
|
strategyName,
|
|
697
713
|
exchangeName,
|
|
698
714
|
});
|
|
@@ -742,8 +758,8 @@ class PaperMainService {
|
|
|
742
758
|
this.symbolSchemaService.addSchema();
|
|
743
759
|
}
|
|
744
760
|
const symbol = payload.symbol || "BTCUSDT";
|
|
745
|
-
const [defaultStrategyName = null] = await
|
|
746
|
-
const [defaultExchangeName = null] = await
|
|
761
|
+
const [defaultStrategyName = null] = await BacktestKit.listStrategySchema();
|
|
762
|
+
const [defaultExchangeName = null] = await BacktestKit.listExchangeSchema();
|
|
747
763
|
const strategyName = payload.strategy || defaultStrategyName?.strategyName;
|
|
748
764
|
if (!strategyName) {
|
|
749
765
|
throw new Error("Strategy name is required");
|
|
@@ -753,7 +769,7 @@ class PaperMainService {
|
|
|
753
769
|
throw new Error("Exchange name is required");
|
|
754
770
|
}
|
|
755
771
|
if (payload.verbose) {
|
|
756
|
-
|
|
772
|
+
BacktestKit.overrideExchangeSchema({
|
|
757
773
|
exchangeName,
|
|
758
774
|
callbacks: {
|
|
759
775
|
onCandleData(symbol, interval, since) {
|
|
@@ -763,7 +779,7 @@ class PaperMainService {
|
|
|
763
779
|
});
|
|
764
780
|
notifyVerbose();
|
|
765
781
|
}
|
|
766
|
-
|
|
782
|
+
BacktestKit.Live.background(symbol, {
|
|
767
783
|
strategyName,
|
|
768
784
|
exchangeName,
|
|
769
785
|
});
|
|
@@ -873,7 +889,7 @@ class TelegramProviderService {
|
|
|
873
889
|
|
|
874
890
|
const CANDLES_LIMIT = 160;
|
|
875
891
|
const GET_CONFIG_FN = async (symbol, interval) => {
|
|
876
|
-
const candles = await
|
|
892
|
+
const candles = await BacktestKit.getCandles(symbol, interval, CANDLES_LIMIT);
|
|
877
893
|
const labels = candles.map(({ timestamp }) => new Date(timestamp).toLocaleTimeString("en-US", {
|
|
878
894
|
hour: "2-digit",
|
|
879
895
|
minute: "2-digit",
|
|
@@ -1289,7 +1305,7 @@ class TelegramWebService {
|
|
|
1289
1305
|
}
|
|
1290
1306
|
|
|
1291
1307
|
const GET_TIMEFRAME_RANGE_FN = async (frameName) => {
|
|
1292
|
-
const frameList = await
|
|
1308
|
+
const frameList = await BacktestKit.listFrameSchema();
|
|
1293
1309
|
const frameSchema = frameList.find((frameSchema) => frameSchema.frameName === frameName);
|
|
1294
1310
|
if (!frameSchema) {
|
|
1295
1311
|
throw new Error(`Frame with name ${frameName} not found`);
|
|
@@ -1300,7 +1316,7 @@ const GET_TIMEFRAME_RANGE_FN = async (frameName) => {
|
|
|
1300
1316
|
const CACHE_CANDLES_FN = functoolsKit.retry(async (interval, dto) => {
|
|
1301
1317
|
try {
|
|
1302
1318
|
console.log(`Checking candles cache for ${dto.symbol} ${interval} from ${dto.from} to ${dto.to}`);
|
|
1303
|
-
await
|
|
1319
|
+
await BacktestKit.checkCandles({
|
|
1304
1320
|
exchangeName: dto.exchangeName,
|
|
1305
1321
|
from: dto.from,
|
|
1306
1322
|
to: dto.to,
|
|
@@ -1310,7 +1326,7 @@ const CACHE_CANDLES_FN = functoolsKit.retry(async (interval, dto) => {
|
|
|
1310
1326
|
}
|
|
1311
1327
|
catch (error) {
|
|
1312
1328
|
console.log(`Caching candles for ${dto.symbol} ${interval} from ${dto.from} to ${dto.to}`);
|
|
1313
|
-
await
|
|
1329
|
+
await BacktestKit.warmCandles({
|
|
1314
1330
|
symbol: dto.symbol,
|
|
1315
1331
|
exchangeName: dto.exchangeName,
|
|
1316
1332
|
from: dto.from,
|
|
@@ -1467,10 +1483,10 @@ class TelegramLogicService {
|
|
|
1467
1483
|
};
|
|
1468
1484
|
this.connect = functoolsKit.singleshot(() => {
|
|
1469
1485
|
this.loggerService.log("telegramLogicService connect");
|
|
1470
|
-
const unRisk =
|
|
1486
|
+
const unRisk = BacktestKit.listenRisk(async (event) => {
|
|
1471
1487
|
await this.notifyRisk(event);
|
|
1472
1488
|
});
|
|
1473
|
-
const unSignal =
|
|
1489
|
+
const unSignal = BacktestKit.listenSignal(async (event) => {
|
|
1474
1490
|
if (event.action === "scheduled") {
|
|
1475
1491
|
await this.notifyScheduled(event);
|
|
1476
1492
|
return;
|
|
@@ -1488,7 +1504,7 @@ class TelegramLogicService {
|
|
|
1488
1504
|
return;
|
|
1489
1505
|
}
|
|
1490
1506
|
});
|
|
1491
|
-
const unCommit =
|
|
1507
|
+
const unCommit = BacktestKit.listenStrategyCommit(async (event) => {
|
|
1492
1508
|
if (event.action === "trailing-take") {
|
|
1493
1509
|
await this.notifyTrailingTake(event);
|
|
1494
1510
|
return;
|
|
@@ -1631,9 +1647,16 @@ const REQUIRE_MODULE_FACTORY = (fileName) => {
|
|
|
1631
1647
|
return null;
|
|
1632
1648
|
};
|
|
1633
1649
|
const IMPORT_MODULE_FACTORY = async (fileName) => {
|
|
1650
|
+
{
|
|
1651
|
+
return null;
|
|
1652
|
+
}
|
|
1653
|
+
};
|
|
1654
|
+
const BABEL_MODULE_FACTORY = async (fileName, self) => {
|
|
1634
1655
|
for (const variant of getExtVariants(fileName)) {
|
|
1635
1656
|
try {
|
|
1636
|
-
|
|
1657
|
+
const code = await fs$1.readFile(variant, "utf-8");
|
|
1658
|
+
const exports = self.babelService.transpileAndRun(code);
|
|
1659
|
+
return exports.default ?? exports;
|
|
1637
1660
|
}
|
|
1638
1661
|
catch {
|
|
1639
1662
|
continue;
|
|
@@ -1653,7 +1676,10 @@ const LOAD_MODULE_MODULE_FN = async (fileName, self) => {
|
|
|
1653
1676
|
if ((Ctor = REQUIRE_MODULE_FACTORY(resolvedFile))) {
|
|
1654
1677
|
return typeof Ctor === "function" ? new Ctor() : Ctor;
|
|
1655
1678
|
}
|
|
1656
|
-
if ((Ctor = await IMPORT_MODULE_FACTORY(
|
|
1679
|
+
if ((Ctor = await IMPORT_MODULE_FACTORY())) {
|
|
1680
|
+
return typeof Ctor === "function" ? new Ctor() : Ctor;
|
|
1681
|
+
}
|
|
1682
|
+
if ((Ctor = await BABEL_MODULE_FACTORY(resolvedFile, self))) {
|
|
1657
1683
|
return typeof Ctor === "function" ? new Ctor() : Ctor;
|
|
1658
1684
|
}
|
|
1659
1685
|
throw new Error(`Module module import failed for file: ${resolvedFile}`);
|
|
@@ -1662,6 +1688,7 @@ class ModuleConnectionService {
|
|
|
1662
1688
|
constructor() {
|
|
1663
1689
|
this.loggerService = inject(TYPES.loggerService);
|
|
1664
1690
|
this.resolveService = inject(TYPES.resolveService);
|
|
1691
|
+
this.babelService = inject(TYPES.babelService);
|
|
1665
1692
|
this.getInstance = functoolsKit.memoize(([fileName]) => `${fileName}`, async (fileName) => {
|
|
1666
1693
|
this.loggerService.log("moduleConnectionService getInstance", {
|
|
1667
1694
|
fileName,
|
|
@@ -1788,10 +1815,10 @@ class LiveProviderService {
|
|
|
1788
1815
|
console.log("No ./modules/live.module.mjs found, live trading failed to initialize");
|
|
1789
1816
|
process.exit(-1);
|
|
1790
1817
|
});
|
|
1791
|
-
const unRisk =
|
|
1818
|
+
const unRisk = BacktestKit.listenRisk(async (event) => {
|
|
1792
1819
|
await this.handleRisk(event);
|
|
1793
1820
|
});
|
|
1794
|
-
const unSignal =
|
|
1821
|
+
const unSignal = BacktestKit.listenSignal(async (event) => {
|
|
1795
1822
|
if (event.action === "scheduled") {
|
|
1796
1823
|
await this.handleScheduled(event);
|
|
1797
1824
|
return;
|
|
@@ -1809,7 +1836,7 @@ class LiveProviderService {
|
|
|
1809
1836
|
return;
|
|
1810
1837
|
}
|
|
1811
1838
|
});
|
|
1812
|
-
const unCommit =
|
|
1839
|
+
const unCommit = BacktestKit.listenStrategyCommit(async (event) => {
|
|
1813
1840
|
if (event.action === "trailing-take") {
|
|
1814
1841
|
await this.handleTrailingTake(event);
|
|
1815
1842
|
return;
|
|
@@ -1855,6 +1882,55 @@ class LiveProviderService {
|
|
|
1855
1882
|
}
|
|
1856
1883
|
}
|
|
1857
1884
|
|
|
1885
|
+
standalone.registerPlugin("plugin-transform-modules-umd", pluginUMD);
|
|
1886
|
+
module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
|
|
1887
|
+
const __filename$1 = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
|
|
1888
|
+
path.dirname(__filename$1);
|
|
1889
|
+
const BacktestKitCli = new Proxy({}, {
|
|
1890
|
+
get(_target, prop) {
|
|
1891
|
+
throw new Error(`@backtest-kit/cli is not available in this context (accessed: ${String(prop)})`);
|
|
1892
|
+
},
|
|
1893
|
+
});
|
|
1894
|
+
class BabelService {
|
|
1895
|
+
constructor() {
|
|
1896
|
+
this.loggerService = inject(TYPES.loggerService);
|
|
1897
|
+
this.transpile = (code) => {
|
|
1898
|
+
this.loggerService.log("babelService transpile", { codeLen: code.length });
|
|
1899
|
+
const result = standalone.transform(code, {
|
|
1900
|
+
filename: "index.ts",
|
|
1901
|
+
presets: ["env", "typescript"],
|
|
1902
|
+
plugins: [
|
|
1903
|
+
[
|
|
1904
|
+
"plugin-transform-modules-umd",
|
|
1905
|
+
{
|
|
1906
|
+
globals: {
|
|
1907
|
+
"backtest-kit": "BacktestKit",
|
|
1908
|
+
"@backtest-kit/cli": "BacktestKitCli",
|
|
1909
|
+
},
|
|
1910
|
+
moduleId: "Executor",
|
|
1911
|
+
},
|
|
1912
|
+
],
|
|
1913
|
+
],
|
|
1914
|
+
parserOpts: { strictMode: false },
|
|
1915
|
+
});
|
|
1916
|
+
if (!result.code) {
|
|
1917
|
+
throw new Error("BabelService transpile failed");
|
|
1918
|
+
}
|
|
1919
|
+
return result.code;
|
|
1920
|
+
};
|
|
1921
|
+
this.transpileAndRun = (code) => {
|
|
1922
|
+
this.loggerService.log("babelService transpileAndRun", {
|
|
1923
|
+
codeLen: code.length,
|
|
1924
|
+
});
|
|
1925
|
+
const module = { exports: {} };
|
|
1926
|
+
eval(this.transpile(code));
|
|
1927
|
+
return module.exports;
|
|
1928
|
+
};
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1931
|
+
globalThis.BacktestKit = BacktestKit__namespace;
|
|
1932
|
+
globalThis.BacktestKitCli = BacktestKitCli;
|
|
1933
|
+
|
|
1858
1934
|
{
|
|
1859
1935
|
provide(TYPES.quickchartApiService, () => new QuickchartApiService());
|
|
1860
1936
|
provide(TYPES.telegramApiService, () => new TelegramApiService());
|
|
@@ -1863,6 +1939,7 @@ class LiveProviderService {
|
|
|
1863
1939
|
provide(TYPES.errorService, () => new ErrorService());
|
|
1864
1940
|
provide(TYPES.loggerService, () => new LoggerService());
|
|
1865
1941
|
provide(TYPES.resolveService, () => new ResolveService());
|
|
1942
|
+
provide(TYPES.babelService, () => new BabelService());
|
|
1866
1943
|
}
|
|
1867
1944
|
{
|
|
1868
1945
|
provide(TYPES.moduleConnectionService, () => new ModuleConnectionService());
|
|
@@ -1901,6 +1978,7 @@ const baseServices = {
|
|
|
1901
1978
|
errorService: inject(TYPES.errorService),
|
|
1902
1979
|
loggerService: inject(TYPES.loggerService),
|
|
1903
1980
|
resolveService: inject(TYPES.resolveService),
|
|
1981
|
+
babelService: inject(TYPES.babelService),
|
|
1904
1982
|
};
|
|
1905
1983
|
const connectionServices = {
|
|
1906
1984
|
moduleConnectionService: inject(TYPES.moduleConnectionService),
|
|
@@ -1949,7 +2027,7 @@ const notifyShutdown = functoolsKit.singleshot(async () => {
|
|
|
1949
2027
|
|
|
1950
2028
|
const BEFORE_EXIT_FN$4 = functoolsKit.singleshot(async () => {
|
|
1951
2029
|
process.off("SIGINT", BEFORE_EXIT_FN$4);
|
|
1952
|
-
const [running = null] = await
|
|
2030
|
+
const [running = null] = await BacktestKit.Backtest.list();
|
|
1953
2031
|
if (!running) {
|
|
1954
2032
|
return;
|
|
1955
2033
|
}
|
|
@@ -1958,7 +2036,7 @@ const BEFORE_EXIT_FN$4 = functoolsKit.singleshot(async () => {
|
|
|
1958
2036
|
if (status === "fulfilled") {
|
|
1959
2037
|
return;
|
|
1960
2038
|
}
|
|
1961
|
-
|
|
2039
|
+
BacktestKit.Backtest.stop(symbol, {
|
|
1962
2040
|
exchangeName,
|
|
1963
2041
|
strategyName,
|
|
1964
2042
|
frameName,
|
|
@@ -1982,7 +2060,7 @@ main$4();
|
|
|
1982
2060
|
|
|
1983
2061
|
const BEFORE_EXIT_FN$3 = functoolsKit.singleshot(async () => {
|
|
1984
2062
|
process.off("SIGINT", BEFORE_EXIT_FN$3);
|
|
1985
|
-
const [running = null] = await
|
|
2063
|
+
const [running = null] = await BacktestKit.Live.list();
|
|
1986
2064
|
if (!running) {
|
|
1987
2065
|
return;
|
|
1988
2066
|
}
|
|
@@ -1991,7 +2069,7 @@ const BEFORE_EXIT_FN$3 = functoolsKit.singleshot(async () => {
|
|
|
1991
2069
|
if (status === "fulfilled") {
|
|
1992
2070
|
return;
|
|
1993
2071
|
}
|
|
1994
|
-
|
|
2072
|
+
BacktestKit.Live.stop(symbol, {
|
|
1995
2073
|
exchangeName,
|
|
1996
2074
|
strategyName,
|
|
1997
2075
|
});
|
|
@@ -2014,7 +2092,7 @@ main$3();
|
|
|
2014
2092
|
|
|
2015
2093
|
const BEFORE_EXIT_FN$2 = functoolsKit.singleshot(async () => {
|
|
2016
2094
|
process.off("SIGINT", BEFORE_EXIT_FN$2);
|
|
2017
|
-
const [running = null] = await
|
|
2095
|
+
const [running = null] = await BacktestKit.Live.list();
|
|
2018
2096
|
if (!running) {
|
|
2019
2097
|
return;
|
|
2020
2098
|
}
|
|
@@ -2023,11 +2101,11 @@ const BEFORE_EXIT_FN$2 = functoolsKit.singleshot(async () => {
|
|
|
2023
2101
|
if (status === "fulfilled") {
|
|
2024
2102
|
return;
|
|
2025
2103
|
}
|
|
2026
|
-
|
|
2104
|
+
BacktestKit.Live.stop(symbol, {
|
|
2027
2105
|
exchangeName,
|
|
2028
2106
|
strategyName,
|
|
2029
2107
|
});
|
|
2030
|
-
|
|
2108
|
+
BacktestKit.listenDoneLive(cli.liveProviderService.disable);
|
|
2031
2109
|
});
|
|
2032
2110
|
const listenGracefulShutdown$2 = functoolsKit.singleshot(() => {
|
|
2033
2111
|
process.on("SIGINT", BEFORE_EXIT_FN$2);
|
package/build/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import * as BacktestKit from 'backtest-kit';
|
|
2
3
|
import { Storage, Notification, Markdown, Report, StorageLive, StorageBacktest, NotificationLive, NotificationBacktest, setConfig, listExchangeSchema, addExchangeSchema, roundTicks, listFrameSchema, addFrameSchema, listenDoneLive, listenDoneBacktest, listenSignal, listStrategySchema, overrideExchangeSchema, Backtest, Live, getCandles, checkCandles, warmCandles, listenRisk, listenStrategyCommit } from 'backtest-kit';
|
|
3
4
|
import { getErrorMessage, errorData, singleshot, str, BehaviorSubject, compose, execpool, queued, sleep, randomString, createAwaiter, TIMEOUT_SYMBOL, typo, retry, memoize, trycatch } from 'functools-kit';
|
|
4
5
|
import fs, { constants } from 'fs';
|
|
@@ -21,6 +22,8 @@ import MarkdownIt from 'markdown-it';
|
|
|
21
22
|
import sanitizeHtml from 'sanitize-html';
|
|
22
23
|
import { JSDOM } from 'jsdom';
|
|
23
24
|
import Mustache from 'mustache';
|
|
25
|
+
import { registerPlugin, transform } from '@babel/standalone';
|
|
26
|
+
import pluginUMD from '@babel/plugin-transform-modules-umd';
|
|
24
27
|
|
|
25
28
|
/**
|
|
26
29
|
* Fix for `Attempted to assign to readonly property (at redactToken)`
|
|
@@ -169,6 +172,7 @@ const baseServices$1 = {
|
|
|
169
172
|
errorService: Symbol('errorService'),
|
|
170
173
|
loggerService: Symbol('loggerService'),
|
|
171
174
|
resolveService: Symbol('resolveService'),
|
|
175
|
+
babelService: Symbol('babelService'),
|
|
172
176
|
};
|
|
173
177
|
const connectionServices$1 = {
|
|
174
178
|
moduleConnectionService: Symbol('moduleConnectionService'),
|
|
@@ -212,38 +216,50 @@ const TYPES = {
|
|
|
212
216
|
|
|
213
217
|
const entrySubject = new BehaviorSubject();
|
|
214
218
|
|
|
215
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
216
|
-
const __dirname = path.dirname(__filename);
|
|
217
|
-
|
|
219
|
+
const __filename$1 = fileURLToPath(import.meta.url);
|
|
220
|
+
const __dirname = path.dirname(__filename$1);
|
|
221
|
+
createRequire(import.meta.url);
|
|
218
222
|
const REQUIRE_ENTRY_FACTORY = (filePath) => {
|
|
223
|
+
{
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
const IMPORT_ENTRY_FACTORY = async (filePath) => {
|
|
219
228
|
try {
|
|
220
|
-
|
|
229
|
+
await import(pathToFileURL(filePath).href);
|
|
221
230
|
return true;
|
|
222
231
|
}
|
|
223
232
|
catch {
|
|
224
233
|
return false;
|
|
225
234
|
}
|
|
226
235
|
};
|
|
227
|
-
const
|
|
228
|
-
await
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
236
|
+
const BABEL_ENTRY_FACTORY = async (filePath, self) => {
|
|
237
|
+
const code = await fs$1.readFile(filePath, "utf-8");
|
|
238
|
+
try {
|
|
239
|
+
await self.babelService.transpileAndRun(code);
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
catch {
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
233
245
|
};
|
|
234
|
-
const LOAD_ENTRY_FN = async (filePath) => {
|
|
235
|
-
if (
|
|
236
|
-
await TSX_ENTRY_FACTORY(filePath);
|
|
246
|
+
const LOAD_ENTRY_FN = async (filePath, self) => {
|
|
247
|
+
if (REQUIRE_ENTRY_FACTORY()) {
|
|
237
248
|
return;
|
|
238
249
|
}
|
|
239
|
-
if (
|
|
240
|
-
|
|
250
|
+
if (await IMPORT_ENTRY_FACTORY(filePath)) {
|
|
251
|
+
return;
|
|
241
252
|
}
|
|
253
|
+
if (await BABEL_ENTRY_FACTORY(filePath, self)) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
throw new Error(`Failed to load entry point: ${filePath}`);
|
|
242
257
|
};
|
|
243
258
|
let _is_launched = false;
|
|
244
259
|
class ResolveService {
|
|
245
260
|
constructor() {
|
|
246
261
|
this.loggerService = inject(TYPES.loggerService);
|
|
262
|
+
this.babelService = inject(TYPES.babelService);
|
|
247
263
|
this.DEFAULT_TEMPLATE_DIR = path.resolve(__dirname, '..', 'template');
|
|
248
264
|
this.OVERRIDE_TEMPLATE_DIR = path.resolve(process.cwd(), 'template');
|
|
249
265
|
this.OVERRIDE_MODULES_DIR = path.resolve(process.cwd(), 'modules');
|
|
@@ -260,7 +276,7 @@ class ResolveService {
|
|
|
260
276
|
process.chdir(moduleRoot);
|
|
261
277
|
dotenv.config({ path: path.join(cwd, '.env'), override: true, quiet: true });
|
|
262
278
|
dotenv.config({ path: path.join(moduleRoot, '.env'), override: true, quiet: true });
|
|
263
|
-
await LOAD_ENTRY_FN(absolutePath);
|
|
279
|
+
await LOAD_ENTRY_FN(absolutePath, this);
|
|
264
280
|
await entrySubject.next(absolutePath);
|
|
265
281
|
}
|
|
266
282
|
_is_launched = true;
|
|
@@ -1591,16 +1607,21 @@ class TelegramTemplateService {
|
|
|
1591
1607
|
}
|
|
1592
1608
|
}
|
|
1593
1609
|
|
|
1594
|
-
|
|
1610
|
+
createRequire(import.meta.url);
|
|
1595
1611
|
const getExtVariants = (fileName) => {
|
|
1596
1612
|
const ext = path.extname(fileName);
|
|
1597
1613
|
const base = ext ? fileName.slice(0, -ext.length) : fileName;
|
|
1598
1614
|
return [fileName, `${base}.cjs`, `${base}.mjs`];
|
|
1599
1615
|
};
|
|
1600
1616
|
const REQUIRE_MODULE_FACTORY = (fileName) => {
|
|
1617
|
+
{
|
|
1618
|
+
return null;
|
|
1619
|
+
}
|
|
1620
|
+
};
|
|
1621
|
+
const IMPORT_MODULE_FACTORY = async (fileName) => {
|
|
1601
1622
|
for (const variant of getExtVariants(fileName)) {
|
|
1602
1623
|
try {
|
|
1603
|
-
return
|
|
1624
|
+
return await import(pathToFileURL(variant).href);
|
|
1604
1625
|
}
|
|
1605
1626
|
catch {
|
|
1606
1627
|
continue;
|
|
@@ -1608,10 +1629,12 @@ const REQUIRE_MODULE_FACTORY = (fileName) => {
|
|
|
1608
1629
|
}
|
|
1609
1630
|
return null;
|
|
1610
1631
|
};
|
|
1611
|
-
const
|
|
1632
|
+
const BABEL_MODULE_FACTORY = async (fileName, self) => {
|
|
1612
1633
|
for (const variant of getExtVariants(fileName)) {
|
|
1613
1634
|
try {
|
|
1614
|
-
|
|
1635
|
+
const code = await fs$1.readFile(variant, "utf-8");
|
|
1636
|
+
const exports = self.babelService.transpileAndRun(code);
|
|
1637
|
+
return exports.default ?? exports;
|
|
1615
1638
|
}
|
|
1616
1639
|
catch {
|
|
1617
1640
|
continue;
|
|
@@ -1628,18 +1651,22 @@ const LOAD_MODULE_MODULE_FN = async (fileName, self) => {
|
|
|
1628
1651
|
.then(() => true)
|
|
1629
1652
|
.catch(() => false);
|
|
1630
1653
|
const resolvedFile = hasOverride ? overridePath : targetPath;
|
|
1631
|
-
if ((Ctor = REQUIRE_MODULE_FACTORY(
|
|
1654
|
+
if ((Ctor = REQUIRE_MODULE_FACTORY())) {
|
|
1632
1655
|
return typeof Ctor === "function" ? new Ctor() : Ctor;
|
|
1633
1656
|
}
|
|
1634
1657
|
if ((Ctor = await IMPORT_MODULE_FACTORY(resolvedFile))) {
|
|
1635
1658
|
return typeof Ctor === "function" ? new Ctor() : Ctor;
|
|
1636
1659
|
}
|
|
1660
|
+
if ((Ctor = await BABEL_MODULE_FACTORY(resolvedFile, self))) {
|
|
1661
|
+
return typeof Ctor === "function" ? new Ctor() : Ctor;
|
|
1662
|
+
}
|
|
1637
1663
|
throw new Error(`Module module import failed for file: ${resolvedFile}`);
|
|
1638
1664
|
};
|
|
1639
1665
|
class ModuleConnectionService {
|
|
1640
1666
|
constructor() {
|
|
1641
1667
|
this.loggerService = inject(TYPES.loggerService);
|
|
1642
1668
|
this.resolveService = inject(TYPES.resolveService);
|
|
1669
|
+
this.babelService = inject(TYPES.babelService);
|
|
1643
1670
|
this.getInstance = memoize(([fileName]) => `${fileName}`, async (fileName) => {
|
|
1644
1671
|
this.loggerService.log("moduleConnectionService getInstance", {
|
|
1645
1672
|
fileName,
|
|
@@ -1833,6 +1860,55 @@ class LiveProviderService {
|
|
|
1833
1860
|
}
|
|
1834
1861
|
}
|
|
1835
1862
|
|
|
1863
|
+
registerPlugin("plugin-transform-modules-umd", pluginUMD);
|
|
1864
|
+
createRequire(import.meta.url);
|
|
1865
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
1866
|
+
path.dirname(__filename);
|
|
1867
|
+
const BacktestKitCli = new Proxy({}, {
|
|
1868
|
+
get(_target, prop) {
|
|
1869
|
+
throw new Error(`@backtest-kit/cli is not available in this context (accessed: ${String(prop)})`);
|
|
1870
|
+
},
|
|
1871
|
+
});
|
|
1872
|
+
class BabelService {
|
|
1873
|
+
constructor() {
|
|
1874
|
+
this.loggerService = inject(TYPES.loggerService);
|
|
1875
|
+
this.transpile = (code) => {
|
|
1876
|
+
this.loggerService.log("babelService transpile", { codeLen: code.length });
|
|
1877
|
+
const result = transform(code, {
|
|
1878
|
+
filename: "index.ts",
|
|
1879
|
+
presets: ["env", "typescript"],
|
|
1880
|
+
plugins: [
|
|
1881
|
+
[
|
|
1882
|
+
"plugin-transform-modules-umd",
|
|
1883
|
+
{
|
|
1884
|
+
globals: {
|
|
1885
|
+
"backtest-kit": "BacktestKit",
|
|
1886
|
+
"@backtest-kit/cli": "BacktestKitCli",
|
|
1887
|
+
},
|
|
1888
|
+
moduleId: "Executor",
|
|
1889
|
+
},
|
|
1890
|
+
],
|
|
1891
|
+
],
|
|
1892
|
+
parserOpts: { strictMode: false },
|
|
1893
|
+
});
|
|
1894
|
+
if (!result.code) {
|
|
1895
|
+
throw new Error("BabelService transpile failed");
|
|
1896
|
+
}
|
|
1897
|
+
return result.code;
|
|
1898
|
+
};
|
|
1899
|
+
this.transpileAndRun = (code) => {
|
|
1900
|
+
this.loggerService.log("babelService transpileAndRun", {
|
|
1901
|
+
codeLen: code.length,
|
|
1902
|
+
});
|
|
1903
|
+
const module = { exports: {} };
|
|
1904
|
+
eval(this.transpile(code));
|
|
1905
|
+
return module.exports;
|
|
1906
|
+
};
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
globalThis.BacktestKit = BacktestKit;
|
|
1910
|
+
globalThis.BacktestKitCli = BacktestKitCli;
|
|
1911
|
+
|
|
1836
1912
|
{
|
|
1837
1913
|
provide(TYPES.quickchartApiService, () => new QuickchartApiService());
|
|
1838
1914
|
provide(TYPES.telegramApiService, () => new TelegramApiService());
|
|
@@ -1841,6 +1917,7 @@ class LiveProviderService {
|
|
|
1841
1917
|
provide(TYPES.errorService, () => new ErrorService());
|
|
1842
1918
|
provide(TYPES.loggerService, () => new LoggerService());
|
|
1843
1919
|
provide(TYPES.resolveService, () => new ResolveService());
|
|
1920
|
+
provide(TYPES.babelService, () => new BabelService());
|
|
1844
1921
|
}
|
|
1845
1922
|
{
|
|
1846
1923
|
provide(TYPES.moduleConnectionService, () => new ModuleConnectionService());
|
|
@@ -1879,6 +1956,7 @@ const baseServices = {
|
|
|
1879
1956
|
errorService: inject(TYPES.errorService),
|
|
1880
1957
|
loggerService: inject(TYPES.loggerService),
|
|
1881
1958
|
resolveService: inject(TYPES.resolveService),
|
|
1959
|
+
babelService: inject(TYPES.babelService),
|
|
1882
1960
|
};
|
|
1883
1961
|
const connectionServices = {
|
|
1884
1962
|
moduleConnectionService: inject(TYPES.moduleConnectionService),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backtest-kit/cli",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.5",
|
|
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",
|
|
@@ -58,8 +58,10 @@
|
|
|
58
58
|
"default": "./build/index.cjs"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
|
+
"@babel/plugin-transform-modules-umd": "7.27.1",
|
|
62
|
+
"@babel/standalone": "7.29.1",
|
|
61
63
|
"@backtest-kit/ui": "3.3.2",
|
|
62
|
-
"
|
|
64
|
+
"@rollup/plugin-replace": "6.0.3",
|
|
63
65
|
"@rollup/plugin-typescript": "11.1.6",
|
|
64
66
|
"@types/image-size": "0.7.0",
|
|
65
67
|
"@types/jsdom": "21.1.7",
|
|
@@ -68,6 +70,7 @@
|
|
|
68
70
|
"@types/stack-trace": "0.0.33",
|
|
69
71
|
"backtest-kit": "3.3.2",
|
|
70
72
|
"glob": "11.0.1",
|
|
73
|
+
"markdown-it": "14.1.1",
|
|
71
74
|
"rimraf": "6.0.1",
|
|
72
75
|
"rollup": "3.29.5",
|
|
73
76
|
"rollup-plugin-dts": "6.1.1",
|
|
@@ -75,15 +78,15 @@
|
|
|
75
78
|
"ts-morph": "27.0.2",
|
|
76
79
|
"tslib": "2.7.0",
|
|
77
80
|
"typedoc": "0.27.9",
|
|
78
|
-
"tsx": "4.19.3",
|
|
79
81
|
"worker-testbed": "1.0.12"
|
|
80
82
|
},
|
|
81
83
|
"peerDependencies": {
|
|
82
|
-
"
|
|
84
|
+
"@babel/plugin-transform-modules-umd": "^7.27.1",
|
|
85
|
+
"@babel/standalone": "^7.29.1",
|
|
83
86
|
"@backtest-kit/ui": "^3.3.2",
|
|
84
87
|
"backtest-kit": "^3.3.2",
|
|
85
88
|
"markdown-it": "^14.1.1",
|
|
86
|
-
"
|
|
89
|
+
"typescript": "^5.0.0"
|
|
87
90
|
},
|
|
88
91
|
"dependencies": {
|
|
89
92
|
"ccxt": "4.5.39",
|
package/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as functools_kit from 'functools-kit';
|
|
2
|
+
import * as BacktestKit from 'backtest-kit';
|
|
2
3
|
import { CandleInterval, TrailingTakeCommit, TrailingStopCommit, BreakevenCommit, PartialProfitCommit, PartialLossCommit, IStrategyTickResultScheduled, IStrategyTickResultCancelled, IStrategyTickResultOpened, IStrategyTickResultClosed, RiskContract, AverageBuyCommit } from 'backtest-kit';
|
|
3
4
|
import { Input } from 'telegraf';
|
|
4
5
|
|
|
@@ -85,8 +86,22 @@ declare class FrameSchemaService {
|
|
|
85
86
|
addSchema: (() => Promise<void>) & functools_kit.ISingleshotClearable;
|
|
86
87
|
}
|
|
87
88
|
|
|
89
|
+
declare const BacktestKitCli: {};
|
|
90
|
+
declare global {
|
|
91
|
+
interface Window {
|
|
92
|
+
BacktestKit: typeof BacktestKit;
|
|
93
|
+
BacktestKitCli: typeof BacktestKitCli;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
declare class BabelService {
|
|
97
|
+
readonly loggerService: LoggerService;
|
|
98
|
+
transpile: (code: string) => any;
|
|
99
|
+
transpileAndRun: (code: string) => Record<string, unknown>;
|
|
100
|
+
}
|
|
101
|
+
|
|
88
102
|
declare class ResolveService {
|
|
89
|
-
|
|
103
|
+
readonly loggerService: LoggerService;
|
|
104
|
+
readonly babelService: BabelService;
|
|
90
105
|
readonly DEFAULT_TEMPLATE_DIR: string;
|
|
91
106
|
readonly OVERRIDE_TEMPLATE_DIR: string;
|
|
92
107
|
readonly OVERRIDE_MODULES_DIR: string;
|
|
@@ -203,6 +218,7 @@ type TBaseModuleCtor = new () => BaseModule;
|
|
|
203
218
|
declare class ModuleConnectionService {
|
|
204
219
|
readonly loggerService: LoggerService;
|
|
205
220
|
readonly resolveService: ResolveService;
|
|
221
|
+
readonly babelService: BabelService;
|
|
206
222
|
getInstance: ((fileName: string) => Promise<BaseModule>) & functools_kit.IClearableMemoize<string> & functools_kit.IControlMemoize<string, Promise<Partial<ILiveModule>>>;
|
|
207
223
|
}
|
|
208
224
|
|
|
@@ -243,6 +259,7 @@ declare const cli: {
|
|
|
243
259
|
errorService: ErrorService;
|
|
244
260
|
loggerService: LoggerService;
|
|
245
261
|
resolveService: ResolveService;
|
|
262
|
+
babelService: BabelService;
|
|
246
263
|
telegramApiService: TelegramApiService;
|
|
247
264
|
quickchartApiService: QuickchartApiService;
|
|
248
265
|
};
|