@tradejs/node 1.0.2 → 1.0.4

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.
@@ -5,9 +5,9 @@ import {
5
5
  buildAiPayload,
6
6
  buildAiSystemPrompt,
7
7
  trimSeriesDeep
8
- } from "./chunk-ZIMX3JX2.mjs";
9
- import "./chunk-MHCXPD2B.mjs";
10
- import "./chunk-DE7ADBIR.mjs";
8
+ } from "./chunk-LMAKIC3C.mjs";
9
+ import "./chunk-ZY6ULOWK.mjs";
10
+ import "./chunk-P2ZUWONT.mjs";
11
11
  import "./chunk-6DZX6EAA.mjs";
12
12
  export {
13
13
  MAX_AI_SERIES_POINTS,
@@ -1,7 +1,7 @@
1
1
  export * from '@tradejs/core/backtest';
2
2
  import { TestingBox, TestConnectorCreator } from '@tradejs/types';
3
3
 
4
- declare const resetTestingKlineCache: () => void;
4
+ declare const resetTestingKlineCache: (cwd?: string) => void;
5
5
  declare const testing: TestingBox;
6
6
 
7
7
  declare const createTestConnector: TestConnectorCreator;
@@ -1,7 +1,7 @@
1
1
  export * from '@tradejs/core/backtest';
2
2
  import { TestingBox, TestConnectorCreator } from '@tradejs/types';
3
3
 
4
- declare const resetTestingKlineCache: () => void;
4
+ declare const resetTestingKlineCache: (cwd?: string) => void;
5
5
  declare const testing: TestingBox;
6
6
 
7
7
  declare const createTestConnector: TestConnectorCreator;
package/dist/backtest.js CHANGED
@@ -5550,6 +5550,7 @@ var TS_MODULE_RE = /\.(cts|mts|ts)$/i;
5550
5550
  var cachedByCwd = /* @__PURE__ */ new Map();
5551
5551
  var announcedConfigFile = /* @__PURE__ */ new Set();
5552
5552
  var tsNodeRegistered = false;
5553
+ var tsconfigPathsRegisteredByCwd = /* @__PURE__ */ new Set();
5553
5554
  var getTradejsProjectCwd = (cwd) => {
5554
5555
  const explicit = String(cwd ?? "").trim();
5555
5556
  if (explicit) {
@@ -5591,6 +5592,28 @@ var ensureTsNodeRegistered = async () => {
5591
5592
  });
5592
5593
  tsNodeRegistered = true;
5593
5594
  };
5595
+ var ensureTsconfigPathsRegistered = async (cwd = getTradejsProjectCwd()) => {
5596
+ const projectRoot = getTradejsProjectCwd(cwd);
5597
+ if (tsconfigPathsRegisteredByCwd.has(projectRoot)) {
5598
+ return;
5599
+ }
5600
+ const tsconfigPathsModule = await import("tsconfig-paths");
5601
+ const loadConfig = tsconfigPathsModule.loadConfig;
5602
+ const register = tsconfigPathsModule.register;
5603
+ if (typeof loadConfig !== "function" || typeof register !== "function") {
5604
+ return;
5605
+ }
5606
+ const loadedConfig = loadConfig(projectRoot);
5607
+ if (loadedConfig.resultType !== "success") {
5608
+ return;
5609
+ }
5610
+ register({
5611
+ baseUrl: loadedConfig.absoluteBaseUrl,
5612
+ paths: loadedConfig.paths,
5613
+ addMatchAll: false
5614
+ });
5615
+ tsconfigPathsRegisteredByCwd.add(projectRoot);
5616
+ };
5594
5617
  var toImportSpecifier = (moduleName) => {
5595
5618
  if (moduleName.startsWith("file://")) {
5596
5619
  return moduleName;
@@ -5618,6 +5641,7 @@ var importConfigFile = async (configFilePath) => {
5618
5641
  if (ext === ".ts" || ext === ".mts") {
5619
5642
  const requireFn = getRequireFn(import_path.default.dirname(configFilePath));
5620
5643
  await ensureTsNodeRegistered();
5644
+ await ensureTsconfigPathsRegistered(import_path.default.dirname(configFilePath));
5621
5645
  return requireFn(configFilePath);
5622
5646
  }
5623
5647
  return import(
@@ -5625,7 +5649,7 @@ var importConfigFile = async (configFilePath) => {
5625
5649
  configFileUrl
5626
5650
  );
5627
5651
  };
5628
- var importTradejsModule = async (moduleName) => {
5652
+ var importTradejsModule = async (moduleName, cwd = getTradejsProjectCwd()) => {
5629
5653
  const normalized = String(moduleName ?? "").trim();
5630
5654
  if (!normalized) {
5631
5655
  return {};
@@ -5639,13 +5663,15 @@ var importTradejsModule = async (moduleName) => {
5639
5663
  }
5640
5664
  }
5641
5665
  const requireFn = getRequireFn(
5642
- import_path.default.isAbsolute(modulePath) ? import_path.default.dirname(modulePath) : getTradejsProjectCwd()
5666
+ import_path.default.isAbsolute(modulePath) ? import_path.default.dirname(modulePath) : cwd
5643
5667
  );
5644
5668
  if (isTsModulePath(modulePath)) {
5645
5669
  await ensureTsNodeRegistered();
5670
+ await ensureTsconfigPathsRegistered(cwd);
5646
5671
  return requireFn(modulePath);
5647
5672
  }
5648
5673
  if (isBareModuleSpecifier(normalized)) {
5674
+ await ensureTsconfigPathsRegistered(cwd);
5649
5675
  return requireFn(normalized);
5650
5676
  }
5651
5677
  try {
@@ -5656,6 +5682,7 @@ var importTradejsModule = async (moduleName) => {
5656
5682
  } catch (error) {
5657
5683
  if (isTsModulePath(modulePath)) {
5658
5684
  await ensureTsNodeRegistered();
5685
+ await ensureTsconfigPathsRegistered(cwd);
5659
5686
  return requireFn(modulePath);
5660
5687
  }
5661
5688
  throw error;
@@ -5733,14 +5760,29 @@ var loadTradejsConfig = async (cwd = getTradejsProjectCwd()) => {
5733
5760
  };
5734
5761
 
5735
5762
  // src/strategy/manifests.ts
5736
- var strategyCreators = /* @__PURE__ */ new Map();
5737
- var strategyManifestsMap = /* @__PURE__ */ new Map();
5738
- var pluginsLoadPromise = null;
5763
+ var createStrategyRegistryState = () => ({
5764
+ strategyCreators: /* @__PURE__ */ new Map(),
5765
+ strategyManifestsMap: /* @__PURE__ */ new Map(),
5766
+ pluginsLoadPromise: null
5767
+ });
5768
+ var registryStateByProjectRoot = /* @__PURE__ */ new Map();
5769
+ var getStrategyRegistryState = (cwd = getTradejsProjectCwd()) => {
5770
+ const projectRoot = getTradejsProjectCwd(cwd);
5771
+ let state = registryStateByProjectRoot.get(projectRoot);
5772
+ if (!state) {
5773
+ state = createStrategyRegistryState();
5774
+ registryStateByProjectRoot.set(projectRoot, state);
5775
+ }
5776
+ return {
5777
+ projectRoot,
5778
+ state
5779
+ };
5780
+ };
5739
5781
  var toUniqueModules = (modules = []) => [
5740
5782
  ...new Set(modules.map((moduleName) => moduleName.trim()).filter(Boolean))
5741
5783
  ];
5742
- var getConfiguredPluginModuleNames = async () => {
5743
- const config = await loadTradejsConfig();
5784
+ var getConfiguredPluginModuleNames = async (cwd = getTradejsProjectCwd()) => {
5785
+ const config = await loadTradejsConfig(cwd);
5744
5786
  return {
5745
5787
  strategyModules: toUniqueModules(config.strategies),
5746
5788
  indicatorModules: toUniqueModules(config.indicators)
@@ -5774,14 +5816,14 @@ var extractIndicatorPluginDefinition = (moduleExport) => {
5774
5816
  );
5775
5817
  return indicatorEntries ? { indicatorEntries } : null;
5776
5818
  };
5777
- var registerEntries = (entries, source) => {
5819
+ var registerEntries = (entries, source, state) => {
5778
5820
  for (const entry of entries) {
5779
5821
  const strategyName = entry.manifest?.name;
5780
5822
  if (!strategyName) {
5781
5823
  import_logger2.logger.warn("Skip strategy entry without name from %s", source);
5782
5824
  continue;
5783
5825
  }
5784
- if (strategyCreators.has(strategyName)) {
5826
+ if (state.strategyCreators.has(strategyName)) {
5785
5827
  import_logger2.logger.warn(
5786
5828
  'Skip duplicate strategy "%s" from %s: already registered',
5787
5829
  strategyName,
@@ -5789,83 +5831,102 @@ var registerEntries = (entries, source) => {
5789
5831
  );
5790
5832
  continue;
5791
5833
  }
5792
- strategyCreators.set(strategyName, entry.creator);
5793
- strategyManifestsMap.set(strategyName, entry.manifest);
5834
+ state.strategyCreators.set(strategyName, entry.creator);
5835
+ state.strategyManifestsMap.set(strategyName, entry.manifest);
5794
5836
  }
5795
5837
  };
5796
- var importStrategyPluginModule = async (moduleName) => {
5838
+ var importStrategyPluginModule = async (moduleName, cwd = getTradejsProjectCwd()) => {
5797
5839
  if (typeof importTradejsModule === "function") {
5798
- return importTradejsModule(moduleName);
5840
+ return importTradejsModule(moduleName, cwd);
5799
5841
  }
5800
5842
  return import(
5801
5843
  /* webpackIgnore: true */
5802
5844
  moduleName
5803
5845
  );
5804
5846
  };
5805
- var ensureStrategyPluginsLoaded = async () => {
5806
- if (pluginsLoadPromise) {
5807
- return pluginsLoadPromise;
5808
- }
5809
- pluginsLoadPromise = (async () => {
5810
- const { strategyModules, indicatorModules } = await getConfiguredPluginModuleNames();
5811
- const strategySet = new Set(strategyModules);
5812
- const indicatorSet = new Set(indicatorModules);
5813
- const pluginModuleNames = [
5814
- .../* @__PURE__ */ new Set([...strategyModules, ...indicatorModules])
5815
- ];
5816
- if (!pluginModuleNames.length) return;
5817
- for (const moduleName of pluginModuleNames) {
5818
- try {
5819
- const resolvedModuleName = resolvePluginModuleSpecifier(moduleName);
5820
- const moduleExport = await importStrategyPluginModule(resolvedModuleName);
5821
- if (strategySet.has(moduleName)) {
5822
- const pluginDefinition = extractStrategyPluginDefinition(moduleExport);
5823
- if (!pluginDefinition) {
5824
- import_logger2.logger.warn(
5825
- 'Skip strategy plugin "%s": export { strategyEntries } is missing',
5826
- moduleName
5827
- );
5828
- } else {
5829
- registerEntries(pluginDefinition.strategyEntries, moduleName);
5847
+ var ensureStrategyPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
5848
+ const { projectRoot, state } = getStrategyRegistryState(cwd);
5849
+ if (!state.pluginsLoadPromise) {
5850
+ (0, import_indicators.resetIndicatorRegistryCache)(projectRoot);
5851
+ state.pluginsLoadPromise = (async () => {
5852
+ const { strategyModules, indicatorModules } = await getConfiguredPluginModuleNames(projectRoot);
5853
+ const strategySet = new Set(strategyModules);
5854
+ const indicatorSet = new Set(indicatorModules);
5855
+ const pluginModuleNames = [
5856
+ .../* @__PURE__ */ new Set([...strategyModules, ...indicatorModules])
5857
+ ];
5858
+ if (!pluginModuleNames.length) {
5859
+ return;
5860
+ }
5861
+ for (const moduleName of pluginModuleNames) {
5862
+ try {
5863
+ const resolvedModuleName = resolvePluginModuleSpecifier(
5864
+ moduleName,
5865
+ projectRoot
5866
+ );
5867
+ const moduleExport = await importStrategyPluginModule(
5868
+ resolvedModuleName,
5869
+ projectRoot
5870
+ );
5871
+ if (strategySet.has(moduleName)) {
5872
+ const pluginDefinition = extractStrategyPluginDefinition(moduleExport);
5873
+ if (!pluginDefinition) {
5874
+ import_logger2.logger.warn(
5875
+ 'Skip strategy plugin "%s": export { strategyEntries } is missing',
5876
+ moduleName
5877
+ );
5878
+ } else {
5879
+ registerEntries(
5880
+ pluginDefinition.strategyEntries,
5881
+ moduleName,
5882
+ state
5883
+ );
5884
+ }
5830
5885
  }
5831
- }
5832
- if (indicatorSet.has(moduleName)) {
5833
- const indicatorPluginDefinition = extractIndicatorPluginDefinition(moduleExport);
5834
- if (!indicatorPluginDefinition) {
5886
+ if (indicatorSet.has(moduleName)) {
5887
+ const indicatorPluginDefinition = extractIndicatorPluginDefinition(moduleExport);
5888
+ if (!indicatorPluginDefinition) {
5889
+ import_logger2.logger.warn(
5890
+ 'Skip indicator plugin "%s": export { indicatorEntries } is missing',
5891
+ moduleName
5892
+ );
5893
+ } else {
5894
+ (0, import_indicators.registerIndicatorEntries)(
5895
+ indicatorPluginDefinition.indicatorEntries,
5896
+ moduleName,
5897
+ projectRoot
5898
+ );
5899
+ }
5900
+ }
5901
+ if (!strategySet.has(moduleName) && !indicatorSet.has(moduleName)) {
5835
5902
  import_logger2.logger.warn(
5836
- 'Skip indicator plugin "%s": export { indicatorEntries } is missing',
5837
- moduleName
5838
- );
5839
- } else {
5840
- (0, import_indicators.registerIndicatorEntries)(
5841
- indicatorPluginDefinition.indicatorEntries,
5903
+ 'Skip plugin "%s": no strategy/indicator sections requested in config',
5842
5904
  moduleName
5843
5905
  );
5844
5906
  }
5845
- }
5846
- if (!strategySet.has(moduleName) && !indicatorSet.has(moduleName)) {
5907
+ } catch (error) {
5847
5908
  import_logger2.logger.warn(
5848
- 'Skip plugin "%s": no strategy/indicator sections requested in config',
5849
- moduleName
5909
+ 'Failed to load plugin "%s": %s',
5910
+ moduleName,
5911
+ String(error)
5850
5912
  );
5851
5913
  }
5852
- } catch (error) {
5853
- import_logger2.logger.warn(
5854
- 'Failed to load plugin "%s": %s',
5855
- moduleName,
5856
- String(error)
5857
- );
5858
5914
  }
5859
- }
5860
- })();
5861
- return pluginsLoadPromise;
5915
+ })();
5916
+ }
5917
+ await state.pluginsLoadPromise;
5862
5918
  };
5863
- var getStrategyCreator = async (name) => {
5864
- await ensureStrategyPluginsLoaded();
5865
- return strategyCreators.get(name);
5919
+ var getStrategyCreator = async (name, cwd = getTradejsProjectCwd()) => {
5920
+ await ensureStrategyPluginsLoaded(cwd);
5921
+ const { state } = getStrategyRegistryState(cwd);
5922
+ return state.strategyCreators.get(name);
5866
5923
  };
5867
- var getStrategyManifest = (name) => {
5868
- return name ? strategyManifestsMap.get(name) : void 0;
5924
+ var getStrategyManifest = (name, cwd = getTradejsProjectCwd()) => {
5925
+ if (!name) {
5926
+ return void 0;
5927
+ }
5928
+ const { state } = getStrategyRegistryState(cwd);
5929
+ return state.strategyManifestsMap.get(name);
5869
5930
  };
5870
5931
  var strategies = new Proxy(
5871
5932
  {},
@@ -5874,10 +5935,10 @@ var strategies = new Proxy(
5874
5935
  if (typeof property !== "string") {
5875
5936
  return void 0;
5876
5937
  }
5877
- return strategyCreators.get(property);
5938
+ return getStrategyRegistryState().state.strategyCreators.get(property);
5878
5939
  },
5879
5940
  ownKeys: () => {
5880
- return [...strategyCreators.keys()];
5941
+ return [...getStrategyRegistryState().state.strategyCreators.keys()];
5881
5942
  },
5882
5943
  getOwnPropertyDescriptor: () => ({
5883
5944
  enumerable: true,
@@ -5930,9 +5991,24 @@ var buildMlPayload = (payload) => {
5930
5991
 
5931
5992
  // src/connectorsRegistry.ts
5932
5993
  var import_logger3 = require("@tradejs/infra/logger");
5933
- var connectorCreators = /* @__PURE__ */ new Map();
5934
- var providerToConnectorName = /* @__PURE__ */ new Map();
5935
- var pluginsLoadPromise2 = null;
5994
+ var createConnectorRegistryState = () => ({
5995
+ connectorCreators: /* @__PURE__ */ new Map(),
5996
+ providerToConnectorName: /* @__PURE__ */ new Map(),
5997
+ pluginsLoadPromise: null
5998
+ });
5999
+ var registryStateByProjectRoot2 = /* @__PURE__ */ new Map();
6000
+ var getConnectorRegistryState = (cwd = getTradejsProjectCwd()) => {
6001
+ const projectRoot = getTradejsProjectCwd(cwd);
6002
+ let state = registryStateByProjectRoot2.get(projectRoot);
6003
+ if (!state) {
6004
+ state = createConnectorRegistryState();
6005
+ registryStateByProjectRoot2.set(projectRoot, state);
6006
+ }
6007
+ return {
6008
+ projectRoot,
6009
+ state
6010
+ };
6011
+ };
5936
6012
  var BUILTIN_CONNECTOR_NAMES = {
5937
6013
  ByBit: "ByBit",
5938
6014
  Binance: "Binance",
@@ -5943,7 +6019,7 @@ var normalizeProvider = (value) => String(value ?? "").trim().toLowerCase();
5943
6019
  var toUniqueModules2 = (modules = []) => [
5944
6020
  ...new Set(modules.map((moduleName) => moduleName.trim()).filter(Boolean))
5945
6021
  ];
5946
- var findConnectorNameInsensitive = (name) => {
6022
+ var findConnectorNameInsensitive = (name, connectorCreators) => {
5947
6023
  const normalized = name.trim().toLowerCase();
5948
6024
  if (!normalized) {
5949
6025
  return null;
@@ -5963,7 +6039,7 @@ var normalizeProviders = (providers, connectorName) => {
5963
6039
  }
5964
6040
  return [normalizeProvider(connectorName)];
5965
6041
  };
5966
- var registerProvider = (provider, connectorName, source) => {
6042
+ var registerProvider = (provider, connectorName, source, providerToConnectorName) => {
5967
6043
  const existing = providerToConnectorName.get(provider);
5968
6044
  if (existing && existing !== connectorName) {
5969
6045
  import_logger3.logger.warn(
@@ -5976,7 +6052,7 @@ var registerProvider = (provider, connectorName, source) => {
5976
6052
  }
5977
6053
  providerToConnectorName.set(provider, connectorName);
5978
6054
  };
5979
- var registerEntry = (entry, source) => {
6055
+ var registerEntry = (entry, source, state) => {
5980
6056
  const connectorName = String(entry?.name ?? "").trim();
5981
6057
  if (!connectorName) {
5982
6058
  import_logger3.logger.warn("Skip connector entry without name from %s", source);
@@ -5990,7 +6066,10 @@ var registerEntry = (entry, source) => {
5990
6066
  );
5991
6067
  return;
5992
6068
  }
5993
- const existingByName = findConnectorNameInsensitive(connectorName);
6069
+ const existingByName = findConnectorNameInsensitive(
6070
+ connectorName,
6071
+ state.connectorCreators
6072
+ );
5994
6073
  if (existingByName) {
5995
6074
  import_logger3.logger.warn(
5996
6075
  'Skip duplicate connector "%s" from %s: already registered as %s',
@@ -6000,15 +6079,20 @@ var registerEntry = (entry, source) => {
6000
6079
  );
6001
6080
  return;
6002
6081
  }
6003
- connectorCreators.set(connectorName, entry.creator);
6082
+ state.connectorCreators.set(connectorName, entry.creator);
6004
6083
  const providers = normalizeProviders(entry.providers, connectorName);
6005
6084
  for (const provider of providers) {
6006
- registerProvider(provider, connectorName, source);
6085
+ registerProvider(
6086
+ provider,
6087
+ connectorName,
6088
+ source,
6089
+ state.providerToConnectorName
6090
+ );
6007
6091
  }
6008
6092
  };
6009
- var registerEntries2 = (entries, source) => {
6093
+ var registerEntries2 = (entries, source, state) => {
6010
6094
  for (const entry of entries) {
6011
- registerEntry(entry, source);
6095
+ registerEntry(entry, source, state);
6012
6096
  }
6013
6097
  };
6014
6098
  var extractConnectorPluginDefinition = (moduleExport) => {
@@ -6029,64 +6113,71 @@ var extractConnectorPluginDefinition = (moduleExport) => {
6029
6113
  }
6030
6114
  return null;
6031
6115
  };
6032
- var importConnectorPluginModule = async (moduleName) => {
6116
+ var importConnectorPluginModule = async (moduleName, cwd = getTradejsProjectCwd()) => {
6033
6117
  if (typeof importTradejsModule === "function") {
6034
- return importTradejsModule(moduleName);
6118
+ return importTradejsModule(moduleName, cwd);
6035
6119
  }
6036
6120
  return import(
6037
6121
  /* webpackIgnore: true */
6038
6122
  moduleName
6039
6123
  );
6040
6124
  };
6041
- var ensureConnectorPluginsLoaded = async () => {
6042
- if (pluginsLoadPromise2) {
6043
- return pluginsLoadPromise2;
6044
- }
6045
- pluginsLoadPromise2 = (async () => {
6046
- const config = await loadTradejsConfig();
6047
- const connectorModules = toUniqueModules2(config.connectors);
6048
- if (!connectorModules.length) {
6049
- return;
6050
- }
6051
- for (const moduleName of connectorModules) {
6052
- try {
6053
- const resolvedModuleName = resolvePluginModuleSpecifier(moduleName);
6054
- const moduleExport = await importConnectorPluginModule(resolvedModuleName);
6055
- const pluginDefinition = extractConnectorPluginDefinition(moduleExport);
6056
- if (!pluginDefinition) {
6125
+ var ensureConnectorPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
6126
+ const { projectRoot, state } = getConnectorRegistryState(cwd);
6127
+ if (!state.pluginsLoadPromise) {
6128
+ state.pluginsLoadPromise = (async () => {
6129
+ const config = await loadTradejsConfig(projectRoot);
6130
+ const connectorModules = toUniqueModules2(config.connectors);
6131
+ if (!connectorModules.length) {
6132
+ return;
6133
+ }
6134
+ for (const moduleName of connectorModules) {
6135
+ try {
6136
+ const resolvedModuleName = resolvePluginModuleSpecifier(
6137
+ moduleName,
6138
+ projectRoot
6139
+ );
6140
+ const moduleExport = await importConnectorPluginModule(
6141
+ resolvedModuleName,
6142
+ projectRoot
6143
+ );
6144
+ const pluginDefinition = extractConnectorPluginDefinition(moduleExport);
6145
+ if (!pluginDefinition) {
6146
+ import_logger3.logger.warn(
6147
+ 'Skip connector plugin "%s": export { connectorEntries } is missing',
6148
+ moduleName
6149
+ );
6150
+ continue;
6151
+ }
6152
+ registerEntries2(pluginDefinition.connectorEntries, moduleName, state);
6153
+ } catch (error) {
6057
6154
  import_logger3.logger.warn(
6058
- 'Skip connector plugin "%s": export { connectorEntries } is missing',
6059
- moduleName
6155
+ 'Failed to load connector plugin "%s": %s',
6156
+ moduleName,
6157
+ String(error)
6060
6158
  );
6061
- continue;
6062
- }
6063
- registerEntries2(pluginDefinition.connectorEntries, moduleName);
6064
- } catch (error) {
6065
- import_logger3.logger.warn(
6066
- 'Failed to load connector plugin "%s": %s',
6067
- moduleName,
6068
- String(error)
6069
- );
6159
+ }
6070
6160
  }
6071
- }
6072
- })();
6073
- return pluginsLoadPromise2;
6161
+ })();
6162
+ }
6163
+ await state.pluginsLoadPromise;
6074
6164
  };
6075
- var getConnectorCreatorByName = async (connectorName) => {
6076
- await ensureConnectorPluginsLoaded();
6165
+ var getConnectorCreatorByName = async (connectorName, cwd = getTradejsProjectCwd()) => {
6166
+ await ensureConnectorPluginsLoaded(cwd);
6167
+ const { state } = getConnectorRegistryState(cwd);
6077
6168
  const raw = String(connectorName ?? "").trim();
6078
6169
  if (!raw) {
6079
6170
  return void 0;
6080
6171
  }
6081
- const direct = connectorCreators.get(raw);
6172
+ const direct = state.connectorCreators.get(raw);
6082
6173
  if (direct) {
6083
6174
  return direct;
6084
6175
  }
6085
- const existing = findConnectorNameInsensitive(raw);
6176
+ const existing = findConnectorNameInsensitive(raw, state.connectorCreators);
6086
6177
  if (!existing) {
6087
6178
  return void 0;
6088
6179
  }
6089
- return connectorCreators.get(existing);
6180
+ return state.connectorCreators.get(existing);
6090
6181
  };
6091
6182
  var DEFAULT_CONNECTOR_NAME = BUILTIN_CONNECTOR_NAMES.ByBit;
6092
6183
 
@@ -6291,10 +6382,25 @@ var createTestConnector = (connector, context) => {
6291
6382
 
6292
6383
  // src/testing.ts
6293
6384
  var preloadStart = (0, import_time.getTimestamp)(import_constants2.PRELOAD_DAYS);
6294
- var coinKlineCache = /* @__PURE__ */ new Map();
6295
- var btcKlineCache = /* @__PURE__ */ new Map();
6296
- var btcBinanceKlineCache = /* @__PURE__ */ new Map();
6297
- var btcCoinbaseKlineCache = /* @__PURE__ */ new Map();
6385
+ var createTestingKlineCacheState = () => ({
6386
+ coinKlineCache: /* @__PURE__ */ new Map(),
6387
+ btcKlineCache: /* @__PURE__ */ new Map(),
6388
+ btcBinanceKlineCache: /* @__PURE__ */ new Map(),
6389
+ btcCoinbaseKlineCache: /* @__PURE__ */ new Map()
6390
+ });
6391
+ var testingKlineCacheStateByProjectRoot = /* @__PURE__ */ new Map();
6392
+ var getTestingKlineCacheState = (cwd = getTradejsProjectCwd()) => {
6393
+ const projectRoot = getTradejsProjectCwd(cwd);
6394
+ let state = testingKlineCacheStateByProjectRoot.get(projectRoot);
6395
+ if (!state) {
6396
+ state = createTestingKlineCacheState();
6397
+ testingKlineCacheStateByProjectRoot.set(projectRoot, state);
6398
+ }
6399
+ return {
6400
+ projectRoot,
6401
+ state
6402
+ };
6403
+ };
6298
6404
  var getKlineCacheKey = (params) => {
6299
6405
  const { userName, connectorName, symbol, end, interval, cacheOnly } = params;
6300
6406
  return [
@@ -6307,11 +6413,15 @@ var getKlineCacheKey = (params) => {
6307
6413
  cacheOnly ? 1 : 0
6308
6414
  ].join(":");
6309
6415
  };
6310
- var resetTestingKlineCache = () => {
6311
- coinKlineCache.clear();
6312
- btcKlineCache.clear();
6313
- btcBinanceKlineCache.clear();
6314
- btcCoinbaseKlineCache.clear();
6416
+ var resetTestingKlineCache = (cwd) => {
6417
+ const normalizedCwd = String(cwd ?? "").trim();
6418
+ if (!normalizedCwd) {
6419
+ testingKlineCacheStateByProjectRoot.clear();
6420
+ return;
6421
+ }
6422
+ testingKlineCacheStateByProjectRoot.delete(
6423
+ getTradejsProjectCwd(normalizedCwd)
6424
+ );
6315
6425
  };
6316
6426
  var testing = async ({
6317
6427
  userName,
@@ -6329,22 +6439,28 @@ var testing = async ({
6329
6439
  if (!start) {
6330
6440
  throw new Error("no start");
6331
6441
  }
6332
- const connectorCreator = await getConnectorCreatorByName(connectorName);
6442
+ const { projectRoot, state } = getTestingKlineCacheState();
6443
+ const connectorCreator = await getConnectorCreatorByName(
6444
+ connectorName,
6445
+ projectRoot
6446
+ );
6333
6447
  if (!connectorCreator) {
6334
6448
  throw new Error(`Unknown connector: ${connectorName}`);
6335
6449
  }
6336
6450
  const connector = await connectorCreator({
6337
6451
  userName
6338
6452
  });
6339
- const strategyCreator = await getStrategyCreator(strategyName);
6453
+ const strategyCreator = await getStrategyCreator(strategyName, projectRoot);
6340
6454
  if (!strategyCreator) {
6341
6455
  throw new Error(`Unknown strategy: ${strategyName}`);
6342
6456
  }
6343
6457
  const binanceCreator = await getConnectorCreatorByName(
6344
- BUILTIN_CONNECTOR_NAMES.Binance
6458
+ BUILTIN_CONNECTOR_NAMES.Binance,
6459
+ projectRoot
6345
6460
  );
6346
6461
  const coinbaseCreator = await getConnectorCreatorByName(
6347
- BUILTIN_CONNECTOR_NAMES.Coinbase
6462
+ BUILTIN_CONNECTOR_NAMES.Coinbase,
6463
+ projectRoot
6348
6464
  );
6349
6465
  if (!binanceCreator || !coinbaseCreator) {
6350
6466
  import_logger4.logger.warn(
@@ -6370,8 +6486,8 @@ var testing = async ({
6370
6486
  interval,
6371
6487
  cacheOnly
6372
6488
  });
6373
- const cachedCoinData = coinKlineCache.get(coinCacheKey);
6374
- const cachedBtcData = btcKlineCache.get(btcCacheKey);
6489
+ const cachedCoinData = state.coinKlineCache.get(coinCacheKey);
6490
+ const cachedBtcData = state.btcKlineCache.get(btcCacheKey);
6375
6491
  const btcBinanceCacheKey = getKlineCacheKey({
6376
6492
  userName,
6377
6493
  connectorName: binanceCreator ? BUILTIN_CONNECTOR_NAMES.Binance : connectorName,
@@ -6388,8 +6504,8 @@ var testing = async ({
6388
6504
  interval,
6389
6505
  cacheOnly
6390
6506
  });
6391
- const cachedBtcBinanceData = btcBinanceKlineCache.get(btcBinanceCacheKey);
6392
- const cachedBtcCoinbaseData = btcCoinbaseKlineCache.get(btcCoinbaseCacheKey);
6507
+ const cachedBtcBinanceData = state.btcBinanceKlineCache.get(btcBinanceCacheKey);
6508
+ const cachedBtcCoinbaseData = state.btcCoinbaseKlineCache.get(btcCoinbaseCacheKey);
6393
6509
  const [data, btcData, btcBinanceData, btcCoinbaseData] = await Promise.all([
6394
6510
  cachedCoinData ? Promise.resolve(cachedCoinData) : connector.kline({
6395
6511
  symbol,
@@ -6443,16 +6559,16 @@ var testing = async ({
6443
6559
  })
6444
6560
  ]);
6445
6561
  if (!cachedCoinData) {
6446
- coinKlineCache.set(coinCacheKey, data);
6562
+ state.coinKlineCache.set(coinCacheKey, data);
6447
6563
  }
6448
6564
  if (!cachedBtcData) {
6449
- btcKlineCache.set(btcCacheKey, btcData);
6565
+ state.btcKlineCache.set(btcCacheKey, btcData);
6450
6566
  }
6451
6567
  if (!cachedBtcBinanceData) {
6452
- btcBinanceKlineCache.set(btcBinanceCacheKey, btcBinanceData);
6568
+ state.btcBinanceKlineCache.set(btcBinanceCacheKey, btcBinanceData);
6453
6569
  }
6454
6570
  if (!cachedBtcCoinbaseData) {
6455
- btcCoinbaseKlineCache.set(btcCoinbaseCacheKey, btcCoinbaseData);
6571
+ state.btcCoinbaseKlineCache.set(btcCoinbaseCacheKey, btcCoinbaseData);
6456
6572
  }
6457
6573
  const prevDataRaw = data.filter(
6458
6574
  (candle) => candle.timestamp >= preloadStart && candle.timestamp < start