@tradejs/node 3.1.11 → 3.1.12-beta.217
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 +0 -1
- package/dist/ai.mjs +1 -1
- package/dist/backtest.js +99 -82
- package/dist/backtest.mjs +2 -2
- package/dist/{chunk-B6X2HEGL.mjs → chunk-6PIVDS4M.mjs} +6 -6
- package/dist/{chunk-C3KRBNUR.mjs → chunk-IKRSNRP6.mjs} +58 -31
- package/dist/chunk-NQO2MFP6.mjs +552 -0
- package/dist/cli.js +108 -91
- package/dist/cli.mjs +1 -1
- package/dist/registry.js +86 -65
- package/dist/registry.mjs +2 -2
- package/dist/runtimeDashboard.js +420 -216
- package/dist/runtimeDashboard.mjs +9 -9
- package/dist/runtimeStrategies.d.mts +66 -6
- package/dist/runtimeStrategies.d.ts +66 -6
- package/dist/runtimeStrategies.js +450 -218
- package/dist/runtimeStrategies.mjs +11 -3
- package/dist/strategies.js +97 -76
- package/dist/strategies.mjs +2 -2
- package/package.json +14 -8
- package/dist/chunk-7BAL7EN3.mjs +0 -345
|
@@ -30,13 +30,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/runtimeStrategies.ts
|
|
31
31
|
var runtimeStrategies_exports = {};
|
|
32
32
|
__export(runtimeStrategies_exports, {
|
|
33
|
+
RUNTIME_PACKAGE_MANIFEST_SCHEMA: () => RUNTIME_PACKAGE_MANIFEST_SCHEMA,
|
|
34
|
+
computeDeploymentCompositionId: () => computeDeploymentCompositionId,
|
|
35
|
+
computeStrategyRevision: () => computeStrategyRevision,
|
|
33
36
|
getRuntimeDeployment: () => getRuntimeDeployment,
|
|
34
37
|
getRuntimeStrategyPackageMetadata: () => getRuntimeStrategyPackageMetadata,
|
|
35
38
|
listRuntimeDeployments: () => listRuntimeDeployments,
|
|
36
39
|
loadResolvedRuntimeStrategies: () => loadResolvedRuntimeStrategies,
|
|
40
|
+
resolveRuntimeComposition: () => resolveRuntimeComposition,
|
|
37
41
|
verifyRuntimeDeclaration: () => verifyRuntimeDeclaration
|
|
38
42
|
});
|
|
39
43
|
module.exports = __toCommonJS(runtimeStrategies_exports);
|
|
44
|
+
var import_node_crypto4 = require("crypto");
|
|
40
45
|
var import_promises = require("fs/promises");
|
|
41
46
|
var import_node_path = __toESM(require("path"));
|
|
42
47
|
var import_runtimeControls = require("@tradejs/infra/runtimeControls");
|
|
@@ -45,10 +50,10 @@ var import_tradingAccounts = require("@tradejs/infra/tradingAccounts");
|
|
|
45
50
|
// src/strategyRuntime.ts
|
|
46
51
|
var import_constants5 = require("@tradejs/core/constants");
|
|
47
52
|
var import_strategies6 = require("@tradejs/core/strategies");
|
|
48
|
-
var
|
|
53
|
+
var import_logger10 = require("@tradejs/infra/logger");
|
|
49
54
|
|
|
50
55
|
// src/strategyHelpers/runtime.ts
|
|
51
|
-
var
|
|
56
|
+
var import_logger8 = require("@tradejs/infra/logger");
|
|
52
57
|
var import_constants3 = require("@tradejs/core/constants");
|
|
53
58
|
var import_ml2 = require("@tradejs/infra/ml");
|
|
54
59
|
|
|
@@ -630,7 +635,6 @@ var buildAiMarketContext = (signal) => ({
|
|
|
630
635
|
|
|
631
636
|
// src/strategy/manifests.ts
|
|
632
637
|
var import_indicators = require("@tradejs/core/indicators");
|
|
633
|
-
var import_logger2 = require("@tradejs/infra/logger");
|
|
634
638
|
|
|
635
639
|
// src/tradejsConfig.ts
|
|
636
640
|
var import_fs = __toESM(require("fs"));
|
|
@@ -983,21 +987,34 @@ var extractIndicatorPluginDefinition = (moduleExport) => {
|
|
|
983
987
|
);
|
|
984
988
|
return indicatorEntries ? { indicatorEntries } : null;
|
|
985
989
|
};
|
|
986
|
-
var
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
990
|
+
var validateStrategyEntries = (moduleName, entries, state) => {
|
|
991
|
+
const issues = [];
|
|
992
|
+
const names = /* @__PURE__ */ new Set();
|
|
993
|
+
entries.forEach((entry, index) => {
|
|
994
|
+
const entryPath = `${moduleName}.strategyEntries[${index}]`;
|
|
995
|
+
const strategyName = entry?.manifest?.name;
|
|
996
|
+
if (typeof strategyName !== "string" || !strategyName.trim()) {
|
|
997
|
+
issues.push(`${entryPath}: manifest.name is required`);
|
|
998
|
+
} else if (names.has(strategyName) || state.strategyEntriesMap.has(strategyName)) {
|
|
999
|
+
issues.push(`${entryPath}: duplicate strategy ${strategyName}`);
|
|
1000
|
+
} else {
|
|
1001
|
+
names.add(strategyName);
|
|
992
1002
|
}
|
|
993
|
-
if (
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1003
|
+
if (!entry || typeof entry !== "object" || !entry.defaults || typeof entry.defaults !== "object" || Array.isArray(entry.defaults)) {
|
|
1004
|
+
issues.push(`${entryPath}: defaults must be an object`);
|
|
1005
|
+
}
|
|
1006
|
+
if (typeof entry?.parseConfig !== "function") {
|
|
1007
|
+
issues.push(`${entryPath}: parseConfig is required`);
|
|
1008
|
+
}
|
|
1009
|
+
if (typeof entry?.createCore !== "function") {
|
|
1010
|
+
issues.push(`${entryPath}: createCore is required`);
|
|
1000
1011
|
}
|
|
1012
|
+
});
|
|
1013
|
+
return issues;
|
|
1014
|
+
};
|
|
1015
|
+
var registerEntries = (entries, source, state) => {
|
|
1016
|
+
for (const entry of entries) {
|
|
1017
|
+
const strategyName = entry.manifest.name;
|
|
1001
1018
|
state.strategyManifestsMap.set(strategyName, entry.manifest);
|
|
1002
1019
|
state.strategyEntriesMap.set(strategyName, entry);
|
|
1003
1020
|
state.strategySourcesMap.set(strategyName, source);
|
|
@@ -1054,6 +1071,7 @@ var ensureStrategyPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
|
|
|
1054
1071
|
if (!pluginModuleNames.length) {
|
|
1055
1072
|
return;
|
|
1056
1073
|
}
|
|
1074
|
+
const issues = [];
|
|
1057
1075
|
for (const moduleName of pluginModuleNames) {
|
|
1058
1076
|
try {
|
|
1059
1077
|
const resolvedModuleName = resolvePluginModuleSpecifier(
|
|
@@ -1067,24 +1085,30 @@ var ensureStrategyPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
|
|
|
1067
1085
|
if (strategySet.has(moduleName)) {
|
|
1068
1086
|
const pluginDefinition = extractStrategyPluginDefinition(moduleExport);
|
|
1069
1087
|
if (!pluginDefinition) {
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
moduleName
|
|
1088
|
+
issues.push(
|
|
1089
|
+
`${moduleName}: export { strategyEntries } is missing`
|
|
1073
1090
|
);
|
|
1074
1091
|
} else {
|
|
1075
|
-
|
|
1076
|
-
pluginDefinition.strategyEntries,
|
|
1092
|
+
const entryIssues = validateStrategyEntries(
|
|
1077
1093
|
moduleName,
|
|
1094
|
+
pluginDefinition.strategyEntries,
|
|
1078
1095
|
state
|
|
1079
1096
|
);
|
|
1097
|
+
issues.push(...entryIssues);
|
|
1098
|
+
if (entryIssues.length === 0) {
|
|
1099
|
+
registerEntries(
|
|
1100
|
+
pluginDefinition.strategyEntries,
|
|
1101
|
+
moduleName,
|
|
1102
|
+
state
|
|
1103
|
+
);
|
|
1104
|
+
}
|
|
1080
1105
|
}
|
|
1081
1106
|
}
|
|
1082
1107
|
if (indicatorSet.has(moduleName)) {
|
|
1083
1108
|
const indicatorPluginDefinition = extractIndicatorPluginDefinition(moduleExport);
|
|
1084
1109
|
if (!indicatorPluginDefinition) {
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
moduleName
|
|
1110
|
+
issues.push(
|
|
1111
|
+
`${moduleName}: export { indicatorEntries } is missing`
|
|
1088
1112
|
);
|
|
1089
1113
|
} else {
|
|
1090
1114
|
(0, import_indicators.registerIndicatorEntries)(
|
|
@@ -1095,19 +1119,17 @@ var ensureStrategyPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
|
|
|
1095
1119
|
}
|
|
1096
1120
|
}
|
|
1097
1121
|
if (!strategySet.has(moduleName) && !indicatorSet.has(moduleName)) {
|
|
1098
|
-
|
|
1099
|
-
'Skip plugin "%s": no strategy/indicator sections requested in config',
|
|
1100
|
-
moduleName
|
|
1101
|
-
);
|
|
1122
|
+
issues.push(`${moduleName}: plugin is not declared in config`);
|
|
1102
1123
|
}
|
|
1103
1124
|
} catch (error) {
|
|
1104
|
-
|
|
1105
|
-
'Failed to load plugin "%s": %s',
|
|
1106
|
-
moduleName,
|
|
1107
|
-
String(error)
|
|
1108
|
-
);
|
|
1125
|
+
issues.push(`${moduleName}: failed to import: ${String(error)}`);
|
|
1109
1126
|
}
|
|
1110
1127
|
}
|
|
1128
|
+
if (issues.length > 0) {
|
|
1129
|
+
throw new Error(
|
|
1130
|
+
["Invalid TradeJS plugin catalog:", ...issues].join("\n")
|
|
1131
|
+
);
|
|
1132
|
+
}
|
|
1111
1133
|
})();
|
|
1112
1134
|
}
|
|
1113
1135
|
await state.pluginsLoadPromise;
|
|
@@ -1117,6 +1139,11 @@ var getStrategyCreator = async (name, cwd = getTradejsProjectCwd()) => {
|
|
|
1117
1139
|
const { state } = getStrategyRegistryState(cwd);
|
|
1118
1140
|
return state.strategyCreators.get(name);
|
|
1119
1141
|
};
|
|
1142
|
+
var getStrategyEntry = async (name, cwd = getTradejsProjectCwd()) => {
|
|
1143
|
+
await ensureStrategyPluginsLoaded(cwd);
|
|
1144
|
+
const { state } = getStrategyRegistryState(cwd);
|
|
1145
|
+
return state.strategyEntriesMap.get(name);
|
|
1146
|
+
};
|
|
1120
1147
|
var getStrategyPluginSource = async (name, cwd = getTradejsProjectCwd()) => {
|
|
1121
1148
|
await ensureStrategyPluginsLoaded(cwd);
|
|
1122
1149
|
const { state } = getStrategyRegistryState(cwd);
|
|
@@ -1769,7 +1796,7 @@ var import_node_crypto = require("crypto");
|
|
|
1769
1796
|
var import_constants = require("@tradejs/core/constants");
|
|
1770
1797
|
var import_time = require("@tradejs/core/time");
|
|
1771
1798
|
var import_trade = require("@tradejs/core/trade");
|
|
1772
|
-
var
|
|
1799
|
+
var import_logger2 = require("@tradejs/infra/logger");
|
|
1773
1800
|
var import_redis2 = require("@tradejs/infra/redis");
|
|
1774
1801
|
var now = () => Date.now();
|
|
1775
1802
|
var toRandomOrderSuffix = () => (0, import_node_crypto.randomUUID)().replace(/-/g, "").slice(0, 12).toLowerCase();
|
|
@@ -1828,7 +1855,7 @@ var recordRuntimeTradeOpen = async (params) => {
|
|
|
1828
1855
|
)
|
|
1829
1856
|
]);
|
|
1830
1857
|
} catch (error) {
|
|
1831
|
-
|
|
1858
|
+
import_logger2.logger.error(
|
|
1832
1859
|
"runtime trade open journal failed: %s %s",
|
|
1833
1860
|
record.symbol,
|
|
1834
1861
|
error?.message || String(error)
|
|
@@ -1895,7 +1922,7 @@ var recordRuntimeTradeIncrease = async (params) => {
|
|
|
1895
1922
|
)
|
|
1896
1923
|
]);
|
|
1897
1924
|
} catch (error) {
|
|
1898
|
-
|
|
1925
|
+
import_logger2.logger.error(
|
|
1899
1926
|
"runtime trade increase journal failed: %s %s",
|
|
1900
1927
|
symbol,
|
|
1901
1928
|
error?.message || String(error)
|
|
@@ -2002,7 +2029,7 @@ var markRuntimeTradeClosed = async (params) => {
|
|
|
2002
2029
|
)
|
|
2003
2030
|
]);
|
|
2004
2031
|
} catch (error) {
|
|
2005
|
-
|
|
2032
|
+
import_logger2.logger.error(
|
|
2006
2033
|
"runtime trade close journal failed: %s %s",
|
|
2007
2034
|
symbol,
|
|
2008
2035
|
error?.message || String(error)
|
|
@@ -2012,11 +2039,11 @@ var markRuntimeTradeClosed = async (params) => {
|
|
|
2012
2039
|
};
|
|
2013
2040
|
|
|
2014
2041
|
// src/strategyHelpers/marketContextStages.ts
|
|
2015
|
-
var
|
|
2042
|
+
var import_logger7 = require("@tradejs/infra/logger");
|
|
2016
2043
|
|
|
2017
2044
|
// src/strategyHelpers/binanceMarketContext.ts
|
|
2018
2045
|
var import_marketContext = require("@tradejs/infra/timescale/marketContext");
|
|
2019
|
-
var
|
|
2046
|
+
var import_logger3 = require("@tradejs/infra/logger");
|
|
2020
2047
|
var import_strategies = require("@tradejs/core/strategies");
|
|
2021
2048
|
|
|
2022
2049
|
// src/binanceBreadthUniverses.ts
|
|
@@ -2612,7 +2639,7 @@ var enrichSignalWithBinanceMarketContext = async (params) => {
|
|
|
2612
2639
|
throw error;
|
|
2613
2640
|
}
|
|
2614
2641
|
binanceMarketContextUnavailable = true;
|
|
2615
|
-
|
|
2642
|
+
import_logger3.logger.warn(
|
|
2616
2643
|
"Binance market context disabled after Timescale read failure: %s",
|
|
2617
2644
|
String(error)
|
|
2618
2645
|
);
|
|
@@ -2622,7 +2649,7 @@ var enrichSignalWithBinanceMarketContext = async (params) => {
|
|
|
2622
2649
|
|
|
2623
2650
|
// src/strategyHelpers/coinMarketCapContext.ts
|
|
2624
2651
|
var import_strategies2 = require("@tradejs/core/strategies");
|
|
2625
|
-
var
|
|
2652
|
+
var import_logger4 = require("@tradejs/infra/logger");
|
|
2626
2653
|
var import_marketContext2 = require("@tradejs/infra/timescale/marketContext");
|
|
2627
2654
|
var DEFAULT_MAX_AGE_MS = 48 * 60 * 6e4;
|
|
2628
2655
|
var SOURCE_GLOBAL_DAILY = "coinmarketcap_global";
|
|
@@ -3111,7 +3138,7 @@ var enrichSignalWithCoinMarketCapContext = async (params) => {
|
|
|
3111
3138
|
throw error;
|
|
3112
3139
|
}
|
|
3113
3140
|
coinMarketCapContextUnavailable = true;
|
|
3114
|
-
|
|
3141
|
+
import_logger4.logger.warn(
|
|
3115
3142
|
"CoinMarketCap context disabled after Timescale read failure: %s",
|
|
3116
3143
|
String(error)
|
|
3117
3144
|
);
|
|
@@ -3125,7 +3152,7 @@ var import_data = require("@tradejs/core/data");
|
|
|
3125
3152
|
var import_strategies3 = require("@tradejs/core/strategies");
|
|
3126
3153
|
var import_constants2 = require("@tradejs/core/constants");
|
|
3127
3154
|
var import_derivatives = require("@tradejs/infra/timescale/derivatives");
|
|
3128
|
-
var
|
|
3155
|
+
var import_logger5 = require("@tradejs/infra/logger");
|
|
3129
3156
|
var STORED_INTERVALS = ["15m", "1h"];
|
|
3130
3157
|
var CONTEXT_INTERVALS = ["15m", "1h"];
|
|
3131
3158
|
var DEFAULT_LOOKBACK_HOURS = 48;
|
|
@@ -3357,7 +3384,7 @@ var enrichSignalWithDerivativesContext = async (params) => {
|
|
|
3357
3384
|
throw error;
|
|
3358
3385
|
}
|
|
3359
3386
|
derivativesContextUnavailable = true;
|
|
3360
|
-
|
|
3387
|
+
import_logger5.logger.warn(
|
|
3361
3388
|
"Derivatives context disabled after Timescale read failure: %s",
|
|
3362
3389
|
String(error)
|
|
3363
3390
|
);
|
|
@@ -3369,7 +3396,7 @@ var enrichSignalWithDerivativesContext = async (params) => {
|
|
|
3369
3396
|
var import_data2 = require("@tradejs/core/data");
|
|
3370
3397
|
var import_strategies4 = require("@tradejs/core/strategies");
|
|
3371
3398
|
var import_hyperliquidWhales2 = require("@tradejs/infra/timescale/hyperliquidWhales");
|
|
3372
|
-
var
|
|
3399
|
+
var import_logger6 = require("@tradejs/infra/logger");
|
|
3373
3400
|
|
|
3374
3401
|
// src/hyperliquidWhaleUniverse.ts
|
|
3375
3402
|
var import_node_crypto3 = require("crypto");
|
|
@@ -3889,7 +3916,7 @@ var loadHyperliquidWhaleFlowContext = async (params) => {
|
|
|
3889
3916
|
throw error;
|
|
3890
3917
|
}
|
|
3891
3918
|
hyperliquidWhaleContextUnavailable = true;
|
|
3892
|
-
|
|
3919
|
+
import_logger6.logger.warn(
|
|
3893
3920
|
"Hyperliquid whale context disabled after Timescale read failure: %s",
|
|
3894
3921
|
String(error)
|
|
3895
3922
|
);
|
|
@@ -3972,7 +3999,7 @@ var runMarketContextStage = async ({
|
|
|
3972
3999
|
elapsedMs: Date.now() - startedAt
|
|
3973
4000
|
};
|
|
3974
4001
|
if (status === "timed_out") {
|
|
3975
|
-
|
|
4002
|
+
import_logger7.logger.warn(
|
|
3976
4003
|
"Market context stage timed out: %s after %sms",
|
|
3977
4004
|
stage,
|
|
3978
4005
|
result.elapsedMs
|
|
@@ -4162,7 +4189,7 @@ var enrichSignalWithAi = async ({
|
|
|
4162
4189
|
signal.aiAnalysis = analysis;
|
|
4163
4190
|
return resolveAiQuality(analysis, direction);
|
|
4164
4191
|
} catch (err) {
|
|
4165
|
-
|
|
4192
|
+
import_logger8.logger.error("AI analysis error: %s %s", symbol, formatAiError(err));
|
|
4166
4193
|
}
|
|
4167
4194
|
return void 0;
|
|
4168
4195
|
};
|
|
@@ -4197,7 +4224,7 @@ var getOrderArrivalSnapshot = async ({
|
|
|
4197
4224
|
spreadBps
|
|
4198
4225
|
};
|
|
4199
4226
|
} catch (error) {
|
|
4200
|
-
|
|
4227
|
+
import_logger8.logger.warn(
|
|
4201
4228
|
"runtime order arrival snapshot failed: %s %s",
|
|
4202
4229
|
symbol,
|
|
4203
4230
|
error?.message || String(error)
|
|
@@ -4426,7 +4453,7 @@ var executeEntryOrder = async ({
|
|
|
4426
4453
|
deploymentId: signal.deploymentId,
|
|
4427
4454
|
policyProfileId: signal.policyProfileId,
|
|
4428
4455
|
runtimeConfigId: signal.runtimeConfigId,
|
|
4429
|
-
|
|
4456
|
+
strategyRevision: signal.strategyRevision,
|
|
4430
4457
|
runtimeLineage: signal.runtimeLineage,
|
|
4431
4458
|
...signal.aiAnalysis ? { aiAnalysis: signal.aiAnalysis } : {}
|
|
4432
4459
|
});
|
|
@@ -4978,7 +5005,7 @@ var canUseSharedReplayState = ({
|
|
|
4978
5005
|
}) => (env === "BACKTEST" || env === "PARITY") && Boolean(sharedReplayKey);
|
|
4979
5006
|
|
|
4980
5007
|
// src/strategy/runtimeExecution.ts
|
|
4981
|
-
var
|
|
5008
|
+
var import_logger9 = require("@tradejs/infra/logger");
|
|
4982
5009
|
var import_types = require("@tradejs/types");
|
|
4983
5010
|
var buildExitOrderSignal = ({
|
|
4984
5011
|
strategyName,
|
|
@@ -5030,7 +5057,7 @@ var handleExitDecision = async ({
|
|
|
5030
5057
|
deploymentId: connector.deploymentId
|
|
5031
5058
|
});
|
|
5032
5059
|
if (!activeTrade) {
|
|
5033
|
-
|
|
5060
|
+
import_logger9.logger.warn(
|
|
5034
5061
|
"[%s] blocked closePosition for untracked runtime position: %s",
|
|
5035
5062
|
strategyName ?? "unknown",
|
|
5036
5063
|
symbol
|
|
@@ -5038,7 +5065,7 @@ var handleExitDecision = async ({
|
|
|
5038
5065
|
return "CLOSE_BLOCKED_BY_UNTRACKED_POSITION";
|
|
5039
5066
|
}
|
|
5040
5067
|
if (!strategyName || activeTrade.strategy !== strategyName) {
|
|
5041
|
-
|
|
5068
|
+
import_logger9.logger.warn(
|
|
5042
5069
|
"[%s] blocked closePosition for foreign runtime position: %s ownedBy=%s",
|
|
5043
5070
|
strategyName ?? "unknown",
|
|
5044
5071
|
symbol,
|
|
@@ -5090,7 +5117,7 @@ var handleExitDecision = async ({
|
|
|
5090
5117
|
exitType: closedTrade?.exitType ?? "exit"
|
|
5091
5118
|
});
|
|
5092
5119
|
} catch (notificationError) {
|
|
5093
|
-
|
|
5120
|
+
import_logger9.logger.error(
|
|
5094
5121
|
"runtime close notification error: %s %s",
|
|
5095
5122
|
symbol,
|
|
5096
5123
|
notificationError
|
|
@@ -5104,7 +5131,7 @@ var handleExitDecision = async ({
|
|
|
5104
5131
|
decision,
|
|
5105
5132
|
market
|
|
5106
5133
|
});
|
|
5107
|
-
|
|
5134
|
+
import_logger9.logger.error("close order error: %s %s", symbol, err);
|
|
5108
5135
|
return "ORDER_ERROR";
|
|
5109
5136
|
}
|
|
5110
5137
|
return decision.code;
|
|
@@ -5131,7 +5158,7 @@ var handleProtectDecision = async ({
|
|
|
5131
5158
|
decision,
|
|
5132
5159
|
market
|
|
5133
5160
|
});
|
|
5134
|
-
|
|
5161
|
+
import_logger9.logger.error("protect position error: %s %s", symbol, err);
|
|
5135
5162
|
return "ORDER_ERROR";
|
|
5136
5163
|
}
|
|
5137
5164
|
return decision.code;
|
|
@@ -5294,9 +5321,9 @@ var executeEntryDecision = async ({
|
|
|
5294
5321
|
market
|
|
5295
5322
|
});
|
|
5296
5323
|
if (err?.message === import_types.BACKTEST_WARNING_CODES.TAKE_PROFIT_CROSSED_BEFORE_ENTRY) {
|
|
5297
|
-
|
|
5324
|
+
import_logger9.logger.warn("order warning: %s %s", symbol, err);
|
|
5298
5325
|
} else {
|
|
5299
|
-
|
|
5326
|
+
import_logger9.logger.error("order error: %s %s", symbol, err);
|
|
5300
5327
|
}
|
|
5301
5328
|
return signal ?? "ORDER_ERROR";
|
|
5302
5329
|
}
|
|
@@ -5337,7 +5364,7 @@ var createStrategyRuntime = ({
|
|
|
5337
5364
|
deploymentId: requestedDeploymentId,
|
|
5338
5365
|
policyProfileId,
|
|
5339
5366
|
runtimeConfigId,
|
|
5340
|
-
|
|
5367
|
+
strategyRevision,
|
|
5341
5368
|
entriesPaused = false,
|
|
5342
5369
|
runtimeLineage,
|
|
5343
5370
|
runtimeConfigSnapshot,
|
|
@@ -5450,7 +5477,7 @@ var createStrategyRuntime = ({
|
|
|
5450
5477
|
try {
|
|
5451
5478
|
await projectHook(errorParams);
|
|
5452
5479
|
} catch (hookError) {
|
|
5453
|
-
|
|
5480
|
+
import_logger10.logger.error(
|
|
5454
5481
|
"project hook onRuntimeError failed: %s %s",
|
|
5455
5482
|
strategyName,
|
|
5456
5483
|
hookError
|
|
@@ -5464,7 +5491,7 @@ var createStrategyRuntime = ({
|
|
|
5464
5491
|
try {
|
|
5465
5492
|
await onRuntimeError(errorParams);
|
|
5466
5493
|
} catch (hookError) {
|
|
5467
|
-
|
|
5494
|
+
import_logger10.logger.error(
|
|
5468
5495
|
"runtime hook onRuntimeError failed: %s %s",
|
|
5469
5496
|
strategyName,
|
|
5470
5497
|
hookError
|
|
@@ -5478,7 +5505,7 @@ var createStrategyRuntime = ({
|
|
|
5478
5505
|
try {
|
|
5479
5506
|
return await hook(params);
|
|
5480
5507
|
} catch (error) {
|
|
5481
|
-
|
|
5508
|
+
import_logger10.logger.error(
|
|
5482
5509
|
'strategy hook "%s" failed for %s: %s',
|
|
5483
5510
|
stage,
|
|
5484
5511
|
strategyName,
|
|
@@ -6009,8 +6036,8 @@ var createStrategyRuntime = ({
|
|
|
6009
6036
|
signal.signalId = `${signal.signalId}:${runtimeConfigId}`;
|
|
6010
6037
|
}
|
|
6011
6038
|
}
|
|
6012
|
-
if (
|
|
6013
|
-
signal.
|
|
6039
|
+
if (strategyRevision) {
|
|
6040
|
+
signal.strategyRevision = strategyRevision;
|
|
6014
6041
|
}
|
|
6015
6042
|
if (decisionHookCtx.policyProfileId) {
|
|
6016
6043
|
signal.policyProfileId = decisionHookCtx.policyProfileId;
|
|
@@ -6123,7 +6150,7 @@ var createStrategyRuntime = ({
|
|
|
6123
6150
|
if (signal) {
|
|
6124
6151
|
signal.orderStatus = "skipped";
|
|
6125
6152
|
signal.orderSkipReason = skipReason;
|
|
6126
|
-
signal.
|
|
6153
|
+
signal.strategyRevision = strategyRevision;
|
|
6127
6154
|
}
|
|
6128
6155
|
return signal ?? skipReason;
|
|
6129
6156
|
}
|
|
@@ -6235,6 +6262,7 @@ var createStrategyRuntime = ({
|
|
|
6235
6262
|
setStrategyRuntimeFactory(createStrategyRuntime);
|
|
6236
6263
|
|
|
6237
6264
|
// src/runtimeStrategies.ts
|
|
6265
|
+
var RUNTIME_PACKAGE_MANIFEST_SCHEMA = "tradejs-runtime-package-manifest/v1";
|
|
6238
6266
|
var INTERVALS = /* @__PURE__ */ new Set([
|
|
6239
6267
|
"1",
|
|
6240
6268
|
"3",
|
|
@@ -6261,7 +6289,7 @@ var DEPLOYMENT_KEYS = /* @__PURE__ */ new Set([
|
|
|
6261
6289
|
"assetClasses",
|
|
6262
6290
|
"tickers"
|
|
6263
6291
|
]);
|
|
6264
|
-
var STRATEGY_KEYS = /* @__PURE__ */ new Set(["
|
|
6292
|
+
var STRATEGY_KEYS = /* @__PURE__ */ new Set(["generation", "enabled", "selection", "config"]);
|
|
6265
6293
|
var SELECTION_KEYS = /* @__PURE__ */ new Set(["tickers"]);
|
|
6266
6294
|
var FORBIDDEN_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
6267
6295
|
"ACCOUNT_ID",
|
|
@@ -6270,60 +6298,165 @@ var FORBIDDEN_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
6270
6298
|
"ENABLE"
|
|
6271
6299
|
]);
|
|
6272
6300
|
var isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
6273
|
-
var
|
|
6274
|
-
|
|
6275
|
-
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
6279
|
-
|
|
6280
|
-
|
|
6281
|
-
|
|
6282
|
-
await (0, import_promises.readFile)(candidate, "utf8")
|
|
6283
|
-
);
|
|
6284
|
-
} catch {
|
|
6285
|
-
}
|
|
6301
|
+
var normalizeForCanonicalJson = (value) => {
|
|
6302
|
+
if (Array.isArray(value)) return value.map(normalizeForCanonicalJson);
|
|
6303
|
+
if (isRecord(value)) {
|
|
6304
|
+
return Object.fromEntries(
|
|
6305
|
+
Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, nestedValue]) => [
|
|
6306
|
+
key,
|
|
6307
|
+
normalizeForCanonicalJson(nestedValue)
|
|
6308
|
+
])
|
|
6309
|
+
);
|
|
6286
6310
|
}
|
|
6287
|
-
return
|
|
6311
|
+
return value;
|
|
6288
6312
|
};
|
|
6289
|
-
var
|
|
6290
|
-
|
|
6291
|
-
|
|
6292
|
-
|
|
6313
|
+
var revision = (prefix, value) => `${prefix}:${(0, import_node_crypto4.createHash)("sha256").update(JSON.stringify(normalizeForCanonicalJson(value))).digest("hex").slice(0, 16)}`;
|
|
6314
|
+
var computeStrategyRevision = ({
|
|
6315
|
+
strategyName,
|
|
6316
|
+
strategyPackage,
|
|
6317
|
+
strategyPackageVersion,
|
|
6318
|
+
strategyDependencyVersions,
|
|
6319
|
+
runtimePackageVersion,
|
|
6320
|
+
strategyConfig
|
|
6321
|
+
}) => revision("sr1", {
|
|
6322
|
+
schema: "tradejs-strategy-revision/v1",
|
|
6323
|
+
strategyName,
|
|
6324
|
+
strategyPackage,
|
|
6325
|
+
strategyPackageVersion,
|
|
6326
|
+
strategyDependencyVersions,
|
|
6327
|
+
runtimePackageVersion,
|
|
6328
|
+
strategyConfig
|
|
6329
|
+
});
|
|
6330
|
+
var computeDeploymentCompositionId = (value) => revision("dc1", {
|
|
6331
|
+
schema: "tradejs-deployment-composition/v1",
|
|
6332
|
+
...value,
|
|
6333
|
+
assetClasses: value.assetClasses ? [...value.assetClasses].sort((left, right) => left.localeCompare(right)) : void 0,
|
|
6334
|
+
strategies: [...value.strategies].sort(
|
|
6335
|
+
(left, right) => left.strategyName.localeCompare(right.strategyName)
|
|
6336
|
+
).map((strategy) => ({
|
|
6337
|
+
...strategy,
|
|
6338
|
+
selection: strategy.selection ? {
|
|
6339
|
+
tickers: [...strategy.selection.tickers].sort(
|
|
6340
|
+
(left, right) => left.localeCompare(right)
|
|
6341
|
+
)
|
|
6342
|
+
} : void 0
|
|
6343
|
+
}))
|
|
6344
|
+
});
|
|
6345
|
+
var readRuntimePackageManifest = async (projectRoot) => {
|
|
6346
|
+
const manifestPath = process.env.TRADEJS_RUNTIME_PACKAGE_MANIFEST?.trim() || import_node_path.default.join(projectRoot, "runtime-package-manifest.json");
|
|
6347
|
+
let value;
|
|
6293
6348
|
try {
|
|
6294
|
-
|
|
6295
|
-
|
|
6296
|
-
|
|
6297
|
-
|
|
6298
|
-
"package.json"
|
|
6349
|
+
value = JSON.parse(await (0, import_promises.readFile)(manifestPath, "utf8"));
|
|
6350
|
+
} catch (error) {
|
|
6351
|
+
throw new Error(
|
|
6352
|
+
`Unable to read runtime package manifest ${manifestPath}: ${String(error)}`
|
|
6299
6353
|
);
|
|
6354
|
+
}
|
|
6355
|
+
if (!isRecord(value) || Object.keys(value).some(
|
|
6356
|
+
(key) => !["schema", "projectSha", "packages"].includes(key)
|
|
6357
|
+
) || value.schema !== RUNTIME_PACKAGE_MANIFEST_SCHEMA || typeof value.projectSha !== "string" || !/^[a-f0-9]{40}$/.test(value.projectSha) || !isRecord(value.packages) || Object.keys(value.packages).length === 0 || Object.entries(value.packages).some(
|
|
6358
|
+
([packageName, version]) => !packageName.trim() || typeof version !== "string" || !version.trim()
|
|
6359
|
+
)) {
|
|
6360
|
+
throw new Error(`Invalid runtime package manifest: ${manifestPath}`);
|
|
6361
|
+
}
|
|
6362
|
+
return value;
|
|
6363
|
+
};
|
|
6364
|
+
var readInstalledPackageMetadata = async ({
|
|
6365
|
+
projectRoot,
|
|
6366
|
+
packageName,
|
|
6367
|
+
projectPackage
|
|
6368
|
+
}) => {
|
|
6369
|
+
const packageJsonPath = projectPackage ? import_node_path.default.join(projectRoot, "package.json") : import_node_path.default.join(
|
|
6370
|
+
projectRoot,
|
|
6371
|
+
"node_modules",
|
|
6372
|
+
...packageName.split("/"),
|
|
6373
|
+
"package.json"
|
|
6374
|
+
);
|
|
6375
|
+
try {
|
|
6300
6376
|
const packageJson = JSON.parse(await (0, import_promises.readFile)(packageJsonPath, "utf8"));
|
|
6301
|
-
|
|
6302
|
-
|
|
6303
|
-
|
|
6377
|
+
if (packageJson.name !== void 0 && packageJson.name !== packageName || typeof packageJson.version !== "string" || !packageJson.version.trim()) {
|
|
6378
|
+
throw new Error("name or version is invalid");
|
|
6379
|
+
}
|
|
6380
|
+
const dependencyNames = [
|
|
6381
|
+
...isRecord(packageJson.dependencies) ? Object.keys(packageJson.dependencies) : [],
|
|
6382
|
+
...isRecord(packageJson.peerDependencies) ? Object.keys(packageJson.peerDependencies) : []
|
|
6383
|
+
];
|
|
6384
|
+
return {
|
|
6385
|
+
version: packageJson.version,
|
|
6386
|
+
runtimeDependencies: [...new Set(dependencyNames)].filter((name) => name.startsWith("@tradejs/")).sort((left, right) => left.localeCompare(right))
|
|
6387
|
+
};
|
|
6388
|
+
} catch (error) {
|
|
6389
|
+
throw new Error(
|
|
6390
|
+
`Installed package manifest not found for ${packageName}: ${String(error)}`
|
|
6391
|
+
);
|
|
6304
6392
|
}
|
|
6305
6393
|
};
|
|
6306
|
-
var
|
|
6394
|
+
var resolveVerifiedPackageVersion = async ({
|
|
6395
|
+
projectRoot,
|
|
6396
|
+
packageName,
|
|
6397
|
+
manifest,
|
|
6398
|
+
projectPackage = false
|
|
6399
|
+
}) => {
|
|
6400
|
+
const declaredVersion = manifest.packages[packageName];
|
|
6401
|
+
if (!declaredVersion) {
|
|
6402
|
+
throw new Error(`Runtime package manifest is missing ${packageName}`);
|
|
6403
|
+
}
|
|
6404
|
+
const installed = await readInstalledPackageMetadata({
|
|
6405
|
+
projectRoot,
|
|
6406
|
+
packageName,
|
|
6407
|
+
projectPackage
|
|
6408
|
+
});
|
|
6409
|
+
if (declaredVersion !== installed.version) {
|
|
6410
|
+
throw new Error(
|
|
6411
|
+
`Runtime package manifest mismatch for ${packageName}: declared=${declaredVersion} installed=${installed.version}`
|
|
6412
|
+
);
|
|
6413
|
+
}
|
|
6414
|
+
return installed.version;
|
|
6415
|
+
};
|
|
6416
|
+
var resolveVerifiedStrategyDependencyVersions = async ({
|
|
6417
|
+
projectRoot,
|
|
6418
|
+
strategyPackage,
|
|
6419
|
+
manifest
|
|
6420
|
+
}) => {
|
|
6421
|
+
const metadata = await readInstalledPackageMetadata({
|
|
6422
|
+
projectRoot,
|
|
6423
|
+
packageName: strategyPackage.name,
|
|
6424
|
+
projectPackage: strategyPackage.projectPackage
|
|
6425
|
+
});
|
|
6426
|
+
return Object.fromEntries(
|
|
6427
|
+
await Promise.all(
|
|
6428
|
+
metadata.runtimeDependencies.map(async (packageName) => [
|
|
6429
|
+
packageName,
|
|
6430
|
+
await resolveVerifiedPackageVersion({
|
|
6431
|
+
projectRoot,
|
|
6432
|
+
packageName,
|
|
6433
|
+
manifest
|
|
6434
|
+
})
|
|
6435
|
+
])
|
|
6436
|
+
)
|
|
6437
|
+
);
|
|
6438
|
+
};
|
|
6439
|
+
var resolveStrategyPackage = async ({
|
|
6307
6440
|
pluginSource,
|
|
6308
6441
|
projectRoot
|
|
6309
6442
|
}) => {
|
|
6310
6443
|
if (!pluginSource) return null;
|
|
6311
6444
|
if (!pluginSource.startsWith(".") && !import_node_path.default.isAbsolute(pluginSource)) {
|
|
6312
|
-
return pluginSource;
|
|
6445
|
+
return { name: pluginSource, projectPackage: false };
|
|
6313
6446
|
}
|
|
6314
6447
|
try {
|
|
6315
6448
|
const packageJson = JSON.parse(
|
|
6316
6449
|
await (0, import_promises.readFile)(import_node_path.default.join(projectRoot, "package.json"), "utf8")
|
|
6317
6450
|
);
|
|
6318
|
-
return typeof packageJson.name === "string" && packageJson.name.trim() ? packageJson.name : null;
|
|
6451
|
+
return typeof packageJson.name === "string" && packageJson.name.trim() ? { name: packageJson.name, projectPackage: true } : null;
|
|
6319
6452
|
} catch {
|
|
6320
6453
|
return null;
|
|
6321
6454
|
}
|
|
6322
6455
|
};
|
|
6323
|
-
var
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
);
|
|
6456
|
+
var verifyStringSet = (value) => value === void 0 || Array.isArray(value) && value.length > 0 && value.every(
|
|
6457
|
+
(item) => typeof item === "string" && item.length > 0 && item === item.trim()
|
|
6458
|
+
) && new Set(value).size === value.length;
|
|
6459
|
+
var verifyStrategySelection = (value) => value === void 0 || isRecord(value) && Object.keys(value).length === 1 && Object.keys(value).every((key) => SELECTION_KEYS.has(key)) && value.tickers !== void 0 && verifyStringSet(value.tickers);
|
|
6327
6460
|
var cloneSelection = (selection) => selection ? { tickers: [...selection.tickers] } : void 0;
|
|
6328
6461
|
var resolveStrategySelection = ({
|
|
6329
6462
|
deployment,
|
|
@@ -6332,13 +6465,13 @@ var resolveStrategySelection = ({
|
|
|
6332
6465
|
strategy.selection ?? (deployment.tickers ? { tickers: deployment.tickers } : void 0)
|
|
6333
6466
|
);
|
|
6334
6467
|
var verifyDeploymentDeclaration = (deploymentId, value) => {
|
|
6335
|
-
if (!deploymentId.trim() || !isRecord(value) || Object.keys(value).some((key) => !DEPLOYMENT_KEYS.has(key)) || typeof value.connectorName !== "string" || !value.connectorName.trim() || typeof value.accountId !== "string" || !value.accountId.trim() || value.label !== void 0 && typeof value.label !== "string" || value.provider !== void 0 && typeof value.provider !== "string" || value.enabled !== void 0 && typeof value.enabled !== "boolean" || !
|
|
6468
|
+
if (!deploymentId.trim() || !isRecord(value) || Object.keys(value).some((key) => !DEPLOYMENT_KEYS.has(key)) || typeof value.connectorName !== "string" || !value.connectorName.trim() || typeof value.accountId !== "string" || !value.accountId.trim() || value.label !== void 0 && typeof value.label !== "string" || value.provider !== void 0 && typeof value.provider !== "string" || value.enabled !== void 0 && typeof value.enabled !== "boolean" || !verifyStringSet(value.assetClasses) || !verifyStringSet(value.tickers) || !isRecord(value.strategies) || !Object.keys(value.strategies).length) {
|
|
6336
6469
|
throw new Error(`Invalid runtime deployment declaration: ${deploymentId}`);
|
|
6337
6470
|
}
|
|
6338
6471
|
for (const [strategyName, strategyValue] of Object.entries(
|
|
6339
6472
|
value.strategies
|
|
6340
6473
|
)) {
|
|
6341
|
-
if (!strategyName.trim() || !isRecord(strategyValue) || Object.keys(strategyValue).some((key) => !STRATEGY_KEYS.has(key)) ||
|
|
6474
|
+
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(
|
|
6342
6475
|
(key) => FORBIDDEN_CONFIG_KEYS.has(key)
|
|
6343
6476
|
) || !INTERVALS.has(String(strategyValue.config.INTERVAL)) || !["crypto", "tradfi"].includes(String(strategyValue.config.UNIVERSE))) {
|
|
6344
6477
|
throw new Error(
|
|
@@ -6357,55 +6490,180 @@ var verifyRuntimeDeclaration = (value) => {
|
|
|
6357
6490
|
}
|
|
6358
6491
|
return value;
|
|
6359
6492
|
};
|
|
6360
|
-
var
|
|
6361
|
-
|
|
6493
|
+
var loadRuntimeDeclaration = async (projectRoot) => {
|
|
6494
|
+
const projectConfig = await loadTradejsConfig(projectRoot);
|
|
6495
|
+
if (!projectConfig.runtime) {
|
|
6496
|
+
throw new Error("Runtime declaration is required in tradejs.config.ts");
|
|
6497
|
+
}
|
|
6498
|
+
return verifyRuntimeDeclaration(projectConfig.runtime);
|
|
6499
|
+
};
|
|
6500
|
+
var resolveStrategyComposition = async ({
|
|
6501
|
+
strategyName,
|
|
6362
6502
|
declaration,
|
|
6503
|
+
deployment,
|
|
6504
|
+
projectRoot,
|
|
6505
|
+
packageManifest
|
|
6506
|
+
}) => {
|
|
6507
|
+
const [strategyEntry, strategyCreator, pluginSource] = await Promise.all([
|
|
6508
|
+
getStrategyEntry(strategyName, projectRoot),
|
|
6509
|
+
getStrategyCreator(strategyName, projectRoot),
|
|
6510
|
+
getStrategyPluginSource(strategyName, projectRoot)
|
|
6511
|
+
]);
|
|
6512
|
+
if (!strategyEntry || !strategyCreator) {
|
|
6513
|
+
throw new Error(`Unknown strategy: ${strategyName}`);
|
|
6514
|
+
}
|
|
6515
|
+
if (typeof strategyEntry.parseConfig !== "function") {
|
|
6516
|
+
throw new Error(`Strategy config parser is missing: ${strategyName}`);
|
|
6517
|
+
}
|
|
6518
|
+
const strategyPackage = await resolveStrategyPackage({
|
|
6519
|
+
pluginSource: pluginSource ?? null,
|
|
6520
|
+
projectRoot
|
|
6521
|
+
});
|
|
6522
|
+
if (!strategyPackage) {
|
|
6523
|
+
throw new Error(`Installed strategy package not found: ${strategyName}`);
|
|
6524
|
+
}
|
|
6525
|
+
const [
|
|
6526
|
+
strategyPackageVersion,
|
|
6527
|
+
strategyDependencyVersions,
|
|
6528
|
+
runtimePackageVersion
|
|
6529
|
+
] = await Promise.all([
|
|
6530
|
+
resolveVerifiedPackageVersion({
|
|
6531
|
+
projectRoot,
|
|
6532
|
+
packageName: strategyPackage.name,
|
|
6533
|
+
projectPackage: strategyPackage.projectPackage,
|
|
6534
|
+
manifest: packageManifest
|
|
6535
|
+
}),
|
|
6536
|
+
resolveVerifiedStrategyDependencyVersions({
|
|
6537
|
+
projectRoot,
|
|
6538
|
+
strategyPackage,
|
|
6539
|
+
manifest: packageManifest
|
|
6540
|
+
}),
|
|
6541
|
+
resolveVerifiedPackageVersion({
|
|
6542
|
+
projectRoot,
|
|
6543
|
+
packageName: "@tradejs/node",
|
|
6544
|
+
manifest: packageManifest
|
|
6545
|
+
})
|
|
6546
|
+
]);
|
|
6547
|
+
const parsedConfig = strategyEntry.parseConfig(declaration.config);
|
|
6548
|
+
if (!isRecord(parsedConfig)) {
|
|
6549
|
+
throw new Error(
|
|
6550
|
+
`Strategy config parser returned a non-object: ${strategyName}`
|
|
6551
|
+
);
|
|
6552
|
+
}
|
|
6553
|
+
const strategyConfig = parsedConfig;
|
|
6554
|
+
const selection = resolveStrategySelection({
|
|
6555
|
+
deployment,
|
|
6556
|
+
strategy: declaration
|
|
6557
|
+
});
|
|
6558
|
+
return {
|
|
6559
|
+
strategyName,
|
|
6560
|
+
strategyRevision: computeStrategyRevision({
|
|
6561
|
+
strategyName,
|
|
6562
|
+
strategyPackage: strategyPackage.name,
|
|
6563
|
+
strategyPackageVersion,
|
|
6564
|
+
strategyDependencyVersions,
|
|
6565
|
+
runtimePackageVersion,
|
|
6566
|
+
strategyConfig
|
|
6567
|
+
}),
|
|
6568
|
+
...declaration.generation ? { generation: declaration.generation } : {},
|
|
6569
|
+
enabled: declaration.enabled,
|
|
6570
|
+
interval: String(strategyConfig.INTERVAL),
|
|
6571
|
+
universe: strategyConfig.UNIVERSE,
|
|
6572
|
+
strategyPackage: strategyPackage.name,
|
|
6573
|
+
strategyPackageVersion,
|
|
6574
|
+
strategyDependencyVersions,
|
|
6575
|
+
runtimePackageVersion,
|
|
6576
|
+
strategyCreator,
|
|
6577
|
+
sourceStrategyConfig: declaration.config,
|
|
6578
|
+
strategyConfig,
|
|
6579
|
+
...selection ? { selection } : {}
|
|
6580
|
+
};
|
|
6581
|
+
};
|
|
6582
|
+
var resolveRuntimeComposition = async ({
|
|
6583
|
+
projectRoot
|
|
6584
|
+
}) => {
|
|
6585
|
+
const [runtime, packageManifest] = await Promise.all([
|
|
6586
|
+
loadRuntimeDeclaration(projectRoot),
|
|
6587
|
+
readRuntimePackageManifest(projectRoot)
|
|
6588
|
+
]);
|
|
6589
|
+
const deployments = await Promise.all(
|
|
6590
|
+
Object.entries(runtime.deployments).map(
|
|
6591
|
+
async ([deploymentId, declaration]) => {
|
|
6592
|
+
const strategies2 = await Promise.all(
|
|
6593
|
+
Object.entries(declaration.strategies).map(
|
|
6594
|
+
([strategyName, strategyDeclaration]) => resolveStrategyComposition({
|
|
6595
|
+
strategyName,
|
|
6596
|
+
declaration: strategyDeclaration,
|
|
6597
|
+
deployment: declaration,
|
|
6598
|
+
projectRoot,
|
|
6599
|
+
packageManifest
|
|
6600
|
+
})
|
|
6601
|
+
)
|
|
6602
|
+
);
|
|
6603
|
+
const provider = (declaration.provider || declaration.connectorName).trim().toLowerCase();
|
|
6604
|
+
return {
|
|
6605
|
+
deploymentId,
|
|
6606
|
+
deploymentCompositionId: computeDeploymentCompositionId({
|
|
6607
|
+
deploymentId,
|
|
6608
|
+
connectorName: declaration.connectorName.trim(),
|
|
6609
|
+
provider,
|
|
6610
|
+
accountId: declaration.accountId.trim(),
|
|
6611
|
+
enabled: declaration.enabled ?? true,
|
|
6612
|
+
...declaration.assetClasses ? { assetClasses: declaration.assetClasses } : {},
|
|
6613
|
+
strategies: strategies2.map((strategy) => ({
|
|
6614
|
+
strategyName: strategy.strategyName,
|
|
6615
|
+
strategyRevision: strategy.strategyRevision,
|
|
6616
|
+
enabled: strategy.enabled,
|
|
6617
|
+
...strategy.selection ? { selection: strategy.selection } : {}
|
|
6618
|
+
}))
|
|
6619
|
+
}),
|
|
6620
|
+
declaration,
|
|
6621
|
+
strategies: strategies2
|
|
6622
|
+
};
|
|
6623
|
+
}
|
|
6624
|
+
)
|
|
6625
|
+
);
|
|
6626
|
+
return {
|
|
6627
|
+
deployments: deployments.sort(
|
|
6628
|
+
(left, right) => left.deploymentId.localeCompare(right.deploymentId)
|
|
6629
|
+
)
|
|
6630
|
+
};
|
|
6631
|
+
};
|
|
6632
|
+
var toRuntimeDeployment = ({
|
|
6633
|
+
composition,
|
|
6363
6634
|
controls
|
|
6364
6635
|
}) => {
|
|
6636
|
+
const { declaration, deploymentId } = composition;
|
|
6365
6637
|
const deploymentEnabled = declaration.enabled ?? true;
|
|
6366
6638
|
return {
|
|
6367
|
-
id,
|
|
6368
|
-
|
|
6639
|
+
id: deploymentId,
|
|
6640
|
+
deploymentCompositionId: composition.deploymentCompositionId,
|
|
6641
|
+
label: declaration.label?.trim() || deploymentId,
|
|
6369
6642
|
connectorName: declaration.connectorName.trim(),
|
|
6370
6643
|
provider: (declaration.provider || declaration.connectorName).trim().toLowerCase(),
|
|
6371
6644
|
accountId: declaration.accountId.trim(),
|
|
6372
6645
|
enabled: deploymentEnabled,
|
|
6373
|
-
strategies:
|
|
6374
|
-
|
|
6375
|
-
|
|
6376
|
-
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
|
|
6380
|
-
strategyName,
|
|
6381
|
-
version: strategy.version,
|
|
6382
|
-
enabled: strategy.enabled,
|
|
6383
|
-
controlState: deploymentEnabled && strategy.enabled && !controls.deployments[id]?.[strategyName]?.entriesPaused ? "active" : "entries_paused",
|
|
6384
|
-
...selection ? { selection } : {}
|
|
6385
|
-
};
|
|
6386
|
-
}
|
|
6387
|
-
),
|
|
6646
|
+
strategies: composition.strategies.map((strategy) => ({
|
|
6647
|
+
strategyName: strategy.strategyName,
|
|
6648
|
+
strategyRevision: strategy.strategyRevision,
|
|
6649
|
+
enabled: strategy.enabled,
|
|
6650
|
+
controlState: deploymentEnabled && strategy.enabled && !controls.deployments[deploymentId]?.[strategy.strategyName]?.entriesPaused ? "active" : "entries_paused",
|
|
6651
|
+
...strategy.selection ? { selection: strategy.selection } : {}
|
|
6652
|
+
})),
|
|
6388
6653
|
...declaration.assetClasses ? { assetClasses: declaration.assetClasses } : {},
|
|
6389
6654
|
...declaration.tickers ? { tickers: declaration.tickers } : {}
|
|
6390
6655
|
};
|
|
6391
6656
|
};
|
|
6392
|
-
var loadRuntimeDeclaration = async (projectRoot) => {
|
|
6393
|
-
const projectConfig = await loadTradejsConfig(projectRoot);
|
|
6394
|
-
if (!projectConfig.runtime) {
|
|
6395
|
-
throw new Error("Runtime declaration is required in tradejs.config.ts");
|
|
6396
|
-
}
|
|
6397
|
-
return verifyRuntimeDeclaration(projectConfig.runtime);
|
|
6398
|
-
};
|
|
6399
6657
|
var listRuntimeDeployments = async ({
|
|
6400
6658
|
userName,
|
|
6401
6659
|
projectRoot
|
|
6402
6660
|
}) => {
|
|
6403
|
-
const [
|
|
6404
|
-
|
|
6661
|
+
const [composition, controls] = await Promise.all([
|
|
6662
|
+
resolveRuntimeComposition({ projectRoot }),
|
|
6405
6663
|
(0, import_runtimeControls.getRuntimeControls)(userName)
|
|
6406
6664
|
]);
|
|
6407
|
-
return
|
|
6408
|
-
(
|
|
6665
|
+
return composition.deployments.map(
|
|
6666
|
+
(deploymentComposition) => toRuntimeDeployment({ composition: deploymentComposition, controls })
|
|
6409
6667
|
).sort((left, right) => left.label.localeCompare(right.label));
|
|
6410
6668
|
};
|
|
6411
6669
|
var getRuntimeDeployment = async ({
|
|
@@ -6440,87 +6698,37 @@ var loadResolvedRuntimeStrategies = async ({
|
|
|
6440
6698
|
accountId,
|
|
6441
6699
|
interval
|
|
6442
6700
|
}) => {
|
|
6443
|
-
const [
|
|
6444
|
-
|
|
6445
|
-
(0, import_runtimeControls.getRuntimeControls)(userName)
|
|
6446
|
-
readPackageManifest(projectRoot)
|
|
6701
|
+
const [composition, controls] = await Promise.all([
|
|
6702
|
+
resolveRuntimeComposition({ projectRoot }),
|
|
6703
|
+
(0, import_runtimeControls.getRuntimeControls)(userName)
|
|
6447
6704
|
]);
|
|
6448
|
-
const
|
|
6449
|
-
|
|
6705
|
+
const deploymentComposition = composition.deployments.find(
|
|
6706
|
+
(candidate) => candidate.deploymentId === deploymentId
|
|
6707
|
+
);
|
|
6708
|
+
if (!deploymentComposition) {
|
|
6450
6709
|
throw new Error(`Runtime deployment not found: ${deploymentId}`);
|
|
6451
6710
|
}
|
|
6452
6711
|
const deployment = toRuntimeDeployment({
|
|
6453
|
-
|
|
6454
|
-
declaration,
|
|
6712
|
+
composition: deploymentComposition,
|
|
6455
6713
|
controls
|
|
6456
6714
|
});
|
|
6457
6715
|
const strategies2 = await Promise.all(
|
|
6458
|
-
|
|
6459
|
-
|
|
6460
|
-
|
|
6461
|
-
|
|
6462
|
-
|
|
6463
|
-
|
|
6464
|
-
|
|
6465
|
-
|
|
6466
|
-
|
|
6467
|
-
|
|
6468
|
-
|
|
6469
|
-
|
|
6470
|
-
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
|
|
6474
|
-
projectRoot,
|
|
6475
|
-
strategyPackage,
|
|
6476
|
-
packageManifest
|
|
6477
|
-
),
|
|
6478
|
-
resolveInstalledPackageVersion(
|
|
6479
|
-
projectRoot,
|
|
6480
|
-
"@tradejs/node",
|
|
6481
|
-
packageManifest
|
|
6482
|
-
)
|
|
6483
|
-
]);
|
|
6484
|
-
if (!strategyPackage || !strategyPackageVersion) {
|
|
6485
|
-
throw new Error(
|
|
6486
|
-
`Installed strategy package not found: ${strategyName}`
|
|
6487
|
-
);
|
|
6488
|
-
}
|
|
6489
|
-
if (!runtimePackageVersion) {
|
|
6490
|
-
throw new Error("Installed @tradejs/node package version not found");
|
|
6491
|
-
}
|
|
6492
|
-
const strategyView = deployment.strategies.find(
|
|
6493
|
-
(candidate) => candidate.strategyName === strategyName
|
|
6494
|
-
);
|
|
6495
|
-
const selection = resolveStrategySelection({
|
|
6496
|
-
deployment: declaration,
|
|
6497
|
-
strategy: strategyDeclaration
|
|
6498
|
-
});
|
|
6499
|
-
const strategyConfig = strategyDeclaration.config;
|
|
6500
|
-
const strategyUniverse = strategyConfig.UNIVERSE;
|
|
6501
|
-
const resolvedAccountId = await resolveAccountId({
|
|
6502
|
-
userName,
|
|
6503
|
-
deployment,
|
|
6504
|
-
universe: strategyUniverse
|
|
6505
|
-
});
|
|
6506
|
-
return {
|
|
6507
|
-
strategyName,
|
|
6508
|
-
version: strategyDeclaration.version,
|
|
6509
|
-
enabled: strategyDeclaration.enabled,
|
|
6510
|
-
controlState: strategyView?.controlState ?? "entries_paused",
|
|
6511
|
-
interval: String(strategyConfig.INTERVAL),
|
|
6512
|
-
universe: strategyUniverse,
|
|
6513
|
-
accountId: resolvedAccountId,
|
|
6514
|
-
strategyPackage,
|
|
6515
|
-
strategyPackageVersion,
|
|
6516
|
-
runtimePackageVersion,
|
|
6517
|
-
strategyCreator,
|
|
6518
|
-
sourceStrategyConfig: strategyConfig,
|
|
6519
|
-
strategyConfig,
|
|
6520
|
-
...selection ? { selection } : {}
|
|
6521
|
-
};
|
|
6522
|
-
}
|
|
6523
|
-
)
|
|
6716
|
+
deploymentComposition.strategies.map(async (strategy) => {
|
|
6717
|
+
const strategyView = deployment.strategies.find(
|
|
6718
|
+
(candidate) => candidate.strategyName === strategy.strategyName
|
|
6719
|
+
);
|
|
6720
|
+
const resolvedAccountId = await resolveAccountId({
|
|
6721
|
+
userName,
|
|
6722
|
+
deployment,
|
|
6723
|
+
universe: strategy.universe
|
|
6724
|
+
});
|
|
6725
|
+
return {
|
|
6726
|
+
...strategy,
|
|
6727
|
+
deploymentCompositionId: deploymentComposition.deploymentCompositionId,
|
|
6728
|
+
accountId: resolvedAccountId,
|
|
6729
|
+
controlState: strategyView?.controlState ?? "entries_paused"
|
|
6730
|
+
};
|
|
6731
|
+
})
|
|
6524
6732
|
);
|
|
6525
6733
|
const filtered = strategies2.filter(
|
|
6526
6734
|
(candidate) => (!universe || candidate.universe === universe) && (!interval || String(candidate.interval) === String(interval)) && (!accountId || candidate.accountId === accountId)
|
|
@@ -6539,31 +6747,55 @@ var getRuntimeStrategyPackageMetadata = async ({
|
|
|
6539
6747
|
strategyName,
|
|
6540
6748
|
projectRoot
|
|
6541
6749
|
}) => {
|
|
6542
|
-
const packageManifest = await
|
|
6543
|
-
|
|
6544
|
-
|
|
6545
|
-
|
|
6750
|
+
const [packageManifest, pluginSource] = await Promise.all([
|
|
6751
|
+
readRuntimePackageManifest(projectRoot),
|
|
6752
|
+
getStrategyPluginSource(strategyName, projectRoot)
|
|
6753
|
+
]);
|
|
6754
|
+
const strategyPackage = await resolveStrategyPackage({
|
|
6755
|
+
pluginSource: pluginSource ?? null,
|
|
6546
6756
|
projectRoot
|
|
6547
6757
|
});
|
|
6548
|
-
|
|
6549
|
-
|
|
6550
|
-
|
|
6758
|
+
if (!strategyPackage) {
|
|
6759
|
+
throw new Error(`Installed strategy package not found: ${strategyName}`);
|
|
6760
|
+
}
|
|
6761
|
+
const [
|
|
6762
|
+
strategyPackageVersion,
|
|
6763
|
+
strategyDependencyVersions,
|
|
6764
|
+
runtimePackageVersion
|
|
6765
|
+
] = await Promise.all([
|
|
6766
|
+
resolveVerifiedPackageVersion({
|
|
6767
|
+
projectRoot,
|
|
6768
|
+
packageName: strategyPackage.name,
|
|
6769
|
+
projectPackage: strategyPackage.projectPackage,
|
|
6770
|
+
manifest: packageManifest
|
|
6771
|
+
}),
|
|
6772
|
+
resolveVerifiedStrategyDependencyVersions({
|
|
6551
6773
|
projectRoot,
|
|
6552
6774
|
strategyPackage,
|
|
6553
|
-
packageManifest
|
|
6554
|
-
),
|
|
6555
|
-
|
|
6775
|
+
manifest: packageManifest
|
|
6776
|
+
}),
|
|
6777
|
+
resolveVerifiedPackageVersion({
|
|
6556
6778
|
projectRoot,
|
|
6557
|
-
"@tradejs/node",
|
|
6558
|
-
packageManifest
|
|
6559
|
-
)
|
|
6779
|
+
packageName: "@tradejs/node",
|
|
6780
|
+
manifest: packageManifest
|
|
6781
|
+
})
|
|
6782
|
+
]);
|
|
6783
|
+
return {
|
|
6784
|
+
strategyPackage: strategyPackage.name,
|
|
6785
|
+
strategyPackageVersion,
|
|
6786
|
+
strategyDependencyVersions,
|
|
6787
|
+
runtimePackageVersion
|
|
6560
6788
|
};
|
|
6561
6789
|
};
|
|
6562
6790
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6563
6791
|
0 && (module.exports = {
|
|
6792
|
+
RUNTIME_PACKAGE_MANIFEST_SCHEMA,
|
|
6793
|
+
computeDeploymentCompositionId,
|
|
6794
|
+
computeStrategyRevision,
|
|
6564
6795
|
getRuntimeDeployment,
|
|
6565
6796
|
getRuntimeStrategyPackageMetadata,
|
|
6566
6797
|
listRuntimeDeployments,
|
|
6567
6798
|
loadResolvedRuntimeStrategies,
|
|
6799
|
+
resolveRuntimeComposition,
|
|
6568
6800
|
verifyRuntimeDeclaration
|
|
6569
6801
|
});
|