@tradejs/node 3.1.27 → 3.1.28-beta.252
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/ai.js +1 -0
- package/dist/ai.mjs +1 -1
- package/dist/backtest.d.mts +3 -1
- package/dist/backtest.d.ts +3 -1
- package/dist/backtest.js +287 -39
- package/dist/backtest.mjs +30 -16
- package/dist/{chunk-NQO2MFP6.mjs → chunk-K2YQ3MQC.mjs} +58 -10
- package/dist/{chunk-FB5NUEOQ.mjs → chunk-OFVUEYUR.mjs} +4 -1
- package/dist/{chunk-IKRSNRP6.mjs → chunk-UITD6LG6.mjs} +83 -4
- package/dist/{chunk-XHNJ757K.mjs → chunk-VQSGH7YA.mjs} +341 -22
- package/dist/cli.js +2 -1
- package/dist/cli.mjs +1 -1
- package/dist/{registry-DHTLjQcr.d.mts → registry-3TsO1Ff1.d.mts} +2 -2
- package/dist/{registry-DHTLjQcr.d.ts → registry-3TsO1Ff1.d.ts} +2 -2
- package/dist/registry.d.mts +1 -1
- package/dist/registry.d.ts +1 -1
- package/dist/registry.js +260 -23
- package/dist/registry.mjs +2 -2
- package/dist/runtimeDashboard.js +378 -37
- package/dist/runtimeDashboard.mjs +54 -8
- package/dist/runtimeStrategies.d.mts +4 -1
- package/dist/runtimeStrategies.d.ts +4 -1
- package/dist/runtimeStrategies.js +327 -34
- package/dist/runtimeStrategies.mjs +3 -3
- package/dist/runtimeTrades.d.mts +2 -1
- package/dist/runtimeTrades.d.ts +2 -1
- package/dist/runtimeTrades.js +4 -1
- package/dist/runtimeTrades.mjs +1 -1
- package/dist/strategies.d.mts +14 -2
- package/dist/strategies.d.ts +14 -2
- package/dist/strategies.js +417 -24
- package/dist/strategies.mjs +4 -2
- package/package.json +5 -5
package/dist/backtest.mjs
CHANGED
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
buildMlPayload,
|
|
7
7
|
enrichSignalWithMarketContextStages
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-VQSGH7YA.mjs";
|
|
9
9
|
import {
|
|
10
10
|
buildAiPayload,
|
|
11
11
|
getStrategyCreator
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-UITD6LG6.mjs";
|
|
13
13
|
import {
|
|
14
14
|
getTradejsProjectCwd
|
|
15
15
|
} from "./chunk-LZDXRXIU.mjs";
|
|
@@ -159,6 +159,10 @@ import {
|
|
|
159
159
|
BACKTEST_SPREAD_SLIPPAGE_MULTIPLIER,
|
|
160
160
|
FEE_PERCENT
|
|
161
161
|
} from "@tradejs/core/constants";
|
|
162
|
+
import {
|
|
163
|
+
assertStrategyExecutionIsolation,
|
|
164
|
+
parseBacktestExecutionCosts
|
|
165
|
+
} from "@tradejs/core/backtest";
|
|
162
166
|
var finiteOr = (value, fallback) => {
|
|
163
167
|
const parsed = Number(value);
|
|
164
168
|
return Number.isFinite(parsed) ? parsed : fallback;
|
|
@@ -195,20 +199,27 @@ var loadFundingRates = (connector, symbol, startTime, endTime) => {
|
|
|
195
199
|
};
|
|
196
200
|
var resolveExecutionCosts = async (params) => {
|
|
197
201
|
const { connector, symbol, config, startTime, endTime, instrument } = params;
|
|
198
|
-
|
|
199
|
-
const
|
|
202
|
+
assertStrategyExecutionIsolation(config);
|
|
203
|
+
const costs = params.executionCosts == null ? void 0 : parseBacktestExecutionCosts(params.executionCosts);
|
|
204
|
+
const cacheOnly = params.cacheOnly === true;
|
|
205
|
+
const hasConfiguredFees = costs != null;
|
|
200
206
|
const exchangeFees = !cacheOnly && !hasConfiguredFees && connector.getTradingFeeRate ? await loadTradingFee(connector, symbol).catch(() => null) : null;
|
|
201
|
-
const makerRate = hasConfiguredFees ?
|
|
202
|
-
const takerRate = hasConfiguredFees ?
|
|
203
|
-
const fundingEnabled =
|
|
207
|
+
const makerRate = hasConfiguredFees ? costs.fees.makerRate : exchangeFees?.makerRate ?? FEE_PERCENT;
|
|
208
|
+
const takerRate = hasConfiguredFees ? costs.fees.takerRate : exchangeFees?.takerRate ?? FEE_PERCENT;
|
|
209
|
+
const fundingEnabled = costs?.funding.enabled !== false && !cacheOnly && typeof connector.getFundingRateHistory === "function";
|
|
204
210
|
const fundingRates = fundingEnabled ? await loadFundingRates(connector, symbol, startTime, endTime) : [];
|
|
205
211
|
const requestedLeverage = Math.max(1, finiteOr(config.LEVERAGE, 10));
|
|
206
212
|
const venueMaxLeverage = Number(instrument?.venueMetadata?.maxLeverage);
|
|
207
213
|
const maxAllowed = Number.isFinite(venueMaxLeverage) ? venueMaxLeverage : null;
|
|
208
214
|
const effectiveLeverage = maxAllowed == null ? requestedLeverage : Math.min(requestedLeverage, maxAllowed);
|
|
209
215
|
const feeSource = hasConfiguredFees ? "config" : exchangeFees?.source ?? "fallback";
|
|
210
|
-
const fundingSource = !fundingEnabled ? cacheOnly ? "fallback" : "disabled" : fundingRates.length ? "historical" : "unavailable";
|
|
211
|
-
const usesFallback = feeSource === "fallback" || fundingEnabled && fundingSource === "unavailable" ||
|
|
216
|
+
const fundingSource = !fundingEnabled ? costs?.funding.enabled === false ? "disabled" : cacheOnly ? "fallback" : "disabled" : fundingRates.length ? "historical" : "unavailable";
|
|
217
|
+
const usesFallback = feeSource === "fallback" || fundingEnabled && fundingSource === "unavailable" || !costs;
|
|
218
|
+
if (costs?.funding.enabled && (!fundingEnabled || fundingSource !== "historical")) {
|
|
219
|
+
throw new Error(
|
|
220
|
+
"Requested funding history is unavailable; explicitly disable funding or provide historical data"
|
|
221
|
+
);
|
|
222
|
+
}
|
|
212
223
|
return {
|
|
213
224
|
model: {
|
|
214
225
|
fees: { makerRate, takerRate, source: feeSource },
|
|
@@ -220,20 +231,20 @@ var resolveExecutionCosts = async (params) => {
|
|
|
220
231
|
toTimestamp: fundingRates.at(-1)?.timestamp ?? null
|
|
221
232
|
},
|
|
222
233
|
slippage: {
|
|
223
|
-
baseBps:
|
|
234
|
+
baseBps: costs?.slippage.baseBps ?? BACKTEST_BASE_SLIPPAGE_BPS,
|
|
224
235
|
spreadMultiplier: finiteOr(
|
|
225
|
-
|
|
236
|
+
costs?.slippage.spreadMultiplier,
|
|
226
237
|
BACKTEST_SPREAD_SLIPPAGE_MULTIPLIER
|
|
227
238
|
),
|
|
228
239
|
marketImpactBps: finiteOr(
|
|
229
|
-
|
|
240
|
+
costs?.slippage.marketImpactBps,
|
|
230
241
|
BACKTEST_MARKET_IMPACT_BPS
|
|
231
242
|
),
|
|
232
243
|
delayRiskMultiplier: finiteOr(
|
|
233
|
-
|
|
244
|
+
costs?.slippage.delayRiskMultiplier,
|
|
234
245
|
BACKTEST_DELAY_RISK_MULTIPLIER
|
|
235
246
|
),
|
|
236
|
-
source:
|
|
247
|
+
source: costs != null ? "config" : "fallback"
|
|
237
248
|
},
|
|
238
249
|
leverage: {
|
|
239
250
|
requested: requestedLeverage,
|
|
@@ -555,7 +566,7 @@ var createTestConnector = (connector, context) => {
|
|
|
555
566
|
allocatedQty += legExitQty;
|
|
556
567
|
const legResult = currentEntryLegResults[leg.index];
|
|
557
568
|
const legGrossProfit = currentPosition.direction === "LONG" ? (executionPrice - legResult.entryPrice) * legExitQty : (legResult.entryPrice - executionPrice) * legExitQty;
|
|
558
|
-
const legFee =
|
|
569
|
+
const legFee = fee * (legExitQty / qty);
|
|
559
570
|
currentEntryLegResults[leg.index] = appendExitToTradeResult({
|
|
560
571
|
tradeResult: legResult,
|
|
561
572
|
direction: currentPosition.direction,
|
|
@@ -1239,7 +1250,8 @@ var createTestConnector = (connector, context) => {
|
|
|
1239
1250
|
const { fee, profit } = getNetProfit({
|
|
1240
1251
|
grossProfit,
|
|
1241
1252
|
price: executionPrice,
|
|
1242
|
-
qty: currentPosition.qty
|
|
1253
|
+
qty: currentPosition.qty,
|
|
1254
|
+
feeRate: order.isLimit ? makerFeeRate : takerFeeRate
|
|
1243
1255
|
});
|
|
1244
1256
|
recordExitResult({
|
|
1245
1257
|
timestamp: order.timestamp,
|
|
@@ -1384,6 +1396,8 @@ var createBacktestSession = async ({
|
|
|
1384
1396
|
connector,
|
|
1385
1397
|
symbol: test.symbol,
|
|
1386
1398
|
config: test.strategyConfig,
|
|
1399
|
+
executionCosts: test.executionCosts,
|
|
1400
|
+
cacheOnly: test.executionCostsCacheOnly,
|
|
1387
1401
|
startTime: start,
|
|
1388
1402
|
endTime: test.options.end,
|
|
1389
1403
|
instrument
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
getStrategyCreator,
|
|
3
3
|
getStrategyEntry,
|
|
4
4
|
getStrategyPluginSource
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-UITD6LG6.mjs";
|
|
6
6
|
import {
|
|
7
7
|
loadTradejsConfig
|
|
8
8
|
} from "./chunk-LZDXRXIU.mjs";
|
|
@@ -40,7 +40,13 @@ var DEPLOYMENT_KEYS = /* @__PURE__ */ new Set([
|
|
|
40
40
|
"assetClasses",
|
|
41
41
|
"tickers"
|
|
42
42
|
]);
|
|
43
|
-
var STRATEGY_KEYS = /* @__PURE__ */ new Set([
|
|
43
|
+
var STRATEGY_KEYS = /* @__PURE__ */ new Set([
|
|
44
|
+
"module",
|
|
45
|
+
"generation",
|
|
46
|
+
"enabled",
|
|
47
|
+
"selection",
|
|
48
|
+
"config"
|
|
49
|
+
]);
|
|
44
50
|
var SELECTION_KEYS = /* @__PURE__ */ new Set(["tickers"]);
|
|
45
51
|
var FORBIDDEN_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
46
52
|
"ACCOUNT_ID",
|
|
@@ -112,6 +118,39 @@ var readRuntimePackageManifest = async (projectRoot) => {
|
|
|
112
118
|
}
|
|
113
119
|
return value;
|
|
114
120
|
};
|
|
121
|
+
var parseNpmAliasReference = (value) => {
|
|
122
|
+
if (typeof value !== "string" || !value.startsWith("npm:")) return null;
|
|
123
|
+
const target = value.slice("npm:".length);
|
|
124
|
+
const versionSeparator = target.lastIndexOf("@");
|
|
125
|
+
if (versionSeparator <= 0 || versionSeparator === target.length - 1) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
packageName: target.slice(0, versionSeparator),
|
|
130
|
+
version: target.slice(versionSeparator + 1)
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
var verifyInstalledPackageName = async ({
|
|
134
|
+
projectRoot,
|
|
135
|
+
packageName,
|
|
136
|
+
installedName,
|
|
137
|
+
installedVersion,
|
|
138
|
+
projectPackage
|
|
139
|
+
}) => {
|
|
140
|
+
if (installedName === void 0 || installedName === packageName) return;
|
|
141
|
+
if (projectPackage || typeof installedName !== "string") {
|
|
142
|
+
throw new Error("name is invalid");
|
|
143
|
+
}
|
|
144
|
+
const projectManifest = JSON.parse(
|
|
145
|
+
await readFile(path.join(projectRoot, "package.json"), "utf8")
|
|
146
|
+
);
|
|
147
|
+
const alias = parseNpmAliasReference(
|
|
148
|
+
projectManifest.dependencies?.[packageName]
|
|
149
|
+
);
|
|
150
|
+
if (alias?.packageName !== installedName || alias.version !== installedVersion) {
|
|
151
|
+
throw new Error("name or alias target is invalid");
|
|
152
|
+
}
|
|
153
|
+
};
|
|
115
154
|
var readInstalledPackageMetadata = async ({
|
|
116
155
|
projectRoot,
|
|
117
156
|
packageName,
|
|
@@ -125,9 +164,16 @@ var readInstalledPackageMetadata = async ({
|
|
|
125
164
|
);
|
|
126
165
|
try {
|
|
127
166
|
const packageJson = JSON.parse(await readFile(packageJsonPath, "utf8"));
|
|
128
|
-
if (
|
|
129
|
-
throw new Error("
|
|
167
|
+
if (typeof packageJson.version !== "string" || !packageJson.version.trim()) {
|
|
168
|
+
throw new Error("version is invalid");
|
|
130
169
|
}
|
|
170
|
+
await verifyInstalledPackageName({
|
|
171
|
+
projectRoot,
|
|
172
|
+
packageName,
|
|
173
|
+
installedName: packageJson.name,
|
|
174
|
+
installedVersion: packageJson.version,
|
|
175
|
+
projectPackage
|
|
176
|
+
});
|
|
131
177
|
const dependencyNames = [
|
|
132
178
|
...isRecord(packageJson.dependencies) ? Object.keys(packageJson.dependencies) : [],
|
|
133
179
|
...isRecord(packageJson.peerDependencies) ? Object.keys(packageJson.peerDependencies) : []
|
|
@@ -222,7 +268,7 @@ var verifyDeploymentDeclaration = (deploymentId, value) => {
|
|
|
222
268
|
for (const [strategyName, strategyValue] of Object.entries(
|
|
223
269
|
value.strategies
|
|
224
270
|
)) {
|
|
225
|
-
if (!strategyName.trim() || !isRecord(strategyValue) || Object.keys(strategyValue).some((key) => !STRATEGY_KEYS.has(key)) || strategyValue.generation !== void 0 && (typeof strategyValue.generation !== "string" || !strategyValue.generation.trim()) || typeof strategyValue.enabled !== "boolean" || !verifyStrategySelection(strategyValue.selection) || !isRecord(strategyValue.config) || Object.keys(strategyValue.config).some(
|
|
271
|
+
if (!strategyName.trim() || !isRecord(strategyValue) || Object.keys(strategyValue).some((key) => !STRATEGY_KEYS.has(key)) || strategyValue.generation !== void 0 && (typeof strategyValue.generation !== "string" || !strategyValue.generation.trim()) || strategyValue.module !== void 0 && (typeof strategyValue.module !== "string" || !strategyValue.module.trim()) || typeof strategyValue.enabled !== "boolean" || !verifyStrategySelection(strategyValue.selection) || !isRecord(strategyValue.config) || Object.keys(strategyValue.config).some(
|
|
226
272
|
(key) => FORBIDDEN_CONFIG_KEYS.has(key)
|
|
227
273
|
) || !INTERVALS.has(String(strategyValue.config.INTERVAL)) || !["crypto", "tradfi"].includes(String(strategyValue.config.UNIVERSE))) {
|
|
228
274
|
throw new Error(
|
|
@@ -256,9 +302,9 @@ var resolveStrategyComposition = async ({
|
|
|
256
302
|
packageManifest
|
|
257
303
|
}) => {
|
|
258
304
|
const [strategyEntry, strategyCreator, pluginSource] = await Promise.all([
|
|
259
|
-
getStrategyEntry(strategyName, projectRoot),
|
|
260
|
-
getStrategyCreator(strategyName, projectRoot),
|
|
261
|
-
getStrategyPluginSource(strategyName, projectRoot)
|
|
305
|
+
getStrategyEntry(strategyName, projectRoot, declaration.module),
|
|
306
|
+
getStrategyCreator(strategyName, projectRoot, declaration.module),
|
|
307
|
+
getStrategyPluginSource(strategyName, projectRoot, declaration.module)
|
|
262
308
|
]);
|
|
263
309
|
if (!strategyEntry || !strategyCreator) {
|
|
264
310
|
throw new Error(`Unknown strategy: ${strategyName}`);
|
|
@@ -308,6 +354,7 @@ var resolveStrategyComposition = async ({
|
|
|
308
354
|
});
|
|
309
355
|
return {
|
|
310
356
|
strategyName,
|
|
357
|
+
strategyModule: pluginSource ?? strategyPackage.name,
|
|
311
358
|
strategyRevision: computeStrategyRevision({
|
|
312
359
|
strategyName,
|
|
313
360
|
strategyPackage: strategyPackage.name,
|
|
@@ -496,11 +543,12 @@ var loadResolvedRuntimeStrategies = async ({
|
|
|
496
543
|
};
|
|
497
544
|
var getRuntimeStrategyPackageMetadata = async ({
|
|
498
545
|
strategyName,
|
|
499
|
-
projectRoot
|
|
546
|
+
projectRoot,
|
|
547
|
+
strategyModule
|
|
500
548
|
}) => {
|
|
501
549
|
const [packageManifest, pluginSource] = await Promise.all([
|
|
502
550
|
readRuntimePackageManifest(projectRoot),
|
|
503
|
-
getStrategyPluginSource(strategyName, projectRoot)
|
|
551
|
+
getStrategyPluginSource(strategyName, projectRoot, strategyModule)
|
|
504
552
|
]);
|
|
505
553
|
const strategyPackage = await resolveStrategyPackage({
|
|
506
554
|
pluginSource: pluginSource ?? null,
|
|
@@ -164,7 +164,8 @@ var buildExchangeFallbackRuntimeTrades = ({
|
|
|
164
164
|
openPositions,
|
|
165
165
|
strategyNames,
|
|
166
166
|
existingTrades,
|
|
167
|
-
endTime
|
|
167
|
+
endTime,
|
|
168
|
+
scope
|
|
168
169
|
}) => {
|
|
169
170
|
if (!entryRows.length && !closedPnlRows.length) return [];
|
|
170
171
|
const strategyNameByOrderId = new Map(
|
|
@@ -219,6 +220,7 @@ var buildExchangeFallbackRuntimeTrades = ({
|
|
|
219
220
|
const entryPrice = typeof entry.entryPrice === "number" && Number.isFinite(entry.entryPrice) ? entry.entryPrice : typeof closed?.entryPrice === "number" && Number.isFinite(closed.entryPrice) ? closed.entryPrice : null;
|
|
220
221
|
if (entryPrice == null) return null;
|
|
221
222
|
return {
|
|
223
|
+
...scope,
|
|
222
224
|
orderId: runtimeOrderId,
|
|
223
225
|
strategy,
|
|
224
226
|
symbol: entry.symbol,
|
|
@@ -261,6 +263,7 @@ var buildExchangeFallbackRuntimeTrades = ({
|
|
|
261
263
|
return null;
|
|
262
264
|
}
|
|
263
265
|
return {
|
|
266
|
+
...scope,
|
|
264
267
|
orderId: runtimeOrderId,
|
|
265
268
|
strategy,
|
|
266
269
|
symbol: row.symbol,
|
|
@@ -599,6 +599,7 @@ var createStrategyRegistryState = () => ({
|
|
|
599
599
|
strategyManifestsMap: /* @__PURE__ */ new Map(),
|
|
600
600
|
strategyEntriesMap: /* @__PURE__ */ new Map(),
|
|
601
601
|
strategySourcesMap: /* @__PURE__ */ new Map(),
|
|
602
|
+
strategyModuleResolutions: /* @__PURE__ */ new Map(),
|
|
602
603
|
pluginsLoadPromise: null
|
|
603
604
|
});
|
|
604
605
|
var registryStateByProjectRoot = sharedStrategyRegistry.registryStateByProjectRoot;
|
|
@@ -660,7 +661,7 @@ var validateStrategyEntries = (moduleName, entries, state) => {
|
|
|
660
661
|
const strategyName = entry?.manifest?.name;
|
|
661
662
|
if (typeof strategyName !== "string" || !strategyName.trim()) {
|
|
662
663
|
issues.push(`${entryPath}: manifest.name is required`);
|
|
663
|
-
} else if (names.has(strategyName) || state
|
|
664
|
+
} else if (names.has(strategyName) || state?.strategyEntriesMap.has(strategyName)) {
|
|
664
665
|
issues.push(`${entryPath}: duplicate strategy ${strategyName}`);
|
|
665
666
|
} else {
|
|
666
667
|
names.add(strategyName);
|
|
@@ -722,6 +723,72 @@ var importStrategyPluginModule = async (moduleName, cwd = getTradejsProjectCwd()
|
|
|
722
723
|
moduleName
|
|
723
724
|
);
|
|
724
725
|
};
|
|
726
|
+
var resolveStrategyModuleEntry = async ({
|
|
727
|
+
strategyName,
|
|
728
|
+
moduleName,
|
|
729
|
+
cwd
|
|
730
|
+
}) => {
|
|
731
|
+
const { projectRoot, state } = getStrategyRegistryState(cwd);
|
|
732
|
+
const source = moduleName.trim();
|
|
733
|
+
const resolvedModuleName = resolvePluginModuleSpecifier(source, projectRoot);
|
|
734
|
+
const cacheKey = `${resolvedModuleName}\0${strategyName}`;
|
|
735
|
+
const cached = state.strategyModuleResolutions.get(cacheKey);
|
|
736
|
+
if (cached) return cached;
|
|
737
|
+
const resolution = (async () => {
|
|
738
|
+
const moduleExport = await importStrategyPluginModule(
|
|
739
|
+
resolvedModuleName,
|
|
740
|
+
projectRoot
|
|
741
|
+
);
|
|
742
|
+
const pluginDefinition = extractStrategyPluginDefinition(moduleExport);
|
|
743
|
+
if (!pluginDefinition) {
|
|
744
|
+
throw new Error(`${source}: export { strategyEntries } is missing`);
|
|
745
|
+
}
|
|
746
|
+
const issues = validateStrategyEntries(
|
|
747
|
+
source,
|
|
748
|
+
pluginDefinition.strategyEntries
|
|
749
|
+
);
|
|
750
|
+
if (issues.length > 0) {
|
|
751
|
+
throw new Error(
|
|
752
|
+
["Invalid TradeJS strategy module:", ...issues].join("\n")
|
|
753
|
+
);
|
|
754
|
+
}
|
|
755
|
+
const entry = pluginDefinition.strategyEntries.find(
|
|
756
|
+
(candidate) => candidate.manifest.name === strategyName
|
|
757
|
+
);
|
|
758
|
+
if (!entry) {
|
|
759
|
+
throw new Error(`${source}: strategy ${strategyName} is missing`);
|
|
760
|
+
}
|
|
761
|
+
const factory = sharedStrategyRegistry.strategyRuntimeFactory;
|
|
762
|
+
if (!factory) {
|
|
763
|
+
throw new Error("Strategy runtime factory is not configured");
|
|
764
|
+
}
|
|
765
|
+
const manifestsByName = new Map(
|
|
766
|
+
pluginDefinition.strategyEntries.map(
|
|
767
|
+
(candidate) => [candidate.manifest.name, candidate.manifest]
|
|
768
|
+
)
|
|
769
|
+
);
|
|
770
|
+
return {
|
|
771
|
+
entry,
|
|
772
|
+
creator: factory({
|
|
773
|
+
strategyName,
|
|
774
|
+
defaults: entry.defaults,
|
|
775
|
+
createCore: entry.createCore,
|
|
776
|
+
manifest: entry.manifest,
|
|
777
|
+
detectorKey: entry.detectorKey,
|
|
778
|
+
detectorNoSignalSkipReason: entry.detectorNoSignalSkipReason,
|
|
779
|
+
resolveRegisteredManifest: (name) => manifestsByName.get(name) ?? state.strategyManifestsMap.get(name)
|
|
780
|
+
}),
|
|
781
|
+
source
|
|
782
|
+
};
|
|
783
|
+
})();
|
|
784
|
+
state.strategyModuleResolutions.set(cacheKey, resolution);
|
|
785
|
+
try {
|
|
786
|
+
return await resolution;
|
|
787
|
+
} catch (error) {
|
|
788
|
+
state.strategyModuleResolutions.delete(cacheKey);
|
|
789
|
+
throw error;
|
|
790
|
+
}
|
|
791
|
+
};
|
|
725
792
|
var ensureStrategyPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
|
|
726
793
|
const { projectRoot, state } = getStrategyRegistryState(cwd);
|
|
727
794
|
if (!state.pluginsLoadPromise) {
|
|
@@ -800,7 +867,11 @@ var ensureStrategyPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
|
|
|
800
867
|
await state.pluginsLoadPromise;
|
|
801
868
|
};
|
|
802
869
|
var ensureIndicatorPluginsLoaded = async (cwd = getTradejsProjectCwd()) => ensureStrategyPluginsLoaded(cwd);
|
|
803
|
-
var getStrategyCreator = async (name, cwd = getTradejsProjectCwd()) => {
|
|
870
|
+
var getStrategyCreator = async (name, cwd = getTradejsProjectCwd(), moduleName) => {
|
|
871
|
+
if (moduleName?.trim()) {
|
|
872
|
+
await ensureStrategyPluginsLoaded(cwd);
|
|
873
|
+
return (await resolveStrategyModuleEntry({ strategyName: name, moduleName, cwd })).creator;
|
|
874
|
+
}
|
|
804
875
|
await ensureStrategyPluginsLoaded(cwd);
|
|
805
876
|
const { state } = getStrategyRegistryState(cwd);
|
|
806
877
|
return state.strategyCreators.get(name);
|
|
@@ -810,12 +881,20 @@ var getStrategyDefaults = async (name, cwd = getTradejsProjectCwd()) => {
|
|
|
810
881
|
const { state } = getStrategyRegistryState(cwd);
|
|
811
882
|
return state.strategyEntriesMap.get(name)?.defaults;
|
|
812
883
|
};
|
|
813
|
-
var getStrategyEntry = async (name, cwd = getTradejsProjectCwd()) => {
|
|
884
|
+
var getStrategyEntry = async (name, cwd = getTradejsProjectCwd(), moduleName) => {
|
|
885
|
+
if (moduleName?.trim()) {
|
|
886
|
+
await ensureStrategyPluginsLoaded(cwd);
|
|
887
|
+
return (await resolveStrategyModuleEntry({ strategyName: name, moduleName, cwd })).entry;
|
|
888
|
+
}
|
|
814
889
|
await ensureStrategyPluginsLoaded(cwd);
|
|
815
890
|
const { state } = getStrategyRegistryState(cwd);
|
|
816
891
|
return state.strategyEntriesMap.get(name);
|
|
817
892
|
};
|
|
818
|
-
var getStrategyPluginSource = async (name, cwd = getTradejsProjectCwd()) => {
|
|
893
|
+
var getStrategyPluginSource = async (name, cwd = getTradejsProjectCwd(), moduleName) => {
|
|
894
|
+
if (moduleName?.trim()) {
|
|
895
|
+
await ensureStrategyPluginsLoaded(cwd);
|
|
896
|
+
return (await resolveStrategyModuleEntry({ strategyName: name, moduleName, cwd })).source;
|
|
897
|
+
}
|
|
819
898
|
await ensureStrategyPluginsLoaded(cwd);
|
|
820
899
|
const { state } = getStrategyRegistryState(cwd);
|
|
821
900
|
return state.strategySourcesMap.get(name);
|