@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/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
- const unServer = BacktestKitUi.serve(CC_WWWROOT_HOST, CC_WWWROOT_PORT, this.resolveService.PROJECT_ROOT_DIR);
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 getInstance", {
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.1.0"}\n`);
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.1.0"}\n\n`);
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.1.0"}\n`);
3535
+ process.stdout.write(`@backtest-kit/cli ${"7.3.0"}\n`);
3309
3536
  process.exit(0);
3310
3537
  };
3311
3538
  main();