@tradejs/node 3.1.18 → 3.1.19-beta.234

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.
@@ -7764,26 +7764,52 @@ var loadRuntimeTrades = async (userName, {
7764
7764
  }) => {
7765
7765
  const filterByWindow = (trade) => trade.entryTimestamp >= startTime || typeof trade.exitTimestamp === "number" && trade.exitTimestamp >= startTime;
7766
7766
  const dayKeys = (0, import_time4.getRuntimeStorageDayKeys)(startTime, endTime);
7767
- const bucketTrades = (await Promise.all(
7768
- dayKeys.map(
7769
- (dayKey) => (0, import_redis4.getHashJsonValues)(
7770
- import_redis4.redisKeys.runtimeTradeBucket(userName, dayKey)
7767
+ const [bucketTradeGroups, legacyKeys] = await Promise.all([
7768
+ Promise.all(
7769
+ dayKeys.map(
7770
+ (dayKey) => (0, import_redis4.getHashJsonValues)(
7771
+ import_redis4.redisKeys.runtimeTradeBucket(userName, dayKey)
7772
+ )
7771
7773
  )
7772
- )
7773
- )).flat();
7774
- const dedupedBucketTrades = /* @__PURE__ */ new Map();
7775
- for (const trade of bucketTrades) {
7774
+ ),
7775
+ (0, import_redis4.getKeys)(import_redis4.redisKeys.runtimeTrades(userName))
7776
+ ]);
7777
+ const legacyTradeKeys = legacyKeys.filter(
7778
+ (key) => !key.startsWith(import_redis4.redisKeys.runtimeTradeBuckets(userName))
7779
+ );
7780
+ const legacyTrades = await Promise.all(
7781
+ legacyTradeKeys.map((key) => (0, import_redis4.getData)(key, null))
7782
+ );
7783
+ const dedupedTrades = /* @__PURE__ */ new Map();
7784
+ for (const trade of [...legacyTrades, ...bucketTradeGroups.flat()]) {
7776
7785
  if (!(0, import_runtimeTrades3.isRuntimeTradeRecord)(trade)) {
7777
7786
  continue;
7778
7787
  }
7779
- dedupedBucketTrades.set(trade.orderId, trade);
7788
+ const existing = dedupedTrades.get(trade.orderId);
7789
+ if (!existing || (trade.lastSyncedAt ?? Number.NEGATIVE_INFINITY) >= (existing.lastSyncedAt ?? Number.NEGATIVE_INFINITY)) {
7790
+ dedupedTrades.set(trade.orderId, trade);
7791
+ }
7780
7792
  }
7781
- if (dedupedBucketTrades.size > 0 || dayKeys.length === 0) {
7782
- return [...dedupedBucketTrades.values()].filter(filterByWindow).sort((left, right) => left.entryTimestamp - right.entryTimestamp);
7793
+ return [...dedupedTrades.values()].filter(filterByWindow).sort((left, right) => left.entryTimestamp - right.entryTimestamp);
7794
+ };
7795
+ var getTradeStrategyRevision = (trade) => trade.strategyRevision ?? (trade.runtimeLineage?.schemaVersion === 3 ? trade.runtimeLineage.strategyRevision : void 0);
7796
+ var buildStrategyRevisionChanges = (trades) => {
7797
+ const changes = [];
7798
+ let previousRevision;
7799
+ for (const trade of [...trades].sort(
7800
+ (left, right) => left.entryTimestamp - right.entryTimestamp || left.orderId.localeCompare(right.orderId)
7801
+ )) {
7802
+ const strategyRevision = getTradeStrategyRevision(trade);
7803
+ if (!strategyRevision) continue;
7804
+ if (previousRevision && strategyRevision !== previousRevision) {
7805
+ changes.push({
7806
+ timestamp: trade.entryTimestamp,
7807
+ strategyRevision
7808
+ });
7809
+ }
7810
+ previousRevision = strategyRevision;
7783
7811
  }
7784
- const keys = await (0, import_redis4.getKeys)(import_redis4.redisKeys.runtimeTrades(userName));
7785
- const trades = await Promise.all(keys.map((key) => (0, import_redis4.getData)(key, null)));
7786
- return trades.filter(import_runtimeTrades3.isRuntimeTradeRecord).filter(filterByWindow).sort((left, right) => left.entryTimestamp - right.entryTimestamp);
7812
+ return changes;
7787
7813
  };
7788
7814
  var buildExchangeTimeRanges = (startTime, endTime) => {
7789
7815
  const ranges = [];
@@ -8024,14 +8050,6 @@ var loadRuntimeDashboard = async ({
8024
8050
  )
8025
8051
  )
8026
8052
  );
8027
- const runtimeIdentityKey = (trade) => (0, import_runtimeTrades3.buildRuntimeStrategyIdentityKey)({
8028
- strategyName: trade.strategy,
8029
- configId: trade.strategyRevision,
8030
- universe: trade.universe,
8031
- accountId: trade.accountId,
8032
- deploymentId: trade.deploymentId,
8033
- policyProfileId: trade.policyProfileId
8034
- });
8035
8053
  const identityByKey = /* @__PURE__ */ new Map();
8036
8054
  for (const deployment of runtimeDeployments) {
8037
8055
  for (const resolvedStrategy of resolvedStrategiesByDeployment.get(
@@ -8067,24 +8085,12 @@ var loadRuntimeDashboard = async ({
8067
8085
  });
8068
8086
  }
8069
8087
  }
8070
- const accountScopedTrades = allTrades;
8071
- for (const trade of accountScopedTrades) {
8072
- const key = runtimeIdentityKey(trade);
8073
- const configuredIdentity = identityByKey.get(key);
8074
- if (!configuredIdentity) continue;
8075
- const strategyRevision = trade.strategyRevision ?? (trade.runtimeLineage?.schemaVersion === 3 ? trade.runtimeLineage.strategyRevision : void 0);
8076
- if (strategyRevision !== configuredIdentity.strategyRevision) continue;
8077
- identityByKey.set(key, {
8078
- ...configuredIdentity,
8079
- interval: String(
8080
- trade.interval ?? configuredIdentity.interval
8081
- )
8082
- });
8083
- }
8084
8088
  const strategies2 = await Promise.all(
8085
8089
  [...identityByKey.entries()].map(async ([runtimeKey, identity]) => {
8086
8090
  const { strategyName } = identity;
8087
- const strategyTrades = accountScopedTrades.filter((trade) => runtimeIdentityKey(trade) === runtimeKey).sort((left, right) => right.entryTimestamp - left.entryTimestamp);
8091
+ const strategyTrades = allTrades.filter(
8092
+ (trade) => trade.strategy === strategyName && String(trade.interval) === String(identity.interval)
8093
+ ).sort((left, right) => right.entryTimestamp - left.entryTimestamp);
8088
8094
  const orders = strategyTrades.sort((left, right) => {
8089
8095
  const leftDate = left.exitTimestamp ?? left.entryTimestamp;
8090
8096
  const rightDate = right.exitTimestamp ?? right.entryTimestamp;
@@ -8116,6 +8122,7 @@ var loadRuntimeDashboard = async ({
8116
8122
  stat: analytics.stat,
8117
8123
  summary: analytics.summary,
8118
8124
  orderLog: analytics.orderLog,
8125
+ revisionChanges: buildStrategyRevisionChanges(strategyTrades),
8119
8126
  recentTrades: strategyTrades.slice(0, 8).map((trade) => (0, import_runtimeTrades3.toRuntimeTradeView)(trade, endTime)),
8120
8127
  orders
8121
8128
  };
@@ -271,26 +271,52 @@ var loadRuntimeTrades = async (userName, {
271
271
  }) => {
272
272
  const filterByWindow = (trade) => trade.entryTimestamp >= startTime || typeof trade.exitTimestamp === "number" && trade.exitTimestamp >= startTime;
273
273
  const dayKeys = getRuntimeStorageDayKeys(startTime, endTime);
274
- const bucketTrades = (await Promise.all(
275
- dayKeys.map(
276
- (dayKey) => getHashJsonValues(
277
- redisKeys2.runtimeTradeBucket(userName, dayKey)
274
+ const [bucketTradeGroups, legacyKeys] = await Promise.all([
275
+ Promise.all(
276
+ dayKeys.map(
277
+ (dayKey) => getHashJsonValues(
278
+ redisKeys2.runtimeTradeBucket(userName, dayKey)
279
+ )
278
280
  )
279
- )
280
- )).flat();
281
- const dedupedBucketTrades = /* @__PURE__ */ new Map();
282
- for (const trade of bucketTrades) {
281
+ ),
282
+ getKeys(redisKeys2.runtimeTrades(userName))
283
+ ]);
284
+ const legacyTradeKeys = legacyKeys.filter(
285
+ (key) => !key.startsWith(redisKeys2.runtimeTradeBuckets(userName))
286
+ );
287
+ const legacyTrades = await Promise.all(
288
+ legacyTradeKeys.map((key) => getData2(key, null))
289
+ );
290
+ const dedupedTrades = /* @__PURE__ */ new Map();
291
+ for (const trade of [...legacyTrades, ...bucketTradeGroups.flat()]) {
283
292
  if (!isRuntimeTradeRecord(trade)) {
284
293
  continue;
285
294
  }
286
- dedupedBucketTrades.set(trade.orderId, trade);
295
+ const existing = dedupedTrades.get(trade.orderId);
296
+ if (!existing || (trade.lastSyncedAt ?? Number.NEGATIVE_INFINITY) >= (existing.lastSyncedAt ?? Number.NEGATIVE_INFINITY)) {
297
+ dedupedTrades.set(trade.orderId, trade);
298
+ }
287
299
  }
288
- if (dedupedBucketTrades.size > 0 || dayKeys.length === 0) {
289
- return [...dedupedBucketTrades.values()].filter(filterByWindow).sort((left, right) => left.entryTimestamp - right.entryTimestamp);
300
+ return [...dedupedTrades.values()].filter(filterByWindow).sort((left, right) => left.entryTimestamp - right.entryTimestamp);
301
+ };
302
+ var getTradeStrategyRevision = (trade) => trade.strategyRevision ?? (trade.runtimeLineage?.schemaVersion === 3 ? trade.runtimeLineage.strategyRevision : void 0);
303
+ var buildStrategyRevisionChanges = (trades) => {
304
+ const changes = [];
305
+ let previousRevision;
306
+ for (const trade of [...trades].sort(
307
+ (left, right) => left.entryTimestamp - right.entryTimestamp || left.orderId.localeCompare(right.orderId)
308
+ )) {
309
+ const strategyRevision = getTradeStrategyRevision(trade);
310
+ if (!strategyRevision) continue;
311
+ if (previousRevision && strategyRevision !== previousRevision) {
312
+ changes.push({
313
+ timestamp: trade.entryTimestamp,
314
+ strategyRevision
315
+ });
316
+ }
317
+ previousRevision = strategyRevision;
290
318
  }
291
- const keys = await getKeys(redisKeys2.runtimeTrades(userName));
292
- const trades = await Promise.all(keys.map((key) => getData2(key, null)));
293
- return trades.filter(isRuntimeTradeRecord).filter(filterByWindow).sort((left, right) => left.entryTimestamp - right.entryTimestamp);
319
+ return changes;
294
320
  };
295
321
  var buildExchangeTimeRanges = (startTime, endTime) => {
296
322
  const ranges = [];
@@ -531,14 +557,6 @@ var loadRuntimeDashboard = async ({
531
557
  )
532
558
  )
533
559
  );
534
- const runtimeIdentityKey = (trade) => buildRuntimeStrategyIdentityKey({
535
- strategyName: trade.strategy,
536
- configId: trade.strategyRevision,
537
- universe: trade.universe,
538
- accountId: trade.accountId,
539
- deploymentId: trade.deploymentId,
540
- policyProfileId: trade.policyProfileId
541
- });
542
560
  const identityByKey = /* @__PURE__ */ new Map();
543
561
  for (const deployment of runtimeDeployments) {
544
562
  for (const resolvedStrategy of resolvedStrategiesByDeployment.get(
@@ -574,24 +592,12 @@ var loadRuntimeDashboard = async ({
574
592
  });
575
593
  }
576
594
  }
577
- const accountScopedTrades = allTrades;
578
- for (const trade of accountScopedTrades) {
579
- const key = runtimeIdentityKey(trade);
580
- const configuredIdentity = identityByKey.get(key);
581
- if (!configuredIdentity) continue;
582
- const strategyRevision = trade.strategyRevision ?? (trade.runtimeLineage?.schemaVersion === 3 ? trade.runtimeLineage.strategyRevision : void 0);
583
- if (strategyRevision !== configuredIdentity.strategyRevision) continue;
584
- identityByKey.set(key, {
585
- ...configuredIdentity,
586
- interval: String(
587
- trade.interval ?? configuredIdentity.interval
588
- )
589
- });
590
- }
591
595
  const strategies = await Promise.all(
592
596
  [...identityByKey.entries()].map(async ([runtimeKey, identity]) => {
593
597
  const { strategyName } = identity;
594
- const strategyTrades = accountScopedTrades.filter((trade) => runtimeIdentityKey(trade) === runtimeKey).sort((left, right) => right.entryTimestamp - left.entryTimestamp);
598
+ const strategyTrades = allTrades.filter(
599
+ (trade) => trade.strategy === strategyName && String(trade.interval) === String(identity.interval)
600
+ ).sort((left, right) => right.entryTimestamp - left.entryTimestamp);
595
601
  const orders = strategyTrades.sort((left, right) => {
596
602
  const leftDate = left.exitTimestamp ?? left.entryTimestamp;
597
603
  const rightDate = right.exitTimestamp ?? right.entryTimestamp;
@@ -623,6 +629,7 @@ var loadRuntimeDashboard = async ({
623
629
  stat: analytics.stat,
624
630
  summary: analytics.summary,
625
631
  orderLog: analytics.orderLog,
632
+ revisionChanges: buildStrategyRevisionChanges(strategyTrades),
626
633
  recentTrades: strategyTrades.slice(0, 8).map((trade) => toRuntimeTradeView(trade, endTime)),
627
634
  orders
628
635
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tradejs/node",
3
- "version": "3.1.18",
3
+ "version": "3.1.19-beta.234",
4
4
  "description": "Node-only runtime for the TradeJS TypeScript framework: strategies, backtests, Pine strategy loading, and plugin registries.",
5
5
  "keywords": [
6
6
  "tradejs",
@@ -89,9 +89,9 @@
89
89
  "dependencies": {
90
90
  "@langchain/core": "^1.2.3",
91
91
  "@langchain/openai": "^1.5.5",
92
- "@tradejs/core": "^3.1.18",
93
- "@tradejs/infra": "^3.1.18",
94
- "@tradejs/types": "^3.1.18",
92
+ "@tradejs/core": "^3.1.19-beta.234",
93
+ "@tradejs/infra": "^3.1.19-beta.234",
94
+ "@tradejs/types": "^3.1.19-beta.234",
95
95
  "@types/node": "^24",
96
96
  "chalk": "4.1.2",
97
97
  "ioredis": "5.11.1",
@@ -104,7 +104,7 @@
104
104
  "typescript": "^5.9"
105
105
  },
106
106
  "devDependencies": {
107
- "@tradejs/indicators": "^3.1.18",
107
+ "@tradejs/indicators": "^3.1.19-beta.234",
108
108
  "@tradejs/strategy-adaptive-momentum-ribbon": "3.0.2",
109
109
  "@tradejs/strategy-hyperliquid-consensus": "3.0.2",
110
110
  "@tradejs/strategy-kit": "3.0.3",