@tradejs/cli 2.0.14 → 2.0.16
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 +2916 -978
- package/dist/lib/aiPocketSearch.js +493 -24
- package/dist/lib/aiTrainResearch.js +19 -2
- package/dist/lib/marketContextPrepare.js +85 -8
- package/dist/lib/researchAgent.js +3 -30
- package/dist/lib/runtimeDebugEvidence.js +76 -1
- package/dist/lib/runtimeEvidenceArtifacts.js +255 -0
- package/dist/lib/runtimeEvidenceSync.js +308 -0
- package/dist/lib/runtimeRedis.js +25 -0
- package/dist/lib/runtimeScorecard.js +442 -0
- package/dist/lib/runtimeTradeSync.js +9 -0
- package/dist/scripts/agentRun.js +16 -31
- package/dist/scripts/aiPocketSearch.js +717 -29
- package/dist/scripts/aiTrain.js +32 -2
- package/dist/scripts/backtest.js +83 -8
- package/dist/scripts/replay.js +92 -8
- package/dist/scripts/replayRunner.js +92 -8
- package/dist/scripts/replayRuntimeEvidence.js +68 -161
- package/dist/scripts/runtimeEvidence.js +316 -161
- package/dist/scripts/runtimeEvidenceSync.js +335 -0
- package/dist/scripts/runtimeParity.js +83 -8
- package/dist/scripts/runtimeScorecard.js +731 -0
- package/dist/scripts/signals.js +234 -142
- package/dist/scripts/signalsDaemon.js +234 -142
- package/dist/scripts/signalsSummary.js +9 -0
- package/dist/workers/testerWorker.js +2 -0
- package/package.json +11 -9
package/dist/scripts/aiTrain.js
CHANGED
|
@@ -2594,6 +2594,20 @@ var DERIVATIVES_CONTEXT_DATA_MODEL = {
|
|
|
2594
2594
|
hyperliquidWhaleMinCoveragePct: 0.8,
|
|
2595
2595
|
hyperliquidWhaleDataModelVersion: import_types.HYPERLIQUID_WHALE_DATA_MODEL_VERSION
|
|
2596
2596
|
};
|
|
2597
|
+
var writeAiTrainResearchSnapshot = async ({
|
|
2598
|
+
outputPath,
|
|
2599
|
+
result
|
|
2600
|
+
}) => {
|
|
2601
|
+
const resolvedPath = import_node_path.default.resolve(outputPath);
|
|
2602
|
+
await import_promises.default.mkdir(import_node_path.default.dirname(resolvedPath), { recursive: true });
|
|
2603
|
+
await import_promises.default.writeFile(
|
|
2604
|
+
resolvedPath,
|
|
2605
|
+
`${JSON.stringify(result, null, 2)}
|
|
2606
|
+
`,
|
|
2607
|
+
"utf8"
|
|
2608
|
+
);
|
|
2609
|
+
return resolvedPath;
|
|
2610
|
+
};
|
|
2597
2611
|
var normalizeForStableJson = (value) => {
|
|
2598
2612
|
if (Array.isArray(value)) {
|
|
2599
2613
|
return value.map(normalizeForStableJson);
|
|
@@ -2708,6 +2722,7 @@ var resolveGateFingerprint = async (projectRoot, strategyName, gitSha) => {
|
|
|
2708
2722
|
`packages/strategies/src/${strategyName}/guardrails.ts`,
|
|
2709
2723
|
`packages/strategies/src/${strategyName}/pockets.ts`,
|
|
2710
2724
|
`packages/strategies/src/${strategyName}/config.ts`,
|
|
2725
|
+
"packages/strategies/src/shared/localAiGate.ts",
|
|
2711
2726
|
"packages/node/src/ai.ts"
|
|
2712
2727
|
];
|
|
2713
2728
|
const optionalSourceEntries = await Promise.all(
|
|
@@ -3000,6 +3015,11 @@ import_args.default.option(
|
|
|
3000
3015
|
false
|
|
3001
3016
|
);
|
|
3002
3017
|
import_args.default.option(["j", "json"], "Print structured JSON summary", false);
|
|
3018
|
+
import_args.default.option(
|
|
3019
|
+
["O", "output"],
|
|
3020
|
+
"Write the structured JSON summary to a file and suppress table output",
|
|
3021
|
+
""
|
|
3022
|
+
);
|
|
3003
3023
|
import_args.default.option(
|
|
3004
3024
|
["S", "since"],
|
|
3005
3025
|
"Only evaluate rows at or after this timestamp (ISO date or epoch ms)",
|
|
@@ -3358,7 +3378,9 @@ var main = async () => {
|
|
|
3358
3378
|
const minQuality = normalizeInt(flags.minQuality, 4);
|
|
3359
3379
|
const localOnly = Boolean(flags.localOnly);
|
|
3360
3380
|
const saveChart = Boolean(flags.chart);
|
|
3361
|
-
const
|
|
3381
|
+
const printJsonOutput = Boolean(flags.json);
|
|
3382
|
+
const jsonOutputPath = String(flags.output || "").trim();
|
|
3383
|
+
const jsonOutput = printJsonOutput || Boolean(jsonOutputPath);
|
|
3362
3384
|
const sinceInput = parseTimestampFilter(flags.since);
|
|
3363
3385
|
const untilInput = parseTimestampFilter(flags.until);
|
|
3364
3386
|
const trailingPeriodMs = parseTrailingPeriodMs(flags.period);
|
|
@@ -3638,6 +3660,12 @@ var main = async () => {
|
|
|
3638
3660
|
providerErrors: errorMessages
|
|
3639
3661
|
}
|
|
3640
3662
|
};
|
|
3663
|
+
if (jsonOutputPath) {
|
|
3664
|
+
await writeAiTrainResearchSnapshot({
|
|
3665
|
+
outputPath: jsonOutputPath,
|
|
3666
|
+
result
|
|
3667
|
+
});
|
|
3668
|
+
}
|
|
3641
3669
|
if (dumpEvaluationsPath) {
|
|
3642
3670
|
await import_promises2.default.mkdir(import_path.default.dirname(import_path.default.resolve(dumpEvaluationsPath)), {
|
|
3643
3671
|
recursive: true
|
|
@@ -3681,7 +3709,9 @@ var main = async () => {
|
|
|
3681
3709
|
});
|
|
3682
3710
|
}
|
|
3683
3711
|
if (jsonOutput) {
|
|
3684
|
-
|
|
3712
|
+
if (printJsonOutput) {
|
|
3713
|
+
console.log(JSON.stringify(result));
|
|
3714
|
+
}
|
|
3685
3715
|
process.exit(failed === selectedRows ? 1 : 0);
|
|
3686
3716
|
}
|
|
3687
3717
|
console.log("");
|
package/dist/scripts/backtest.js
CHANGED
|
@@ -1705,6 +1705,8 @@ var timeOperation = async (label, operation, log = console.log) => {
|
|
|
1705
1705
|
|
|
1706
1706
|
// src/lib/marketContextPrepare.ts
|
|
1707
1707
|
var import_chalk4 = __toESM(require("chalk"));
|
|
1708
|
+
var import_timescale5 = require("@tradejs/infra/timescale");
|
|
1709
|
+
var import_registry = require("@tradejs/node/registry");
|
|
1708
1710
|
|
|
1709
1711
|
// src/lib/binanceMarketContextBackfill.ts
|
|
1710
1712
|
var import_progress = __toESM(require("progress"));
|
|
@@ -4946,6 +4948,9 @@ var backfillHyperliquidWhaleContext = async (params) => {
|
|
|
4946
4948
|
};
|
|
4947
4949
|
|
|
4948
4950
|
// src/lib/marketContextPrepare.ts
|
|
4951
|
+
var uniqueReasons = (reasons) => [
|
|
4952
|
+
...new Set(reasons)
|
|
4953
|
+
];
|
|
4949
4954
|
var shouldPrepareDerivativesContextForRun = (params) => {
|
|
4950
4955
|
if (params.universe === "tradfi") return false;
|
|
4951
4956
|
if (params.mode === "signals") {
|
|
@@ -4953,6 +4958,9 @@ var shouldPrepareDerivativesContextForRun = (params) => {
|
|
|
4953
4958
|
cacheOnly: params.cacheOnly
|
|
4954
4959
|
});
|
|
4955
4960
|
}
|
|
4961
|
+
if (params.mode === "backtest" && !params.aiEnabled && !params.mlEnabled) {
|
|
4962
|
+
return false;
|
|
4963
|
+
}
|
|
4956
4964
|
return shouldBackfillDerivativesContextForBacktest({
|
|
4957
4965
|
aiEnabled: Boolean(params.aiEnabled),
|
|
4958
4966
|
cacheOnly: params.cacheOnly,
|
|
@@ -4962,6 +4970,7 @@ var shouldPrepareDerivativesContextForRun = (params) => {
|
|
|
4962
4970
|
var shouldPrepareBinanceMarketContextForRun = (params) => {
|
|
4963
4971
|
if (params.universe === "tradfi") return false;
|
|
4964
4972
|
if (params.mode === "backtest") {
|
|
4973
|
+
if (!params.aiEnabled && !params.mlEnabled) return false;
|
|
4965
4974
|
return shouldBackfillBinanceMarketContextForBacktest({
|
|
4966
4975
|
aiEnabled: Boolean(params.aiEnabled),
|
|
4967
4976
|
cacheOnly: params.cacheOnly,
|
|
@@ -4980,6 +4989,7 @@ var shouldPrepareBinanceMarketContextForRun = (params) => {
|
|
|
4980
4989
|
var shouldPrepareCoinMarketCapContextForRun = (params) => {
|
|
4981
4990
|
if (params.universe === "tradfi") return false;
|
|
4982
4991
|
if (params.mode === "backtest") {
|
|
4992
|
+
if (!params.aiEnabled && !params.mlEnabled) return false;
|
|
4983
4993
|
return shouldBackfillCoinMarketCapContextForBacktest({
|
|
4984
4994
|
aiEnabled: Boolean(params.aiEnabled),
|
|
4985
4995
|
cacheOnly: params.cacheOnly,
|
|
@@ -4995,10 +5005,8 @@ var shouldPrepareCoinMarketCapContextForRun = (params) => {
|
|
|
4995
5005
|
cacheOnly: params.cacheOnly
|
|
4996
5006
|
});
|
|
4997
5007
|
};
|
|
4998
|
-
var shouldPrepareHyperliquidWhaleContextForRun = (params) => {
|
|
4999
|
-
const strategyRequiresContext =
|
|
5000
|
-
"HyperliquidConsensus"
|
|
5001
|
-
);
|
|
5008
|
+
var shouldPrepareHyperliquidWhaleContextForRun = (params, coreContextSources = []) => {
|
|
5009
|
+
const strategyRequiresContext = coreContextSources.includes("hyperliquidWhales");
|
|
5002
5010
|
if (params.universe === "tradfi" || params.mode === "signals" || params.cacheOnly || !params.aiEnabled && !params.mlEnabled && !strategyRequiresContext) {
|
|
5003
5011
|
return false;
|
|
5004
5012
|
}
|
|
@@ -5009,6 +5017,64 @@ var shouldPrepareHyperliquidWhaleContextForRun = (params) => {
|
|
|
5009
5017
|
if (strategyRequiresContext) return true;
|
|
5010
5018
|
return ["1", "true", "yes", "on"].includes(configured);
|
|
5011
5019
|
};
|
|
5020
|
+
var resolveCoreContextSources = async (params) => {
|
|
5021
|
+
const strategyNames = [...new Set(params.strategyNames ?? [])];
|
|
5022
|
+
if (!strategyNames.length) return [];
|
|
5023
|
+
await (0, import_registry.ensureStrategyPluginsLoaded)(params.projectRoot);
|
|
5024
|
+
return [
|
|
5025
|
+
...new Set(
|
|
5026
|
+
strategyNames.flatMap(
|
|
5027
|
+
(strategyName) => (0, import_registry.getStrategyManifest)(strategyName, params.projectRoot)?.contextRequirements?.core ?? []
|
|
5028
|
+
)
|
|
5029
|
+
)
|
|
5030
|
+
];
|
|
5031
|
+
};
|
|
5032
|
+
var resolveMarketContextRunRequirements = async (params) => {
|
|
5033
|
+
const coreContextSources = await resolveCoreContextSources(params);
|
|
5034
|
+
const paramsWithCoreDemand = (source) => coreContextSources.includes(source) ? { ...params, aiEnabled: true } : params;
|
|
5035
|
+
const isCrypto = params.universe !== "tradfi";
|
|
5036
|
+
const capturesPayload = Boolean(params.aiEnabled || params.mlEnabled);
|
|
5037
|
+
const runtimeReadsContext = params.mode !== "backtest";
|
|
5038
|
+
const reasonsFor = (source) => uniqueReasons([
|
|
5039
|
+
...coreContextSources.includes(source) ? ["core"] : [],
|
|
5040
|
+
...params.aiEnabled ? ["ai"] : [],
|
|
5041
|
+
...params.mlEnabled ? ["ml"] : [],
|
|
5042
|
+
...runtimeReadsContext ? ["runtime"] : []
|
|
5043
|
+
]);
|
|
5044
|
+
const readsStandardContext = isCrypto && (capturesPayload || runtimeReadsContext);
|
|
5045
|
+
const readsHyperliquid = isCrypto && (readsStandardContext || coreContextSources.includes("hyperliquidWhales"));
|
|
5046
|
+
return {
|
|
5047
|
+
binance: {
|
|
5048
|
+
read: readsStandardContext || coreContextSources.includes("binance"),
|
|
5049
|
+
backfill: shouldPrepareBinanceMarketContextForRun(
|
|
5050
|
+
paramsWithCoreDemand("binance")
|
|
5051
|
+
),
|
|
5052
|
+
requiredBy: reasonsFor("binance")
|
|
5053
|
+
},
|
|
5054
|
+
coinmarketcap: {
|
|
5055
|
+
read: readsStandardContext || coreContextSources.includes("coinmarketcap"),
|
|
5056
|
+
backfill: shouldPrepareCoinMarketCapContextForRun(
|
|
5057
|
+
paramsWithCoreDemand("coinmarketcap")
|
|
5058
|
+
),
|
|
5059
|
+
requiredBy: reasonsFor("coinmarketcap")
|
|
5060
|
+
},
|
|
5061
|
+
derivatives: {
|
|
5062
|
+
read: readsStandardContext || coreContextSources.includes("derivatives"),
|
|
5063
|
+
backfill: shouldPrepareDerivativesContextForRun(
|
|
5064
|
+
paramsWithCoreDemand("derivatives")
|
|
5065
|
+
),
|
|
5066
|
+
requiredBy: reasonsFor("derivatives")
|
|
5067
|
+
},
|
|
5068
|
+
hyperliquidWhales: {
|
|
5069
|
+
read: readsHyperliquid,
|
|
5070
|
+
backfill: shouldPrepareHyperliquidWhaleContextForRun(
|
|
5071
|
+
params,
|
|
5072
|
+
coreContextSources
|
|
5073
|
+
),
|
|
5074
|
+
requiredBy: reasonsFor("hyperliquidWhales")
|
|
5075
|
+
}
|
|
5076
|
+
};
|
|
5077
|
+
};
|
|
5012
5078
|
var resolveCoinMarketCapBackfillForMode = (mode) => mode === "backtest" ? backfillCoinMarketCapContextForBacktest : mode === "signals" ? backfillCoinMarketCapContextForSignals : backfillCoinMarketCapContextForReplay;
|
|
5013
5079
|
var buildCoinMarketCapBackfillParams = (params) => ({
|
|
5014
5080
|
userName: params.userName,
|
|
@@ -5037,7 +5103,15 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5037
5103
|
console.log(import_chalk4.default.gray(message));
|
|
5038
5104
|
});
|
|
5039
5105
|
const timeOperation3 = (label, operation) => timeOperation(label, operation, log);
|
|
5040
|
-
|
|
5106
|
+
const requirements = await resolveMarketContextRunRequirements(params);
|
|
5107
|
+
const readableSources = Object.entries(requirements).filter(([, requirement]) => requirement.read).map(([source]) => source);
|
|
5108
|
+
if (readableSources.length) {
|
|
5109
|
+
await timeOperation3(
|
|
5110
|
+
"market context schema ensure",
|
|
5111
|
+
() => (0, import_timescale5.ensureMarketContextSchemas)(readableSources)
|
|
5112
|
+
);
|
|
5113
|
+
}
|
|
5114
|
+
if (requirements.derivatives.backfill) {
|
|
5041
5115
|
await timeOperation3(
|
|
5042
5116
|
"derivatives context backfill",
|
|
5043
5117
|
() => (params.mode === "signals" ? backfillDerivativesContextForSignals : backfillDerivativesContextForBacktest)(
|
|
@@ -5045,7 +5119,7 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5045
5119
|
)
|
|
5046
5120
|
);
|
|
5047
5121
|
}
|
|
5048
|
-
if (
|
|
5122
|
+
if (requirements.hyperliquidWhales.backfill) {
|
|
5049
5123
|
await timeOperation3(
|
|
5050
5124
|
"hyperliquid whale context backfill",
|
|
5051
5125
|
() => backfillHyperliquidWhaleContext({
|
|
@@ -5057,13 +5131,13 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5057
5131
|
})
|
|
5058
5132
|
);
|
|
5059
5133
|
}
|
|
5060
|
-
if (
|
|
5134
|
+
if (requirements.binance.backfill) {
|
|
5061
5135
|
await timeOperation3("binance market context backfill", () => {
|
|
5062
5136
|
const backfill = params.mode === "backtest" ? backfillBinanceMarketContextForBacktest : params.mode === "signals" ? backfillBinanceMarketContextForSignals : backfillBinanceMarketContextForReplay;
|
|
5063
5137
|
return backfill(buildBinanceMarketBackfillParams(params));
|
|
5064
5138
|
});
|
|
5065
5139
|
}
|
|
5066
|
-
if (
|
|
5140
|
+
if (requirements.coinmarketcap.backfill) {
|
|
5067
5141
|
await timeOperation3(
|
|
5068
5142
|
"coinmarketcap historical context backfill",
|
|
5069
5143
|
() => resolveCoinMarketCapBackfillForMode(params.mode)(
|
|
@@ -5071,6 +5145,7 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5071
5145
|
)
|
|
5072
5146
|
);
|
|
5073
5147
|
}
|
|
5148
|
+
return requirements;
|
|
5074
5149
|
};
|
|
5075
5150
|
|
|
5076
5151
|
// src/lib/runEnvironment.ts
|
package/dist/scripts/replay.js
CHANGED
|
@@ -2346,6 +2346,8 @@ var prepareRunEnvironment = async ({
|
|
|
2346
2346
|
|
|
2347
2347
|
// src/lib/marketContextPrepare.ts
|
|
2348
2348
|
var import_chalk7 = __toESM(require("chalk"));
|
|
2349
|
+
var import_timescale5 = require("@tradejs/infra/timescale");
|
|
2350
|
+
var import_registry = require("@tradejs/node/registry");
|
|
2349
2351
|
|
|
2350
2352
|
// src/lib/binanceMarketContextBackfill.ts
|
|
2351
2353
|
var import_progress = __toESM(require("progress"));
|
|
@@ -5587,6 +5589,9 @@ var backfillHyperliquidWhaleContext = async (params) => {
|
|
|
5587
5589
|
};
|
|
5588
5590
|
|
|
5589
5591
|
// src/lib/marketContextPrepare.ts
|
|
5592
|
+
var uniqueReasons = (reasons) => [
|
|
5593
|
+
...new Set(reasons)
|
|
5594
|
+
];
|
|
5590
5595
|
var shouldPrepareDerivativesContextForRun = (params) => {
|
|
5591
5596
|
if (params.universe === "tradfi") return false;
|
|
5592
5597
|
if (params.mode === "signals") {
|
|
@@ -5594,6 +5599,9 @@ var shouldPrepareDerivativesContextForRun = (params) => {
|
|
|
5594
5599
|
cacheOnly: params.cacheOnly
|
|
5595
5600
|
});
|
|
5596
5601
|
}
|
|
5602
|
+
if (params.mode === "backtest" && !params.aiEnabled && !params.mlEnabled) {
|
|
5603
|
+
return false;
|
|
5604
|
+
}
|
|
5597
5605
|
return shouldBackfillDerivativesContextForBacktest({
|
|
5598
5606
|
aiEnabled: Boolean(params.aiEnabled),
|
|
5599
5607
|
cacheOnly: params.cacheOnly,
|
|
@@ -5603,6 +5611,7 @@ var shouldPrepareDerivativesContextForRun = (params) => {
|
|
|
5603
5611
|
var shouldPrepareBinanceMarketContextForRun = (params) => {
|
|
5604
5612
|
if (params.universe === "tradfi") return false;
|
|
5605
5613
|
if (params.mode === "backtest") {
|
|
5614
|
+
if (!params.aiEnabled && !params.mlEnabled) return false;
|
|
5606
5615
|
return shouldBackfillBinanceMarketContextForBacktest({
|
|
5607
5616
|
aiEnabled: Boolean(params.aiEnabled),
|
|
5608
5617
|
cacheOnly: params.cacheOnly,
|
|
@@ -5621,6 +5630,7 @@ var shouldPrepareBinanceMarketContextForRun = (params) => {
|
|
|
5621
5630
|
var shouldPrepareCoinMarketCapContextForRun = (params) => {
|
|
5622
5631
|
if (params.universe === "tradfi") return false;
|
|
5623
5632
|
if (params.mode === "backtest") {
|
|
5633
|
+
if (!params.aiEnabled && !params.mlEnabled) return false;
|
|
5624
5634
|
return shouldBackfillCoinMarketCapContextForBacktest({
|
|
5625
5635
|
aiEnabled: Boolean(params.aiEnabled),
|
|
5626
5636
|
cacheOnly: params.cacheOnly,
|
|
@@ -5636,10 +5646,8 @@ var shouldPrepareCoinMarketCapContextForRun = (params) => {
|
|
|
5636
5646
|
cacheOnly: params.cacheOnly
|
|
5637
5647
|
});
|
|
5638
5648
|
};
|
|
5639
|
-
var shouldPrepareHyperliquidWhaleContextForRun = (params) => {
|
|
5640
|
-
const strategyRequiresContext =
|
|
5641
|
-
"HyperliquidConsensus"
|
|
5642
|
-
);
|
|
5649
|
+
var shouldPrepareHyperliquidWhaleContextForRun = (params, coreContextSources = []) => {
|
|
5650
|
+
const strategyRequiresContext = coreContextSources.includes("hyperliquidWhales");
|
|
5643
5651
|
if (params.universe === "tradfi" || params.mode === "signals" || params.cacheOnly || !params.aiEnabled && !params.mlEnabled && !strategyRequiresContext) {
|
|
5644
5652
|
return false;
|
|
5645
5653
|
}
|
|
@@ -5650,6 +5658,64 @@ var shouldPrepareHyperliquidWhaleContextForRun = (params) => {
|
|
|
5650
5658
|
if (strategyRequiresContext) return true;
|
|
5651
5659
|
return ["1", "true", "yes", "on"].includes(configured);
|
|
5652
5660
|
};
|
|
5661
|
+
var resolveCoreContextSources = async (params) => {
|
|
5662
|
+
const strategyNames = [...new Set(params.strategyNames ?? [])];
|
|
5663
|
+
if (!strategyNames.length) return [];
|
|
5664
|
+
await (0, import_registry.ensureStrategyPluginsLoaded)(params.projectRoot);
|
|
5665
|
+
return [
|
|
5666
|
+
...new Set(
|
|
5667
|
+
strategyNames.flatMap(
|
|
5668
|
+
(strategyName) => (0, import_registry.getStrategyManifest)(strategyName, params.projectRoot)?.contextRequirements?.core ?? []
|
|
5669
|
+
)
|
|
5670
|
+
)
|
|
5671
|
+
];
|
|
5672
|
+
};
|
|
5673
|
+
var resolveMarketContextRunRequirements = async (params) => {
|
|
5674
|
+
const coreContextSources = await resolveCoreContextSources(params);
|
|
5675
|
+
const paramsWithCoreDemand = (source) => coreContextSources.includes(source) ? { ...params, aiEnabled: true } : params;
|
|
5676
|
+
const isCrypto = params.universe !== "tradfi";
|
|
5677
|
+
const capturesPayload = Boolean(params.aiEnabled || params.mlEnabled);
|
|
5678
|
+
const runtimeReadsContext = params.mode !== "backtest";
|
|
5679
|
+
const reasonsFor = (source) => uniqueReasons([
|
|
5680
|
+
...coreContextSources.includes(source) ? ["core"] : [],
|
|
5681
|
+
...params.aiEnabled ? ["ai"] : [],
|
|
5682
|
+
...params.mlEnabled ? ["ml"] : [],
|
|
5683
|
+
...runtimeReadsContext ? ["runtime"] : []
|
|
5684
|
+
]);
|
|
5685
|
+
const readsStandardContext = isCrypto && (capturesPayload || runtimeReadsContext);
|
|
5686
|
+
const readsHyperliquid = isCrypto && (readsStandardContext || coreContextSources.includes("hyperliquidWhales"));
|
|
5687
|
+
return {
|
|
5688
|
+
binance: {
|
|
5689
|
+
read: readsStandardContext || coreContextSources.includes("binance"),
|
|
5690
|
+
backfill: shouldPrepareBinanceMarketContextForRun(
|
|
5691
|
+
paramsWithCoreDemand("binance")
|
|
5692
|
+
),
|
|
5693
|
+
requiredBy: reasonsFor("binance")
|
|
5694
|
+
},
|
|
5695
|
+
coinmarketcap: {
|
|
5696
|
+
read: readsStandardContext || coreContextSources.includes("coinmarketcap"),
|
|
5697
|
+
backfill: shouldPrepareCoinMarketCapContextForRun(
|
|
5698
|
+
paramsWithCoreDemand("coinmarketcap")
|
|
5699
|
+
),
|
|
5700
|
+
requiredBy: reasonsFor("coinmarketcap")
|
|
5701
|
+
},
|
|
5702
|
+
derivatives: {
|
|
5703
|
+
read: readsStandardContext || coreContextSources.includes("derivatives"),
|
|
5704
|
+
backfill: shouldPrepareDerivativesContextForRun(
|
|
5705
|
+
paramsWithCoreDemand("derivatives")
|
|
5706
|
+
),
|
|
5707
|
+
requiredBy: reasonsFor("derivatives")
|
|
5708
|
+
},
|
|
5709
|
+
hyperliquidWhales: {
|
|
5710
|
+
read: readsHyperliquid,
|
|
5711
|
+
backfill: shouldPrepareHyperliquidWhaleContextForRun(
|
|
5712
|
+
params,
|
|
5713
|
+
coreContextSources
|
|
5714
|
+
),
|
|
5715
|
+
requiredBy: reasonsFor("hyperliquidWhales")
|
|
5716
|
+
}
|
|
5717
|
+
};
|
|
5718
|
+
};
|
|
5653
5719
|
var resolveCoinMarketCapBackfillForMode = (mode) => mode === "backtest" ? backfillCoinMarketCapContextForBacktest : mode === "signals" ? backfillCoinMarketCapContextForSignals : backfillCoinMarketCapContextForReplay;
|
|
5654
5720
|
var buildCoinMarketCapBackfillParams = (params) => ({
|
|
5655
5721
|
userName: params.userName,
|
|
@@ -5678,7 +5744,15 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5678
5744
|
console.log(import_chalk7.default.gray(message));
|
|
5679
5745
|
});
|
|
5680
5746
|
const timeOperation3 = (label, operation) => timeOperation(label, operation, log);
|
|
5681
|
-
|
|
5747
|
+
const requirements = await resolveMarketContextRunRequirements(params);
|
|
5748
|
+
const readableSources = Object.entries(requirements).filter(([, requirement]) => requirement.read).map(([source]) => source);
|
|
5749
|
+
if (readableSources.length) {
|
|
5750
|
+
await timeOperation3(
|
|
5751
|
+
"market context schema ensure",
|
|
5752
|
+
() => (0, import_timescale5.ensureMarketContextSchemas)(readableSources)
|
|
5753
|
+
);
|
|
5754
|
+
}
|
|
5755
|
+
if (requirements.derivatives.backfill) {
|
|
5682
5756
|
await timeOperation3(
|
|
5683
5757
|
"derivatives context backfill",
|
|
5684
5758
|
() => (params.mode === "signals" ? backfillDerivativesContextForSignals : backfillDerivativesContextForBacktest)(
|
|
@@ -5686,7 +5760,7 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5686
5760
|
)
|
|
5687
5761
|
);
|
|
5688
5762
|
}
|
|
5689
|
-
if (
|
|
5763
|
+
if (requirements.hyperliquidWhales.backfill) {
|
|
5690
5764
|
await timeOperation3(
|
|
5691
5765
|
"hyperliquid whale context backfill",
|
|
5692
5766
|
() => backfillHyperliquidWhaleContext({
|
|
@@ -5698,13 +5772,13 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5698
5772
|
})
|
|
5699
5773
|
);
|
|
5700
5774
|
}
|
|
5701
|
-
if (
|
|
5775
|
+
if (requirements.binance.backfill) {
|
|
5702
5776
|
await timeOperation3("binance market context backfill", () => {
|
|
5703
5777
|
const backfill = params.mode === "backtest" ? backfillBinanceMarketContextForBacktest : params.mode === "signals" ? backfillBinanceMarketContextForSignals : backfillBinanceMarketContextForReplay;
|
|
5704
5778
|
return backfill(buildBinanceMarketBackfillParams(params));
|
|
5705
5779
|
});
|
|
5706
5780
|
}
|
|
5707
|
-
if (
|
|
5781
|
+
if (requirements.coinmarketcap.backfill) {
|
|
5708
5782
|
await timeOperation3(
|
|
5709
5783
|
"coinmarketcap historical context backfill",
|
|
5710
5784
|
() => resolveCoinMarketCapBackfillForMode(params.mode)(
|
|
@@ -5712,6 +5786,7 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5712
5786
|
)
|
|
5713
5787
|
);
|
|
5714
5788
|
}
|
|
5789
|
+
return requirements;
|
|
5715
5790
|
};
|
|
5716
5791
|
|
|
5717
5792
|
// src/lib/backtest/runState.ts
|
|
@@ -7960,6 +8035,15 @@ var syncRuntimeTrades = async ({
|
|
|
7960
8035
|
nextTrade,
|
|
7961
8036
|
{ expire: import_constants5.TTL_1M }
|
|
7962
8037
|
),
|
|
8038
|
+
(0, import_redis5.setHashJsonField)(
|
|
8039
|
+
import_redis5.redisKeys.runtimeClosedTradeBucket(
|
|
8040
|
+
userName,
|
|
8041
|
+
(0, import_time5.getRuntimeStorageDayKey)(nextTrade.exitTimestamp)
|
|
8042
|
+
),
|
|
8043
|
+
trade.orderId,
|
|
8044
|
+
nextTrade,
|
|
8045
|
+
{ expire: import_constants5.TTL_1M }
|
|
8046
|
+
),
|
|
7963
8047
|
...isCurrentActiveTrade ? [(0, import_redis5.delKey)(activeTradeKey)] : []
|
|
7964
8048
|
]);
|
|
7965
8049
|
syncedTrades.push(nextTrade);
|
|
@@ -2349,6 +2349,8 @@ var prepareRunEnvironment = async ({
|
|
|
2349
2349
|
|
|
2350
2350
|
// src/lib/marketContextPrepare.ts
|
|
2351
2351
|
var import_chalk7 = __toESM(require("chalk"));
|
|
2352
|
+
var import_timescale5 = require("@tradejs/infra/timescale");
|
|
2353
|
+
var import_registry = require("@tradejs/node/registry");
|
|
2352
2354
|
|
|
2353
2355
|
// src/lib/binanceMarketContextBackfill.ts
|
|
2354
2356
|
var import_progress = __toESM(require("progress"));
|
|
@@ -5590,6 +5592,9 @@ var backfillHyperliquidWhaleContext = async (params) => {
|
|
|
5590
5592
|
};
|
|
5591
5593
|
|
|
5592
5594
|
// src/lib/marketContextPrepare.ts
|
|
5595
|
+
var uniqueReasons = (reasons) => [
|
|
5596
|
+
...new Set(reasons)
|
|
5597
|
+
];
|
|
5593
5598
|
var shouldPrepareDerivativesContextForRun = (params) => {
|
|
5594
5599
|
if (params.universe === "tradfi") return false;
|
|
5595
5600
|
if (params.mode === "signals") {
|
|
@@ -5597,6 +5602,9 @@ var shouldPrepareDerivativesContextForRun = (params) => {
|
|
|
5597
5602
|
cacheOnly: params.cacheOnly
|
|
5598
5603
|
});
|
|
5599
5604
|
}
|
|
5605
|
+
if (params.mode === "backtest" && !params.aiEnabled && !params.mlEnabled) {
|
|
5606
|
+
return false;
|
|
5607
|
+
}
|
|
5600
5608
|
return shouldBackfillDerivativesContextForBacktest({
|
|
5601
5609
|
aiEnabled: Boolean(params.aiEnabled),
|
|
5602
5610
|
cacheOnly: params.cacheOnly,
|
|
@@ -5606,6 +5614,7 @@ var shouldPrepareDerivativesContextForRun = (params) => {
|
|
|
5606
5614
|
var shouldPrepareBinanceMarketContextForRun = (params) => {
|
|
5607
5615
|
if (params.universe === "tradfi") return false;
|
|
5608
5616
|
if (params.mode === "backtest") {
|
|
5617
|
+
if (!params.aiEnabled && !params.mlEnabled) return false;
|
|
5609
5618
|
return shouldBackfillBinanceMarketContextForBacktest({
|
|
5610
5619
|
aiEnabled: Boolean(params.aiEnabled),
|
|
5611
5620
|
cacheOnly: params.cacheOnly,
|
|
@@ -5624,6 +5633,7 @@ var shouldPrepareBinanceMarketContextForRun = (params) => {
|
|
|
5624
5633
|
var shouldPrepareCoinMarketCapContextForRun = (params) => {
|
|
5625
5634
|
if (params.universe === "tradfi") return false;
|
|
5626
5635
|
if (params.mode === "backtest") {
|
|
5636
|
+
if (!params.aiEnabled && !params.mlEnabled) return false;
|
|
5627
5637
|
return shouldBackfillCoinMarketCapContextForBacktest({
|
|
5628
5638
|
aiEnabled: Boolean(params.aiEnabled),
|
|
5629
5639
|
cacheOnly: params.cacheOnly,
|
|
@@ -5639,10 +5649,8 @@ var shouldPrepareCoinMarketCapContextForRun = (params) => {
|
|
|
5639
5649
|
cacheOnly: params.cacheOnly
|
|
5640
5650
|
});
|
|
5641
5651
|
};
|
|
5642
|
-
var shouldPrepareHyperliquidWhaleContextForRun = (params) => {
|
|
5643
|
-
const strategyRequiresContext =
|
|
5644
|
-
"HyperliquidConsensus"
|
|
5645
|
-
);
|
|
5652
|
+
var shouldPrepareHyperliquidWhaleContextForRun = (params, coreContextSources = []) => {
|
|
5653
|
+
const strategyRequiresContext = coreContextSources.includes("hyperliquidWhales");
|
|
5646
5654
|
if (params.universe === "tradfi" || params.mode === "signals" || params.cacheOnly || !params.aiEnabled && !params.mlEnabled && !strategyRequiresContext) {
|
|
5647
5655
|
return false;
|
|
5648
5656
|
}
|
|
@@ -5653,6 +5661,64 @@ var shouldPrepareHyperliquidWhaleContextForRun = (params) => {
|
|
|
5653
5661
|
if (strategyRequiresContext) return true;
|
|
5654
5662
|
return ["1", "true", "yes", "on"].includes(configured);
|
|
5655
5663
|
};
|
|
5664
|
+
var resolveCoreContextSources = async (params) => {
|
|
5665
|
+
const strategyNames = [...new Set(params.strategyNames ?? [])];
|
|
5666
|
+
if (!strategyNames.length) return [];
|
|
5667
|
+
await (0, import_registry.ensureStrategyPluginsLoaded)(params.projectRoot);
|
|
5668
|
+
return [
|
|
5669
|
+
...new Set(
|
|
5670
|
+
strategyNames.flatMap(
|
|
5671
|
+
(strategyName) => (0, import_registry.getStrategyManifest)(strategyName, params.projectRoot)?.contextRequirements?.core ?? []
|
|
5672
|
+
)
|
|
5673
|
+
)
|
|
5674
|
+
];
|
|
5675
|
+
};
|
|
5676
|
+
var resolveMarketContextRunRequirements = async (params) => {
|
|
5677
|
+
const coreContextSources = await resolveCoreContextSources(params);
|
|
5678
|
+
const paramsWithCoreDemand = (source) => coreContextSources.includes(source) ? { ...params, aiEnabled: true } : params;
|
|
5679
|
+
const isCrypto = params.universe !== "tradfi";
|
|
5680
|
+
const capturesPayload = Boolean(params.aiEnabled || params.mlEnabled);
|
|
5681
|
+
const runtimeReadsContext = params.mode !== "backtest";
|
|
5682
|
+
const reasonsFor = (source) => uniqueReasons([
|
|
5683
|
+
...coreContextSources.includes(source) ? ["core"] : [],
|
|
5684
|
+
...params.aiEnabled ? ["ai"] : [],
|
|
5685
|
+
...params.mlEnabled ? ["ml"] : [],
|
|
5686
|
+
...runtimeReadsContext ? ["runtime"] : []
|
|
5687
|
+
]);
|
|
5688
|
+
const readsStandardContext = isCrypto && (capturesPayload || runtimeReadsContext);
|
|
5689
|
+
const readsHyperliquid = isCrypto && (readsStandardContext || coreContextSources.includes("hyperliquidWhales"));
|
|
5690
|
+
return {
|
|
5691
|
+
binance: {
|
|
5692
|
+
read: readsStandardContext || coreContextSources.includes("binance"),
|
|
5693
|
+
backfill: shouldPrepareBinanceMarketContextForRun(
|
|
5694
|
+
paramsWithCoreDemand("binance")
|
|
5695
|
+
),
|
|
5696
|
+
requiredBy: reasonsFor("binance")
|
|
5697
|
+
},
|
|
5698
|
+
coinmarketcap: {
|
|
5699
|
+
read: readsStandardContext || coreContextSources.includes("coinmarketcap"),
|
|
5700
|
+
backfill: shouldPrepareCoinMarketCapContextForRun(
|
|
5701
|
+
paramsWithCoreDemand("coinmarketcap")
|
|
5702
|
+
),
|
|
5703
|
+
requiredBy: reasonsFor("coinmarketcap")
|
|
5704
|
+
},
|
|
5705
|
+
derivatives: {
|
|
5706
|
+
read: readsStandardContext || coreContextSources.includes("derivatives"),
|
|
5707
|
+
backfill: shouldPrepareDerivativesContextForRun(
|
|
5708
|
+
paramsWithCoreDemand("derivatives")
|
|
5709
|
+
),
|
|
5710
|
+
requiredBy: reasonsFor("derivatives")
|
|
5711
|
+
},
|
|
5712
|
+
hyperliquidWhales: {
|
|
5713
|
+
read: readsHyperliquid,
|
|
5714
|
+
backfill: shouldPrepareHyperliquidWhaleContextForRun(
|
|
5715
|
+
params,
|
|
5716
|
+
coreContextSources
|
|
5717
|
+
),
|
|
5718
|
+
requiredBy: reasonsFor("hyperliquidWhales")
|
|
5719
|
+
}
|
|
5720
|
+
};
|
|
5721
|
+
};
|
|
5656
5722
|
var resolveCoinMarketCapBackfillForMode = (mode) => mode === "backtest" ? backfillCoinMarketCapContextForBacktest : mode === "signals" ? backfillCoinMarketCapContextForSignals : backfillCoinMarketCapContextForReplay;
|
|
5657
5723
|
var buildCoinMarketCapBackfillParams = (params) => ({
|
|
5658
5724
|
userName: params.userName,
|
|
@@ -5681,7 +5747,15 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5681
5747
|
console.log(import_chalk7.default.gray(message));
|
|
5682
5748
|
});
|
|
5683
5749
|
const timeOperation3 = (label, operation) => timeOperation(label, operation, log);
|
|
5684
|
-
|
|
5750
|
+
const requirements = await resolveMarketContextRunRequirements(params);
|
|
5751
|
+
const readableSources = Object.entries(requirements).filter(([, requirement]) => requirement.read).map(([source]) => source);
|
|
5752
|
+
if (readableSources.length) {
|
|
5753
|
+
await timeOperation3(
|
|
5754
|
+
"market context schema ensure",
|
|
5755
|
+
() => (0, import_timescale5.ensureMarketContextSchemas)(readableSources)
|
|
5756
|
+
);
|
|
5757
|
+
}
|
|
5758
|
+
if (requirements.derivatives.backfill) {
|
|
5685
5759
|
await timeOperation3(
|
|
5686
5760
|
"derivatives context backfill",
|
|
5687
5761
|
() => (params.mode === "signals" ? backfillDerivativesContextForSignals : backfillDerivativesContextForBacktest)(
|
|
@@ -5689,7 +5763,7 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5689
5763
|
)
|
|
5690
5764
|
);
|
|
5691
5765
|
}
|
|
5692
|
-
if (
|
|
5766
|
+
if (requirements.hyperliquidWhales.backfill) {
|
|
5693
5767
|
await timeOperation3(
|
|
5694
5768
|
"hyperliquid whale context backfill",
|
|
5695
5769
|
() => backfillHyperliquidWhaleContext({
|
|
@@ -5701,13 +5775,13 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5701
5775
|
})
|
|
5702
5776
|
);
|
|
5703
5777
|
}
|
|
5704
|
-
if (
|
|
5778
|
+
if (requirements.binance.backfill) {
|
|
5705
5779
|
await timeOperation3("binance market context backfill", () => {
|
|
5706
5780
|
const backfill = params.mode === "backtest" ? backfillBinanceMarketContextForBacktest : params.mode === "signals" ? backfillBinanceMarketContextForSignals : backfillBinanceMarketContextForReplay;
|
|
5707
5781
|
return backfill(buildBinanceMarketBackfillParams(params));
|
|
5708
5782
|
});
|
|
5709
5783
|
}
|
|
5710
|
-
if (
|
|
5784
|
+
if (requirements.coinmarketcap.backfill) {
|
|
5711
5785
|
await timeOperation3(
|
|
5712
5786
|
"coinmarketcap historical context backfill",
|
|
5713
5787
|
() => resolveCoinMarketCapBackfillForMode(params.mode)(
|
|
@@ -5715,6 +5789,7 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5715
5789
|
)
|
|
5716
5790
|
);
|
|
5717
5791
|
}
|
|
5792
|
+
return requirements;
|
|
5718
5793
|
};
|
|
5719
5794
|
|
|
5720
5795
|
// src/lib/backtest/runState.ts
|
|
@@ -7963,6 +8038,15 @@ var syncRuntimeTrades = async ({
|
|
|
7963
8038
|
nextTrade,
|
|
7964
8039
|
{ expire: import_constants5.TTL_1M }
|
|
7965
8040
|
),
|
|
8041
|
+
(0, import_redis5.setHashJsonField)(
|
|
8042
|
+
import_redis5.redisKeys.runtimeClosedTradeBucket(
|
|
8043
|
+
userName,
|
|
8044
|
+
(0, import_time5.getRuntimeStorageDayKey)(nextTrade.exitTimestamp)
|
|
8045
|
+
),
|
|
8046
|
+
trade.orderId,
|
|
8047
|
+
nextTrade,
|
|
8048
|
+
{ expire: import_constants5.TTL_1M }
|
|
8049
|
+
),
|
|
7966
8050
|
...isCurrentActiveTrade ? [(0, import_redis5.delKey)(activeTradeKey)] : []
|
|
7967
8051
|
]);
|
|
7968
8052
|
syncedTrades.push(nextTrade);
|