@tradejs/cli 2.0.15 → 2.0.17
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 +2982 -994
- package/dist/lib/aiPocketSearch.js +493 -24
- package/dist/lib/aiTrainResearch.js +19 -2
- package/dist/lib/hyperliquidWhaleBackfill.js +37 -1
- package/dist/lib/marketContextPrepare.js +112 -9
- 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 +136 -11
- package/dist/scripts/hyperliquidWhaleBackfill.js +27 -1
- package/dist/scripts/hyperliquidWhalesUpdate.js +1 -0
- package/dist/scripts/replay.js +122 -12
- package/dist/scripts/replayRunner.js +122 -12
- 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 +110 -9
- package/dist/scripts/runtimeScorecard.js +731 -0
- package/dist/scripts/signals.js +263 -145
- package/dist/scripts/signalsDaemon.js +263 -145
- 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"));
|
|
@@ -4540,6 +4542,7 @@ var backfillCoinMarketCapContextForReplay = backfillCoinMarketCapContext;
|
|
|
4540
4542
|
var backfillCoinMarketCapContextForSignals = (params) => backfillCoinMarketCapContext({ ...params, refreshStaleFearGreed: true });
|
|
4541
4543
|
|
|
4542
4544
|
// src/lib/hyperliquidWhaleBackfill.ts
|
|
4545
|
+
var import_progress3 = __toESM(require("progress"));
|
|
4543
4546
|
var import_timescale4 = require("@tradejs/infra/timescale");
|
|
4544
4547
|
var import_strategies2 = require("@tradejs/node/strategies");
|
|
4545
4548
|
|
|
@@ -4914,11 +4917,36 @@ var backfillHyperliquidWhaleContext = async (params) => {
|
|
|
4914
4917
|
toMs,
|
|
4915
4918
|
...identity
|
|
4916
4919
|
});
|
|
4920
|
+
const totalCoverageBuckets = Math.ceil(
|
|
4921
|
+
(toMs - fromMs) / HYPERLIQUID_WHALE_BUCKET_MS
|
|
4922
|
+
);
|
|
4923
|
+
const coverageBar = new import_progress3.default(
|
|
4924
|
+
"Hyperliquid coverage :current/:total [:bar][:percent] :eta(s) rows=:rows chunk=:chunk",
|
|
4925
|
+
{
|
|
4926
|
+
total: Math.max(1, totalCoverageBuckets),
|
|
4927
|
+
width: 24
|
|
4928
|
+
}
|
|
4929
|
+
);
|
|
4930
|
+
let displayedCoverageBuckets = 0;
|
|
4917
4931
|
const coverageBuckets = await (0, import_timescale4.rebuildHyperliquidWhaleCoverageRows)({
|
|
4918
4932
|
fromMs,
|
|
4919
4933
|
toMs,
|
|
4920
4934
|
expectedWhales: whales.addresses.length,
|
|
4921
|
-
...identity
|
|
4935
|
+
...identity,
|
|
4936
|
+
onProgress: (progress) => {
|
|
4937
|
+
const next = Math.max(
|
|
4938
|
+
displayedCoverageBuckets,
|
|
4939
|
+
Math.min(progress.completedBuckets, coverageBar.total)
|
|
4940
|
+
);
|
|
4941
|
+
const delta = next - displayedCoverageBuckets;
|
|
4942
|
+
if (delta > 0) {
|
|
4943
|
+
coverageBar.tick(delta, {
|
|
4944
|
+
rows: progress.rows,
|
|
4945
|
+
chunk: `${progress.chunkIndex}/${progress.totalChunks}`
|
|
4946
|
+
});
|
|
4947
|
+
displayedCoverageBuckets = next;
|
|
4948
|
+
}
|
|
4949
|
+
}
|
|
4922
4950
|
});
|
|
4923
4951
|
const result = {
|
|
4924
4952
|
cached: false,
|
|
@@ -4946,6 +4974,9 @@ var backfillHyperliquidWhaleContext = async (params) => {
|
|
|
4946
4974
|
};
|
|
4947
4975
|
|
|
4948
4976
|
// src/lib/marketContextPrepare.ts
|
|
4977
|
+
var uniqueReasons = (reasons) => [
|
|
4978
|
+
...new Set(reasons)
|
|
4979
|
+
];
|
|
4949
4980
|
var shouldPrepareDerivativesContextForRun = (params) => {
|
|
4950
4981
|
if (params.universe === "tradfi") return false;
|
|
4951
4982
|
if (params.mode === "signals") {
|
|
@@ -4953,6 +4984,9 @@ var shouldPrepareDerivativesContextForRun = (params) => {
|
|
|
4953
4984
|
cacheOnly: params.cacheOnly
|
|
4954
4985
|
});
|
|
4955
4986
|
}
|
|
4987
|
+
if (params.mode === "backtest" && !params.aiEnabled && !params.mlEnabled) {
|
|
4988
|
+
return false;
|
|
4989
|
+
}
|
|
4956
4990
|
return shouldBackfillDerivativesContextForBacktest({
|
|
4957
4991
|
aiEnabled: Boolean(params.aiEnabled),
|
|
4958
4992
|
cacheOnly: params.cacheOnly,
|
|
@@ -4962,6 +4996,7 @@ var shouldPrepareDerivativesContextForRun = (params) => {
|
|
|
4962
4996
|
var shouldPrepareBinanceMarketContextForRun = (params) => {
|
|
4963
4997
|
if (params.universe === "tradfi") return false;
|
|
4964
4998
|
if (params.mode === "backtest") {
|
|
4999
|
+
if (!params.aiEnabled && !params.mlEnabled) return false;
|
|
4965
5000
|
return shouldBackfillBinanceMarketContextForBacktest({
|
|
4966
5001
|
aiEnabled: Boolean(params.aiEnabled),
|
|
4967
5002
|
cacheOnly: params.cacheOnly,
|
|
@@ -4980,6 +5015,7 @@ var shouldPrepareBinanceMarketContextForRun = (params) => {
|
|
|
4980
5015
|
var shouldPrepareCoinMarketCapContextForRun = (params) => {
|
|
4981
5016
|
if (params.universe === "tradfi") return false;
|
|
4982
5017
|
if (params.mode === "backtest") {
|
|
5018
|
+
if (!params.aiEnabled && !params.mlEnabled) return false;
|
|
4983
5019
|
return shouldBackfillCoinMarketCapContextForBacktest({
|
|
4984
5020
|
aiEnabled: Boolean(params.aiEnabled),
|
|
4985
5021
|
cacheOnly: params.cacheOnly,
|
|
@@ -4995,10 +5031,8 @@ var shouldPrepareCoinMarketCapContextForRun = (params) => {
|
|
|
4995
5031
|
cacheOnly: params.cacheOnly
|
|
4996
5032
|
});
|
|
4997
5033
|
};
|
|
4998
|
-
var shouldPrepareHyperliquidWhaleContextForRun = (params) => {
|
|
4999
|
-
const strategyRequiresContext =
|
|
5000
|
-
"HyperliquidConsensus"
|
|
5001
|
-
);
|
|
5034
|
+
var shouldPrepareHyperliquidWhaleContextForRun = (params, coreContextSources = []) => {
|
|
5035
|
+
const strategyRequiresContext = coreContextSources.includes("hyperliquidWhales");
|
|
5002
5036
|
if (params.universe === "tradfi" || params.mode === "signals" || params.cacheOnly || !params.aiEnabled && !params.mlEnabled && !strategyRequiresContext) {
|
|
5003
5037
|
return false;
|
|
5004
5038
|
}
|
|
@@ -5009,6 +5043,64 @@ var shouldPrepareHyperliquidWhaleContextForRun = (params) => {
|
|
|
5009
5043
|
if (strategyRequiresContext) return true;
|
|
5010
5044
|
return ["1", "true", "yes", "on"].includes(configured);
|
|
5011
5045
|
};
|
|
5046
|
+
var resolveCoreContextSources = async (params) => {
|
|
5047
|
+
const strategyNames = [...new Set(params.strategyNames ?? [])];
|
|
5048
|
+
if (!strategyNames.length) return [];
|
|
5049
|
+
await (0, import_registry.ensureStrategyPluginsLoaded)(params.projectRoot);
|
|
5050
|
+
return [
|
|
5051
|
+
...new Set(
|
|
5052
|
+
strategyNames.flatMap(
|
|
5053
|
+
(strategyName) => (0, import_registry.getStrategyManifest)(strategyName, params.projectRoot)?.contextRequirements?.core ?? []
|
|
5054
|
+
)
|
|
5055
|
+
)
|
|
5056
|
+
];
|
|
5057
|
+
};
|
|
5058
|
+
var resolveMarketContextRunRequirements = async (params) => {
|
|
5059
|
+
const coreContextSources = await resolveCoreContextSources(params);
|
|
5060
|
+
const paramsWithCoreDemand = (source) => coreContextSources.includes(source) ? { ...params, aiEnabled: true } : params;
|
|
5061
|
+
const isCrypto = params.universe !== "tradfi";
|
|
5062
|
+
const capturesPayload = Boolean(params.aiEnabled || params.mlEnabled);
|
|
5063
|
+
const runtimeReadsContext = params.mode !== "backtest";
|
|
5064
|
+
const reasonsFor = (source) => uniqueReasons([
|
|
5065
|
+
...coreContextSources.includes(source) ? ["core"] : [],
|
|
5066
|
+
...params.aiEnabled ? ["ai"] : [],
|
|
5067
|
+
...params.mlEnabled ? ["ml"] : [],
|
|
5068
|
+
...runtimeReadsContext ? ["runtime"] : []
|
|
5069
|
+
]);
|
|
5070
|
+
const readsStandardContext = isCrypto && (capturesPayload || runtimeReadsContext);
|
|
5071
|
+
const readsHyperliquid = isCrypto && (readsStandardContext || coreContextSources.includes("hyperliquidWhales"));
|
|
5072
|
+
return {
|
|
5073
|
+
binance: {
|
|
5074
|
+
read: readsStandardContext || coreContextSources.includes("binance"),
|
|
5075
|
+
backfill: shouldPrepareBinanceMarketContextForRun(
|
|
5076
|
+
paramsWithCoreDemand("binance")
|
|
5077
|
+
),
|
|
5078
|
+
requiredBy: reasonsFor("binance")
|
|
5079
|
+
},
|
|
5080
|
+
coinmarketcap: {
|
|
5081
|
+
read: readsStandardContext || coreContextSources.includes("coinmarketcap"),
|
|
5082
|
+
backfill: shouldPrepareCoinMarketCapContextForRun(
|
|
5083
|
+
paramsWithCoreDemand("coinmarketcap")
|
|
5084
|
+
),
|
|
5085
|
+
requiredBy: reasonsFor("coinmarketcap")
|
|
5086
|
+
},
|
|
5087
|
+
derivatives: {
|
|
5088
|
+
read: readsStandardContext || coreContextSources.includes("derivatives"),
|
|
5089
|
+
backfill: shouldPrepareDerivativesContextForRun(
|
|
5090
|
+
paramsWithCoreDemand("derivatives")
|
|
5091
|
+
),
|
|
5092
|
+
requiredBy: reasonsFor("derivatives")
|
|
5093
|
+
},
|
|
5094
|
+
hyperliquidWhales: {
|
|
5095
|
+
read: readsHyperliquid,
|
|
5096
|
+
backfill: shouldPrepareHyperliquidWhaleContextForRun(
|
|
5097
|
+
params,
|
|
5098
|
+
coreContextSources
|
|
5099
|
+
),
|
|
5100
|
+
requiredBy: reasonsFor("hyperliquidWhales")
|
|
5101
|
+
}
|
|
5102
|
+
};
|
|
5103
|
+
};
|
|
5012
5104
|
var resolveCoinMarketCapBackfillForMode = (mode) => mode === "backtest" ? backfillCoinMarketCapContextForBacktest : mode === "signals" ? backfillCoinMarketCapContextForSignals : backfillCoinMarketCapContextForReplay;
|
|
5013
5105
|
var buildCoinMarketCapBackfillParams = (params) => ({
|
|
5014
5106
|
userName: params.userName,
|
|
@@ -5037,7 +5129,15 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5037
5129
|
console.log(import_chalk4.default.gray(message));
|
|
5038
5130
|
});
|
|
5039
5131
|
const timeOperation3 = (label, operation) => timeOperation(label, operation, log);
|
|
5040
|
-
|
|
5132
|
+
const requirements = await resolveMarketContextRunRequirements(params);
|
|
5133
|
+
const readableSources = Object.entries(requirements).filter(([, requirement]) => requirement.read).map(([source]) => source);
|
|
5134
|
+
if (readableSources.length) {
|
|
5135
|
+
await timeOperation3(
|
|
5136
|
+
"market context schema ensure",
|
|
5137
|
+
() => (0, import_timescale5.ensureMarketContextSchemas)(readableSources)
|
|
5138
|
+
);
|
|
5139
|
+
}
|
|
5140
|
+
if (requirements.derivatives.backfill) {
|
|
5041
5141
|
await timeOperation3(
|
|
5042
5142
|
"derivatives context backfill",
|
|
5043
5143
|
() => (params.mode === "signals" ? backfillDerivativesContextForSignals : backfillDerivativesContextForBacktest)(
|
|
@@ -5045,7 +5145,7 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5045
5145
|
)
|
|
5046
5146
|
);
|
|
5047
5147
|
}
|
|
5048
|
-
if (
|
|
5148
|
+
if (requirements.hyperliquidWhales.backfill) {
|
|
5049
5149
|
await timeOperation3(
|
|
5050
5150
|
"hyperliquid whale context backfill",
|
|
5051
5151
|
() => backfillHyperliquidWhaleContext({
|
|
@@ -5057,13 +5157,13 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5057
5157
|
})
|
|
5058
5158
|
);
|
|
5059
5159
|
}
|
|
5060
|
-
if (
|
|
5160
|
+
if (requirements.binance.backfill) {
|
|
5061
5161
|
await timeOperation3("binance market context backfill", () => {
|
|
5062
5162
|
const backfill = params.mode === "backtest" ? backfillBinanceMarketContextForBacktest : params.mode === "signals" ? backfillBinanceMarketContextForSignals : backfillBinanceMarketContextForReplay;
|
|
5063
5163
|
return backfill(buildBinanceMarketBackfillParams(params));
|
|
5064
5164
|
});
|
|
5065
5165
|
}
|
|
5066
|
-
if (
|
|
5166
|
+
if (requirements.coinmarketcap.backfill) {
|
|
5067
5167
|
await timeOperation3(
|
|
5068
5168
|
"coinmarketcap historical context backfill",
|
|
5069
5169
|
() => resolveCoinMarketCapBackfillForMode(params.mode)(
|
|
@@ -5071,6 +5171,7 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5071
5171
|
)
|
|
5072
5172
|
);
|
|
5073
5173
|
}
|
|
5174
|
+
return requirements;
|
|
5074
5175
|
};
|
|
5075
5176
|
|
|
5076
5177
|
// src/lib/runEnvironment.ts
|
|
@@ -6198,10 +6299,27 @@ var resetRunState = () => {
|
|
|
6198
6299
|
};
|
|
6199
6300
|
|
|
6200
6301
|
// src/lib/backtest/workerPool.ts
|
|
6201
|
-
var
|
|
6302
|
+
var import_progress4 = __toESM(require("progress"));
|
|
6202
6303
|
var import_child_process = require("child_process");
|
|
6203
6304
|
var import_chalk8 = __toESM(require("chalk"));
|
|
6204
6305
|
var import_node_crypto2 = require("crypto");
|
|
6306
|
+
var DEFAULT_PG_POOL_MAX = 10;
|
|
6307
|
+
var FAST_AI_PG_CONNECTION_BUDGET = 18;
|
|
6308
|
+
var MIN_FAST_AI_WORKER_PG_POOL_MAX = 3;
|
|
6309
|
+
var resolveFastAiWorkerPgPoolMax = (testSuite, workerCount, configuredPoolMax) => {
|
|
6310
|
+
if (configuredPoolMax?.trim() || workerCount <= 1 || testSuite.length === 0 || testSuite.some((test) => !test.fast || !test.ai)) {
|
|
6311
|
+
return void 0;
|
|
6312
|
+
}
|
|
6313
|
+
return String(
|
|
6314
|
+
Math.min(
|
|
6315
|
+
DEFAULT_PG_POOL_MAX,
|
|
6316
|
+
Math.max(
|
|
6317
|
+
MIN_FAST_AI_WORKER_PG_POOL_MAX,
|
|
6318
|
+
Math.floor(FAST_AI_PG_CONNECTION_BUDGET / workerCount)
|
|
6319
|
+
)
|
|
6320
|
+
)
|
|
6321
|
+
);
|
|
6322
|
+
};
|
|
6205
6323
|
var executeBacktestWorkerPool = async ({
|
|
6206
6324
|
testSuite,
|
|
6207
6325
|
userName: userName2,
|
|
@@ -6220,6 +6338,12 @@ var executeBacktestWorkerPool = async ({
|
|
|
6220
6338
|
totalTests
|
|
6221
6339
|
}) => {
|
|
6222
6340
|
const chunks = chunkTestSuite(testSuite);
|
|
6341
|
+
const fastAiWorkerPgPoolMax = resolveFastAiWorkerPgPoolMax(
|
|
6342
|
+
testSuite,
|
|
6343
|
+
chunks.length,
|
|
6344
|
+
process.env.PG_POOL_MAX
|
|
6345
|
+
);
|
|
6346
|
+
const workerEnv = fastAiWorkerPgPoolMax ? { ...process.env, PG_POOL_MAX: fastAiWorkerPgPoolMax } : void 0;
|
|
6223
6347
|
const totalExpectedTests = Math.max(
|
|
6224
6348
|
testSuite.length,
|
|
6225
6349
|
totalTests ?? testSuite.length,
|
|
@@ -6277,7 +6401,7 @@ var executeBacktestWorkerPool = async ({
|
|
|
6277
6401
|
console.log(line);
|
|
6278
6402
|
}
|
|
6279
6403
|
console.log("");
|
|
6280
|
-
const bar = new
|
|
6404
|
+
const bar = new import_progress4.default(
|
|
6281
6405
|
":current/:total [:bar][:percent] avg :amount win :winRate trades :trades :eta(s)",
|
|
6282
6406
|
{
|
|
6283
6407
|
total: totalExpectedTests,
|
|
@@ -6305,6 +6429,7 @@ var executeBacktestWorkerPool = async ({
|
|
|
6305
6429
|
const chunkId = runId ? `${runId}-${attemptId}` : attemptId;
|
|
6306
6430
|
const chunkWithId = chunk.map((test) => ({ ...test, chunkId }));
|
|
6307
6431
|
const tester = (0, import_child_process.fork)(testerWorkerPath, [], {
|
|
6432
|
+
...workerEnv ? { env: workerEnv } : {},
|
|
6308
6433
|
execArgv: testerNeedsTsRuntime ? [
|
|
6309
6434
|
`--max-old-space-size=${workerHeapMb2}`,
|
|
6310
6435
|
"-r",
|
|
@@ -36,6 +36,7 @@ module.exports = __toCommonJS(hyperliquidWhaleBackfill_exports);
|
|
|
36
36
|
var import_args = __toESM(require("args"));
|
|
37
37
|
|
|
38
38
|
// src/lib/hyperliquidWhaleBackfill.ts
|
|
39
|
+
var import_progress = __toESM(require("progress"));
|
|
39
40
|
var import_timescale = require("@tradejs/infra/timescale");
|
|
40
41
|
var import_strategies = require("@tradejs/node/strategies");
|
|
41
42
|
|
|
@@ -410,11 +411,36 @@ var backfillHyperliquidWhaleContext = async (params) => {
|
|
|
410
411
|
toMs,
|
|
411
412
|
...identity
|
|
412
413
|
});
|
|
414
|
+
const totalCoverageBuckets = Math.ceil(
|
|
415
|
+
(toMs - fromMs) / HYPERLIQUID_WHALE_BUCKET_MS
|
|
416
|
+
);
|
|
417
|
+
const coverageBar = new import_progress.default(
|
|
418
|
+
"Hyperliquid coverage :current/:total [:bar][:percent] :eta(s) rows=:rows chunk=:chunk",
|
|
419
|
+
{
|
|
420
|
+
total: Math.max(1, totalCoverageBuckets),
|
|
421
|
+
width: 24
|
|
422
|
+
}
|
|
423
|
+
);
|
|
424
|
+
let displayedCoverageBuckets = 0;
|
|
413
425
|
const coverageBuckets = await (0, import_timescale.rebuildHyperliquidWhaleCoverageRows)({
|
|
414
426
|
fromMs,
|
|
415
427
|
toMs,
|
|
416
428
|
expectedWhales: whales.addresses.length,
|
|
417
|
-
...identity
|
|
429
|
+
...identity,
|
|
430
|
+
onProgress: (progress) => {
|
|
431
|
+
const next = Math.max(
|
|
432
|
+
displayedCoverageBuckets,
|
|
433
|
+
Math.min(progress.completedBuckets, coverageBar.total)
|
|
434
|
+
);
|
|
435
|
+
const delta = next - displayedCoverageBuckets;
|
|
436
|
+
if (delta > 0) {
|
|
437
|
+
coverageBar.tick(delta, {
|
|
438
|
+
rows: progress.rows,
|
|
439
|
+
chunk: `${progress.chunkIndex}/${progress.totalChunks}`
|
|
440
|
+
});
|
|
441
|
+
displayedCoverageBuckets = next;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
418
444
|
});
|
|
419
445
|
const result = {
|
|
420
446
|
cached: false,
|
|
@@ -39,6 +39,7 @@ var import_node_crypto = require("crypto");
|
|
|
39
39
|
var import_strategies2 = require("@tradejs/node/strategies");
|
|
40
40
|
|
|
41
41
|
// src/lib/hyperliquidWhaleBackfill.ts
|
|
42
|
+
var import_progress = __toESM(require("progress"));
|
|
42
43
|
var import_timescale = require("@tradejs/infra/timescale");
|
|
43
44
|
var import_strategies = require("@tradejs/node/strategies");
|
|
44
45
|
|
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"));
|
|
@@ -5181,6 +5183,7 @@ var backfillCoinMarketCapContextForReplay = backfillCoinMarketCapContext;
|
|
|
5181
5183
|
var backfillCoinMarketCapContextForSignals = (params) => backfillCoinMarketCapContext({ ...params, refreshStaleFearGreed: true });
|
|
5182
5184
|
|
|
5183
5185
|
// src/lib/hyperliquidWhaleBackfill.ts
|
|
5186
|
+
var import_progress3 = __toESM(require("progress"));
|
|
5184
5187
|
var import_timescale4 = require("@tradejs/infra/timescale");
|
|
5185
5188
|
var import_strategies2 = require("@tradejs/node/strategies");
|
|
5186
5189
|
|
|
@@ -5555,11 +5558,36 @@ var backfillHyperliquidWhaleContext = async (params) => {
|
|
|
5555
5558
|
toMs,
|
|
5556
5559
|
...identity
|
|
5557
5560
|
});
|
|
5561
|
+
const totalCoverageBuckets = Math.ceil(
|
|
5562
|
+
(toMs - fromMs) / HYPERLIQUID_WHALE_BUCKET_MS
|
|
5563
|
+
);
|
|
5564
|
+
const coverageBar = new import_progress3.default(
|
|
5565
|
+
"Hyperliquid coverage :current/:total [:bar][:percent] :eta(s) rows=:rows chunk=:chunk",
|
|
5566
|
+
{
|
|
5567
|
+
total: Math.max(1, totalCoverageBuckets),
|
|
5568
|
+
width: 24
|
|
5569
|
+
}
|
|
5570
|
+
);
|
|
5571
|
+
let displayedCoverageBuckets = 0;
|
|
5558
5572
|
const coverageBuckets = await (0, import_timescale4.rebuildHyperliquidWhaleCoverageRows)({
|
|
5559
5573
|
fromMs,
|
|
5560
5574
|
toMs,
|
|
5561
5575
|
expectedWhales: whales.addresses.length,
|
|
5562
|
-
...identity
|
|
5576
|
+
...identity,
|
|
5577
|
+
onProgress: (progress) => {
|
|
5578
|
+
const next = Math.max(
|
|
5579
|
+
displayedCoverageBuckets,
|
|
5580
|
+
Math.min(progress.completedBuckets, coverageBar.total)
|
|
5581
|
+
);
|
|
5582
|
+
const delta = next - displayedCoverageBuckets;
|
|
5583
|
+
if (delta > 0) {
|
|
5584
|
+
coverageBar.tick(delta, {
|
|
5585
|
+
rows: progress.rows,
|
|
5586
|
+
chunk: `${progress.chunkIndex}/${progress.totalChunks}`
|
|
5587
|
+
});
|
|
5588
|
+
displayedCoverageBuckets = next;
|
|
5589
|
+
}
|
|
5590
|
+
}
|
|
5563
5591
|
});
|
|
5564
5592
|
const result = {
|
|
5565
5593
|
cached: false,
|
|
@@ -5587,6 +5615,9 @@ var backfillHyperliquidWhaleContext = async (params) => {
|
|
|
5587
5615
|
};
|
|
5588
5616
|
|
|
5589
5617
|
// src/lib/marketContextPrepare.ts
|
|
5618
|
+
var uniqueReasons = (reasons) => [
|
|
5619
|
+
...new Set(reasons)
|
|
5620
|
+
];
|
|
5590
5621
|
var shouldPrepareDerivativesContextForRun = (params) => {
|
|
5591
5622
|
if (params.universe === "tradfi") return false;
|
|
5592
5623
|
if (params.mode === "signals") {
|
|
@@ -5594,6 +5625,9 @@ var shouldPrepareDerivativesContextForRun = (params) => {
|
|
|
5594
5625
|
cacheOnly: params.cacheOnly
|
|
5595
5626
|
});
|
|
5596
5627
|
}
|
|
5628
|
+
if (params.mode === "backtest" && !params.aiEnabled && !params.mlEnabled) {
|
|
5629
|
+
return false;
|
|
5630
|
+
}
|
|
5597
5631
|
return shouldBackfillDerivativesContextForBacktest({
|
|
5598
5632
|
aiEnabled: Boolean(params.aiEnabled),
|
|
5599
5633
|
cacheOnly: params.cacheOnly,
|
|
@@ -5603,6 +5637,7 @@ var shouldPrepareDerivativesContextForRun = (params) => {
|
|
|
5603
5637
|
var shouldPrepareBinanceMarketContextForRun = (params) => {
|
|
5604
5638
|
if (params.universe === "tradfi") return false;
|
|
5605
5639
|
if (params.mode === "backtest") {
|
|
5640
|
+
if (!params.aiEnabled && !params.mlEnabled) return false;
|
|
5606
5641
|
return shouldBackfillBinanceMarketContextForBacktest({
|
|
5607
5642
|
aiEnabled: Boolean(params.aiEnabled),
|
|
5608
5643
|
cacheOnly: params.cacheOnly,
|
|
@@ -5621,6 +5656,7 @@ var shouldPrepareBinanceMarketContextForRun = (params) => {
|
|
|
5621
5656
|
var shouldPrepareCoinMarketCapContextForRun = (params) => {
|
|
5622
5657
|
if (params.universe === "tradfi") return false;
|
|
5623
5658
|
if (params.mode === "backtest") {
|
|
5659
|
+
if (!params.aiEnabled && !params.mlEnabled) return false;
|
|
5624
5660
|
return shouldBackfillCoinMarketCapContextForBacktest({
|
|
5625
5661
|
aiEnabled: Boolean(params.aiEnabled),
|
|
5626
5662
|
cacheOnly: params.cacheOnly,
|
|
@@ -5636,10 +5672,8 @@ var shouldPrepareCoinMarketCapContextForRun = (params) => {
|
|
|
5636
5672
|
cacheOnly: params.cacheOnly
|
|
5637
5673
|
});
|
|
5638
5674
|
};
|
|
5639
|
-
var shouldPrepareHyperliquidWhaleContextForRun = (params) => {
|
|
5640
|
-
const strategyRequiresContext =
|
|
5641
|
-
"HyperliquidConsensus"
|
|
5642
|
-
);
|
|
5675
|
+
var shouldPrepareHyperliquidWhaleContextForRun = (params, coreContextSources = []) => {
|
|
5676
|
+
const strategyRequiresContext = coreContextSources.includes("hyperliquidWhales");
|
|
5643
5677
|
if (params.universe === "tradfi" || params.mode === "signals" || params.cacheOnly || !params.aiEnabled && !params.mlEnabled && !strategyRequiresContext) {
|
|
5644
5678
|
return false;
|
|
5645
5679
|
}
|
|
@@ -5650,6 +5684,64 @@ var shouldPrepareHyperliquidWhaleContextForRun = (params) => {
|
|
|
5650
5684
|
if (strategyRequiresContext) return true;
|
|
5651
5685
|
return ["1", "true", "yes", "on"].includes(configured);
|
|
5652
5686
|
};
|
|
5687
|
+
var resolveCoreContextSources = async (params) => {
|
|
5688
|
+
const strategyNames = [...new Set(params.strategyNames ?? [])];
|
|
5689
|
+
if (!strategyNames.length) return [];
|
|
5690
|
+
await (0, import_registry.ensureStrategyPluginsLoaded)(params.projectRoot);
|
|
5691
|
+
return [
|
|
5692
|
+
...new Set(
|
|
5693
|
+
strategyNames.flatMap(
|
|
5694
|
+
(strategyName) => (0, import_registry.getStrategyManifest)(strategyName, params.projectRoot)?.contextRequirements?.core ?? []
|
|
5695
|
+
)
|
|
5696
|
+
)
|
|
5697
|
+
];
|
|
5698
|
+
};
|
|
5699
|
+
var resolveMarketContextRunRequirements = async (params) => {
|
|
5700
|
+
const coreContextSources = await resolveCoreContextSources(params);
|
|
5701
|
+
const paramsWithCoreDemand = (source) => coreContextSources.includes(source) ? { ...params, aiEnabled: true } : params;
|
|
5702
|
+
const isCrypto = params.universe !== "tradfi";
|
|
5703
|
+
const capturesPayload = Boolean(params.aiEnabled || params.mlEnabled);
|
|
5704
|
+
const runtimeReadsContext = params.mode !== "backtest";
|
|
5705
|
+
const reasonsFor = (source) => uniqueReasons([
|
|
5706
|
+
...coreContextSources.includes(source) ? ["core"] : [],
|
|
5707
|
+
...params.aiEnabled ? ["ai"] : [],
|
|
5708
|
+
...params.mlEnabled ? ["ml"] : [],
|
|
5709
|
+
...runtimeReadsContext ? ["runtime"] : []
|
|
5710
|
+
]);
|
|
5711
|
+
const readsStandardContext = isCrypto && (capturesPayload || runtimeReadsContext);
|
|
5712
|
+
const readsHyperliquid = isCrypto && (readsStandardContext || coreContextSources.includes("hyperliquidWhales"));
|
|
5713
|
+
return {
|
|
5714
|
+
binance: {
|
|
5715
|
+
read: readsStandardContext || coreContextSources.includes("binance"),
|
|
5716
|
+
backfill: shouldPrepareBinanceMarketContextForRun(
|
|
5717
|
+
paramsWithCoreDemand("binance")
|
|
5718
|
+
),
|
|
5719
|
+
requiredBy: reasonsFor("binance")
|
|
5720
|
+
},
|
|
5721
|
+
coinmarketcap: {
|
|
5722
|
+
read: readsStandardContext || coreContextSources.includes("coinmarketcap"),
|
|
5723
|
+
backfill: shouldPrepareCoinMarketCapContextForRun(
|
|
5724
|
+
paramsWithCoreDemand("coinmarketcap")
|
|
5725
|
+
),
|
|
5726
|
+
requiredBy: reasonsFor("coinmarketcap")
|
|
5727
|
+
},
|
|
5728
|
+
derivatives: {
|
|
5729
|
+
read: readsStandardContext || coreContextSources.includes("derivatives"),
|
|
5730
|
+
backfill: shouldPrepareDerivativesContextForRun(
|
|
5731
|
+
paramsWithCoreDemand("derivatives")
|
|
5732
|
+
),
|
|
5733
|
+
requiredBy: reasonsFor("derivatives")
|
|
5734
|
+
},
|
|
5735
|
+
hyperliquidWhales: {
|
|
5736
|
+
read: readsHyperliquid,
|
|
5737
|
+
backfill: shouldPrepareHyperliquidWhaleContextForRun(
|
|
5738
|
+
params,
|
|
5739
|
+
coreContextSources
|
|
5740
|
+
),
|
|
5741
|
+
requiredBy: reasonsFor("hyperliquidWhales")
|
|
5742
|
+
}
|
|
5743
|
+
};
|
|
5744
|
+
};
|
|
5653
5745
|
var resolveCoinMarketCapBackfillForMode = (mode) => mode === "backtest" ? backfillCoinMarketCapContextForBacktest : mode === "signals" ? backfillCoinMarketCapContextForSignals : backfillCoinMarketCapContextForReplay;
|
|
5654
5746
|
var buildCoinMarketCapBackfillParams = (params) => ({
|
|
5655
5747
|
userName: params.userName,
|
|
@@ -5678,7 +5770,15 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5678
5770
|
console.log(import_chalk7.default.gray(message));
|
|
5679
5771
|
});
|
|
5680
5772
|
const timeOperation3 = (label, operation) => timeOperation(label, operation, log);
|
|
5681
|
-
|
|
5773
|
+
const requirements = await resolveMarketContextRunRequirements(params);
|
|
5774
|
+
const readableSources = Object.entries(requirements).filter(([, requirement]) => requirement.read).map(([source]) => source);
|
|
5775
|
+
if (readableSources.length) {
|
|
5776
|
+
await timeOperation3(
|
|
5777
|
+
"market context schema ensure",
|
|
5778
|
+
() => (0, import_timescale5.ensureMarketContextSchemas)(readableSources)
|
|
5779
|
+
);
|
|
5780
|
+
}
|
|
5781
|
+
if (requirements.derivatives.backfill) {
|
|
5682
5782
|
await timeOperation3(
|
|
5683
5783
|
"derivatives context backfill",
|
|
5684
5784
|
() => (params.mode === "signals" ? backfillDerivativesContextForSignals : backfillDerivativesContextForBacktest)(
|
|
@@ -5686,7 +5786,7 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5686
5786
|
)
|
|
5687
5787
|
);
|
|
5688
5788
|
}
|
|
5689
|
-
if (
|
|
5789
|
+
if (requirements.hyperliquidWhales.backfill) {
|
|
5690
5790
|
await timeOperation3(
|
|
5691
5791
|
"hyperliquid whale context backfill",
|
|
5692
5792
|
() => backfillHyperliquidWhaleContext({
|
|
@@ -5698,13 +5798,13 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5698
5798
|
})
|
|
5699
5799
|
);
|
|
5700
5800
|
}
|
|
5701
|
-
if (
|
|
5801
|
+
if (requirements.binance.backfill) {
|
|
5702
5802
|
await timeOperation3("binance market context backfill", () => {
|
|
5703
5803
|
const backfill = params.mode === "backtest" ? backfillBinanceMarketContextForBacktest : params.mode === "signals" ? backfillBinanceMarketContextForSignals : backfillBinanceMarketContextForReplay;
|
|
5704
5804
|
return backfill(buildBinanceMarketBackfillParams(params));
|
|
5705
5805
|
});
|
|
5706
5806
|
}
|
|
5707
|
-
if (
|
|
5807
|
+
if (requirements.coinmarketcap.backfill) {
|
|
5708
5808
|
await timeOperation3(
|
|
5709
5809
|
"coinmarketcap historical context backfill",
|
|
5710
5810
|
() => resolveCoinMarketCapBackfillForMode(params.mode)(
|
|
@@ -5712,6 +5812,7 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5712
5812
|
)
|
|
5713
5813
|
);
|
|
5714
5814
|
}
|
|
5815
|
+
return requirements;
|
|
5715
5816
|
};
|
|
5716
5817
|
|
|
5717
5818
|
// src/lib/backtest/runState.ts
|
|
@@ -5984,7 +6085,7 @@ var compactReplaySignal = (signal) => {
|
|
|
5984
6085
|
|
|
5985
6086
|
// src/lib/replay/historicalSignalsReplay.ts
|
|
5986
6087
|
var import_chalk9 = __toESM(require("chalk"));
|
|
5987
|
-
var
|
|
6088
|
+
var import_progress4 = __toESM(require("progress"));
|
|
5988
6089
|
var import_backtest = require("@tradejs/core/backtest");
|
|
5989
6090
|
var import_strategies4 = require("@tradejs/core/strategies");
|
|
5990
6091
|
var import_time3 = require("@tradejs/core/time");
|
|
@@ -6868,7 +6969,7 @@ var runHistoricalSignalsReplay = async ({
|
|
|
6868
6969
|
const sharedReplayKeyPrefixes = [];
|
|
6869
6970
|
let preparedSymbols = 0;
|
|
6870
6971
|
let skippedSymbols = 0;
|
|
6871
|
-
const prepareBar = new
|
|
6972
|
+
const prepareBar = new import_progress4.default(
|
|
6872
6973
|
"prepare :current/:total [:bar][:percent] skipped=:skipped :etas(s) :symbol",
|
|
6873
6974
|
{
|
|
6874
6975
|
total: preparedRun.tickers.length,
|
|
@@ -6990,7 +7091,7 @@ var runHistoricalSignalsReplay = async ({
|
|
|
6990
7091
|
interval
|
|
6991
7092
|
});
|
|
6992
7093
|
let abortedCycles = 0;
|
|
6993
|
-
const cycleBar = new
|
|
7094
|
+
const cycleBar = new import_progress4.default(
|
|
6994
7095
|
"cycles :current/:total [:bar][:percent] sig=:signals abort=:aborted :etas(s) :ts",
|
|
6995
7096
|
{
|
|
6996
7097
|
total: orderedTimestamps.length,
|
|
@@ -7960,6 +8061,15 @@ var syncRuntimeTrades = async ({
|
|
|
7960
8061
|
nextTrade,
|
|
7961
8062
|
{ expire: import_constants5.TTL_1M }
|
|
7962
8063
|
),
|
|
8064
|
+
(0, import_redis5.setHashJsonField)(
|
|
8065
|
+
import_redis5.redisKeys.runtimeClosedTradeBucket(
|
|
8066
|
+
userName,
|
|
8067
|
+
(0, import_time5.getRuntimeStorageDayKey)(nextTrade.exitTimestamp)
|
|
8068
|
+
),
|
|
8069
|
+
trade.orderId,
|
|
8070
|
+
nextTrade,
|
|
8071
|
+
{ expire: import_constants5.TTL_1M }
|
|
8072
|
+
),
|
|
7963
8073
|
...isCurrentActiveTrade ? [(0, import_redis5.delKey)(activeTradeKey)] : []
|
|
7964
8074
|
]);
|
|
7965
8075
|
syncedTrades.push(nextTrade);
|