@tradejs/node 3.1.0 → 3.1.2

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.
@@ -40,6 +40,7 @@ var import_strategyReleaseEvidence2 = require("@tradejs/infra/strategyReleaseEvi
40
40
  var import_tradingAccounts2 = require("@tradejs/infra/tradingAccounts");
41
41
  var import_runtimeDeployments = require("@tradejs/infra/runtimeDeployments");
42
42
  var import_runtimeStrategyConfigs2 = require("@tradejs/infra/runtimeStrategyConfigs");
43
+ var import_runtimeStrategyReleases = require("@tradejs/infra/runtimeStrategyReleases");
43
44
  var import_redis4 = require("@tradejs/infra/redis");
44
45
 
45
46
  // src/strategies.ts
@@ -86,6 +87,7 @@ __export(strategies_exports, {
86
87
  getStrategyCreator: () => getStrategyCreator,
87
88
  getStrategyDefaults: () => getStrategyDefaults,
88
89
  getStrategyManifest: () => getStrategyManifest,
90
+ getStrategyPluginSource: () => getStrategyPluginSource,
89
91
  invokeAiChat: () => invokeAiChat,
90
92
  isKnownStrategy: () => isKnownStrategy,
91
93
  isTrackedHyperliquidPerp: () => isTrackedHyperliquidPerp,
@@ -978,6 +980,7 @@ var createStrategyRegistryState = () => ({
978
980
  strategyCreators: /* @__PURE__ */ new Map(),
979
981
  strategyManifestsMap: /* @__PURE__ */ new Map(),
980
982
  strategyEntriesMap: /* @__PURE__ */ new Map(),
983
+ strategySourcesMap: /* @__PURE__ */ new Map(),
981
984
  pluginsLoadPromise: null
982
985
  });
983
986
  var registryStateByProjectRoot = sharedStrategyRegistry.registryStateByProjectRoot;
@@ -1048,6 +1051,7 @@ var registerEntries = (entries, source, state) => {
1048
1051
  }
1049
1052
  state.strategyManifestsMap.set(strategyName, entry.manifest);
1050
1053
  state.strategyEntriesMap.set(strategyName, entry);
1054
+ state.strategySourcesMap.set(strategyName, source);
1051
1055
  materializeStrategyCreator(strategyName, state);
1052
1056
  }
1053
1057
  };
@@ -1170,6 +1174,11 @@ var getStrategyDefaults = async (name, cwd = getTradejsProjectCwd()) => {
1170
1174
  const { state } = getStrategyRegistryState(cwd);
1171
1175
  return state.strategyEntriesMap.get(name)?.defaults;
1172
1176
  };
1177
+ var getStrategyPluginSource = async (name, cwd = getTradejsProjectCwd()) => {
1178
+ await ensureStrategyPluginsLoaded(cwd);
1179
+ const { state } = getStrategyRegistryState(cwd);
1180
+ return state.strategySourcesMap.get(name);
1181
+ };
1173
1182
  var getAvailableStrategyNames = async (cwd = getTradejsProjectCwd()) => {
1174
1183
  await ensureStrategyPluginsLoaded(cwd);
1175
1184
  const { state } = getStrategyRegistryState(cwd);
@@ -4551,6 +4560,7 @@ var executeEntryOrder = async ({
4551
4560
  deploymentId: signal.deploymentId,
4552
4561
  policyProfileId: signal.policyProfileId,
4553
4562
  runtimeConfigId: signal.runtimeConfigId,
4563
+ runtimeReleaseVersion: signal.runtimeReleaseVersion,
4554
4564
  runtimeLineage: signal.runtimeLineage,
4555
4565
  ...signal.aiAnalysis ? { aiAnalysis: signal.aiAnalysis } : {}
4556
4566
  });
@@ -5475,6 +5485,9 @@ var createStrategyRuntime = ({
5475
5485
  deploymentId: requestedDeploymentId,
5476
5486
  policyProfileId,
5477
5487
  runtimeConfigId,
5488
+ runtimeReleaseVersion,
5489
+ entriesPaused = false,
5490
+ runtimeLineage,
5478
5491
  runtimeConfigSnapshot,
5479
5492
  data,
5480
5493
  btcData,
@@ -6133,6 +6146,7 @@ var createStrategyRuntime = ({
6133
6146
  });
6134
6147
  const signal = decision.signal;
6135
6148
  if (signal) {
6149
+ if (runtimeLineage) signal.runtimeLineage = runtimeLineage;
6136
6150
  if (universe) signal.universe = universe;
6137
6151
  if (assetClass) signal.assetClass = assetClass;
6138
6152
  if (accountId) signal.accountId = accountId;
@@ -6143,6 +6157,9 @@ var createStrategyRuntime = ({
6143
6157
  signal.signalId = `${signal.signalId}:${runtimeConfigId}`;
6144
6158
  }
6145
6159
  }
6160
+ if (runtimeReleaseVersion) {
6161
+ signal.runtimeReleaseVersion = runtimeReleaseVersion;
6162
+ }
6146
6163
  if (decisionHookCtx.policyProfileId) {
6147
6164
  signal.policyProfileId = decisionHookCtx.policyProfileId;
6148
6165
  }
@@ -6249,6 +6266,15 @@ var createStrategyRuntime = ({
6249
6266
  quality,
6250
6267
  minAiQuality
6251
6268
  });
6269
+ if (entriesPaused) {
6270
+ const skipReason = "RUNTIME_ENTRIES_PAUSED";
6271
+ if (signal) {
6272
+ signal.orderStatus = "skipped";
6273
+ signal.orderSkipReason = skipReason;
6274
+ signal.runtimeReleaseVersion = runtimeReleaseVersion;
6275
+ }
6276
+ return signal ?? skipReason;
6277
+ }
6252
6278
  if (!shouldMakeOrder) {
6253
6279
  if (signal) {
6254
6280
  signal.orderStatus = "skipped";
@@ -7242,6 +7268,7 @@ var asRecord2 = (value) => value && typeof value === "object" && !Array.isArray(
7242
7268
  var isNonEmptyString = (value) => typeof value === "string" && value.trim().length > 0;
7243
7269
  var strategyEvidenceTimelineSelectorKey = (selector) => [
7244
7270
  selector.strategy,
7271
+ selector.releaseVersion ?? "",
7245
7272
  selector.compositionId ?? "",
7246
7273
  selector.gitSha ?? "",
7247
7274
  selector.gateFingerprint ?? "",
@@ -7293,6 +7320,11 @@ var missingTimeline = () => ({
7293
7320
  observedFrom: null,
7294
7321
  markers: []
7295
7322
  });
7323
+ var notAttachedTimeline = () => ({
7324
+ status: "not_attached",
7325
+ observedFrom: null,
7326
+ markers: []
7327
+ });
7296
7328
  var invalidTimeline = () => ({
7297
7329
  status: "invalid",
7298
7330
  observedFrom: null,
@@ -7314,7 +7346,7 @@ var loadStrategyEvidenceTimelines = async ({
7314
7346
  const timelines = new Map(
7315
7347
  selectors.map((selector) => [
7316
7348
  strategyEvidenceTimelineSelectorKey(selector),
7317
- missingTimeline()
7349
+ selector.releaseVersion ? notAttachedTimeline() : missingTimeline()
7318
7350
  ])
7319
7351
  );
7320
7352
  if (!selectors.length) return timelines;
@@ -7384,7 +7416,7 @@ var loadStrategyEvidenceTimelines = async ({
7384
7416
  }
7385
7417
  const envelopes = envelopesByStrategy.get(strategy) ?? [];
7386
7418
  if (!envelopes.length) continue;
7387
- const hasCompleteSelector = Boolean(selector.compositionId) && Boolean(selector.gitSha) && Boolean(selector.gateFingerprint) && Boolean(selector.configFingerprint) && Boolean(selector.contextFingerprint);
7419
+ const hasCompleteSelector = selector.releaseVersion != null || Boolean(selector.compositionId) && Boolean(selector.gitSha) && Boolean(selector.gateFingerprint) && Boolean(selector.configFingerprint) && Boolean(selector.contextFingerprint);
7388
7420
  if (selector.requireCompleteLineage && !hasCompleteSelector) continue;
7389
7421
  const markersById = /* @__PURE__ */ new Map();
7390
7422
  let hasConflict = false;
@@ -7404,7 +7436,7 @@ var loadStrategyEvidenceTimelines = async ({
7404
7436
  continue;
7405
7437
  }
7406
7438
  const matchingMarkers = [...markersById.values()].filter(
7407
- (marker) => (!selector.compositionId || marker.compositionId === selector.compositionId) && (!selector.gitSha || marker.gitSha === selector.gitSha) && (!selector.gateFingerprint || marker.gateFingerprint === selector.gateFingerprint) && (!selector.configFingerprint || marker.configFingerprint === selector.configFingerprint) && (!selector.contextFingerprint || marker.contextFingerprint === selector.contextFingerprint) && marker.timestamp >= startTime && marker.timestamp < endTime
7439
+ (marker) => (!selector.compositionId || marker.compositionId === selector.compositionId) && (!selector.releaseVersion || marker.releaseVersion === selector.releaseVersion) && (!selector.gitSha || marker.gitSha === selector.gitSha) && (!selector.gateFingerprint || marker.gateFingerprint === selector.gateFingerprint) && (!selector.configFingerprint || marker.configFingerprint === selector.configFingerprint) && (!selector.contextFingerprint || marker.contextFingerprint === selector.contextFingerprint) && marker.timestamp >= startTime && marker.timestamp < endTime
7408
7440
  ).sort(
7409
7441
  (left, right) => left.timestamp - right.timestamp || left.type.localeCompare(right.type) || left.id.localeCompare(right.id)
7410
7442
  );
@@ -7419,7 +7451,7 @@ var loadStrategyEvidenceTimelines = async ({
7419
7451
  lastLossValue = marker.maxLossValue;
7420
7452
  return true;
7421
7453
  });
7422
- if (!markers.length && (selector.compositionId || selector.gitSha || selector.gateFingerprint || selector.configFingerprint || selector.contextFingerprint)) {
7454
+ if (!markers.length && (selector.compositionId || selector.releaseVersion || selector.gitSha || selector.gateFingerprint || selector.configFingerprint || selector.contextFingerprint)) {
7423
7455
  continue;
7424
7456
  }
7425
7457
  timelines.set(selectorKey, {
@@ -8234,7 +8266,7 @@ var loadRuntimeDashboard = async ({
8234
8266
  );
8235
8267
  const runtimeIdentityKey = (trade) => (0, import_runtimeTrades3.buildRuntimeStrategyIdentityKey)({
8236
8268
  strategyName: trade.strategy,
8237
- configId: trade.runtimeConfigId,
8269
+ configId: trade.runtimeReleaseVersion ? `v${trade.runtimeReleaseVersion}` : trade.runtimeConfigId,
8238
8270
  universe: trade.universe,
8239
8271
  accountId: trade.accountId,
8240
8272
  deploymentId: trade.deploymentId,
@@ -8242,32 +8274,58 @@ var loadRuntimeDashboard = async ({
8242
8274
  });
8243
8275
  const identityByKey = /* @__PURE__ */ new Map();
8244
8276
  const runtimeConfigAccountScopes = new Array();
8277
+ const versionedBindings = /* @__PURE__ */ new Set();
8245
8278
  for (const deployment of runtimeDeployments) {
8246
8279
  for (const deploymentStrategy of deployment.strategies) {
8280
+ const release = deploymentStrategy.releaseVersion ? await (0, import_runtimeStrategyReleases.getRuntimeStrategyRelease)(
8281
+ userName,
8282
+ deploymentStrategy.strategyName,
8283
+ deploymentStrategy.releaseVersion
8284
+ ).catch((error) => {
8285
+ import_logger17.logger.warn(
8286
+ "strategies runtime: failed to load %s v%s: %s",
8287
+ deploymentStrategy.strategyName,
8288
+ deploymentStrategy.releaseVersion,
8289
+ String(error)
8290
+ );
8291
+ return null;
8292
+ }) : null;
8293
+ const deploymentConfig = release?.config ?? (deploymentStrategy.config && typeof deploymentStrategy.config === "object" && !Array.isArray(deploymentStrategy.config) ? deploymentStrategy.config : void 0);
8294
+ const releaseUniverse = release?.config.UNIVERSE === "tradfi" ? "tradfi" : "crypto";
8295
+ const releaseInterval = String(
8296
+ release?.config.INTERVAL ?? deployment.interval
8297
+ );
8298
+ const releaseConfigId = deploymentStrategy.releaseVersion ? `v${deploymentStrategy.releaseVersion}` : `deployment-${deployment.id}`;
8299
+ const releasePolicyProfileId = release ? typeof release.config.POLICY_PROFILE_ID === "string" ? release.config.POLICY_PROFILE_ID : void 0 : deploymentStrategy.policyProfileId;
8247
8300
  const runtimeKey = (0, import_runtimeTrades3.buildRuntimeStrategyIdentityKey)({
8248
8301
  strategyName: deploymentStrategy.strategyName,
8249
- configId: `deployment-${deployment.id}`,
8250
- universe: deployment.universe,
8302
+ configId: releaseConfigId,
8303
+ universe: release ? releaseUniverse : deployment.universe,
8251
8304
  accountId: deployment.accountId,
8252
8305
  deploymentId: deployment.id,
8253
- policyProfileId: deploymentStrategy.policyProfileId
8306
+ policyProfileId: releasePolicyProfileId
8254
8307
  });
8308
+ if (deploymentStrategy.releaseVersion) {
8309
+ versionedBindings.add(
8310
+ `${deploymentStrategy.strategyName}:${deployment.accountId}`
8311
+ );
8312
+ }
8255
8313
  identityByKey.set(runtimeKey, {
8256
8314
  strategyName: deploymentStrategy.strategyName,
8257
- configId: `deployment-${deployment.id}`,
8258
- interval: String(deployment.interval),
8259
- universe: deployment.universe,
8315
+ configId: releaseConfigId,
8316
+ releaseVersion: deploymentStrategy.releaseVersion,
8317
+ controlState: deploymentStrategy.controlState ?? "active",
8318
+ interval: releaseInterval,
8319
+ universe: release ? releaseUniverse : deployment.universe,
8260
8320
  accountId: deployment.accountId,
8261
8321
  accountLabel: accountsById.get(deployment.accountId)?.label,
8262
8322
  deploymentId: deployment.id,
8263
- policyProfileId: deploymentStrategy.policyProfileId,
8323
+ policyProfileId: releasePolicyProfileId,
8264
8324
  releaseCompositionId: deploymentStrategy.releaseCompositionId,
8265
- enabled: deployment.enabled && deploymentStrategy.enabled !== false,
8266
- config: deploymentStrategy.config,
8267
- connected: false,
8268
- configFingerprint: (0, import_strategyReleaseEvidence2.strategyLogicConfigFingerprint)(
8269
- deploymentStrategy.config
8270
- )
8325
+ enabled: deployment.enabled && (deploymentStrategy.releaseVersion ? deploymentStrategy.controlState !== "entries_paused" : deploymentStrategy.enabled !== false),
8326
+ config: deploymentConfig,
8327
+ connected: Boolean(release && deployment.enabled),
8328
+ configFingerprint: deploymentConfig ? (0, import_strategyReleaseEvidence2.strategyLogicConfigFingerprint)(deploymentConfig) : void 0
8271
8329
  });
8272
8330
  }
8273
8331
  }
@@ -8281,6 +8339,11 @@ var loadRuntimeDashboard = async ({
8281
8339
  universe
8282
8340
  }).catch(() => null);
8283
8341
  const accountId = resolvedAccount?.id ?? configuredAccountId;
8342
+ if (versionedBindings.has(
8343
+ `${runtimeConfig.strategyName}:${accountId ?? "default"}`
8344
+ )) {
8345
+ continue;
8346
+ }
8284
8347
  runtimeConfigAccountScopes.push({
8285
8348
  strategyName: runtimeConfig.strategyName,
8286
8349
  configId: runtimeConfig.configId,
@@ -8313,12 +8376,14 @@ var loadRuntimeDashboard = async ({
8313
8376
  for (const trade of accountScopedTrades) {
8314
8377
  const key = runtimeIdentityKey(trade);
8315
8378
  const configuredCompositionId = identityByKey.get(key)?.releaseCompositionId;
8316
- const observedCompositionId = trade.runtimeLineage?.compositionId;
8379
+ const observedCompositionId = trade.runtimeLineage?.schemaVersion === 1 ? trade.runtimeLineage.compositionId : void 0;
8317
8380
  const releaseCompositionId = configuredCompositionId && observedCompositionId && configuredCompositionId !== observedCompositionId ? void 0 : observedCompositionId ?? configuredCompositionId;
8381
+ const releaseVersion = trade.runtimeReleaseVersion ?? (trade.runtimeLineage?.schemaVersion === 2 ? trade.runtimeLineage.releaseVersion : void 0);
8318
8382
  identityByKey.set(key, {
8319
8383
  ...identityByKey.get(key),
8320
8384
  strategyName: trade.strategy,
8321
- configId: trade.runtimeConfigId ?? "config",
8385
+ configId: releaseVersion ? `v${releaseVersion}` : trade.runtimeConfigId ?? "config",
8386
+ releaseVersion,
8322
8387
  interval: String(trade.interval ?? "15"),
8323
8388
  universe: trade.universe ?? "crypto",
8324
8389
  accountId: trade.accountId,
@@ -8326,10 +8391,10 @@ var loadRuntimeDashboard = async ({
8326
8391
  deploymentId: trade.deploymentId,
8327
8392
  policyProfileId: trade.policyProfileId,
8328
8393
  releaseCompositionId,
8329
- configFingerprint: trade.runtimeLineage?.configFingerprint,
8330
- gateFingerprint: trade.runtimeLineage?.gateFingerprint,
8331
- contextFingerprint: trade.runtimeLineage?.contextFingerprint,
8332
- gitSha: trade.runtimeLineage?.gitSha ?? void 0,
8394
+ configFingerprint: trade.runtimeLineage?.schemaVersion === 1 ? trade.runtimeLineage.configFingerprint : void 0,
8395
+ gateFingerprint: trade.runtimeLineage?.schemaVersion === 1 ? trade.runtimeLineage.gateFingerprint : void 0,
8396
+ contextFingerprint: trade.runtimeLineage?.schemaVersion === 1 ? trade.runtimeLineage.contextFingerprint : void 0,
8397
+ gitSha: trade.runtimeLineage?.schemaVersion === 1 ? trade.runtimeLineage.gitSha ?? void 0 : void 0,
8333
8398
  maxLossValue: trade.runtimeLineage?.maxLossValue ?? void 0
8334
8399
  });
8335
8400
  }
@@ -8338,6 +8403,7 @@ var loadRuntimeDashboard = async ({
8338
8403
  markerDir: process.env.STRATEGY_RELEASE_MARKER_DIR,
8339
8404
  selectors: [...identityByKey.values()].map((identity) => ({
8340
8405
  strategy: identity.strategyName,
8406
+ releaseVersion: identity.releaseVersion,
8341
8407
  compositionId: identity.releaseCompositionId,
8342
8408
  configFingerprint: identity.configFingerprint,
8343
8409
  gateFingerprint: identity.gateFingerprint,
@@ -8368,6 +8434,8 @@ var loadRuntimeDashboard = async ({
8368
8434
  runtimeKey,
8369
8435
  strategyName,
8370
8436
  configId: identity.configId,
8437
+ releaseVersion: identity.releaseVersion,
8438
+ controlState: identity.controlState,
8371
8439
  interval: identity.interval,
8372
8440
  universe: identity.universe,
8373
8441
  accountId: identity.accountId,
@@ -8384,6 +8452,7 @@ var loadRuntimeDashboard = async ({
8384
8452
  evidenceTimeline: evidenceTimelines.get(
8385
8453
  strategyEvidenceTimelineSelectorKey({
8386
8454
  strategy: strategyName,
8455
+ releaseVersion: identity.releaseVersion,
8387
8456
  compositionId: identity.releaseCompositionId,
8388
8457
  configFingerprint: identity.configFingerprint,
8389
8458
  gateFingerprint: identity.gateFingerprint,
@@ -6,10 +6,11 @@ import "./chunk-LAJ7NA3Q.mjs";
6
6
  import {
7
7
  getConnectorCreatorByProvider
8
8
  } from "./chunk-3TWULKHV.mjs";
9
- import "./chunk-MKLTJQLY.mjs";
9
+ import "./chunk-W26Y6IRP.mjs";
10
+ import "./chunk-SEQJ6V6B.mjs";
10
11
  import {
11
12
  getAvailableStrategyNames
12
- } from "./chunk-KOQSLFT2.mjs";
13
+ } from "./chunk-XN7BC7XK.mjs";
13
14
  import "./chunk-WS5DYEVZ.mjs";
14
15
  import "./chunk-Y6FXYEAI.mjs";
15
16
 
@@ -23,6 +24,7 @@ import {
23
24
  } from "@tradejs/infra/tradingAccounts";
24
25
  import { listRuntimeDeployments } from "@tradejs/infra/runtimeDeployments";
25
26
  import { loadRuntimeStrategyConfigs as loadStoredRuntimeStrategyConfigs } from "@tradejs/infra/runtimeStrategyConfigs";
27
+ import { getRuntimeStrategyRelease } from "@tradejs/infra/runtimeStrategyReleases";
26
28
  import {
27
29
  getData as getData2,
28
30
  getHashJsonValues,
@@ -51,6 +53,7 @@ var asRecord = (value) => value && typeof value === "object" && !Array.isArray(v
51
53
  var isNonEmptyString = (value) => typeof value === "string" && value.trim().length > 0;
52
54
  var strategyEvidenceTimelineSelectorKey = (selector) => [
53
55
  selector.strategy,
56
+ selector.releaseVersion ?? "",
54
57
  selector.compositionId ?? "",
55
58
  selector.gitSha ?? "",
56
59
  selector.gateFingerprint ?? "",
@@ -102,6 +105,11 @@ var missingTimeline = () => ({
102
105
  observedFrom: null,
103
106
  markers: []
104
107
  });
108
+ var notAttachedTimeline = () => ({
109
+ status: "not_attached",
110
+ observedFrom: null,
111
+ markers: []
112
+ });
105
113
  var invalidTimeline = () => ({
106
114
  status: "invalid",
107
115
  observedFrom: null,
@@ -123,7 +131,7 @@ var loadStrategyEvidenceTimelines = async ({
123
131
  const timelines = new Map(
124
132
  selectors.map((selector) => [
125
133
  strategyEvidenceTimelineSelectorKey(selector),
126
- missingTimeline()
134
+ selector.releaseVersion ? notAttachedTimeline() : missingTimeline()
127
135
  ])
128
136
  );
129
137
  if (!selectors.length) return timelines;
@@ -193,7 +201,7 @@ var loadStrategyEvidenceTimelines = async ({
193
201
  }
194
202
  const envelopes = envelopesByStrategy.get(strategy) ?? [];
195
203
  if (!envelopes.length) continue;
196
- const hasCompleteSelector = Boolean(selector.compositionId) && Boolean(selector.gitSha) && Boolean(selector.gateFingerprint) && Boolean(selector.configFingerprint) && Boolean(selector.contextFingerprint);
204
+ const hasCompleteSelector = selector.releaseVersion != null || Boolean(selector.compositionId) && Boolean(selector.gitSha) && Boolean(selector.gateFingerprint) && Boolean(selector.configFingerprint) && Boolean(selector.contextFingerprint);
197
205
  if (selector.requireCompleteLineage && !hasCompleteSelector) continue;
198
206
  const markersById = /* @__PURE__ */ new Map();
199
207
  let hasConflict = false;
@@ -213,7 +221,7 @@ var loadStrategyEvidenceTimelines = async ({
213
221
  continue;
214
222
  }
215
223
  const matchingMarkers = [...markersById.values()].filter(
216
- (marker) => (!selector.compositionId || marker.compositionId === selector.compositionId) && (!selector.gitSha || marker.gitSha === selector.gitSha) && (!selector.gateFingerprint || marker.gateFingerprint === selector.gateFingerprint) && (!selector.configFingerprint || marker.configFingerprint === selector.configFingerprint) && (!selector.contextFingerprint || marker.contextFingerprint === selector.contextFingerprint) && marker.timestamp >= startTime && marker.timestamp < endTime
224
+ (marker) => (!selector.compositionId || marker.compositionId === selector.compositionId) && (!selector.releaseVersion || marker.releaseVersion === selector.releaseVersion) && (!selector.gitSha || marker.gitSha === selector.gitSha) && (!selector.gateFingerprint || marker.gateFingerprint === selector.gateFingerprint) && (!selector.configFingerprint || marker.configFingerprint === selector.configFingerprint) && (!selector.contextFingerprint || marker.contextFingerprint === selector.contextFingerprint) && marker.timestamp >= startTime && marker.timestamp < endTime
217
225
  ).sort(
218
226
  (left, right) => left.timestamp - right.timestamp || left.type.localeCompare(right.type) || left.id.localeCompare(right.id)
219
227
  );
@@ -228,7 +236,7 @@ var loadStrategyEvidenceTimelines = async ({
228
236
  lastLossValue = marker.maxLossValue;
229
237
  return true;
230
238
  });
231
- if (!markers.length && (selector.compositionId || selector.gitSha || selector.gateFingerprint || selector.configFingerprint || selector.contextFingerprint)) {
239
+ if (!markers.length && (selector.compositionId || selector.releaseVersion || selector.gitSha || selector.gateFingerprint || selector.configFingerprint || selector.contextFingerprint)) {
232
240
  continue;
233
241
  }
234
242
  timelines.set(selectorKey, {
@@ -757,7 +765,7 @@ var loadRuntimeDashboard = async ({
757
765
  );
758
766
  const runtimeIdentityKey = (trade) => buildRuntimeStrategyIdentityKey({
759
767
  strategyName: trade.strategy,
760
- configId: trade.runtimeConfigId,
768
+ configId: trade.runtimeReleaseVersion ? `v${trade.runtimeReleaseVersion}` : trade.runtimeConfigId,
761
769
  universe: trade.universe,
762
770
  accountId: trade.accountId,
763
771
  deploymentId: trade.deploymentId,
@@ -765,32 +773,58 @@ var loadRuntimeDashboard = async ({
765
773
  });
766
774
  const identityByKey = /* @__PURE__ */ new Map();
767
775
  const runtimeConfigAccountScopes = new Array();
776
+ const versionedBindings = /* @__PURE__ */ new Set();
768
777
  for (const deployment of runtimeDeployments) {
769
778
  for (const deploymentStrategy of deployment.strategies) {
779
+ const release = deploymentStrategy.releaseVersion ? await getRuntimeStrategyRelease(
780
+ userName,
781
+ deploymentStrategy.strategyName,
782
+ deploymentStrategy.releaseVersion
783
+ ).catch((error) => {
784
+ logger.warn(
785
+ "strategies runtime: failed to load %s v%s: %s",
786
+ deploymentStrategy.strategyName,
787
+ deploymentStrategy.releaseVersion,
788
+ String(error)
789
+ );
790
+ return null;
791
+ }) : null;
792
+ const deploymentConfig = release?.config ?? (deploymentStrategy.config && typeof deploymentStrategy.config === "object" && !Array.isArray(deploymentStrategy.config) ? deploymentStrategy.config : void 0);
793
+ const releaseUniverse = release?.config.UNIVERSE === "tradfi" ? "tradfi" : "crypto";
794
+ const releaseInterval = String(
795
+ release?.config.INTERVAL ?? deployment.interval
796
+ );
797
+ const releaseConfigId = deploymentStrategy.releaseVersion ? `v${deploymentStrategy.releaseVersion}` : `deployment-${deployment.id}`;
798
+ const releasePolicyProfileId = release ? typeof release.config.POLICY_PROFILE_ID === "string" ? release.config.POLICY_PROFILE_ID : void 0 : deploymentStrategy.policyProfileId;
770
799
  const runtimeKey = buildRuntimeStrategyIdentityKey({
771
800
  strategyName: deploymentStrategy.strategyName,
772
- configId: `deployment-${deployment.id}`,
773
- universe: deployment.universe,
801
+ configId: releaseConfigId,
802
+ universe: release ? releaseUniverse : deployment.universe,
774
803
  accountId: deployment.accountId,
775
804
  deploymentId: deployment.id,
776
- policyProfileId: deploymentStrategy.policyProfileId
805
+ policyProfileId: releasePolicyProfileId
777
806
  });
807
+ if (deploymentStrategy.releaseVersion) {
808
+ versionedBindings.add(
809
+ `${deploymentStrategy.strategyName}:${deployment.accountId}`
810
+ );
811
+ }
778
812
  identityByKey.set(runtimeKey, {
779
813
  strategyName: deploymentStrategy.strategyName,
780
- configId: `deployment-${deployment.id}`,
781
- interval: String(deployment.interval),
782
- universe: deployment.universe,
814
+ configId: releaseConfigId,
815
+ releaseVersion: deploymentStrategy.releaseVersion,
816
+ controlState: deploymentStrategy.controlState ?? "active",
817
+ interval: releaseInterval,
818
+ universe: release ? releaseUniverse : deployment.universe,
783
819
  accountId: deployment.accountId,
784
820
  accountLabel: accountsById.get(deployment.accountId)?.label,
785
821
  deploymentId: deployment.id,
786
- policyProfileId: deploymentStrategy.policyProfileId,
822
+ policyProfileId: releasePolicyProfileId,
787
823
  releaseCompositionId: deploymentStrategy.releaseCompositionId,
788
- enabled: deployment.enabled && deploymentStrategy.enabled !== false,
789
- config: deploymentStrategy.config,
790
- connected: false,
791
- configFingerprint: strategyLogicConfigFingerprint(
792
- deploymentStrategy.config
793
- )
824
+ enabled: deployment.enabled && (deploymentStrategy.releaseVersion ? deploymentStrategy.controlState !== "entries_paused" : deploymentStrategy.enabled !== false),
825
+ config: deploymentConfig,
826
+ connected: Boolean(release && deployment.enabled),
827
+ configFingerprint: deploymentConfig ? strategyLogicConfigFingerprint(deploymentConfig) : void 0
794
828
  });
795
829
  }
796
830
  }
@@ -804,6 +838,11 @@ var loadRuntimeDashboard = async ({
804
838
  universe
805
839
  }).catch(() => null);
806
840
  const accountId = resolvedAccount?.id ?? configuredAccountId;
841
+ if (versionedBindings.has(
842
+ `${runtimeConfig.strategyName}:${accountId ?? "default"}`
843
+ )) {
844
+ continue;
845
+ }
807
846
  runtimeConfigAccountScopes.push({
808
847
  strategyName: runtimeConfig.strategyName,
809
848
  configId: runtimeConfig.configId,
@@ -836,12 +875,14 @@ var loadRuntimeDashboard = async ({
836
875
  for (const trade of accountScopedTrades) {
837
876
  const key = runtimeIdentityKey(trade);
838
877
  const configuredCompositionId = identityByKey.get(key)?.releaseCompositionId;
839
- const observedCompositionId = trade.runtimeLineage?.compositionId;
878
+ const observedCompositionId = trade.runtimeLineage?.schemaVersion === 1 ? trade.runtimeLineage.compositionId : void 0;
840
879
  const releaseCompositionId = configuredCompositionId && observedCompositionId && configuredCompositionId !== observedCompositionId ? void 0 : observedCompositionId ?? configuredCompositionId;
880
+ const releaseVersion = trade.runtimeReleaseVersion ?? (trade.runtimeLineage?.schemaVersion === 2 ? trade.runtimeLineage.releaseVersion : void 0);
841
881
  identityByKey.set(key, {
842
882
  ...identityByKey.get(key),
843
883
  strategyName: trade.strategy,
844
- configId: trade.runtimeConfigId ?? "config",
884
+ configId: releaseVersion ? `v${releaseVersion}` : trade.runtimeConfigId ?? "config",
885
+ releaseVersion,
845
886
  interval: String(trade.interval ?? "15"),
846
887
  universe: trade.universe ?? "crypto",
847
888
  accountId: trade.accountId,
@@ -849,10 +890,10 @@ var loadRuntimeDashboard = async ({
849
890
  deploymentId: trade.deploymentId,
850
891
  policyProfileId: trade.policyProfileId,
851
892
  releaseCompositionId,
852
- configFingerprint: trade.runtimeLineage?.configFingerprint,
853
- gateFingerprint: trade.runtimeLineage?.gateFingerprint,
854
- contextFingerprint: trade.runtimeLineage?.contextFingerprint,
855
- gitSha: trade.runtimeLineage?.gitSha ?? void 0,
893
+ configFingerprint: trade.runtimeLineage?.schemaVersion === 1 ? trade.runtimeLineage.configFingerprint : void 0,
894
+ gateFingerprint: trade.runtimeLineage?.schemaVersion === 1 ? trade.runtimeLineage.gateFingerprint : void 0,
895
+ contextFingerprint: trade.runtimeLineage?.schemaVersion === 1 ? trade.runtimeLineage.contextFingerprint : void 0,
896
+ gitSha: trade.runtimeLineage?.schemaVersion === 1 ? trade.runtimeLineage.gitSha ?? void 0 : void 0,
856
897
  maxLossValue: trade.runtimeLineage?.maxLossValue ?? void 0
857
898
  });
858
899
  }
@@ -861,6 +902,7 @@ var loadRuntimeDashboard = async ({
861
902
  markerDir: process.env.STRATEGY_RELEASE_MARKER_DIR,
862
903
  selectors: [...identityByKey.values()].map((identity) => ({
863
904
  strategy: identity.strategyName,
905
+ releaseVersion: identity.releaseVersion,
864
906
  compositionId: identity.releaseCompositionId,
865
907
  configFingerprint: identity.configFingerprint,
866
908
  gateFingerprint: identity.gateFingerprint,
@@ -891,6 +933,8 @@ var loadRuntimeDashboard = async ({
891
933
  runtimeKey,
892
934
  strategyName,
893
935
  configId: identity.configId,
936
+ releaseVersion: identity.releaseVersion,
937
+ controlState: identity.controlState,
894
938
  interval: identity.interval,
895
939
  universe: identity.universe,
896
940
  accountId: identity.accountId,
@@ -907,6 +951,7 @@ var loadRuntimeDashboard = async ({
907
951
  evidenceTimeline: evidenceTimelines.get(
908
952
  strategyEvidenceTimelineSelectorKey({
909
953
  strategy: strategyName,
954
+ releaseVersion: identity.releaseVersion,
910
955
  compositionId: identity.releaseCompositionId,
911
956
  configFingerprint: identity.configFingerprint,
912
957
  gateFingerprint: identity.gateFingerprint,
@@ -0,0 +1,38 @@
1
+ import { RuntimeStrategyControlState, Interval, MarketUniverse, StrategyCreator, StrategyConfig, StrategyResults, RuntimeDeployment } from '@tradejs/types';
2
+
3
+ interface ResolvedRuntimeStrategy {
4
+ strategyName: string;
5
+ /** Legacy-only Redis config identity. */
6
+ configId?: string;
7
+ releaseVersion?: number;
8
+ controlState: RuntimeStrategyControlState;
9
+ interval: Interval;
10
+ universe: MarketUniverse;
11
+ accountId?: string;
12
+ strategyPackage?: string | null;
13
+ strategyPackageVersion?: string | null;
14
+ runtimePackageVersion?: string | null;
15
+ strategyCreator: StrategyCreator;
16
+ sourceStrategyConfig: StrategyConfig;
17
+ strategyConfig: StrategyConfig;
18
+ strategyResults: StrategyResults;
19
+ }
20
+ declare const loadResolvedRuntimeStrategies: ({ userName, projectRoot, deployment, connectorName, universe, accountId, interval, }: {
21
+ userName: string;
22
+ projectRoot: string;
23
+ deployment?: RuntimeDeployment | null;
24
+ connectorName?: string;
25
+ universe?: MarketUniverse;
26
+ accountId?: string;
27
+ interval?: Interval;
28
+ }) => Promise<ResolvedRuntimeStrategy[]>;
29
+ declare const getRuntimeStrategyPackageMetadata: ({ strategyName, projectRoot, }: {
30
+ strategyName: string;
31
+ projectRoot: string;
32
+ }) => Promise<{
33
+ strategyPackage: string | null;
34
+ strategyPackageVersion: string | null;
35
+ runtimePackageVersion: string | null;
36
+ }>;
37
+
38
+ export { type ResolvedRuntimeStrategy, getRuntimeStrategyPackageMetadata, loadResolvedRuntimeStrategies };
@@ -0,0 +1,38 @@
1
+ import { RuntimeStrategyControlState, Interval, MarketUniverse, StrategyCreator, StrategyConfig, StrategyResults, RuntimeDeployment } from '@tradejs/types';
2
+
3
+ interface ResolvedRuntimeStrategy {
4
+ strategyName: string;
5
+ /** Legacy-only Redis config identity. */
6
+ configId?: string;
7
+ releaseVersion?: number;
8
+ controlState: RuntimeStrategyControlState;
9
+ interval: Interval;
10
+ universe: MarketUniverse;
11
+ accountId?: string;
12
+ strategyPackage?: string | null;
13
+ strategyPackageVersion?: string | null;
14
+ runtimePackageVersion?: string | null;
15
+ strategyCreator: StrategyCreator;
16
+ sourceStrategyConfig: StrategyConfig;
17
+ strategyConfig: StrategyConfig;
18
+ strategyResults: StrategyResults;
19
+ }
20
+ declare const loadResolvedRuntimeStrategies: ({ userName, projectRoot, deployment, connectorName, universe, accountId, interval, }: {
21
+ userName: string;
22
+ projectRoot: string;
23
+ deployment?: RuntimeDeployment | null;
24
+ connectorName?: string;
25
+ universe?: MarketUniverse;
26
+ accountId?: string;
27
+ interval?: Interval;
28
+ }) => Promise<ResolvedRuntimeStrategy[]>;
29
+ declare const getRuntimeStrategyPackageMetadata: ({ strategyName, projectRoot, }: {
30
+ strategyName: string;
31
+ projectRoot: string;
32
+ }) => Promise<{
33
+ strategyPackage: string | null;
34
+ strategyPackageVersion: string | null;
35
+ runtimePackageVersion: string | null;
36
+ }>;
37
+
38
+ export { type ResolvedRuntimeStrategy, getRuntimeStrategyPackageMetadata, loadResolvedRuntimeStrategies };