@backtest-kit/cli 7.1.0 → 7.3.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 +119 -0
- package/build/index.cjs +376 -149
- package/build/index.mjs +379 -152
- package/config/notification.config.mjs +13 -0
- package/config/symbol.config.mjs +460 -0
- package/package.json +16 -15
- package/template/average-buy.mustache +2 -0
- package/template/breakeven.mustache +2 -0
- package/template/cancel-scheduled.mustache +1 -1
- package/template/cancelled.mustache +2 -0
- package/template/close-pending.mustache +2 -0
- package/template/closed.mustache +2 -0
- package/template/opened.mustache +2 -0
- package/template/partial-loss.mustache +2 -0
- package/template/partial-profit.mustache +2 -0
- package/template/project/package.mustache +7 -7
- package/template/scheduled.mustache +2 -0
- package/template/signal-close.mustache +2 -0
- package/template/signal-info.mustache +21 -0
- package/template/signal-open.mustache +2 -0
- package/template/trailing-stop.mustache +2 -0
- package/template/trailing-take.mustache +2 -0
- package/types.d.ts +149 -39
- /package/template/project/config/{symbol.config.cjs → symbol.config.ts} +0 -0
package/build/index.cjs
CHANGED
|
@@ -88,6 +88,38 @@ var BacktestKitSignals__namespace = /*#__PURE__*/_interopNamespaceDefault(Backte
|
|
|
88
88
|
});
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
BacktestKit.setConfig({
|
|
92
|
+
CC_MAX_NOTIFICATIONS: 5000,
|
|
93
|
+
CC_MAX_SIGNALS: 750,
|
|
94
|
+
});
|
|
95
|
+
BacktestKit.setConfig({
|
|
96
|
+
CC_ENABLE_DCA_EVERYWHERE: true,
|
|
97
|
+
CC_ENABLE_PPPL_EVERYWHERE: true,
|
|
98
|
+
CC_ENABLE_TRAILING_EVERYWHERE: true,
|
|
99
|
+
});
|
|
100
|
+
BacktestKit.setConfig({
|
|
101
|
+
CC_MAX_SIGNAL_GENERATION_SECONDS: 15 * 60,
|
|
102
|
+
});
|
|
103
|
+
BacktestKit.setConfig({
|
|
104
|
+
CC_MAX_BACKTEST_MARKDOWN_ROWS: 1000,
|
|
105
|
+
CC_MAX_BREAKEVEN_MARKDOWN_ROWS: 1000,
|
|
106
|
+
CC_MAX_HEATMAP_MARKDOWN_ROWS: 1000,
|
|
107
|
+
CC_MAX_HIGHEST_PROFIT_MARKDOWN_ROWS: 1000,
|
|
108
|
+
CC_MAX_LIVE_MARKDOWN_ROWS: 1000,
|
|
109
|
+
CC_MAX_PARTIAL_MARKDOWN_ROWS: 1000,
|
|
110
|
+
CC_MAX_RISK_MARKDOWN_ROWS: 1000,
|
|
111
|
+
CC_MAX_SCHEDULE_MARKDOWN_ROWS: 1000,
|
|
112
|
+
CC_MAX_STRATEGY_MARKDOWN_ROWS: 1000,
|
|
113
|
+
CC_MAX_SYNC_MARKDOWN_ROWS: 1000,
|
|
114
|
+
CC_MAX_PERFORMANCE_MARKDOWN_ROWS: 1000,
|
|
115
|
+
});
|
|
116
|
+
BacktestKit.setConfig({
|
|
117
|
+
CC_MAX_SIGNAL_LIFETIME_MINUTES: Infinity,
|
|
118
|
+
});
|
|
119
|
+
BacktestKit.setConfig({
|
|
120
|
+
CC_WALKER_MARKDOWN_TOP_N: 10,
|
|
121
|
+
});
|
|
122
|
+
|
|
91
123
|
const ERROR_HANDLER_INSTALLED = Symbol.for("error-handler-installed");
|
|
92
124
|
function dumpStackTrace() {
|
|
93
125
|
const trace = stackTrace__namespace.get();
|
|
@@ -183,12 +215,16 @@ const apiServices$1 = {
|
|
|
183
215
|
const baseServices$1 = {
|
|
184
216
|
errorService: Symbol('errorService'),
|
|
185
217
|
loggerService: Symbol('loggerService'),
|
|
218
|
+
};
|
|
219
|
+
const coreServices$1 = {
|
|
186
220
|
resolveService: Symbol('resolveService'),
|
|
187
221
|
loaderService: Symbol('loaderService'),
|
|
222
|
+
configService: Symbol('configService'),
|
|
188
223
|
babelService: Symbol('babelService'),
|
|
189
224
|
};
|
|
190
225
|
const connectionServices$1 = {
|
|
191
226
|
moduleConnectionService: Symbol('moduleConnectionService'),
|
|
227
|
+
configConnectionService: Symbol('configConnectionService'),
|
|
192
228
|
};
|
|
193
229
|
const mainServices$1 = {
|
|
194
230
|
backtestMainService: Symbol('backtestMainService'),
|
|
@@ -218,6 +254,7 @@ const templateServices$1 = {
|
|
|
218
254
|
const TYPES = {
|
|
219
255
|
...apiServices$1,
|
|
220
256
|
...baseServices$1,
|
|
257
|
+
...coreServices$1,
|
|
221
258
|
...connectionServices$1,
|
|
222
259
|
...mainServices$1,
|
|
223
260
|
...logicServices$1,
|
|
@@ -238,8 +275,10 @@ class ResolveService {
|
|
|
238
275
|
this.loaderService = inject(TYPES.loaderService);
|
|
239
276
|
this.DEFAULT_TEMPLATE_DIR = path.resolve(__dirname$2, '..', 'template');
|
|
240
277
|
this.DEFAULT_MODULES_DIR = path.resolve(__dirname$2, '..', 'modules');
|
|
278
|
+
this.DEFAULT_CONFIG_DIR = path.resolve(__dirname$2, '..', 'config');
|
|
241
279
|
this.OVERRIDE_TEMPLATE_DIR = path.resolve(process.cwd(), 'template');
|
|
242
280
|
this.OVERRIDE_MODULES_DIR = path.resolve(process.cwd(), 'modules');
|
|
281
|
+
this.OVERRIDE_CONFIG_DIR = path.resolve(process.cwd(), 'config');
|
|
243
282
|
this.PROJECT_ROOT_DIR = process.cwd();
|
|
244
283
|
this.getIsLaunched = () => {
|
|
245
284
|
this.loggerService.log("resolveService getIsLaunched");
|
|
@@ -416,6 +455,10 @@ const ALLOWED_EXTENSIONS = [
|
|
|
416
455
|
const DISALLOWED_PATHS = [
|
|
417
456
|
"node_modules",
|
|
418
457
|
"@backtest-kit",
|
|
458
|
+
"build/index.mjs",
|
|
459
|
+
"build/index.js",
|
|
460
|
+
"build\\index.mjs",
|
|
461
|
+
"build\\index.js",
|
|
419
462
|
];
|
|
420
463
|
const getArgs = functoolsKit.singleshot(() => {
|
|
421
464
|
const { values, positionals } = util.parseArgs({
|
|
@@ -657,6 +700,105 @@ const notifyVerbose = functoolsKit.singleshot(() => {
|
|
|
657
700
|
});
|
|
658
701
|
});
|
|
659
702
|
|
|
703
|
+
class SetupUtils {
|
|
704
|
+
constructor() {
|
|
705
|
+
this.enable = functoolsKit.singleshot(() => {
|
|
706
|
+
cli.loggerService.debug("SetupUtils enable");
|
|
707
|
+
{
|
|
708
|
+
const config = cli.configService.getNotificationConfig();
|
|
709
|
+
BacktestKit.Notification.enable(config);
|
|
710
|
+
}
|
|
711
|
+
{
|
|
712
|
+
BacktestKit.Recent.enable();
|
|
713
|
+
BacktestKit.Storage.enable();
|
|
714
|
+
}
|
|
715
|
+
{
|
|
716
|
+
BacktestKit.Markdown.enable();
|
|
717
|
+
BacktestKit.Report.enable();
|
|
718
|
+
BacktestKit.Dump.enable();
|
|
719
|
+
BacktestKit.Memory.enable();
|
|
720
|
+
}
|
|
721
|
+
{
|
|
722
|
+
BacktestKit.Dump.useMarkdown();
|
|
723
|
+
BacktestKit.Memory.usePersist();
|
|
724
|
+
}
|
|
725
|
+
{
|
|
726
|
+
BacktestKit.StorageLive.usePersist();
|
|
727
|
+
BacktestKit.StorageBacktest.useMemory();
|
|
728
|
+
}
|
|
729
|
+
{
|
|
730
|
+
BacktestKit.RecentLive.usePersist();
|
|
731
|
+
BacktestKit.RecentBacktest.useMemory();
|
|
732
|
+
}
|
|
733
|
+
{
|
|
734
|
+
BacktestKit.NotificationLive.usePersist();
|
|
735
|
+
BacktestKit.NotificationBacktest.useMemory();
|
|
736
|
+
}
|
|
737
|
+
{
|
|
738
|
+
BacktestKit.Markdown.useDummy();
|
|
739
|
+
BacktestKit.Log.useJsonl();
|
|
740
|
+
}
|
|
741
|
+
});
|
|
742
|
+
this.clear = () => {
|
|
743
|
+
cli.loggerService.debug("SetupUtils clear");
|
|
744
|
+
if (!this.enable.hasValue()) {
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
this.enable.clear();
|
|
748
|
+
{
|
|
749
|
+
BacktestKit.Recent.disable();
|
|
750
|
+
BacktestKit.Storage.disable();
|
|
751
|
+
BacktestKit.Notification.disable();
|
|
752
|
+
}
|
|
753
|
+
{
|
|
754
|
+
BacktestKit.Markdown.disable();
|
|
755
|
+
BacktestKit.Report.disable();
|
|
756
|
+
BacktestKit.Dump.disable();
|
|
757
|
+
BacktestKit.Memory.disable();
|
|
758
|
+
}
|
|
759
|
+
{
|
|
760
|
+
BacktestKit.Markdown.clear();
|
|
761
|
+
BacktestKit.Report.clear();
|
|
762
|
+
BacktestKit.MarkdownWriter.clear();
|
|
763
|
+
BacktestKit.ReportWriter.clear();
|
|
764
|
+
}
|
|
765
|
+
{
|
|
766
|
+
BacktestKit.PersistSignalAdapter.clear();
|
|
767
|
+
BacktestKit.PersistRiskAdapter.clear();
|
|
768
|
+
BacktestKit.PersistScheduleAdapter.clear();
|
|
769
|
+
BacktestKit.PersistPartialAdapter.clear();
|
|
770
|
+
BacktestKit.PersistBreakevenAdapter.clear();
|
|
771
|
+
BacktestKit.PersistCandleAdapter.clear();
|
|
772
|
+
BacktestKit.PersistStorageAdapter.clear();
|
|
773
|
+
BacktestKit.PersistNotificationAdapter.clear();
|
|
774
|
+
BacktestKit.PersistLogAdapter.clear();
|
|
775
|
+
BacktestKit.PersistMeasureAdapter.clear();
|
|
776
|
+
BacktestKit.PersistIntervalAdapter.clear();
|
|
777
|
+
BacktestKit.PersistMemoryAdapter.clear();
|
|
778
|
+
BacktestKit.PersistRecentAdapter.clear();
|
|
779
|
+
}
|
|
780
|
+
{
|
|
781
|
+
BacktestKit.Dump.clear();
|
|
782
|
+
BacktestKit.Log.clear();
|
|
783
|
+
BacktestKit.Markdown.clear();
|
|
784
|
+
}
|
|
785
|
+
{
|
|
786
|
+
BacktestKit.StorageLive.clear();
|
|
787
|
+
BacktestKit.StorageBacktest.clear();
|
|
788
|
+
}
|
|
789
|
+
{
|
|
790
|
+
BacktestKit.NotificationLive.clear();
|
|
791
|
+
BacktestKit.NotificationBacktest.clear();
|
|
792
|
+
}
|
|
793
|
+
{
|
|
794
|
+
BacktestKit.RecentLive.clear();
|
|
795
|
+
BacktestKit.RecentBacktest.clear();
|
|
796
|
+
}
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
const Setup = new SetupUtils();
|
|
801
|
+
|
|
660
802
|
const DEFAULT_CACHE_LIST$1 = ["1m", "15m", "30m", "1h", "4h"];
|
|
661
803
|
const GET_CACHE_INTERVAL_LIST_FN$1 = () => {
|
|
662
804
|
const { values } = getArgs();
|
|
@@ -671,6 +813,7 @@ class BacktestMainService {
|
|
|
671
813
|
constructor() {
|
|
672
814
|
this.loggerService = inject(TYPES.loggerService);
|
|
673
815
|
this.resolveService = inject(TYPES.resolveService);
|
|
816
|
+
this.configService = inject(TYPES.configService);
|
|
674
817
|
this.exchangeSchemaService = inject(TYPES.exchangeSchemaService);
|
|
675
818
|
this.frameSchemaService = inject(TYPES.frameSchemaService);
|
|
676
819
|
this.symbolSchemaService = inject(TYPES.symbolSchemaService);
|
|
@@ -682,6 +825,10 @@ class BacktestMainService {
|
|
|
682
825
|
this.loggerService.log("backtestMainService run", {
|
|
683
826
|
payload,
|
|
684
827
|
});
|
|
828
|
+
{
|
|
829
|
+
await this.configService.waitForInit();
|
|
830
|
+
Setup.enable();
|
|
831
|
+
}
|
|
685
832
|
{
|
|
686
833
|
this.frontendProviderService.connect();
|
|
687
834
|
this.telegramProviderService.connect();
|
|
@@ -784,12 +931,17 @@ class WalkerMainService {
|
|
|
784
931
|
constructor() {
|
|
785
932
|
this.loggerService = inject(TYPES.loggerService);
|
|
786
933
|
this.resolveService = inject(TYPES.resolveService);
|
|
934
|
+
this.configService = inject(TYPES.configService);
|
|
787
935
|
this.exchangeSchemaService = inject(TYPES.exchangeSchemaService);
|
|
788
936
|
this.symbolSchemaService = inject(TYPES.symbolSchemaService);
|
|
789
937
|
this.cacheLogicService = inject(TYPES.cacheLogicService);
|
|
790
938
|
this.moduleConnectionService = inject(TYPES.moduleConnectionService);
|
|
791
939
|
this.run = functoolsKit.singleshot(async (payload) => {
|
|
792
940
|
this.loggerService.log("walkerMainService run", { payload });
|
|
941
|
+
{
|
|
942
|
+
await this.configService.waitForInit();
|
|
943
|
+
Setup.enable();
|
|
944
|
+
}
|
|
793
945
|
const strategyMap = new Map();
|
|
794
946
|
const sessionMap = new Map();
|
|
795
947
|
const cwd = process.cwd();
|
|
@@ -995,6 +1147,7 @@ class LiveMainService {
|
|
|
995
1147
|
constructor() {
|
|
996
1148
|
this.loggerService = inject(TYPES.loggerService);
|
|
997
1149
|
this.resolveService = inject(TYPES.resolveService);
|
|
1150
|
+
this.configService = inject(TYPES.configService);
|
|
998
1151
|
this.exchangeSchemaService = inject(TYPES.exchangeSchemaService);
|
|
999
1152
|
this.symbolSchemaService = inject(TYPES.symbolSchemaService);
|
|
1000
1153
|
this.frontendProviderService = inject(TYPES.frontendProviderService);
|
|
@@ -1004,6 +1157,10 @@ class LiveMainService {
|
|
|
1004
1157
|
this.loggerService.log("liveMainService run", {
|
|
1005
1158
|
payload,
|
|
1006
1159
|
});
|
|
1160
|
+
{
|
|
1161
|
+
await this.configService.waitForInit();
|
|
1162
|
+
Setup.enable();
|
|
1163
|
+
}
|
|
1007
1164
|
{
|
|
1008
1165
|
this.frontendProviderService.connect();
|
|
1009
1166
|
this.telegramProviderService.connect();
|
|
@@ -1072,6 +1229,7 @@ class PaperMainService {
|
|
|
1072
1229
|
constructor() {
|
|
1073
1230
|
this.loggerService = inject(TYPES.loggerService);
|
|
1074
1231
|
this.resolveService = inject(TYPES.resolveService);
|
|
1232
|
+
this.configService = inject(TYPES.configService);
|
|
1075
1233
|
this.exchangeSchemaService = inject(TYPES.exchangeSchemaService);
|
|
1076
1234
|
this.symbolSchemaService = inject(TYPES.symbolSchemaService);
|
|
1077
1235
|
this.frontendProviderService = inject(TYPES.frontendProviderService);
|
|
@@ -1079,6 +1237,10 @@ class PaperMainService {
|
|
|
1079
1237
|
this.moduleConnectionService = inject(TYPES.moduleConnectionService);
|
|
1080
1238
|
this.run = functoolsKit.singleshot(async (payload) => {
|
|
1081
1239
|
this.loggerService.log("paperMainService init");
|
|
1240
|
+
{
|
|
1241
|
+
await this.configService.waitForInit();
|
|
1242
|
+
Setup.enable();
|
|
1243
|
+
}
|
|
1082
1244
|
{
|
|
1083
1245
|
this.frontendProviderService.connect();
|
|
1084
1246
|
this.telegramProviderService.connect();
|
|
@@ -1156,16 +1318,72 @@ const getEnv = functoolsKit.singleshot(() => {
|
|
|
1156
1318
|
};
|
|
1157
1319
|
});
|
|
1158
1320
|
|
|
1321
|
+
const GET_SYMBOL_EXPORTS_FN = async (self) => {
|
|
1322
|
+
const exports = await self.configConnectionService.loadConfig("symbol.config");
|
|
1323
|
+
if (!exports) {
|
|
1324
|
+
return null;
|
|
1325
|
+
}
|
|
1326
|
+
return "default" in exports
|
|
1327
|
+
? exports.default
|
|
1328
|
+
: exports;
|
|
1329
|
+
};
|
|
1330
|
+
const GET_SYMBOL_CONFIG_FN = async (self) => {
|
|
1331
|
+
const config = await GET_SYMBOL_EXPORTS_FN(self);
|
|
1332
|
+
if (!config) {
|
|
1333
|
+
throw new Error("FrontendProviderService getSymbolConfig `symbol.config` is not found");
|
|
1334
|
+
}
|
|
1335
|
+
if (Array.isArray(config)) {
|
|
1336
|
+
return config;
|
|
1337
|
+
}
|
|
1338
|
+
if ("symbol_list" in config) {
|
|
1339
|
+
return config.symbol_list;
|
|
1340
|
+
}
|
|
1341
|
+
throw new Error("FrontendProviderService getSymbolConfig `symbol.config` is not found");
|
|
1342
|
+
};
|
|
1343
|
+
const MAP_SYMBOL_CONFIG_FN = (config) => {
|
|
1344
|
+
const uniqueSymbols = new Set();
|
|
1345
|
+
const symbolList = config
|
|
1346
|
+
.filter((item) => {
|
|
1347
|
+
if (uniqueSymbols.has(item.symbol)) {
|
|
1348
|
+
return false;
|
|
1349
|
+
}
|
|
1350
|
+
uniqueSymbols.add(item.symbol);
|
|
1351
|
+
return true;
|
|
1352
|
+
})
|
|
1353
|
+
.map(({ priority, displayName, symbol, logo, icon, ...other }, idx) => ({
|
|
1354
|
+
symbol,
|
|
1355
|
+
icon,
|
|
1356
|
+
logo: logo ?? icon,
|
|
1357
|
+
priority: priority ?? idx,
|
|
1358
|
+
displayName: displayName ?? symbol,
|
|
1359
|
+
index: idx,
|
|
1360
|
+
...other,
|
|
1361
|
+
}));
|
|
1362
|
+
symbolList.sort(({ priority: a_p, index: a_x }, { priority: b_p, index: b_x }) => b_p - a_p || a_x - b_x);
|
|
1363
|
+
return symbolList;
|
|
1364
|
+
};
|
|
1159
1365
|
class FrontendProviderService {
|
|
1160
1366
|
constructor() {
|
|
1161
1367
|
this.loggerService = inject(TYPES.loggerService);
|
|
1162
1368
|
this.resolveService = inject(TYPES.resolveService);
|
|
1369
|
+
this.configConnectionService = inject(TYPES.configConnectionService);
|
|
1163
1370
|
this.enable = functoolsKit.singleshot(() => {
|
|
1164
1371
|
this.loggerService.log("frontendProviderService enable");
|
|
1165
1372
|
const { CC_WWWROOT_HOST, CC_WWWROOT_PORT } = getEnv();
|
|
1166
|
-
|
|
1373
|
+
let unServer;
|
|
1374
|
+
const init = async () => {
|
|
1375
|
+
{
|
|
1376
|
+
const config = await GET_SYMBOL_CONFIG_FN(this);
|
|
1377
|
+
if (config) {
|
|
1378
|
+
const symbolList = MAP_SYMBOL_CONFIG_FN(config);
|
|
1379
|
+
BacktestKitUi.lib.symbolConnectionService.getSymbolList.setValue(Promise.resolve(symbolList));
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
unServer = BacktestKitUi.serve(CC_WWWROOT_HOST, CC_WWWROOT_PORT, this.resolveService.PROJECT_ROOT_DIR);
|
|
1383
|
+
};
|
|
1384
|
+
init();
|
|
1167
1385
|
return () => {
|
|
1168
|
-
unServer();
|
|
1386
|
+
unServer && unServer();
|
|
1169
1387
|
this.enable.clear();
|
|
1170
1388
|
};
|
|
1171
1389
|
});
|
|
@@ -1836,6 +2054,16 @@ class TelegramLogicService {
|
|
|
1836
2054
|
markdown,
|
|
1837
2055
|
});
|
|
1838
2056
|
});
|
|
2057
|
+
this.notifySignalInfo = functoolsKit.trycatch(async (event) => {
|
|
2058
|
+
this.loggerService.log("telegramLogicService notifySignalInfo", {
|
|
2059
|
+
event,
|
|
2060
|
+
});
|
|
2061
|
+
const markdown = await this.telegramTemplateService.getSignalInfoMarkdown(event);
|
|
2062
|
+
await this.telegramWebService.publishNotify({
|
|
2063
|
+
symbol: event.symbol,
|
|
2064
|
+
markdown,
|
|
2065
|
+
});
|
|
2066
|
+
});
|
|
1839
2067
|
this.notifyCancelScheduled = async (event) => {
|
|
1840
2068
|
this.loggerService.log("telegramLogicService notifyCancelScheduled", {
|
|
1841
2069
|
event,
|
|
@@ -1923,8 +2151,11 @@ class TelegramLogicService {
|
|
|
1923
2151
|
return;
|
|
1924
2152
|
}
|
|
1925
2153
|
});
|
|
2154
|
+
const unSignalNotify = BacktestKit.listenSignalNotify(async (event) => {
|
|
2155
|
+
await this.notifySignalInfo(event);
|
|
2156
|
+
});
|
|
1926
2157
|
const unConnect = () => this.connect.clear();
|
|
1927
|
-
const unListen = functoolsKit.compose(() => unRisk(), () => unSignal(), () => unCommit(), () => unSync(), () => unConnect());
|
|
2158
|
+
const unListen = functoolsKit.compose(() => unRisk(), () => unSignal(), () => unCommit(), () => unSync(), () => unSignalNotify(), () => unConnect());
|
|
1928
2159
|
return () => {
|
|
1929
2160
|
STOP_BOT_FN();
|
|
1930
2161
|
unListen();
|
|
@@ -2043,6 +2274,12 @@ class TelegramTemplateService {
|
|
|
2043
2274
|
});
|
|
2044
2275
|
return await RENDER_TEMPLATE_FN("close-pending.mustache", event, this);
|
|
2045
2276
|
};
|
|
2277
|
+
this.getSignalInfoMarkdown = async (event) => {
|
|
2278
|
+
this.loggerService.log("telegramTemplateService getSignalInfoMarkdown", {
|
|
2279
|
+
event,
|
|
2280
|
+
});
|
|
2281
|
+
return await RENDER_TEMPLATE_FN("signal-info.mustache", event, this);
|
|
2282
|
+
};
|
|
2046
2283
|
}
|
|
2047
2284
|
}
|
|
2048
2285
|
|
|
@@ -2083,7 +2320,7 @@ class ModuleConnectionService {
|
|
|
2083
2320
|
this.resolveService = inject(TYPES.resolveService);
|
|
2084
2321
|
this.loaderService = inject(TYPES.loaderService);
|
|
2085
2322
|
this.loadModule = async (fileName) => {
|
|
2086
|
-
this.loggerService.log("moduleConnectionService
|
|
2323
|
+
this.loggerService.log("moduleConnectionService loadModule", {
|
|
2087
2324
|
fileName,
|
|
2088
2325
|
});
|
|
2089
2326
|
return await LOAD_MODULE_MODULE_FN(fileName, this);
|
|
@@ -2130,6 +2367,19 @@ class BabelService {
|
|
|
2130
2367
|
}
|
|
2131
2368
|
}
|
|
2132
2369
|
|
|
2370
|
+
/**
|
|
2371
|
+
* This file is used to define any aliases for imports in the client code. This is useful for mocking modules during testing or for providing alternative implementations of certain modules.
|
|
2372
|
+
* For example, if we want to mock the "pinets" module during testing, we can add an entry to the IMPORT_ALIAS object that points to our mock implementation. Then, when the client code tries to import "pinets", it will receive our mock implementation instead of the actual "pinets" module.
|
|
2373
|
+
* This allows us to isolate the client code from external dependencies and test it more effectively.
|
|
2374
|
+
* Note that the keys in the IMPORT_ALIAS object should match the module names used in the client code, and the values should be the corresponding mock implementations or alternative modules.
|
|
2375
|
+
* @example
|
|
2376
|
+
* // To mock the "pinets" module, we can add the following entry to the IMPORT_ALIAS object:
|
|
2377
|
+
* Object.assign(IMPORT_ALIAS, {
|
|
2378
|
+
* "pinets": require("pinets/dist/pinets.min.browser.js"),
|
|
2379
|
+
* });
|
|
2380
|
+
*/
|
|
2381
|
+
const IMPORT_ALIAS = {};
|
|
2382
|
+
|
|
2133
2383
|
const USE_ESMODULE_DEFAULT = false;
|
|
2134
2384
|
const IMPORT_PATHS_EXCLUDE = new Set(["dump", "logs", "modules", "node_modules"]);
|
|
2135
2385
|
const TRANSPILE_FN = functoolsKit.memoize(([path]) => `${path}`, (path, code, self, require) => {
|
|
@@ -2249,6 +2499,8 @@ const CREATE_BASE_REQUIRE_FN = (self, seen) => {
|
|
|
2249
2499
|
return new Proxy(baseRequire, {
|
|
2250
2500
|
apply(_target, _this, args) {
|
|
2251
2501
|
const id = args[0];
|
|
2502
|
+
if (IMPORT_ALIAS[id])
|
|
2503
|
+
return IMPORT_ALIAS[id];
|
|
2252
2504
|
if (id === "backtest-kit")
|
|
2253
2505
|
return globalThis.BacktestKit;
|
|
2254
2506
|
if (id === "@backtest-kit/cli")
|
|
@@ -2352,6 +2604,26 @@ globalThis.BacktestKitOllama = BacktestKitOllama__namespace;
|
|
|
2352
2604
|
globalThis.BacktestKitPinets = BacktestKitPinets__namespace;
|
|
2353
2605
|
globalThis.BacktestKitSignals = BacktestKitSignals__namespace;
|
|
2354
2606
|
|
|
2607
|
+
const GET_ALIAS_EXPORTS_FN = (self) => {
|
|
2608
|
+
const instance = self.getInstance(self.resolveService.OVERRIDE_CONFIG_DIR);
|
|
2609
|
+
if (!instance.check("alias.module")) {
|
|
2610
|
+
return null;
|
|
2611
|
+
}
|
|
2612
|
+
const exports = instance.import("alias.module");
|
|
2613
|
+
return "default" in exports
|
|
2614
|
+
? exports.default
|
|
2615
|
+
: exports;
|
|
2616
|
+
};
|
|
2617
|
+
const INIT_ALIAS_FN = (self) => {
|
|
2618
|
+
const alias = GET_ALIAS_EXPORTS_FN(self);
|
|
2619
|
+
if (!alias) {
|
|
2620
|
+
return;
|
|
2621
|
+
}
|
|
2622
|
+
if (!functoolsKit.isObject(alias)) {
|
|
2623
|
+
return;
|
|
2624
|
+
}
|
|
2625
|
+
Object.assign(IMPORT_ALIAS, alias);
|
|
2626
|
+
};
|
|
2355
2627
|
class LoaderService {
|
|
2356
2628
|
constructor() {
|
|
2357
2629
|
this.babelService = inject(TYPES.babelService);
|
|
@@ -2379,6 +2651,90 @@ class LoaderService {
|
|
|
2379
2651
|
const instance = this.getInstance(basePath);
|
|
2380
2652
|
return instance.check(filePath);
|
|
2381
2653
|
};
|
|
2654
|
+
this.init = functoolsKit.singleshot(() => {
|
|
2655
|
+
this.loggerService.log("loaderService init");
|
|
2656
|
+
INIT_ALIAS_FN(this);
|
|
2657
|
+
});
|
|
2658
|
+
}
|
|
2659
|
+
}
|
|
2660
|
+
|
|
2661
|
+
const GET_CONFIG_VARIANTS_FN = (fileName, self) => {
|
|
2662
|
+
const result = [];
|
|
2663
|
+
result.push({
|
|
2664
|
+
filePath: path.join(process.cwd(), "config", fileName),
|
|
2665
|
+
baseDir: path.join(process.cwd(), "config")
|
|
2666
|
+
});
|
|
2667
|
+
result.push({
|
|
2668
|
+
filePath: path.join(self.resolveService.OVERRIDE_CONFIG_DIR, fileName),
|
|
2669
|
+
baseDir: self.resolveService.OVERRIDE_CONFIG_DIR,
|
|
2670
|
+
});
|
|
2671
|
+
result.push({
|
|
2672
|
+
filePath: path.join(self.resolveService.DEFAULT_CONFIG_DIR, fileName),
|
|
2673
|
+
baseDir: self.resolveService.DEFAULT_CONFIG_DIR,
|
|
2674
|
+
});
|
|
2675
|
+
return result;
|
|
2676
|
+
};
|
|
2677
|
+
const LOAD_CONFIG_CONFIG_FN = async (fileName, self) => {
|
|
2678
|
+
for (const { filePath, baseDir } of GET_CONFIG_VARIANTS_FN(fileName, self)) {
|
|
2679
|
+
try {
|
|
2680
|
+
if (await self.loaderService.check(filePath, baseDir)) {
|
|
2681
|
+
return self.loaderService.import(filePath, baseDir);
|
|
2682
|
+
}
|
|
2683
|
+
}
|
|
2684
|
+
catch {
|
|
2685
|
+
console.warn(`Module module import failed filePath=${filePath} baseDir=${baseDir}`);
|
|
2686
|
+
process.exit(-1);
|
|
2687
|
+
}
|
|
2688
|
+
}
|
|
2689
|
+
return null;
|
|
2690
|
+
};
|
|
2691
|
+
class ConfigConnectionService {
|
|
2692
|
+
constructor() {
|
|
2693
|
+
this.loggerService = inject(TYPES.loggerService);
|
|
2694
|
+
this.resolveService = inject(TYPES.resolveService);
|
|
2695
|
+
this.loaderService = inject(TYPES.loaderService);
|
|
2696
|
+
this.loadConfig = (fileName) => {
|
|
2697
|
+
this.loggerService.log("configConnectionService loadConfig", {
|
|
2698
|
+
fileName,
|
|
2699
|
+
});
|
|
2700
|
+
return LOAD_CONFIG_CONFIG_FN(fileName, this);
|
|
2701
|
+
};
|
|
2702
|
+
}
|
|
2703
|
+
}
|
|
2704
|
+
|
|
2705
|
+
const GET_NOTIFICATION_EXPORTS_FN = async (self) => {
|
|
2706
|
+
const exports = await self.configConnectionService.loadConfig("notification.config");
|
|
2707
|
+
if (!exports) {
|
|
2708
|
+
return null;
|
|
2709
|
+
}
|
|
2710
|
+
return "default" in exports
|
|
2711
|
+
? exports.default
|
|
2712
|
+
: exports;
|
|
2713
|
+
};
|
|
2714
|
+
const GET_NOTIFICATION_CONFIG_FN = async (self) => {
|
|
2715
|
+
const config = await GET_NOTIFICATION_EXPORTS_FN(self);
|
|
2716
|
+
if (!config) {
|
|
2717
|
+
throw new Error("ConfigService getNotificationConfig `notification.config` is not found");
|
|
2718
|
+
}
|
|
2719
|
+
if ("notification_config" in config) {
|
|
2720
|
+
return config.notification_config;
|
|
2721
|
+
}
|
|
2722
|
+
return config;
|
|
2723
|
+
};
|
|
2724
|
+
class ConfigService {
|
|
2725
|
+
constructor() {
|
|
2726
|
+
this.loggerService = inject(TYPES.loggerService);
|
|
2727
|
+
this.configConnectionService = inject(TYPES.configConnectionService);
|
|
2728
|
+
this.getNotificationConfig = functoolsKit.singleshot(() => {
|
|
2729
|
+
throw new Error("ConfigService getNotificationConfig waitForInit is not called");
|
|
2730
|
+
});
|
|
2731
|
+
this.waitForInit = functoolsKit.singleshot(async () => {
|
|
2732
|
+
this.loggerService.log("configService waitForInit");
|
|
2733
|
+
{
|
|
2734
|
+
const config = await GET_NOTIFICATION_CONFIG_FN(this);
|
|
2735
|
+
this.getNotificationConfig.setValue(config);
|
|
2736
|
+
}
|
|
2737
|
+
});
|
|
2382
2738
|
}
|
|
2383
2739
|
}
|
|
2384
2740
|
|
|
@@ -2389,12 +2745,16 @@ class LoaderService {
|
|
|
2389
2745
|
{
|
|
2390
2746
|
provide(TYPES.errorService, () => new ErrorService());
|
|
2391
2747
|
provide(TYPES.loggerService, () => new LoggerService());
|
|
2748
|
+
}
|
|
2749
|
+
{
|
|
2392
2750
|
provide(TYPES.resolveService, () => new ResolveService());
|
|
2393
2751
|
provide(TYPES.loaderService, () => new LoaderService());
|
|
2752
|
+
provide(TYPES.configService, () => new ConfigService());
|
|
2394
2753
|
provide(TYPES.babelService, () => new BabelService());
|
|
2395
2754
|
}
|
|
2396
2755
|
{
|
|
2397
2756
|
provide(TYPES.moduleConnectionService, () => new ModuleConnectionService());
|
|
2757
|
+
provide(TYPES.configConnectionService, () => new ConfigConnectionService());
|
|
2398
2758
|
}
|
|
2399
2759
|
{
|
|
2400
2760
|
provide(TYPES.backtestMainService, () => new BacktestMainService());
|
|
@@ -2429,12 +2789,16 @@ const apiServices = {
|
|
|
2429
2789
|
const baseServices = {
|
|
2430
2790
|
errorService: inject(TYPES.errorService),
|
|
2431
2791
|
loggerService: inject(TYPES.loggerService),
|
|
2792
|
+
};
|
|
2793
|
+
const coreServices = {
|
|
2432
2794
|
resolveService: inject(TYPES.resolveService),
|
|
2433
2795
|
loaderService: inject(TYPES.loaderService),
|
|
2796
|
+
configService: inject(TYPES.configService),
|
|
2434
2797
|
babelService: inject(TYPES.babelService),
|
|
2435
2798
|
};
|
|
2436
2799
|
const connectionServices = {
|
|
2437
2800
|
moduleConnectionService: inject(TYPES.moduleConnectionService),
|
|
2801
|
+
configConnectionService: inject(TYPES.configConnectionService),
|
|
2438
2802
|
};
|
|
2439
2803
|
const mainServices = {
|
|
2440
2804
|
backtestMainService: inject(TYPES.backtestMainService),
|
|
@@ -2464,6 +2828,7 @@ const templateServices = {
|
|
|
2464
2828
|
const cli = {
|
|
2465
2829
|
...apiServices,
|
|
2466
2830
|
...baseServices,
|
|
2831
|
+
...coreServices,
|
|
2467
2832
|
...connectionServices,
|
|
2468
2833
|
...mainServices,
|
|
2469
2834
|
...logicServices,
|
|
@@ -2474,148 +2839,6 @@ const cli = {
|
|
|
2474
2839
|
};
|
|
2475
2840
|
init();
|
|
2476
2841
|
|
|
2477
|
-
const NOTIFICATION_CONFIG = {
|
|
2478
|
-
signal: true,
|
|
2479
|
-
risk: true,
|
|
2480
|
-
info: true,
|
|
2481
|
-
breakeven: true,
|
|
2482
|
-
common_error: true,
|
|
2483
|
-
critical_error: true,
|
|
2484
|
-
validation_error: true,
|
|
2485
|
-
partial_loss: false,
|
|
2486
|
-
partial_profit: false,
|
|
2487
|
-
signal_sync: false,
|
|
2488
|
-
strategy_commit: true,
|
|
2489
|
-
};
|
|
2490
|
-
class SetupUtils {
|
|
2491
|
-
constructor() {
|
|
2492
|
-
this.enable = functoolsKit.singleshot(() => {
|
|
2493
|
-
cli.loggerService.debug("SetupUtils enable");
|
|
2494
|
-
BacktestKit.Notification.enable(NOTIFICATION_CONFIG);
|
|
2495
|
-
{
|
|
2496
|
-
BacktestKit.Recent.enable();
|
|
2497
|
-
BacktestKit.Storage.enable();
|
|
2498
|
-
}
|
|
2499
|
-
{
|
|
2500
|
-
BacktestKit.Markdown.enable();
|
|
2501
|
-
BacktestKit.Report.enable();
|
|
2502
|
-
BacktestKit.Dump.enable();
|
|
2503
|
-
BacktestKit.Memory.enable();
|
|
2504
|
-
}
|
|
2505
|
-
{
|
|
2506
|
-
BacktestKit.Dump.useMarkdown();
|
|
2507
|
-
BacktestKit.Memory.usePersist();
|
|
2508
|
-
}
|
|
2509
|
-
{
|
|
2510
|
-
BacktestKit.StorageLive.usePersist();
|
|
2511
|
-
BacktestKit.StorageBacktest.useMemory();
|
|
2512
|
-
}
|
|
2513
|
-
{
|
|
2514
|
-
BacktestKit.RecentLive.usePersist();
|
|
2515
|
-
BacktestKit.RecentBacktest.useMemory();
|
|
2516
|
-
}
|
|
2517
|
-
{
|
|
2518
|
-
BacktestKit.NotificationLive.usePersist();
|
|
2519
|
-
BacktestKit.NotificationBacktest.useMemory();
|
|
2520
|
-
}
|
|
2521
|
-
{
|
|
2522
|
-
BacktestKit.Markdown.useDummy();
|
|
2523
|
-
BacktestKit.Log.useJsonl();
|
|
2524
|
-
}
|
|
2525
|
-
});
|
|
2526
|
-
this.clear = () => {
|
|
2527
|
-
cli.loggerService.debug("SetupUtils clear");
|
|
2528
|
-
if (!this.enable.hasValue()) {
|
|
2529
|
-
return;
|
|
2530
|
-
}
|
|
2531
|
-
this.enable.clear();
|
|
2532
|
-
{
|
|
2533
|
-
BacktestKit.Recent.disable();
|
|
2534
|
-
BacktestKit.Storage.disable();
|
|
2535
|
-
BacktestKit.Notification.disable();
|
|
2536
|
-
}
|
|
2537
|
-
{
|
|
2538
|
-
BacktestKit.Markdown.disable();
|
|
2539
|
-
BacktestKit.Report.disable();
|
|
2540
|
-
BacktestKit.Dump.disable();
|
|
2541
|
-
BacktestKit.Memory.disable();
|
|
2542
|
-
}
|
|
2543
|
-
{
|
|
2544
|
-
BacktestKit.Markdown.clear();
|
|
2545
|
-
BacktestKit.Report.clear();
|
|
2546
|
-
BacktestKit.MarkdownWriter.clear();
|
|
2547
|
-
BacktestKit.ReportWriter.clear();
|
|
2548
|
-
}
|
|
2549
|
-
{
|
|
2550
|
-
BacktestKit.PersistSignalAdapter.clear();
|
|
2551
|
-
BacktestKit.PersistRiskAdapter.clear();
|
|
2552
|
-
BacktestKit.PersistScheduleAdapter.clear();
|
|
2553
|
-
BacktestKit.PersistPartialAdapter.clear();
|
|
2554
|
-
BacktestKit.PersistBreakevenAdapter.clear();
|
|
2555
|
-
BacktestKit.PersistCandleAdapter.clear();
|
|
2556
|
-
BacktestKit.PersistStorageAdapter.clear();
|
|
2557
|
-
BacktestKit.PersistNotificationAdapter.clear();
|
|
2558
|
-
BacktestKit.PersistLogAdapter.clear();
|
|
2559
|
-
BacktestKit.PersistMeasureAdapter.clear();
|
|
2560
|
-
BacktestKit.PersistIntervalAdapter.clear();
|
|
2561
|
-
BacktestKit.PersistMemoryAdapter.clear();
|
|
2562
|
-
BacktestKit.PersistRecentAdapter.clear();
|
|
2563
|
-
}
|
|
2564
|
-
{
|
|
2565
|
-
BacktestKit.Dump.clear();
|
|
2566
|
-
BacktestKit.Log.clear();
|
|
2567
|
-
BacktestKit.Markdown.clear();
|
|
2568
|
-
}
|
|
2569
|
-
{
|
|
2570
|
-
BacktestKit.StorageLive.clear();
|
|
2571
|
-
BacktestKit.StorageBacktest.clear();
|
|
2572
|
-
}
|
|
2573
|
-
{
|
|
2574
|
-
BacktestKit.NotificationLive.clear();
|
|
2575
|
-
BacktestKit.NotificationBacktest.clear();
|
|
2576
|
-
}
|
|
2577
|
-
{
|
|
2578
|
-
BacktestKit.RecentLive.clear();
|
|
2579
|
-
BacktestKit.RecentBacktest.clear();
|
|
2580
|
-
}
|
|
2581
|
-
};
|
|
2582
|
-
}
|
|
2583
|
-
}
|
|
2584
|
-
const Setup = new SetupUtils();
|
|
2585
|
-
|
|
2586
|
-
Setup.enable();
|
|
2587
|
-
BacktestKit.setConfig({
|
|
2588
|
-
CC_MAX_NOTIFICATIONS: 5000,
|
|
2589
|
-
CC_MAX_SIGNALS: 750,
|
|
2590
|
-
});
|
|
2591
|
-
BacktestKit.setConfig({
|
|
2592
|
-
CC_ENABLE_DCA_EVERYWHERE: true,
|
|
2593
|
-
CC_ENABLE_PPPL_EVERYWHERE: true,
|
|
2594
|
-
CC_ENABLE_TRAILING_EVERYWHERE: true,
|
|
2595
|
-
});
|
|
2596
|
-
BacktestKit.setConfig({
|
|
2597
|
-
CC_MAX_SIGNAL_GENERATION_SECONDS: 15 * 60,
|
|
2598
|
-
});
|
|
2599
|
-
BacktestKit.setConfig({
|
|
2600
|
-
CC_MAX_BACKTEST_MARKDOWN_ROWS: 1000,
|
|
2601
|
-
CC_MAX_BREAKEVEN_MARKDOWN_ROWS: 1000,
|
|
2602
|
-
CC_MAX_HEATMAP_MARKDOWN_ROWS: 1000,
|
|
2603
|
-
CC_MAX_HIGHEST_PROFIT_MARKDOWN_ROWS: 1000,
|
|
2604
|
-
CC_MAX_LIVE_MARKDOWN_ROWS: 1000,
|
|
2605
|
-
CC_MAX_PARTIAL_MARKDOWN_ROWS: 1000,
|
|
2606
|
-
CC_MAX_RISK_MARKDOWN_ROWS: 1000,
|
|
2607
|
-
CC_MAX_SCHEDULE_MARKDOWN_ROWS: 1000,
|
|
2608
|
-
CC_MAX_STRATEGY_MARKDOWN_ROWS: 1000,
|
|
2609
|
-
CC_MAX_SYNC_MARKDOWN_ROWS: 1000,
|
|
2610
|
-
CC_MAX_PERFORMANCE_MARKDOWN_ROWS: 1000,
|
|
2611
|
-
});
|
|
2612
|
-
BacktestKit.setConfig({
|
|
2613
|
-
CC_MAX_SIGNAL_LIFETIME_MINUTES: Infinity,
|
|
2614
|
-
});
|
|
2615
|
-
BacktestKit.setConfig({
|
|
2616
|
-
CC_WALKER_MARKDOWN_TOP_N: 10,
|
|
2617
|
-
});
|
|
2618
|
-
|
|
2619
2842
|
const MODES = ["backtest", "walker", "paper", "live", "pine", "editor", "dump", "flush", "init", "help", "version"];
|
|
2620
2843
|
const ENTRY_PATH$1 = "./node_modules/@backtest-kit/cli/build/index.mjs";
|
|
2621
2844
|
const HELP_TEXT$1 = `
|
|
@@ -2631,7 +2854,7 @@ const main$d = async () => {
|
|
|
2631
2854
|
if (MODES.some((mode) => values[mode])) {
|
|
2632
2855
|
return;
|
|
2633
2856
|
}
|
|
2634
|
-
process.stdout.write(`@backtest-kit/cli ${"7.
|
|
2857
|
+
process.stdout.write(`@backtest-kit/cli ${"7.3.0"}\n`);
|
|
2635
2858
|
process.stdout.write("\n");
|
|
2636
2859
|
process.stdout.write(`Run with --help to see available commands.\n`);
|
|
2637
2860
|
process.stdout.write("\n");
|
|
@@ -2962,6 +3185,10 @@ const main$4 = async () => {
|
|
|
2962
3185
|
console.warn("--editor and --pine are mutually exclusive. Use one at a time.");
|
|
2963
3186
|
process.exit(1);
|
|
2964
3187
|
}
|
|
3188
|
+
{
|
|
3189
|
+
await cli.configService.waitForInit();
|
|
3190
|
+
Setup.enable();
|
|
3191
|
+
}
|
|
2965
3192
|
await cli.moduleConnectionService.loadModule("./editor.module");
|
|
2966
3193
|
{
|
|
2967
3194
|
await cli.exchangeSchemaService.addSchema();
|
|
@@ -3291,7 +3518,7 @@ const main$1 = async () => {
|
|
|
3291
3518
|
if (!values.help) {
|
|
3292
3519
|
return;
|
|
3293
3520
|
}
|
|
3294
|
-
process.stdout.write(`@backtest-kit/cli ${"7.
|
|
3521
|
+
process.stdout.write(`@backtest-kit/cli ${"7.3.0"}\n\n`);
|
|
3295
3522
|
process.stdout.write(HELP_TEXT);
|
|
3296
3523
|
process.exit(0);
|
|
3297
3524
|
};
|
|
@@ -3305,7 +3532,7 @@ const main = async () => {
|
|
|
3305
3532
|
if (!values.version) {
|
|
3306
3533
|
return;
|
|
3307
3534
|
}
|
|
3308
|
-
process.stdout.write(`@backtest-kit/cli ${"7.
|
|
3535
|
+
process.stdout.write(`@backtest-kit/cli ${"7.3.0"}\n`);
|
|
3309
3536
|
process.exit(0);
|
|
3310
3537
|
};
|
|
3311
3538
|
main();
|