@tradejs/cli 1.0.9 → 1.0.10

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.
Files changed (76) hide show
  1. package/dist/cli.js +29497 -13537
  2. package/dist/lib/aiPocketSearch.js +1316 -0
  3. package/dist/lib/aiTrainCharts.js +711 -0
  4. package/dist/lib/aiTrainDataset.js +40 -0
  5. package/dist/lib/aiTrainEvaluationDump.js +76 -0
  6. package/dist/lib/aiTrainMetrics.js +148 -8
  7. package/dist/lib/aiTrainOptions.js +130 -0
  8. package/dist/lib/aiTrainQuarantine.js +199 -0
  9. package/dist/lib/aiTrainResearch.js +467 -0
  10. package/dist/lib/binanceMarketContextBackfill.js +841 -0
  11. package/dist/lib/binanceMarketData.js +392 -0
  12. package/dist/lib/coinMarketCapContextBackfill.js +1088 -0
  13. package/dist/lib/continuity.js +60 -0
  14. package/dist/lib/derivativesContextBackfill.js +490 -77
  15. package/dist/lib/executionCalibration.js +705 -0
  16. package/dist/lib/marketContextPrepare.js +4403 -0
  17. package/dist/lib/paritySummary.js +101 -0
  18. package/dist/lib/runBot.js +1 -0
  19. package/dist/lib/runEnvironment.js +2254 -0
  20. package/dist/lib/runFormatting.js +1657 -0
  21. package/dist/lib/runtimeDebugEvidence.js +526 -0
  22. package/dist/lib/runtimeModeConfig.js +53 -0
  23. package/dist/lib/runtimeParity.js +88 -11
  24. package/dist/lib/runtimeParityDetails.js +751 -0
  25. package/dist/lib/runtimeRedis.js +157 -0
  26. package/dist/lib/runtimeSignalsLoader.js +40 -6
  27. package/dist/lib/runtimeSignalsStorage.js +45 -22
  28. package/dist/lib/runtimeStrategyBacktest.js +134 -0
  29. package/dist/lib/runtimeTradeSync.js +263 -0
  30. package/dist/lib/telegramReports.js +9 -0
  31. package/dist/lib/tickerUniverseCache.js +116 -0
  32. package/dist/lib/timeWindow.js +3 -3
  33. package/dist/scripts/agentRun.js +14 -8
  34. package/dist/scripts/aiExport.js +1721 -7
  35. package/dist/scripts/aiExportSelect.js +16 -4
  36. package/dist/scripts/aiPocketSearch.js +4190 -0
  37. package/dist/scripts/aiTrain.js +1866 -87
  38. package/dist/scripts/backtest.js +4509 -818
  39. package/dist/scripts/binanceMarketIngest.js +565 -0
  40. package/dist/scripts/bot.js +16 -2
  41. package/dist/scripts/candlesMigrateProvider.js +32 -22
  42. package/dist/scripts/cleanDir.js +15 -2
  43. package/dist/scripts/cleanRedis.js +15 -2
  44. package/dist/scripts/cleanTests.js +38 -2
  45. package/dist/scripts/cleanupMarketContext.js +69 -0
  46. package/dist/scripts/continuity.js +148 -67
  47. package/dist/scripts/derivativesIngest.js +14 -4
  48. package/dist/scripts/derivativesIngestCoinalyzeAll.js +14 -4
  49. package/dist/scripts/doctor.js +14 -4
  50. package/dist/scripts/executionCalibration.js +792 -0
  51. package/dist/scripts/infraCommon.js +10 -0
  52. package/dist/scripts/infraDown.js +14 -4
  53. package/dist/scripts/infraInit.js +24 -4
  54. package/dist/scripts/infraUp.js +14 -4
  55. package/dist/scripts/marketWs.js +222 -0
  56. package/dist/scripts/migration.js +15 -2
  57. package/dist/scripts/mlExport.js +1698 -10
  58. package/dist/scripts/mlExportSelect.js +16 -4
  59. package/dist/scripts/mlInspect.js +13 -3
  60. package/dist/scripts/mlTrainLatestSelect.js +14 -4
  61. package/dist/scripts/replay.js +8824 -0
  62. package/dist/scripts/replayRunner.js +8827 -0
  63. package/dist/scripts/replayRuntimeEvidence.js +868 -0
  64. package/dist/scripts/researchAuto.js +286 -59
  65. package/dist/scripts/results.js +3 -3
  66. package/dist/scripts/runtimeEvidence.js +605 -0
  67. package/dist/scripts/runtimeParity.js +6362 -1043
  68. package/dist/scripts/serverHealth.js +588 -0
  69. package/dist/scripts/signals.js +5590 -511
  70. package/dist/scripts/signalsDaemon.js +6167 -0
  71. package/dist/scripts/signalsSummary.js +833 -248
  72. package/dist/scripts/test-ml.js +25 -3
  73. package/dist/scripts/test.js +26 -1
  74. package/dist/scripts/user-add.js +15 -2
  75. package/dist/workers/testerWorker.js +130 -21
  76. package/package.json +18 -12
@@ -0,0 +1,526 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/lib/runtimeDebugEvidence.ts
21
+ var runtimeDebugEvidence_exports = {};
22
+ __export(runtimeDebugEvidence_exports, {
23
+ RUNTIME_DEBUG_TIMEZONE: () => RUNTIME_DEBUG_TIMEZONE,
24
+ RUNTIME_DEBUG_TIMEZONE_LABEL: () => RUNTIME_DEBUG_TIMEZONE_LABEL,
25
+ buildRuntimeDebugEvaluationId: () => buildRuntimeDebugEvaluationId,
26
+ buildRuntimeDebugReportAttachment: () => buildRuntimeDebugReportAttachment,
27
+ buildRuntimeDebugReportPayload: () => buildRuntimeDebugReportPayload,
28
+ collectRuntimeDebugEvidence: () => collectRuntimeDebugEvidence
29
+ });
30
+ module.exports = __toCommonJS(runtimeDebugEvidence_exports);
31
+ var import_redis3 = require("@tradejs/infra/redis");
32
+
33
+ // src/lib/runtimeRedis.ts
34
+ var import_redis = require("@tradejs/infra/redis");
35
+ var import_time = require("@tradejs/core/time");
36
+ var RESERVED_STRATEGY_NAMES = /* @__PURE__ */ new Set(["charts"]);
37
+ var RESERVED_CONFIG_IDS = /* @__PURE__ */ new Set(["results"]);
38
+ var resolveStrategyConfigIdentityByKey = (userName, key) => {
39
+ const parts = key.split(":");
40
+ if (parts.length !== 5) return null;
41
+ const [users, keyUserName, strategiesKey, strategyName, configId] = parts;
42
+ if (users !== "users" || keyUserName !== userName || strategiesKey !== "strategies" || !strategyName || !configId || RESERVED_STRATEGY_NAMES.has(strategyName) || RESERVED_CONFIG_IDS.has(configId) || !/^[a-zA-Z0-9_-]+$/.test(configId)) {
43
+ return null;
44
+ }
45
+ return { strategyName, configId };
46
+ };
47
+ var isRuntimeTradeRecord = (value) => {
48
+ if (!value || typeof value !== "object") {
49
+ return false;
50
+ }
51
+ const record = value;
52
+ 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");
53
+ };
54
+ var resolveStrategyNameByConfigKey = (userName, key) => {
55
+ return resolveStrategyConfigIdentityByKey(userName, key)?.strategyName ?? null;
56
+ };
57
+ var getRuntimeStrategyConfigKeys = async (userName) => {
58
+ const keys = await (0, import_redis.getKeys)(`${import_redis.redisKeys.strategies(userName)}:`);
59
+ return keys.filter((key) => resolveStrategyConfigIdentityByKey(userName, key)).sort((left, right) => left.localeCompare(right));
60
+ };
61
+ var loadRuntimeStrategyConfigs = async (userName, {
62
+ onInvalidConfig
63
+ } = {}) => {
64
+ const configKeys = await getRuntimeStrategyConfigKeys(userName);
65
+ const strategyConfigs = await Promise.all(
66
+ configKeys.map(async (key) => {
67
+ const strategyName = resolveStrategyNameByConfigKey(userName, key);
68
+ const identity = resolveStrategyConfigIdentityByKey(userName, key);
69
+ if (!strategyName || !identity) {
70
+ return null;
71
+ }
72
+ const strategyConfig = await (0, import_redis.getData)(
73
+ key,
74
+ null
75
+ );
76
+ if (!strategyConfig || typeof strategyConfig !== "object" || Array.isArray(strategyConfig)) {
77
+ onInvalidConfig?.(key);
78
+ return null;
79
+ }
80
+ return {
81
+ key,
82
+ strategyName,
83
+ configId: identity.configId,
84
+ strategyConfig
85
+ };
86
+ })
87
+ );
88
+ return strategyConfigs.filter(Boolean);
89
+ };
90
+ var loadRuntimeTrades = async (userName, {
91
+ startTime,
92
+ endTime
93
+ } = {}) => {
94
+ const hasWindow = Number.isFinite(startTime) && Number.isFinite(endTime) && startTime != null && endTime != null;
95
+ const filterByWindow = (trade) => !hasWindow || trade.entryTimestamp >= startTime && trade.entryTimestamp <= endTime;
96
+ if (hasWindow) {
97
+ const dayKeys = (0, import_time.getRuntimeStorageDayKeys)(startTime, endTime);
98
+ const bucketTrades = (await Promise.all(
99
+ dayKeys.map(
100
+ (dayKey) => (0, import_redis.getHashJsonValues)(
101
+ import_redis.redisKeys.runtimeTradeBucket(userName, dayKey)
102
+ )
103
+ )
104
+ )).flat();
105
+ const dedupedBucketTrades = /* @__PURE__ */ new Map();
106
+ for (const trade of bucketTrades) {
107
+ if (!isRuntimeTradeRecord(trade)) {
108
+ continue;
109
+ }
110
+ dedupedBucketTrades.set(trade.orderId, trade);
111
+ }
112
+ const windowedTrades = [...dedupedBucketTrades.values()].filter(filterByWindow).sort((left, right) => left.entryTimestamp - right.entryTimestamp);
113
+ if (windowedTrades.length > 0 || dayKeys.length === 0) {
114
+ return windowedTrades;
115
+ }
116
+ }
117
+ const tradePrefix = import_redis.redisKeys.runtimeTrades(userName);
118
+ const bucketPrefix = import_redis.redisKeys.runtimeTradeBuckets(userName);
119
+ const keys = (await (0, import_redis.getKeys)(tradePrefix)).filter(
120
+ (key) => !key.startsWith(bucketPrefix)
121
+ );
122
+ const trades = await Promise.all(keys.map((key) => (0, import_redis.getData)(key, null)));
123
+ return trades.filter(isRuntimeTradeRecord).filter(filterByWindow).sort((left, right) => left.entryTimestamp - right.entryTimestamp);
124
+ };
125
+
126
+ // src/lib/runtimeSignalsLoader.ts
127
+ var import_redis2 = require("@tradejs/infra/redis");
128
+
129
+ // src/lib/runtimeSignalsStorage.ts
130
+ var import_constants = require("@tradejs/core/constants");
131
+ var import_time2 = require("@tradejs/core/time");
132
+ var isRuntimeSignalBucketRef = (value) => {
133
+ if (!value || typeof value !== "object") {
134
+ return false;
135
+ }
136
+ const record = value;
137
+ return typeof record.signalId === "string" && typeof record.symbol === "string" && typeof record.strategy === "string" && typeof record.timestamp === "number";
138
+ };
139
+ var toCount = (value) => {
140
+ const parsed = Number.parseInt(String(value ?? "0"), 10);
141
+ return Number.isFinite(parsed) ? parsed : 0;
142
+ };
143
+ var parseRuntimeSignalStatsBucket = (value) => {
144
+ const reasonGroups = /* @__PURE__ */ new Map();
145
+ for (const [field, rawCount] of Object.entries(value)) {
146
+ if (!field.startsWith("reason:")) {
147
+ continue;
148
+ }
149
+ const [, source, ...reasonParts] = field.split(":");
150
+ const reason = reasonParts.join(":");
151
+ if (!source || !reason) {
152
+ continue;
153
+ }
154
+ const reasons = reasonGroups.get(source) ?? /* @__PURE__ */ new Map();
155
+ reasons.set(reason, toCount(rawCount));
156
+ reasonGroups.set(source, reasons);
157
+ }
158
+ return {
159
+ evaluated: toCount(value.evaluated),
160
+ signals: toCount(value.signals),
161
+ reasonGroups
162
+ };
163
+ };
164
+
165
+ // src/lib/runtimeSignalsLoader.ts
166
+ var isSignalRecord = (value) => {
167
+ if (!value || typeof value !== "object") {
168
+ return false;
169
+ }
170
+ const record = value;
171
+ return typeof record.signalId === "string" && typeof record.strategy === "string" && typeof record.symbol === "string" && typeof record.timestamp === "number";
172
+ };
173
+ var isRuntimeSignalEvaluationRecord = (value) => {
174
+ if (!value || typeof value !== "object") {
175
+ return false;
176
+ }
177
+ const record = value;
178
+ return typeof record.evaluationId === "string" && typeof record.strategy === "string" && typeof record.symbol === "string" && typeof record.timestamp === "number" && (record.status === "signal" || record.status === "skip" || record.status === "error");
179
+ };
180
+ var sortByTimestamp = (records) => [...records].sort((left, right) => left.timestamp - right.timestamp);
181
+ var filterBucketKeysByWindow = (bucketKeys, prefix, startTime, endTime) => {
182
+ if (!Number.isFinite(startTime) || !Number.isFinite(endTime) || startTime == null || endTime == null) {
183
+ return bucketKeys;
184
+ }
185
+ const allowedDayKeys = new Set((0, import_time2.getRuntimeStorageDayKeys)(startTime, endTime));
186
+ if (!allowedDayKeys.size) {
187
+ return [];
188
+ }
189
+ return bucketKeys.filter((key) => {
190
+ const suffix = key.slice(prefix.length);
191
+ const firstColon = suffix.indexOf(":");
192
+ if (firstColon <= 0) {
193
+ return false;
194
+ }
195
+ return allowedDayKeys.has(suffix.slice(0, firstColon));
196
+ });
197
+ };
198
+ var loadRuntimeSignals = async (userName, {
199
+ startTime,
200
+ endTime
201
+ } = {}) => {
202
+ const bucketPrefix = import_redis2.redisKeys.runtimeSignalBuckets(userName);
203
+ const bucketKeys = filterBucketKeysByWindow(
204
+ await (0, import_redis2.getKeys)(bucketPrefix),
205
+ bucketPrefix,
206
+ startTime,
207
+ endTime
208
+ );
209
+ const refs = (await Promise.all(bucketKeys.map((key) => (0, import_redis2.getHashJsonValues)(key)))).flat().filter(isRuntimeSignalBucketRef);
210
+ const seen = /* @__PURE__ */ new Set();
211
+ const payloads = await Promise.all(
212
+ refs.map(async (ref) => {
213
+ const dedupeKey = `${ref.symbol}:${ref.signalId}`;
214
+ if (seen.has(dedupeKey)) {
215
+ return null;
216
+ }
217
+ seen.add(dedupeKey);
218
+ const signal = await (0, import_redis2.getData)(
219
+ import_redis2.redisKeys.storeSignal(ref.symbol, ref.signalId),
220
+ null
221
+ );
222
+ return isSignalRecord(signal) ? signal : null;
223
+ })
224
+ );
225
+ return sortByTimestamp(payloads.filter(isSignalRecord));
226
+ };
227
+ var loadRuntimeSignalEvaluations = async (userName, {
228
+ startTime,
229
+ endTime
230
+ } = {}) => {
231
+ const bucketPrefix = import_redis2.redisKeys.runtimeSignalEvaluationBuckets(userName);
232
+ const bucketKeys = filterBucketKeysByWindow(
233
+ await (0, import_redis2.getKeys)(bucketPrefix),
234
+ bucketPrefix,
235
+ startTime,
236
+ endTime
237
+ );
238
+ const evaluations = (await Promise.all(bucketKeys.map((key) => (0, import_redis2.getHashJsonValues)(key)))).flat().filter(isRuntimeSignalEvaluationRecord);
239
+ const deduped = /* @__PURE__ */ new Map();
240
+ for (const evaluation of evaluations) {
241
+ deduped.set(evaluation.evaluationId, evaluation);
242
+ }
243
+ return sortByTimestamp([...deduped.values()]);
244
+ };
245
+ var parseBucketKey = (prefix, key) => {
246
+ if (!key.startsWith(prefix)) {
247
+ return null;
248
+ }
249
+ const suffix = key.slice(prefix.length);
250
+ const firstColon = suffix.indexOf(":");
251
+ if (firstColon <= 0 || firstColon >= suffix.length - 1) {
252
+ return null;
253
+ }
254
+ return {
255
+ dayKey: suffix.slice(0, firstColon),
256
+ strategy: suffix.slice(firstColon + 1)
257
+ };
258
+ };
259
+ var loadRuntimeSignalEvaluationStatsBuckets = async (userName) => {
260
+ const prefix = import_redis2.redisKeys.runtimeSignalEvaluationStatsBuckets(userName);
261
+ const keys = await (0, import_redis2.getKeys)(prefix);
262
+ const entries = await Promise.all(
263
+ keys.map(async (key) => {
264
+ const parsedKey = parseBucketKey(prefix, key);
265
+ if (!parsedKey) {
266
+ return null;
267
+ }
268
+ return {
269
+ key,
270
+ ...parsedKey,
271
+ stats: parseRuntimeSignalStatsBucket(await (0, import_redis2.getHashData)(key))
272
+ };
273
+ })
274
+ );
275
+ return entries.filter(Boolean);
276
+ };
277
+
278
+ // src/lib/runtimeDebugEvidence.ts
279
+ var RUNTIME_DEBUG_TIMEZONE = "Europe/Moscow";
280
+ var RUNTIME_DEBUG_TIMEZONE_LABEL = "MSK";
281
+ var formatRuntimeDebugDateTime = (timestamp) => new Intl.DateTimeFormat("ru-RU", {
282
+ timeZone: RUNTIME_DEBUG_TIMEZONE,
283
+ year: "numeric",
284
+ month: "2-digit",
285
+ day: "2-digit",
286
+ hour: "2-digit",
287
+ minute: "2-digit",
288
+ hour12: false
289
+ }).format(new Date(timestamp));
290
+ var getRuntimeDebugDateParts = (timestamp) => Object.fromEntries(
291
+ new Intl.DateTimeFormat("en-US", {
292
+ timeZone: RUNTIME_DEBUG_TIMEZONE,
293
+ year: "numeric",
294
+ month: "2-digit",
295
+ day: "2-digit"
296
+ }).formatToParts(new Date(timestamp)).map((part) => [part.type, part.value])
297
+ );
298
+ var formatRuntimeDebugIsoDayKey = (timestamp) => {
299
+ const parts = getRuntimeDebugDateParts(timestamp);
300
+ return `${parts.year}-${parts.month}-${parts.day}`;
301
+ };
302
+ var buildRuntimeDebugEvaluationId = ({
303
+ strategy,
304
+ symbol,
305
+ timestamp
306
+ }) => `${strategy}:${symbol}:${timestamp}`;
307
+ var filterByStrategies = (values, strategies) => {
308
+ if (!strategies?.length) {
309
+ return values;
310
+ }
311
+ const strategySet = new Set(strategies);
312
+ return values.filter((value) => strategySet.has(value.strategy));
313
+ };
314
+ var collectRuntimeDebugEvidence = async ({
315
+ userName,
316
+ startTime,
317
+ endTime,
318
+ strategies
319
+ }) => {
320
+ const dayKeys = (0, import_time2.getRuntimeStorageDayKeys)(startTime, endTime);
321
+ const dayKeySet = new Set(dayKeys);
322
+ const [trades, signals, evaluations, evaluationStatsBuckets, configs] = await Promise.all([
323
+ loadRuntimeTrades(userName, { startTime, endTime }),
324
+ loadRuntimeSignals(userName, { startTime, endTime }),
325
+ loadRuntimeSignalEvaluations(userName, { startTime, endTime }),
326
+ loadRuntimeSignalEvaluationStatsBuckets(userName),
327
+ loadRuntimeStrategyConfigs(userName)
328
+ ]);
329
+ const filteredStats = evaluationStatsBuckets.filter(
330
+ (entry) => dayKeySet.has(entry.dayKey) && (!strategies?.length || strategies.includes(entry.strategy))
331
+ );
332
+ return {
333
+ dayKeys,
334
+ trades: filterByStrategies(trades, strategies),
335
+ signals: filterByStrategies(signals, strategies),
336
+ evaluations: filterByStrategies(evaluations, strategies),
337
+ evaluationStatsBuckets: filteredStats,
338
+ strategyConfigs: configs.filter(
339
+ (config) => !strategies?.length || strategies.includes(config.strategyName)
340
+ )
341
+ };
342
+ };
343
+ var buildRuntimeDebugReportPayload = async ({
344
+ userName,
345
+ startTime,
346
+ endTime,
347
+ signals,
348
+ evaluations,
349
+ trades,
350
+ strategyConfigs,
351
+ evaluationStatsBuckets
352
+ }) => {
353
+ const signalById = new Map(
354
+ signals.map((signal) => [signal.signalId, signal])
355
+ );
356
+ const evaluationById = new Map(
357
+ evaluations.map((evaluation) => [evaluation.evaluationId, evaluation])
358
+ );
359
+ const evaluationBySignalShape = new Map(
360
+ evaluations.map((evaluation) => [
361
+ buildRuntimeDebugEvaluationId(evaluation),
362
+ evaluation
363
+ ])
364
+ );
365
+ const dayKeys = (0, import_time2.getRuntimeStorageDayKeys)(startTime, endTime);
366
+ const debugTrades = await Promise.all(
367
+ trades.map(async (trade) => {
368
+ const signal = trade.signalId != null ? signalById.get(trade.signalId) : void 0;
369
+ const evaluationId = buildRuntimeDebugEvaluationId({
370
+ strategy: trade.strategy,
371
+ symbol: trade.symbol,
372
+ timestamp: signal?.timestamp ?? trade.entryTimestamp
373
+ });
374
+ const knownEvaluation = evaluationById.get(evaluationId) ?? evaluationBySignalShape.get(evaluationId);
375
+ const tradeDayKey = (0, import_time2.getRuntimeStorageDayKey)(trade.entryTimestamp);
376
+ const signalDayKey = signal != null ? (0, import_time2.getRuntimeStorageDayKey)(signal.timestamp) : tradeDayKey;
377
+ const evaluationDayKey = knownEvaluation != null ? (0, import_time2.getRuntimeStorageDayKey)(knownEvaluation.timestamp) : signalDayKey;
378
+ const tradeKey = import_redis3.redisKeys.runtimeTrade(userName, trade.orderId);
379
+ const tradeBucketKey = import_redis3.redisKeys.runtimeTradeBucket(
380
+ userName,
381
+ tradeDayKey
382
+ );
383
+ const activeTradeKey = import_redis3.redisKeys.runtimeActiveTrade(
384
+ userName,
385
+ trade.symbol
386
+ );
387
+ const signalKey = trade.signalId != null ? import_redis3.redisKeys.storeSignal(trade.symbol, trade.signalId) : null;
388
+ const evaluationBucketKey = import_redis3.redisKeys.runtimeSignalEvaluationBucket(
389
+ userName,
390
+ evaluationDayKey,
391
+ knownEvaluation?.strategy ?? trade.strategy
392
+ );
393
+ const evaluationField = knownEvaluation?.evaluationId ?? evaluationId;
394
+ const evaluationKey = import_redis3.redisKeys.runtimeSignalEvaluation(
395
+ userName,
396
+ evaluationField
397
+ );
398
+ const [
399
+ tradeValue,
400
+ activeTradeValue,
401
+ signalValue,
402
+ directEvaluationValue,
403
+ bucketEvaluationValue
404
+ ] = await Promise.all([
405
+ (0, import_redis3.getData)(tradeKey, null),
406
+ (0, import_redis3.getData)(activeTradeKey, null),
407
+ signalKey ? (0, import_redis3.getData)(signalKey, null) : Promise.resolve(null),
408
+ (0, import_redis3.getData)(evaluationKey, null),
409
+ knownEvaluation ? Promise.resolve(knownEvaluation) : (0, import_redis3.getHashJsonField)(
410
+ evaluationBucketKey,
411
+ evaluationField,
412
+ null
413
+ )
414
+ ]);
415
+ const evaluationValue = directEvaluationValue ?? bucketEvaluationValue ?? knownEvaluation ?? null;
416
+ return {
417
+ redisDebug: {
418
+ trade: tradeKey,
419
+ tradeBucket: {
420
+ key: tradeBucketKey,
421
+ field: trade.orderId
422
+ },
423
+ activeTrade: activeTradeKey,
424
+ signal: signalKey,
425
+ evaluation: {
426
+ key: evaluationBucketKey,
427
+ field: evaluationField,
428
+ directKey: evaluationKey
429
+ }
430
+ },
431
+ trade,
432
+ redisValues: {
433
+ trade: tradeValue,
434
+ tradeBucket: trade,
435
+ activeTrade: activeTradeValue,
436
+ signal: signalValue ?? signal ?? null,
437
+ evaluation: evaluationValue ?? knownEvaluation ?? null
438
+ }
439
+ };
440
+ })
441
+ );
442
+ const linkedEvaluations = /* @__PURE__ */ new Map();
443
+ for (const trade of debugTrades) {
444
+ const evaluation = trade.redisValues.evaluation;
445
+ if (evaluation && typeof evaluation === "object" && "evaluationId" in evaluation && typeof evaluation.evaluationId === "string") {
446
+ linkedEvaluations.set(
447
+ evaluation.evaluationId,
448
+ evaluation
449
+ );
450
+ }
451
+ }
452
+ const reportEvaluations = evaluations.length > 0 ? evaluations : [...linkedEvaluations.values()];
453
+ return {
454
+ reportType: "runtime-daily-debug",
455
+ generatedAt: Date.now(),
456
+ generatedAtMsk: formatRuntimeDebugDateTime(Date.now()),
457
+ userName,
458
+ window: {
459
+ startTime,
460
+ endTime,
461
+ startMsk: formatRuntimeDebugDateTime(startTime),
462
+ endMsk: formatRuntimeDebugDateTime(endTime),
463
+ dayKeys
464
+ },
465
+ redisPrefixes: {
466
+ runtimeTrades: import_redis3.redisKeys.runtimeTrades(userName),
467
+ runtimeTradeBuckets: import_redis3.redisKeys.runtimeTradeBuckets(userName),
468
+ runtimeActiveTrades: import_redis3.redisKeys.runtimeActiveTrades(userName),
469
+ runtimeSignals: import_redis3.redisKeys.runtimeSignalBuckets(userName),
470
+ runtimeSignalEvaluations: import_redis3.redisKeys.runtimeSignalEvaluationBuckets(userName),
471
+ runtimeSignalEvaluationStats: import_redis3.redisKeys.runtimeSignalEvaluationStatsBuckets(userName)
472
+ },
473
+ counts: {
474
+ trades: trades.length,
475
+ signals: signals.length,
476
+ evaluations: reportEvaluations.length,
477
+ evaluationStatsBuckets: evaluationStatsBuckets?.length ?? 0,
478
+ strategyConfigs: strategyConfigs?.length ?? 0
479
+ },
480
+ trades: debugTrades,
481
+ signals: signals.map((signal) => ({
482
+ redisKey: import_redis3.redisKeys.storeSignal(signal.symbol, signal.signalId),
483
+ signal
484
+ })),
485
+ evaluations: reportEvaluations.map((evaluation) => ({
486
+ redisDebug: {
487
+ key: import_redis3.redisKeys.runtimeSignalEvaluationBucket(
488
+ userName,
489
+ (0, import_time2.getRuntimeStorageDayKey)(evaluation.timestamp),
490
+ evaluation.strategy
491
+ ),
492
+ field: evaluation.evaluationId,
493
+ directKey: import_redis3.redisKeys.runtimeSignalEvaluation(
494
+ userName,
495
+ evaluation.evaluationId
496
+ )
497
+ },
498
+ evaluation
499
+ })),
500
+ evaluationStatsBuckets: evaluationStatsBuckets ?? [],
501
+ strategyConfigs: strategyConfigs ?? []
502
+ };
503
+ };
504
+ var buildRuntimeDebugReportAttachment = async (params) => {
505
+ const payload = await buildRuntimeDebugReportPayload(params);
506
+ const dayKey = formatRuntimeDebugIsoDayKey(params.endTime);
507
+ return {
508
+ filename: `tradejs-runtime-debug-${params.userName}-${dayKey}.json`,
509
+ content: JSON.stringify(payload, null, 2),
510
+ caption: `Runtime debug ${dayKey} ${RUNTIME_DEBUG_TIMEZONE_LABEL}`,
511
+ summary: {
512
+ trades: payload.counts.trades,
513
+ signals: payload.counts.signals,
514
+ evaluations: payload.counts.evaluations
515
+ }
516
+ };
517
+ };
518
+ // Annotate the CommonJS export names for ESM import in node:
519
+ 0 && (module.exports = {
520
+ RUNTIME_DEBUG_TIMEZONE,
521
+ RUNTIME_DEBUG_TIMEZONE_LABEL,
522
+ buildRuntimeDebugEvaluationId,
523
+ buildRuntimeDebugReportAttachment,
524
+ buildRuntimeDebugReportPayload,
525
+ collectRuntimeDebugEvidence
526
+ });
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/lib/runtimeModeConfig.ts
21
+ var runtimeModeConfig_exports = {};
22
+ __export(runtimeModeConfig_exports, {
23
+ buildRuntimeModeStrategyConfig: () => buildRuntimeModeStrategyConfig,
24
+ hasRuntimeEntryGateEnabled: () => hasRuntimeEntryGateEnabled,
25
+ resolveReplayStrategyEnv: () => resolveReplayStrategyEnv
26
+ });
27
+ module.exports = __toCommonJS(runtimeModeConfig_exports);
28
+ var hasRuntimeEntryGateEnabled = (strategyConfig) => strategyConfig.AI_ENABLED === true || strategyConfig.ML_ENABLED === true;
29
+ var resolveReplayStrategyEnv = ({
30
+ strategyConfig,
31
+ forceRuntimeGates = false
32
+ }) => forceRuntimeGates || hasRuntimeEntryGateEnabled(strategyConfig) ? "PARITY" : "BACKTEST";
33
+ var buildRuntimeModeStrategyConfig = ({
34
+ strategyConfig,
35
+ env,
36
+ interval,
37
+ makeOrders,
38
+ recordRuntimeTrades,
39
+ aiReplayAnalyses
40
+ }) => ({
41
+ ...strategyConfig,
42
+ ENV: env,
43
+ MAKE_ORDERS: makeOrders,
44
+ INTERVAL: interval,
45
+ ...typeof recordRuntimeTrades === "boolean" ? { RECORD_RUNTIME_TRADES: recordRuntimeTrades } : {},
46
+ ...aiReplayAnalyses?.length ? { AI_REPLAY_ANALYSES: aiReplayAnalyses } : {}
47
+ });
48
+ // Annotate the CommonJS export names for ESM import in node:
49
+ 0 && (module.exports = {
50
+ buildRuntimeModeStrategyConfig,
51
+ hasRuntimeEntryGateEnabled,
52
+ resolveReplayStrategyEnv
53
+ });