@tradejs/cli 3.1.2 → 3.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +173 -187
- package/dist/scripts/backtest.js +4 -20
- package/dist/scripts/runtimeConfig.js +127 -102
- package/dist/scripts/signals.js +43 -63
- package/dist/scripts/signalsDaemon.js +43 -63
- package/dist/scripts/signalsSummary.js +1 -1
- package/package.json +7 -7
package/dist/cli.js
CHANGED
|
@@ -13668,8 +13668,7 @@ var init_runnerCore = __esm({
|
|
|
13668
13668
|
};
|
|
13669
13669
|
validateBacktestRuntimeDeployment = ({
|
|
13670
13670
|
deployment,
|
|
13671
|
-
deploymentId
|
|
13672
|
-
requestedInterval
|
|
13671
|
+
deploymentId
|
|
13673
13672
|
}) => {
|
|
13674
13673
|
if (deploymentId && !deployment) {
|
|
13675
13674
|
throw new Error(`Runtime deployment not found: ${deploymentId}`);
|
|
@@ -13677,18 +13676,12 @@ var init_runnerCore = __esm({
|
|
|
13677
13676
|
if (deployment && !deployment.enabled) {
|
|
13678
13677
|
throw new Error(`Runtime deployment is disabled: ${deployment.id}`);
|
|
13679
13678
|
}
|
|
13680
|
-
if (deployment && String(deployment.interval) !== String(requestedInterval)) {
|
|
13681
|
-
throw new Error(
|
|
13682
|
-
`Deployment ${deployment.id} requires timeframe ${deployment.interval}; received ${requestedInterval}`
|
|
13683
|
-
);
|
|
13684
|
-
}
|
|
13685
13679
|
return deployment;
|
|
13686
13680
|
};
|
|
13687
13681
|
prepareRunEnvironment2 = async () => {
|
|
13688
13682
|
const deployment = validateBacktestRuntimeDeployment({
|
|
13689
13683
|
deployment: flags5.deployment ? await (0, import_runtimeDeployments.getRuntimeDeployment)(userName, String(flags5.deployment)) : null,
|
|
13690
|
-
deploymentId: typeof flags5.deployment === "string" ? flags5.deployment : void 0
|
|
13691
|
-
requestedInterval: interval
|
|
13684
|
+
deploymentId: typeof flags5.deployment === "string" ? flags5.deployment : void 0
|
|
13692
13685
|
});
|
|
13693
13686
|
const preparedRun = await prepareRunEnvironment({
|
|
13694
13687
|
connector: deployment?.connectorName ?? flags5.connector,
|
|
@@ -13703,7 +13696,7 @@ var init_runnerCore = __esm({
|
|
|
13703
13696
|
cacheOnly: flags5.cacheOnly,
|
|
13704
13697
|
interval,
|
|
13705
13698
|
projectRoot: projectRoot3,
|
|
13706
|
-
universe:
|
|
13699
|
+
universe: marketUniverse,
|
|
13707
13700
|
accountId: deployment?.accountId ?? flags5.account,
|
|
13708
13701
|
deploymentId: deployment?.id,
|
|
13709
13702
|
assetClasses: deployment?.assetClasses,
|
|
@@ -14409,15 +14402,7 @@ var init_backtest = __esm({
|
|
|
14409
14402
|
preparedRun.connectorName,
|
|
14410
14403
|
interval
|
|
14411
14404
|
).map((test) => {
|
|
14412
|
-
const
|
|
14413
|
-
({ strategyName }) => strategyName === config2.strategyName
|
|
14414
|
-
);
|
|
14415
|
-
if (deploymentStrategy?.enabled === false) {
|
|
14416
|
-
throw new Error(
|
|
14417
|
-
`Strategy ${config2.strategyName} is disabled in deployment ${preparedRun.deployment?.id}`
|
|
14418
|
-
);
|
|
14419
|
-
}
|
|
14420
|
-
const policyProfileId = (typeof flags5.policyProfile === "string" && flags5.policyProfile.trim() ? flags5.policyProfile.trim() : deploymentStrategy?.policyProfileId) || void 0;
|
|
14405
|
+
const policyProfileId = (typeof flags5.policyProfile === "string" && flags5.policyProfile.trim() ? flags5.policyProfile.trim() : void 0) || void 0;
|
|
14421
14406
|
return {
|
|
14422
14407
|
...test,
|
|
14423
14408
|
instrument: preparedRun.instrumentsBySymbol.get(
|
|
@@ -14429,7 +14414,6 @@ var init_backtest = __esm({
|
|
|
14429
14414
|
policyProfileId,
|
|
14430
14415
|
strategyConfig: {
|
|
14431
14416
|
...test.strategyConfig,
|
|
14432
|
-
...deploymentStrategy?.config,
|
|
14433
14417
|
...policyProfileId ? { POLICY_PROFILE_ID: policyProfileId } : {}
|
|
14434
14418
|
}
|
|
14435
14419
|
};
|
|
@@ -28101,23 +28085,35 @@ var init_runtimeScorecard2 = __esm({
|
|
|
28101
28085
|
// src/scripts/runtimeConfig.ts
|
|
28102
28086
|
var runtimeConfig_exports = {};
|
|
28103
28087
|
__export(runtimeConfig_exports, {
|
|
28104
|
-
|
|
28088
|
+
RUNTIME_CONFIG_ACTIONS: () => RUNTIME_CONFIG_ACTIONS,
|
|
28089
|
+
buildProvisionedRuntimeDeployment: () => buildProvisionedRuntimeDeployment,
|
|
28090
|
+
isEquivalentRuntimeStrategyRelease: () => isEquivalentRuntimeStrategyRelease,
|
|
28105
28091
|
main: () => main37,
|
|
28092
|
+
pointRuntimeDeploymentAtRelease: () => pointRuntimeDeploymentAtRelease,
|
|
28106
28093
|
runtimeConfig: () => runtimeConfig
|
|
28107
28094
|
});
|
|
28108
|
-
var import_config9, import_promises28, import_node_path23,
|
|
28095
|
+
var import_config9, import_promises28, import_node_path23, import_node_util2, import_runtimeDeployments2, import_runtimeStrategyReleases, import_runtimeStrategies, import_strategies11, argv, RUNTIME_CONFIG_ACTIONS, action, option, hasFlag, required2, projectRoot12, userName2, OPERATIONAL_CONFIG_KEYS, requireRuntimePackageIdentity, toReleaseConfig, publish, buildProvisionedRuntimeDeployment, isEquivalentRuntimeStrategyRelease, pointRuntimeDeploymentAtRelease, provision, rollout, updateControlState, rollback, verify, inspect, runtimeConfig, main37;
|
|
28109
28096
|
var init_runtimeConfig = __esm({
|
|
28110
28097
|
"src/scripts/runtimeConfig.ts"() {
|
|
28111
28098
|
"use strict";
|
|
28112
28099
|
import_config9 = require("dotenv/config");
|
|
28113
28100
|
import_promises28 = require("fs/promises");
|
|
28114
28101
|
import_node_path23 = __toESM(require("path"));
|
|
28102
|
+
import_node_util2 = require("util");
|
|
28115
28103
|
import_runtimeDeployments2 = require("@tradejs/infra/runtimeDeployments");
|
|
28116
|
-
import_runtimeStrategyConfigs2 = require("@tradejs/infra/runtimeStrategyConfigs");
|
|
28117
28104
|
import_runtimeStrategyReleases = require("@tradejs/infra/runtimeStrategyReleases");
|
|
28118
28105
|
import_runtimeStrategies = require("@tradejs/node/runtimeStrategies");
|
|
28119
28106
|
import_strategies11 = require("@tradejs/node/strategies");
|
|
28120
28107
|
argv = process.argv.slice(2);
|
|
28108
|
+
RUNTIME_CONFIG_ACTIONS = [
|
|
28109
|
+
"inspect",
|
|
28110
|
+
"verify",
|
|
28111
|
+
"provision",
|
|
28112
|
+
"rollout",
|
|
28113
|
+
"pause",
|
|
28114
|
+
"resume",
|
|
28115
|
+
"rollback"
|
|
28116
|
+
];
|
|
28121
28117
|
action = argv[0] ?? "inspect";
|
|
28122
28118
|
option = (name) => {
|
|
28123
28119
|
const index = argv.indexOf(`--${name}`);
|
|
@@ -28138,28 +28134,26 @@ var init_runtimeConfig = __esm({
|
|
|
28138
28134
|
"ENABLE",
|
|
28139
28135
|
"ENV",
|
|
28140
28136
|
"MAKE_ORDERS",
|
|
28141
|
-
"RECORD_RUNTIME_TRADES"
|
|
28142
|
-
"configId"
|
|
28137
|
+
"RECORD_RUNTIME_TRADES"
|
|
28143
28138
|
];
|
|
28139
|
+
requireRuntimePackageIdentity = (strategyName, metadata) => {
|
|
28140
|
+
if (!metadata.strategyPackage || !metadata.strategyPackageVersion || !metadata.runtimePackageVersion) {
|
|
28141
|
+
throw new Error(
|
|
28142
|
+
`Runtime package manifest is incomplete for ${strategyName}`
|
|
28143
|
+
);
|
|
28144
|
+
}
|
|
28145
|
+
return {
|
|
28146
|
+
strategyPackage: metadata.strategyPackage,
|
|
28147
|
+
strategyPackageVersion: metadata.strategyPackageVersion,
|
|
28148
|
+
runtimePackageVersion: metadata.runtimePackageVersion
|
|
28149
|
+
};
|
|
28150
|
+
};
|
|
28144
28151
|
toReleaseConfig = async (strategyName, sourceConfig) => {
|
|
28145
28152
|
const defaults = await (0, import_strategies11.getStrategyDefaults)(strategyName, projectRoot12) ?? {};
|
|
28146
28153
|
const config2 = { ...defaults, ...sourceConfig };
|
|
28147
28154
|
for (const key of OPERATIONAL_CONFIG_KEYS) delete config2[key];
|
|
28148
28155
|
return config2;
|
|
28149
28156
|
};
|
|
28150
|
-
writeMigrationBackup = async (payload) => {
|
|
28151
|
-
const directory = import_node_path23.default.join(projectRoot12, "data", "runtime-config-backups");
|
|
28152
|
-
await (0, import_promises28.mkdir)(directory, { recursive: true });
|
|
28153
|
-
const backupPath = import_node_path23.default.join(
|
|
28154
|
-
directory,
|
|
28155
|
-
`${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.json`
|
|
28156
|
-
);
|
|
28157
|
-
await (0, import_promises28.writeFile)(backupPath, `${JSON.stringify(payload, null, 2)}
|
|
28158
|
-
`, {
|
|
28159
|
-
flag: "wx"
|
|
28160
|
-
});
|
|
28161
|
-
return backupPath;
|
|
28162
|
-
};
|
|
28163
28157
|
publish = async ({
|
|
28164
28158
|
strategyName,
|
|
28165
28159
|
sourceConfig
|
|
@@ -28169,31 +28163,29 @@ var init_runtimeConfig = __esm({
|
|
|
28169
28163
|
strategyName,
|
|
28170
28164
|
projectRoot: projectRoot12
|
|
28171
28165
|
});
|
|
28166
|
+
const packageIdentity = requireRuntimePackageIdentity(strategyName, metadata);
|
|
28172
28167
|
return (0, import_runtimeStrategyReleases.publishRuntimeStrategyRelease)({
|
|
28173
28168
|
userName: userName2,
|
|
28174
28169
|
strategyName,
|
|
28175
28170
|
config: config2,
|
|
28176
|
-
...
|
|
28171
|
+
...packageIdentity,
|
|
28177
28172
|
createdBy: `cli:${userName2}`
|
|
28178
28173
|
});
|
|
28179
28174
|
};
|
|
28180
|
-
|
|
28175
|
+
buildProvisionedRuntimeDeployment = ({
|
|
28181
28176
|
deploymentId,
|
|
28182
28177
|
label,
|
|
28183
28178
|
connectorName,
|
|
28184
28179
|
provider,
|
|
28185
28180
|
accountId,
|
|
28186
28181
|
strategyName,
|
|
28187
|
-
releaseVersion
|
|
28188
|
-
config: config2
|
|
28182
|
+
releaseVersion
|
|
28189
28183
|
}) => ({
|
|
28190
28184
|
id: deploymentId,
|
|
28191
28185
|
label,
|
|
28192
28186
|
connectorName,
|
|
28193
28187
|
provider,
|
|
28194
28188
|
accountId,
|
|
28195
|
-
universe: config2.UNIVERSE,
|
|
28196
|
-
interval: String(config2.INTERVAL),
|
|
28197
28189
|
enabled: true,
|
|
28198
28190
|
strategies: [
|
|
28199
28191
|
{
|
|
@@ -28203,7 +28195,30 @@ var init_runtimeConfig = __esm({
|
|
|
28203
28195
|
}
|
|
28204
28196
|
]
|
|
28205
28197
|
});
|
|
28206
|
-
|
|
28198
|
+
isEquivalentRuntimeStrategyRelease = ({
|
|
28199
|
+
release,
|
|
28200
|
+
config: config2,
|
|
28201
|
+
strategyPackage,
|
|
28202
|
+
strategyPackageVersion,
|
|
28203
|
+
runtimePackageVersion
|
|
28204
|
+
}) => Boolean(
|
|
28205
|
+
release && (0, import_node_util2.isDeepStrictEqual)(release.config, config2) && release.strategyPackage === strategyPackage && release.strategyPackageVersion === strategyPackageVersion && release.runtimePackageVersion === runtimePackageVersion
|
|
28206
|
+
);
|
|
28207
|
+
pointRuntimeDeploymentAtRelease = ({
|
|
28208
|
+
deployment,
|
|
28209
|
+
strategyName,
|
|
28210
|
+
releaseVersion
|
|
28211
|
+
}) => ({
|
|
28212
|
+
...deployment,
|
|
28213
|
+
strategies: deployment.strategies.map(
|
|
28214
|
+
(strategy) => strategy.strategyName === strategyName ? {
|
|
28215
|
+
strategyName,
|
|
28216
|
+
releaseVersion,
|
|
28217
|
+
controlState: "entries_paused"
|
|
28218
|
+
} : strategy
|
|
28219
|
+
)
|
|
28220
|
+
});
|
|
28221
|
+
provision = async () => {
|
|
28207
28222
|
const strategyName = required2("strategy");
|
|
28208
28223
|
const deploymentId = required2("deployment");
|
|
28209
28224
|
const accountId = required2("account");
|
|
@@ -28221,15 +28236,14 @@ var init_runtimeConfig = __esm({
|
|
|
28221
28236
|
);
|
|
28222
28237
|
}
|
|
28223
28238
|
const releaseConfig = await toReleaseConfig(strategyName, sourceConfig);
|
|
28224
|
-
const previewDeployment =
|
|
28239
|
+
const previewDeployment = buildProvisionedRuntimeDeployment({
|
|
28225
28240
|
deploymentId,
|
|
28226
28241
|
label,
|
|
28227
28242
|
connectorName,
|
|
28228
28243
|
provider,
|
|
28229
28244
|
accountId,
|
|
28230
28245
|
strategyName,
|
|
28231
|
-
releaseVersion: 1
|
|
28232
|
-
config: releaseConfig
|
|
28246
|
+
releaseVersion: 1
|
|
28233
28247
|
});
|
|
28234
28248
|
if (!hasFlag("write")) {
|
|
28235
28249
|
console.log(
|
|
@@ -28251,102 +28265,103 @@ var init_runtimeConfig = __esm({
|
|
|
28251
28265
|
);
|
|
28252
28266
|
return;
|
|
28253
28267
|
}
|
|
28254
|
-
const backupPath = await writeMigrationBackup({
|
|
28255
|
-
userName: userName2,
|
|
28256
|
-
capturedAt: Date.now(),
|
|
28257
|
-
reason: "bootstrap",
|
|
28258
|
-
sourceConfig
|
|
28259
|
-
});
|
|
28260
28268
|
const release = await publish({ strategyName, sourceConfig });
|
|
28261
28269
|
const deployment = await (0, import_runtimeDeployments2.saveRuntimeDeployment)(
|
|
28262
28270
|
userName2,
|
|
28263
|
-
|
|
28271
|
+
buildProvisionedRuntimeDeployment({
|
|
28264
28272
|
deploymentId,
|
|
28265
28273
|
label,
|
|
28266
28274
|
connectorName,
|
|
28267
28275
|
provider,
|
|
28268
28276
|
accountId,
|
|
28269
28277
|
strategyName,
|
|
28270
|
-
releaseVersion: release.releaseVersion
|
|
28271
|
-
config: release.config
|
|
28278
|
+
releaseVersion: release.releaseVersion
|
|
28272
28279
|
})
|
|
28273
28280
|
);
|
|
28274
28281
|
console.log(
|
|
28275
|
-
JSON.stringify(
|
|
28276
|
-
{ bootstrapped: true, backupPath, release, deployment },
|
|
28277
|
-
null,
|
|
28278
|
-
2
|
|
28279
|
-
)
|
|
28282
|
+
JSON.stringify({ provisioned: true, release, deployment }, null, 2)
|
|
28280
28283
|
);
|
|
28281
28284
|
};
|
|
28282
|
-
|
|
28285
|
+
rollout = async () => {
|
|
28283
28286
|
const strategyName = required2("strategy");
|
|
28284
|
-
const configId = option("config") ?? "config";
|
|
28285
28287
|
const deploymentId = required2("deployment");
|
|
28286
|
-
const
|
|
28287
|
-
|
|
28288
|
-
(0, import_runtimeDeployments2.getRuntimeDeployment)(userName2, deploymentId)
|
|
28288
|
+
const configFile = import_node_path23.default.resolve(projectRoot12, required2("file"));
|
|
28289
|
+
const [deployment, sourceConfig] = await Promise.all([
|
|
28290
|
+
(0, import_runtimeDeployments2.getRuntimeDeployment)(userName2, deploymentId),
|
|
28291
|
+
(0, import_promises28.readFile)(configFile, "utf8").then(
|
|
28292
|
+
(value) => JSON.parse(value)
|
|
28293
|
+
)
|
|
28289
28294
|
]);
|
|
28290
|
-
if (!sourceConfig) {
|
|
28291
|
-
throw new Error(`Legacy config not found: ${strategyName}:${configId}`);
|
|
28292
|
-
}
|
|
28293
28295
|
if (!deployment) throw new Error(`Deployment not found: ${deploymentId}`);
|
|
28294
28296
|
const reference = deployment.strategies.find(
|
|
28295
28297
|
(strategy) => strategy.strategyName === strategyName
|
|
28296
28298
|
);
|
|
28297
|
-
if (!reference)
|
|
28299
|
+
if (!reference)
|
|
28298
28300
|
throw new Error(`${strategyName} is not bound to ${deploymentId}`);
|
|
28299
|
-
|
|
28301
|
+
const [config2, metadata, currentRelease] = await Promise.all([
|
|
28302
|
+
toReleaseConfig(strategyName, sourceConfig),
|
|
28303
|
+
(0, import_runtimeStrategies.getRuntimeStrategyPackageMetadata)({ strategyName, projectRoot: projectRoot12 }),
|
|
28304
|
+
(0, import_runtimeStrategyReleases.getRuntimeStrategyRelease)(userName2, strategyName, reference.releaseVersion)
|
|
28305
|
+
]);
|
|
28306
|
+
const packageIdentity = requireRuntimePackageIdentity(strategyName, metadata);
|
|
28307
|
+
const unchanged = isEquivalentRuntimeStrategyRelease({
|
|
28308
|
+
release: currentRelease,
|
|
28309
|
+
config: config2,
|
|
28310
|
+
...packageIdentity
|
|
28311
|
+
});
|
|
28300
28312
|
const preview = {
|
|
28301
|
-
|
|
28302
|
-
|
|
28303
|
-
|
|
28304
|
-
|
|
28305
|
-
|
|
28306
|
-
|
|
28307
|
-
|
|
28308
|
-
releaseVersion: "<allocated on write>",
|
|
28309
|
-
controlState: "entries_paused"
|
|
28310
|
-
}
|
|
28311
|
-
}
|
|
28313
|
+
deploymentId,
|
|
28314
|
+
strategyName,
|
|
28315
|
+
currentReleaseVersion: reference.releaseVersion,
|
|
28316
|
+
nextControlState: "entries_paused",
|
|
28317
|
+
unchanged,
|
|
28318
|
+
config: config2,
|
|
28319
|
+
...packageIdentity
|
|
28312
28320
|
};
|
|
28313
28321
|
if (!hasFlag("write")) {
|
|
28314
28322
|
console.log(JSON.stringify({ dryRun: true, ...preview }, null, 2));
|
|
28315
28323
|
return;
|
|
28316
28324
|
}
|
|
28317
|
-
|
|
28325
|
+
if (unchanged) {
|
|
28326
|
+
console.log(
|
|
28327
|
+
JSON.stringify(
|
|
28328
|
+
{
|
|
28329
|
+
rolledOut: false,
|
|
28330
|
+
reason: "release_config_and_packages_unchanged",
|
|
28331
|
+
release: currentRelease,
|
|
28332
|
+
deployment
|
|
28333
|
+
},
|
|
28334
|
+
null,
|
|
28335
|
+
2
|
|
28336
|
+
)
|
|
28337
|
+
);
|
|
28338
|
+
return;
|
|
28339
|
+
}
|
|
28340
|
+
const release = await (0, import_runtimeStrategyReleases.publishRuntimeStrategyRelease)({
|
|
28318
28341
|
userName: userName2,
|
|
28319
|
-
|
|
28342
|
+
strategyName,
|
|
28343
|
+
config: config2,
|
|
28344
|
+
...packageIdentity,
|
|
28345
|
+
createdBy: `cli:${userName2}`
|
|
28346
|
+
});
|
|
28347
|
+
const updatedDeployment = pointRuntimeDeploymentAtRelease({
|
|
28320
28348
|
deployment,
|
|
28321
|
-
|
|
28349
|
+
strategyName,
|
|
28350
|
+
releaseVersion: release.releaseVersion
|
|
28322
28351
|
});
|
|
28323
|
-
const release = await publish({ strategyName, sourceConfig });
|
|
28324
|
-
const updatedDeployment = {
|
|
28325
|
-
...deployment,
|
|
28326
|
-
strategies: deployment.strategies.map(
|
|
28327
|
-
(strategy) => strategy.strategyName === strategyName ? {
|
|
28328
|
-
strategyName,
|
|
28329
|
-
releaseVersion: release.releaseVersion,
|
|
28330
|
-
controlState: "entries_paused"
|
|
28331
|
-
} : strategy
|
|
28332
|
-
)
|
|
28333
|
-
};
|
|
28334
28352
|
await (0, import_runtimeDeployments2.saveRuntimeDeployment)(userName2, updatedDeployment);
|
|
28335
28353
|
console.log(
|
|
28336
28354
|
JSON.stringify(
|
|
28337
|
-
{
|
|
28355
|
+
{
|
|
28356
|
+
rolledOut: true,
|
|
28357
|
+
release,
|
|
28358
|
+
deployment: updatedDeployment
|
|
28359
|
+
},
|
|
28338
28360
|
null,
|
|
28339
28361
|
2
|
|
28340
28362
|
)
|
|
28341
28363
|
);
|
|
28342
28364
|
};
|
|
28343
|
-
publishDraft = async () => {
|
|
28344
|
-
const strategyName = required2("strategy");
|
|
28345
|
-
const draft = await (0, import_runtimeStrategyReleases.getRuntimeStrategyDraft)(userName2, strategyName);
|
|
28346
|
-
if (!draft) throw new Error(`Draft not found: ${strategyName}`);
|
|
28347
|
-
const release = await publish({ strategyName, sourceConfig: draft.config });
|
|
28348
|
-
console.log(JSON.stringify({ release }, null, 2));
|
|
28349
|
-
};
|
|
28350
28365
|
updateControlState = async (nextState) => {
|
|
28351
28366
|
const strategyName = required2("strategy");
|
|
28352
28367
|
const deploymentId = required2("deployment");
|
|
@@ -28355,10 +28370,9 @@ var init_runtimeConfig = __esm({
|
|
|
28355
28370
|
const reference = deployment.strategies.find(
|
|
28356
28371
|
(strategy) => strategy.strategyName === strategyName
|
|
28357
28372
|
);
|
|
28358
|
-
if (!reference
|
|
28359
|
-
throw new Error(`${strategyName} is not
|
|
28360
|
-
|
|
28361
|
-
const previousState = reference.controlState ?? "active";
|
|
28373
|
+
if (!reference)
|
|
28374
|
+
throw new Error(`${strategyName} is not bound to ${deploymentId}`);
|
|
28375
|
+
const previousState = reference.controlState;
|
|
28362
28376
|
const updated = await (0, import_runtimeDeployments2.saveRuntimeDeployment)(userName2, {
|
|
28363
28377
|
...deployment,
|
|
28364
28378
|
strategies: deployment.strategies.map(
|
|
@@ -28388,12 +28402,6 @@ var init_runtimeConfig = __esm({
|
|
|
28388
28402
|
const release = (await (0, import_runtimeStrategyReleases.listRuntimeStrategyReleases)(userName2, strategyName)).find((candidate) => candidate.releaseVersion === releaseVersion);
|
|
28389
28403
|
if (!release)
|
|
28390
28404
|
throw new Error(`Release not found: ${strategyName} v${releaseVersion}`);
|
|
28391
|
-
const backupPath = await writeMigrationBackup({
|
|
28392
|
-
userName: userName2,
|
|
28393
|
-
capturedAt: Date.now(),
|
|
28394
|
-
deployment,
|
|
28395
|
-
reason: "rollback"
|
|
28396
|
-
});
|
|
28397
28405
|
const updated = await (0, import_runtimeDeployments2.saveRuntimeDeployment)(userName2, {
|
|
28398
28406
|
...deployment,
|
|
28399
28407
|
strategies: deployment.strategies.map(
|
|
@@ -28404,7 +28412,7 @@ var init_runtimeConfig = __esm({
|
|
|
28404
28412
|
} : strategy
|
|
28405
28413
|
)
|
|
28406
28414
|
});
|
|
28407
|
-
console.log(JSON.stringify({
|
|
28415
|
+
console.log(JSON.stringify({ deployment: updated }, null, 2));
|
|
28408
28416
|
};
|
|
28409
28417
|
verify = async () => {
|
|
28410
28418
|
const deployments = await (0, import_runtimeDeployments2.listRuntimeDeployments)(userName2);
|
|
@@ -28415,8 +28423,7 @@ var init_runtimeConfig = __esm({
|
|
|
28415
28423
|
const strategies = await (0, import_runtimeStrategies.loadResolvedRuntimeStrategies)({
|
|
28416
28424
|
userName: userName2,
|
|
28417
28425
|
projectRoot: projectRoot12,
|
|
28418
|
-
deployment
|
|
28419
|
-
connectorName: deployment.connectorName
|
|
28426
|
+
deployment
|
|
28420
28427
|
});
|
|
28421
28428
|
results2.push({
|
|
28422
28429
|
deploymentId: deployment.id,
|
|
@@ -28448,16 +28455,15 @@ var init_runtimeConfig = __esm({
|
|
|
28448
28455
|
console.log(JSON.stringify({ userName: userName2, deployments, releases }, null, 2));
|
|
28449
28456
|
};
|
|
28450
28457
|
runtimeConfig = async () => {
|
|
28451
|
-
if (action === "
|
|
28452
|
-
if (action === "
|
|
28453
|
-
if (action === "publish-draft") return publishDraft();
|
|
28458
|
+
if (action === "provision") return provision();
|
|
28459
|
+
if (action === "rollout") return rollout();
|
|
28454
28460
|
if (action === "verify") return verify();
|
|
28455
28461
|
if (action === "pause") return updateControlState("entries_paused");
|
|
28456
28462
|
if (action === "resume") return updateControlState("active");
|
|
28457
28463
|
if (action === "rollback") return rollback();
|
|
28458
28464
|
if (action === "inspect") return inspect();
|
|
28459
28465
|
throw new Error(
|
|
28460
|
-
|
|
28466
|
+
`Usage: tradejs runtime-config ${RUNTIME_CONFIG_ACTIONS.join("|")}`
|
|
28461
28467
|
);
|
|
28462
28468
|
};
|
|
28463
28469
|
main37 = runtimeConfig;
|
|
@@ -32057,18 +32063,15 @@ var init_tickerEvaluator = __esm({
|
|
|
32057
32063
|
for (const runtimeStrategy of runtimeStrategies) {
|
|
32058
32064
|
const {
|
|
32059
32065
|
strategyName,
|
|
32060
|
-
configId,
|
|
32061
32066
|
releaseVersion,
|
|
32062
32067
|
controlState,
|
|
32063
32068
|
strategyPackageVersion,
|
|
32064
32069
|
runtimePackageVersion,
|
|
32065
32070
|
strategyCreator,
|
|
32066
32071
|
sourceStrategyConfig,
|
|
32067
|
-
strategyConfig
|
|
32068
|
-
strategyResults
|
|
32072
|
+
strategyConfig
|
|
32069
32073
|
} = runtimeStrategy;
|
|
32070
|
-
const runtimeIdentity =
|
|
32071
|
-
const symbolResultConfig = strategyResults?.[symbol]?.config ?? null;
|
|
32074
|
+
const runtimeIdentity = `v${releaseVersion}`;
|
|
32072
32075
|
const runtimeConfig2 = buildRuntimeModeStrategyConfig({
|
|
32073
32076
|
strategyConfig,
|
|
32074
32077
|
env: "CRON",
|
|
@@ -32081,7 +32084,7 @@ var init_tickerEvaluator = __esm({
|
|
|
32081
32084
|
releaseVersion,
|
|
32082
32085
|
strategyPackageVersion,
|
|
32083
32086
|
runtimePackageVersion,
|
|
32084
|
-
config: {
|
|
32087
|
+
config: { strategyConfig },
|
|
32085
32088
|
runContext: {
|
|
32086
32089
|
connectorName: connectorName.toLowerCase(),
|
|
32087
32090
|
interval: String(interval4),
|
|
@@ -32109,7 +32112,7 @@ var init_tickerEvaluator = __esm({
|
|
|
32109
32112
|
evaluation = await lifecycle.evaluate({
|
|
32110
32113
|
key: lifecycleKey,
|
|
32111
32114
|
timestamp: lastCandle.timestamp,
|
|
32112
|
-
config: { runtimeConfig: runtimeConfig2, sourceStrategyConfig
|
|
32115
|
+
config: { runtimeConfig: runtimeConfig2, sourceStrategyConfig },
|
|
32113
32116
|
btcBinanceData,
|
|
32114
32117
|
btcCoinbaseData,
|
|
32115
32118
|
onRuntimeClose: (event) => runtimeCloseNotifications.push(event),
|
|
@@ -32120,13 +32123,12 @@ var init_tickerEvaluator = __esm({
|
|
|
32120
32123
|
}) => strategyCreator({
|
|
32121
32124
|
userName: userName3,
|
|
32122
32125
|
connectorName,
|
|
32123
|
-
runtimeConfigId:
|
|
32126
|
+
runtimeConfigId: runtimeIdentity,
|
|
32124
32127
|
runtimeReleaseVersion: releaseVersion,
|
|
32125
32128
|
entriesPaused: controlState === "entries_paused",
|
|
32126
32129
|
runtimeLineage,
|
|
32127
32130
|
runtimeConfigSnapshot: {
|
|
32128
|
-
userConfig: sourceStrategyConfig
|
|
32129
|
-
symbolResultConfig
|
|
32131
|
+
userConfig: sourceStrategyConfig
|
|
32130
32132
|
},
|
|
32131
32133
|
connector,
|
|
32132
32134
|
symbol,
|
|
@@ -32176,12 +32178,12 @@ var init_tickerEvaluator = __esm({
|
|
|
32176
32178
|
strategyName,
|
|
32177
32179
|
symbol,
|
|
32178
32180
|
timestamp: lastCandle.timestamp,
|
|
32179
|
-
runtimeConfigId:
|
|
32181
|
+
runtimeConfigId: runtimeIdentity,
|
|
32180
32182
|
runtimeReleaseVersion: releaseVersion
|
|
32181
32183
|
}),
|
|
32182
32184
|
userName: userName3,
|
|
32183
32185
|
strategy: strategyName,
|
|
32184
|
-
runtimeConfigId:
|
|
32186
|
+
runtimeConfigId: runtimeIdentity,
|
|
32185
32187
|
runtimeReleaseVersion: releaseVersion,
|
|
32186
32188
|
runtimeLineage,
|
|
32187
32189
|
symbol,
|
|
@@ -32199,12 +32201,9 @@ var init_tickerEvaluator = __esm({
|
|
|
32199
32201
|
continue;
|
|
32200
32202
|
}
|
|
32201
32203
|
if (stats) stats.signals += 1;
|
|
32202
|
-
signal.runtimeConfigId =
|
|
32204
|
+
signal.runtimeConfigId = runtimeIdentity;
|
|
32203
32205
|
signal.runtimeReleaseVersion = releaseVersion;
|
|
32204
32206
|
signal.runtimeLineage = runtimeLineage;
|
|
32205
|
-
if (configId && configId !== "config" && !signal.signalId.endsWith(`:${configId}`)) {
|
|
32206
|
-
signal.signalId = `${signal.signalId}:${configId}`;
|
|
32207
|
-
}
|
|
32208
32207
|
if (releaseVersion && !signal.signalId.endsWith(`:v${releaseVersion}`)) {
|
|
32209
32208
|
signal.signalId = `${signal.signalId}:v${releaseVersion}`;
|
|
32210
32209
|
}
|
|
@@ -32224,12 +32223,12 @@ var init_tickerEvaluator = __esm({
|
|
|
32224
32223
|
strategyName,
|
|
32225
32224
|
symbol,
|
|
32226
32225
|
timestamp: lastCandle.timestamp,
|
|
32227
|
-
runtimeConfigId:
|
|
32226
|
+
runtimeConfigId: runtimeIdentity,
|
|
32228
32227
|
runtimeReleaseVersion: releaseVersion
|
|
32229
32228
|
}),
|
|
32230
32229
|
userName: userName3,
|
|
32231
32230
|
strategy: strategyName,
|
|
32232
|
-
runtimeConfigId:
|
|
32231
|
+
runtimeConfigId: runtimeIdentity,
|
|
32233
32232
|
runtimeReleaseVersion: releaseVersion,
|
|
32234
32233
|
runtimeLineage,
|
|
32235
32234
|
symbol,
|
|
@@ -32338,15 +32337,12 @@ var init_runner = __esm({
|
|
|
32338
32337
|
].join("\n");
|
|
32339
32338
|
const resolveSignalsConnectorName = async (value) => {
|
|
32340
32339
|
const connectorName = await (0, import_connectors16.resolveConnectorName)(value, projectRoot15);
|
|
32341
|
-
if (connectorName) {
|
|
32342
|
-
|
|
32340
|
+
if (!connectorName) {
|
|
32341
|
+
throw new Error(
|
|
32342
|
+
`Unknown runtime connector: ${String(value || "").trim() || String(value)}`
|
|
32343
|
+
);
|
|
32343
32344
|
}
|
|
32344
|
-
|
|
32345
|
-
'Unknown connector "%s". Fallback to %s.',
|
|
32346
|
-
String(value || "").trim() || String(value),
|
|
32347
|
-
import_connectors16.DEFAULT_CONNECTOR_NAME
|
|
32348
|
-
);
|
|
32349
|
-
return import_connectors16.DEFAULT_CONNECTOR_NAME;
|
|
32345
|
+
return connectorName;
|
|
32350
32346
|
};
|
|
32351
32347
|
const createSignalsSession2 = async (lifecycle, scope = {}) => {
|
|
32352
32348
|
const deployment = config2.deploymentId ? await (0, import_runtimeDeployments3.getRuntimeDeployment)(config2.userName, config2.deploymentId) : null;
|
|
@@ -32357,25 +32353,15 @@ var init_runner = __esm({
|
|
|
32357
32353
|
throw new Error(`Runtime deployment is disabled: ${deployment.id}`);
|
|
32358
32354
|
}
|
|
32359
32355
|
const requestedRuntimeInterval = scope.interval ?? interval4;
|
|
32360
|
-
const
|
|
32361
|
-
deployment?.strategies.some(
|
|
32362
|
-
(strategy) => strategy.releaseVersion != null
|
|
32363
|
-
)
|
|
32364
|
-
);
|
|
32365
|
-
const runtimeInterval = versionedDeployment ? requestedRuntimeInterval : deployment?.interval ?? requestedRuntimeInterval;
|
|
32356
|
+
const runtimeInterval = requestedRuntimeInterval;
|
|
32366
32357
|
const runtimeIntervalMs = Number(runtimeInterval) * 6e4;
|
|
32367
32358
|
if (!Number.isFinite(runtimeIntervalMs) || runtimeIntervalMs <= 0) {
|
|
32368
32359
|
throw new Error(`Invalid runtime timeframe: ${runtimeInterval}`);
|
|
32369
32360
|
}
|
|
32370
|
-
if (deployment && !versionedDeployment && String(deployment.interval) !== String(requestedRuntimeInterval)) {
|
|
32371
|
-
throw new Error(
|
|
32372
|
-
`Deployment ${deployment.id} requires timeframe ${deployment.interval}; received ${requestedRuntimeInterval}`
|
|
32373
|
-
);
|
|
32374
|
-
}
|
|
32375
32361
|
const connectorName = await resolveSignalsConnectorName(
|
|
32376
32362
|
deployment?.connectorName ?? scope.connectorName ?? config2.connectorName
|
|
32377
32363
|
);
|
|
32378
|
-
const universe =
|
|
32364
|
+
const universe = scope.universe ?? config2.universe;
|
|
32379
32365
|
const requestedAccountId = deployment?.accountId ?? scope.accountId ?? config2.accountId;
|
|
32380
32366
|
const connectorFactory = await (0, import_connectors16.getConnectorCreatorByName)(
|
|
32381
32367
|
connectorName,
|
|
@@ -32587,7 +32573,6 @@ var init_runner = __esm({
|
|
|
32587
32573
|
userName: config2.userName,
|
|
32588
32574
|
projectRoot: projectRoot15,
|
|
32589
32575
|
deployment,
|
|
32590
|
-
connectorName,
|
|
32591
32576
|
universe,
|
|
32592
32577
|
accountId,
|
|
32593
32578
|
interval: interval5
|
|
@@ -32595,8 +32580,8 @@ var init_runner = __esm({
|
|
|
32595
32580
|
if (!runtimeStrategies.length) {
|
|
32596
32581
|
lifecycle.clear();
|
|
32597
32582
|
import_logger10.logger.warn(
|
|
32598
|
-
"No strategy
|
|
32599
|
-
|
|
32583
|
+
"No strategy releases are bound to deployment %s",
|
|
32584
|
+
deployment?.id
|
|
32600
32585
|
);
|
|
32601
32586
|
return;
|
|
32602
32587
|
}
|
|
@@ -32604,7 +32589,7 @@ var init_runner = __esm({
|
|
|
32604
32589
|
new Set(
|
|
32605
32590
|
tickers.flatMap(
|
|
32606
32591
|
(symbol) => runtimeStrategies.map(
|
|
32607
|
-
({ strategyName,
|
|
32592
|
+
({ strategyName, releaseVersion }) => buildSignalsStrategyLifecycleKey({
|
|
32608
32593
|
connectorName,
|
|
32609
32594
|
universe: sessionUniverse,
|
|
32610
32595
|
accountId,
|
|
@@ -32612,7 +32597,7 @@ var init_runner = __esm({
|
|
|
32612
32597
|
symbol,
|
|
32613
32598
|
interval: interval5,
|
|
32614
32599
|
strategyName,
|
|
32615
|
-
configId:
|
|
32600
|
+
configId: `v${releaseVersion}`
|
|
32616
32601
|
})
|
|
32617
32602
|
)
|
|
32618
32603
|
)
|
|
@@ -32801,11 +32786,10 @@ var init_runner = __esm({
|
|
|
32801
32786
|
const configuredStrategies = await (0, import_runtimeStrategies2.loadResolvedRuntimeStrategies)({
|
|
32802
32787
|
userName: config2.userName,
|
|
32803
32788
|
projectRoot: projectRoot15,
|
|
32804
|
-
deployment
|
|
32805
|
-
connectorName: config2.connectorName
|
|
32789
|
+
deployment
|
|
32806
32790
|
});
|
|
32807
32791
|
const connectorName = await resolveSignalsConnectorName(
|
|
32808
|
-
deployment
|
|
32792
|
+
deployment.connectorName
|
|
32809
32793
|
);
|
|
32810
32794
|
const scopes = /* @__PURE__ */ new Map();
|
|
32811
32795
|
for (const strategy of configuredStrategies) {
|
|
@@ -32824,13 +32808,18 @@ var init_runner = __esm({
|
|
|
32824
32808
|
}
|
|
32825
32809
|
return scopes;
|
|
32826
32810
|
};
|
|
32827
|
-
const hasExplicitSignalsScope = () => Boolean(config2.hasExplicitScope);
|
|
32828
32811
|
const signalsConfiguredScopesOnce2 = async () => {
|
|
32829
|
-
if (config2.updateOnly || config2.showTickersList
|
|
32812
|
+
if (config2.updateOnly || config2.showTickersList) {
|
|
32830
32813
|
return signals2();
|
|
32831
32814
|
}
|
|
32832
|
-
|
|
32833
|
-
|
|
32815
|
+
if (!config2.deploymentId) {
|
|
32816
|
+
throw new Error("Runtime deployment id is required");
|
|
32817
|
+
}
|
|
32818
|
+
const configuredDeployment = await (0, import_runtimeDeployments3.getRuntimeDeployment)(
|
|
32819
|
+
config2.userName,
|
|
32820
|
+
config2.deploymentId
|
|
32821
|
+
);
|
|
32822
|
+
if (!configuredDeployment) {
|
|
32834
32823
|
throw new Error(`Runtime deployment not found: ${config2.deploymentId}`);
|
|
32835
32824
|
}
|
|
32836
32825
|
const scopes = await loadConfiguredSignalsScopes(configuredDeployment);
|
|
@@ -32855,8 +32844,14 @@ var init_runner = __esm({
|
|
|
32855
32844
|
);
|
|
32856
32845
|
}
|
|
32857
32846
|
const abortController = new AbortController();
|
|
32858
|
-
|
|
32859
|
-
|
|
32847
|
+
if (!config2.deploymentId) {
|
|
32848
|
+
throw new Error("Runtime deployment id is required");
|
|
32849
|
+
}
|
|
32850
|
+
const daemonDeployment = await (0, import_runtimeDeployments3.getRuntimeDeployment)(
|
|
32851
|
+
config2.userName,
|
|
32852
|
+
config2.deploymentId
|
|
32853
|
+
);
|
|
32854
|
+
if (!daemonDeployment) {
|
|
32860
32855
|
throw new Error(`Runtime deployment not found: ${config2.deploymentId}`);
|
|
32861
32856
|
}
|
|
32862
32857
|
const sessions = /* @__PURE__ */ new Map();
|
|
@@ -32869,10 +32864,7 @@ var init_runner = __esm({
|
|
|
32869
32864
|
const stopOnSigterm = () => stop("SIGTERM");
|
|
32870
32865
|
process.once("SIGINT", stopOnSigint);
|
|
32871
32866
|
process.once("SIGTERM", stopOnSigterm);
|
|
32872
|
-
import_logger10.logger.info(
|
|
32873
|
-
"signals daemon started (config-driven scopes, fallback interval=%s)",
|
|
32874
|
-
interval4
|
|
32875
|
-
);
|
|
32867
|
+
import_logger10.logger.info("signals daemon started (deployment-driven scopes)");
|
|
32876
32868
|
try {
|
|
32877
32869
|
await runSignalsDaemon({
|
|
32878
32870
|
intervalMs: 6e4,
|
|
@@ -32985,7 +32977,7 @@ __export(signals_exports, {
|
|
|
32985
32977
|
signalsConfiguredScopesOnce: () => signalsConfiguredScopesOnce,
|
|
32986
32978
|
signalsDaemon: () => signalsDaemon
|
|
32987
32979
|
});
|
|
32988
|
-
var import_config12, import_args31, flags29,
|
|
32980
|
+
var import_config12, import_args31, flags29, config, runner, createSignalsSession, signals, signalsConfiguredScopesOnce, signalsDaemon, main41;
|
|
32989
32981
|
var init_signals = __esm({
|
|
32990
32982
|
"src/scripts/signals.ts"() {
|
|
32991
32983
|
"use strict";
|
|
@@ -33029,11 +33021,6 @@ var init_signals = __esm({
|
|
|
33029
33021
|
import_args31.default.option(["A", "account"], "Trading account id");
|
|
33030
33022
|
import_args31.default.option(["D", "deployment"], "Runtime deployment id");
|
|
33031
33023
|
flags29 = import_args31.default.parse(process.argv);
|
|
33032
|
-
hasExplicitScope = process.argv.some(
|
|
33033
|
-
(argument) => ["-f", "--timeframe", "-V", "--universe", "-A", "--account"].some(
|
|
33034
|
-
(option2) => argument === option2 || argument.startsWith(`${option2}=`)
|
|
33035
|
-
)
|
|
33036
|
-
);
|
|
33037
33024
|
config = {
|
|
33038
33025
|
projectRoot: String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd(),
|
|
33039
33026
|
userName: String(flags29.user || "root"),
|
|
@@ -33055,8 +33042,7 @@ var init_signals = __esm({
|
|
|
33055
33042
|
showSkipStats: Boolean(flags29.showSkipStats),
|
|
33056
33043
|
parallel: flags29.parallel,
|
|
33057
33044
|
watch: Boolean(flags29.watch),
|
|
33058
|
-
settleDelayMs: flags29.settleDelayMs
|
|
33059
|
-
hasExplicitScope
|
|
33045
|
+
settleDelayMs: flags29.settleDelayMs
|
|
33060
33046
|
};
|
|
33061
33047
|
runner = createSignalsRunner(config);
|
|
33062
33048
|
createSignalsSession = runner.createSession;
|
|
@@ -37134,7 +37120,7 @@ var init_signalsSummary = __esm({
|
|
|
37134
37120
|
for (const trade of trades) {
|
|
37135
37121
|
const deployment = trade.deploymentId ? deploymentById.get(trade.deploymentId) : void 0;
|
|
37136
37122
|
const connectorName = deployment?.connectorName ?? fallbackConnectorName;
|
|
37137
|
-
const universe = trade.universe ??
|
|
37123
|
+
const universe = trade.universe ?? "crypto";
|
|
37138
37124
|
const accountId = trade.accountId ?? deployment?.accountId;
|
|
37139
37125
|
const deploymentId = trade.deploymentId;
|
|
37140
37126
|
const scopeKey = JSON.stringify([
|