@tradejs/cli 3.1.29-beta.292 → 3.1.29-beta.297
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 +968 -680
- package/dist/lib/binanceMarketContextBackfill.js +2 -2
- package/dist/lib/coinMarketCapContextBackfill.js +22 -6
- package/dist/lib/derivativesContextBackfill.js +14 -0
- package/dist/lib/marketContextPrepare.js +24 -8
- package/dist/lib/strategyResearch.js +33 -79
- package/dist/scripts/backtest.js +213 -74
- package/dist/scripts/binanceMarketIngest.js +3 -3
- package/dist/scripts/coverageBackfill.js +1731 -0
- package/dist/scripts/replay.js +24 -8
- package/dist/scripts/replayRunner.js +24 -8
- package/dist/scripts/replayRuntimeEvidence.js +4 -1
- package/dist/scripts/runtimeParity.js +24 -8
- package/dist/scripts/signals.js +24 -8
- package/dist/scripts/signalsDaemon.js +24 -8
- package/dist/scripts/strategyRelease.js +6 -37
- package/dist/scripts/strategyResearch.js +36 -82
- package/package.json +7 -7
- package/dist/lib/researchMetricSnapshot.js +0 -74
package/dist/scripts/replay.js
CHANGED
|
@@ -1515,13 +1515,12 @@ var getReferenceSymbols = () => {
|
|
|
1515
1515
|
};
|
|
1516
1516
|
var intervalToMarketFeatureInterval = (interval) => {
|
|
1517
1517
|
const normalized = String(interval).trim().toLowerCase();
|
|
1518
|
-
if (normalized === "1" || normalized === "1m") return
|
|
1518
|
+
if (normalized === "1" || normalized === "1m") return null;
|
|
1519
1519
|
if (normalized === "5" || normalized === "5m") return "5m";
|
|
1520
1520
|
if (normalized === "60" || normalized === "1h") return "1h";
|
|
1521
1521
|
return "15m";
|
|
1522
1522
|
};
|
|
1523
1523
|
var marketIntervalToConnectorInterval = (interval) => {
|
|
1524
|
-
if (interval === "1m") return "1";
|
|
1525
1524
|
if (interval === "5m") return "5";
|
|
1526
1525
|
if (interval === "1h") return "60";
|
|
1527
1526
|
return "15";
|
|
@@ -1686,6 +1685,7 @@ var backfillBinanceMarketContext = async (params, enabled) => {
|
|
|
1686
1685
|
return skippedBackfillResult();
|
|
1687
1686
|
}
|
|
1688
1687
|
const interval = intervalToMarketFeatureInterval(params.interval);
|
|
1688
|
+
if (interval === null) return skippedBackfillResult();
|
|
1689
1689
|
const intervalMs = MARKET_FEATURE_INTERVAL_MS[interval];
|
|
1690
1690
|
const { breadthStartMs, tradeFlowStartMs, endMs } = resolveBinanceMarketContextBackfillWindow(params);
|
|
1691
1691
|
if (endMs <= Math.min(breadthStartMs, tradeFlowStartMs)) {
|
|
@@ -3266,7 +3266,7 @@ var coinMarketCapFetch = async (params) => {
|
|
|
3266
3266
|
};
|
|
3267
3267
|
var fetchCoinMarketCapIndexRows = async (params) => {
|
|
3268
3268
|
const rows = [];
|
|
3269
|
-
const maxChunkDays =
|
|
3269
|
+
const maxChunkDays = 4;
|
|
3270
3270
|
const totalChunks = Math.max(
|
|
3271
3271
|
1,
|
|
3272
3272
|
Math.ceil(
|
|
@@ -3703,11 +3703,27 @@ var backfillCoinMarketCapContext = async (params) => {
|
|
|
3703
3703
|
toMs
|
|
3704
3704
|
})
|
|
3705
3705
|
);
|
|
3706
|
-
const
|
|
3707
|
-
const
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3706
|
+
const ready = (dataset, existing) => params.repairDataset ? params.repairDataset !== dataset : existing;
|
|
3707
|
+
const globalDailyReady = ready(
|
|
3708
|
+
"cmc-global-1d",
|
|
3709
|
+
globalDailyCached || globalDailyBackfillCovered
|
|
3710
|
+
);
|
|
3711
|
+
const referencesDailyReady = ready(
|
|
3712
|
+
"cmc-reference_asset-1d",
|
|
3713
|
+
referencesDailyCached || referencesDailyBackfillCovered
|
|
3714
|
+
);
|
|
3715
|
+
const exchangeLiquidityReady = ready(
|
|
3716
|
+
"cmc-exchange_liquidity-1d",
|
|
3717
|
+
exchangeLiquidityCached || !exchangeLiquidityEnabled || exchangeLiquidityBackfillCovered
|
|
3718
|
+
);
|
|
3719
|
+
const fearGreedReady = ready(
|
|
3720
|
+
"cmc-fear_greed-1d",
|
|
3721
|
+
fearGreedCached || !fearGreedEnabled || fearGreedBackfillCovered
|
|
3722
|
+
);
|
|
3723
|
+
const indexesReady = ready(
|
|
3724
|
+
"cmc-index-1d",
|
|
3725
|
+
indexesCached || indexesBackfillCovered
|
|
3726
|
+
);
|
|
3711
3727
|
let globalStatus = resolveBackfillStatus({
|
|
3712
3728
|
cached: globalDailyCached,
|
|
3713
3729
|
covered: globalDailyBackfillCovered
|
|
@@ -1520,13 +1520,12 @@ var getReferenceSymbols = () => {
|
|
|
1520
1520
|
};
|
|
1521
1521
|
var intervalToMarketFeatureInterval = (interval) => {
|
|
1522
1522
|
const normalized = String(interval).trim().toLowerCase();
|
|
1523
|
-
if (normalized === "1" || normalized === "1m") return
|
|
1523
|
+
if (normalized === "1" || normalized === "1m") return null;
|
|
1524
1524
|
if (normalized === "5" || normalized === "5m") return "5m";
|
|
1525
1525
|
if (normalized === "60" || normalized === "1h") return "1h";
|
|
1526
1526
|
return "15m";
|
|
1527
1527
|
};
|
|
1528
1528
|
var marketIntervalToConnectorInterval = (interval) => {
|
|
1529
|
-
if (interval === "1m") return "1";
|
|
1530
1529
|
if (interval === "5m") return "5";
|
|
1531
1530
|
if (interval === "1h") return "60";
|
|
1532
1531
|
return "15";
|
|
@@ -1691,6 +1690,7 @@ var backfillBinanceMarketContext = async (params, enabled) => {
|
|
|
1691
1690
|
return skippedBackfillResult();
|
|
1692
1691
|
}
|
|
1693
1692
|
const interval = intervalToMarketFeatureInterval(params.interval);
|
|
1693
|
+
if (interval === null) return skippedBackfillResult();
|
|
1694
1694
|
const intervalMs = MARKET_FEATURE_INTERVAL_MS[interval];
|
|
1695
1695
|
const { breadthStartMs, tradeFlowStartMs, endMs } = resolveBinanceMarketContextBackfillWindow(params);
|
|
1696
1696
|
if (endMs <= Math.min(breadthStartMs, tradeFlowStartMs)) {
|
|
@@ -3271,7 +3271,7 @@ var coinMarketCapFetch = async (params) => {
|
|
|
3271
3271
|
};
|
|
3272
3272
|
var fetchCoinMarketCapIndexRows = async (params) => {
|
|
3273
3273
|
const rows = [];
|
|
3274
|
-
const maxChunkDays =
|
|
3274
|
+
const maxChunkDays = 4;
|
|
3275
3275
|
const totalChunks = Math.max(
|
|
3276
3276
|
1,
|
|
3277
3277
|
Math.ceil(
|
|
@@ -3708,11 +3708,27 @@ var backfillCoinMarketCapContext = async (params) => {
|
|
|
3708
3708
|
toMs
|
|
3709
3709
|
})
|
|
3710
3710
|
);
|
|
3711
|
-
const
|
|
3712
|
-
const
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3711
|
+
const ready = (dataset, existing) => params.repairDataset ? params.repairDataset !== dataset : existing;
|
|
3712
|
+
const globalDailyReady = ready(
|
|
3713
|
+
"cmc-global-1d",
|
|
3714
|
+
globalDailyCached || globalDailyBackfillCovered
|
|
3715
|
+
);
|
|
3716
|
+
const referencesDailyReady = ready(
|
|
3717
|
+
"cmc-reference_asset-1d",
|
|
3718
|
+
referencesDailyCached || referencesDailyBackfillCovered
|
|
3719
|
+
);
|
|
3720
|
+
const exchangeLiquidityReady = ready(
|
|
3721
|
+
"cmc-exchange_liquidity-1d",
|
|
3722
|
+
exchangeLiquidityCached || !exchangeLiquidityEnabled || exchangeLiquidityBackfillCovered
|
|
3723
|
+
);
|
|
3724
|
+
const fearGreedReady = ready(
|
|
3725
|
+
"cmc-fear_greed-1d",
|
|
3726
|
+
fearGreedCached || !fearGreedEnabled || fearGreedBackfillCovered
|
|
3727
|
+
);
|
|
3728
|
+
const indexesReady = ready(
|
|
3729
|
+
"cmc-index-1d",
|
|
3730
|
+
indexesCached || indexesBackfillCovered
|
|
3731
|
+
);
|
|
3716
3732
|
let globalStatus = resolveBackfillStatus({
|
|
3717
3733
|
cached: globalDailyCached,
|
|
3718
3734
|
covered: globalDailyBackfillCovered
|
|
@@ -593,6 +593,8 @@ var compactMatched = (item) => {
|
|
|
593
593
|
timestampDiffMs: item.timestampDiffMs ?? null,
|
|
594
594
|
backtestPrice: backtest.price ?? null,
|
|
595
595
|
runtimePrice: runtime.price ?? null,
|
|
596
|
+
backtestQty: backtest.qty ?? null,
|
|
597
|
+
runtimeQty: runtime.qty ?? null,
|
|
596
598
|
backtestExitPrice: backtest.exitPrice ?? null,
|
|
597
599
|
runtimeExitPrice: runtime.exitPrice ?? null,
|
|
598
600
|
expectedPnl: pnl.expectedPnl ?? null,
|
|
@@ -603,7 +605,8 @@ var compactMatched = (item) => {
|
|
|
603
605
|
totalSlippageCost: slippage.totalCost ?? null,
|
|
604
606
|
orderId: runtime.orderId ?? backtest.orderId ?? null,
|
|
605
607
|
orderLinkId: runtime.orderLinkId ?? null,
|
|
606
|
-
signalId: backtest.signalId ?? null
|
|
608
|
+
signalId: backtest.signalId ?? null,
|
|
609
|
+
runtimeSignalId: runtime.signalId ?? null
|
|
607
610
|
};
|
|
608
611
|
};
|
|
609
612
|
var resolveItemStrategy = (item) => asRecord(item.backtest).strategy ?? asRecord(item.runtime).inferredStrategy ?? item.strategy ?? item.inferredStrategy ?? null;
|
|
@@ -1028,13 +1028,12 @@ var getReferenceSymbols = () => {
|
|
|
1028
1028
|
};
|
|
1029
1029
|
var intervalToMarketFeatureInterval = (interval2) => {
|
|
1030
1030
|
const normalized = String(interval2).trim().toLowerCase();
|
|
1031
|
-
if (normalized === "1" || normalized === "1m") return
|
|
1031
|
+
if (normalized === "1" || normalized === "1m") return null;
|
|
1032
1032
|
if (normalized === "5" || normalized === "5m") return "5m";
|
|
1033
1033
|
if (normalized === "60" || normalized === "1h") return "1h";
|
|
1034
1034
|
return "15m";
|
|
1035
1035
|
};
|
|
1036
1036
|
var marketIntervalToConnectorInterval = (interval2) => {
|
|
1037
|
-
if (interval2 === "1m") return "1";
|
|
1038
1037
|
if (interval2 === "5m") return "5";
|
|
1039
1038
|
if (interval2 === "1h") return "60";
|
|
1040
1039
|
return "15";
|
|
@@ -1199,6 +1198,7 @@ var backfillBinanceMarketContext = async (params, enabled) => {
|
|
|
1199
1198
|
return skippedBackfillResult();
|
|
1200
1199
|
}
|
|
1201
1200
|
const interval2 = intervalToMarketFeatureInterval(params.interval);
|
|
1201
|
+
if (interval2 === null) return skippedBackfillResult();
|
|
1202
1202
|
const intervalMs = MARKET_FEATURE_INTERVAL_MS[interval2];
|
|
1203
1203
|
const { breadthStartMs, tradeFlowStartMs, endMs } = resolveBinanceMarketContextBackfillWindow(params);
|
|
1204
1204
|
if (endMs <= Math.min(breadthStartMs, tradeFlowStartMs)) {
|
|
@@ -2779,7 +2779,7 @@ var coinMarketCapFetch = async (params) => {
|
|
|
2779
2779
|
};
|
|
2780
2780
|
var fetchCoinMarketCapIndexRows = async (params) => {
|
|
2781
2781
|
const rows = [];
|
|
2782
|
-
const maxChunkDays =
|
|
2782
|
+
const maxChunkDays = 4;
|
|
2783
2783
|
const totalChunks = Math.max(
|
|
2784
2784
|
1,
|
|
2785
2785
|
Math.ceil(
|
|
@@ -3216,11 +3216,27 @@ var backfillCoinMarketCapContext = async (params) => {
|
|
|
3216
3216
|
toMs
|
|
3217
3217
|
})
|
|
3218
3218
|
);
|
|
3219
|
-
const
|
|
3220
|
-
const
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3219
|
+
const ready = (dataset, existing) => params.repairDataset ? params.repairDataset !== dataset : existing;
|
|
3220
|
+
const globalDailyReady = ready(
|
|
3221
|
+
"cmc-global-1d",
|
|
3222
|
+
globalDailyCached || globalDailyBackfillCovered
|
|
3223
|
+
);
|
|
3224
|
+
const referencesDailyReady = ready(
|
|
3225
|
+
"cmc-reference_asset-1d",
|
|
3226
|
+
referencesDailyCached || referencesDailyBackfillCovered
|
|
3227
|
+
);
|
|
3228
|
+
const exchangeLiquidityReady = ready(
|
|
3229
|
+
"cmc-exchange_liquidity-1d",
|
|
3230
|
+
exchangeLiquidityCached || !exchangeLiquidityEnabled || exchangeLiquidityBackfillCovered
|
|
3231
|
+
);
|
|
3232
|
+
const fearGreedReady = ready(
|
|
3233
|
+
"cmc-fear_greed-1d",
|
|
3234
|
+
fearGreedCached || !fearGreedEnabled || fearGreedBackfillCovered
|
|
3235
|
+
);
|
|
3236
|
+
const indexesReady = ready(
|
|
3237
|
+
"cmc-index-1d",
|
|
3238
|
+
indexesCached || indexesBackfillCovered
|
|
3239
|
+
);
|
|
3224
3240
|
let globalStatus = resolveBackfillStatus({
|
|
3225
3241
|
cached: globalDailyCached,
|
|
3226
3242
|
covered: globalDailyBackfillCovered
|
package/dist/scripts/signals.js
CHANGED
|
@@ -488,13 +488,12 @@ var getReferenceSymbols = () => {
|
|
|
488
488
|
};
|
|
489
489
|
var intervalToMarketFeatureInterval = (interval) => {
|
|
490
490
|
const normalized = String(interval).trim().toLowerCase();
|
|
491
|
-
if (normalized === "1" || normalized === "1m") return
|
|
491
|
+
if (normalized === "1" || normalized === "1m") return null;
|
|
492
492
|
if (normalized === "5" || normalized === "5m") return "5m";
|
|
493
493
|
if (normalized === "60" || normalized === "1h") return "1h";
|
|
494
494
|
return "15m";
|
|
495
495
|
};
|
|
496
496
|
var marketIntervalToConnectorInterval = (interval) => {
|
|
497
|
-
if (interval === "1m") return "1";
|
|
498
497
|
if (interval === "5m") return "5";
|
|
499
498
|
if (interval === "1h") return "60";
|
|
500
499
|
return "15";
|
|
@@ -659,6 +658,7 @@ var backfillBinanceMarketContext = async (params, enabled) => {
|
|
|
659
658
|
return skippedBackfillResult();
|
|
660
659
|
}
|
|
661
660
|
const interval = intervalToMarketFeatureInterval(params.interval);
|
|
661
|
+
if (interval === null) return skippedBackfillResult();
|
|
662
662
|
const intervalMs = MARKET_FEATURE_INTERVAL_MS[interval];
|
|
663
663
|
const { breadthStartMs, tradeFlowStartMs, endMs } = resolveBinanceMarketContextBackfillWindow(params);
|
|
664
664
|
if (endMs <= Math.min(breadthStartMs, tradeFlowStartMs)) {
|
|
@@ -2239,7 +2239,7 @@ var coinMarketCapFetch = async (params) => {
|
|
|
2239
2239
|
};
|
|
2240
2240
|
var fetchCoinMarketCapIndexRows = async (params) => {
|
|
2241
2241
|
const rows = [];
|
|
2242
|
-
const maxChunkDays =
|
|
2242
|
+
const maxChunkDays = 4;
|
|
2243
2243
|
const totalChunks = Math.max(
|
|
2244
2244
|
1,
|
|
2245
2245
|
Math.ceil(
|
|
@@ -2676,11 +2676,27 @@ var backfillCoinMarketCapContext = async (params) => {
|
|
|
2676
2676
|
toMs
|
|
2677
2677
|
})
|
|
2678
2678
|
);
|
|
2679
|
-
const
|
|
2680
|
-
const
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2679
|
+
const ready = (dataset, existing) => params.repairDataset ? params.repairDataset !== dataset : existing;
|
|
2680
|
+
const globalDailyReady = ready(
|
|
2681
|
+
"cmc-global-1d",
|
|
2682
|
+
globalDailyCached || globalDailyBackfillCovered
|
|
2683
|
+
);
|
|
2684
|
+
const referencesDailyReady = ready(
|
|
2685
|
+
"cmc-reference_asset-1d",
|
|
2686
|
+
referencesDailyCached || referencesDailyBackfillCovered
|
|
2687
|
+
);
|
|
2688
|
+
const exchangeLiquidityReady = ready(
|
|
2689
|
+
"cmc-exchange_liquidity-1d",
|
|
2690
|
+
exchangeLiquidityCached || !exchangeLiquidityEnabled || exchangeLiquidityBackfillCovered
|
|
2691
|
+
);
|
|
2692
|
+
const fearGreedReady = ready(
|
|
2693
|
+
"cmc-fear_greed-1d",
|
|
2694
|
+
fearGreedCached || !fearGreedEnabled || fearGreedBackfillCovered
|
|
2695
|
+
);
|
|
2696
|
+
const indexesReady = ready(
|
|
2697
|
+
"cmc-index-1d",
|
|
2698
|
+
indexesCached || indexesBackfillCovered
|
|
2699
|
+
);
|
|
2684
2700
|
let globalStatus = resolveBackfillStatus({
|
|
2685
2701
|
cached: globalDailyCached,
|
|
2686
2702
|
covered: globalDailyBackfillCovered
|
|
@@ -486,13 +486,12 @@ var getReferenceSymbols = () => {
|
|
|
486
486
|
};
|
|
487
487
|
var intervalToMarketFeatureInterval = (interval) => {
|
|
488
488
|
const normalized = String(interval).trim().toLowerCase();
|
|
489
|
-
if (normalized === "1" || normalized === "1m") return
|
|
489
|
+
if (normalized === "1" || normalized === "1m") return null;
|
|
490
490
|
if (normalized === "5" || normalized === "5m") return "5m";
|
|
491
491
|
if (normalized === "60" || normalized === "1h") return "1h";
|
|
492
492
|
return "15m";
|
|
493
493
|
};
|
|
494
494
|
var marketIntervalToConnectorInterval = (interval) => {
|
|
495
|
-
if (interval === "1m") return "1";
|
|
496
495
|
if (interval === "5m") return "5";
|
|
497
496
|
if (interval === "1h") return "60";
|
|
498
497
|
return "15";
|
|
@@ -657,6 +656,7 @@ var backfillBinanceMarketContext = async (params, enabled) => {
|
|
|
657
656
|
return skippedBackfillResult();
|
|
658
657
|
}
|
|
659
658
|
const interval = intervalToMarketFeatureInterval(params.interval);
|
|
659
|
+
if (interval === null) return skippedBackfillResult();
|
|
660
660
|
const intervalMs = MARKET_FEATURE_INTERVAL_MS[interval];
|
|
661
661
|
const { breadthStartMs, tradeFlowStartMs, endMs } = resolveBinanceMarketContextBackfillWindow(params);
|
|
662
662
|
if (endMs <= Math.min(breadthStartMs, tradeFlowStartMs)) {
|
|
@@ -2237,7 +2237,7 @@ var coinMarketCapFetch = async (params) => {
|
|
|
2237
2237
|
};
|
|
2238
2238
|
var fetchCoinMarketCapIndexRows = async (params) => {
|
|
2239
2239
|
const rows = [];
|
|
2240
|
-
const maxChunkDays =
|
|
2240
|
+
const maxChunkDays = 4;
|
|
2241
2241
|
const totalChunks = Math.max(
|
|
2242
2242
|
1,
|
|
2243
2243
|
Math.ceil(
|
|
@@ -2674,11 +2674,27 @@ var backfillCoinMarketCapContext = async (params) => {
|
|
|
2674
2674
|
toMs
|
|
2675
2675
|
})
|
|
2676
2676
|
);
|
|
2677
|
-
const
|
|
2678
|
-
const
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2677
|
+
const ready = (dataset, existing) => params.repairDataset ? params.repairDataset !== dataset : existing;
|
|
2678
|
+
const globalDailyReady = ready(
|
|
2679
|
+
"cmc-global-1d",
|
|
2680
|
+
globalDailyCached || globalDailyBackfillCovered
|
|
2681
|
+
);
|
|
2682
|
+
const referencesDailyReady = ready(
|
|
2683
|
+
"cmc-reference_asset-1d",
|
|
2684
|
+
referencesDailyCached || referencesDailyBackfillCovered
|
|
2685
|
+
);
|
|
2686
|
+
const exchangeLiquidityReady = ready(
|
|
2687
|
+
"cmc-exchange_liquidity-1d",
|
|
2688
|
+
exchangeLiquidityCached || !exchangeLiquidityEnabled || exchangeLiquidityBackfillCovered
|
|
2689
|
+
);
|
|
2690
|
+
const fearGreedReady = ready(
|
|
2691
|
+
"cmc-fear_greed-1d",
|
|
2692
|
+
fearGreedCached || !fearGreedEnabled || fearGreedBackfillCovered
|
|
2693
|
+
);
|
|
2694
|
+
const indexesReady = ready(
|
|
2695
|
+
"cmc-index-1d",
|
|
2696
|
+
indexesCached || indexesBackfillCovered
|
|
2697
|
+
);
|
|
2682
2698
|
let globalStatus = resolveBackfillStatus({
|
|
2683
2699
|
cached: globalDailyCached,
|
|
2684
2700
|
covered: globalDailyBackfillCovered
|
|
@@ -42,40 +42,9 @@ var import_chalk = __toESM(require("chalk"));
|
|
|
42
42
|
|
|
43
43
|
// src/lib/strategyRelease/researchRetention.ts
|
|
44
44
|
var import_promises = __toESM(require("fs/promises"));
|
|
45
|
-
|
|
46
|
-
// src/lib/researchMetricSnapshot.ts
|
|
47
|
-
var import_node_crypto = require("crypto");
|
|
48
|
-
var import_node_zlib = require("zlib");
|
|
49
|
-
var MAX_BYTES = 256 * 1024 * 1024;
|
|
50
|
-
var hash = (bytes) => (0, import_node_crypto.createHash)("sha256").update(bytes).digest("hex");
|
|
51
|
-
var validatePermanentResearchMetrics = (value) => {
|
|
52
|
-
if (!value || typeof value !== "object") return;
|
|
53
|
-
for (const [key, child] of Object.entries(value)) {
|
|
54
|
-
if (["matchedPairs", "tradeRows", "allProjectedLeaves"].includes(key) && Array.isArray(child) && child.length)
|
|
55
|
-
throw new Error(`Temporary payload ${key} is not a permanent metric`);
|
|
56
|
-
if (key === "trades" && Array.isArray(child) && child.some(
|
|
57
|
-
(row) => row && typeof row === "object" && ("signalId" in row || "entryTimestamp" in row)
|
|
58
|
-
))
|
|
59
|
-
throw new Error("Temporary trade records are not permanent metrics");
|
|
60
|
-
validatePermanentResearchMetrics(child);
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
var decodeResearchMetricSnapshot = (snapshot) => {
|
|
64
|
-
if (!snapshot || typeof snapshot !== "object" || !("schema" in snapshot) || snapshot.schema !== "tradejs-metric-snapshot/v1" || !("encoding" in snapshot) || snapshot.encoding !== "gzip+base64" || !("decodedBytes" in snapshot) || typeof snapshot.decodedBytes !== "number" || !Number.isSafeInteger(snapshot.decodedBytes) || snapshot.decodedBytes <= 0 || snapshot.decodedBytes > MAX_BYTES || !("sha256" in snapshot) || typeof snapshot.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(snapshot.sha256) || !("payload" in snapshot) || typeof snapshot.payload !== "string")
|
|
65
|
-
throw new Error("Invalid metric snapshot envelope");
|
|
66
|
-
const bytes = (0, import_node_zlib.gunzipSync)(Buffer.from(snapshot.payload, "base64"), {
|
|
67
|
-
maxOutputLength: snapshot.decodedBytes
|
|
68
|
-
});
|
|
69
|
-
if (bytes.length !== snapshot.decodedBytes || hash(bytes) !== snapshot.sha256)
|
|
70
|
-
throw new Error("Metric snapshot checksum or size mismatch");
|
|
71
|
-
const metrics = JSON.parse(bytes.toString("utf8"));
|
|
72
|
-
validatePermanentResearchMetrics(metrics);
|
|
73
|
-
return metrics;
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
// src/lib/strategyRelease/researchRetention.ts
|
|
45
|
+
var import_researchMetricSnapshot = require("@tradejs/infra/researchMetricSnapshot");
|
|
77
46
|
var import_node_path2 = __toESM(require("path"));
|
|
78
|
-
var
|
|
47
|
+
var import_node_crypto = require("crypto");
|
|
79
48
|
var import_strategyReleaseEvidence = require("@tradejs/infra/strategyReleaseEvidence");
|
|
80
49
|
|
|
81
50
|
// src/lib/strategyRelease/researchFileConsumers.ts
|
|
@@ -267,7 +236,7 @@ var mapFiles = async (entries, visit) => {
|
|
|
267
236
|
if (worker.status === "rejected") throw worker.reason;
|
|
268
237
|
return results;
|
|
269
238
|
};
|
|
270
|
-
var fileSha256 = async (file, bytes) => bytes <= 1024 * 1024 ? (0,
|
|
239
|
+
var fileSha256 = async (file, bytes) => bytes <= 1024 * 1024 ? (0, import_node_crypto.createHash)("sha256").update(await import_promises.default.readFile(file)).digest("hex") : (0, import_strategyReleaseEvidence.strategyEvidenceFileSha256)(file);
|
|
271
240
|
var inside = (root, file) => {
|
|
272
241
|
const relative = import_node_path2.default.relative(root, file);
|
|
273
242
|
return relative !== "" && !relative.startsWith(`..${import_node_path2.default.sep}`) && relative !== ".." && !import_node_path2.default.isAbsolute(relative);
|
|
@@ -330,7 +299,7 @@ var applyResearchRetention = async (options) => {
|
|
|
330
299
|
throw new Error(
|
|
331
300
|
"Complete v2 note needs one verified metric snapshot"
|
|
332
301
|
);
|
|
333
|
-
decodeResearchMetricSnapshot(JSON.parse(blocks[0][1]));
|
|
302
|
+
(0, import_researchMetricSnapshot.decodeResearchMetricSnapshot)(JSON.parse(blocks[0][1]));
|
|
334
303
|
}
|
|
335
304
|
} finally {
|
|
336
305
|
await handle.close();
|
|
@@ -415,7 +384,7 @@ var applyResearchRetention = async (options) => {
|
|
|
415
384
|
};
|
|
416
385
|
|
|
417
386
|
// src/lib/strategyRelease.ts
|
|
418
|
-
var
|
|
387
|
+
var import_node_crypto2 = require("crypto");
|
|
419
388
|
var import_promises2 = __toESM(require("fs/promises"));
|
|
420
389
|
var import_node_path3 = __toESM(require("path"));
|
|
421
390
|
var import_types2 = require("@tradejs/types");
|
|
@@ -1585,7 +1554,7 @@ var verifyCompletedCoreResearchBundle = async ({
|
|
|
1585
1554
|
const artifactHashes = manifest.artifactHashes != null && typeof manifest.artifactHashes === "object" && !Array.isArray(manifest.artifactHashes) ? manifest.artifactHashes : null;
|
|
1586
1555
|
const parsedSpec = JSON.parse(specBytes.toString("utf8"));
|
|
1587
1556
|
assert2(
|
|
1588
|
-
manifest.schema === "tradejs-core-research-manifest/v1" && manifest.status === "completed" && manifest.researchId === researchId && manifest.specSha256 === specSha256 && artifactHashes?.["result.json"] === resultSha256 && (0,
|
|
1557
|
+
manifest.schema === "tradejs-core-research-manifest/v1" && manifest.status === "completed" && manifest.researchId === researchId && manifest.specSha256 === specSha256 && artifactHashes?.["result.json"] === resultSha256 && (0, import_node_crypto2.createHash)("sha256").update(canonicalStrategyReleaseJson(parsedSpec)).digest("hex") === specSha256,
|
|
1589
1558
|
"core result is not bound by its completed core research manifest"
|
|
1590
1559
|
);
|
|
1591
1560
|
for (const [relativePath, expectedSha256] of Object.entries(
|