@tradejs/cli 3.1.8 → 3.1.9-beta.214
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 +856 -334
- package/dist/lib/runEnvironment.js +88 -48
- package/dist/lib/runtimeDebugEvidence.js +48 -12
- package/dist/lib/runtimeEvidenceDeployment.js +162 -0
- package/dist/lib/runtimeLineage.js +9 -1
- package/dist/lib/runtimeScorecard.js +119 -8
- package/dist/lib/runtimeSignalsLoader.js +8 -4
- package/dist/scripts/backtest.js +50 -49
- package/dist/scripts/replay.js +921 -648
- package/dist/scripts/replayRunner.js +921 -648
- package/dist/scripts/replayRuntimeEvidence.js +50 -13
- package/dist/scripts/runtimeEvidence.js +136 -18
- package/dist/scripts/runtimeScorecard.js +143 -44
- package/dist/scripts/signals.js +47 -8
- package/dist/scripts/signalsDaemon.js +47 -8
- package/dist/scripts/signalsSummary.js +12 -5
- package/package.json +7 -7
package/dist/cli.js
CHANGED
|
@@ -12181,114 +12181,6 @@ var init_marketContextPrepare = __esm({
|
|
|
12181
12181
|
}
|
|
12182
12182
|
});
|
|
12183
12183
|
|
|
12184
|
-
// src/lib/timeWindow.ts
|
|
12185
|
-
var ONE_DAY_MS, toEpochMs, toPositiveNumber, resolveTimeWindow;
|
|
12186
|
-
var init_timeWindow = __esm({
|
|
12187
|
-
"src/lib/timeWindow.ts"() {
|
|
12188
|
-
"use strict";
|
|
12189
|
-
ONE_DAY_MS = 24 * 60 * 60 * 1e3;
|
|
12190
|
-
toEpochMs = (value) => {
|
|
12191
|
-
if (value == null || value === "") {
|
|
12192
|
-
return null;
|
|
12193
|
-
}
|
|
12194
|
-
const parsed = Number(value);
|
|
12195
|
-
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
12196
|
-
return null;
|
|
12197
|
-
}
|
|
12198
|
-
return parsed < 1e12 ? Math.trunc(parsed * 1e3) : Math.trunc(parsed);
|
|
12199
|
-
};
|
|
12200
|
-
toPositiveNumber = (value) => {
|
|
12201
|
-
if (value == null || value === "") {
|
|
12202
|
-
return null;
|
|
12203
|
-
}
|
|
12204
|
-
const parsed = Number(value);
|
|
12205
|
-
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
12206
|
-
return null;
|
|
12207
|
-
}
|
|
12208
|
-
return parsed;
|
|
12209
|
-
};
|
|
12210
|
-
resolveTimeWindow = ({
|
|
12211
|
-
days,
|
|
12212
|
-
startTime,
|
|
12213
|
-
endTime,
|
|
12214
|
-
nowMs = Date.now(),
|
|
12215
|
-
defaultStartMs,
|
|
12216
|
-
defaultEndMs,
|
|
12217
|
-
closedIntervalMs
|
|
12218
|
-
}) => {
|
|
12219
|
-
const explicitStart = toEpochMs(startTime);
|
|
12220
|
-
const explicitEnd = toEpochMs(endTime);
|
|
12221
|
-
const resolvedDays = toPositiveNumber(days);
|
|
12222
|
-
const alignToLastClosedInterval = (window, preserveDuration) => {
|
|
12223
|
-
if (typeof closedIntervalMs !== "number" || !Number.isFinite(closedIntervalMs) || closedIntervalMs <= 0) {
|
|
12224
|
-
return window;
|
|
12225
|
-
}
|
|
12226
|
-
const alignedEnd = Math.floor(window.end / closedIntervalMs) * closedIntervalMs - 1;
|
|
12227
|
-
const delta = window.end - alignedEnd;
|
|
12228
|
-
const alignedStart = preserveDuration ? window.start - delta : window.start;
|
|
12229
|
-
if (alignedStart >= alignedEnd) {
|
|
12230
|
-
throw new Error(
|
|
12231
|
-
`Invalid closed-candle window: start (${alignedStart}) must be less than end (${alignedEnd})`
|
|
12232
|
-
);
|
|
12233
|
-
}
|
|
12234
|
-
return {
|
|
12235
|
-
...window,
|
|
12236
|
-
start: Math.trunc(alignedStart),
|
|
12237
|
-
end: Math.trunc(alignedEnd)
|
|
12238
|
-
};
|
|
12239
|
-
};
|
|
12240
|
-
if (explicitStart != null || explicitEnd != null) {
|
|
12241
|
-
const resolvedStart = explicitStart ?? (resolvedDays != null && explicitEnd != null ? explicitEnd - resolvedDays * ONE_DAY_MS : defaultStartMs);
|
|
12242
|
-
const resolvedEnd2 = explicitEnd ?? (resolvedDays != null && explicitStart != null ? explicitStart + resolvedDays * ONE_DAY_MS : defaultEndMs ?? nowMs);
|
|
12243
|
-
if (resolvedStart >= resolvedEnd2) {
|
|
12244
|
-
throw new Error(
|
|
12245
|
-
`Invalid time window: startTime (${resolvedStart}) must be less than endTime (${resolvedEnd2})`
|
|
12246
|
-
);
|
|
12247
|
-
}
|
|
12248
|
-
return alignToLastClosedInterval(
|
|
12249
|
-
{
|
|
12250
|
-
start: resolvedStart,
|
|
12251
|
-
end: resolvedEnd2,
|
|
12252
|
-
source: "explicit"
|
|
12253
|
-
},
|
|
12254
|
-
explicitStart == null && resolvedDays != null
|
|
12255
|
-
);
|
|
12256
|
-
}
|
|
12257
|
-
if (resolvedDays != null) {
|
|
12258
|
-
const resolvedEnd2 = defaultEndMs ?? nowMs;
|
|
12259
|
-
const resolvedStart = resolvedEnd2 - resolvedDays * ONE_DAY_MS;
|
|
12260
|
-
if (resolvedStart >= resolvedEnd2) {
|
|
12261
|
-
throw new Error(
|
|
12262
|
-
`Invalid time window: computed start (${resolvedStart}) must be less than end (${resolvedEnd2})`
|
|
12263
|
-
);
|
|
12264
|
-
}
|
|
12265
|
-
return alignToLastClosedInterval(
|
|
12266
|
-
{
|
|
12267
|
-
start: Math.trunc(resolvedStart),
|
|
12268
|
-
end: Math.trunc(resolvedEnd2),
|
|
12269
|
-
source: "days"
|
|
12270
|
-
},
|
|
12271
|
-
true
|
|
12272
|
-
);
|
|
12273
|
-
}
|
|
12274
|
-
const resolvedEnd = defaultEndMs ?? nowMs;
|
|
12275
|
-
if (defaultStartMs >= resolvedEnd) {
|
|
12276
|
-
throw new Error(
|
|
12277
|
-
`Invalid default time window: start (${defaultStartMs}) must be less than end (${resolvedEnd})`
|
|
12278
|
-
);
|
|
12279
|
-
}
|
|
12280
|
-
return alignToLastClosedInterval(
|
|
12281
|
-
{
|
|
12282
|
-
start: Math.trunc(defaultStartMs),
|
|
12283
|
-
end: Math.trunc(resolvedEnd),
|
|
12284
|
-
source: "default"
|
|
12285
|
-
},
|
|
12286
|
-
true
|
|
12287
|
-
);
|
|
12288
|
-
};
|
|
12289
|
-
}
|
|
12290
|
-
});
|
|
12291
|
-
|
|
12292
12184
|
// src/lib/runtimeRedis.ts
|
|
12293
12185
|
var import_redis4, import_time, import_runtimeStrategyConfigs, isRuntimeStrategyEnabled, isRuntimeTradeRecord, loadRuntimeTrades, loadRuntimeClosedTrades, loadRuntimeActiveTradeOrderIds, loadStrategyResultSymbols;
|
|
12294
12186
|
var init_runtimeRedis = __esm({
|
|
@@ -12433,6 +12325,114 @@ var init_runtimeStrategyBacktest = __esm({
|
|
|
12433
12325
|
}
|
|
12434
12326
|
});
|
|
12435
12327
|
|
|
12328
|
+
// src/lib/timeWindow.ts
|
|
12329
|
+
var ONE_DAY_MS, toEpochMs, toPositiveNumber, resolveTimeWindow;
|
|
12330
|
+
var init_timeWindow = __esm({
|
|
12331
|
+
"src/lib/timeWindow.ts"() {
|
|
12332
|
+
"use strict";
|
|
12333
|
+
ONE_DAY_MS = 24 * 60 * 60 * 1e3;
|
|
12334
|
+
toEpochMs = (value) => {
|
|
12335
|
+
if (value == null || value === "") {
|
|
12336
|
+
return null;
|
|
12337
|
+
}
|
|
12338
|
+
const parsed = Number(value);
|
|
12339
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
12340
|
+
return null;
|
|
12341
|
+
}
|
|
12342
|
+
return parsed < 1e12 ? Math.trunc(parsed * 1e3) : Math.trunc(parsed);
|
|
12343
|
+
};
|
|
12344
|
+
toPositiveNumber = (value) => {
|
|
12345
|
+
if (value == null || value === "") {
|
|
12346
|
+
return null;
|
|
12347
|
+
}
|
|
12348
|
+
const parsed = Number(value);
|
|
12349
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
12350
|
+
return null;
|
|
12351
|
+
}
|
|
12352
|
+
return parsed;
|
|
12353
|
+
};
|
|
12354
|
+
resolveTimeWindow = ({
|
|
12355
|
+
days,
|
|
12356
|
+
startTime,
|
|
12357
|
+
endTime,
|
|
12358
|
+
nowMs = Date.now(),
|
|
12359
|
+
defaultStartMs,
|
|
12360
|
+
defaultEndMs,
|
|
12361
|
+
closedIntervalMs
|
|
12362
|
+
}) => {
|
|
12363
|
+
const explicitStart = toEpochMs(startTime);
|
|
12364
|
+
const explicitEnd = toEpochMs(endTime);
|
|
12365
|
+
const resolvedDays = toPositiveNumber(days);
|
|
12366
|
+
const alignToLastClosedInterval = (window, preserveDuration) => {
|
|
12367
|
+
if (typeof closedIntervalMs !== "number" || !Number.isFinite(closedIntervalMs) || closedIntervalMs <= 0) {
|
|
12368
|
+
return window;
|
|
12369
|
+
}
|
|
12370
|
+
const alignedEnd = Math.floor(window.end / closedIntervalMs) * closedIntervalMs - 1;
|
|
12371
|
+
const delta = window.end - alignedEnd;
|
|
12372
|
+
const alignedStart = preserveDuration ? window.start - delta : window.start;
|
|
12373
|
+
if (alignedStart >= alignedEnd) {
|
|
12374
|
+
throw new Error(
|
|
12375
|
+
`Invalid closed-candle window: start (${alignedStart}) must be less than end (${alignedEnd})`
|
|
12376
|
+
);
|
|
12377
|
+
}
|
|
12378
|
+
return {
|
|
12379
|
+
...window,
|
|
12380
|
+
start: Math.trunc(alignedStart),
|
|
12381
|
+
end: Math.trunc(alignedEnd)
|
|
12382
|
+
};
|
|
12383
|
+
};
|
|
12384
|
+
if (explicitStart != null || explicitEnd != null) {
|
|
12385
|
+
const resolvedStart = explicitStart ?? (resolvedDays != null && explicitEnd != null ? explicitEnd - resolvedDays * ONE_DAY_MS : defaultStartMs);
|
|
12386
|
+
const resolvedEnd2 = explicitEnd ?? (resolvedDays != null && explicitStart != null ? explicitStart + resolvedDays * ONE_DAY_MS : defaultEndMs ?? nowMs);
|
|
12387
|
+
if (resolvedStart >= resolvedEnd2) {
|
|
12388
|
+
throw new Error(
|
|
12389
|
+
`Invalid time window: startTime (${resolvedStart}) must be less than endTime (${resolvedEnd2})`
|
|
12390
|
+
);
|
|
12391
|
+
}
|
|
12392
|
+
return alignToLastClosedInterval(
|
|
12393
|
+
{
|
|
12394
|
+
start: resolvedStart,
|
|
12395
|
+
end: resolvedEnd2,
|
|
12396
|
+
source: "explicit"
|
|
12397
|
+
},
|
|
12398
|
+
explicitStart == null && resolvedDays != null
|
|
12399
|
+
);
|
|
12400
|
+
}
|
|
12401
|
+
if (resolvedDays != null) {
|
|
12402
|
+
const resolvedEnd2 = defaultEndMs ?? nowMs;
|
|
12403
|
+
const resolvedStart = resolvedEnd2 - resolvedDays * ONE_DAY_MS;
|
|
12404
|
+
if (resolvedStart >= resolvedEnd2) {
|
|
12405
|
+
throw new Error(
|
|
12406
|
+
`Invalid time window: computed start (${resolvedStart}) must be less than end (${resolvedEnd2})`
|
|
12407
|
+
);
|
|
12408
|
+
}
|
|
12409
|
+
return alignToLastClosedInterval(
|
|
12410
|
+
{
|
|
12411
|
+
start: Math.trunc(resolvedStart),
|
|
12412
|
+
end: Math.trunc(resolvedEnd2),
|
|
12413
|
+
source: "days"
|
|
12414
|
+
},
|
|
12415
|
+
true
|
|
12416
|
+
);
|
|
12417
|
+
}
|
|
12418
|
+
const resolvedEnd = defaultEndMs ?? nowMs;
|
|
12419
|
+
if (defaultStartMs >= resolvedEnd) {
|
|
12420
|
+
throw new Error(
|
|
12421
|
+
`Invalid default time window: start (${defaultStartMs}) must be less than end (${resolvedEnd})`
|
|
12422
|
+
);
|
|
12423
|
+
}
|
|
12424
|
+
return alignToLastClosedInterval(
|
|
12425
|
+
{
|
|
12426
|
+
start: Math.trunc(defaultStartMs),
|
|
12427
|
+
end: Math.trunc(resolvedEnd),
|
|
12428
|
+
source: "default"
|
|
12429
|
+
},
|
|
12430
|
+
true
|
|
12431
|
+
);
|
|
12432
|
+
};
|
|
12433
|
+
}
|
|
12434
|
+
});
|
|
12435
|
+
|
|
12436
12436
|
// src/lib/marketData/historyPrepare.ts
|
|
12437
12437
|
var import_chalk11, import_connectors3, import_cli2, import_connectors4, withPrimaryMarketReferenceSymbols, loadBtcReferenceConnectors, updateMarketHistoryWithBtcReferences, updatePrimaryMarketHistory, updateBtcReferenceHistory;
|
|
12438
12438
|
var init_historyPrepare = __esm({
|
|
@@ -12689,7 +12689,7 @@ var init_tickerUniverseCache = __esm({
|
|
|
12689
12689
|
});
|
|
12690
12690
|
|
|
12691
12691
|
// src/lib/runEnvironment.ts
|
|
12692
|
-
var import_chalk12, import_connectors5, import_cli4, import_constants6, import_time2, timeOperation2, resolveBacktestExecutionPreloadInterval, resolveRunConnectorName,
|
|
12692
|
+
var import_chalk12, import_connectors5, import_cli4, import_constants6, import_time2, import_runtimeStrategies, timeOperation2, resolveBacktestExecutionPreloadInterval, resolveRunConnectorName, loadDeploymentReplayStrategies, prepareRunEnvironment;
|
|
12693
12693
|
var init_runEnvironment = __esm({
|
|
12694
12694
|
"src/lib/runEnvironment.ts"() {
|
|
12695
12695
|
"use strict";
|
|
@@ -12698,8 +12698,9 @@ var init_runEnvironment = __esm({
|
|
|
12698
12698
|
import_cli4 = require("@tradejs/node/cli");
|
|
12699
12699
|
import_constants6 = require("@tradejs/core/constants");
|
|
12700
12700
|
import_time2 = require("@tradejs/core/time");
|
|
12701
|
-
|
|
12701
|
+
import_runtimeStrategies = require("@tradejs/node/runtimeStrategies");
|
|
12702
12702
|
init_runtimeStrategyBacktest();
|
|
12703
|
+
init_timeWindow();
|
|
12703
12704
|
init_runFormatting();
|
|
12704
12705
|
init_historyPrepare();
|
|
12705
12706
|
init_tickerUniverseCache();
|
|
@@ -12733,17 +12734,43 @@ var init_runEnvironment = __esm({
|
|
|
12733
12734
|
);
|
|
12734
12735
|
return import_connectors5.DEFAULT_CONNECTOR_NAME;
|
|
12735
12736
|
};
|
|
12736
|
-
|
|
12737
|
-
|
|
12738
|
-
|
|
12737
|
+
loadDeploymentReplayStrategies = async ({
|
|
12738
|
+
userName: userName3,
|
|
12739
|
+
projectRoot: projectRoot15,
|
|
12740
|
+
deploymentId
|
|
12741
|
+
}) => {
|
|
12742
|
+
const [deployment, runtimeStrategies] = await Promise.all([
|
|
12743
|
+
(0, import_runtimeStrategies.getRuntimeDeployment)({ userName: userName3, projectRoot: projectRoot15, deploymentId }),
|
|
12744
|
+
(0, import_runtimeStrategies.loadResolvedRuntimeStrategies)({ userName: userName3, projectRoot: projectRoot15, deploymentId })
|
|
12745
|
+
]);
|
|
12746
|
+
if (!deployment) {
|
|
12747
|
+
throw new Error(`Runtime deployment not found: ${deploymentId}`);
|
|
12748
|
+
}
|
|
12749
|
+
const strategies = deployment.enabled ? runtimeStrategies.filter((strategy) => strategy.enabled).map(
|
|
12750
|
+
({
|
|
12751
|
+
strategyName,
|
|
12752
|
+
version,
|
|
12753
|
+
strategyPackage,
|
|
12754
|
+
strategyPackageVersion,
|
|
12755
|
+
runtimePackageVersion,
|
|
12756
|
+
sourceStrategyConfig
|
|
12757
|
+
}) => ({
|
|
12758
|
+
strategyName,
|
|
12759
|
+
version,
|
|
12760
|
+
strategyPackage,
|
|
12761
|
+
strategyPackageVersion,
|
|
12762
|
+
runtimePackageVersion,
|
|
12763
|
+
strategyConfig: sourceStrategyConfig
|
|
12764
|
+
})
|
|
12765
|
+
) : [];
|
|
12766
|
+
if (!strategies.length) {
|
|
12739
12767
|
console.log(
|
|
12740
12768
|
import_chalk12.default.yellow(
|
|
12741
|
-
`No
|
|
12769
|
+
`No enabled strategies found in runtime deployment ${deploymentId}`
|
|
12742
12770
|
)
|
|
12743
12771
|
);
|
|
12744
|
-
return [];
|
|
12745
12772
|
}
|
|
12746
|
-
return
|
|
12773
|
+
return { deployment, strategies };
|
|
12747
12774
|
};
|
|
12748
12775
|
prepareRunEnvironment = async ({
|
|
12749
12776
|
connector,
|
|
@@ -13460,7 +13487,7 @@ var init_workerPool = __esm({
|
|
|
13460
13487
|
});
|
|
13461
13488
|
|
|
13462
13489
|
// src/lib/backtest/runnerCore.ts
|
|
13463
|
-
var import_fs, import_path5, import_chalk14, import_backtest, import_constants8, import_time3, import_backtestArtifacts, import_redis6,
|
|
13490
|
+
var import_fs, import_path5, import_chalk14, import_backtest, import_constants8, import_time3, import_backtestArtifacts, import_redis6, import_runtimeStrategies2, import_types4, formatWindowDays, getResultAmount, getResultNetProfit2, recordError, insertTopResult, updateTopResults, updateBestTickerResult, chunkTestSuiteBySymbol, mergePersistedTestSummaries, getLogsById, resolveResultArtifacts, setTestData, persistTestSummariesIndex, validateBacktestRuntimeDeployment, prepareRunEnvironment2, buildPreparedTestSuite, trackTopResult, buildRunIntroLines, resolveTesterWorker, executeTestSuite, printRunOutro;
|
|
13464
13491
|
var init_runnerCore = __esm({
|
|
13465
13492
|
"src/lib/backtest/runnerCore.ts"() {
|
|
13466
13493
|
"use strict";
|
|
@@ -13472,7 +13499,7 @@ var init_runnerCore = __esm({
|
|
|
13472
13499
|
import_time3 = require("@tradejs/core/time");
|
|
13473
13500
|
import_backtestArtifacts = require("@tradejs/infra/backtestArtifacts");
|
|
13474
13501
|
import_redis6 = require("@tradejs/infra/redis");
|
|
13475
|
-
|
|
13502
|
+
import_runtimeStrategies2 = require("@tradejs/node/runtimeStrategies");
|
|
13476
13503
|
import_types4 = require("@tradejs/types");
|
|
13477
13504
|
init_runFormatting();
|
|
13478
13505
|
init_marketContextPrepare();
|
|
@@ -13680,7 +13707,7 @@ var init_runnerCore = __esm({
|
|
|
13680
13707
|
};
|
|
13681
13708
|
prepareRunEnvironment2 = async () => {
|
|
13682
13709
|
const deployment = validateBacktestRuntimeDeployment({
|
|
13683
|
-
deployment: flags5.deployment ? await (0,
|
|
13710
|
+
deployment: flags5.deployment ? await (0, import_runtimeStrategies2.getRuntimeDeployment)({
|
|
13684
13711
|
userName,
|
|
13685
13712
|
projectRoot: projectRoot3,
|
|
13686
13713
|
deploymentId: String(flags5.deployment)
|
|
@@ -24177,13 +24204,17 @@ var init_runtimeSignalsLoader = __esm({
|
|
|
24177
24204
|
return null;
|
|
24178
24205
|
}
|
|
24179
24206
|
const suffix = key.slice(prefix.length);
|
|
24180
|
-
const
|
|
24181
|
-
if (
|
|
24207
|
+
const parts = suffix.split(":");
|
|
24208
|
+
if (parts.length < 2 || parts.some((part) => !part)) {
|
|
24182
24209
|
return null;
|
|
24183
24210
|
}
|
|
24211
|
+
const [dayKey, ...scopeParts] = parts;
|
|
24212
|
+
const strategy = scopeParts.at(-1);
|
|
24213
|
+
if (!dayKey || !strategy) return null;
|
|
24184
24214
|
return {
|
|
24185
|
-
dayKey
|
|
24186
|
-
|
|
24215
|
+
dayKey,
|
|
24216
|
+
...scopeParts.length > 1 ? { deploymentId: scopeParts.slice(0, -1).join(":") } : {},
|
|
24217
|
+
strategy
|
|
24187
24218
|
};
|
|
24188
24219
|
};
|
|
24189
24220
|
loadRuntimeSignalEvaluationStatsBuckets = async (userName3) => {
|
|
@@ -24255,7 +24286,8 @@ var init_runtimeDebugEvidence = __esm({
|
|
|
24255
24286
|
userName: userName3,
|
|
24256
24287
|
startTime,
|
|
24257
24288
|
endTime,
|
|
24258
|
-
strategies
|
|
24289
|
+
strategies,
|
|
24290
|
+
deploymentId
|
|
24259
24291
|
}) => {
|
|
24260
24292
|
const dayKeys = (0, import_time6.getRuntimeStorageDayKeys)(startTime, endTime);
|
|
24261
24293
|
const dayKeySet = new Set(dayKeys);
|
|
@@ -24265,6 +24297,7 @@ var init_runtimeDebugEvidence = __esm({
|
|
|
24265
24297
|
signals2,
|
|
24266
24298
|
evaluations,
|
|
24267
24299
|
evaluationStatsBuckets,
|
|
24300
|
+
lineageScopes,
|
|
24268
24301
|
configs
|
|
24269
24302
|
] = await Promise.all([
|
|
24270
24303
|
loadRuntimeTrades(userName3, { startTime, endTime }),
|
|
@@ -24272,6 +24305,7 @@ var init_runtimeDebugEvidence = __esm({
|
|
|
24272
24305
|
loadRuntimeSignals(userName3, { startTime, endTime }),
|
|
24273
24306
|
loadRuntimeSignalEvaluations(userName3, { startTime, endTime }),
|
|
24274
24307
|
loadRuntimeSignalEvaluationStatsBuckets(userName3),
|
|
24308
|
+
loadRuntimeLineageScopes(userName3, { startTime, endTime }),
|
|
24275
24309
|
(0, import_runtimeStrategyConfigs.loadRuntimeStrategyConfigs)(userName3)
|
|
24276
24310
|
]);
|
|
24277
24311
|
const tradesByOrderId = new Map(
|
|
@@ -24284,15 +24318,21 @@ var init_runtimeDebugEvidence = __esm({
|
|
|
24284
24318
|
(left, right) => left.entryTimestamp - right.entryTimestamp
|
|
24285
24319
|
);
|
|
24286
24320
|
const filteredStats = evaluationStatsBuckets.filter(
|
|
24287
|
-
(entry) => dayKeySet.has(entry.dayKey) && (!strategies?.length || strategies.includes(entry.strategy))
|
|
24321
|
+
(entry) => dayKeySet.has(entry.dayKey) && (!deploymentId || entry.deploymentId === deploymentId) && (!strategies?.length || strategies.includes(entry.strategy))
|
|
24288
24322
|
);
|
|
24323
|
+
const matchesDeployment = (value) => !deploymentId || value.deploymentId === deploymentId;
|
|
24289
24324
|
return {
|
|
24290
24325
|
dayKeys,
|
|
24291
|
-
trades: filterByStrategies(trades, strategies),
|
|
24292
|
-
signals: filterByStrategies(signals2, strategies),
|
|
24293
|
-
evaluations: filterByStrategies(evaluations, strategies)
|
|
24326
|
+
trades: filterByStrategies(trades, strategies).filter(matchesDeployment),
|
|
24327
|
+
signals: filterByStrategies(signals2, strategies).filter(matchesDeployment),
|
|
24328
|
+
evaluations: filterByStrategies(evaluations, strategies).filter(
|
|
24329
|
+
matchesDeployment
|
|
24330
|
+
),
|
|
24294
24331
|
evaluationStatsBuckets: filteredStats,
|
|
24295
|
-
|
|
24332
|
+
lineageScopes: lineageScopes.filter(matchesDeployment).filter(
|
|
24333
|
+
(scope) => !strategies?.length || strategies.includes(scope.strategy)
|
|
24334
|
+
),
|
|
24335
|
+
strategyConfigs: deploymentId ? [] : configs.filter(
|
|
24296
24336
|
(config2) => !strategies?.length || strategies.includes(config2.strategyName)
|
|
24297
24337
|
)
|
|
24298
24338
|
};
|
|
@@ -24305,7 +24345,8 @@ var init_runtimeDebugEvidence = __esm({
|
|
|
24305
24345
|
evaluations,
|
|
24306
24346
|
trades,
|
|
24307
24347
|
strategyConfigs,
|
|
24308
|
-
evaluationStatsBuckets
|
|
24348
|
+
evaluationStatsBuckets,
|
|
24349
|
+
lineageScopes
|
|
24309
24350
|
}) => {
|
|
24310
24351
|
const signalById = new Map(
|
|
24311
24352
|
signals2.map((signal) => [signal.signalId, signal])
|
|
@@ -24433,6 +24474,7 @@ var init_runtimeDebugEvidence = __esm({
|
|
|
24433
24474
|
signals: signals2.length,
|
|
24434
24475
|
evaluations: reportEvaluations.length,
|
|
24435
24476
|
evaluationStatsBuckets: evaluationStatsBuckets?.length ?? 0,
|
|
24477
|
+
lineageScopes: lineageScopes?.length ?? 0,
|
|
24436
24478
|
strategyConfigs: strategyConfigs?.length ?? 0
|
|
24437
24479
|
},
|
|
24438
24480
|
trades: debugTrades,
|
|
@@ -24456,6 +24498,7 @@ var init_runtimeDebugEvidence = __esm({
|
|
|
24456
24498
|
evaluation
|
|
24457
24499
|
})),
|
|
24458
24500
|
evaluationStatsBuckets: evaluationStatsBuckets ?? [],
|
|
24501
|
+
lineageScopes: lineageScopes ?? [],
|
|
24459
24502
|
strategyConfigs: strategyConfigs ?? []
|
|
24460
24503
|
};
|
|
24461
24504
|
};
|
|
@@ -24467,7 +24510,8 @@ var init_runtimeDebugEvidence = __esm({
|
|
|
24467
24510
|
evaluations,
|
|
24468
24511
|
trades,
|
|
24469
24512
|
strategyConfigs,
|
|
24470
|
-
evaluationStatsBuckets
|
|
24513
|
+
evaluationStatsBuckets,
|
|
24514
|
+
lineageScopes
|
|
24471
24515
|
}) => ({
|
|
24472
24516
|
reportType: "runtime-daily-evidence",
|
|
24473
24517
|
generatedAt: Date.now(),
|
|
@@ -24484,12 +24528,14 @@ var init_runtimeDebugEvidence = __esm({
|
|
|
24484
24528
|
signals: signals2.length,
|
|
24485
24529
|
evaluations: evaluations.length,
|
|
24486
24530
|
evaluationStatsBuckets: evaluationStatsBuckets?.length ?? 0,
|
|
24531
|
+
lineageScopes: lineageScopes?.length ?? 0,
|
|
24487
24532
|
strategyConfigs: strategyConfigs?.length ?? 0
|
|
24488
24533
|
},
|
|
24489
24534
|
trades: trades.map((trade) => ({ trade })),
|
|
24490
24535
|
signals: signals2.map((signal) => ({ signal })),
|
|
24491
24536
|
evaluations: evaluations.map((evaluation) => ({ evaluation })),
|
|
24492
24537
|
evaluationStatsBuckets: evaluationStatsBuckets ?? [],
|
|
24538
|
+
lineageScopes: lineageScopes ?? [],
|
|
24493
24539
|
strategyConfigs: strategyConfigs ?? []
|
|
24494
24540
|
});
|
|
24495
24541
|
buildRuntimeDebugReportAttachment = async (params) => {
|
|
@@ -24899,7 +24945,8 @@ var init_replayRuntimeEvidence = __esm({
|
|
|
24899
24945
|
return {
|
|
24900
24946
|
source: "file",
|
|
24901
24947
|
path: runtimeEvidencePath,
|
|
24902
|
-
payload: artifact.runtime ?? artifact
|
|
24948
|
+
payload: artifact.runtime ?? artifact,
|
|
24949
|
+
deployment: artifact.deployment ?? null
|
|
24903
24950
|
};
|
|
24904
24951
|
}
|
|
24905
24952
|
const runtimeEvidence2 = await collectRuntimeDebugEvidence({
|
|
@@ -24911,6 +24958,7 @@ var init_replayRuntimeEvidence = __esm({
|
|
|
24911
24958
|
return {
|
|
24912
24959
|
source: "local-redis",
|
|
24913
24960
|
path: null,
|
|
24961
|
+
deployment: null,
|
|
24914
24962
|
payload: buildRuntimeEvidenceReportPayload({
|
|
24915
24963
|
userName: userName3,
|
|
24916
24964
|
startTime,
|
|
@@ -24919,7 +24967,8 @@ var init_replayRuntimeEvidence = __esm({
|
|
|
24919
24967
|
evaluations: runtimeEvidence2.evaluations,
|
|
24920
24968
|
trades: runtimeEvidence2.trades,
|
|
24921
24969
|
strategyConfigs: runtimeEvidence2.strategyConfigs,
|
|
24922
|
-
evaluationStatsBuckets: runtimeEvidence2.evaluationStatsBuckets
|
|
24970
|
+
evaluationStatsBuckets: runtimeEvidence2.evaluationStatsBuckets,
|
|
24971
|
+
lineageScopes: runtimeEvidence2.lineageScopes
|
|
24923
24972
|
})
|
|
24924
24973
|
};
|
|
24925
24974
|
};
|
|
@@ -24959,6 +25008,7 @@ var init_replayRuntimeEvidence = __esm({
|
|
|
24959
25008
|
type: runtime.source,
|
|
24960
25009
|
path: runtime.path
|
|
24961
25010
|
},
|
|
25011
|
+
deployment: runtime.deployment,
|
|
24962
25012
|
replay: {
|
|
24963
25013
|
key: replay.key,
|
|
24964
25014
|
availableKeys: replay.availableKeys,
|
|
@@ -25283,7 +25333,7 @@ async function buildRuntimeLineage({
|
|
|
25283
25333
|
maxLossValue: resolveRuntimeMaxLossValue(config2)
|
|
25284
25334
|
};
|
|
25285
25335
|
}
|
|
25286
|
-
var import_node_child_process6, import_node_crypto11, import_promises23, import_node_path17, import_types8, import_strategies10, import_strategyReleaseEvidence2, RUNTIME_CONTEXT_ENV_KEYS, RUNTIME_CONTEXT_DATA_MODEL, normalizeForStableJson2, resolveRuntimeMaxLossValue, fingerprintRuntimeValue, gitLineageCache, gateFingerprintCache, binanceBreadthFingerprintCache, snapshotFingerprintCache, resolveGitLineage, readOptionalFile, resolveBinanceBreadthFingerprint, resolveSnapshotFingerprint, resolveRuntimeGateFingerprint, runtimeLineageKey, runtimeLineagesMatch;
|
|
25336
|
+
var import_node_child_process6, import_node_crypto11, import_promises23, import_node_path17, import_types8, import_strategies10, import_strategyReleaseEvidence2, RUNTIME_CONTEXT_ENV_KEYS, RUNTIME_CONTEXT_DATA_MODEL, normalizeForStableJson2, resolveRuntimeMaxLossValue, fingerprintRuntimeValue, gitLineageCache, gateFingerprintCache, binanceBreadthFingerprintCache, snapshotFingerprintCache, resolveGitLineage, readOptionalFile, resolveBinanceBreadthFingerprint, resolveSnapshotFingerprint, resolveRuntimeGateFingerprint, runtimeLineageKey, runtimeLineagesMatch, runtimeLineagesComparable;
|
|
25287
25337
|
var init_runtimeLineage = __esm({
|
|
25288
25338
|
"src/lib/runtimeLineage.ts"() {
|
|
25289
25339
|
"use strict";
|
|
@@ -25469,7 +25519,12 @@ var init_runtimeLineage = __esm({
|
|
|
25469
25519
|
gateFingerprintCache.set(cacheKey, result);
|
|
25470
25520
|
return result;
|
|
25471
25521
|
};
|
|
25472
|
-
runtimeLineageKey = (lineage) => lineage.schemaVersion === 2 ? [
|
|
25522
|
+
runtimeLineageKey = (lineage) => lineage.schemaVersion === 2 ? [
|
|
25523
|
+
"v2",
|
|
25524
|
+
lineage.version,
|
|
25525
|
+
lineage.strategyPackageVersion ?? "strategy:unknown",
|
|
25526
|
+
lineage.runtimePackageVersion ?? "runtime:unknown"
|
|
25527
|
+
].join(":") : [
|
|
25473
25528
|
lineage.schemaVersion,
|
|
25474
25529
|
lineage.compositionId ?? "unbound-composition",
|
|
25475
25530
|
lineage.gitSha ?? "unknown",
|
|
@@ -25479,26 +25534,163 @@ var init_runtimeLineage = __esm({
|
|
|
25479
25534
|
lineage.contextFingerprint
|
|
25480
25535
|
].join(":");
|
|
25481
25536
|
runtimeLineagesMatch = (left, right) => left != null && right != null && runtimeLineageKey(left) === runtimeLineageKey(right);
|
|
25537
|
+
runtimeLineagesComparable = (left, right) => runtimeLineagesMatch(left, right) && typeof left?.maxLossValue === "number" && Number.isFinite(left.maxLossValue) && typeof right?.maxLossValue === "number" && Number.isFinite(right.maxLossValue) && left.maxLossValue === right.maxLossValue;
|
|
25482
25538
|
}
|
|
25483
25539
|
});
|
|
25484
25540
|
|
|
25485
|
-
// src/
|
|
25486
|
-
var
|
|
25487
|
-
|
|
25488
|
-
|
|
25489
|
-
runtimeEvidence: () => runtimeEvidence
|
|
25490
|
-
});
|
|
25491
|
-
var import_promises24, import_node_path18, import_args26, import_chalk39, flags25, projectRoot9, toEpochMs3, resolveWindow2, parseStrategyFilter2, runtimeEvidence, main34;
|
|
25492
|
-
var init_runtimeEvidence = __esm({
|
|
25493
|
-
"src/scripts/runtimeEvidence.ts"() {
|
|
25541
|
+
// src/lib/runtimeEvidenceDeployment.ts
|
|
25542
|
+
var import_runtimeStrategies3, isRecord, isNonEmptyString, INTERVALS, UNIVERSES, parseRuntimeEvidenceDeploymentSnapshot, activeRuntimeEvidenceStrategies, runtimeDeploymentFromEvidence, resolveRuntimeEvidenceDeploymentSnapshot;
|
|
25543
|
+
var init_runtimeEvidenceDeployment = __esm({
|
|
25544
|
+
"src/lib/runtimeEvidenceDeployment.ts"() {
|
|
25494
25545
|
"use strict";
|
|
25495
|
-
|
|
25546
|
+
import_runtimeStrategies3 = require("@tradejs/node/runtimeStrategies");
|
|
25547
|
+
isRecord = (value) => value != null && typeof value === "object" && !Array.isArray(value);
|
|
25548
|
+
isNonEmptyString = (value) => typeof value === "string" && value.trim().length > 0;
|
|
25549
|
+
INTERVALS = /* @__PURE__ */ new Set([
|
|
25550
|
+
"1",
|
|
25551
|
+
"3",
|
|
25552
|
+
"5",
|
|
25553
|
+
"15",
|
|
25554
|
+
"30",
|
|
25555
|
+
"60",
|
|
25556
|
+
"120",
|
|
25557
|
+
"240",
|
|
25558
|
+
"360",
|
|
25559
|
+
"720",
|
|
25560
|
+
"D",
|
|
25561
|
+
"W",
|
|
25562
|
+
"M"
|
|
25563
|
+
]);
|
|
25564
|
+
UNIVERSES = /* @__PURE__ */ new Set(["crypto", "tradfi"]);
|
|
25565
|
+
parseRuntimeEvidenceDeploymentSnapshot = (value) => {
|
|
25566
|
+
if (!isRecord(value) || value.schemaVersion !== 1 || !isNonEmptyString(value.id) || !isNonEmptyString(value.label) || !isNonEmptyString(value.connectorName) || !isNonEmptyString(value.provider) || !isNonEmptyString(value.accountId) || typeof value.enabled !== "boolean" || !Array.isArray(value.strategies)) {
|
|
25567
|
+
throw new Error(
|
|
25568
|
+
"Runtime evidence deployment snapshot is missing or invalid"
|
|
25569
|
+
);
|
|
25570
|
+
}
|
|
25571
|
+
const strategies = value.strategies.map((candidate) => {
|
|
25572
|
+
if (!isRecord(candidate) || !isNonEmptyString(candidate.strategyName) || !Number.isSafeInteger(candidate.version) || Number(candidate.version) <= 0 || typeof candidate.enabled !== "boolean" || !["active", "entries_paused"].includes(String(candidate.controlState)) || !INTERVALS.has(String(candidate.interval)) || !UNIVERSES.has(String(candidate.universe)) || !isNonEmptyString(candidate.strategyPackage) || !isNonEmptyString(candidate.strategyPackageVersion) || !isNonEmptyString(candidate.runtimePackageVersion) || !isRecord(candidate.strategyConfig)) {
|
|
25573
|
+
throw new Error(
|
|
25574
|
+
"Runtime evidence deployment strategy snapshot is invalid"
|
|
25575
|
+
);
|
|
25576
|
+
}
|
|
25577
|
+
if (String(candidate.strategyConfig.INTERVAL) !== String(candidate.interval) || String(candidate.strategyConfig.UNIVERSE) !== String(candidate.universe)) {
|
|
25578
|
+
throw new Error(
|
|
25579
|
+
`Runtime evidence strategy config does not match its scope: ${candidate.strategyName}`
|
|
25580
|
+
);
|
|
25581
|
+
}
|
|
25582
|
+
if (candidate.accountId != null && (!isNonEmptyString(candidate.accountId) || candidate.accountId !== value.accountId)) {
|
|
25583
|
+
throw new Error(
|
|
25584
|
+
`Runtime evidence strategy account does not match deployment: ${candidate.strategyName}`
|
|
25585
|
+
);
|
|
25586
|
+
}
|
|
25587
|
+
return candidate;
|
|
25588
|
+
});
|
|
25589
|
+
const identities = /* @__PURE__ */ new Set();
|
|
25590
|
+
for (const strategy of strategies) {
|
|
25591
|
+
if (identities.has(strategy.strategyName)) {
|
|
25592
|
+
throw new Error(
|
|
25593
|
+
`Duplicate runtime evidence strategy: ${strategy.strategyName}`
|
|
25594
|
+
);
|
|
25595
|
+
}
|
|
25596
|
+
identities.add(strategy.strategyName);
|
|
25597
|
+
}
|
|
25598
|
+
return {
|
|
25599
|
+
...value,
|
|
25600
|
+
strategies
|
|
25601
|
+
};
|
|
25602
|
+
};
|
|
25603
|
+
activeRuntimeEvidenceStrategies = (deployment) => deployment.enabled ? deployment.strategies.filter((strategy) => strategy.enabled) : [];
|
|
25604
|
+
runtimeDeploymentFromEvidence = (deployment) => ({
|
|
25605
|
+
id: deployment.id,
|
|
25606
|
+
label: deployment.label,
|
|
25607
|
+
connectorName: deployment.connectorName,
|
|
25608
|
+
provider: deployment.provider,
|
|
25609
|
+
accountId: deployment.accountId,
|
|
25610
|
+
enabled: deployment.enabled,
|
|
25611
|
+
strategies: deployment.strategies.map(
|
|
25612
|
+
({ strategyName, version, enabled, controlState }) => ({
|
|
25613
|
+
strategyName,
|
|
25614
|
+
version,
|
|
25615
|
+
enabled,
|
|
25616
|
+
controlState
|
|
25617
|
+
})
|
|
25618
|
+
),
|
|
25619
|
+
...deployment.assetClasses ? { assetClasses: [...deployment.assetClasses] } : {},
|
|
25620
|
+
...deployment.tickers ? { tickers: [...deployment.tickers] } : {}
|
|
25621
|
+
});
|
|
25622
|
+
resolveRuntimeEvidenceDeploymentSnapshot = async ({
|
|
25623
|
+
userName: userName3,
|
|
25624
|
+
projectRoot: projectRoot15,
|
|
25625
|
+
deploymentId
|
|
25626
|
+
}) => {
|
|
25627
|
+
const [deployment, strategies] = await Promise.all([
|
|
25628
|
+
(0, import_runtimeStrategies3.getRuntimeDeployment)({ userName: userName3, projectRoot: projectRoot15, deploymentId }),
|
|
25629
|
+
(0, import_runtimeStrategies3.loadResolvedRuntimeStrategies)({ userName: userName3, projectRoot: projectRoot15, deploymentId })
|
|
25630
|
+
]);
|
|
25631
|
+
if (!deployment) {
|
|
25632
|
+
throw new Error(`Runtime deployment not found: ${deploymentId}`);
|
|
25633
|
+
}
|
|
25634
|
+
return {
|
|
25635
|
+
schemaVersion: 1,
|
|
25636
|
+
id: deployment.id,
|
|
25637
|
+
label: deployment.label,
|
|
25638
|
+
connectorName: deployment.connectorName,
|
|
25639
|
+
provider: deployment.provider,
|
|
25640
|
+
accountId: deployment.accountId,
|
|
25641
|
+
enabled: deployment.enabled,
|
|
25642
|
+
strategies: strategies.map(
|
|
25643
|
+
({
|
|
25644
|
+
strategyName,
|
|
25645
|
+
version,
|
|
25646
|
+
enabled,
|
|
25647
|
+
controlState,
|
|
25648
|
+
interval: interval4,
|
|
25649
|
+
universe,
|
|
25650
|
+
accountId,
|
|
25651
|
+
strategyPackage,
|
|
25652
|
+
strategyPackageVersion,
|
|
25653
|
+
runtimePackageVersion,
|
|
25654
|
+
sourceStrategyConfig
|
|
25655
|
+
}) => ({
|
|
25656
|
+
strategyName,
|
|
25657
|
+
version,
|
|
25658
|
+
enabled,
|
|
25659
|
+
controlState,
|
|
25660
|
+
interval: interval4,
|
|
25661
|
+
universe,
|
|
25662
|
+
...accountId ? { accountId } : {},
|
|
25663
|
+
strategyPackage,
|
|
25664
|
+
strategyPackageVersion,
|
|
25665
|
+
runtimePackageVersion,
|
|
25666
|
+
strategyConfig: sourceStrategyConfig
|
|
25667
|
+
})
|
|
25668
|
+
),
|
|
25669
|
+
...deployment.assetClasses ? { assetClasses: [...deployment.assetClasses] } : {},
|
|
25670
|
+
...deployment.tickers ? { tickers: [...deployment.tickers] } : {}
|
|
25671
|
+
};
|
|
25672
|
+
};
|
|
25673
|
+
}
|
|
25674
|
+
});
|
|
25675
|
+
|
|
25676
|
+
// src/scripts/runtimeEvidence.ts
|
|
25677
|
+
var runtimeEvidence_exports = {};
|
|
25678
|
+
__export(runtimeEvidence_exports, {
|
|
25679
|
+
main: () => main34,
|
|
25680
|
+
runtimeEvidence: () => runtimeEvidence
|
|
25681
|
+
});
|
|
25682
|
+
var import_promises24, import_node_path18, import_args26, import_chalk39, flags25, projectRoot9, toEpochMs3, resolveWindow2, parseStrategyFilter2, runtimeEvidence, main34;
|
|
25683
|
+
var init_runtimeEvidence = __esm({
|
|
25684
|
+
"src/scripts/runtimeEvidence.ts"() {
|
|
25685
|
+
"use strict";
|
|
25686
|
+
import_promises24 = __toESM(require("fs/promises"));
|
|
25496
25687
|
import_node_path18 = __toESM(require("path"));
|
|
25497
25688
|
import_args26 = __toESM(require("args"));
|
|
25498
25689
|
import_chalk39 = __toESM(require("chalk"));
|
|
25499
25690
|
init_runtimeDebugEvidence();
|
|
25500
25691
|
init_runtimeEvidenceArtifacts();
|
|
25501
25692
|
init_runtimeLineage();
|
|
25693
|
+
init_runtimeEvidenceDeployment();
|
|
25502
25694
|
import_args26.default.option(["u", "user"], "Use user config", "root");
|
|
25503
25695
|
import_args26.default.option(
|
|
25504
25696
|
["S", "startTime"],
|
|
@@ -25577,12 +25769,34 @@ var init_runtimeEvidence = __esm({
|
|
|
25577
25769
|
parseStrategyFilter2 = (value) => String(value ?? "").split(",").map((item) => item.trim()).filter(Boolean);
|
|
25578
25770
|
runtimeEvidence = async () => {
|
|
25579
25771
|
const { startTime, endTime, source } = resolveWindow2();
|
|
25580
|
-
const
|
|
25772
|
+
const deploymentId = String(flags25.deployment);
|
|
25773
|
+
const deployment = await resolveRuntimeEvidenceDeploymentSnapshot({
|
|
25774
|
+
userName: String(flags25.user),
|
|
25775
|
+
projectRoot: projectRoot9,
|
|
25776
|
+
deploymentId
|
|
25777
|
+
});
|
|
25778
|
+
const activeStrategies = activeRuntimeEvidenceStrategies(deployment).map(
|
|
25779
|
+
({ strategyName }) => strategyName
|
|
25780
|
+
);
|
|
25781
|
+
const requestedStrategies = parseStrategyFilter2(flags25.strategy);
|
|
25782
|
+
const strategies = requestedStrategies.length ? requestedStrategies : activeStrategies;
|
|
25783
|
+
const declaredStrategies = new Set(
|
|
25784
|
+
deployment.strategies.map(({ strategyName }) => strategyName)
|
|
25785
|
+
);
|
|
25786
|
+
const unknownStrategies = strategies.filter(
|
|
25787
|
+
(strategyName) => !declaredStrategies.has(strategyName)
|
|
25788
|
+
);
|
|
25789
|
+
if (unknownStrategies.length) {
|
|
25790
|
+
throw new Error(
|
|
25791
|
+
`Strategies are not declared in ${deploymentId}: ${unknownStrategies.join(", ")}`
|
|
25792
|
+
);
|
|
25793
|
+
}
|
|
25581
25794
|
const evidence = await collectRuntimeDebugEvidence({
|
|
25582
25795
|
userName: flags25.user,
|
|
25583
25796
|
startTime,
|
|
25584
25797
|
endTime,
|
|
25585
|
-
strategies
|
|
25798
|
+
strategies,
|
|
25799
|
+
deploymentId
|
|
25586
25800
|
});
|
|
25587
25801
|
const runtime = buildRuntimeEvidenceReportPayload({
|
|
25588
25802
|
userName: flags25.user,
|
|
@@ -25592,7 +25806,8 @@ var init_runtimeEvidence = __esm({
|
|
|
25592
25806
|
evaluations: evidence.evaluations,
|
|
25593
25807
|
trades: evidence.trades,
|
|
25594
25808
|
strategyConfigs: evidence.strategyConfigs,
|
|
25595
|
-
evaluationStatsBuckets: evidence.evaluationStatsBuckets
|
|
25809
|
+
evaluationStatsBuckets: evidence.evaluationStatsBuckets,
|
|
25810
|
+
lineageScopes: evidence.lineageScopes
|
|
25596
25811
|
});
|
|
25597
25812
|
const artifact = {
|
|
25598
25813
|
reportType: "runtime-evidence",
|
|
@@ -25606,6 +25821,7 @@ var init_runtimeEvidence = __esm({
|
|
|
25606
25821
|
source
|
|
25607
25822
|
},
|
|
25608
25823
|
strategies,
|
|
25824
|
+
deployment,
|
|
25609
25825
|
runtime
|
|
25610
25826
|
};
|
|
25611
25827
|
const outPath = import_node_path18.default.resolve(projectRoot9, String(flags25.out));
|
|
@@ -25615,7 +25831,7 @@ var init_runtimeEvidence = __esm({
|
|
|
25615
25831
|
const publishDir = String(flags25.publishDir ?? "").trim();
|
|
25616
25832
|
const published = publishDir ? await publishRuntimeEvidenceBundle({
|
|
25617
25833
|
publishRoot: import_node_path18.default.resolve(projectRoot9, publishDir),
|
|
25618
|
-
deploymentId
|
|
25834
|
+
deploymentId,
|
|
25619
25835
|
userName: String(flags25.user),
|
|
25620
25836
|
startTime,
|
|
25621
25837
|
endTime,
|
|
@@ -25626,8 +25842,9 @@ var init_runtimeEvidence = __esm({
|
|
|
25626
25842
|
...evidence.evaluations.map(
|
|
25627
25843
|
(evaluation) => evaluation.runtimeLineage
|
|
25628
25844
|
),
|
|
25629
|
-
...evidence.trades.map((trade) => trade.runtimeLineage)
|
|
25630
|
-
|
|
25845
|
+
...evidence.trades.map((trade) => trade.runtimeLineage),
|
|
25846
|
+
...evidence.lineageScopes.map((scope) => scope.lineage)
|
|
25847
|
+
].filter((lineage) => lineage != null).map(runtimeLineageKey).filter((key, index, values) => values.indexOf(key) === index)
|
|
25631
25848
|
}) : null;
|
|
25632
25849
|
console.log(import_chalk39.default.green(`Wrote ${outPath}`));
|
|
25633
25850
|
if (published) {
|
|
@@ -25886,10 +26103,11 @@ var init_runtimeEvidenceSync2 = __esm({
|
|
|
25886
26103
|
});
|
|
25887
26104
|
|
|
25888
26105
|
// src/lib/runtimeScorecard.ts
|
|
25889
|
-
var asRecord6, asArray3, finiteNumber5, finiteString2, round, unwrapRows, runtimePayload, runtimeWindow, extractRuntimeRows, buildRuntimeLineageSummary, belongsToStrategy, filterArtifactByStrategy, countBy2, buildDistributions, buildDistributionDelta, sum2, statsCount, tradeTimestamp, dedupeTrades, maxDrawdown, buildRollingPerformance, getReplayComparison, replayCountsForStrategy, getCalibrationSummary, getProspectiveSummary, buildRuntimeScorecard, formatRuntimeScorecardMarkdown;
|
|
26106
|
+
var asRecord6, asArray3, finiteNumber5, finiteString2, round, unwrapRows, runtimePayload, runtimeWindow, extractRuntimeRows, buildRuntimeLineageSummary, belongsToRuntimeLineage, runtimeDeploymentBinding, belongsToRuntimeDeployment, belongsToStrategy, filterArtifactByStrategy, countBy2, buildDistributions, buildDistributionDelta, sum2, statsCount, tradeTimestamp, dedupeTrades, maxDrawdown, buildRollingPerformance, getReplayComparison, replayCountsForStrategy, getCalibrationSummary, getProspectiveSummary, buildRuntimeScorecard, formatRuntimeScorecardMarkdown;
|
|
25890
26107
|
var init_runtimeScorecard = __esm({
|
|
25891
26108
|
"src/lib/runtimeScorecard.ts"() {
|
|
25892
26109
|
"use strict";
|
|
26110
|
+
init_runtimeLineage();
|
|
25893
26111
|
asRecord6 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
25894
26112
|
asArray3 = (value) => Array.isArray(value) ? value : [];
|
|
25895
26113
|
finiteNumber5 = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
@@ -25910,15 +26128,32 @@ var init_runtimeScorecard = __esm({
|
|
|
25910
26128
|
evaluations: unwrapRows(runtime.evaluations, "evaluation"),
|
|
25911
26129
|
signals: unwrapRows(runtime.signals, "signal"),
|
|
25912
26130
|
trades: unwrapRows(runtime.trades, "trade"),
|
|
26131
|
+
lineageScopes: unwrapRows(runtime.lineageScopes, "lineageScope"),
|
|
25913
26132
|
statsBuckets: asArray3(runtime.evaluationStatsBuckets).map(asRecord6).filter((item) => item != null)
|
|
25914
26133
|
};
|
|
25915
26134
|
};
|
|
25916
26135
|
buildRuntimeLineageSummary = (rows) => {
|
|
25917
|
-
const lineageRows = [
|
|
26136
|
+
const lineageRows = [
|
|
26137
|
+
...rows.evaluations,
|
|
26138
|
+
...rows.signals,
|
|
26139
|
+
...rows.trades,
|
|
26140
|
+
...rows.lineageScopes.map((scope) => ({
|
|
26141
|
+
runtimeLineage: scope.lineage
|
|
26142
|
+
}))
|
|
26143
|
+
];
|
|
25918
26144
|
const lineages = lineageRows.map((row) => asRecord6(row.runtimeLineage)).filter((lineage) => lineage != null);
|
|
25919
26145
|
const identities = /* @__PURE__ */ new Map();
|
|
25920
26146
|
for (const lineage of lineages) {
|
|
25921
|
-
const identity2 = {
|
|
26147
|
+
const identity2 = lineage.schemaVersion === 2 ? {
|
|
26148
|
+
schemaVersion: 2,
|
|
26149
|
+
version: finiteNumber5(lineage.version),
|
|
26150
|
+
strategyPackageVersion: finiteString2(
|
|
26151
|
+
lineage.strategyPackageVersion
|
|
26152
|
+
),
|
|
26153
|
+
runtimePackageVersion: finiteString2(lineage.runtimePackageVersion),
|
|
26154
|
+
maxLossValue: finiteNumber5(lineage.maxLossValue)
|
|
26155
|
+
} : {
|
|
26156
|
+
schemaVersion: 1,
|
|
25922
26157
|
compositionId: finiteString2(lineage.compositionId),
|
|
25923
26158
|
gitSha: finiteString2(lineage.gitSha),
|
|
25924
26159
|
gitDirty: typeof lineage.gitDirty === "boolean" ? lineage.gitDirty : null,
|
|
@@ -25930,12 +26165,23 @@ var init_runtimeScorecard = __esm({
|
|
|
25930
26165
|
identities.set(JSON.stringify(identity2), identity2);
|
|
25931
26166
|
}
|
|
25932
26167
|
const identity = identities.size === 1 ? [...identities.values()][0] : null;
|
|
25933
|
-
const
|
|
26168
|
+
const schemaVersion = finiteNumber5(identity?.schemaVersion);
|
|
26169
|
+
const identityComplete = lineages.length > 0 && identity != null && (schemaVersion === 2 && finiteNumber5(identity.version) != null && finiteString2(identity.strategyPackageVersion) != null && finiteString2(identity.runtimePackageVersion) != null || schemaVersion === 1 && identity.compositionId != null && identity.gitSha != null && identity.gitDirty === false && identity.gateFingerprint != null && identity.configFingerprint != null && identity.contextFingerprint != null) && identity.maxLossValue != null;
|
|
26170
|
+
const coverageComplete = lineageRows.length > 0 && lineages.length === lineageRows.length;
|
|
26171
|
+
const complete = identityComplete && coverageComplete;
|
|
26172
|
+
const lineageKey = identityComplete ? runtimeLineageKey(identity) : null;
|
|
25934
26173
|
return {
|
|
25935
26174
|
complete,
|
|
26175
|
+
identityComplete,
|
|
26176
|
+
coverageComplete,
|
|
25936
26177
|
conflicts: identities.size > 1,
|
|
25937
26178
|
rows: lineageRows.length,
|
|
25938
26179
|
rowsWithLineage: lineages.length,
|
|
26180
|
+
schemaVersion,
|
|
26181
|
+
lineageKey,
|
|
26182
|
+
version: finiteNumber5(identity?.version),
|
|
26183
|
+
strategyPackageVersion: finiteString2(identity?.strategyPackageVersion),
|
|
26184
|
+
runtimePackageVersion: finiteString2(identity?.runtimePackageVersion),
|
|
25939
26185
|
compositionId: finiteString2(identity?.compositionId),
|
|
25940
26186
|
gitSha: finiteString2(identity?.gitSha),
|
|
25941
26187
|
gitDirty: typeof identity?.gitDirty === "boolean" ? identity.gitDirty : null,
|
|
@@ -25945,6 +26191,20 @@ var init_runtimeScorecard = __esm({
|
|
|
25945
26191
|
maxLossValue: finiteNumber5(identity?.maxLossValue)
|
|
25946
26192
|
};
|
|
25947
26193
|
};
|
|
26194
|
+
belongsToRuntimeLineage = (row, summary) => {
|
|
26195
|
+
if (!summary.identityComplete || !summary.lineageKey) return false;
|
|
26196
|
+
const lineage = asRecord6(row.runtimeLineage);
|
|
26197
|
+
if (!lineage) return false;
|
|
26198
|
+
return runtimeLineageKey(lineage) === summary.lineageKey && finiteNumber5(lineage.maxLossValue) === summary.maxLossValue;
|
|
26199
|
+
};
|
|
26200
|
+
runtimeDeploymentBinding = (artifact) => {
|
|
26201
|
+
const deployment = asRecord6(asRecord6(artifact)?.deployment);
|
|
26202
|
+
return {
|
|
26203
|
+
deploymentId: finiteString2(deployment?.id),
|
|
26204
|
+
accountId: finiteString2(deployment?.accountId)
|
|
26205
|
+
};
|
|
26206
|
+
};
|
|
26207
|
+
belongsToRuntimeDeployment = (row, binding) => binding.deploymentId == null && binding.accountId == null ? true : finiteString2(row.deploymentId) === binding.deploymentId && finiteString2(row.accountId) === binding.accountId;
|
|
25948
26208
|
belongsToStrategy = (row, strategy) => strategy == null || finiteString2(row.strategy) === strategy;
|
|
25949
26209
|
filterArtifactByStrategy = (artifact, strategy) => {
|
|
25950
26210
|
if (!strategy) return artifact;
|
|
@@ -25972,6 +26232,9 @@ var init_runtimeScorecard = __esm({
|
|
|
25972
26232
|
strategy
|
|
25973
26233
|
)
|
|
25974
26234
|
),
|
|
26235
|
+
lineageScopes: asArray3(runtime.lineageScopes).filter(
|
|
26236
|
+
(item) => belongsToStrategy(asRecord6(item) ?? {}, strategy)
|
|
26237
|
+
),
|
|
25975
26238
|
evaluationStatsBuckets: asArray3(runtime.evaluationStatsBuckets).filter(
|
|
25976
26239
|
(item) => belongsToStrategy(asRecord6(item) ?? {}, strategy)
|
|
25977
26240
|
)
|
|
@@ -26151,6 +26414,7 @@ var init_runtimeScorecard = __esm({
|
|
|
26151
26414
|
const scopedHistoryArtifacts = historyRuntimeArtifacts.map(
|
|
26152
26415
|
(artifact) => filterArtifactByStrategy(artifact, strategy)
|
|
26153
26416
|
);
|
|
26417
|
+
const deploymentBinding = runtimeDeploymentBinding(runtimeArtifact);
|
|
26154
26418
|
const rows = extractRuntimeRows(scopedRuntimeArtifact);
|
|
26155
26419
|
const runtimeLineage = buildRuntimeLineageSummary(rows);
|
|
26156
26420
|
const window = runtimeWindow(runtimeArtifact);
|
|
@@ -26213,6 +26477,12 @@ var init_runtimeScorecard = __esm({
|
|
|
26213
26477
|
...scopedHistoryArtifacts,
|
|
26214
26478
|
scopedRuntimeArtifact
|
|
26215
26479
|
]);
|
|
26480
|
+
const comparableHistoryTrades = historyTrades.filter(
|
|
26481
|
+
(trade) => belongsToRuntimeDeployment(trade, deploymentBinding) && belongsToRuntimeLineage(trade, runtimeLineage)
|
|
26482
|
+
);
|
|
26483
|
+
const comparableCurrentClosedTrades = currentClosedTrades.filter(
|
|
26484
|
+
(trade) => belongsToRuntimeDeployment(trade, deploymentBinding) && belongsToRuntimeLineage(trade, runtimeLineage)
|
|
26485
|
+
);
|
|
26216
26486
|
const currentDistributions = buildDistributions(rows);
|
|
26217
26487
|
const previousArtifact = scopedHistoryArtifacts.map((artifact) => ({ artifact, window: runtimeWindow(artifact) })).filter(({ window: candidateWindow }) => {
|
|
26218
26488
|
const candidateEndTime = finiteNumber5(candidateWindow.endTime);
|
|
@@ -26223,7 +26493,7 @@ var init_runtimeScorecard = __esm({
|
|
|
26223
26493
|
const previousDistributions = previousArtifact ? buildDistributions(extractRuntimeRows(previousArtifact.artifact)) : null;
|
|
26224
26494
|
const rolling = [7, 30, 90].map(
|
|
26225
26495
|
(days) => buildRollingPerformance({
|
|
26226
|
-
trades: [...
|
|
26496
|
+
trades: [...comparableHistoryTrades],
|
|
26227
26497
|
anchorTime: endTime,
|
|
26228
26498
|
days
|
|
26229
26499
|
})
|
|
@@ -26237,6 +26507,13 @@ var init_runtimeScorecard = __esm({
|
|
|
26237
26507
|
message: lineageReason
|
|
26238
26508
|
});
|
|
26239
26509
|
}
|
|
26510
|
+
if (!runtimeLineage.complete) {
|
|
26511
|
+
reactions.push({
|
|
26512
|
+
code: "RUNTIME_LINEAGE_INCOMPLETE",
|
|
26513
|
+
severity: "blocking",
|
|
26514
|
+
message: "Runtime rows do not share one complete composition lineage."
|
|
26515
|
+
});
|
|
26516
|
+
}
|
|
26240
26517
|
if (parityRatio != null && parityRatio < thresholds.minimumParityRatio) {
|
|
26241
26518
|
reactions.push({
|
|
26242
26519
|
code: "PARITY_REGRESSION",
|
|
@@ -26274,6 +26551,7 @@ var init_runtimeScorecard = __esm({
|
|
|
26274
26551
|
generatedAt,
|
|
26275
26552
|
window: { startTime, endTime },
|
|
26276
26553
|
strategy,
|
|
26554
|
+
deployment: deploymentBinding,
|
|
26277
26555
|
lineage: runtimeLineage,
|
|
26278
26556
|
promotionStatus,
|
|
26279
26557
|
thresholds,
|
|
@@ -26318,17 +26596,25 @@ var init_runtimeScorecard = __esm({
|
|
|
26318
26596
|
)
|
|
26319
26597
|
).length,
|
|
26320
26598
|
fills: rows.trades.length,
|
|
26321
|
-
closedTrades: currentClosedTrades.length
|
|
26599
|
+
closedTrades: currentClosedTrades.length,
|
|
26600
|
+
comparableClosedTrades: comparableCurrentClosedTrades.length,
|
|
26601
|
+
nonComparableClosedTrades: currentClosedTrades.length - comparableCurrentClosedTrades.length
|
|
26322
26602
|
},
|
|
26323
26603
|
realized: {
|
|
26324
26604
|
pnl: sum2(
|
|
26325
|
-
|
|
26605
|
+
comparableCurrentClosedTrades.map(
|
|
26606
|
+
(trade) => finiteNumber5(trade.closedPnl)
|
|
26607
|
+
)
|
|
26326
26608
|
),
|
|
26327
26609
|
fees: sum2(
|
|
26328
|
-
|
|
26610
|
+
comparableCurrentClosedTrades.map(
|
|
26611
|
+
(trade) => finiteNumber5(trade.totalFee)
|
|
26612
|
+
)
|
|
26329
26613
|
),
|
|
26330
26614
|
funding: sum2(
|
|
26331
|
-
|
|
26615
|
+
comparableCurrentClosedTrades.map(
|
|
26616
|
+
(trade) => finiteNumber5(trade.fundingFee)
|
|
26617
|
+
)
|
|
26332
26618
|
)
|
|
26333
26619
|
},
|
|
26334
26620
|
gateComparison: {
|
|
@@ -28094,13 +28380,13 @@ __export(runtimeControl_exports, {
|
|
|
28094
28380
|
main: () => main37,
|
|
28095
28381
|
runtimeControl: () => runtimeControl
|
|
28096
28382
|
});
|
|
28097
|
-
var import_config9, import_runtimeControls,
|
|
28383
|
+
var import_config9, import_runtimeControls, import_runtimeStrategies4, argv, RUNTIME_CONTROL_ACTIONS, action, option, required2, projectRoot12, userName2, verify, inspect, updateControlState, runtimeControl, main37;
|
|
28098
28384
|
var init_runtimeControl = __esm({
|
|
28099
28385
|
"src/scripts/runtimeControl.ts"() {
|
|
28100
28386
|
"use strict";
|
|
28101
28387
|
import_config9 = require("dotenv/config");
|
|
28102
28388
|
import_runtimeControls = require("@tradejs/infra/runtimeControls");
|
|
28103
|
-
|
|
28389
|
+
import_runtimeStrategies4 = require("@tradejs/node/runtimeStrategies");
|
|
28104
28390
|
argv = process.argv.slice(2);
|
|
28105
28391
|
RUNTIME_CONTROL_ACTIONS = [
|
|
28106
28392
|
"inspect",
|
|
@@ -28121,7 +28407,7 @@ var init_runtimeControl = __esm({
|
|
|
28121
28407
|
projectRoot12 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
|
|
28122
28408
|
userName2 = String(option("user") ?? process.env.USER_NAME ?? "root");
|
|
28123
28409
|
verify = async () => {
|
|
28124
|
-
const deployments = await (0,
|
|
28410
|
+
const deployments = await (0, import_runtimeStrategies4.listRuntimeDeployments)({ userName: userName2, projectRoot: projectRoot12 });
|
|
28125
28411
|
const requestedDeployment = option("deployment");
|
|
28126
28412
|
const selected = requestedDeployment ? deployments.filter((deployment) => deployment.id === requestedDeployment) : deployments;
|
|
28127
28413
|
if (requestedDeployment && !selected.length) {
|
|
@@ -28130,7 +28416,7 @@ var init_runtimeControl = __esm({
|
|
|
28130
28416
|
const results2 = [];
|
|
28131
28417
|
for (const deployment of selected) {
|
|
28132
28418
|
try {
|
|
28133
|
-
const strategies = await (0,
|
|
28419
|
+
const strategies = await (0, import_runtimeStrategies4.loadResolvedRuntimeStrategies)({
|
|
28134
28420
|
userName: userName2,
|
|
28135
28421
|
projectRoot: projectRoot12,
|
|
28136
28422
|
deploymentId: deployment.id
|
|
@@ -28164,7 +28450,7 @@ var init_runtimeControl = __esm({
|
|
|
28164
28450
|
inspect = async () => {
|
|
28165
28451
|
const requestedDeployment = option("deployment");
|
|
28166
28452
|
const requestedStrategy = option("strategy");
|
|
28167
|
-
const deployments = (await (0,
|
|
28453
|
+
const deployments = (await (0, import_runtimeStrategies4.listRuntimeDeployments)({ userName: userName2, projectRoot: projectRoot12 })).filter(
|
|
28168
28454
|
(deployment) => !requestedDeployment || deployment.id === requestedDeployment
|
|
28169
28455
|
).map((deployment) => ({
|
|
28170
28456
|
...deployment,
|
|
@@ -28177,7 +28463,7 @@ var init_runtimeControl = __esm({
|
|
|
28177
28463
|
updateControlState = async (nextState) => {
|
|
28178
28464
|
const deploymentId = required2("deployment");
|
|
28179
28465
|
const strategyName = required2("strategy");
|
|
28180
|
-
const deployment = await (0,
|
|
28466
|
+
const deployment = await (0, import_runtimeStrategies4.getRuntimeDeployment)({
|
|
28181
28467
|
userName: userName2,
|
|
28182
28468
|
projectRoot: projectRoot12,
|
|
28183
28469
|
deploymentId
|
|
@@ -28207,7 +28493,7 @@ var init_runtimeControl = __esm({
|
|
|
28207
28493
|
} else {
|
|
28208
28494
|
await (0, import_runtimeControls.resumeRuntimeStrategy)({ userName: userName2, deploymentId, strategyName });
|
|
28209
28495
|
}
|
|
28210
|
-
const updated = await (0,
|
|
28496
|
+
const updated = await (0, import_runtimeStrategies4.getRuntimeDeployment)({
|
|
28211
28497
|
userName: userName2,
|
|
28212
28498
|
projectRoot: projectRoot12,
|
|
28213
28499
|
deploymentId
|
|
@@ -31155,11 +31441,11 @@ var init_hooks = __esm({
|
|
|
31155
31441
|
});
|
|
31156
31442
|
|
|
31157
31443
|
// src/lib/signals/runtimeStrategies.ts
|
|
31158
|
-
var
|
|
31444
|
+
var import_runtimeStrategies5;
|
|
31159
31445
|
var init_runtimeStrategies = __esm({
|
|
31160
31446
|
"src/lib/signals/runtimeStrategies.ts"() {
|
|
31161
31447
|
"use strict";
|
|
31162
|
-
|
|
31448
|
+
import_runtimeStrategies5 = require("@tradejs/node/runtimeStrategies");
|
|
31163
31449
|
}
|
|
31164
31450
|
});
|
|
31165
31451
|
|
|
@@ -31234,9 +31520,28 @@ var init_evaluations = __esm({
|
|
|
31234
31520
|
symbol,
|
|
31235
31521
|
timestamp,
|
|
31236
31522
|
runtimeConfigId,
|
|
31237
|
-
runtimeVersion
|
|
31238
|
-
|
|
31523
|
+
runtimeVersion,
|
|
31524
|
+
deploymentId,
|
|
31525
|
+
accountId
|
|
31526
|
+
}) => {
|
|
31527
|
+
const runtimeScope = deploymentId ? [deploymentId, accountId ?? "default-account"] : [];
|
|
31528
|
+
return runtimeVersion ? [
|
|
31529
|
+
...runtimeScope,
|
|
31530
|
+
strategyName,
|
|
31531
|
+
`v${runtimeVersion}`,
|
|
31532
|
+
symbol,
|
|
31533
|
+
timestamp
|
|
31534
|
+
].join(":") : runtimeConfigId && runtimeConfigId !== "config" ? [
|
|
31535
|
+
...runtimeScope,
|
|
31536
|
+
strategyName,
|
|
31537
|
+
runtimeConfigId,
|
|
31538
|
+
symbol,
|
|
31539
|
+
timestamp
|
|
31540
|
+
].join(":") : [...runtimeScope, strategyName, symbol, timestamp].join(":");
|
|
31541
|
+
};
|
|
31239
31542
|
buildLineageField = (scope) => [
|
|
31543
|
+
scope.deploymentId ?? "default-deployment",
|
|
31544
|
+
scope.accountId ?? "default-account",
|
|
31240
31545
|
scope.strategy,
|
|
31241
31546
|
scope.runtimeConfigId ?? "config",
|
|
31242
31547
|
scope.runtimeVersion ? `v${scope.runtimeVersion}` : "legacy",
|
|
@@ -31278,6 +31583,8 @@ var init_evaluations = __esm({
|
|
|
31278
31583
|
for (const evaluation of lineageEvaluations) {
|
|
31279
31584
|
const lineageField = buildLineageField({
|
|
31280
31585
|
strategy: evaluation.strategy,
|
|
31586
|
+
deploymentId: evaluation.deploymentId,
|
|
31587
|
+
accountId: evaluation.accountId,
|
|
31281
31588
|
runtimeConfigId: evaluation.runtimeConfigId,
|
|
31282
31589
|
runtimeVersion: evaluation.runtimeVersion,
|
|
31283
31590
|
symbol: evaluation.symbol,
|
|
@@ -31288,6 +31595,8 @@ var init_evaluations = __esm({
|
|
|
31288
31595
|
const scope = {
|
|
31289
31596
|
strategy: evaluation.strategy,
|
|
31290
31597
|
symbol: evaluation.symbol,
|
|
31598
|
+
...evaluation.deploymentId ? { deploymentId: evaluation.deploymentId } : {},
|
|
31599
|
+
...evaluation.accountId ? { accountId: evaluation.accountId } : {},
|
|
31291
31600
|
runtimeConfigId: evaluation.runtimeConfigId,
|
|
31292
31601
|
runtimeVersion: evaluation.runtimeVersion,
|
|
31293
31602
|
lineage: evaluation.runtimeLineage,
|
|
@@ -31331,7 +31640,8 @@ var init_evaluations = __esm({
|
|
|
31331
31640
|
const statsBucket = import_redis18.redisKeys.runtimeSignalEvaluationStatsBucket(
|
|
31332
31641
|
evaluation.userName,
|
|
31333
31642
|
dayKey,
|
|
31334
|
-
evaluation.strategy
|
|
31643
|
+
evaluation.strategy,
|
|
31644
|
+
evaluation.deploymentId
|
|
31335
31645
|
);
|
|
31336
31646
|
const increments = statsIncrements.get(statsBucket) ?? {};
|
|
31337
31647
|
for (const [field, increment] of Object.entries(
|
|
@@ -31954,7 +32264,9 @@ var init_tickerEvaluator = __esm({
|
|
|
31954
32264
|
symbol,
|
|
31955
32265
|
timestamp: lastCandle.timestamp,
|
|
31956
32266
|
runtimeConfigId: runtimeIdentity,
|
|
31957
|
-
runtimeVersion: version
|
|
32267
|
+
runtimeVersion: version,
|
|
32268
|
+
deploymentId,
|
|
32269
|
+
accountId
|
|
31958
32270
|
}),
|
|
31959
32271
|
userName: userName3,
|
|
31960
32272
|
strategy: strategyName,
|
|
@@ -31979,8 +32291,14 @@ var init_tickerEvaluator = __esm({
|
|
|
31979
32291
|
signal.runtimeConfigId = runtimeIdentity;
|
|
31980
32292
|
signal.runtimeVersion = version;
|
|
31981
32293
|
signal.runtimeLineage = runtimeLineage;
|
|
31982
|
-
|
|
31983
|
-
|
|
32294
|
+
signal.deploymentId = deploymentId;
|
|
32295
|
+
signal.accountId = accountId;
|
|
32296
|
+
const signalRuntimeIdentity = [
|
|
32297
|
+
...deploymentId ? [deploymentId, accountId ?? "default-account"] : [],
|
|
32298
|
+
...version ? [`v${version}`] : []
|
|
32299
|
+
].join(":");
|
|
32300
|
+
if (signalRuntimeIdentity && !signal.signalId.endsWith(`:${signalRuntimeIdentity}`)) {
|
|
32301
|
+
signal.signalId = `${signal.signalId}:${signalRuntimeIdentity}`;
|
|
31984
32302
|
}
|
|
31985
32303
|
await (0, import_strategies11.enrichSignalWithBinanceMarketContext)({ signal, env: "CRON" });
|
|
31986
32304
|
if (signal.orderStatus === "skipped" && typeof signal.orderSkipReason === "string" && signal.orderSkipReason.trim()) {
|
|
@@ -31999,7 +32317,9 @@ var init_tickerEvaluator = __esm({
|
|
|
31999
32317
|
symbol,
|
|
32000
32318
|
timestamp: lastCandle.timestamp,
|
|
32001
32319
|
runtimeConfigId: runtimeIdentity,
|
|
32002
|
-
runtimeVersion: version
|
|
32320
|
+
runtimeVersion: version,
|
|
32321
|
+
deploymentId,
|
|
32322
|
+
accountId
|
|
32003
32323
|
}),
|
|
32004
32324
|
userName: userName3,
|
|
32005
32325
|
strategy: strategyName,
|
|
@@ -32083,7 +32403,7 @@ var init_configuredScopes = __esm({
|
|
|
32083
32403
|
});
|
|
32084
32404
|
|
|
32085
32405
|
// src/lib/signals/runner.ts
|
|
32086
|
-
var import_progress11, import_chalk45, import_connectors16, import_cli12, import_async5, import_strategies12, import_constants16, import_time8, import_logger10, import_runtimeHeartbeats,
|
|
32406
|
+
var import_progress11, import_chalk45, import_connectors16, import_cli12, import_async5, import_strategies12, import_constants16, import_time8, import_logger10, import_runtimeHeartbeats, import_runtimeStrategies6, SLOW_SIGNALS_WARNING_MS, formatDuration3, resolvePositiveInteger2, resolveNonNegativeInteger, createSignalsRunner;
|
|
32087
32407
|
var init_runner = __esm({
|
|
32088
32408
|
"src/lib/signals/runner.ts"() {
|
|
32089
32409
|
"use strict";
|
|
@@ -32097,7 +32417,7 @@ var init_runner = __esm({
|
|
|
32097
32417
|
import_time8 = require("@tradejs/core/time");
|
|
32098
32418
|
import_logger10 = require("@tradejs/infra/logger");
|
|
32099
32419
|
import_runtimeHeartbeats = require("@tradejs/infra/runtimeHeartbeats");
|
|
32100
|
-
|
|
32420
|
+
import_runtimeStrategies6 = require("@tradejs/node/runtimeStrategies");
|
|
32101
32421
|
init_windows();
|
|
32102
32422
|
init_runFormatting();
|
|
32103
32423
|
init_hooks();
|
|
@@ -32173,7 +32493,7 @@ var init_runner = __esm({
|
|
|
32173
32493
|
return connectorName;
|
|
32174
32494
|
};
|
|
32175
32495
|
const createSignalsSession2 = async (lifecycle, scope = {}) => {
|
|
32176
|
-
const deployment = config2.deploymentId ? await (0,
|
|
32496
|
+
const deployment = config2.deploymentId ? await (0, import_runtimeStrategies6.getRuntimeDeployment)({
|
|
32177
32497
|
userName: config2.userName,
|
|
32178
32498
|
projectRoot: projectRoot15,
|
|
32179
32499
|
deploymentId: config2.deploymentId
|
|
@@ -32398,7 +32718,7 @@ var init_runner = __esm({
|
|
|
32398
32718
|
const primaryEthByTimestamp = new Map(
|
|
32399
32719
|
primaryEthClosedData.map((candle) => [candle.timestamp, candle])
|
|
32400
32720
|
);
|
|
32401
|
-
const runtimeStrategies = await (0,
|
|
32721
|
+
const runtimeStrategies = await (0, import_runtimeStrategies5.loadResolvedRuntimeStrategies)({
|
|
32402
32722
|
userName: config2.userName,
|
|
32403
32723
|
projectRoot: projectRoot15,
|
|
32404
32724
|
deploymentId: deployment?.id ?? "",
|
|
@@ -32612,7 +32932,7 @@ var init_runner = __esm({
|
|
|
32612
32932
|
}
|
|
32613
32933
|
};
|
|
32614
32934
|
const loadConfiguredSignalsScopes = async (deployment) => {
|
|
32615
|
-
const configuredStrategies = await (0,
|
|
32935
|
+
const configuredStrategies = await (0, import_runtimeStrategies5.loadResolvedRuntimeStrategies)({
|
|
32616
32936
|
userName: config2.userName,
|
|
32617
32937
|
projectRoot: projectRoot15,
|
|
32618
32938
|
deploymentId: deployment.id
|
|
@@ -32635,7 +32955,7 @@ var init_runner = __esm({
|
|
|
32635
32955
|
if (!config2.deploymentId) {
|
|
32636
32956
|
throw new Error("Runtime deployment id is required");
|
|
32637
32957
|
}
|
|
32638
|
-
const configuredDeployment = await (0,
|
|
32958
|
+
const configuredDeployment = await (0, import_runtimeStrategies6.getRuntimeDeployment)({
|
|
32639
32959
|
userName: config2.userName,
|
|
32640
32960
|
projectRoot: projectRoot15,
|
|
32641
32961
|
deploymentId: config2.deploymentId
|
|
@@ -32669,7 +32989,7 @@ var init_runner = __esm({
|
|
|
32669
32989
|
throw new Error("Runtime deployment id is required");
|
|
32670
32990
|
}
|
|
32671
32991
|
const deploymentId = config2.deploymentId;
|
|
32672
|
-
const initialDeployment = await (0,
|
|
32992
|
+
const initialDeployment = await (0, import_runtimeStrategies6.getRuntimeDeployment)({
|
|
32673
32993
|
userName: config2.userName,
|
|
32674
32994
|
projectRoot: projectRoot15,
|
|
32675
32995
|
deploymentId
|
|
@@ -32694,7 +33014,7 @@ var init_runner = __esm({
|
|
|
32694
33014
|
settleDelayMs: resolveNonNegativeInteger(config2.settleDelayMs, 5e3),
|
|
32695
33015
|
signal: abortController.signal,
|
|
32696
33016
|
runCycle: async () => {
|
|
32697
|
-
const currentDeployment = await (0,
|
|
33017
|
+
const currentDeployment = await (0, import_runtimeStrategies6.getRuntimeDeployment)({
|
|
32698
33018
|
userName: config2.userName,
|
|
32699
33019
|
projectRoot: projectRoot15,
|
|
32700
33020
|
deploymentId
|
|
@@ -32899,7 +33219,7 @@ var init_signalsDaemon = __esm({
|
|
|
32899
33219
|
});
|
|
32900
33220
|
|
|
32901
33221
|
// src/lib/replay/cliConfig.ts
|
|
32902
|
-
var import_args32, REPLAY_UNSUPPORTED_FLAGS, hasCliFlag2, assertNoUnsupportedReplayFlags, replayNormalizedArgv, replayFlags, replayInterval, replayUserName, replayProjectRoot, replayRuntimeEvidencePath, isReplayUpdateOnlyRun;
|
|
33222
|
+
var import_args32, REPLAY_UNSUPPORTED_FLAGS, hasCliFlag2, assertNoUnsupportedReplayFlags, replayNormalizedArgv, replayFlags, replayInterval, replayUserName, replayProjectRoot, replayRuntimeEvidencePath, replayDeploymentId, isReplayUpdateOnlyRun;
|
|
32903
33223
|
var init_cliConfig2 = __esm({
|
|
32904
33224
|
"src/lib/replay/cliConfig.ts"() {
|
|
32905
33225
|
"use strict";
|
|
@@ -32952,6 +33272,11 @@ var init_cliConfig2 = __esm({
|
|
|
32952
33272
|
"runtimeEvidence",
|
|
32953
33273
|
"Immutable runtime evidence JSON used for offline runtime comparison"
|
|
32954
33274
|
);
|
|
33275
|
+
import_args32.default.option(
|
|
33276
|
+
"deployment",
|
|
33277
|
+
"Git-owned runtime deployment used when runtime evidence is omitted",
|
|
33278
|
+
"production"
|
|
33279
|
+
);
|
|
32955
33280
|
import_args32.default.option(["u", "updateOnly"], "Only update tickers history", false);
|
|
32956
33281
|
import_args32.default.option(["C", "cacheOnly"], "Do not update tickers history", false);
|
|
32957
33282
|
import_args32.default.option(
|
|
@@ -32978,10 +33303,203 @@ var init_cliConfig2 = __esm({
|
|
|
32978
33303
|
replayUserName = String(replayFlags.user ?? "root");
|
|
32979
33304
|
replayProjectRoot = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
|
|
32980
33305
|
replayRuntimeEvidencePath = typeof replayFlags.runtimeEvidence === "string" && replayFlags.runtimeEvidence.trim() ? replayFlags.runtimeEvidence.trim() : null;
|
|
33306
|
+
replayDeploymentId = String(
|
|
33307
|
+
replayFlags.deployment ?? "production"
|
|
33308
|
+
).trim();
|
|
32981
33309
|
isReplayUpdateOnlyRun = Boolean(replayFlags.updateOnly);
|
|
32982
33310
|
}
|
|
32983
33311
|
});
|
|
32984
33312
|
|
|
33313
|
+
// src/lib/replay/runtimeEvidenceSource.ts
|
|
33314
|
+
var import_promises29, import_node_path24, asRecord7, asFiniteNumber, unwrapRows2, assertRuntimeRowsMatchDeployment, readRuntimeEvidenceArtifact, loadReplayRuntimeEvidenceMetadata, buildRuntimeEvidenceLineageScopes, loadReplayRuntimeEvidenceSource;
|
|
33315
|
+
var init_runtimeEvidenceSource = __esm({
|
|
33316
|
+
"src/lib/replay/runtimeEvidenceSource.ts"() {
|
|
33317
|
+
"use strict";
|
|
33318
|
+
import_promises29 = __toESM(require("fs/promises"));
|
|
33319
|
+
import_node_path24 = __toESM(require("path"));
|
|
33320
|
+
init_runtimeLineage();
|
|
33321
|
+
init_runtimeEvidenceDeployment();
|
|
33322
|
+
asRecord7 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
33323
|
+
asFiniteNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
33324
|
+
unwrapRows2 = (value, field) => (Array.isArray(value) ? value : []).map((item) => {
|
|
33325
|
+
const row = asRecord7(item);
|
|
33326
|
+
return asRecord7(row?.[field]) ?? row;
|
|
33327
|
+
}).filter((item) => item != null);
|
|
33328
|
+
assertRuntimeRowsMatchDeployment = ({
|
|
33329
|
+
label,
|
|
33330
|
+
rows,
|
|
33331
|
+
deployment
|
|
33332
|
+
}) => {
|
|
33333
|
+
const activeStrategies = new Set(
|
|
33334
|
+
activeRuntimeEvidenceStrategies(deployment).map(
|
|
33335
|
+
({ strategyName }) => strategyName
|
|
33336
|
+
)
|
|
33337
|
+
);
|
|
33338
|
+
for (const row of rows) {
|
|
33339
|
+
if (row.deploymentId !== deployment.id || row.accountId !== deployment.accountId || !row.strategy || !activeStrategies.has(row.strategy)) {
|
|
33340
|
+
throw new Error(
|
|
33341
|
+
`Runtime evidence ${label} row is outside embedded deployment composition`
|
|
33342
|
+
);
|
|
33343
|
+
}
|
|
33344
|
+
}
|
|
33345
|
+
};
|
|
33346
|
+
readRuntimeEvidenceArtifact = async ({
|
|
33347
|
+
filePath,
|
|
33348
|
+
projectRoot: projectRoot15
|
|
33349
|
+
}) => {
|
|
33350
|
+
const resolvedPath = import_node_path24.default.resolve(projectRoot15, filePath);
|
|
33351
|
+
const root = asRecord7(
|
|
33352
|
+
JSON.parse(await import_promises29.default.readFile(resolvedPath, "utf8"))
|
|
33353
|
+
);
|
|
33354
|
+
const runtime = asRecord7(root?.runtime) ?? root;
|
|
33355
|
+
if (!root || !runtime) {
|
|
33356
|
+
throw new Error(`Invalid runtime evidence JSON: ${resolvedPath}`);
|
|
33357
|
+
}
|
|
33358
|
+
const rootWindow = asRecord7(root.window);
|
|
33359
|
+
const runtimeWindow2 = asRecord7(runtime.window);
|
|
33360
|
+
return {
|
|
33361
|
+
resolvedPath,
|
|
33362
|
+
root,
|
|
33363
|
+
runtime,
|
|
33364
|
+
userName: String(root.userName ?? runtime.userName ?? "").trim(),
|
|
33365
|
+
startTime: asFiniteNumber(rootWindow?.startTime) ?? asFiniteNumber(runtimeWindow2?.startTime),
|
|
33366
|
+
endTime: asFiniteNumber(rootWindow?.endTime) ?? asFiniteNumber(runtimeWindow2?.endTime),
|
|
33367
|
+
deployment: parseRuntimeEvidenceDeploymentSnapshot(root.deployment)
|
|
33368
|
+
};
|
|
33369
|
+
};
|
|
33370
|
+
loadReplayRuntimeEvidenceMetadata = async (params) => {
|
|
33371
|
+
const artifact = await readRuntimeEvidenceArtifact(params);
|
|
33372
|
+
return {
|
|
33373
|
+
path: artifact.resolvedPath,
|
|
33374
|
+
userName: artifact.userName,
|
|
33375
|
+
startTime: artifact.startTime,
|
|
33376
|
+
endTime: artifact.endTime,
|
|
33377
|
+
deployment: artifact.deployment
|
|
33378
|
+
};
|
|
33379
|
+
};
|
|
33380
|
+
buildRuntimeEvidenceLineageScopes = ({
|
|
33381
|
+
signals: signals2,
|
|
33382
|
+
evaluations
|
|
33383
|
+
}) => {
|
|
33384
|
+
const scopes = /* @__PURE__ */ new Map();
|
|
33385
|
+
const add = ({
|
|
33386
|
+
strategy,
|
|
33387
|
+
symbol,
|
|
33388
|
+
deploymentId,
|
|
33389
|
+
accountId,
|
|
33390
|
+
runtimeConfigId,
|
|
33391
|
+
runtimeVersion,
|
|
33392
|
+
timestamp,
|
|
33393
|
+
lineage
|
|
33394
|
+
}) => {
|
|
33395
|
+
if (!lineage || !Number.isFinite(timestamp)) {
|
|
33396
|
+
return;
|
|
33397
|
+
}
|
|
33398
|
+
const key = `${deploymentId ?? "default"}::${accountId ?? "default"}::${strategy}::${symbol}::${runtimeLineageKey(lineage)}`;
|
|
33399
|
+
const existing = scopes.get(key);
|
|
33400
|
+
scopes.set(key, {
|
|
33401
|
+
strategy,
|
|
33402
|
+
symbol,
|
|
33403
|
+
...deploymentId ? { deploymentId } : {},
|
|
33404
|
+
...accountId ? { accountId } : {},
|
|
33405
|
+
...runtimeConfigId ? { runtimeConfigId } : {},
|
|
33406
|
+
...runtimeVersion ? { runtimeVersion } : {},
|
|
33407
|
+
lineage,
|
|
33408
|
+
firstTimestamp: existing ? Math.min(existing.firstTimestamp, timestamp) : timestamp,
|
|
33409
|
+
lastTimestamp: existing ? Math.max(existing.lastTimestamp, timestamp) : timestamp
|
|
33410
|
+
});
|
|
33411
|
+
};
|
|
33412
|
+
for (const signal of signals2) {
|
|
33413
|
+
add({
|
|
33414
|
+
strategy: signal.strategy,
|
|
33415
|
+
symbol: signal.symbol,
|
|
33416
|
+
deploymentId: signal.deploymentId,
|
|
33417
|
+
accountId: signal.accountId,
|
|
33418
|
+
runtimeConfigId: signal.runtimeConfigId,
|
|
33419
|
+
runtimeVersion: signal.runtimeVersion,
|
|
33420
|
+
timestamp: signal.timestamp,
|
|
33421
|
+
lineage: signal.runtimeLineage
|
|
33422
|
+
});
|
|
33423
|
+
}
|
|
33424
|
+
for (const evaluation of evaluations) {
|
|
33425
|
+
add({
|
|
33426
|
+
strategy: evaluation.strategy,
|
|
33427
|
+
symbol: evaluation.symbol,
|
|
33428
|
+
deploymentId: evaluation.deploymentId,
|
|
33429
|
+
accountId: evaluation.accountId,
|
|
33430
|
+
runtimeConfigId: evaluation.runtimeConfigId,
|
|
33431
|
+
runtimeVersion: evaluation.runtimeVersion,
|
|
33432
|
+
timestamp: evaluation.timestamp,
|
|
33433
|
+
lineage: evaluation.runtimeLineage
|
|
33434
|
+
});
|
|
33435
|
+
}
|
|
33436
|
+
return [...scopes.values()].sort(
|
|
33437
|
+
(left, right) => left.strategy.localeCompare(right.strategy) || left.symbol.localeCompare(right.symbol) || left.firstTimestamp - right.firstTimestamp
|
|
33438
|
+
);
|
|
33439
|
+
};
|
|
33440
|
+
loadReplayRuntimeEvidenceSource = async ({
|
|
33441
|
+
filePath,
|
|
33442
|
+
projectRoot: projectRoot15,
|
|
33443
|
+
expectedUserName,
|
|
33444
|
+
expectedWindow
|
|
33445
|
+
}) => {
|
|
33446
|
+
const { resolvedPath, runtime, userName: userName3, startTime, endTime, deployment } = await readRuntimeEvidenceArtifact({ filePath, projectRoot: projectRoot15 });
|
|
33447
|
+
if (!userName3 || userName3 !== expectedUserName) {
|
|
33448
|
+
throw new Error(
|
|
33449
|
+
`Runtime evidence user mismatch: expected=${expectedUserName}, actual=${userName3 || "missing"}`
|
|
33450
|
+
);
|
|
33451
|
+
}
|
|
33452
|
+
const endTimeMatches = endTime === expectedWindow.end || endTime === expectedWindow.end + 1;
|
|
33453
|
+
if (startTime !== expectedWindow.start || !endTimeMatches) {
|
|
33454
|
+
throw new Error(
|
|
33455
|
+
`Runtime evidence window mismatch: expected=${expectedWindow.start}..${expectedWindow.end}, actual=${startTime ?? "missing"}..${endTime ?? "missing"}`
|
|
33456
|
+
);
|
|
33457
|
+
}
|
|
33458
|
+
const trades = unwrapRows2(runtime.trades, "trade");
|
|
33459
|
+
const signals2 = unwrapRows2(runtime.signals, "signal");
|
|
33460
|
+
const evaluations = unwrapRows2(
|
|
33461
|
+
runtime.evaluations,
|
|
33462
|
+
"evaluation"
|
|
33463
|
+
);
|
|
33464
|
+
const storedLineageScopes = unwrapRows2(
|
|
33465
|
+
runtime.lineageScopes,
|
|
33466
|
+
"lineageScope"
|
|
33467
|
+
);
|
|
33468
|
+
assertRuntimeRowsMatchDeployment({
|
|
33469
|
+
label: "trade",
|
|
33470
|
+
rows: trades,
|
|
33471
|
+
deployment
|
|
33472
|
+
});
|
|
33473
|
+
assertRuntimeRowsMatchDeployment({
|
|
33474
|
+
label: "signal",
|
|
33475
|
+
rows: signals2,
|
|
33476
|
+
deployment
|
|
33477
|
+
});
|
|
33478
|
+
assertRuntimeRowsMatchDeployment({
|
|
33479
|
+
label: "evaluation",
|
|
33480
|
+
rows: evaluations,
|
|
33481
|
+
deployment
|
|
33482
|
+
});
|
|
33483
|
+
assertRuntimeRowsMatchDeployment({
|
|
33484
|
+
label: "lineage scope",
|
|
33485
|
+
rows: storedLineageScopes,
|
|
33486
|
+
deployment
|
|
33487
|
+
});
|
|
33488
|
+
return {
|
|
33489
|
+
path: resolvedPath,
|
|
33490
|
+
userName: userName3,
|
|
33491
|
+
startTime,
|
|
33492
|
+
endTime,
|
|
33493
|
+
trades,
|
|
33494
|
+
signals: signals2,
|
|
33495
|
+
evaluations,
|
|
33496
|
+
lineageScopes: storedLineageScopes.length ? storedLineageScopes : buildRuntimeEvidenceLineageScopes({ signals: signals2, evaluations }),
|
|
33497
|
+
deployment
|
|
33498
|
+
};
|
|
33499
|
+
};
|
|
33500
|
+
}
|
|
33501
|
+
});
|
|
33502
|
+
|
|
32985
33503
|
// src/lib/replay/portfolioReplayConnector.ts
|
|
32986
33504
|
var import_constants17, import_math, import_trade2, UNKNOWN_STRATEGY, getStrategyName, getPositionPnlSnapshot, createPortfolioReplayConnector;
|
|
32987
33505
|
var init_portfolioReplayConnector = __esm({
|
|
@@ -33393,7 +33911,7 @@ var init_portfolioReplayConnector = __esm({
|
|
|
33393
33911
|
});
|
|
33394
33912
|
|
|
33395
33913
|
// src/lib/replay/historicalSignalsReplay.ts
|
|
33396
|
-
var import_chalk46, import_progress12, import_backtest4, import_strategies13, import_time9, import_logger11, import_redis19, import_connectors17, import_cli13, import_strategies14, loadRuntimeStrategies, loadReferenceConnector, buildPreparedData, buildAfterSignalsContext, buildSymbolSharedReplayKey, runHistoricalSignalsReplay;
|
|
33914
|
+
var import_chalk46, import_progress12, import_backtest4, import_strategies13, import_time9, import_logger11, import_redis19, import_connectors17, import_cli13, import_strategies14, import_runtimeStrategies8, loadRuntimeStrategies, loadReferenceConnector, buildPreparedData, buildAfterSignalsContext, buildSymbolSharedReplayKey, runHistoricalSignalsReplay;
|
|
33397
33915
|
var init_historicalSignalsReplay = __esm({
|
|
33398
33916
|
"src/lib/replay/historicalSignalsReplay.ts"() {
|
|
33399
33917
|
"use strict";
|
|
@@ -33407,6 +33925,7 @@ var init_historicalSignalsReplay = __esm({
|
|
|
33407
33925
|
import_connectors17 = require("@tradejs/node/connectors");
|
|
33408
33926
|
import_cli13 = require("@tradejs/node/cli");
|
|
33409
33927
|
import_strategies14 = require("@tradejs/node/strategies");
|
|
33928
|
+
import_runtimeStrategies8 = require("@tradejs/node/runtimeStrategies");
|
|
33410
33929
|
init_cliConfig2();
|
|
33411
33930
|
init_support();
|
|
33412
33931
|
init_portfolioReplayConnector();
|
|
@@ -33415,7 +33934,15 @@ var init_historicalSignalsReplay = __esm({
|
|
|
33415
33934
|
init_runtimeLineage();
|
|
33416
33935
|
loadRuntimeStrategies = async (runtimeStrategies) => {
|
|
33417
33936
|
const strategies = await Promise.all(
|
|
33418
|
-
runtimeStrategies.map(async (
|
|
33937
|
+
runtimeStrategies.map(async (runtimeStrategy) => {
|
|
33938
|
+
const {
|
|
33939
|
+
strategyName,
|
|
33940
|
+
version,
|
|
33941
|
+
strategyPackage,
|
|
33942
|
+
strategyPackageVersion,
|
|
33943
|
+
runtimePackageVersion,
|
|
33944
|
+
strategyConfig
|
|
33945
|
+
} = runtimeStrategy;
|
|
33419
33946
|
const strategyCreator = await (0, import_strategies14.getStrategyCreator)(
|
|
33420
33947
|
strategyName,
|
|
33421
33948
|
replayProjectRoot
|
|
@@ -33423,12 +33950,25 @@ var init_historicalSignalsReplay = __esm({
|
|
|
33423
33950
|
if (!strategyCreator) {
|
|
33424
33951
|
throw new Error(`Unknown strategy: ${strategyName}`);
|
|
33425
33952
|
}
|
|
33953
|
+
const installed = await (0, import_runtimeStrategies8.getRuntimeStrategyPackageMetadata)({
|
|
33954
|
+
strategyName,
|
|
33955
|
+
projectRoot: replayProjectRoot
|
|
33956
|
+
});
|
|
33957
|
+
if (installed.strategyPackage !== strategyPackage || installed.strategyPackageVersion !== strategyPackageVersion || installed.runtimePackageVersion !== runtimePackageVersion) {
|
|
33958
|
+
throw new Error(
|
|
33959
|
+
`Runtime evidence package mismatch for ${strategyName}: expected=${strategyPackage}@${strategyPackageVersion}/@tradejs/node@${runtimePackageVersion}, installed=${installed.strategyPackage ?? "missing"}@${installed.strategyPackageVersion ?? "missing"}/@tradejs/node@${installed.runtimePackageVersion ?? "missing"}`
|
|
33960
|
+
);
|
|
33961
|
+
}
|
|
33426
33962
|
const strategyResults = await (0, import_redis19.getData)(
|
|
33427
33963
|
import_redis19.redisKeys.strategyResults(replayUserName, strategyName),
|
|
33428
33964
|
{}
|
|
33429
33965
|
);
|
|
33430
33966
|
return {
|
|
33431
33967
|
strategyName,
|
|
33968
|
+
version,
|
|
33969
|
+
strategyPackage,
|
|
33970
|
+
strategyPackageVersion,
|
|
33971
|
+
runtimePackageVersion,
|
|
33432
33972
|
strategyCreator,
|
|
33433
33973
|
strategyConfig,
|
|
33434
33974
|
strategyResults
|
|
@@ -33622,6 +34162,9 @@ var init_historicalSignalsReplay = __esm({
|
|
|
33622
34162
|
loadedStrategies.map(
|
|
33623
34163
|
async ({
|
|
33624
34164
|
strategyName,
|
|
34165
|
+
version,
|
|
34166
|
+
strategyPackageVersion,
|
|
34167
|
+
runtimePackageVersion,
|
|
33625
34168
|
strategyCreator,
|
|
33626
34169
|
strategyConfig,
|
|
33627
34170
|
strategyResults
|
|
@@ -33629,8 +34172,11 @@ var init_historicalSignalsReplay = __esm({
|
|
|
33629
34172
|
const runtimeLineage = await buildRuntimeLineage({
|
|
33630
34173
|
projectRoot: replayProjectRoot,
|
|
33631
34174
|
strategyName,
|
|
34175
|
+
version,
|
|
34176
|
+
strategyPackageVersion,
|
|
34177
|
+
runtimePackageVersion,
|
|
33632
34178
|
config: {
|
|
33633
|
-
configId:
|
|
34179
|
+
configId: `v${version}`,
|
|
33634
34180
|
strategyConfig,
|
|
33635
34181
|
symbolResultConfig: strategyResults?.[symbol]?.config ?? null
|
|
33636
34182
|
},
|
|
@@ -33643,6 +34189,8 @@ var init_historicalSignalsReplay = __esm({
|
|
|
33643
34189
|
runtimeLineages.push({
|
|
33644
34190
|
strategy: strategyName,
|
|
33645
34191
|
symbol,
|
|
34192
|
+
...preparedRun.deploymentId ? { deploymentId: preparedRun.deploymentId } : {},
|
|
34193
|
+
...preparedRun.accountId ? { accountId: preparedRun.accountId } : {},
|
|
33646
34194
|
lineage: runtimeLineage
|
|
33647
34195
|
});
|
|
33648
34196
|
return {
|
|
@@ -33652,8 +34200,11 @@ var init_historicalSignalsReplay = __esm({
|
|
|
33652
34200
|
run: await strategyCreator({
|
|
33653
34201
|
userName: replayUserName,
|
|
33654
34202
|
connectorName,
|
|
33655
|
-
runtimeConfigId:
|
|
34203
|
+
runtimeConfigId: `v${version}`,
|
|
33656
34204
|
runtimeLineage,
|
|
34205
|
+
universe: preparedRun.universe,
|
|
34206
|
+
accountId: preparedRun.accountId,
|
|
34207
|
+
deploymentId: preparedRun.deploymentId,
|
|
33657
34208
|
config: buildReplayStrategyConfig({
|
|
33658
34209
|
strategyConfig,
|
|
33659
34210
|
interval: interval4
|
|
@@ -35006,125 +35557,6 @@ var init_runtimeParityDetails = __esm({
|
|
|
35006
35557
|
}
|
|
35007
35558
|
});
|
|
35008
35559
|
|
|
35009
|
-
// src/lib/replay/runtimeEvidenceSource.ts
|
|
35010
|
-
var import_promises29, import_node_path24, asRecord7, asFiniteNumber, unwrapRows2, buildRuntimeEvidenceLineageScopes, loadReplayRuntimeEvidenceSource;
|
|
35011
|
-
var init_runtimeEvidenceSource = __esm({
|
|
35012
|
-
"src/lib/replay/runtimeEvidenceSource.ts"() {
|
|
35013
|
-
"use strict";
|
|
35014
|
-
import_promises29 = __toESM(require("fs/promises"));
|
|
35015
|
-
import_node_path24 = __toESM(require("path"));
|
|
35016
|
-
init_runtimeLineage();
|
|
35017
|
-
asRecord7 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
35018
|
-
asFiniteNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
35019
|
-
unwrapRows2 = (value, field) => (Array.isArray(value) ? value : []).map((item) => {
|
|
35020
|
-
const row = asRecord7(item);
|
|
35021
|
-
return asRecord7(row?.[field]) ?? row;
|
|
35022
|
-
}).filter((item) => item != null);
|
|
35023
|
-
buildRuntimeEvidenceLineageScopes = ({
|
|
35024
|
-
signals: signals2,
|
|
35025
|
-
evaluations
|
|
35026
|
-
}) => {
|
|
35027
|
-
const scopes = /* @__PURE__ */ new Map();
|
|
35028
|
-
const add = ({
|
|
35029
|
-
strategy,
|
|
35030
|
-
symbol,
|
|
35031
|
-
runtimeConfigId,
|
|
35032
|
-
runtimeVersion,
|
|
35033
|
-
timestamp,
|
|
35034
|
-
lineage
|
|
35035
|
-
}) => {
|
|
35036
|
-
if (!lineage || !Number.isFinite(timestamp)) {
|
|
35037
|
-
return;
|
|
35038
|
-
}
|
|
35039
|
-
const key = `${strategy}::${symbol}::${runtimeLineageKey(lineage)}`;
|
|
35040
|
-
const existing = scopes.get(key);
|
|
35041
|
-
scopes.set(key, {
|
|
35042
|
-
strategy,
|
|
35043
|
-
symbol,
|
|
35044
|
-
...runtimeConfigId ? { runtimeConfigId } : {},
|
|
35045
|
-
...runtimeVersion ? { runtimeVersion } : {},
|
|
35046
|
-
lineage,
|
|
35047
|
-
firstTimestamp: existing ? Math.min(existing.firstTimestamp, timestamp) : timestamp,
|
|
35048
|
-
lastTimestamp: existing ? Math.max(existing.lastTimestamp, timestamp) : timestamp
|
|
35049
|
-
});
|
|
35050
|
-
};
|
|
35051
|
-
for (const signal of signals2) {
|
|
35052
|
-
add({
|
|
35053
|
-
strategy: signal.strategy,
|
|
35054
|
-
symbol: signal.symbol,
|
|
35055
|
-
runtimeConfigId: signal.runtimeConfigId,
|
|
35056
|
-
runtimeVersion: signal.runtimeVersion,
|
|
35057
|
-
timestamp: signal.timestamp,
|
|
35058
|
-
lineage: signal.runtimeLineage
|
|
35059
|
-
});
|
|
35060
|
-
}
|
|
35061
|
-
for (const evaluation of evaluations) {
|
|
35062
|
-
add({
|
|
35063
|
-
strategy: evaluation.strategy,
|
|
35064
|
-
symbol: evaluation.symbol,
|
|
35065
|
-
runtimeConfigId: evaluation.runtimeConfigId,
|
|
35066
|
-
runtimeVersion: evaluation.runtimeVersion,
|
|
35067
|
-
timestamp: evaluation.timestamp,
|
|
35068
|
-
lineage: evaluation.runtimeLineage
|
|
35069
|
-
});
|
|
35070
|
-
}
|
|
35071
|
-
return [...scopes.values()].sort(
|
|
35072
|
-
(left, right) => left.strategy.localeCompare(right.strategy) || left.symbol.localeCompare(right.symbol) || left.firstTimestamp - right.firstTimestamp
|
|
35073
|
-
);
|
|
35074
|
-
};
|
|
35075
|
-
loadReplayRuntimeEvidenceSource = async ({
|
|
35076
|
-
filePath,
|
|
35077
|
-
projectRoot: projectRoot15,
|
|
35078
|
-
expectedUserName,
|
|
35079
|
-
expectedWindow
|
|
35080
|
-
}) => {
|
|
35081
|
-
const resolvedPath = import_node_path24.default.resolve(projectRoot15, filePath);
|
|
35082
|
-
const root = asRecord7(
|
|
35083
|
-
JSON.parse(await import_promises29.default.readFile(resolvedPath, "utf8"))
|
|
35084
|
-
);
|
|
35085
|
-
const runtime = asRecord7(root?.runtime) ?? root;
|
|
35086
|
-
if (!root || !runtime) {
|
|
35087
|
-
throw new Error(`Invalid runtime evidence JSON: ${resolvedPath}`);
|
|
35088
|
-
}
|
|
35089
|
-
const rootWindow = asRecord7(root.window);
|
|
35090
|
-
const runtimeWindow2 = asRecord7(runtime.window);
|
|
35091
|
-
const startTime = asFiniteNumber(rootWindow?.startTime) ?? asFiniteNumber(runtimeWindow2?.startTime);
|
|
35092
|
-
const endTime = asFiniteNumber(rootWindow?.endTime) ?? asFiniteNumber(runtimeWindow2?.endTime);
|
|
35093
|
-
const userName3 = String(root.userName ?? runtime.userName ?? "").trim();
|
|
35094
|
-
if (!userName3 || userName3 !== expectedUserName) {
|
|
35095
|
-
throw new Error(
|
|
35096
|
-
`Runtime evidence user mismatch: expected=${expectedUserName}, actual=${userName3 || "missing"}`
|
|
35097
|
-
);
|
|
35098
|
-
}
|
|
35099
|
-
const endTimeMatches = endTime === expectedWindow.end || endTime === expectedWindow.end + 1;
|
|
35100
|
-
if (startTime !== expectedWindow.start || !endTimeMatches) {
|
|
35101
|
-
throw new Error(
|
|
35102
|
-
`Runtime evidence window mismatch: expected=${expectedWindow.start}..${expectedWindow.end}, actual=${startTime ?? "missing"}..${endTime ?? "missing"}`
|
|
35103
|
-
);
|
|
35104
|
-
}
|
|
35105
|
-
const trades = unwrapRows2(runtime.trades, "trade");
|
|
35106
|
-
const signals2 = unwrapRows2(runtime.signals, "signal");
|
|
35107
|
-
const evaluations = unwrapRows2(
|
|
35108
|
-
runtime.evaluations,
|
|
35109
|
-
"evaluation"
|
|
35110
|
-
);
|
|
35111
|
-
return {
|
|
35112
|
-
path: resolvedPath,
|
|
35113
|
-
userName: userName3,
|
|
35114
|
-
startTime,
|
|
35115
|
-
endTime,
|
|
35116
|
-
trades,
|
|
35117
|
-
signals: signals2,
|
|
35118
|
-
evaluations,
|
|
35119
|
-
lineageScopes: buildRuntimeEvidenceLineageScopes({
|
|
35120
|
-
signals: signals2,
|
|
35121
|
-
evaluations
|
|
35122
|
-
})
|
|
35123
|
-
};
|
|
35124
|
-
};
|
|
35125
|
-
}
|
|
35126
|
-
});
|
|
35127
|
-
|
|
35128
35560
|
// src/lib/replay/runtimeComparison.ts
|
|
35129
35561
|
var import_chalk48, import_time11, getReplayEntryTimestampCompareOffsetMs, buildReplaySignalEvaluations, lineageScopeKey, buildExpectedLineageByScope, hasExpectedLineage, filterReplayComparisonByLineage, formatDrilldownSummary, toFiniteNumberOrNull4, sumOptionalNumbers, firstFiniteNumber, firstString, summarizeBacktestPnlByStrategy, getExchangeExecutionMergeKey, mergeExchangeExecutionGroup, mergeExchangeEntryExecutions, loadExchangeEntryRows, buildPriceDeltaPct3, loadExchangeEntriesForComparison, compareExchangeEntriesToBacktest, findExchangeRuntimeOutcome, splitExchangeMatchesByRuntimeOrderStatus, saveAndPrintReplayExchangeComparison, saveAndPrintReplayRuntimeComparison;
|
|
35130
35562
|
var init_runtimeComparison = __esm({
|
|
@@ -35160,27 +35592,40 @@ var init_runtimeComparison = __esm({
|
|
|
35160
35592
|
reason: signal.orderSkipReason || signal.orderStatus || "SIGNAL",
|
|
35161
35593
|
signalId: signal.signalId,
|
|
35162
35594
|
direction: signal.direction,
|
|
35595
|
+
accountId: signal.accountId,
|
|
35596
|
+
deploymentId: signal.deploymentId,
|
|
35163
35597
|
runtimeLineage: signal.runtimeLineage,
|
|
35164
35598
|
orderStatus: signal.orderStatus,
|
|
35165
35599
|
orderSkipReason: signal.orderSkipReason,
|
|
35166
35600
|
...signal.aiAnalysis ? { aiAnalysis: signal.aiAnalysis } : {},
|
|
35167
35601
|
...signal.ml ? { ml: signal.ml } : {}
|
|
35168
35602
|
}));
|
|
35169
|
-
lineageScopeKey = (
|
|
35603
|
+
lineageScopeKey = ({
|
|
35604
|
+
strategy,
|
|
35605
|
+
symbol,
|
|
35606
|
+
deploymentId,
|
|
35607
|
+
accountId
|
|
35608
|
+
}) => `${deploymentId ?? "default-deployment"}::${accountId ?? "default-account"}::${strategy}::${symbol}`;
|
|
35170
35609
|
buildExpectedLineageByScope = (replayLineages) => new Map(
|
|
35171
|
-
replayLineages.map((record) => [
|
|
35172
|
-
lineageScopeKey(record.strategy, record.symbol),
|
|
35173
|
-
record.lineage
|
|
35174
|
-
])
|
|
35610
|
+
replayLineages.map((record) => [lineageScopeKey(record), record.lineage])
|
|
35175
35611
|
);
|
|
35176
35612
|
hasExpectedLineage = ({
|
|
35177
35613
|
strategy,
|
|
35178
35614
|
symbol,
|
|
35615
|
+
deploymentId,
|
|
35616
|
+
accountId,
|
|
35179
35617
|
lineage,
|
|
35180
35618
|
expectedByScope
|
|
35181
|
-
}) =>
|
|
35619
|
+
}) => runtimeLineagesComparable(
|
|
35182
35620
|
lineage,
|
|
35183
|
-
expectedByScope.get(
|
|
35621
|
+
expectedByScope.get(
|
|
35622
|
+
lineageScopeKey({
|
|
35623
|
+
strategy,
|
|
35624
|
+
symbol,
|
|
35625
|
+
deploymentId,
|
|
35626
|
+
accountId
|
|
35627
|
+
})
|
|
35628
|
+
)
|
|
35184
35629
|
);
|
|
35185
35630
|
filterReplayComparisonByLineage = ({
|
|
35186
35631
|
replayLineages,
|
|
@@ -35195,6 +35640,8 @@ var init_runtimeComparison = __esm({
|
|
|
35195
35640
|
(signal) => hasExpectedLineage({
|
|
35196
35641
|
strategy: signal.strategy,
|
|
35197
35642
|
symbol: signal.symbol,
|
|
35643
|
+
deploymentId: signal.deploymentId,
|
|
35644
|
+
accountId: signal.accountId,
|
|
35198
35645
|
lineage: signal.runtimeLineage,
|
|
35199
35646
|
expectedByScope
|
|
35200
35647
|
})
|
|
@@ -35203,6 +35650,8 @@ var init_runtimeComparison = __esm({
|
|
|
35203
35650
|
(evaluation) => hasExpectedLineage({
|
|
35204
35651
|
strategy: evaluation.strategy,
|
|
35205
35652
|
symbol: evaluation.symbol,
|
|
35653
|
+
deploymentId: evaluation.deploymentId,
|
|
35654
|
+
accountId: evaluation.accountId,
|
|
35206
35655
|
lineage: evaluation.runtimeLineage,
|
|
35207
35656
|
expectedByScope
|
|
35208
35657
|
})
|
|
@@ -35211,13 +35660,15 @@ var init_runtimeComparison = __esm({
|
|
|
35211
35660
|
(scope) => hasExpectedLineage({
|
|
35212
35661
|
strategy: scope.strategy,
|
|
35213
35662
|
symbol: scope.symbol,
|
|
35663
|
+
deploymentId: scope.deploymentId,
|
|
35664
|
+
accountId: scope.accountId,
|
|
35214
35665
|
lineage: scope.lineage,
|
|
35215
35666
|
expectedByScope
|
|
35216
35667
|
})
|
|
35217
35668
|
);
|
|
35218
35669
|
const deploymentWindows = /* @__PURE__ */ new Map();
|
|
35219
35670
|
for (const scope of comparableRuntimeLineageScopes) {
|
|
35220
|
-
const key = lineageScopeKey(scope
|
|
35671
|
+
const key = lineageScopeKey(scope);
|
|
35221
35672
|
const existing = deploymentWindows.get(key);
|
|
35222
35673
|
deploymentWindows.set(key, {
|
|
35223
35674
|
firstTimestamp: existing == null ? scope.firstTimestamp : Math.min(existing.firstTimestamp, scope.firstTimestamp),
|
|
@@ -35241,13 +35692,13 @@ var init_runtimeComparison = __esm({
|
|
|
35241
35692
|
return hasExpectedLineage({
|
|
35242
35693
|
strategy: trade.strategy,
|
|
35243
35694
|
symbol: trade.symbol,
|
|
35695
|
+
deploymentId: trade.deploymentId,
|
|
35696
|
+
accountId: trade.accountId,
|
|
35244
35697
|
lineage,
|
|
35245
35698
|
expectedByScope
|
|
35246
35699
|
});
|
|
35247
35700
|
}
|
|
35248
|
-
const window = deploymentWindows.get(
|
|
35249
|
-
lineageScopeKey(trade.strategy, trade.symbol)
|
|
35250
|
-
);
|
|
35701
|
+
const window = deploymentWindows.get(lineageScopeKey(trade));
|
|
35251
35702
|
const signalTimestamp = trade.signalTimestamp ?? trade.entryTimestamp;
|
|
35252
35703
|
return window != null && signalTimestamp >= window.firstTimestamp && signalTimestamp <= window.lastTimestamp;
|
|
35253
35704
|
});
|
|
@@ -35255,17 +35706,24 @@ var init_runtimeComparison = __esm({
|
|
|
35255
35706
|
...comparableRuntimeSignals,
|
|
35256
35707
|
...comparableRuntimeEvaluations
|
|
35257
35708
|
]) {
|
|
35258
|
-
const key = lineageScopeKey(artifact
|
|
35709
|
+
const key = lineageScopeKey(artifact);
|
|
35259
35710
|
const existing = deploymentWindows.get(key);
|
|
35260
35711
|
deploymentWindows.set(key, {
|
|
35261
35712
|
firstTimestamp: existing == null ? artifact.timestamp : Math.min(existing.firstTimestamp, artifact.timestamp),
|
|
35262
35713
|
lastTimestamp: existing == null ? artifact.timestamp : Math.max(existing.lastTimestamp, artifact.timestamp)
|
|
35263
35714
|
});
|
|
35264
35715
|
}
|
|
35716
|
+
const replayScopeByStrategySymbol = new Map(
|
|
35717
|
+
replayLineages.map((record) => [
|
|
35718
|
+
`${record.strategy}::${record.symbol}`,
|
|
35719
|
+
lineageScopeKey(record)
|
|
35720
|
+
])
|
|
35721
|
+
);
|
|
35265
35722
|
const comparableBacktestEntries = backtestEntries.filter((entry) => {
|
|
35266
|
-
const
|
|
35267
|
-
|
|
35723
|
+
const replayScope = replayScopeByStrategySymbol.get(
|
|
35724
|
+
`${entry.strategy}::${entry.symbol}`
|
|
35268
35725
|
);
|
|
35726
|
+
const window = replayScope ? deploymentWindows.get(replayScope) : null;
|
|
35269
35727
|
const signalTimestamp = entry.signalTimestamp ?? entry.timestamp;
|
|
35270
35728
|
return window != null && signalTimestamp >= window.firstTimestamp && signalTimestamp <= window.lastTimestamp;
|
|
35271
35729
|
});
|
|
@@ -35287,10 +35745,12 @@ var init_runtimeComparison = __esm({
|
|
|
35287
35745
|
excludedBacktestEntries: backtestEntries.length - comparableBacktestEntries.length,
|
|
35288
35746
|
reason: comparableScopeKeys.size > 0 ? null : "no_runtime_artifacts_with_matching_lineage",
|
|
35289
35747
|
replay: [...expectedByScope.entries()].map(([scope, lineage]) => {
|
|
35290
|
-
const
|
|
35748
|
+
const [deploymentId, accountId, strategy, symbol] = scope.split("::");
|
|
35291
35749
|
return {
|
|
35292
|
-
|
|
35293
|
-
|
|
35750
|
+
deploymentId,
|
|
35751
|
+
accountId,
|
|
35752
|
+
strategy,
|
|
35753
|
+
symbol,
|
|
35294
35754
|
lineage
|
|
35295
35755
|
};
|
|
35296
35756
|
}).sort(
|
|
@@ -36602,6 +37062,8 @@ var init_replayRunner = __esm({
|
|
|
36602
37062
|
init_marketContextPrepare();
|
|
36603
37063
|
init_runState();
|
|
36604
37064
|
init_cliConfig2();
|
|
37065
|
+
init_runtimeEvidenceSource();
|
|
37066
|
+
init_runtimeEvidenceDeployment();
|
|
36605
37067
|
init_support();
|
|
36606
37068
|
init_historicalSignalsReplay();
|
|
36607
37069
|
init_chartSnapshot();
|
|
@@ -36725,10 +37187,69 @@ var init_replayRunner = __esm({
|
|
|
36725
37187
|
};
|
|
36726
37188
|
replayBacktest = async () => {
|
|
36727
37189
|
resetRunState();
|
|
37190
|
+
const evidenceMetadata = replayRuntimeEvidencePath ? await loadReplayRuntimeEvidenceMetadata({
|
|
37191
|
+
filePath: replayRuntimeEvidencePath,
|
|
37192
|
+
projectRoot: replayProjectRoot
|
|
37193
|
+
}) : null;
|
|
37194
|
+
if (evidenceMetadata && evidenceMetadata.userName !== replayUserName) {
|
|
37195
|
+
throw new Error(
|
|
37196
|
+
`Runtime evidence user mismatch: expected=${replayUserName}, actual=${evidenceMetadata.userName || "missing"}`
|
|
37197
|
+
);
|
|
37198
|
+
}
|
|
37199
|
+
const replayComposition = evidenceMetadata ? {
|
|
37200
|
+
deployment: runtimeDeploymentFromEvidence(evidenceMetadata.deployment),
|
|
37201
|
+
strategies: activeRuntimeEvidenceStrategies(
|
|
37202
|
+
evidenceMetadata.deployment
|
|
37203
|
+
).map(
|
|
37204
|
+
({
|
|
37205
|
+
strategyName,
|
|
37206
|
+
version,
|
|
37207
|
+
strategyPackage,
|
|
37208
|
+
strategyPackageVersion,
|
|
37209
|
+
runtimePackageVersion,
|
|
37210
|
+
strategyConfig
|
|
37211
|
+
}) => ({
|
|
37212
|
+
strategyName,
|
|
37213
|
+
version,
|
|
37214
|
+
strategyPackage,
|
|
37215
|
+
strategyPackageVersion,
|
|
37216
|
+
runtimePackageVersion,
|
|
37217
|
+
strategyConfig
|
|
37218
|
+
})
|
|
37219
|
+
)
|
|
37220
|
+
} : await loadDeploymentReplayStrategies({
|
|
37221
|
+
userName: replayUserName,
|
|
37222
|
+
projectRoot: replayProjectRoot,
|
|
37223
|
+
deploymentId: replayDeploymentId
|
|
37224
|
+
});
|
|
37225
|
+
const { deployment, strategies: replayStrategies } = replayComposition;
|
|
37226
|
+
if (!replayStrategies.length) {
|
|
37227
|
+
throw new Error(`No enabled strategies in deployment ${deployment.id}`);
|
|
37228
|
+
}
|
|
37229
|
+
const strategyIntervals = new Set(
|
|
37230
|
+
replayStrategies.map(
|
|
37231
|
+
({ strategyConfig }) => String(strategyConfig.INTERVAL)
|
|
37232
|
+
)
|
|
37233
|
+
);
|
|
37234
|
+
if (strategyIntervals.size !== 1 || !strategyIntervals.has(replayInterval)) {
|
|
37235
|
+
throw new Error(
|
|
37236
|
+
`Replay interval does not match deployment ${deployment.id}: replay=${replayInterval}, strategies=${[...strategyIntervals].join(",")}`
|
|
37237
|
+
);
|
|
37238
|
+
}
|
|
37239
|
+
const strategyUniverses = new Set(
|
|
37240
|
+
replayStrategies.map(
|
|
37241
|
+
({ strategyConfig }) => String(strategyConfig.UNIVERSE)
|
|
37242
|
+
)
|
|
37243
|
+
);
|
|
37244
|
+
if (strategyUniverses.size !== 1) {
|
|
37245
|
+
throw new Error(
|
|
37246
|
+
`Replay requires one deployment universe: ${[...strategyUniverses].join(",")}`
|
|
37247
|
+
);
|
|
37248
|
+
}
|
|
36728
37249
|
const preparedRun = await prepareRunEnvironment({
|
|
36729
|
-
connector:
|
|
37250
|
+
connector: deployment.connectorName,
|
|
36730
37251
|
userName: replayUserName,
|
|
36731
|
-
tickers: replayFlags.tickers,
|
|
37252
|
+
tickers: replayFlags.tickers ?? deployment.tickers,
|
|
36732
37253
|
exclude: replayFlags.exclude,
|
|
36733
37254
|
tickersLimit: replayFlags.tickersLimit,
|
|
36734
37255
|
showTickersList: replayFlags.showTickersList,
|
|
@@ -36738,6 +37259,11 @@ var init_replayRunner = __esm({
|
|
|
36738
37259
|
cacheOnly: replayFlags.cacheOnly,
|
|
36739
37260
|
interval: replayInterval,
|
|
36740
37261
|
projectRoot: replayProjectRoot,
|
|
37262
|
+
universe: [...strategyUniverses][0],
|
|
37263
|
+
accountId: deployment.accountId,
|
|
37264
|
+
deploymentId: deployment.id,
|
|
37265
|
+
assetClasses: deployment.assetClasses,
|
|
37266
|
+
deployment,
|
|
36741
37267
|
closedIntervalMs: (0, import_data5.intervalToMs)(replayInterval)
|
|
36742
37268
|
});
|
|
36743
37269
|
if (!preparedRun || isReplayUpdateOnlyRun) {
|
|
@@ -36751,10 +37277,6 @@ var init_replayRunner = __esm({
|
|
|
36751
37277
|
end: preparedRun.window.end
|
|
36752
37278
|
}
|
|
36753
37279
|
});
|
|
36754
|
-
const replayStrategies = await loadReplayStrategies(replayUserName);
|
|
36755
|
-
if (!replayStrategies.length) {
|
|
36756
|
-
return;
|
|
36757
|
-
}
|
|
36758
37280
|
await prepareReplayBinanceMarketContext({
|
|
36759
37281
|
...preparedRun,
|
|
36760
37282
|
aiEnabled: replayStrategies.some(
|
|
@@ -36812,7 +37334,7 @@ __export(signalsSummary_exports, {
|
|
|
36812
37334
|
main: () => main44,
|
|
36813
37335
|
signalsSummary: () => signalsSummary
|
|
36814
37336
|
});
|
|
36815
|
-
var import_config13, import_args33, import_logger12, import_connectors18,
|
|
37337
|
+
var import_config13, import_args33, import_logger12, import_connectors18, import_runtimeStrategies9, flags30, projectRoot14, SUMMARY_TIMEZONE2, SUMMARY_TIMEZONE_LABEL2, escapeHtml6, formatMskDateTime3, formatSigned3, formatPnlMoneyText, formatWinRateText, resolveSummaryTitle, normalizeStatus, shouldAttachDebugReport, getSummaryDateParts, formatSummaryIsoDayKey, unescapeHtml, stripTelegramHtml, buildSignalsSummaryAttachment, appendReportAttachmentSummary, resolveSummaryConnectorName, groupRuntimeTradesByConnectorScope, syncRuntimeTradeScopes, createRuntimeSignalStats, mergeRuntimeSignalStats, buildSummaryPrelude, resolveTradeStatusEmoji, isTimestampInWindow, isRuntimeTradeClosedInWindow, buildSummaryMessages, signalsSummary, main44;
|
|
36816
37338
|
var init_signalsSummary = __esm({
|
|
36817
37339
|
"src/scripts/signalsSummary.ts"() {
|
|
36818
37340
|
"use strict";
|
|
@@ -36826,7 +37348,7 @@ var init_signalsSummary = __esm({
|
|
|
36826
37348
|
init_runtimeSignalsLoader();
|
|
36827
37349
|
init_runtimeSignalsStorage();
|
|
36828
37350
|
init_runtimeDebugEvidence();
|
|
36829
|
-
|
|
37351
|
+
import_runtimeStrategies9 = require("@tradejs/node/runtimeStrategies");
|
|
36830
37352
|
import_args33.default.option(["u", "user"], "Use user config", "root");
|
|
36831
37353
|
import_args33.default.option(
|
|
36832
37354
|
"connector",
|
|
@@ -37364,7 +37886,7 @@ none`
|
|
|
37364
37886
|
loadRuntimeSignals(flags30.user, { startTime, endTime }),
|
|
37365
37887
|
loadRuntimeSignalEvaluationStatsBuckets(flags30.user),
|
|
37366
37888
|
loadRuntimeTrades(flags30.user),
|
|
37367
|
-
(0,
|
|
37889
|
+
(0, import_runtimeStrategies9.listRuntimeDeployments)({ userName: flags30.user, projectRoot: projectRoot14 })
|
|
37368
37890
|
]);
|
|
37369
37891
|
const {
|
|
37370
37892
|
trades: syncedTrades,
|