@tradejs/cli 3.1.29-beta.281 → 3.1.29-beta.283

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.
@@ -54,39 +54,6 @@ var isRuntimeTradeRecord = (value) => {
54
54
  const record = value;
55
55
  return typeof record.orderId === "string" && typeof record.strategy === "string" && typeof record.symbol === "string" && typeof record.entryTimestamp === "number" && typeof record.entryPrice === "number" && typeof record.qty === "number" && (record.direction === "LONG" || record.direction === "SHORT");
56
56
  };
57
- var loadRuntimeTrades = async (userName, {
58
- startTime,
59
- endTime
60
- } = {}) => {
61
- const hasWindow = Number.isFinite(startTime) && Number.isFinite(endTime) && startTime != null && endTime != null;
62
- const filterByWindow = (trade) => !hasWindow || trade.entryTimestamp >= startTime && trade.entryTimestamp <= endTime;
63
- if (hasWindow) {
64
- const dayKeys = (0, import_time.getRuntimeStorageDayKeys)(startTime, endTime);
65
- const bucketTrades = (await Promise.all(
66
- dayKeys.map(
67
- (dayKey) => (0, import_redis.getHashJsonValues)(
68
- import_redis.redisKeys.runtimeTradeBucket(userName, dayKey)
69
- )
70
- )
71
- )).flat();
72
- const dedupedBucketTrades = /* @__PURE__ */ new Map();
73
- for (const trade of bucketTrades) {
74
- if (!isRuntimeTradeRecord(trade)) {
75
- continue;
76
- }
77
- dedupedBucketTrades.set(trade.orderId, trade);
78
- }
79
- const windowedTrades = [...dedupedBucketTrades.values()].filter(filterByWindow).sort((left, right) => left.entryTimestamp - right.entryTimestamp);
80
- return windowedTrades;
81
- }
82
- const tradePrefix = import_redis.redisKeys.runtimeTrades(userName);
83
- const bucketPrefix = import_redis.redisKeys.runtimeTradeBuckets(userName);
84
- const keys = (await (0, import_redis.getKeys)(tradePrefix)).filter(
85
- (key) => !key.startsWith(bucketPrefix)
86
- );
87
- const trades = await Promise.all(keys.map((key) => (0, import_redis.getData)(key, null)));
88
- return trades.filter(isRuntimeTradeRecord).filter(filterByWindow).sort((left, right) => left.entryTimestamp - right.entryTimestamp);
89
- };
90
57
  var loadRuntimeClosedTrades = async (userName, {
91
58
  startTime,
92
59
  endTime
@@ -110,6 +77,49 @@ var loadRuntimeClosedTrades = async (userName, {
110
77
  (left, right) => left.exitTimestamp - right.exitTimestamp
111
78
  );
112
79
  };
80
+ var loadRuntimeEvidenceTrades = async (userName, { startTime, endTime }) => {
81
+ const prefix = import_redis.redisKeys.runtimeTradeBuckets(userName);
82
+ const lastDay = (0, import_time.getRuntimeStorageDayKey)(endTime - 1);
83
+ const keys = (await (0, import_redis.getKeys)(prefix)).filter((key) => {
84
+ const day = key.slice(prefix.length);
85
+ return key.startsWith(prefix) && /^\d{4}-\d{2}-\d{2}$/.test(day) && day <= lastDay;
86
+ });
87
+ const retained = /* @__PURE__ */ new Map();
88
+ for (let offset = 0; offset < keys.length; offset += 16) {
89
+ const buckets = await Promise.all(
90
+ keys.slice(offset, offset + 16).map((key) => (0, import_redis.getHashJsonValues)(key))
91
+ );
92
+ for (const row of buckets.flat())
93
+ if (isRuntimeTradeRecord(row)) retained.set(row.orderId, row);
94
+ }
95
+ for (const row of await loadRuntimeClosedTrades(userName, {
96
+ startTime,
97
+ endTime
98
+ }))
99
+ retained.set(row.orderId, row);
100
+ return [...retained.values()].filter(
101
+ (row) => row.entryTimestamp < endTime && (row.status === "active" || Number.isFinite(row.exitTimestamp) && row.exitTimestamp >= startTime)
102
+ ).map((row) => {
103
+ const closesAfterCutoff = row.status === "closed" && row.exitTimestamp >= endTime;
104
+ if (!closesAfterCutoff && !(row.status === "active" && row.lastSyncedAt >= endTime))
105
+ return row;
106
+ return {
107
+ ...row,
108
+ status: "active",
109
+ currentPrice: null,
110
+ currentPnl: null,
111
+ closedPnl: null,
112
+ exitPrice: null,
113
+ actualExitPrice: null,
114
+ exitTimestamp: null,
115
+ exitType: null,
116
+ closeFee: null,
117
+ fundingFee: null,
118
+ totalFee: null,
119
+ lastSyncedAt: void 0
120
+ };
121
+ }).sort((a, b) => a.entryTimestamp - b.entryTimestamp);
122
+ };
113
123
 
114
124
  // src/lib/runtimeSignalsLoader.ts
115
125
  var import_redis2 = require("@tradejs/infra/redis");
@@ -312,30 +322,13 @@ var collectRuntimeDebugEvidence = async ({
312
322
  }) => {
313
323
  const dayKeys = (0, import_time2.getRuntimeStorageDayKeys)(startTime, endTime);
314
324
  const dayKeySet = new Set(dayKeys);
315
- const [
316
- entryTrades,
317
- closedTrades,
318
- signals,
319
- evaluations,
320
- evaluationStatsBuckets,
321
- lineageScopes
322
- ] = await Promise.all([
323
- loadRuntimeTrades(userName, { startTime, endTime }),
324
- loadRuntimeClosedTrades(userName, { startTime, endTime }),
325
+ const [trades, signals, evaluations, evaluationStatsBuckets, lineageScopes] = await Promise.all([
326
+ loadRuntimeEvidenceTrades(userName, { startTime, endTime }),
325
327
  loadRuntimeSignals(userName, { startTime, endTime }),
326
328
  loadRuntimeSignalEvaluations(userName, { startTime, endTime }),
327
329
  loadRuntimeSignalEvaluationStatsBuckets(userName),
328
330
  loadRuntimeLineageScopes(userName, { startTime, endTime })
329
331
  ]);
330
- const tradesByOrderId = new Map(
331
- entryTrades.map((trade) => [trade.orderId, trade])
332
- );
333
- for (const trade of closedTrades) {
334
- tradesByOrderId.set(trade.orderId, trade);
335
- }
336
- const trades = [...tradesByOrderId.values()].sort(
337
- (left, right) => left.entryTimestamp - right.entryTimestamp
338
- );
339
332
  const filteredStats = evaluationStatsBuckets.filter(
340
333
  (entry) => dayKeySet.has(entry.dayKey) && (!deploymentId || entry.deploymentId === deploymentId) && (!strategies?.length || strategies.includes(entry.strategy))
341
334
  );