@backtest-kit/cli 9.3.0 → 9.4.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 CHANGED
@@ -732,6 +732,8 @@ Broker.enable();
732
732
 
733
733
  `@backtest-kit/cli` loads a `{projectRoot}/config/setup.config` file once before any module hooks or strategy code run. Use it to perform one-time initialization that must happen before the first persistence call — registering a custom storage backend, configuring a logger, seeding global state, or anything else the process needs before `backtest-kit` starts.
734
734
 
735
+ **Important:** When `setup.config` is present, the CLI skips its own default adapter registration — it does **not** call `usePersist()` / `useLocal()` / `useMemory()` for any of the persistence slots. This means your config takes full ownership of the persistence layer: whatever adapters you register in `{projectRoot}/config/setup.config` are the ones `backtest-kit` uses, with no interference from the CLI defaults.
736
+
735
737
  ### Example: MongoDB + Redis persistence via `@backtest-kit/mongo`
736
738
 
737
739
  The most common use-case is swapping the default file-based persistence for a production-grade backend. Install `@backtest-kit/mongo` and call `setup()` — it registers all 15 persistence adapters in one call and reads connection parameters from environment variables:
package/build/index.cjs CHANGED
@@ -24,7 +24,7 @@ var jsdom = require('jsdom');
24
24
  var Mustache = require('mustache');
25
25
  var standalone = require('@babel/standalone');
26
26
  var pluginUMD = require('@babel/plugin-transform-modules-umd');
27
- var module$1 = require('module');
27
+ var Module = require('module');
28
28
  var BacktestKitGraph = require('@backtest-kit/graph');
29
29
  var BacktestKitOllama = require('@backtest-kit/ollama');
30
30
  var BacktestKitPinets = require('@backtest-kit/pinets');
@@ -266,6 +266,136 @@ const TYPES = {
266
266
 
267
267
  const entrySubject = new functoolsKit.BehaviorSubject();
268
268
 
269
+ const SETUP_ADAPTER_FN = () => {
270
+ {
271
+ BacktestKit.Dump.useMarkdown();
272
+ }
273
+ {
274
+ BacktestKit.SessionLive.usePersist();
275
+ BacktestKit.SessionBacktest.useLocal();
276
+ }
277
+ {
278
+ BacktestKit.StorageLive.usePersist();
279
+ BacktestKit.StorageBacktest.useMemory();
280
+ }
281
+ {
282
+ BacktestKit.RecentLive.usePersist();
283
+ BacktestKit.RecentBacktest.useMemory();
284
+ }
285
+ {
286
+ BacktestKit.NotificationLive.usePersist();
287
+ BacktestKit.NotificationBacktest.useMemory();
288
+ }
289
+ {
290
+ BacktestKit.RecentLive.usePersist();
291
+ BacktestKit.RecentBacktest.useMemory();
292
+ }
293
+ {
294
+ BacktestKit.MemoryLive.usePersist();
295
+ BacktestKit.MemoryBacktest.useLocal();
296
+ }
297
+ {
298
+ BacktestKit.StateLive.usePersist();
299
+ BacktestKit.StateBacktest.useLocal();
300
+ }
301
+ {
302
+ BacktestKit.Markdown.useDummy();
303
+ BacktestKit.Log.useJsonl();
304
+ }
305
+ };
306
+ class SetupUtils {
307
+ constructor() {
308
+ this.enable = functoolsKit.singleshot(() => {
309
+ cli.loggerService.debug("SetupUtils enable");
310
+ {
311
+ const config = cli.configService.getNotificationConfig();
312
+ BacktestKit.Notification.enable(config);
313
+ }
314
+ {
315
+ BacktestKit.Recent.enable();
316
+ BacktestKit.Storage.enable();
317
+ }
318
+ {
319
+ BacktestKit.Markdown.enable();
320
+ BacktestKit.Report.enable();
321
+ BacktestKit.Dump.enable();
322
+ BacktestKit.State.enable();
323
+ BacktestKit.Memory.enable();
324
+ }
325
+ if (!cli.configConnectionService.hasConfig("setup.config")) {
326
+ SETUP_ADAPTER_FN();
327
+ }
328
+ });
329
+ this.clear = () => {
330
+ cli.loggerService.debug("SetupUtils clear");
331
+ if (!this.enable.hasValue()) {
332
+ return;
333
+ }
334
+ this.enable.clear();
335
+ {
336
+ BacktestKit.Recent.disable();
337
+ BacktestKit.Storage.disable();
338
+ BacktestKit.Notification.disable();
339
+ }
340
+ {
341
+ BacktestKit.Markdown.disable();
342
+ BacktestKit.Report.disable();
343
+ BacktestKit.Dump.disable();
344
+ BacktestKit.Memory.disable();
345
+ }
346
+ {
347
+ BacktestKit.Markdown.clear();
348
+ BacktestKit.Report.clear();
349
+ BacktestKit.MarkdownWriter.clear();
350
+ BacktestKit.ReportWriter.clear();
351
+ }
352
+ {
353
+ BacktestKit.PersistSignalAdapter.clear();
354
+ BacktestKit.PersistRiskAdapter.clear();
355
+ BacktestKit.PersistScheduleAdapter.clear();
356
+ BacktestKit.PersistPartialAdapter.clear();
357
+ BacktestKit.PersistBreakevenAdapter.clear();
358
+ BacktestKit.PersistCandleAdapter.clear();
359
+ BacktestKit.PersistStorageAdapter.clear();
360
+ BacktestKit.PersistNotificationAdapter.clear();
361
+ BacktestKit.PersistLogAdapter.clear();
362
+ BacktestKit.PersistMeasureAdapter.clear();
363
+ BacktestKit.PersistIntervalAdapter.clear();
364
+ BacktestKit.PersistMemoryAdapter.clear();
365
+ BacktestKit.PersistRecentAdapter.clear();
366
+ BacktestKit.PersistStateAdapter.clear();
367
+ BacktestKit.PersistSessionAdapter.clear();
368
+ }
369
+ {
370
+ BacktestKit.Dump.clear();
371
+ BacktestKit.Log.clear();
372
+ BacktestKit.Markdown.clear();
373
+ }
374
+ {
375
+ BacktestKit.StorageLive.clear();
376
+ BacktestKit.StorageBacktest.clear();
377
+ }
378
+ {
379
+ BacktestKit.NotificationLive.clear();
380
+ BacktestKit.NotificationBacktest.clear();
381
+ }
382
+ {
383
+ BacktestKit.RecentLive.clear();
384
+ BacktestKit.RecentBacktest.clear();
385
+ }
386
+ };
387
+ this.update = () => {
388
+ cli.loggerService.debug("SetupUtils update");
389
+ if (cli.configConnectionService.hasConfig("setup.config")) {
390
+ return;
391
+ }
392
+ BacktestKit.Log.useJsonl();
393
+ BacktestKit.Dump.useMarkdown();
394
+ };
395
+ }
396
+ }
397
+ const Setup = new SetupUtils();
398
+
269
399
  const __filename$3 = 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)));
270
400
  const __dirname$3 = path.dirname(__filename$3);
271
401
  let _is_launched = false;
@@ -327,7 +457,7 @@ class ResolveService {
327
457
  {
328
458
  const cwd = process.cwd();
329
459
  process.chdir(moduleRoot);
330
- cwd !== moduleRoot && BacktestKit.Log.useJsonl();
460
+ cwd !== moduleRoot && Setup.update();
331
461
  dotenv.config({ path: path.join(cwd, '.env'), override: true, quiet: true });
332
462
  dotenv.config({ path: path.join(moduleRoot, '.env'), override: true, quiet: true });
333
463
  this.loaderService.import(absolutePath);
@@ -753,123 +883,6 @@ const notifyVerbose = functoolsKit.singleshot(() => {
753
883
  });
754
884
  });
755
885
 
756
- class SetupUtils {
757
- constructor() {
758
- this.enable = functoolsKit.singleshot(() => {
759
- cli.loggerService.debug("SetupUtils enable");
760
- {
761
- const config = cli.configService.getNotificationConfig();
762
- BacktestKit.Notification.enable(config);
763
- }
764
- {
765
- BacktestKit.Recent.enable();
766
- BacktestKit.Storage.enable();
767
- }
768
- {
769
- BacktestKit.Markdown.enable();
770
- BacktestKit.Report.enable();
771
- BacktestKit.Dump.enable();
772
- BacktestKit.State.enable();
773
- BacktestKit.Memory.enable();
774
- }
775
- {
776
- BacktestKit.Dump.useMarkdown();
777
- }
778
- {
779
- BacktestKit.SessionLive.usePersist();
780
- BacktestKit.SessionBacktest.useLocal();
781
- }
782
- {
783
- BacktestKit.StorageLive.usePersist();
784
- BacktestKit.StorageBacktest.useMemory();
785
- }
786
- {
787
- BacktestKit.RecentLive.usePersist();
788
- BacktestKit.RecentBacktest.useMemory();
789
- }
790
- {
791
- BacktestKit.NotificationLive.usePersist();
792
- BacktestKit.NotificationBacktest.useMemory();
793
- }
794
- {
795
- BacktestKit.RecentLive.usePersist();
796
- BacktestKit.RecentBacktest.useMemory();
797
- }
798
- {
799
- BacktestKit.MemoryLive.usePersist();
800
- BacktestKit.MemoryBacktest.useLocal();
801
- }
802
- {
803
- BacktestKit.StateLive.usePersist();
804
- BacktestKit.StateBacktest.useLocal();
805
- }
806
- {
807
- BacktestKit.Markdown.useDummy();
808
- BacktestKit.Log.useJsonl();
809
- }
810
- });
811
- this.clear = () => {
812
- cli.loggerService.debug("SetupUtils clear");
813
- if (!this.enable.hasValue()) {
814
- return;
815
- }
816
- this.enable.clear();
817
- {
818
- BacktestKit.Recent.disable();
819
- BacktestKit.Storage.disable();
820
- BacktestKit.Notification.disable();
821
- }
822
- {
823
- BacktestKit.Markdown.disable();
824
- BacktestKit.Report.disable();
825
- BacktestKit.Dump.disable();
826
- BacktestKit.Memory.disable();
827
- }
828
- {
829
- BacktestKit.Markdown.clear();
830
- BacktestKit.Report.clear();
831
- BacktestKit.MarkdownWriter.clear();
832
- BacktestKit.ReportWriter.clear();
833
- }
834
- {
835
- BacktestKit.PersistSignalAdapter.clear();
836
- BacktestKit.PersistRiskAdapter.clear();
837
- BacktestKit.PersistScheduleAdapter.clear();
838
- BacktestKit.PersistPartialAdapter.clear();
839
- BacktestKit.PersistBreakevenAdapter.clear();
840
- BacktestKit.PersistCandleAdapter.clear();
841
- BacktestKit.PersistStorageAdapter.clear();
842
- BacktestKit.PersistNotificationAdapter.clear();
843
- BacktestKit.PersistLogAdapter.clear();
844
- BacktestKit.PersistMeasureAdapter.clear();
845
- BacktestKit.PersistIntervalAdapter.clear();
846
- BacktestKit.PersistMemoryAdapter.clear();
847
- BacktestKit.PersistRecentAdapter.clear();
848
- BacktestKit.PersistStateAdapter.clear();
849
- BacktestKit.PersistSessionAdapter.clear();
850
- }
851
- {
852
- BacktestKit.Dump.clear();
853
- BacktestKit.Log.clear();
854
- BacktestKit.Markdown.clear();
855
- }
856
- {
857
- BacktestKit.StorageLive.clear();
858
- BacktestKit.StorageBacktest.clear();
859
- }
860
- {
861
- BacktestKit.NotificationLive.clear();
862
- BacktestKit.NotificationBacktest.clear();
863
- }
864
- {
865
- BacktestKit.RecentLive.clear();
866
- BacktestKit.RecentBacktest.clear();
867
- }
868
- };
869
- }
870
- }
871
- const Setup = new SetupUtils();
872
-
873
886
  const DEFAULT_CACHE_LIST$1 = ["1m", "15m", "30m", "1h", "4h"];
874
887
  const GET_CACHE_INTERVAL_LIST_FN$1 = () => {
875
888
  const { values } = getArgs();
@@ -897,6 +910,7 @@ class BacktestMainService {
897
910
  this.loggerService.log("backtestMainService run", {
898
911
  payload,
899
912
  });
913
+ await this.configConnectionService.loadConfig("setup.config");
900
914
  {
901
915
  await this.configService.waitForInit();
902
916
  Setup.enable();
@@ -909,7 +923,6 @@ class BacktestMainService {
909
923
  const cwd = process.cwd();
910
924
  dotenv.config({ path: path.join(cwd, '.env'), override: true, quiet: true });
911
925
  }
912
- await this.configConnectionService.loadConfig("setup.config");
913
926
  {
914
927
  await this.resolveService.attachJavascript(payload.entryPoint);
915
928
  await this.moduleConnectionService.loadModule("backtest.module");
@@ -1016,6 +1029,7 @@ class WalkerMainService {
1016
1029
  this.configConnectionService = inject(TYPES.configConnectionService);
1017
1030
  this.run = functoolsKit.singleshot(async (payload) => {
1018
1031
  this.loggerService.log("walkerMainService run", { payload });
1032
+ await this.configConnectionService.loadConfig("setup.config");
1019
1033
  {
1020
1034
  await this.configService.waitForInit();
1021
1035
  Setup.enable();
@@ -1034,7 +1048,7 @@ class WalkerMainService {
1034
1048
  Setup.enable();
1035
1049
  }
1036
1050
  {
1037
- cwd !== moduleRoot && BacktestKit.Log.useJsonl();
1051
+ cwd !== moduleRoot && Setup.update();
1038
1052
  dotenv.config({ path: path.join(cwd, '.env'), override: true, quiet: true });
1039
1053
  dotenv.config({ path: path.join(moduleRoot, '.env'), override: true, quiet: true });
1040
1054
  }
@@ -1053,7 +1067,6 @@ class WalkerMainService {
1053
1067
  const cwd = process.cwd();
1054
1068
  dotenv.config({ path: path.join(cwd, '.env'), override: true, quiet: true });
1055
1069
  }
1056
- await this.configConnectionService.loadConfig("setup.config");
1057
1070
  await this.moduleConnectionService.loadModule("walker.module");
1058
1071
  {
1059
1072
  this.exchangeSchemaService.addSchema();
@@ -1110,7 +1123,7 @@ class WalkerMainService {
1110
1123
  }
1111
1124
  restoreSnapshot();
1112
1125
  {
1113
- cwd !== moduleRoot && BacktestKit.Log.useJsonl();
1126
+ cwd !== moduleRoot && Setup.update();
1114
1127
  dotenv.config({ path: path.join(cwd, '.env'), override: true, quiet: true });
1115
1128
  dotenv.config({ path: path.join(moduleRoot, '.env'), override: true, quiet: true });
1116
1129
  }
@@ -1241,6 +1254,7 @@ class LiveMainService {
1241
1254
  this.loggerService.log("liveMainService run", {
1242
1255
  payload,
1243
1256
  });
1257
+ await this.configConnectionService.loadConfig("setup.config");
1244
1258
  {
1245
1259
  await this.configService.waitForInit();
1246
1260
  Setup.enable();
@@ -1253,7 +1267,6 @@ class LiveMainService {
1253
1267
  const cwd = process.cwd();
1254
1268
  dotenv.config({ path: path.join(cwd, '.env'), override: true, quiet: true });
1255
1269
  }
1256
- await this.configConnectionService.loadConfig("setup.config");
1257
1270
  {
1258
1271
  await this.resolveService.attachJavascript(payload.entryPoint);
1259
1272
  await this.moduleConnectionService.loadModule("live.module");
@@ -1327,6 +1340,7 @@ class PaperMainService {
1327
1340
  this.configConnectionService = inject(TYPES.configConnectionService);
1328
1341
  this.run = functoolsKit.singleshot(async (payload) => {
1329
1342
  this.loggerService.log("paperMainService init");
1343
+ await this.configConnectionService.loadConfig("setup.config");
1330
1344
  {
1331
1345
  await this.configService.waitForInit();
1332
1346
  Setup.enable();
@@ -1339,7 +1353,6 @@ class PaperMainService {
1339
1353
  const cwd = process.cwd();
1340
1354
  dotenv.config({ path: path.join(cwd, '.env'), override: true, quiet: true });
1341
1355
  }
1342
- await this.configConnectionService.loadConfig("setup.config");
1343
1356
  {
1344
1357
  await this.resolveService.attachJavascript(payload.entryPoint);
1345
1358
  await this.moduleConnectionService.loadModule("paper.module");
@@ -2540,12 +2553,22 @@ class ModuleConnectionService {
2540
2553
  this.loggerService = inject(TYPES.loggerService);
2541
2554
  this.resolveService = inject(TYPES.resolveService);
2542
2555
  this.loaderService = inject(TYPES.loaderService);
2543
- this.loadModule = async (fileName) => {
2544
- this.loggerService.log("moduleConnectionService loadModule", {
2556
+ this.hasModule = (fileName) => {
2557
+ this.loggerService.log("moduleConnectionService hasModule", {
2545
2558
  fileName,
2546
2559
  });
2547
- return await LOAD_MODULE_MODULE_FN(fileName, this);
2560
+ return this.loadModule.has(fileName);
2548
2561
  };
2562
+ this.loadModule = functoolsKit.memoize(([fileName]) => `${fileName}`, async (fileName) => {
2563
+ this.loggerService.log("moduleConnectionService loadModule", {
2564
+ fileName,
2565
+ });
2566
+ const module = await LOAD_MODULE_MODULE_FN(fileName, this);
2567
+ if (!module) {
2568
+ this.loadModule.clear(fileName);
2569
+ }
2570
+ return module;
2571
+ });
2549
2572
  }
2550
2573
  }
2551
2574
 
@@ -2588,6 +2611,18 @@ class BabelService {
2588
2611
  }
2589
2612
  }
2590
2613
 
2614
+ const require$1 = Module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
2615
+ const ModuleWithCache = Module;
2616
+ function overrideModule(moduleName, newExports) {
2617
+ const cache = ModuleWithCache._cache;
2618
+ const key = require$1.resolve(moduleName);
2619
+ if (!cache[key]) {
2620
+ cache[key] = new ModuleWithCache(key);
2621
+ cache[key].loaded = true;
2622
+ }
2623
+ cache[key].exports = newExports;
2624
+ }
2625
+
2591
2626
  /**
2592
2627
  * 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.
2593
2628
  * 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.
@@ -2770,7 +2805,7 @@ class ClientLoader {
2770
2805
  this.params.logger.log("ClientLoader baseRequire", {
2771
2806
  basePath: this.params.path,
2772
2807
  });
2773
- return module$1.createRequire(this.__filename);
2808
+ return Module.createRequire(this.__filename);
2774
2809
  });
2775
2810
  this.__filename = path.join(params.path, "index.cjs");
2776
2811
  this.__dirname = path.dirname(this.__filename);
@@ -2824,6 +2859,13 @@ globalThis.BacktestKitGraph = BacktestKitGraph__namespace;
2824
2859
  globalThis.BacktestKitOllama = BacktestKitOllama__namespace;
2825
2860
  globalThis.BacktestKitPinets = BacktestKitPinets__namespace;
2826
2861
  globalThis.BacktestKitSignals = BacktestKitSignals__namespace;
2862
+ overrideModule('backtest-kit', BacktestKit__namespace);
2863
+ overrideModule('@backtest-kit/cli', BacktestKitCli);
2864
+ overrideModule('@backtest-kit/ui', BacktestKitUi__namespace);
2865
+ overrideModule('@backtest-kit/graph', BacktestKitGraph__namespace);
2866
+ overrideModule('@backtest-kit/ollama', BacktestKitOllama__namespace);
2867
+ overrideModule('@backtest-kit/pinets', BacktestKitPinets__namespace);
2868
+ overrideModule('@backtest-kit/signals', BacktestKitSignals__namespace);
2827
2869
 
2828
2870
  const GET_ALIAS_EXPORTS_FN = (self) => {
2829
2871
  const instance = self.getInstance(self.resolveService.OVERRIDE_CONFIG_DIR);
@@ -2831,9 +2873,7 @@ const GET_ALIAS_EXPORTS_FN = (self) => {
2831
2873
  return null;
2832
2874
  }
2833
2875
  const exports = instance.import("alias.config");
2834
- return "default" in exports
2835
- ? exports.default
2836
- : exports;
2876
+ return "default" in exports ? exports.default : exports;
2837
2877
  };
2838
2878
  const INIT_ALIAS_FN = (self) => {
2839
2879
  const alias = GET_ALIAS_EXPORTS_FN(self);
@@ -2843,7 +2883,10 @@ const INIT_ALIAS_FN = (self) => {
2843
2883
  if (!functoolsKit.isObject(alias)) {
2844
2884
  return;
2845
2885
  }
2846
- Object.assign(IMPORT_ALIAS, alias);
2886
+ {
2887
+ Object.entries(alias).forEach(([name, module]) => overrideModule(name, module));
2888
+ Object.assign(IMPORT_ALIAS, alias);
2889
+ }
2847
2890
  };
2848
2891
  class LoaderService {
2849
2892
  constructor() {
@@ -2914,12 +2957,22 @@ class ConfigConnectionService {
2914
2957
  this.loggerService = inject(TYPES.loggerService);
2915
2958
  this.resolveService = inject(TYPES.resolveService);
2916
2959
  this.loaderService = inject(TYPES.loaderService);
2917
- this.loadConfig = (fileName) => {
2918
- this.loggerService.log("configConnectionService loadConfig", {
2960
+ this.hasConfig = (fileName) => {
2961
+ this.loggerService.log("configConnectionService hasConfig", {
2919
2962
  fileName,
2920
2963
  });
2921
- return LOAD_CONFIG_CONFIG_FN(fileName, this);
2964
+ return this.loadConfig.has(fileName);
2922
2965
  };
2966
+ this.loadConfig = functoolsKit.memoize(([fileName]) => `${fileName}`, async (fileName) => {
2967
+ this.loggerService.log("configConnectionService loadConfig", {
2968
+ fileName,
2969
+ });
2970
+ const config = await LOAD_CONFIG_CONFIG_FN(fileName, this);
2971
+ if (!config) {
2972
+ this.loadConfig.clear(fileName);
2973
+ }
2974
+ return config;
2975
+ });
2923
2976
  }
2924
2977
  }
2925
2978
 
@@ -3363,15 +3416,17 @@ const main$a = async () => {
3363
3416
  if (!values.noFlush) {
3364
3417
  await flush(entryPoint);
3365
3418
  }
3366
- await cli.configService.waitForInit();
3367
- Setup.enable();
3419
+ await cli.configConnectionService.loadConfig("setup.config");
3420
+ {
3421
+ await cli.configService.waitForInit();
3422
+ Setup.enable();
3423
+ }
3368
3424
  cli.frontendProviderService.connect();
3369
3425
  cli.telegramProviderService.connect();
3370
3426
  {
3371
3427
  const cwd = process.cwd();
3372
3428
  dotenv.config({ path: path.join(cwd, '.env'), override: true, quiet: true });
3373
3429
  }
3374
- await cli.configConnectionService.loadConfig("setup.config");
3375
3430
  await cli.moduleConnectionService.loadModule(MODE_MODULE[mode]);
3376
3431
  listenFinish();
3377
3432
  createGracefulShutdown(mode)();
@@ -3538,6 +3593,7 @@ const main$6 = async () => {
3538
3593
  console.warn("--editor and --pine are mutually exclusive. Use one at a time.");
3539
3594
  process.exit(1);
3540
3595
  }
3596
+ await cli.configConnectionService.loadConfig("setup.config");
3541
3597
  {
3542
3598
  await cli.configService.waitForInit();
3543
3599
  Setup.enable();
@@ -3546,7 +3602,6 @@ const main$6 = async () => {
3546
3602
  const cwd = process.cwd();
3547
3603
  dotenv.config({ path: path.join(cwd, '.env'), override: true, quiet: true });
3548
3604
  }
3549
- await cli.configConnectionService.loadConfig("setup.config");
3550
3605
  await cli.moduleConnectionService.loadModule("editor.module");
3551
3606
  {
3552
3607
  await cli.exchangeSchemaService.addSchema();
package/build/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import * as BacktestKit from 'backtest-kit';
3
- import { setConfig, Log, listExchangeSchema, addExchangeSchema, roundTicks, listFrameSchema, addFrameSchema, listenDoneLive, listenDoneBacktest, shutdown, listenSignal, Notification, Recent, Storage, Markdown, Report, Dump, State, Memory, SessionLive, SessionBacktest, StorageLive, StorageBacktest, RecentLive, RecentBacktest, NotificationLive, NotificationBacktest, MemoryLive, MemoryBacktest, StateLive, StateBacktest, MarkdownWriter, ReportWriter, PersistSignalAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistPartialAdapter, PersistBreakevenAdapter, PersistCandleAdapter, PersistStorageAdapter, PersistNotificationAdapter, PersistLogAdapter, PersistMeasureAdapter, PersistIntervalAdapter, PersistMemoryAdapter, PersistRecentAdapter, PersistStateAdapter, PersistSessionAdapter, listStrategySchema, overrideExchangeSchema, Backtest, System, Cache, Interval, alignToInterval, addWalkerSchema, overrideWalkerSchema, Walker, listenDoneWalker, Live, getCandles, checkCandles, warmCandles, listenRisk, listenStrategyCommit, listenSync, listenSignalNotify, Exchange } from 'backtest-kit';
3
+ import { setConfig, Notification, Recent, Storage, Markdown, Report, Dump, State, Memory, MarkdownWriter, ReportWriter, PersistSignalAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistPartialAdapter, PersistBreakevenAdapter, PersistCandleAdapter, PersistStorageAdapter, PersistNotificationAdapter, PersistLogAdapter, PersistMeasureAdapter, PersistIntervalAdapter, PersistMemoryAdapter, PersistRecentAdapter, PersistStateAdapter, PersistSessionAdapter, Log, StorageLive, StorageBacktest, NotificationLive, NotificationBacktest, RecentLive, RecentBacktest, SessionLive, SessionBacktest, MemoryLive, MemoryBacktest, StateLive, StateBacktest, listExchangeSchema, addExchangeSchema, roundTicks, listFrameSchema, addFrameSchema, listenDoneLive, listenDoneBacktest, shutdown, listenSignal, listStrategySchema, overrideExchangeSchema, Backtest, System, Cache, Interval, alignToInterval, addWalkerSchema, overrideWalkerSchema, Walker, listenDoneWalker, Live, getCandles, checkCandles, warmCandles, listenRisk, listenStrategyCommit, listenSync, listenSignalNotify, Exchange } from 'backtest-kit';
4
4
  import { getErrorMessage, errorData, singleshot, str, BehaviorSubject, compose, createAwaiter, execpool, queued, sleep, randomString, TIMEOUT_SYMBOL, typo, retry, trycatch, memoize, isObject } from 'functools-kit';
5
5
  import fs, { constants, realpathSync } from 'fs';
6
6
  import * as stackTrace from 'stack-trace';
@@ -24,7 +24,7 @@ import { JSDOM } from 'jsdom';
24
24
  import Mustache from 'mustache';
25
25
  import { registerPlugin, transform } from '@babel/standalone';
26
26
  import pluginUMD from '@babel/plugin-transform-modules-umd';
27
- import { createRequire } from 'module';
27
+ import Module, { createRequire } from 'module';
28
28
  import * as BacktestKitGraph from '@backtest-kit/graph';
29
29
  import * as BacktestKitOllama from '@backtest-kit/ollama';
30
30
  import * as BacktestKitPinets from '@backtest-kit/pinets';
@@ -241,6 +241,136 @@ const TYPES = {
241
241
 
242
242
  const entrySubject = new BehaviorSubject();
243
243
 
244
+ const SETUP_ADAPTER_FN = () => {
245
+ {
246
+ Dump.useMarkdown();
247
+ }
248
+ {
249
+ SessionLive.usePersist();
250
+ SessionBacktest.useLocal();
251
+ }
252
+ {
253
+ StorageLive.usePersist();
254
+ StorageBacktest.useMemory();
255
+ }
256
+ {
257
+ RecentLive.usePersist();
258
+ RecentBacktest.useMemory();
259
+ }
260
+ {
261
+ NotificationLive.usePersist();
262
+ NotificationBacktest.useMemory();
263
+ }
264
+ {
265
+ RecentLive.usePersist();
266
+ RecentBacktest.useMemory();
267
+ }
268
+ {
269
+ MemoryLive.usePersist();
270
+ MemoryBacktest.useLocal();
271
+ }
272
+ {
273
+ StateLive.usePersist();
274
+ StateBacktest.useLocal();
275
+ }
276
+ {
277
+ Markdown.useDummy();
278
+ Log.useJsonl();
279
+ }
280
+ };
281
+ class SetupUtils {
282
+ constructor() {
283
+ this.enable = singleshot(() => {
284
+ cli.loggerService.debug("SetupUtils enable");
285
+ {
286
+ const config = cli.configService.getNotificationConfig();
287
+ Notification.enable(config);
288
+ }
289
+ {
290
+ Recent.enable();
291
+ Storage.enable();
292
+ }
293
+ {
294
+ Markdown.enable();
295
+ Report.enable();
296
+ Dump.enable();
297
+ State.enable();
298
+ Memory.enable();
299
+ }
300
+ if (!cli.configConnectionService.hasConfig("setup.config")) {
301
+ SETUP_ADAPTER_FN();
302
+ }
303
+ });
304
+ this.clear = () => {
305
+ cli.loggerService.debug("SetupUtils clear");
306
+ if (!this.enable.hasValue()) {
307
+ return;
308
+ }
309
+ this.enable.clear();
310
+ {
311
+ Recent.disable();
312
+ Storage.disable();
313
+ Notification.disable();
314
+ }
315
+ {
316
+ Markdown.disable();
317
+ Report.disable();
318
+ Dump.disable();
319
+ Memory.disable();
320
+ }
321
+ {
322
+ Markdown.clear();
323
+ Report.clear();
324
+ MarkdownWriter.clear();
325
+ ReportWriter.clear();
326
+ }
327
+ {
328
+ PersistSignalAdapter.clear();
329
+ PersistRiskAdapter.clear();
330
+ PersistScheduleAdapter.clear();
331
+ PersistPartialAdapter.clear();
332
+ PersistBreakevenAdapter.clear();
333
+ PersistCandleAdapter.clear();
334
+ PersistStorageAdapter.clear();
335
+ PersistNotificationAdapter.clear();
336
+ PersistLogAdapter.clear();
337
+ PersistMeasureAdapter.clear();
338
+ PersistIntervalAdapter.clear();
339
+ PersistMemoryAdapter.clear();
340
+ PersistRecentAdapter.clear();
341
+ PersistStateAdapter.clear();
342
+ PersistSessionAdapter.clear();
343
+ }
344
+ {
345
+ Dump.clear();
346
+ Log.clear();
347
+ Markdown.clear();
348
+ }
349
+ {
350
+ StorageLive.clear();
351
+ StorageBacktest.clear();
352
+ }
353
+ {
354
+ NotificationLive.clear();
355
+ NotificationBacktest.clear();
356
+ }
357
+ {
358
+ RecentLive.clear();
359
+ RecentBacktest.clear();
360
+ }
361
+ };
362
+ this.update = () => {
363
+ cli.loggerService.debug("SetupUtils update");
364
+ if (cli.configConnectionService.hasConfig("setup.config")) {
365
+ return;
366
+ }
367
+ Log.useJsonl();
368
+ Dump.useMarkdown();
369
+ };
370
+ }
371
+ }
372
+ const Setup = new SetupUtils();
373
+
244
374
  const __filename$2 = fileURLToPath(import.meta.url);
245
375
  const __dirname$2 = path.dirname(__filename$2);
246
376
  let _is_launched = false;
@@ -302,7 +432,7 @@ class ResolveService {
302
432
  {
303
433
  const cwd = process.cwd();
304
434
  process.chdir(moduleRoot);
305
- cwd !== moduleRoot && Log.useJsonl();
435
+ cwd !== moduleRoot && Setup.update();
306
436
  dotenv.config({ path: path.join(cwd, '.env'), override: true, quiet: true });
307
437
  dotenv.config({ path: path.join(moduleRoot, '.env'), override: true, quiet: true });
308
438
  this.loaderService.import(absolutePath);
@@ -728,123 +858,6 @@ const notifyVerbose = singleshot(() => {
728
858
  });
729
859
  });
730
860
 
731
- class SetupUtils {
732
- constructor() {
733
- this.enable = singleshot(() => {
734
- cli.loggerService.debug("SetupUtils enable");
735
- {
736
- const config = cli.configService.getNotificationConfig();
737
- Notification.enable(config);
738
- }
739
- {
740
- Recent.enable();
741
- Storage.enable();
742
- }
743
- {
744
- Markdown.enable();
745
- Report.enable();
746
- Dump.enable();
747
- State.enable();
748
- Memory.enable();
749
- }
750
- {
751
- Dump.useMarkdown();
752
- }
753
- {
754
- SessionLive.usePersist();
755
- SessionBacktest.useLocal();
756
- }
757
- {
758
- StorageLive.usePersist();
759
- StorageBacktest.useMemory();
760
- }
761
- {
762
- RecentLive.usePersist();
763
- RecentBacktest.useMemory();
764
- }
765
- {
766
- NotificationLive.usePersist();
767
- NotificationBacktest.useMemory();
768
- }
769
- {
770
- RecentLive.usePersist();
771
- RecentBacktest.useMemory();
772
- }
773
- {
774
- MemoryLive.usePersist();
775
- MemoryBacktest.useLocal();
776
- }
777
- {
778
- StateLive.usePersist();
779
- StateBacktest.useLocal();
780
- }
781
- {
782
- Markdown.useDummy();
783
- Log.useJsonl();
784
- }
785
- });
786
- this.clear = () => {
787
- cli.loggerService.debug("SetupUtils clear");
788
- if (!this.enable.hasValue()) {
789
- return;
790
- }
791
- this.enable.clear();
792
- {
793
- Recent.disable();
794
- Storage.disable();
795
- Notification.disable();
796
- }
797
- {
798
- Markdown.disable();
799
- Report.disable();
800
- Dump.disable();
801
- Memory.disable();
802
- }
803
- {
804
- Markdown.clear();
805
- Report.clear();
806
- MarkdownWriter.clear();
807
- ReportWriter.clear();
808
- }
809
- {
810
- PersistSignalAdapter.clear();
811
- PersistRiskAdapter.clear();
812
- PersistScheduleAdapter.clear();
813
- PersistPartialAdapter.clear();
814
- PersistBreakevenAdapter.clear();
815
- PersistCandleAdapter.clear();
816
- PersistStorageAdapter.clear();
817
- PersistNotificationAdapter.clear();
818
- PersistLogAdapter.clear();
819
- PersistMeasureAdapter.clear();
820
- PersistIntervalAdapter.clear();
821
- PersistMemoryAdapter.clear();
822
- PersistRecentAdapter.clear();
823
- PersistStateAdapter.clear();
824
- PersistSessionAdapter.clear();
825
- }
826
- {
827
- Dump.clear();
828
- Log.clear();
829
- Markdown.clear();
830
- }
831
- {
832
- StorageLive.clear();
833
- StorageBacktest.clear();
834
- }
835
- {
836
- NotificationLive.clear();
837
- NotificationBacktest.clear();
838
- }
839
- {
840
- RecentLive.clear();
841
- RecentBacktest.clear();
842
- }
843
- };
844
- }
845
- }
846
- const Setup = new SetupUtils();
847
-
848
861
  const DEFAULT_CACHE_LIST$1 = ["1m", "15m", "30m", "1h", "4h"];
849
862
  const GET_CACHE_INTERVAL_LIST_FN$1 = () => {
850
863
  const { values } = getArgs();
@@ -872,6 +885,7 @@ class BacktestMainService {
872
885
  this.loggerService.log("backtestMainService run", {
873
886
  payload,
874
887
  });
888
+ await this.configConnectionService.loadConfig("setup.config");
875
889
  {
876
890
  await this.configService.waitForInit();
877
891
  Setup.enable();
@@ -884,7 +898,6 @@ class BacktestMainService {
884
898
  const cwd = process.cwd();
885
899
  dotenv.config({ path: path.join(cwd, '.env'), override: true, quiet: true });
886
900
  }
887
- await this.configConnectionService.loadConfig("setup.config");
888
901
  {
889
902
  await this.resolveService.attachJavascript(payload.entryPoint);
890
903
  await this.moduleConnectionService.loadModule("backtest.module");
@@ -991,6 +1004,7 @@ class WalkerMainService {
991
1004
  this.configConnectionService = inject(TYPES.configConnectionService);
992
1005
  this.run = singleshot(async (payload) => {
993
1006
  this.loggerService.log("walkerMainService run", { payload });
1007
+ await this.configConnectionService.loadConfig("setup.config");
994
1008
  {
995
1009
  await this.configService.waitForInit();
996
1010
  Setup.enable();
@@ -1009,7 +1023,7 @@ class WalkerMainService {
1009
1023
  Setup.enable();
1010
1024
  }
1011
1025
  {
1012
- cwd !== moduleRoot && Log.useJsonl();
1026
+ cwd !== moduleRoot && Setup.update();
1013
1027
  dotenv.config({ path: path.join(cwd, '.env'), override: true, quiet: true });
1014
1028
  dotenv.config({ path: path.join(moduleRoot, '.env'), override: true, quiet: true });
1015
1029
  }
@@ -1028,7 +1042,6 @@ class WalkerMainService {
1028
1042
  const cwd = process.cwd();
1029
1043
  dotenv.config({ path: path.join(cwd, '.env'), override: true, quiet: true });
1030
1044
  }
1031
- await this.configConnectionService.loadConfig("setup.config");
1032
1045
  await this.moduleConnectionService.loadModule("walker.module");
1033
1046
  {
1034
1047
  this.exchangeSchemaService.addSchema();
@@ -1085,7 +1098,7 @@ class WalkerMainService {
1085
1098
  }
1086
1099
  restoreSnapshot();
1087
1100
  {
1088
- cwd !== moduleRoot && Log.useJsonl();
1101
+ cwd !== moduleRoot && Setup.update();
1089
1102
  dotenv.config({ path: path.join(cwd, '.env'), override: true, quiet: true });
1090
1103
  dotenv.config({ path: path.join(moduleRoot, '.env'), override: true, quiet: true });
1091
1104
  }
@@ -1216,6 +1229,7 @@ class LiveMainService {
1216
1229
  this.loggerService.log("liveMainService run", {
1217
1230
  payload,
1218
1231
  });
1232
+ await this.configConnectionService.loadConfig("setup.config");
1219
1233
  {
1220
1234
  await this.configService.waitForInit();
1221
1235
  Setup.enable();
@@ -1228,7 +1242,6 @@ class LiveMainService {
1228
1242
  const cwd = process.cwd();
1229
1243
  dotenv.config({ path: path.join(cwd, '.env'), override: true, quiet: true });
1230
1244
  }
1231
- await this.configConnectionService.loadConfig("setup.config");
1232
1245
  {
1233
1246
  await this.resolveService.attachJavascript(payload.entryPoint);
1234
1247
  await this.moduleConnectionService.loadModule("live.module");
@@ -1302,6 +1315,7 @@ class PaperMainService {
1302
1315
  this.configConnectionService = inject(TYPES.configConnectionService);
1303
1316
  this.run = singleshot(async (payload) => {
1304
1317
  this.loggerService.log("paperMainService init");
1318
+ await this.configConnectionService.loadConfig("setup.config");
1305
1319
  {
1306
1320
  await this.configService.waitForInit();
1307
1321
  Setup.enable();
@@ -1314,7 +1328,6 @@ class PaperMainService {
1314
1328
  const cwd = process.cwd();
1315
1329
  dotenv.config({ path: path.join(cwd, '.env'), override: true, quiet: true });
1316
1330
  }
1317
- await this.configConnectionService.loadConfig("setup.config");
1318
1331
  {
1319
1332
  await this.resolveService.attachJavascript(payload.entryPoint);
1320
1333
  await this.moduleConnectionService.loadModule("paper.module");
@@ -2515,12 +2528,22 @@ class ModuleConnectionService {
2515
2528
  this.loggerService = inject(TYPES.loggerService);
2516
2529
  this.resolveService = inject(TYPES.resolveService);
2517
2530
  this.loaderService = inject(TYPES.loaderService);
2518
- this.loadModule = async (fileName) => {
2519
- this.loggerService.log("moduleConnectionService loadModule", {
2531
+ this.hasModule = (fileName) => {
2532
+ this.loggerService.log("moduleConnectionService hasModule", {
2520
2533
  fileName,
2521
2534
  });
2522
- return await LOAD_MODULE_MODULE_FN(fileName, this);
2535
+ return this.loadModule.has(fileName);
2523
2536
  };
2537
+ this.loadModule = memoize(([fileName]) => `${fileName}`, async (fileName) => {
2538
+ this.loggerService.log("moduleConnectionService loadModule", {
2539
+ fileName,
2540
+ });
2541
+ const module = await LOAD_MODULE_MODULE_FN(fileName, this);
2542
+ if (!module) {
2543
+ this.loadModule.clear(fileName);
2544
+ }
2545
+ return module;
2546
+ });
2524
2547
  }
2525
2548
  }
2526
2549
 
@@ -2563,6 +2586,18 @@ class BabelService {
2563
2586
  }
2564
2587
  }
2565
2588
 
2589
+ const require = createRequire(import.meta.url);
2590
+ const ModuleWithCache = Module;
2591
+ function overrideModule(moduleName, newExports) {
2592
+ const cache = ModuleWithCache._cache;
2593
+ const key = require.resolve(moduleName);
2594
+ if (!cache[key]) {
2595
+ cache[key] = new ModuleWithCache(key);
2596
+ cache[key].loaded = true;
2597
+ }
2598
+ cache[key].exports = newExports;
2599
+ }
2600
+
2566
2601
  /**
2567
2602
  * 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.
2568
2603
  * 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.
@@ -2795,6 +2830,13 @@ globalThis.BacktestKitGraph = BacktestKitGraph;
2795
2830
  globalThis.BacktestKitOllama = BacktestKitOllama;
2796
2831
  globalThis.BacktestKitPinets = BacktestKitPinets;
2797
2832
  globalThis.BacktestKitSignals = BacktestKitSignals;
2833
+ overrideModule('backtest-kit', BacktestKit);
2834
+ overrideModule('@backtest-kit/cli', BacktestKitCli);
2835
+ overrideModule('@backtest-kit/ui', BacktestKitUi);
2836
+ overrideModule('@backtest-kit/graph', BacktestKitGraph);
2837
+ overrideModule('@backtest-kit/ollama', BacktestKitOllama);
2838
+ overrideModule('@backtest-kit/pinets', BacktestKitPinets);
2839
+ overrideModule('@backtest-kit/signals', BacktestKitSignals);
2798
2840
 
2799
2841
  const GET_ALIAS_EXPORTS_FN = (self) => {
2800
2842
  const instance = self.getInstance(self.resolveService.OVERRIDE_CONFIG_DIR);
@@ -2802,9 +2844,7 @@ const GET_ALIAS_EXPORTS_FN = (self) => {
2802
2844
  return null;
2803
2845
  }
2804
2846
  const exports = instance.import("alias.config");
2805
- return "default" in exports
2806
- ? exports.default
2807
- : exports;
2847
+ return "default" in exports ? exports.default : exports;
2808
2848
  };
2809
2849
  const INIT_ALIAS_FN = (self) => {
2810
2850
  const alias = GET_ALIAS_EXPORTS_FN(self);
@@ -2814,7 +2854,10 @@ const INIT_ALIAS_FN = (self) => {
2814
2854
  if (!isObject(alias)) {
2815
2855
  return;
2816
2856
  }
2817
- Object.assign(IMPORT_ALIAS, alias);
2857
+ {
2858
+ Object.entries(alias).forEach(([name, module]) => overrideModule(name, module));
2859
+ Object.assign(IMPORT_ALIAS, alias);
2860
+ }
2818
2861
  };
2819
2862
  class LoaderService {
2820
2863
  constructor() {
@@ -2885,12 +2928,22 @@ class ConfigConnectionService {
2885
2928
  this.loggerService = inject(TYPES.loggerService);
2886
2929
  this.resolveService = inject(TYPES.resolveService);
2887
2930
  this.loaderService = inject(TYPES.loaderService);
2888
- this.loadConfig = (fileName) => {
2889
- this.loggerService.log("configConnectionService loadConfig", {
2931
+ this.hasConfig = (fileName) => {
2932
+ this.loggerService.log("configConnectionService hasConfig", {
2890
2933
  fileName,
2891
2934
  });
2892
- return LOAD_CONFIG_CONFIG_FN(fileName, this);
2935
+ return this.loadConfig.has(fileName);
2893
2936
  };
2937
+ this.loadConfig = memoize(([fileName]) => `${fileName}`, async (fileName) => {
2938
+ this.loggerService.log("configConnectionService loadConfig", {
2939
+ fileName,
2940
+ });
2941
+ const config = await LOAD_CONFIG_CONFIG_FN(fileName, this);
2942
+ if (!config) {
2943
+ this.loadConfig.clear(fileName);
2944
+ }
2945
+ return config;
2946
+ });
2894
2947
  }
2895
2948
  }
2896
2949
 
@@ -3334,15 +3387,17 @@ const main$a = async () => {
3334
3387
  if (!values.noFlush) {
3335
3388
  await flush(entryPoint);
3336
3389
  }
3337
- await cli.configService.waitForInit();
3338
- Setup.enable();
3390
+ await cli.configConnectionService.loadConfig("setup.config");
3391
+ {
3392
+ await cli.configService.waitForInit();
3393
+ Setup.enable();
3394
+ }
3339
3395
  cli.frontendProviderService.connect();
3340
3396
  cli.telegramProviderService.connect();
3341
3397
  {
3342
3398
  const cwd = process.cwd();
3343
3399
  dotenv.config({ path: path.join(cwd, '.env'), override: true, quiet: true });
3344
3400
  }
3345
- await cli.configConnectionService.loadConfig("setup.config");
3346
3401
  await cli.moduleConnectionService.loadModule(MODE_MODULE[mode]);
3347
3402
  listenFinish();
3348
3403
  createGracefulShutdown(mode)();
@@ -3509,6 +3564,7 @@ const main$6 = async () => {
3509
3564
  console.warn("--editor and --pine are mutually exclusive. Use one at a time.");
3510
3565
  process.exit(1);
3511
3566
  }
3567
+ await cli.configConnectionService.loadConfig("setup.config");
3512
3568
  {
3513
3569
  await cli.configService.waitForInit();
3514
3570
  Setup.enable();
@@ -3517,7 +3573,6 @@ const main$6 = async () => {
3517
3573
  const cwd = process.cwd();
3518
3574
  dotenv.config({ path: path.join(cwd, '.env'), override: true, quiet: true });
3519
3575
  }
3520
- await cli.configConnectionService.loadConfig("setup.config");
3521
3576
  await cli.moduleConnectionService.loadModule("editor.module");
3522
3577
  {
3523
3578
  await cli.exchangeSchemaService.addSchema();
@@ -15,17 +15,17 @@
15
15
  "@types/node": "25.6.0"
16
16
  },
17
17
  "dependencies": {
18
- "@backtest-kit/cli": "9.3.0",
19
- "@backtest-kit/graph": "9.3.0",
20
- "@backtest-kit/pinets": "9.3.0",
21
- "@backtest-kit/signals": "9.3.0",
22
- "@backtest-kit/ui": "9.3.0",
18
+ "@backtest-kit/cli": "9.4.0",
19
+ "@backtest-kit/graph": "9.4.0",
20
+ "@backtest-kit/pinets": "9.4.0",
21
+ "@backtest-kit/signals": "9.4.0",
22
+ "@backtest-kit/ui": "9.4.0",
23
23
  "@tavily/core": "0.7.2",
24
24
  "@tensorflow/tfjs": "4.22.0",
25
25
  "@tensorflow/tfjs-backend-wasm": "4.22.0",
26
26
  "@tensorflow/tfjs-core": "4.22.0",
27
27
  "agent-swarm-kit": "2.6.0",
28
- "backtest-kit": "9.3.0",
28
+ "backtest-kit": "9.4.0",
29
29
  "dayjs": "1.11.20",
30
30
  "functools-kit": "2.3.0",
31
31
  "garch": "1.2.3",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backtest-kit/cli",
3
- "version": "9.3.0",
3
+ "version": "9.4.0",
4
4
  "description": "Zero-boilerplate CLI runner for backtest-kit strategies. Run backtests, paper trading, and live bots with candle cache warming, web dashboard, and Telegram notifications — no setup code required.",
5
5
  "author": {
6
6
  "name": "Petr Tripolsky",
@@ -63,11 +63,11 @@
63
63
  "devDependencies": {
64
64
  "@babel/plugin-transform-modules-umd": "7.27.1",
65
65
  "@babel/standalone": "7.29.1",
66
- "@backtest-kit/graph": "9.3.0",
67
- "@backtest-kit/ollama": "9.3.0",
68
- "@backtest-kit/pinets": "9.3.0",
69
- "@backtest-kit/signals": "9.3.0",
70
- "@backtest-kit/ui": "9.3.0",
66
+ "@backtest-kit/graph": "9.4.0",
67
+ "@backtest-kit/ollama": "9.4.0",
68
+ "@backtest-kit/pinets": "9.4.0",
69
+ "@backtest-kit/signals": "9.4.0",
70
+ "@backtest-kit/ui": "9.4.0",
71
71
  "@rollup/plugin-replace": "6.0.3",
72
72
  "@rollup/plugin-typescript": "11.1.6",
73
73
  "@types/image-size": "0.7.0",
@@ -75,7 +75,7 @@
75
75
  "@types/mustache": "4.2.6",
76
76
  "@types/node": "22.9.0",
77
77
  "@types/stack-trace": "0.0.33",
78
- "backtest-kit": "9.3.0",
78
+ "backtest-kit": "9.4.0",
79
79
  "glob": "11.0.1",
80
80
  "markdown-it": "14.1.1",
81
81
  "rimraf": "6.0.1",
@@ -90,12 +90,12 @@
90
90
  "peerDependencies": {
91
91
  "@babel/plugin-transform-modules-umd": "^7.27.1",
92
92
  "@babel/standalone": "^7.29.1",
93
- "@backtest-kit/graph": "^9.3.0",
94
- "@backtest-kit/ollama": "^9.3.0",
95
- "@backtest-kit/pinets": "^9.3.0",
96
- "@backtest-kit/signals": "^9.3.0",
97
- "@backtest-kit/ui": "^9.3.0",
98
- "backtest-kit": "^9.3.0",
93
+ "@backtest-kit/graph": "^9.4.0",
94
+ "@backtest-kit/ollama": "^9.4.0",
95
+ "@backtest-kit/pinets": "^9.4.0",
96
+ "@backtest-kit/signals": "^9.4.0",
97
+ "@backtest-kit/ui": "^9.4.0",
98
+ "backtest-kit": "^9.4.0",
99
99
  "markdown-it": "^14.1.1",
100
100
  "typescript": "^5.0.0"
101
101
  },
@@ -13,12 +13,12 @@
13
13
  "license": "ISC",
14
14
  "type": "commonjs",
15
15
  "dependencies": {
16
- "@backtest-kit/cli": "^9.3.0",
17
- "@backtest-kit/graph": "^9.3.0",
18
- "@backtest-kit/pinets": "^9.3.0",
19
- "@backtest-kit/ui": "^9.3.0",
16
+ "@backtest-kit/cli": "^9.4.0",
17
+ "@backtest-kit/graph": "^9.4.0",
18
+ "@backtest-kit/pinets": "^9.4.0",
19
+ "@backtest-kit/ui": "^9.4.0",
20
20
  "agent-swarm-kit": "^2.6.0",
21
- "backtest-kit": "^9.3.0",
21
+ "backtest-kit": "^9.4.0",
22
22
  "functools-kit": "^2.3.0",
23
23
  "garch": "^1.2.3",
24
24
  "get-moment-stamp": "^1.1.2",
package/types.d.ts CHANGED
@@ -249,7 +249,8 @@ declare class ConfigConnectionService {
249
249
  readonly loggerService: LoggerService;
250
250
  readonly resolveService: ResolveService;
251
251
  readonly loaderService: LoaderService;
252
- loadConfig: (fileName: string) => Promise<ModuleExports>;
252
+ hasConfig: (fileName: string) => boolean;
253
+ loadConfig: ((fileName: string) => Promise<ModuleExports>) & functools_kit.IClearableMemoize<string> & functools_kit.IControlMemoize<string, Promise<ModuleExports>>;
253
254
  }
254
255
 
255
256
  declare class FrontendProviderService {
@@ -381,7 +382,8 @@ declare class ModuleConnectionService {
381
382
  readonly loggerService: LoggerService;
382
383
  readonly resolveService: ResolveService;
383
384
  readonly loaderService: LoaderService;
384
- loadModule: (fileName: string) => Promise<boolean>;
385
+ hasModule: (fileName: string) => boolean;
386
+ loadModule: ((fileName: string) => Promise<boolean>) & functools_kit.IClearableMemoize<string> & functools_kit.IControlMemoize<string, Promise<boolean>>;
385
387
  }
386
388
 
387
389
  declare class ConfigService {
@@ -420,6 +422,7 @@ declare const cli: {
420
422
  declare class SetupUtils {
421
423
  enable: (() => void) & functools_kit.ISingleshotClearable<() => void>;
422
424
  clear: () => void;
425
+ update: () => void;
423
426
  }
424
427
  declare const Setup: SetupUtils;
425
428