@tradejs/node 1.0.2 → 1.0.3

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/dist/backtest.mjs CHANGED
@@ -1,17 +1,19 @@
1
1
  import {
2
2
  BUILTIN_CONNECTOR_NAMES,
3
3
  getConnectorCreatorByName
4
- } from "./chunk-E2QNOA5M.mjs";
4
+ } from "./chunk-MGFEID6K.mjs";
5
5
  import {
6
6
  buildMlPayload
7
- } from "./chunk-PXJJPAQT.mjs";
7
+ } from "./chunk-H4HXW3EZ.mjs";
8
8
  import {
9
9
  require_lodash
10
10
  } from "./chunk-GKDBAF3A.mjs";
11
11
  import {
12
12
  getStrategyCreator
13
- } from "./chunk-MHCXPD2B.mjs";
14
- import "./chunk-DE7ADBIR.mjs";
13
+ } from "./chunk-CK2PW4L5.mjs";
14
+ import {
15
+ getTradejsProjectCwd
16
+ } from "./chunk-3C76HVLA.mjs";
15
17
  import {
16
18
  __toESM
17
19
  } from "./chunk-6DZX6EAA.mjs";
@@ -231,10 +233,25 @@ var createTestConnector = (connector, context) => {
231
233
 
232
234
  // src/testing.ts
233
235
  var preloadStart = getTimestamp(PRELOAD_DAYS);
234
- var coinKlineCache = /* @__PURE__ */ new Map();
235
- var btcKlineCache = /* @__PURE__ */ new Map();
236
- var btcBinanceKlineCache = /* @__PURE__ */ new Map();
237
- var btcCoinbaseKlineCache = /* @__PURE__ */ new Map();
236
+ var createTestingKlineCacheState = () => ({
237
+ coinKlineCache: /* @__PURE__ */ new Map(),
238
+ btcKlineCache: /* @__PURE__ */ new Map(),
239
+ btcBinanceKlineCache: /* @__PURE__ */ new Map(),
240
+ btcCoinbaseKlineCache: /* @__PURE__ */ new Map()
241
+ });
242
+ var testingKlineCacheStateByProjectRoot = /* @__PURE__ */ new Map();
243
+ var getTestingKlineCacheState = (cwd = getTradejsProjectCwd()) => {
244
+ const projectRoot = getTradejsProjectCwd(cwd);
245
+ let state = testingKlineCacheStateByProjectRoot.get(projectRoot);
246
+ if (!state) {
247
+ state = createTestingKlineCacheState();
248
+ testingKlineCacheStateByProjectRoot.set(projectRoot, state);
249
+ }
250
+ return {
251
+ projectRoot,
252
+ state
253
+ };
254
+ };
238
255
  var getKlineCacheKey = (params) => {
239
256
  const { userName, connectorName, symbol, end, interval, cacheOnly } = params;
240
257
  return [
@@ -247,11 +264,15 @@ var getKlineCacheKey = (params) => {
247
264
  cacheOnly ? 1 : 0
248
265
  ].join(":");
249
266
  };
250
- var resetTestingKlineCache = () => {
251
- coinKlineCache.clear();
252
- btcKlineCache.clear();
253
- btcBinanceKlineCache.clear();
254
- btcCoinbaseKlineCache.clear();
267
+ var resetTestingKlineCache = (cwd) => {
268
+ const normalizedCwd = String(cwd ?? "").trim();
269
+ if (!normalizedCwd) {
270
+ testingKlineCacheStateByProjectRoot.clear();
271
+ return;
272
+ }
273
+ testingKlineCacheStateByProjectRoot.delete(
274
+ getTradejsProjectCwd(normalizedCwd)
275
+ );
255
276
  };
256
277
  var testing = async ({
257
278
  userName,
@@ -269,22 +290,28 @@ var testing = async ({
269
290
  if (!start) {
270
291
  throw new Error("no start");
271
292
  }
272
- const connectorCreator = await getConnectorCreatorByName(connectorName);
293
+ const { projectRoot, state } = getTestingKlineCacheState();
294
+ const connectorCreator = await getConnectorCreatorByName(
295
+ connectorName,
296
+ projectRoot
297
+ );
273
298
  if (!connectorCreator) {
274
299
  throw new Error(`Unknown connector: ${connectorName}`);
275
300
  }
276
301
  const connector = await connectorCreator({
277
302
  userName
278
303
  });
279
- const strategyCreator = await getStrategyCreator(strategyName);
304
+ const strategyCreator = await getStrategyCreator(strategyName, projectRoot);
280
305
  if (!strategyCreator) {
281
306
  throw new Error(`Unknown strategy: ${strategyName}`);
282
307
  }
283
308
  const binanceCreator = await getConnectorCreatorByName(
284
- BUILTIN_CONNECTOR_NAMES.Binance
309
+ BUILTIN_CONNECTOR_NAMES.Binance,
310
+ projectRoot
285
311
  );
286
312
  const coinbaseCreator = await getConnectorCreatorByName(
287
- BUILTIN_CONNECTOR_NAMES.Coinbase
313
+ BUILTIN_CONNECTOR_NAMES.Coinbase,
314
+ projectRoot
288
315
  );
289
316
  if (!binanceCreator || !coinbaseCreator) {
290
317
  logger.warn(
@@ -310,8 +337,8 @@ var testing = async ({
310
337
  interval,
311
338
  cacheOnly
312
339
  });
313
- const cachedCoinData = coinKlineCache.get(coinCacheKey);
314
- const cachedBtcData = btcKlineCache.get(btcCacheKey);
340
+ const cachedCoinData = state.coinKlineCache.get(coinCacheKey);
341
+ const cachedBtcData = state.btcKlineCache.get(btcCacheKey);
315
342
  const btcBinanceCacheKey = getKlineCacheKey({
316
343
  userName,
317
344
  connectorName: binanceCreator ? BUILTIN_CONNECTOR_NAMES.Binance : connectorName,
@@ -328,8 +355,8 @@ var testing = async ({
328
355
  interval,
329
356
  cacheOnly
330
357
  });
331
- const cachedBtcBinanceData = btcBinanceKlineCache.get(btcBinanceCacheKey);
332
- const cachedBtcCoinbaseData = btcCoinbaseKlineCache.get(btcCoinbaseCacheKey);
358
+ const cachedBtcBinanceData = state.btcBinanceKlineCache.get(btcBinanceCacheKey);
359
+ const cachedBtcCoinbaseData = state.btcCoinbaseKlineCache.get(btcCoinbaseCacheKey);
333
360
  const [data, btcData, btcBinanceData, btcCoinbaseData] = await Promise.all([
334
361
  cachedCoinData ? Promise.resolve(cachedCoinData) : connector.kline({
335
362
  symbol,
@@ -383,16 +410,16 @@ var testing = async ({
383
410
  })
384
411
  ]);
385
412
  if (!cachedCoinData) {
386
- coinKlineCache.set(coinCacheKey, data);
413
+ state.coinKlineCache.set(coinCacheKey, data);
387
414
  }
388
415
  if (!cachedBtcData) {
389
- btcKlineCache.set(btcCacheKey, btcData);
416
+ state.btcKlineCache.set(btcCacheKey, btcData);
390
417
  }
391
418
  if (!cachedBtcBinanceData) {
392
- btcBinanceKlineCache.set(btcBinanceCacheKey, btcBinanceData);
419
+ state.btcBinanceKlineCache.set(btcBinanceCacheKey, btcBinanceData);
393
420
  }
394
421
  if (!cachedBtcCoinbaseData) {
395
- btcCoinbaseKlineCache.set(btcCoinbaseCacheKey, btcCoinbaseData);
422
+ state.btcCoinbaseKlineCache.set(btcCoinbaseCacheKey, btcCoinbaseData);
396
423
  }
397
424
  const prevDataRaw = data.filter(
398
425
  (candle) => candle.timestamp >= preloadStart && candle.timestamp < start
@@ -198,6 +198,7 @@ var loadTradejsConfig = async (cwd = getTradejsProjectCwd()) => {
198
198
  };
199
199
 
200
200
  export {
201
+ getTradejsProjectCwd,
201
202
  importTradejsModule,
202
203
  resolvePluginModuleSpecifier,
203
204
  loadTradejsConfig
@@ -5,8 +5,6 @@ import {
5
5
  // src/pine.ts
6
6
  import fs from "fs";
7
7
  import path from "path";
8
-
9
- // src/pineShared.ts
10
8
  var getPinePlotSeries = (context, plotName) => {
11
9
  const name = String(plotName || "").trim();
12
10
  if (!name) return [];
@@ -29,8 +27,6 @@ var asPineBoolean = (value) => {
29
27
  if (typeof value === "number") return Number.isFinite(value) && value !== 0;
30
28
  return false;
31
29
  };
32
-
33
- // src/pine.ts
34
30
  var loadPinets = () => {
35
31
  const resolvedPath = __require.resolve("pinets");
36
32
  const cjsPath = resolvedPath.includes("pinets.min.browser") ? resolvedPath.replace(/pinets\.min\.browser(\.es)?\.js$/, "pinets.min.cjs") : resolvedPath;
@@ -0,0 +1,243 @@
1
+ import {
2
+ getTradejsProjectCwd,
3
+ importTradejsModule,
4
+ loadTradejsConfig,
5
+ resolvePluginModuleSpecifier
6
+ } from "./chunk-3C76HVLA.mjs";
7
+
8
+ // src/strategy/manifests.ts
9
+ import {
10
+ registerIndicatorEntries,
11
+ resetIndicatorRegistryCache
12
+ } from "@tradejs/core/indicators";
13
+ import { logger } from "@tradejs/infra/logger";
14
+ var createStrategyRegistryState = () => ({
15
+ strategyCreators: /* @__PURE__ */ new Map(),
16
+ strategyManifestsMap: /* @__PURE__ */ new Map(),
17
+ pluginsLoadPromise: null
18
+ });
19
+ var registryStateByProjectRoot = /* @__PURE__ */ new Map();
20
+ var getStrategyRegistryState = (cwd = getTradejsProjectCwd()) => {
21
+ const projectRoot = getTradejsProjectCwd(cwd);
22
+ let state = registryStateByProjectRoot.get(projectRoot);
23
+ if (!state) {
24
+ state = createStrategyRegistryState();
25
+ registryStateByProjectRoot.set(projectRoot, state);
26
+ }
27
+ return {
28
+ projectRoot,
29
+ state
30
+ };
31
+ };
32
+ var toUniqueModules = (modules = []) => [
33
+ ...new Set(modules.map((moduleName) => moduleName.trim()).filter(Boolean))
34
+ ];
35
+ var getConfiguredPluginModuleNames = async (cwd = getTradejsProjectCwd()) => {
36
+ const config = await loadTradejsConfig(cwd);
37
+ return {
38
+ strategyModules: toUniqueModules(config.strategies),
39
+ indicatorModules: toUniqueModules(config.indicators)
40
+ };
41
+ };
42
+ var extractModuleEntries = (moduleExport, key) => {
43
+ if (!moduleExport || typeof moduleExport !== "object") {
44
+ return null;
45
+ }
46
+ const candidate = moduleExport;
47
+ if (Array.isArray(candidate[key])) {
48
+ return candidate[key];
49
+ }
50
+ const defaultExport = candidate.default;
51
+ if (defaultExport && Array.isArray(defaultExport[key])) {
52
+ return defaultExport[key];
53
+ }
54
+ return null;
55
+ };
56
+ var extractStrategyPluginDefinition = (moduleExport) => {
57
+ const strategyEntries = extractModuleEntries(
58
+ moduleExport,
59
+ "strategyEntries"
60
+ );
61
+ return strategyEntries ? { strategyEntries } : null;
62
+ };
63
+ var extractIndicatorPluginDefinition = (moduleExport) => {
64
+ const indicatorEntries = extractModuleEntries(
65
+ moduleExport,
66
+ "indicatorEntries"
67
+ );
68
+ return indicatorEntries ? { indicatorEntries } : null;
69
+ };
70
+ var registerEntries = (entries, source, state) => {
71
+ for (const entry of entries) {
72
+ const strategyName = entry.manifest?.name;
73
+ if (!strategyName) {
74
+ logger.warn("Skip strategy entry without name from %s", source);
75
+ continue;
76
+ }
77
+ if (state.strategyCreators.has(strategyName)) {
78
+ logger.warn(
79
+ 'Skip duplicate strategy "%s" from %s: already registered',
80
+ strategyName,
81
+ source
82
+ );
83
+ continue;
84
+ }
85
+ state.strategyCreators.set(strategyName, entry.creator);
86
+ state.strategyManifestsMap.set(strategyName, entry.manifest);
87
+ }
88
+ };
89
+ var importStrategyPluginModule = async (moduleName) => {
90
+ if (typeof importTradejsModule === "function") {
91
+ return importTradejsModule(moduleName);
92
+ }
93
+ return import(
94
+ /* webpackIgnore: true */
95
+ moduleName
96
+ );
97
+ };
98
+ var ensureStrategyPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
99
+ const { projectRoot, state } = getStrategyRegistryState(cwd);
100
+ if (!state.pluginsLoadPromise) {
101
+ resetIndicatorRegistryCache(projectRoot);
102
+ state.pluginsLoadPromise = (async () => {
103
+ const { strategyModules, indicatorModules } = await getConfiguredPluginModuleNames(projectRoot);
104
+ const strategySet = new Set(strategyModules);
105
+ const indicatorSet = new Set(indicatorModules);
106
+ const pluginModuleNames = [
107
+ .../* @__PURE__ */ new Set([...strategyModules, ...indicatorModules])
108
+ ];
109
+ if (!pluginModuleNames.length) {
110
+ return;
111
+ }
112
+ for (const moduleName of pluginModuleNames) {
113
+ try {
114
+ const resolvedModuleName = resolvePluginModuleSpecifier(
115
+ moduleName,
116
+ projectRoot
117
+ );
118
+ const moduleExport = await importStrategyPluginModule(resolvedModuleName);
119
+ if (strategySet.has(moduleName)) {
120
+ const pluginDefinition = extractStrategyPluginDefinition(moduleExport);
121
+ if (!pluginDefinition) {
122
+ logger.warn(
123
+ 'Skip strategy plugin "%s": export { strategyEntries } is missing',
124
+ moduleName
125
+ );
126
+ } else {
127
+ registerEntries(
128
+ pluginDefinition.strategyEntries,
129
+ moduleName,
130
+ state
131
+ );
132
+ }
133
+ }
134
+ if (indicatorSet.has(moduleName)) {
135
+ const indicatorPluginDefinition = extractIndicatorPluginDefinition(moduleExport);
136
+ if (!indicatorPluginDefinition) {
137
+ logger.warn(
138
+ 'Skip indicator plugin "%s": export { indicatorEntries } is missing',
139
+ moduleName
140
+ );
141
+ } else {
142
+ registerIndicatorEntries(
143
+ indicatorPluginDefinition.indicatorEntries,
144
+ moduleName,
145
+ projectRoot
146
+ );
147
+ }
148
+ }
149
+ if (!strategySet.has(moduleName) && !indicatorSet.has(moduleName)) {
150
+ logger.warn(
151
+ 'Skip plugin "%s": no strategy/indicator sections requested in config',
152
+ moduleName
153
+ );
154
+ }
155
+ } catch (error) {
156
+ logger.warn(
157
+ 'Failed to load plugin "%s": %s',
158
+ moduleName,
159
+ String(error)
160
+ );
161
+ }
162
+ }
163
+ })();
164
+ }
165
+ await state.pluginsLoadPromise;
166
+ };
167
+ var ensureIndicatorPluginsLoaded = async (cwd = getTradejsProjectCwd()) => ensureStrategyPluginsLoaded(cwd);
168
+ var getStrategyCreator = async (name, cwd = getTradejsProjectCwd()) => {
169
+ await ensureStrategyPluginsLoaded(cwd);
170
+ const { state } = getStrategyRegistryState(cwd);
171
+ return state.strategyCreators.get(name);
172
+ };
173
+ var getAvailableStrategyNames = async (cwd = getTradejsProjectCwd()) => {
174
+ await ensureStrategyPluginsLoaded(cwd);
175
+ const { state } = getStrategyRegistryState(cwd);
176
+ return [...state.strategyCreators.keys()].sort((a, b) => a.localeCompare(b));
177
+ };
178
+ var getRegisteredStrategies = (cwd = getTradejsProjectCwd()) => {
179
+ const { state } = getStrategyRegistryState(cwd);
180
+ return Object.fromEntries(state.strategyCreators.entries());
181
+ };
182
+ var getRegisteredManifests = (cwd = getTradejsProjectCwd()) => {
183
+ const { state } = getStrategyRegistryState(cwd);
184
+ return [...state.strategyManifestsMap.values()];
185
+ };
186
+ var getStrategyManifest = (name, cwd = getTradejsProjectCwd()) => {
187
+ if (!name) {
188
+ return void 0;
189
+ }
190
+ const { state } = getStrategyRegistryState(cwd);
191
+ return state.strategyManifestsMap.get(name);
192
+ };
193
+ var isKnownStrategy = (name, cwd = getTradejsProjectCwd()) => {
194
+ const { state } = getStrategyRegistryState(cwd);
195
+ return state.strategyCreators.has(name);
196
+ };
197
+ var registerStrategyEntries = (entries, cwd = getTradejsProjectCwd()) => {
198
+ const { state } = getStrategyRegistryState(cwd);
199
+ registerEntries(entries, "runtime", state);
200
+ };
201
+ var resetStrategyRegistryCache = (cwd) => {
202
+ const normalizedCwd = String(cwd ?? "").trim();
203
+ if (!normalizedCwd) {
204
+ registryStateByProjectRoot.clear();
205
+ resetIndicatorRegistryCache();
206
+ return;
207
+ }
208
+ const projectRoot = getTradejsProjectCwd(normalizedCwd);
209
+ registryStateByProjectRoot.delete(projectRoot);
210
+ resetIndicatorRegistryCache(projectRoot);
211
+ };
212
+ var strategies = new Proxy(
213
+ {},
214
+ {
215
+ get: (_target, property) => {
216
+ if (typeof property !== "string") {
217
+ return void 0;
218
+ }
219
+ return getStrategyRegistryState().state.strategyCreators.get(property);
220
+ },
221
+ ownKeys: () => {
222
+ return [...getStrategyRegistryState().state.strategyCreators.keys()];
223
+ },
224
+ getOwnPropertyDescriptor: () => ({
225
+ enumerable: true,
226
+ configurable: true
227
+ })
228
+ }
229
+ );
230
+
231
+ export {
232
+ ensureStrategyPluginsLoaded,
233
+ ensureIndicatorPluginsLoaded,
234
+ getStrategyCreator,
235
+ getAvailableStrategyNames,
236
+ getRegisteredStrategies,
237
+ getRegisteredManifests,
238
+ getStrategyManifest,
239
+ isKnownStrategy,
240
+ registerStrategyEntries,
241
+ resetStrategyRegistryCache,
242
+ strategies
243
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getStrategyManifest
3
- } from "./chunk-MHCXPD2B.mjs";
3
+ } from "./chunk-CK2PW4L5.mjs";
4
4
 
5
5
  // src/strategyAdapters/ml.ts
6
6
  var defaultMlAdapter = {
@@ -0,0 +1,268 @@
1
+ import {
2
+ getTradejsProjectCwd,
3
+ importTradejsModule,
4
+ loadTradejsConfig,
5
+ resolvePluginModuleSpecifier
6
+ } from "./chunk-3C76HVLA.mjs";
7
+
8
+ // src/connectorsRegistry.ts
9
+ import { logger } from "@tradejs/infra/logger";
10
+ var createConnectorRegistryState = () => ({
11
+ connectorCreators: /* @__PURE__ */ new Map(),
12
+ providerToConnectorName: /* @__PURE__ */ new Map(),
13
+ pluginsLoadPromise: null
14
+ });
15
+ var registryStateByProjectRoot = /* @__PURE__ */ new Map();
16
+ var getConnectorRegistryState = (cwd = getTradejsProjectCwd()) => {
17
+ const projectRoot = getTradejsProjectCwd(cwd);
18
+ let state = registryStateByProjectRoot.get(projectRoot);
19
+ if (!state) {
20
+ state = createConnectorRegistryState();
21
+ registryStateByProjectRoot.set(projectRoot, state);
22
+ }
23
+ return {
24
+ projectRoot,
25
+ state
26
+ };
27
+ };
28
+ var BUILTIN_CONNECTOR_NAMES = {
29
+ ByBit: "ByBit",
30
+ Binance: "Binance",
31
+ Coinbase: "Coinbase",
32
+ Test: "Test"
33
+ };
34
+ var normalizeProvider = (value) => String(value ?? "").trim().toLowerCase();
35
+ var toUniqueModules = (modules = []) => [
36
+ ...new Set(modules.map((moduleName) => moduleName.trim()).filter(Boolean))
37
+ ];
38
+ var findConnectorNameInsensitive = (name, connectorCreators) => {
39
+ const normalized = name.trim().toLowerCase();
40
+ if (!normalized) {
41
+ return null;
42
+ }
43
+ for (const existingName of connectorCreators.keys()) {
44
+ if (existingName.toLowerCase() === normalized) {
45
+ return existingName;
46
+ }
47
+ }
48
+ return null;
49
+ };
50
+ var normalizeProviders = (providers, connectorName) => {
51
+ const list = Array.isArray(providers) ? providers.map((item) => normalizeProvider(item)).filter(Boolean) : [];
52
+ const deduped = [...new Set(list)];
53
+ if (deduped.length) {
54
+ return deduped;
55
+ }
56
+ return [normalizeProvider(connectorName)];
57
+ };
58
+ var registerProvider = (provider, connectorName, source, providerToConnectorName) => {
59
+ const existing = providerToConnectorName.get(provider);
60
+ if (existing && existing !== connectorName) {
61
+ logger.warn(
62
+ 'Skip duplicate connector provider "%s" from %s: already mapped to %s',
63
+ provider,
64
+ source,
65
+ existing
66
+ );
67
+ return;
68
+ }
69
+ providerToConnectorName.set(provider, connectorName);
70
+ };
71
+ var registerEntry = (entry, source, state) => {
72
+ const connectorName = String(entry?.name ?? "").trim();
73
+ if (!connectorName) {
74
+ logger.warn("Skip connector entry without name from %s", source);
75
+ return;
76
+ }
77
+ if (typeof entry.creator !== "function") {
78
+ logger.warn(
79
+ 'Skip connector entry "%s" from %s: creator must be a function',
80
+ connectorName,
81
+ source
82
+ );
83
+ return;
84
+ }
85
+ const existingByName = findConnectorNameInsensitive(
86
+ connectorName,
87
+ state.connectorCreators
88
+ );
89
+ if (existingByName) {
90
+ logger.warn(
91
+ 'Skip duplicate connector "%s" from %s: already registered as %s',
92
+ connectorName,
93
+ source,
94
+ existingByName
95
+ );
96
+ return;
97
+ }
98
+ state.connectorCreators.set(connectorName, entry.creator);
99
+ const providers = normalizeProviders(entry.providers, connectorName);
100
+ for (const provider of providers) {
101
+ registerProvider(
102
+ provider,
103
+ connectorName,
104
+ source,
105
+ state.providerToConnectorName
106
+ );
107
+ }
108
+ };
109
+ var registerEntries = (entries, source, state) => {
110
+ for (const entry of entries) {
111
+ registerEntry(entry, source, state);
112
+ }
113
+ };
114
+ var extractConnectorPluginDefinition = (moduleExport) => {
115
+ if (!moduleExport || typeof moduleExport !== "object") {
116
+ return null;
117
+ }
118
+ const candidate = moduleExport;
119
+ if (Array.isArray(candidate.connectorEntries)) {
120
+ return {
121
+ connectorEntries: candidate.connectorEntries
122
+ };
123
+ }
124
+ const defaultExport = candidate.default;
125
+ if (defaultExport && Array.isArray(defaultExport.connectorEntries)) {
126
+ return {
127
+ connectorEntries: defaultExport.connectorEntries
128
+ };
129
+ }
130
+ return null;
131
+ };
132
+ var importConnectorPluginModule = async (moduleName) => {
133
+ if (typeof importTradejsModule === "function") {
134
+ return importTradejsModule(moduleName);
135
+ }
136
+ return import(
137
+ /* webpackIgnore: true */
138
+ moduleName
139
+ );
140
+ };
141
+ var ensureConnectorPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
142
+ const { projectRoot, state } = getConnectorRegistryState(cwd);
143
+ if (!state.pluginsLoadPromise) {
144
+ state.pluginsLoadPromise = (async () => {
145
+ const config = await loadTradejsConfig(projectRoot);
146
+ const connectorModules = toUniqueModules(config.connectors);
147
+ if (!connectorModules.length) {
148
+ return;
149
+ }
150
+ for (const moduleName of connectorModules) {
151
+ try {
152
+ const resolvedModuleName = resolvePluginModuleSpecifier(
153
+ moduleName,
154
+ projectRoot
155
+ );
156
+ const moduleExport = await importConnectorPluginModule(resolvedModuleName);
157
+ const pluginDefinition = extractConnectorPluginDefinition(moduleExport);
158
+ if (!pluginDefinition) {
159
+ logger.warn(
160
+ 'Skip connector plugin "%s": export { connectorEntries } is missing',
161
+ moduleName
162
+ );
163
+ continue;
164
+ }
165
+ registerEntries(pluginDefinition.connectorEntries, moduleName, state);
166
+ } catch (error) {
167
+ logger.warn(
168
+ 'Failed to load connector plugin "%s": %s',
169
+ moduleName,
170
+ String(error)
171
+ );
172
+ }
173
+ }
174
+ })();
175
+ }
176
+ await state.pluginsLoadPromise;
177
+ };
178
+ var getConnectorCreatorByName = async (connectorName, cwd = getTradejsProjectCwd()) => {
179
+ await ensureConnectorPluginsLoaded(cwd);
180
+ const { state } = getConnectorRegistryState(cwd);
181
+ const raw = String(connectorName ?? "").trim();
182
+ if (!raw) {
183
+ return void 0;
184
+ }
185
+ const direct = state.connectorCreators.get(raw);
186
+ if (direct) {
187
+ return direct;
188
+ }
189
+ const existing = findConnectorNameInsensitive(raw, state.connectorCreators);
190
+ if (!existing) {
191
+ return void 0;
192
+ }
193
+ return state.connectorCreators.get(existing);
194
+ };
195
+ var getConnectorNameByProvider = async (provider, cwd = getTradejsProjectCwd()) => {
196
+ await ensureConnectorPluginsLoaded(cwd);
197
+ const { state } = getConnectorRegistryState(cwd);
198
+ const normalized = normalizeProvider(provider);
199
+ if (!normalized) {
200
+ return void 0;
201
+ }
202
+ return state.providerToConnectorName.get(normalized);
203
+ };
204
+ var getConnectorCreatorByProvider = async (provider, cwd = getTradejsProjectCwd()) => {
205
+ await ensureConnectorPluginsLoaded(cwd);
206
+ const { state } = getConnectorRegistryState(cwd);
207
+ const normalized = normalizeProvider(provider);
208
+ if (!normalized) {
209
+ return void 0;
210
+ }
211
+ const connectorName = state.providerToConnectorName.get(normalized);
212
+ if (!connectorName) {
213
+ return void 0;
214
+ }
215
+ return state.connectorCreators.get(connectorName);
216
+ };
217
+ var resolveConnectorName = async (providerOrName, cwd = getTradejsProjectCwd()) => {
218
+ await ensureConnectorPluginsLoaded(cwd);
219
+ const { state } = getConnectorRegistryState(cwd);
220
+ const raw = String(providerOrName ?? "").trim();
221
+ if (!raw) {
222
+ return void 0;
223
+ }
224
+ const byProvider = state.providerToConnectorName.get(normalizeProvider(raw));
225
+ if (byProvider) {
226
+ return byProvider;
227
+ }
228
+ return state.connectorCreators.get(raw) && raw ? raw : findConnectorNameInsensitive(raw, state.connectorCreators) ?? void 0;
229
+ };
230
+ var getAvailableConnectorNames = async (cwd = getTradejsProjectCwd()) => {
231
+ await ensureConnectorPluginsLoaded(cwd);
232
+ const { state } = getConnectorRegistryState(cwd);
233
+ return [...state.connectorCreators.keys()].sort((a, b) => a.localeCompare(b));
234
+ };
235
+ var getAvailableConnectorProviders = async (cwd = getTradejsProjectCwd()) => {
236
+ await ensureConnectorPluginsLoaded(cwd);
237
+ const { state } = getConnectorRegistryState(cwd);
238
+ return [...state.providerToConnectorName.keys()].sort(
239
+ (a, b) => a.localeCompare(b)
240
+ );
241
+ };
242
+ var registerConnectorEntries = (entries, cwd = getTradejsProjectCwd()) => {
243
+ const { state } = getConnectorRegistryState(cwd);
244
+ registerEntries(entries, "runtime", state);
245
+ };
246
+ var resetConnectorRegistryCache = (cwd) => {
247
+ const normalizedCwd = String(cwd ?? "").trim();
248
+ if (!normalizedCwd) {
249
+ registryStateByProjectRoot.clear();
250
+ return;
251
+ }
252
+ registryStateByProjectRoot.delete(getTradejsProjectCwd(normalizedCwd));
253
+ };
254
+ var DEFAULT_CONNECTOR_NAME = BUILTIN_CONNECTOR_NAMES.ByBit;
255
+
256
+ export {
257
+ BUILTIN_CONNECTOR_NAMES,
258
+ ensureConnectorPluginsLoaded,
259
+ getConnectorCreatorByName,
260
+ getConnectorNameByProvider,
261
+ getConnectorCreatorByProvider,
262
+ resolveConnectorName,
263
+ getAvailableConnectorNames,
264
+ getAvailableConnectorProviders,
265
+ registerConnectorEntries,
266
+ resetConnectorRegistryCache,
267
+ DEFAULT_CONNECTOR_NAME
268
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getStrategyManifest
3
- } from "./chunk-MHCXPD2B.mjs";
3
+ } from "./chunk-CK2PW4L5.mjs";
4
4
 
5
5
  // src/ai.ts
6
6
  import { setData, redisKeys } from "@tradejs/infra/redis";