@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/cli.js
CHANGED
|
@@ -3086,10 +3086,10 @@ var init_io = __esm({
|
|
|
3086
3086
|
sha256Text = (value) => (0, import_node_crypto4.createHash)("sha256").update(value).digest("hex");
|
|
3087
3087
|
sha256Json = (value) => sha256Text(canonicalJson(value));
|
|
3088
3088
|
sha256File = async (filePath) => {
|
|
3089
|
-
const
|
|
3089
|
+
const hash2 = (0, import_node_crypto4.createHash)("sha256");
|
|
3090
3090
|
const input = (0, import_node_fs2.createReadStream)(filePath);
|
|
3091
|
-
for await (const chunk of input)
|
|
3092
|
-
return
|
|
3091
|
+
for await (const chunk of input) hash2.update(chunk);
|
|
3092
|
+
return hash2.digest("hex");
|
|
3093
3093
|
};
|
|
3094
3094
|
assertFinite = (value, name) => {
|
|
3095
3095
|
assert(typeof value === "number" && Number.isFinite(value), name);
|
|
@@ -5436,15 +5436,15 @@ var init_searchEngine = __esm({
|
|
|
5436
5436
|
};
|
|
5437
5437
|
};
|
|
5438
5438
|
hashMask = (mask) => {
|
|
5439
|
-
let
|
|
5439
|
+
let hash2 = 2166136261;
|
|
5440
5440
|
for (let index = 0; index < mask.length; index += 1) {
|
|
5441
5441
|
if (mask[index] !== 1) {
|
|
5442
5442
|
continue;
|
|
5443
5443
|
}
|
|
5444
|
-
|
|
5445
|
-
|
|
5444
|
+
hash2 ^= index + 1;
|
|
5445
|
+
hash2 = Math.imul(hash2, 16777619);
|
|
5446
5446
|
}
|
|
5447
|
-
return (
|
|
5447
|
+
return (hash2 >>> 0).toString(36);
|
|
5448
5448
|
};
|
|
5449
5449
|
isBetterRepresentativePocket = (candidate, existing, compare2) => candidate.depth < existing.depth || candidate.depth === existing.depth && candidate.condition.length < existing.condition.length || candidate.depth === existing.depth && candidate.condition.length === existing.condition.length && compare2(candidate, existing) < 0;
|
|
5450
5450
|
estimateCombinationCount = (poolSize, maxDepth, maxCombinations) => {
|
|
@@ -9483,18 +9483,18 @@ var init_strategyGateFingerprint = __esm({
|
|
|
9483
9483
|
const sourceEntries = candidates.filter(
|
|
9484
9484
|
(entry) => entry != null
|
|
9485
9485
|
);
|
|
9486
|
-
const
|
|
9487
|
-
|
|
9486
|
+
const hash2 = (0, import_node_crypto5.createHash)("sha256");
|
|
9487
|
+
hash2.update(strategyName);
|
|
9488
9488
|
if (sourceEntries.length) {
|
|
9489
9489
|
for (const entry of sourceEntries) {
|
|
9490
|
-
|
|
9491
|
-
|
|
9490
|
+
hash2.update(entry.specifier);
|
|
9491
|
+
hash2.update(entry.content);
|
|
9492
9492
|
}
|
|
9493
9493
|
} else {
|
|
9494
|
-
|
|
9494
|
+
hash2.update(gitSha ?? "unknown-git-sha");
|
|
9495
9495
|
}
|
|
9496
9496
|
return {
|
|
9497
|
-
gateFingerprint:
|
|
9497
|
+
gateFingerprint: hash2.digest("hex").slice(0, 16),
|
|
9498
9498
|
gateFingerprintFiles: sourceEntries.map((entry) => entry.specifier)
|
|
9499
9499
|
};
|
|
9500
9500
|
};
|
|
@@ -11907,13 +11907,12 @@ var init_binanceMarketContextBackfill = __esm({
|
|
|
11907
11907
|
};
|
|
11908
11908
|
intervalToMarketFeatureInterval = (interval4) => {
|
|
11909
11909
|
const normalized = String(interval4).trim().toLowerCase();
|
|
11910
|
-
if (normalized === "1" || normalized === "1m") return
|
|
11910
|
+
if (normalized === "1" || normalized === "1m") return null;
|
|
11911
11911
|
if (normalized === "5" || normalized === "5m") return "5m";
|
|
11912
11912
|
if (normalized === "60" || normalized === "1h") return "1h";
|
|
11913
11913
|
return "15m";
|
|
11914
11914
|
};
|
|
11915
11915
|
marketIntervalToConnectorInterval = (interval4) => {
|
|
11916
|
-
if (interval4 === "1m") return "1";
|
|
11917
11916
|
if (interval4 === "5m") return "5";
|
|
11918
11917
|
if (interval4 === "1h") return "60";
|
|
11919
11918
|
return "15";
|
|
@@ -12078,6 +12077,7 @@ var init_binanceMarketContextBackfill = __esm({
|
|
|
12078
12077
|
return skippedBackfillResult();
|
|
12079
12078
|
}
|
|
12080
12079
|
const interval4 = intervalToMarketFeatureInterval(params.interval);
|
|
12080
|
+
if (interval4 === null) return skippedBackfillResult();
|
|
12081
12081
|
const intervalMs = MARKET_FEATURE_INTERVAL_MS[interval4];
|
|
12082
12082
|
const { breadthStartMs, tradeFlowStartMs, endMs } = resolveBinanceMarketContextBackfillWindow(params);
|
|
12083
12083
|
if (endMs <= Math.min(breadthStartMs, tradeFlowStartMs)) {
|
|
@@ -12367,6 +12367,18 @@ var init_binanceMarketContextBackfill = __esm({
|
|
|
12367
12367
|
});
|
|
12368
12368
|
|
|
12369
12369
|
// src/lib/derivativesContextBackfill.ts
|
|
12370
|
+
async function resolveCoinalyzeBackfillMarket(userName3, symbol) {
|
|
12371
|
+
const apiKey = await getCoinalyzeApiKey(userName3);
|
|
12372
|
+
if (!apiKey) throw new Error("Missing Coinalyze API key.");
|
|
12373
|
+
const markets = (await fetchCoinalyzeMarkets(apiKey)).filter(
|
|
12374
|
+
(market) => market.quote_asset?.toUpperCase() === "USDT" && market.is_perpetual
|
|
12375
|
+
);
|
|
12376
|
+
const priority = parseList(
|
|
12377
|
+
process.env.COINALYZE_EXCHANGE_PRIORITY || process.env.DERIVATIVES_CONTEXT_EXCHANGE_PRIORITY || "A,6,0"
|
|
12378
|
+
);
|
|
12379
|
+
const { matches: matches2 } = buildMatches([symbol], markets, priority);
|
|
12380
|
+
return { apiKey, marketSymbol: matches2[0]?.marketSymbol };
|
|
12381
|
+
}
|
|
12370
12382
|
var import_chalk7, import_progress5, import_async, import_constants5, import_indicators, import_derivatives, import_client2, import_userSettings3, HOUR_MS, DAY_MS7, DEFAULT_LOOKBACK_HOURS, SOURCE_INTERVALS, coinalyzeIntervalMap, derivativesIntervalMs, lastRequestTs, asInt2, parseList, parseBooleanFlag, normalizeSymbols, isDerivativesTargetContextEnabled, resolveDerivativesContextBackfillSymbols, chunkArray, isBacktestDerivativesContextEnabled, isSignalsDerivativesContextEnabled, isDerivativesContextBackfillEnabled, shouldBackfillDerivativesContextForBacktest, shouldBackfillDerivativesContextForSignals, resolveDerivativesContextIntervals, resolveDerivativesContextLookbackMs, resolveDerivativesContextBackfillWindow, resolveDerivativesContextIntervalBackfillWindow, resolveDerivativesContextMissingFetchFromMs, resolveDerivativesContextFetchFromMs, resolveDerivativesContextRequiredFetchFromMs, countBackfillWindows, buildBackfillWindows, hasDerivativesWindowCoverage, resolveDerivativesContextMissingCoverageFetchFromMs, groupDerivativesContextMissingFetchRanges, getMissingClosedDerivativesSymbols, coverageKey, extendEdges, getCoinalyzeApiKey, getCoinalyzeBaseUrl, getRequestDelayMs, getRequestTimeoutMs, networkErrorCodes, getNestedErrorValue, getCoinalyzeErrorCause, isRetryableCoinalyzeFetchError, formatCoinalyzeRequestError, fetchJsonWithRateLimit, fetchCoinalyzeMarkets, selectBestMarket, buildMatches, normalizeMetricPoint, toSeriesMap, fetchMetricBatch, skippedBackfillResult2, backfillDerivativesContext, backfillDerivativesContextForBacktest, backfillDerivativesContextForSignals;
|
|
12371
12383
|
var init_derivativesContextBackfill = __esm({
|
|
12372
12384
|
"src/lib/derivativesContextBackfill.ts"() {
|
|
@@ -13670,7 +13682,7 @@ var init_coinMarketCapContextBackfill = __esm({
|
|
|
13670
13682
|
};
|
|
13671
13683
|
fetchCoinMarketCapIndexRows = async (params) => {
|
|
13672
13684
|
const rows = [];
|
|
13673
|
-
const maxChunkDays =
|
|
13685
|
+
const maxChunkDays = 4;
|
|
13674
13686
|
const totalChunks = Math.max(
|
|
13675
13687
|
1,
|
|
13676
13688
|
Math.ceil(
|
|
@@ -14107,11 +14119,27 @@ var init_coinMarketCapContextBackfill = __esm({
|
|
|
14107
14119
|
toMs
|
|
14108
14120
|
})
|
|
14109
14121
|
);
|
|
14110
|
-
const
|
|
14111
|
-
const
|
|
14112
|
-
|
|
14113
|
-
|
|
14114
|
-
|
|
14122
|
+
const ready = (dataset, existing) => params.repairDataset ? params.repairDataset !== dataset : existing;
|
|
14123
|
+
const globalDailyReady = ready(
|
|
14124
|
+
"cmc-global-1d",
|
|
14125
|
+
globalDailyCached || globalDailyBackfillCovered
|
|
14126
|
+
);
|
|
14127
|
+
const referencesDailyReady = ready(
|
|
14128
|
+
"cmc-reference_asset-1d",
|
|
14129
|
+
referencesDailyCached || referencesDailyBackfillCovered
|
|
14130
|
+
);
|
|
14131
|
+
const exchangeLiquidityReady = ready(
|
|
14132
|
+
"cmc-exchange_liquidity-1d",
|
|
14133
|
+
exchangeLiquidityCached || !exchangeLiquidityEnabled || exchangeLiquidityBackfillCovered
|
|
14134
|
+
);
|
|
14135
|
+
const fearGreedReady = ready(
|
|
14136
|
+
"cmc-fear_greed-1d",
|
|
14137
|
+
fearGreedCached || !fearGreedEnabled || fearGreedBackfillCovered
|
|
14138
|
+
);
|
|
14139
|
+
const indexesReady = ready(
|
|
14140
|
+
"cmc-index-1d",
|
|
14141
|
+
indexesCached || indexesBackfillCovered
|
|
14142
|
+
);
|
|
14115
14143
|
let globalStatus = resolveBackfillStatus({
|
|
14116
14144
|
cached: globalDailyCached,
|
|
14117
14145
|
covered: globalDailyBackfillCovered
|
|
@@ -16343,7 +16371,9 @@ var init_workerPool = __esm({
|
|
|
16343
16371
|
chunkTestSuite,
|
|
16344
16372
|
getProgressSnapshot,
|
|
16345
16373
|
initialCompletedTests = 0,
|
|
16346
|
-
totalTests
|
|
16374
|
+
totalTests,
|
|
16375
|
+
onProgress,
|
|
16376
|
+
onIncomplete
|
|
16347
16377
|
}) => {
|
|
16348
16378
|
const chunks = chunkTestSuite(testSuite);
|
|
16349
16379
|
const fastAiWorkerPgPoolMax = resolveFastAiWorkerPgPoolMax(
|
|
@@ -16359,7 +16389,9 @@ var init_workerPool = __esm({
|
|
|
16359
16389
|
);
|
|
16360
16390
|
let completedTests = initialCompletedTests;
|
|
16361
16391
|
let renderedTests = 0;
|
|
16392
|
+
let pendingResults = 0;
|
|
16362
16393
|
let isFinishing = false;
|
|
16394
|
+
let isInterrupted = false;
|
|
16363
16395
|
let signalHandlersRemoved = false;
|
|
16364
16396
|
const workers = /* @__PURE__ */ new Set();
|
|
16365
16397
|
const stopWorkers = () => {
|
|
@@ -16370,6 +16402,7 @@ var init_workerPool = __esm({
|
|
|
16370
16402
|
}
|
|
16371
16403
|
};
|
|
16372
16404
|
const handleInterrupt = (signal, exitCode) => {
|
|
16405
|
+
isInterrupted = true;
|
|
16373
16406
|
stopWorkers();
|
|
16374
16407
|
void Promise.resolve(onInterrupt?.(signal)).catch((error) => {
|
|
16375
16408
|
console.error(
|
|
@@ -16390,15 +16423,16 @@ var init_workerPool = __esm({
|
|
|
16390
16423
|
process.removeListener("SIGTERM", handleSigterm);
|
|
16391
16424
|
};
|
|
16392
16425
|
const maybeFinish = async () => {
|
|
16393
|
-
if (isFinishing) {
|
|
16394
|
-
return;
|
|
16395
|
-
}
|
|
16396
|
-
if (completedTests !== totalExpectedTests || workers.size > 0) {
|
|
16426
|
+
if (isFinishing || isInterrupted || workers.size > 0 || pendingResults > 0) {
|
|
16397
16427
|
return;
|
|
16398
16428
|
}
|
|
16399
16429
|
isFinishing = true;
|
|
16400
16430
|
try {
|
|
16401
|
-
|
|
16431
|
+
if (completedTests === totalExpectedTests) {
|
|
16432
|
+
await onFinish();
|
|
16433
|
+
} else {
|
|
16434
|
+
await onIncomplete?.();
|
|
16435
|
+
}
|
|
16402
16436
|
} finally {
|
|
16403
16437
|
cleanupSignalHandlers();
|
|
16404
16438
|
}
|
|
@@ -16457,14 +16491,22 @@ var init_workerPool = __esm({
|
|
|
16457
16491
|
return;
|
|
16458
16492
|
}
|
|
16459
16493
|
completedTests++;
|
|
16460
|
-
|
|
16461
|
-
|
|
16462
|
-
|
|
16494
|
+
onProgress?.(completedTests);
|
|
16495
|
+
pendingResults++;
|
|
16496
|
+
try {
|
|
16497
|
+
await onMessage(msg);
|
|
16498
|
+
if (completedTests % progressStep2 === 0 || completedTests === totalExpectedTests) {
|
|
16499
|
+
tickProgress();
|
|
16500
|
+
}
|
|
16501
|
+
} finally {
|
|
16502
|
+
pendingResults--;
|
|
16463
16503
|
}
|
|
16504
|
+
await maybeFinish();
|
|
16464
16505
|
});
|
|
16465
16506
|
tester.on("error", (err) => {
|
|
16466
16507
|
workers.delete(tester);
|
|
16467
16508
|
onWorkerError(err?.message ?? String(err));
|
|
16509
|
+
void maybeFinish();
|
|
16468
16510
|
});
|
|
16469
16511
|
tester.on("exit", (code) => {
|
|
16470
16512
|
workers.delete(tester);
|
|
@@ -16876,7 +16918,9 @@ var init_runnerCore = __esm({
|
|
|
16876
16918
|
onFinish,
|
|
16877
16919
|
initialCompletedTests = 0,
|
|
16878
16920
|
totalTests,
|
|
16879
|
-
backtestRunId
|
|
16921
|
+
backtestRunId,
|
|
16922
|
+
onProgress,
|
|
16923
|
+
onIncomplete
|
|
16880
16924
|
}) => {
|
|
16881
16925
|
markTestsStarted();
|
|
16882
16926
|
const { testerWorkerPath, testerNeedsTsRuntime } = resolveTesterWorker();
|
|
@@ -16900,6 +16944,8 @@ var init_runnerCore = __esm({
|
|
|
16900
16944
|
chunkTestSuite: (suite) => chunkTestSuiteBySymbol(suite, effectiveParallel),
|
|
16901
16945
|
initialCompletedTests,
|
|
16902
16946
|
totalTests,
|
|
16947
|
+
onProgress,
|
|
16948
|
+
onIncomplete,
|
|
16903
16949
|
onInterrupt,
|
|
16904
16950
|
onMessage: async (msg) => {
|
|
16905
16951
|
if (msg.error) {
|
|
@@ -16955,10 +17001,116 @@ var init_runnerCore = __esm({
|
|
|
16955
17001
|
}
|
|
16956
17002
|
});
|
|
16957
17003
|
|
|
17004
|
+
// src/lib/backtest/observeRun.ts
|
|
17005
|
+
var import_constants9, import_redis7, import_logger, HEARTBEAT_MS, ACTIVE_TTL_SECONDS, LINKED_RUN_TTL_SECONDS, RESEARCH_STUDY, MAX_VALUES_PER_PARAMETER, MAX_VALUE_LENGTH, summarizeBacktestParameters, observeBacktestRun;
|
|
17006
|
+
var init_observeRun = __esm({
|
|
17007
|
+
"src/lib/backtest/observeRun.ts"() {
|
|
17008
|
+
"use strict";
|
|
17009
|
+
import_constants9 = require("@tradejs/core/constants");
|
|
17010
|
+
import_redis7 = require("@tradejs/infra/redis");
|
|
17011
|
+
import_logger = require("@tradejs/infra/logger");
|
|
17012
|
+
HEARTBEAT_MS = 2e3;
|
|
17013
|
+
ACTIVE_TTL_SECONDS = 30;
|
|
17014
|
+
LINKED_RUN_TTL_SECONDS = 30 * 24 * import_constants9.TTL_1H;
|
|
17015
|
+
RESEARCH_STUDY = /^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}\/\d{4}-\d{2}-\d{2}-[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$/;
|
|
17016
|
+
MAX_VALUES_PER_PARAMETER = 12;
|
|
17017
|
+
MAX_VALUE_LENGTH = 500;
|
|
17018
|
+
summarizeBacktestParameters = (tests) => {
|
|
17019
|
+
const parameters = /* @__PURE__ */ new Map();
|
|
17020
|
+
for (const test of tests) {
|
|
17021
|
+
for (const [name, value] of Object.entries(test.strategyConfig)) {
|
|
17022
|
+
const serialized = JSON.stringify(value);
|
|
17023
|
+
if (serialized === void 0) continue;
|
|
17024
|
+
const parameter = parameters.get(name) ?? {
|
|
17025
|
+
values: /* @__PURE__ */ new Set(),
|
|
17026
|
+
truncated: false
|
|
17027
|
+
};
|
|
17028
|
+
parameters.set(name, parameter);
|
|
17029
|
+
if (parameter.values.has(serialized)) continue;
|
|
17030
|
+
if (parameter.values.size === MAX_VALUES_PER_PARAMETER || serialized.length > MAX_VALUE_LENGTH) {
|
|
17031
|
+
parameter.truncated = true;
|
|
17032
|
+
} else {
|
|
17033
|
+
parameter.values.add(serialized);
|
|
17034
|
+
}
|
|
17035
|
+
}
|
|
17036
|
+
}
|
|
17037
|
+
return [...parameters].map(([name, { values, truncated }]) => ({
|
|
17038
|
+
name,
|
|
17039
|
+
values: [...values],
|
|
17040
|
+
truncated
|
|
17041
|
+
}));
|
|
17042
|
+
};
|
|
17043
|
+
observeBacktestRun = async (manifest, initialCompleted, parallel) => {
|
|
17044
|
+
if (process.env.TRADEJS_BACKTEST_WEB_JOB === "1") return;
|
|
17045
|
+
const researchStudy = process.env.TRADEJS_RESEARCH_STUDY?.trim();
|
|
17046
|
+
const linkedStudy = researchStudy && RESEARCH_STUDY.test(researchStudy) ? researchStudy : void 0;
|
|
17047
|
+
if (researchStudy && !linkedStudy) {
|
|
17048
|
+
import_logger.logger.warn(
|
|
17049
|
+
"invalid TRADEJS_RESEARCH_STUDY; expected Strategy/YYYY-MM-DD-slug"
|
|
17050
|
+
);
|
|
17051
|
+
}
|
|
17052
|
+
const { testSuite } = manifest;
|
|
17053
|
+
const firstTest = testSuite[0];
|
|
17054
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
17055
|
+
const run = {
|
|
17056
|
+
id: manifest.runId,
|
|
17057
|
+
...linkedStudy && { researchStudy: linkedStudy },
|
|
17058
|
+
userName: manifest.userName,
|
|
17059
|
+
strategyName: firstTest.strategyName,
|
|
17060
|
+
configId: manifest.config,
|
|
17061
|
+
connector: manifest.connectorName,
|
|
17062
|
+
interval: manifest.interval,
|
|
17063
|
+
startTime: manifest.window.start,
|
|
17064
|
+
endTime: manifest.window.end,
|
|
17065
|
+
symbols: [...new Set(testSuite.map((test) => test.symbol))],
|
|
17066
|
+
settings: {
|
|
17067
|
+
...manifest.flags,
|
|
17068
|
+
parallel,
|
|
17069
|
+
...firstTest.executionCosts && {
|
|
17070
|
+
executionCosts: JSON.stringify(firstTest.executionCosts)
|
|
17071
|
+
}
|
|
17072
|
+
},
|
|
17073
|
+
parameters: summarizeBacktestParameters(testSuite),
|
|
17074
|
+
status: "running",
|
|
17075
|
+
completed: initialCompleted,
|
|
17076
|
+
total: testSuite.length,
|
|
17077
|
+
startedAt,
|
|
17078
|
+
updatedAt: startedAt
|
|
17079
|
+
};
|
|
17080
|
+
const save = async (expire) => {
|
|
17081
|
+
run.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
17082
|
+
try {
|
|
17083
|
+
await import_redis7.cliBacktestRunStorage.put(run, expire);
|
|
17084
|
+
} catch (error) {
|
|
17085
|
+
import_logger.logger.warn("failed to publish CLI backtest progress: %s", String(error));
|
|
17086
|
+
}
|
|
17087
|
+
};
|
|
17088
|
+
await save(ACTIVE_TTL_SECONDS);
|
|
17089
|
+
let pending;
|
|
17090
|
+
const timer = setInterval(() => {
|
|
17091
|
+
pending ??= save(ACTIVE_TTL_SECONDS).finally(() => {
|
|
17092
|
+
pending = void 0;
|
|
17093
|
+
});
|
|
17094
|
+
}, HEARTBEAT_MS).unref();
|
|
17095
|
+
return {
|
|
17096
|
+
progress: (completed) => {
|
|
17097
|
+
run.completed = completed;
|
|
17098
|
+
},
|
|
17099
|
+
finish: async (status) => {
|
|
17100
|
+
clearInterval(timer);
|
|
17101
|
+
await pending;
|
|
17102
|
+
run.status = status;
|
|
17103
|
+
await save(linkedStudy ? LINKED_RUN_TTL_SECONDS : import_constants9.TTL_1H);
|
|
17104
|
+
}
|
|
17105
|
+
};
|
|
17106
|
+
};
|
|
17107
|
+
}
|
|
17108
|
+
});
|
|
17109
|
+
|
|
16958
17110
|
// src/scripts/backtest.ts
|
|
16959
17111
|
var backtest_exports = {};
|
|
16960
17112
|
__export(backtest_exports, {
|
|
16961
|
-
BACKTEST_PRELOAD_DAYS: () =>
|
|
17113
|
+
BACKTEST_PRELOAD_DAYS: () => import_constants10.BACKTEST_PRELOAD_DAYS,
|
|
16962
17114
|
backtest: () => backtest,
|
|
16963
17115
|
chunkTestSuiteBySymbol: () => chunkTestSuiteBySymbol,
|
|
16964
17116
|
interval: () => interval,
|
|
@@ -16983,7 +17135,7 @@ __export(backtest_exports, {
|
|
|
16983
17135
|
toStrategyConfigGrid: () => toStrategyConfigGrid,
|
|
16984
17136
|
userName: () => userName
|
|
16985
17137
|
});
|
|
16986
|
-
var import_fs2, import_path6, import_chalk15, import_backtest4, import_grid, import_data,
|
|
17138
|
+
var import_fs2, import_path6, import_chalk15, import_backtest4, import_grid, import_data, import_redis8, import_constants10, toPersistedBacktestResultEntry, toPersistedBacktestResultEntries, resolveRenderableStat, toFiniteNumber2, toReportRow, collectReportRows, escapeMdCell, formatMoney, formatPercent2, formatRatio4, createMarkdownTable, renderReportRowsTable, safeFileToken, isStrategyConfigGrid, loadBacktestConfig, hasSingleSymbol, writeBacktestMarkdownReport, finishBacktest, restoreCompletedBacktestResults, loadBacktestRunForContinue, prepareContinuedBacktestMarketContext, runBacktestSuite, backtest, main8;
|
|
16987
17139
|
var init_backtest = __esm({
|
|
16988
17140
|
"src/scripts/backtest.ts"() {
|
|
16989
17141
|
"use strict";
|
|
@@ -16993,12 +17145,13 @@ var init_backtest = __esm({
|
|
|
16993
17145
|
import_backtest4 = require("@tradejs/core/backtest");
|
|
16994
17146
|
import_grid = require("@tradejs/core/grid");
|
|
16995
17147
|
import_data = require("@tradejs/core/data");
|
|
16996
|
-
|
|
16997
|
-
|
|
17148
|
+
import_redis8 = require("@tradejs/infra/redis");
|
|
17149
|
+
import_constants10 = require("@tradejs/core/constants");
|
|
16998
17150
|
init_runnerCore();
|
|
16999
17151
|
init_cliConfig();
|
|
17000
17152
|
init_runState();
|
|
17001
17153
|
init_checkpoint();
|
|
17154
|
+
init_observeRun();
|
|
17002
17155
|
init_marketContextPrepare();
|
|
17003
17156
|
if (process.argv.some(
|
|
17004
17157
|
(arg) => arg === "--live" || String(arg).startsWith("--live=")
|
|
@@ -17134,8 +17287,8 @@ var init_backtest = __esm({
|
|
|
17134
17287
|
if (!strategyName) {
|
|
17135
17288
|
throw new Error("Strategy name not found");
|
|
17136
17289
|
}
|
|
17137
|
-
const backtestConfig = await (0,
|
|
17138
|
-
|
|
17290
|
+
const backtestConfig = await (0, import_redis8.getData)(
|
|
17291
|
+
import_redis8.redisKeys.backtestConfig(userName, flags5.config),
|
|
17139
17292
|
null
|
|
17140
17293
|
);
|
|
17141
17294
|
if (!backtestConfig) {
|
|
@@ -17282,8 +17435,8 @@ var init_backtest = __esm({
|
|
|
17282
17435
|
console.log(import_chalk15.default.gray(`full report: ${markdownReportPath}`));
|
|
17283
17436
|
console.log("");
|
|
17284
17437
|
if (!isFastMode || flags5.persistResults) {
|
|
17285
|
-
await (0,
|
|
17286
|
-
|
|
17438
|
+
await (0, import_redis8.setData)(
|
|
17439
|
+
import_redis8.redisKeys.backtestResults(userName, flags5.config, timestamp),
|
|
17287
17440
|
{
|
|
17288
17441
|
config: flags5.config,
|
|
17289
17442
|
mode: "config",
|
|
@@ -17303,11 +17456,10 @@ var init_backtest = __esm({
|
|
|
17303
17456
|
errorTests: errorTests2
|
|
17304
17457
|
},
|
|
17305
17458
|
{
|
|
17306
|
-
expire:
|
|
17459
|
+
expire: import_constants10.TTL_1M
|
|
17307
17460
|
}
|
|
17308
17461
|
);
|
|
17309
17462
|
}
|
|
17310
|
-
process.exit();
|
|
17311
17463
|
};
|
|
17312
17464
|
restoreCompletedBacktestResults = (completed) => {
|
|
17313
17465
|
for (const { result } of completed) {
|
|
@@ -17388,6 +17540,56 @@ var init_backtest = __esm({
|
|
|
17388
17540
|
log: (message) => console.log(import_chalk15.default.gray(message))
|
|
17389
17541
|
});
|
|
17390
17542
|
};
|
|
17543
|
+
runBacktestSuite = async (manifest, testSuite, initialCompletedTests = 0) => {
|
|
17544
|
+
const observation = await observeBacktestRun(
|
|
17545
|
+
manifest,
|
|
17546
|
+
initialCompletedTests,
|
|
17547
|
+
effectiveParallel
|
|
17548
|
+
);
|
|
17549
|
+
try {
|
|
17550
|
+
await executeTestSuite({
|
|
17551
|
+
testSuite,
|
|
17552
|
+
window: manifest.window,
|
|
17553
|
+
preloadStart: manifest.preloadStart,
|
|
17554
|
+
backtestRunId: manifest.runId,
|
|
17555
|
+
initialCompletedTests,
|
|
17556
|
+
totalTests: manifest.testSuite.length,
|
|
17557
|
+
onProgress: observation?.progress,
|
|
17558
|
+
onIncomplete: async () => {
|
|
17559
|
+
await observation?.finish("failed");
|
|
17560
|
+
await markBacktestRunStatus({ run: manifest, status: "interrupted" });
|
|
17561
|
+
process.exit(1);
|
|
17562
|
+
},
|
|
17563
|
+
onResult: async (result) => {
|
|
17564
|
+
await saveBacktestCheckpointResult({
|
|
17565
|
+
result,
|
|
17566
|
+
runId: manifest.runId,
|
|
17567
|
+
userName
|
|
17568
|
+
});
|
|
17569
|
+
trackTopResult(result);
|
|
17570
|
+
updateBestTickerResult(result);
|
|
17571
|
+
},
|
|
17572
|
+
onInterrupt: async () => {
|
|
17573
|
+
await observation?.finish("cancelled");
|
|
17574
|
+
await markBacktestRunStatus({ run: manifest, status: "interrupted" });
|
|
17575
|
+
},
|
|
17576
|
+
onFinish: async () => {
|
|
17577
|
+
try {
|
|
17578
|
+
await markBacktestRunStatus({ run: manifest, status: "completed" });
|
|
17579
|
+
await finishBacktest(manifest.testSuite);
|
|
17580
|
+
await observation?.finish("completed");
|
|
17581
|
+
process.exit();
|
|
17582
|
+
} catch (error) {
|
|
17583
|
+
await observation?.finish("failed");
|
|
17584
|
+
throw error;
|
|
17585
|
+
}
|
|
17586
|
+
}
|
|
17587
|
+
});
|
|
17588
|
+
} catch (error) {
|
|
17589
|
+
await observation?.finish("failed");
|
|
17590
|
+
throw error;
|
|
17591
|
+
}
|
|
17592
|
+
};
|
|
17391
17593
|
backtest = async () => {
|
|
17392
17594
|
resetRunState();
|
|
17393
17595
|
const config2 = await loadBacktestConfig();
|
|
@@ -17402,33 +17604,10 @@ var init_backtest = __esm({
|
|
|
17402
17604
|
if (!remainingSuite.length) {
|
|
17403
17605
|
await markBacktestRunStatus({ run: manifest2, status: "completed" });
|
|
17404
17606
|
await finishBacktest(manifest2.testSuite);
|
|
17405
|
-
|
|
17607
|
+
process.exit();
|
|
17406
17608
|
}
|
|
17407
17609
|
await prepareContinuedBacktestMarketContext({ manifest: manifest2, remainingSuite });
|
|
17408
|
-
await
|
|
17409
|
-
testSuite: remainingSuite,
|
|
17410
|
-
window: manifest2.window,
|
|
17411
|
-
preloadStart: manifest2.preloadStart,
|
|
17412
|
-
backtestRunId: manifest2.runId,
|
|
17413
|
-
initialCompletedTests: completed.length,
|
|
17414
|
-
totalTests: manifest2.testSuite.length,
|
|
17415
|
-
onResult: async (result) => {
|
|
17416
|
-
await saveBacktestCheckpointResult({
|
|
17417
|
-
result,
|
|
17418
|
-
runId: manifest2.runId,
|
|
17419
|
-
userName
|
|
17420
|
-
});
|
|
17421
|
-
trackTopResult(result);
|
|
17422
|
-
updateBestTickerResult(result);
|
|
17423
|
-
},
|
|
17424
|
-
onInterrupt: async () => {
|
|
17425
|
-
await markBacktestRunStatus({ run: manifest2, status: "interrupted" });
|
|
17426
|
-
},
|
|
17427
|
-
onFinish: async () => {
|
|
17428
|
-
await markBacktestRunStatus({ run: manifest2, status: "completed" });
|
|
17429
|
-
await finishBacktest(manifest2.testSuite);
|
|
17430
|
-
}
|
|
17431
|
-
});
|
|
17610
|
+
await runBacktestSuite(manifest2, remainingSuite, completed.length);
|
|
17432
17611
|
return;
|
|
17433
17612
|
}
|
|
17434
17613
|
const preparedRun = await prepareRunEnvironment2(config2.strategyName);
|
|
@@ -17489,28 +17668,7 @@ var init_backtest = __esm({
|
|
|
17489
17668
|
testSuite
|
|
17490
17669
|
});
|
|
17491
17670
|
console.log(import_chalk15.default.gray(`backtest run id: ${manifest.runId}`));
|
|
17492
|
-
await
|
|
17493
|
-
testSuite,
|
|
17494
|
-
window: preparedRun.window,
|
|
17495
|
-
preloadStart: preparedRun.preloadStart,
|
|
17496
|
-
backtestRunId: manifest.runId,
|
|
17497
|
-
onResult: async (result) => {
|
|
17498
|
-
await saveBacktestCheckpointResult({
|
|
17499
|
-
result,
|
|
17500
|
-
runId: manifest.runId,
|
|
17501
|
-
userName
|
|
17502
|
-
});
|
|
17503
|
-
trackTopResult(result);
|
|
17504
|
-
updateBestTickerResult(result);
|
|
17505
|
-
},
|
|
17506
|
-
onInterrupt: async () => {
|
|
17507
|
-
await markBacktestRunStatus({ run: manifest, status: "interrupted" });
|
|
17508
|
-
},
|
|
17509
|
-
onFinish: async () => {
|
|
17510
|
-
await markBacktestRunStatus({ run: manifest, status: "completed" });
|
|
17511
|
-
await finishBacktest(testSuite);
|
|
17512
|
-
}
|
|
17513
|
-
});
|
|
17671
|
+
await runBacktestSuite(manifest, testSuite);
|
|
17514
17672
|
};
|
|
17515
17673
|
main8 = backtest;
|
|
17516
17674
|
}
|
|
@@ -18461,11 +18619,11 @@ var init_memoryProfile = __esm({
|
|
|
18461
18619
|
});
|
|
18462
18620
|
|
|
18463
18621
|
// src/lib/replay/portfolioReplayConnector.ts
|
|
18464
|
-
var
|
|
18622
|
+
var import_constants11, import_math, import_trade, UNKNOWN_STRATEGY, getStrategyName, getPositionPnlSnapshot, createPortfolioReplayConnector;
|
|
18465
18623
|
var init_portfolioReplayConnector = __esm({
|
|
18466
18624
|
"src/lib/replay/portfolioReplayConnector.ts"() {
|
|
18467
18625
|
"use strict";
|
|
18468
|
-
|
|
18626
|
+
import_constants11 = require("@tradejs/core/constants");
|
|
18469
18627
|
import_math = require("@tradejs/core/math");
|
|
18470
18628
|
import_trade = require("@tradejs/core/trade");
|
|
18471
18629
|
init_support2();
|
|
@@ -18493,7 +18651,7 @@ var init_portfolioReplayConnector = __esm({
|
|
|
18493
18651
|
};
|
|
18494
18652
|
createPortfolioReplayConnector = (connector, observeEquity = false) => {
|
|
18495
18653
|
let state = {};
|
|
18496
|
-
let amount =
|
|
18654
|
+
let amount = import_constants11.INITIAL_BACKTEST_AMOUNT;
|
|
18497
18655
|
let executionTimestamp = null;
|
|
18498
18656
|
const positionsBySymbol = /* @__PURE__ */ new Map();
|
|
18499
18657
|
const currentPriceBySymbol = /* @__PURE__ */ new Map();
|
|
@@ -18559,7 +18717,7 @@ var init_portfolioReplayConnector = __esm({
|
|
|
18559
18717
|
price,
|
|
18560
18718
|
qty
|
|
18561
18719
|
}) => {
|
|
18562
|
-
const fee = price * qty *
|
|
18720
|
+
const fee = price * qty * import_constants11.FEE_PERCENT;
|
|
18563
18721
|
return {
|
|
18564
18722
|
fee,
|
|
18565
18723
|
profit: grossProfit - fee
|
|
@@ -18926,7 +19084,7 @@ var init_portfolioReplayConnector = __esm({
|
|
|
18926
19084
|
},
|
|
18927
19085
|
getMarkedEquity: () => {
|
|
18928
19086
|
if (!equityMarks) return null;
|
|
18929
|
-
let equity = amount -
|
|
19087
|
+
let equity = amount - import_constants11.INITIAL_BACKTEST_AMOUNT;
|
|
18930
19088
|
for (const { position } of positionsBySymbol.values()) {
|
|
18931
19089
|
const mark = equityMarks.get(position.symbol);
|
|
18932
19090
|
if (mark == null || !Number.isFinite(mark)) return null;
|
|
@@ -19328,12 +19486,12 @@ var init_historicalSignalsReplayExecution = __esm({
|
|
|
19328
19486
|
});
|
|
19329
19487
|
|
|
19330
19488
|
// src/lib/replay/historicalSignalsReplayResults.ts
|
|
19331
|
-
var import_backtest5,
|
|
19489
|
+
var import_backtest5, import_constants12, emptyStat, positionLogForStats, calculateReplayStat, byTimestamp, byPositionClose, collectHistoricalReplayResult, compactHistoricalReplayResultForPortfolio, mergeHistoricalReplayResults;
|
|
19332
19490
|
var init_historicalSignalsReplayResults = __esm({
|
|
19333
19491
|
"src/lib/replay/historicalSignalsReplayResults.ts"() {
|
|
19334
19492
|
"use strict";
|
|
19335
19493
|
import_backtest5 = require("@tradejs/core/backtest");
|
|
19336
|
-
|
|
19494
|
+
import_constants12 = require("@tradejs/core/constants");
|
|
19337
19495
|
emptyStat = () => ({
|
|
19338
19496
|
orders: 0,
|
|
19339
19497
|
wins: 0,
|
|
@@ -19342,7 +19500,7 @@ var init_historicalSignalsReplayResults = __esm({
|
|
|
19342
19500
|
amount: 0
|
|
19343
19501
|
});
|
|
19344
19502
|
positionLogForStats = (positionLog) => {
|
|
19345
|
-
let amount =
|
|
19503
|
+
let amount = import_constants12.INITIAL_BACKTEST_AMOUNT;
|
|
19346
19504
|
return [...positionLog].sort(
|
|
19347
19505
|
(left, right) => left.close.timestamp - right.close.timestamp || left.open.timestamp - right.open.timestamp
|
|
19348
19506
|
).map((position) => {
|
|
@@ -19436,7 +19594,7 @@ var init_historicalSignalsReplayResults = __esm({
|
|
|
19436
19594
|
});
|
|
19437
19595
|
|
|
19438
19596
|
// src/lib/replay/historicalSignalsReplay.ts
|
|
19439
|
-
var import_chalk17, import_progress8, import_node_path12, import_node_module2, import_strategies5, import_time4,
|
|
19597
|
+
var import_chalk17, import_progress8, import_node_path12, import_node_module2, import_strategies5, import_time4, import_logger2, import_redis9, import_connectors6, import_cli5, import_strategies6, import_runtimeStrategies3, projectReplayCacheReleasers, getProjectReplayCacheReleasers, releaseReplayCacheCopies, loadRuntimeStrategies, loadReferenceConnector, buildAfterSignalsContext, getConnectorName, loadHistoricalReplayReferences, runHistoricalSignalsReplay;
|
|
19440
19598
|
var init_historicalSignalsReplay = __esm({
|
|
19441
19599
|
"src/lib/replay/historicalSignalsReplay.ts"() {
|
|
19442
19600
|
"use strict";
|
|
@@ -19447,8 +19605,8 @@ var init_historicalSignalsReplay = __esm({
|
|
|
19447
19605
|
import_node_module2 = require("module");
|
|
19448
19606
|
import_strategies5 = require("@tradejs/core/strategies");
|
|
19449
19607
|
import_time4 = require("@tradejs/core/time");
|
|
19450
|
-
|
|
19451
|
-
|
|
19608
|
+
import_logger2 = require("@tradejs/infra/logger");
|
|
19609
|
+
import_redis9 = require("@tradejs/infra/redis");
|
|
19452
19610
|
import_connectors6 = require("@tradejs/node/connectors");
|
|
19453
19611
|
import_cli5 = require("@tradejs/node/cli");
|
|
19454
19612
|
import_strategies6 = require("@tradejs/node/strategies");
|
|
@@ -19515,8 +19673,8 @@ var init_historicalSignalsReplay = __esm({
|
|
|
19515
19673
|
`Runtime evidence package mismatch for ${strategyName}: expected=${strategyPackage}@${strategyPackageVersion}/@tradejs/node@${runtimePackageVersion}, installed=${installed.strategyPackage ?? "missing"}@${installed.strategyPackageVersion ?? "missing"}/@tradejs/node@${installed.runtimePackageVersion ?? "missing"}`
|
|
19516
19674
|
);
|
|
19517
19675
|
}
|
|
19518
|
-
const strategyResults = await (0,
|
|
19519
|
-
|
|
19676
|
+
const strategyResults = await (0, import_redis9.getData)(
|
|
19677
|
+
import_redis9.redisKeys.strategyResults(replayUserName, strategyName),
|
|
19520
19678
|
{}
|
|
19521
19679
|
);
|
|
19522
19680
|
return {
|
|
@@ -19721,7 +19879,7 @@ var init_historicalSignalsReplay = __esm({
|
|
|
19721
19879
|
releaseHistoricalReplayPlan(plan);
|
|
19722
19880
|
memory?.("execution:released");
|
|
19723
19881
|
const artifacts = replayConnector.getReplayArtifacts();
|
|
19724
|
-
|
|
19882
|
+
import_logger2.logger.info(
|
|
19725
19883
|
import_chalk17.default.gray(
|
|
19726
19884
|
`signals replay historical cycles: ${plan.orderedTimestamps.length} (aborted=${execution.abortedCycles}) done in ${((Date.now() - startedAt) / 1e3).toFixed(1)}s`
|
|
19727
19885
|
)
|
|
@@ -20297,11 +20455,11 @@ var init_paritySummary = __esm({
|
|
|
20297
20455
|
});
|
|
20298
20456
|
|
|
20299
20457
|
// src/lib/runtimeSignalsStorage.ts
|
|
20300
|
-
var
|
|
20458
|
+
var import_constants13, import_data4, import_time5, appendRuntimeSignalEvaluationRun, SECONDS_PER_DAY, RUNTIME_SIGNAL_RETENTION_DAYS_ENV, DEFAULT_RUNTIME_SIGNAL_RETENTION_TTL_SECONDS, RUNTIME_LINEAGE_SCOPE_RETENTION_TTL_SECONDS, parsePositiveNumber, getRuntimeSignalRetentionTtlSeconds, toRuntimeSignalBucketRef, shouldStoreRuntimeSignalDiagnostics, toStoredRuntimeSignal, isRuntimeSignalBucketRef, normalizeRuntimeSignalSkipReason, buildStatsReasonField, buildRuntimeSignalStatsIncrements, shouldStoreDetailedRuntimeSignalEvaluation, toCount, parseRuntimeSignalStatsBucket;
|
|
20301
20459
|
var init_runtimeSignalsStorage = __esm({
|
|
20302
20460
|
"src/lib/runtimeSignalsStorage.ts"() {
|
|
20303
20461
|
"use strict";
|
|
20304
|
-
|
|
20462
|
+
import_constants13 = require("@tradejs/core/constants");
|
|
20305
20463
|
import_data4 = require("@tradejs/core/data");
|
|
20306
20464
|
import_time5 = require("@tradejs/core/time");
|
|
20307
20465
|
appendRuntimeSignalEvaluationRun = (runs = [], evaluation) => {
|
|
@@ -20336,8 +20494,8 @@ var init_runtimeSignalsStorage = __esm({
|
|
|
20336
20494
|
};
|
|
20337
20495
|
SECONDS_PER_DAY = 86400;
|
|
20338
20496
|
RUNTIME_SIGNAL_RETENTION_DAYS_ENV = "RUNTIME_SIGNAL_RETENTION_DAYS";
|
|
20339
|
-
DEFAULT_RUNTIME_SIGNAL_RETENTION_TTL_SECONDS =
|
|
20340
|
-
RUNTIME_LINEAGE_SCOPE_RETENTION_TTL_SECONDS =
|
|
20497
|
+
DEFAULT_RUNTIME_SIGNAL_RETENTION_TTL_SECONDS = import_constants13.TTL_3D;
|
|
20498
|
+
RUNTIME_LINEAGE_SCOPE_RETENTION_TTL_SECONDS = import_constants13.TTL_1M;
|
|
20341
20499
|
parsePositiveNumber = (value) => {
|
|
20342
20500
|
if (value == null || value === "") {
|
|
20343
20501
|
return null;
|
|
@@ -20470,11 +20628,11 @@ var init_runtimeSignalsStorage = __esm({
|
|
|
20470
20628
|
});
|
|
20471
20629
|
|
|
20472
20630
|
// src/lib/runtimeSignalsLoader.ts
|
|
20473
|
-
var
|
|
20631
|
+
var import_redis10, isSignalRecord, isRuntimeSignalEvaluationRecord, sortByTimestamp, filterBucketKeysByWindow, loadRuntimeSignals, loadRuntimeSignalEvaluations, loadRuntimeLineageScopes, parseBucketKey, loadRuntimeSignalEvaluationStatsBuckets;
|
|
20474
20632
|
var init_runtimeSignalsLoader = __esm({
|
|
20475
20633
|
"src/lib/runtimeSignalsLoader.ts"() {
|
|
20476
20634
|
"use strict";
|
|
20477
|
-
|
|
20635
|
+
import_redis10 = require("@tradejs/infra/redis");
|
|
20478
20636
|
init_runtimeSignalsStorage();
|
|
20479
20637
|
isSignalRecord = (value) => {
|
|
20480
20638
|
if (!value || typeof value !== "object") {
|
|
@@ -20512,14 +20670,14 @@ var init_runtimeSignalsLoader = __esm({
|
|
|
20512
20670
|
startTime,
|
|
20513
20671
|
endTime
|
|
20514
20672
|
} = {}) => {
|
|
20515
|
-
const bucketPrefix =
|
|
20673
|
+
const bucketPrefix = import_redis10.redisKeys.runtimeSignalBuckets(userName3);
|
|
20516
20674
|
const bucketKeys = filterBucketKeysByWindow(
|
|
20517
|
-
await (0,
|
|
20675
|
+
await (0, import_redis10.getKeys)(bucketPrefix),
|
|
20518
20676
|
bucketPrefix,
|
|
20519
20677
|
startTime,
|
|
20520
20678
|
endTime
|
|
20521
20679
|
);
|
|
20522
|
-
const refs = (await Promise.all(bucketKeys.map((key2) => (0,
|
|
20680
|
+
const refs = (await Promise.all(bucketKeys.map((key2) => (0, import_redis10.getHashJsonValues)(key2)))).flat().filter(isRuntimeSignalBucketRef);
|
|
20523
20681
|
const seen = /* @__PURE__ */ new Set();
|
|
20524
20682
|
const payloads = await Promise.all(
|
|
20525
20683
|
refs.map(async (ref) => {
|
|
@@ -20528,8 +20686,8 @@ var init_runtimeSignalsLoader = __esm({
|
|
|
20528
20686
|
return null;
|
|
20529
20687
|
}
|
|
20530
20688
|
seen.add(dedupeKey);
|
|
20531
|
-
const signal = await (0,
|
|
20532
|
-
|
|
20689
|
+
const signal = await (0, import_redis10.getData)(
|
|
20690
|
+
import_redis10.redisKeys.storeSignal(ref.symbol, ref.signalId),
|
|
20533
20691
|
null
|
|
20534
20692
|
);
|
|
20535
20693
|
return isSignalRecord(signal) ? signal : null;
|
|
@@ -20541,14 +20699,14 @@ var init_runtimeSignalsLoader = __esm({
|
|
|
20541
20699
|
startTime,
|
|
20542
20700
|
endTime
|
|
20543
20701
|
} = {}) => {
|
|
20544
|
-
const bucketPrefix =
|
|
20702
|
+
const bucketPrefix = import_redis10.redisKeys.runtimeSignalEvaluationBuckets(userName3);
|
|
20545
20703
|
const bucketKeys = filterBucketKeysByWindow(
|
|
20546
|
-
await (0,
|
|
20704
|
+
await (0, import_redis10.getKeys)(bucketPrefix),
|
|
20547
20705
|
bucketPrefix,
|
|
20548
20706
|
startTime,
|
|
20549
20707
|
endTime
|
|
20550
20708
|
);
|
|
20551
|
-
const evaluations = (await Promise.all(bucketKeys.map((key2) => (0,
|
|
20709
|
+
const evaluations = (await Promise.all(bucketKeys.map((key2) => (0, import_redis10.getHashJsonValues)(key2)))).flat().filter(isRuntimeSignalEvaluationRecord);
|
|
20552
20710
|
const deduped = /* @__PURE__ */ new Map();
|
|
20553
20711
|
for (const evaluation of evaluations) {
|
|
20554
20712
|
deduped.set(evaluation.evaluationId, evaluation);
|
|
@@ -20561,8 +20719,8 @@ var init_runtimeSignalsLoader = __esm({
|
|
|
20561
20719
|
}) => {
|
|
20562
20720
|
const records = (await Promise.all(
|
|
20563
20721
|
(0, import_time5.getRuntimeStorageDayKeys)(startTime, endTime).map(
|
|
20564
|
-
(dayKey) => (0,
|
|
20565
|
-
|
|
20722
|
+
(dayKey) => (0, import_redis10.getHashJsonValues)(
|
|
20723
|
+
import_redis10.redisKeys.runtimeLineageScopeBucket(userName3, dayKey)
|
|
20566
20724
|
)
|
|
20567
20725
|
)
|
|
20568
20726
|
)).flat().filter(
|
|
@@ -20591,8 +20749,8 @@ var init_runtimeSignalsLoader = __esm({
|
|
|
20591
20749
|
};
|
|
20592
20750
|
};
|
|
20593
20751
|
loadRuntimeSignalEvaluationStatsBuckets = async (userName3) => {
|
|
20594
|
-
const prefix =
|
|
20595
|
-
const keys = await (0,
|
|
20752
|
+
const prefix = import_redis10.redisKeys.runtimeSignalEvaluationStatsBuckets(userName3);
|
|
20753
|
+
const keys = await (0, import_redis10.getKeys)(prefix);
|
|
20596
20754
|
const entries = await Promise.all(
|
|
20597
20755
|
keys.map(async (key2) => {
|
|
20598
20756
|
const parsedKey = parseBucketKey(prefix, key2);
|
|
@@ -20602,7 +20760,7 @@ var init_runtimeSignalsLoader = __esm({
|
|
|
20602
20760
|
return {
|
|
20603
20761
|
key: key2,
|
|
20604
20762
|
...parsedKey,
|
|
20605
|
-
stats: parseRuntimeSignalStatsBucket(await (0,
|
|
20763
|
+
stats: parseRuntimeSignalStatsBucket(await (0, import_redis10.getHashData)(key2))
|
|
20606
20764
|
};
|
|
20607
20765
|
})
|
|
20608
20766
|
);
|
|
@@ -20612,13 +20770,13 @@ var init_runtimeSignalsLoader = __esm({
|
|
|
20612
20770
|
});
|
|
20613
20771
|
|
|
20614
20772
|
// src/lib/runtimeTradeSync.ts
|
|
20615
|
-
var
|
|
20773
|
+
var import_constants14, import_time6, import_redis11, CLOSED_PNL_LIMIT, CLOSED_PNL_RECONCILIATION_LOOKBACK_MS, EXCHANGE_HISTORY_MAX_RANGE_MS, isRuntimeTradeSyncFallbackClose, splitExchangeHistoryTimeRange, formatRuntimeTradeSyncError, loadClosedPnlRows, consumeClosedPnlMatch, isRuntimeTradeInConnectorScope, syncRuntimeTrades;
|
|
20616
20774
|
var init_runtimeTradeSync = __esm({
|
|
20617
20775
|
"src/lib/runtimeTradeSync.ts"() {
|
|
20618
20776
|
"use strict";
|
|
20619
|
-
|
|
20777
|
+
import_constants14 = require("@tradejs/core/constants");
|
|
20620
20778
|
import_time6 = require("@tradejs/core/time");
|
|
20621
|
-
|
|
20779
|
+
import_redis11 = require("@tradejs/infra/redis");
|
|
20622
20780
|
CLOSED_PNL_LIMIT = 100;
|
|
20623
20781
|
CLOSED_PNL_RECONCILIATION_LOOKBACK_MS = 24 * 60 * 60 * 1e3;
|
|
20624
20782
|
EXCHANGE_HISTORY_MAX_RANGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
@@ -20751,7 +20909,7 @@ var init_runtimeTradeSync = __esm({
|
|
|
20751
20909
|
const activeTradeKeys = [
|
|
20752
20910
|
...new Set(
|
|
20753
20911
|
trades.filter((trade) => isRuntimeTradeInConnectorScope(trade, connector)).map(
|
|
20754
|
-
(trade) =>
|
|
20912
|
+
(trade) => import_redis11.redisKeys.runtimeActiveTrade(
|
|
20755
20913
|
userName3,
|
|
20756
20914
|
trade.symbol,
|
|
20757
20915
|
trade.deploymentId ?? trade.accountId
|
|
@@ -20761,7 +20919,7 @@ var init_runtimeTradeSync = __esm({
|
|
|
20761
20919
|
];
|
|
20762
20920
|
await Promise.all(
|
|
20763
20921
|
activeTradeKeys.map(async (key2) => {
|
|
20764
|
-
const activeRef = await (0,
|
|
20922
|
+
const activeRef = await (0, import_redis11.getData)(key2, null);
|
|
20765
20923
|
activeOrderIdByKey.set(
|
|
20766
20924
|
key2,
|
|
20767
20925
|
typeof activeRef?.orderId === "string" ? activeRef.orderId : null
|
|
@@ -20790,7 +20948,7 @@ var init_runtimeTradeSync = __esm({
|
|
|
20790
20948
|
syncedTrades.push(trade);
|
|
20791
20949
|
continue;
|
|
20792
20950
|
}
|
|
20793
|
-
const activeTradeKey =
|
|
20951
|
+
const activeTradeKey = import_redis11.redisKeys.runtimeActiveTrade(
|
|
20794
20952
|
userName3,
|
|
20795
20953
|
trade.symbol,
|
|
20796
20954
|
trade.deploymentId ?? trade.accountId
|
|
@@ -20814,15 +20972,15 @@ var init_runtimeTradeSync = __esm({
|
|
|
20814
20972
|
currentPnl: openPosition.unrealizedPnl,
|
|
20815
20973
|
lastSyncedAt: endTime
|
|
20816
20974
|
};
|
|
20817
|
-
await (0,
|
|
20818
|
-
|
|
20975
|
+
await (0, import_redis11.setData)(
|
|
20976
|
+
import_redis11.redisKeys.runtimeTrade(userName3, trade.orderId),
|
|
20819
20977
|
nextTrade2,
|
|
20820
20978
|
{
|
|
20821
20979
|
expire: 0
|
|
20822
20980
|
}
|
|
20823
20981
|
);
|
|
20824
|
-
await (0,
|
|
20825
|
-
|
|
20982
|
+
await (0, import_redis11.setHashJsonField)(
|
|
20983
|
+
import_redis11.redisKeys.runtimeTradeBucket(
|
|
20826
20984
|
userName3,
|
|
20827
20985
|
(0, import_time6.getRuntimeStorageDayKey)(trade.entryTimestamp)
|
|
20828
20986
|
),
|
|
@@ -20856,28 +21014,28 @@ var init_runtimeTradeSync = __esm({
|
|
|
20856
21014
|
lastSyncedAt: endTime
|
|
20857
21015
|
};
|
|
20858
21016
|
await Promise.all([
|
|
20859
|
-
(0,
|
|
20860
|
-
expire:
|
|
21017
|
+
(0, import_redis11.setData)(import_redis11.redisKeys.runtimeTrade(userName3, trade.orderId), nextTrade, {
|
|
21018
|
+
expire: import_constants14.TTL_1M
|
|
20861
21019
|
}),
|
|
20862
|
-
(0,
|
|
20863
|
-
|
|
21020
|
+
(0, import_redis11.setHashJsonField)(
|
|
21021
|
+
import_redis11.redisKeys.runtimeTradeBucket(
|
|
20864
21022
|
userName3,
|
|
20865
21023
|
(0, import_time6.getRuntimeStorageDayKey)(trade.entryTimestamp)
|
|
20866
21024
|
),
|
|
20867
21025
|
trade.orderId,
|
|
20868
21026
|
nextTrade,
|
|
20869
|
-
{ expire:
|
|
21027
|
+
{ expire: import_constants14.TTL_1M }
|
|
20870
21028
|
),
|
|
20871
|
-
(0,
|
|
20872
|
-
|
|
21029
|
+
(0, import_redis11.setHashJsonField)(
|
|
21030
|
+
import_redis11.redisKeys.runtimeClosedTradeBucket(
|
|
20873
21031
|
userName3,
|
|
20874
21032
|
(0, import_time6.getRuntimeStorageDayKey)(nextTrade.exitTimestamp)
|
|
20875
21033
|
),
|
|
20876
21034
|
trade.orderId,
|
|
20877
21035
|
nextTrade,
|
|
20878
|
-
{ expire:
|
|
21036
|
+
{ expire: import_constants14.TTL_1M }
|
|
20879
21037
|
),
|
|
20880
|
-
...isCurrentActiveTrade ? [(0,
|
|
21038
|
+
...isCurrentActiveTrade ? [(0, import_redis11.delKey)(activeTradeKey)] : []
|
|
20881
21039
|
]);
|
|
20882
21040
|
syncedTrades.push(nextTrade);
|
|
20883
21041
|
}
|
|
@@ -24412,16 +24570,16 @@ ${comparison.limitations.join(" ")}
|
|
|
24412
24570
|
});
|
|
24413
24571
|
|
|
24414
24572
|
// src/scripts/replayRunner.ts
|
|
24415
|
-
var import_chalk21,
|
|
24573
|
+
var import_chalk21, import_constants15, import_data6, import_time8, import_redis12, import_candles2, import_runtimeStrategies4, import_strategies7, prepareReplayBinanceMarketContext, replayMarketContextInterval, cachedTickerSymbols, finishReplay, replayBacktest;
|
|
24416
24574
|
var init_replayRunner = __esm({
|
|
24417
24575
|
"src/scripts/replayRunner.ts"() {
|
|
24418
24576
|
"use strict";
|
|
24419
24577
|
init_historicalSignalsReplayPreparation();
|
|
24420
24578
|
import_chalk21 = __toESM(require("chalk"));
|
|
24421
|
-
|
|
24579
|
+
import_constants15 = require("@tradejs/core/constants");
|
|
24422
24580
|
import_data6 = require("@tradejs/core/data");
|
|
24423
24581
|
import_time8 = require("@tradejs/core/time");
|
|
24424
|
-
|
|
24582
|
+
import_redis12 = require("@tradejs/infra/redis");
|
|
24425
24583
|
import_candles2 = require("@tradejs/infra/timescale/candles");
|
|
24426
24584
|
import_runtimeStrategies4 = require("@tradejs/node/runtimeStrategies");
|
|
24427
24585
|
import_strategies7 = require("@tradejs/node/strategies");
|
|
@@ -24475,12 +24633,12 @@ var init_replayRunner = __esm({
|
|
|
24475
24633
|
...connectorName.toLowerCase() === "bybit" ? ["ByBit"] : []
|
|
24476
24634
|
];
|
|
24477
24635
|
const keys = connectorNames.flatMap((name) => [
|
|
24478
|
-
|
|
24479
|
-
|
|
24480
|
-
|
|
24636
|
+
import_redis12.redisKeys.tickerUniverse(replayUserName, name, universe, accountId),
|
|
24637
|
+
import_redis12.redisKeys.tickerUniverse(replayUserName, name, universe, "default"),
|
|
24638
|
+
import_redis12.redisKeys.tickerUniverse(replayUserName, name)
|
|
24481
24639
|
]);
|
|
24482
24640
|
for (const key2 of [...new Set(keys)]) {
|
|
24483
|
-
const cached = await (0,
|
|
24641
|
+
const cached = await (0, import_redis12.getData)(key2, null);
|
|
24484
24642
|
const symbols = (cached?.tickers ?? []).map(
|
|
24485
24643
|
(ticker) => String(ticker.symbol ?? "").trim().toUpperCase()
|
|
24486
24644
|
).filter(Boolean);
|
|
@@ -24522,7 +24680,7 @@ var init_replayRunner = __esm({
|
|
|
24522
24680
|
replayResult.orderLog[replayResult.orderLog.length - 1]?.timestamp ?? finishedAt.getTime()
|
|
24523
24681
|
)}`
|
|
24524
24682
|
}) : null;
|
|
24525
|
-
const replayKey =
|
|
24683
|
+
const replayKey = import_redis12.redisKeys.backtestResults(
|
|
24526
24684
|
replayUserName,
|
|
24527
24685
|
REPLAY_RESULTS_CONFIG,
|
|
24528
24686
|
timestamp
|
|
@@ -24556,7 +24714,7 @@ var init_replayRunner = __esm({
|
|
|
24556
24714
|
console.log(import_chalk21.default.green(`Portfolio report: ${portfolioReport.html}`));
|
|
24557
24715
|
console.log(import_chalk21.default.green(`Portfolio report JSON: ${portfolioReport.json}`));
|
|
24558
24716
|
}
|
|
24559
|
-
await (0,
|
|
24717
|
+
await (0, import_redis12.setData)(
|
|
24560
24718
|
replayKey,
|
|
24561
24719
|
{
|
|
24562
24720
|
config: REPLAY_RESULTS_CONFIG,
|
|
@@ -24583,17 +24741,17 @@ var init_replayRunner = __esm({
|
|
|
24583
24741
|
...portfolioReport ? { portfolioReport } : {}
|
|
24584
24742
|
},
|
|
24585
24743
|
{
|
|
24586
|
-
expire:
|
|
24744
|
+
expire: import_constants15.TTL_1M
|
|
24587
24745
|
}
|
|
24588
24746
|
);
|
|
24589
24747
|
if (replayChartSnapshot) {
|
|
24590
24748
|
await Promise.all(
|
|
24591
24749
|
replayChartSnapshot.strategies.map(
|
|
24592
|
-
(card) => (0,
|
|
24593
|
-
|
|
24750
|
+
(card) => (0, import_redis12.setData)(
|
|
24751
|
+
import_redis12.redisKeys.strategyChartCard(replayUserName, "replay", card.cardId),
|
|
24594
24752
|
card,
|
|
24595
24753
|
{
|
|
24596
|
-
expire:
|
|
24754
|
+
expire: import_constants15.TTL_1M
|
|
24597
24755
|
}
|
|
24598
24756
|
)
|
|
24599
24757
|
)
|
|
@@ -25045,7 +25203,7 @@ var init_binanceMarketIngest = __esm({
|
|
|
25045
25203
|
import_client4 = require("@tradejs/infra/timescale/client");
|
|
25046
25204
|
init_binanceMarketData();
|
|
25047
25205
|
import_args9.default.example(
|
|
25048
|
-
"yarn cli:node8g binance:market-ingest --all --symbols BTCUSDT,ETHUSDT --days 0.05 --interval
|
|
25206
|
+
"yarn cli:node8g binance:market-ingest --all --symbols BTCUSDT,ETHUSDT --days 0.05 --interval 15m --write",
|
|
25049
25207
|
"Ingest Binance public market breadth and historical aggTrades buckets"
|
|
25050
25208
|
);
|
|
25051
25209
|
import_args9.default.option(
|
|
@@ -25053,7 +25211,7 @@ var init_binanceMarketIngest = __esm({
|
|
|
25053
25211
|
"Comma-separated target symbols",
|
|
25054
25212
|
"BTCUSDT,ETHUSDT"
|
|
25055
25213
|
);
|
|
25056
|
-
import_args9.default.option(["i", "interval"], "Aggregation interval:
|
|
25214
|
+
import_args9.default.option(["i", "interval"], "Aggregation interval: 5m,15m,1h", "15m");
|
|
25057
25215
|
import_args9.default.option(["d", "days"], "Lookback window in days", "1");
|
|
25058
25216
|
import_args9.default.option(["h", "hours"], "Lookback window in hours; overrides --days");
|
|
25059
25217
|
import_args9.default.option(["a", "aggTrades"], "Fetch and bucket Binance aggTrades");
|
|
@@ -25087,7 +25245,6 @@ var init_binanceMarketIngest = __esm({
|
|
|
25087
25245
|
};
|
|
25088
25246
|
sleep4 = (ms) => ms > 0 ? new Promise((resolve) => setTimeout(resolve, ms)) : Promise.resolve();
|
|
25089
25247
|
intervalToConnectorInterval = (interval4) => {
|
|
25090
|
-
if (interval4 === "1m") return "1";
|
|
25091
25248
|
if (interval4 === "5m") return "5";
|
|
25092
25249
|
if (interval4 === "15m") return "15";
|
|
25093
25250
|
return "60";
|
|
@@ -25143,6 +25300,7 @@ var init_binanceMarketIngest = __esm({
|
|
|
25143
25300
|
main11 = async () => {
|
|
25144
25301
|
const symbols = normalizeBinanceSymbols(flags7.symbols);
|
|
25145
25302
|
const interval4 = normalizeMarketFeatureInterval(flags7.interval);
|
|
25303
|
+
if (interval4 === "1m") throw new Error("Use interval 5m, 15m, or 1h");
|
|
25146
25304
|
const hours = flags7.hours == null ? null : asFloat2(flags7.hours, 0);
|
|
25147
25305
|
const days = hours != null && hours > 0 ? hours / 24 : asFloat2(flags7.days, 1);
|
|
25148
25306
|
const breadthUniverses = (0, import_strategies9.getBinanceBreadthUniverses)();
|
|
@@ -25256,7 +25414,7 @@ var init_binanceMarketIngest = __esm({
|
|
|
25256
25414
|
});
|
|
25257
25415
|
|
|
25258
25416
|
// src/lib/runBot.ts
|
|
25259
|
-
var import_lodash, import_connectors10, import_data7, import_strategies10, import_async3,
|
|
25417
|
+
var import_lodash, import_connectors10, import_data7, import_strategies10, import_async3, import_constants16, import_time9, import_logger3, import_redis13, projectRoot4, runBot;
|
|
25260
25418
|
var init_runBot = __esm({
|
|
25261
25419
|
"src/lib/runBot.ts"() {
|
|
25262
25420
|
"use strict";
|
|
@@ -25265,33 +25423,33 @@ var init_runBot = __esm({
|
|
|
25265
25423
|
import_data7 = require("@tradejs/core/data");
|
|
25266
25424
|
import_strategies10 = require("@tradejs/node/strategies");
|
|
25267
25425
|
import_async3 = require("@tradejs/core/async");
|
|
25268
|
-
|
|
25426
|
+
import_constants16 = require("@tradejs/core/constants");
|
|
25269
25427
|
import_time9 = require("@tradejs/core/time");
|
|
25270
|
-
|
|
25271
|
-
|
|
25428
|
+
import_logger3 = require("@tradejs/infra/logger");
|
|
25429
|
+
import_redis13 = require("@tradejs/infra/redis");
|
|
25272
25430
|
projectRoot4 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
|
|
25273
25431
|
runBot = async () => {
|
|
25274
25432
|
const botResults = [];
|
|
25275
|
-
const preloadStart = (0, import_time9.getTimestamp)(
|
|
25433
|
+
const preloadStart = (0, import_time9.getTimestamp)(import_constants16.BOT_PRELOAD_DAYS);
|
|
25276
25434
|
const end = (0, import_time9.getTimestamp)();
|
|
25277
|
-
const keys = await (0,
|
|
25435
|
+
const keys = await (0, import_redis13.getKeys)(import_redis13.redisKeys.botsPrefix());
|
|
25278
25436
|
const botKeys = keys.filter((key2) => key2.endsWith(":bots"));
|
|
25279
25437
|
await (0, import_async3.delay)(5e3);
|
|
25280
|
-
|
|
25438
|
+
import_logger3.logger.log("info", "files count: %s", botKeys.length);
|
|
25281
25439
|
for await (const key2 of botKeys) {
|
|
25282
25440
|
const userName3 = key2.split(":")[1];
|
|
25283
|
-
|
|
25284
|
-
const botConfig = await (0,
|
|
25441
|
+
import_logger3.logger.log("info", "user: %s", userName3);
|
|
25442
|
+
const botConfig = await (0, import_redis13.getData)(import_redis13.redisKeys.bots(userName3));
|
|
25285
25443
|
if (import_lodash.default.isEmpty(botConfig)) {
|
|
25286
|
-
|
|
25444
|
+
import_logger3.logger.log("error", "botConfig is empty: %s", userName3);
|
|
25287
25445
|
continue;
|
|
25288
25446
|
}
|
|
25289
|
-
|
|
25447
|
+
import_logger3.logger.log("info", "bots count: %s", botConfig.length);
|
|
25290
25448
|
for await (const bot of botConfig) {
|
|
25291
25449
|
const { symbol, strategyName, strategyConfig, connectorName, disabled } = bot;
|
|
25292
|
-
|
|
25450
|
+
import_logger3.logger.log("info", "bot %s", symbol);
|
|
25293
25451
|
if (disabled) {
|
|
25294
|
-
|
|
25452
|
+
import_logger3.logger.log("error", "bot %s disabled", symbol);
|
|
25295
25453
|
continue;
|
|
25296
25454
|
}
|
|
25297
25455
|
try {
|
|
@@ -25371,7 +25529,7 @@ var init_runBot = __esm({
|
|
|
25371
25529
|
btcCoinbaseData,
|
|
25372
25530
|
connector
|
|
25373
25531
|
});
|
|
25374
|
-
|
|
25532
|
+
import_logger3.logger.log("info", "strategy created");
|
|
25375
25533
|
if (!candle || !btcCandle) {
|
|
25376
25534
|
throw new Error("Candle is empty");
|
|
25377
25535
|
}
|
|
@@ -25381,11 +25539,11 @@ var init_runBot = __esm({
|
|
|
25381
25539
|
status: JSON.stringify(status)
|
|
25382
25540
|
});
|
|
25383
25541
|
} catch (err) {
|
|
25384
|
-
|
|
25542
|
+
import_logger3.logger.log("error", "bot %s error: %s", bot.symbol, (0, import_data7.toJson)(err, false));
|
|
25385
25543
|
}
|
|
25386
25544
|
}
|
|
25387
25545
|
}
|
|
25388
|
-
|
|
25546
|
+
import_logger3.logger.log("info", "botResults: %s", (0, import_data7.toJson)(botResults, true));
|
|
25389
25547
|
return botResults;
|
|
25390
25548
|
};
|
|
25391
25549
|
}
|
|
@@ -25809,7 +25967,7 @@ var cleanTests_exports = {};
|
|
|
25809
25967
|
__export(cleanTests_exports, {
|
|
25810
25968
|
main: () => main16
|
|
25811
25969
|
});
|
|
25812
|
-
var import_args13, import_promises20, import_path7, import_chalk25, import_cli8, import_backtestArtifacts2,
|
|
25970
|
+
var import_args13, import_promises20, import_path7, import_chalk25, import_cli8, import_backtestArtifacts2, import_redis14, flags11, extractUsers, getUsersToClean, cleanUserTests, main16;
|
|
25813
25971
|
var init_cleanTests = __esm({
|
|
25814
25972
|
"src/scripts/cleanTests.ts"() {
|
|
25815
25973
|
"use strict";
|
|
@@ -25819,7 +25977,7 @@ var init_cleanTests = __esm({
|
|
|
25819
25977
|
import_chalk25 = __toESM(require("chalk"));
|
|
25820
25978
|
import_cli8 = require("@tradejs/node/cli");
|
|
25821
25979
|
import_backtestArtifacts2 = require("@tradejs/infra/backtestArtifacts");
|
|
25822
|
-
|
|
25980
|
+
import_redis14 = require("@tradejs/infra/redis");
|
|
25823
25981
|
import_args13.default.option(["U", "user"], "Clean tests for user", "");
|
|
25824
25982
|
import_args13.default.option(["C", "cache"], "Clean only cache keys", false);
|
|
25825
25983
|
flags11 = import_args13.default.parse(process.argv);
|
|
@@ -25845,7 +26003,7 @@ var init_cleanTests = __esm({
|
|
|
25845
26003
|
if (userName3) {
|
|
25846
26004
|
return [userName3];
|
|
25847
26005
|
}
|
|
25848
|
-
const keys = await (0,
|
|
26006
|
+
const keys = await (0, import_redis14.getKeys)(import_redis14.redisKeys.users());
|
|
25849
26007
|
return extractUsers(keys);
|
|
25850
26008
|
};
|
|
25851
26009
|
cleanUserTests = async (userName3) => {
|
|
@@ -25894,6 +26052,184 @@ var init_cleanTests = __esm({
|
|
|
25894
26052
|
}
|
|
25895
26053
|
});
|
|
25896
26054
|
|
|
26055
|
+
// src/scripts/coverageBackfill.ts
|
|
26056
|
+
var coverageBackfill_exports = {};
|
|
26057
|
+
__export(coverageBackfill_exports, {
|
|
26058
|
+
main: () => main17
|
|
26059
|
+
});
|
|
26060
|
+
async function fetchTarget(userName3, request, target, loaded) {
|
|
26061
|
+
const { dataset, end } = target;
|
|
26062
|
+
const { series, day } = request;
|
|
26063
|
+
const endMs = end - 1;
|
|
26064
|
+
const interval4 = dataset.interval;
|
|
26065
|
+
const missing = (time2) => time2 >= day && time2 < end && !loaded.has(time2);
|
|
26066
|
+
if (dataset.provider === "CoinMarketCap") {
|
|
26067
|
+
await backfillCoinMarketCapContext({
|
|
26068
|
+
userName: userName3,
|
|
26069
|
+
startMs: day,
|
|
26070
|
+
preloadStartMs: day,
|
|
26071
|
+
endMs: end,
|
|
26072
|
+
repairDataset: dataset.id
|
|
26073
|
+
});
|
|
26074
|
+
return;
|
|
26075
|
+
}
|
|
26076
|
+
if (dataset.provider === "Coinalyze") {
|
|
26077
|
+
if (interval4 !== "15m" && interval4 !== "1h") return;
|
|
26078
|
+
const { apiKey, marketSymbol } = await resolveCoinalyzeBackfillMarket(
|
|
26079
|
+
userName3,
|
|
26080
|
+
series
|
|
26081
|
+
);
|
|
26082
|
+
if (!marketSymbol) return;
|
|
26083
|
+
const { derivativesRows = [] } = await import_connectors11.marketDataProviders.coinalyze.fetchWindow({
|
|
26084
|
+
symbol: series,
|
|
26085
|
+
marketSymbol,
|
|
26086
|
+
apiKey,
|
|
26087
|
+
interval: interval4,
|
|
26088
|
+
fromMs: day,
|
|
26089
|
+
toMs: endMs
|
|
26090
|
+
});
|
|
26091
|
+
await (0, import_derivatives2.upsertDerivatives)(
|
|
26092
|
+
derivativesRows.filter(({ ts }) => missing(ts.getTime())).flatMap((row) => {
|
|
26093
|
+
const { symbol, ts, interval: interval5, source } = row;
|
|
26094
|
+
if (dataset.id.startsWith("coinalyze-open-interest-")) {
|
|
26095
|
+
return row.openInterest == null ? [] : [
|
|
26096
|
+
{
|
|
26097
|
+
symbol,
|
|
26098
|
+
ts,
|
|
26099
|
+
interval: interval5,
|
|
26100
|
+
source,
|
|
26101
|
+
openInterest: row.openInterest
|
|
26102
|
+
}
|
|
26103
|
+
];
|
|
26104
|
+
}
|
|
26105
|
+
if (dataset.id.startsWith("coinalyze-funding-")) {
|
|
26106
|
+
return row.fundingRate == null ? [] : [
|
|
26107
|
+
{
|
|
26108
|
+
symbol,
|
|
26109
|
+
ts,
|
|
26110
|
+
interval: interval5,
|
|
26111
|
+
source,
|
|
26112
|
+
fundingRate: row.fundingRate
|
|
26113
|
+
}
|
|
26114
|
+
];
|
|
26115
|
+
}
|
|
26116
|
+
const { liqLong, liqShort, liqTotal } = row;
|
|
26117
|
+
return liqLong == null && liqShort == null && liqTotal == null ? [] : [{ symbol, ts, interval: interval5, source, liqLong, liqShort, liqTotal }];
|
|
26118
|
+
})
|
|
26119
|
+
);
|
|
26120
|
+
return;
|
|
26121
|
+
}
|
|
26122
|
+
if (dataset.id === "binance-coinbase-spread-15m") {
|
|
26123
|
+
const { spreadRows = [] } = await import_connectors11.marketDataProviders.binance_coinbase_spread.fetchWindow({
|
|
26124
|
+
symbol: series,
|
|
26125
|
+
interval: "15m",
|
|
26126
|
+
fromMs: day,
|
|
26127
|
+
toMs: endMs
|
|
26128
|
+
});
|
|
26129
|
+
await (0, import_spread.upsertSpreadRows)(
|
|
26130
|
+
spreadRows.filter(({ ts }) => missing(ts.getTime()))
|
|
26131
|
+
);
|
|
26132
|
+
return;
|
|
26133
|
+
}
|
|
26134
|
+
const provider = dataset.provider === "Bybit" ? "bybit" : "binance";
|
|
26135
|
+
const connector = await import_connectors11.connectors[provider === "bybit" ? import_connectors11.ConnectorNames.ByBit : import_connectors11.ConnectorNames.Binance]({ userName: userName3 });
|
|
26136
|
+
const connectorInterval = interval4 === "5m" ? "5" : interval4 === "1h" ? "60" : "15";
|
|
26137
|
+
const fetchCandles = async (symbol, start) => {
|
|
26138
|
+
const candles = await connector.kline({
|
|
26139
|
+
symbol,
|
|
26140
|
+
interval: connectorInterval,
|
|
26141
|
+
start,
|
|
26142
|
+
end: endMs,
|
|
26143
|
+
silent: true
|
|
26144
|
+
});
|
|
26145
|
+
return candles.filter(
|
|
26146
|
+
({ timestamp }) => timestamp >= start && timestamp < end
|
|
26147
|
+
);
|
|
26148
|
+
};
|
|
26149
|
+
if (dataset.id.includes("-candles-")) {
|
|
26150
|
+
const candles = (await fetchCandles(series, day)).filter(
|
|
26151
|
+
({ timestamp }) => missing(timestamp)
|
|
26152
|
+
);
|
|
26153
|
+
await (0, import_candles3.upsertCandles)(
|
|
26154
|
+
(0, import_candles3.toRows)(provider, series, Number(connectorInterval), candles)
|
|
26155
|
+
);
|
|
26156
|
+
return;
|
|
26157
|
+
}
|
|
26158
|
+
if (interval4 === "1d") return;
|
|
26159
|
+
if (dataset.id.startsWith("binance-trade-flow-")) {
|
|
26160
|
+
await (0, import_marketContext5.upsertMarketTradeFlowRows)(
|
|
26161
|
+
buildKlineTradeFlowRows({
|
|
26162
|
+
symbol: series,
|
|
26163
|
+
interval: interval4,
|
|
26164
|
+
candles: (await fetchCandles(series, day)).filter(
|
|
26165
|
+
({ timestamp }) => missing(timestamp)
|
|
26166
|
+
)
|
|
26167
|
+
})
|
|
26168
|
+
);
|
|
26169
|
+
return;
|
|
26170
|
+
}
|
|
26171
|
+
const universe = (0, import_strategies11.getBinanceBreadthUniverses)().find(
|
|
26172
|
+
(item) => item.universe === series
|
|
26173
|
+
);
|
|
26174
|
+
if (!universe)
|
|
26175
|
+
throw new Error("The historical Binance basket is unavailable.");
|
|
26176
|
+
const candlesBySymbol = {};
|
|
26177
|
+
const warmup = day - 2 * DAY_MS11;
|
|
26178
|
+
for (let offset = 0; offset < universe.symbols.length; offset += 4) {
|
|
26179
|
+
const entries = await Promise.all(
|
|
26180
|
+
universe.symbols.slice(offset, offset + 4).map(
|
|
26181
|
+
async (symbol) => [symbol, await fetchCandles(symbol, warmup)]
|
|
26182
|
+
)
|
|
26183
|
+
);
|
|
26184
|
+
Object.assign(candlesBySymbol, Object.fromEntries(entries));
|
|
26185
|
+
}
|
|
26186
|
+
const rows = buildMarketBreadthRows({
|
|
26187
|
+
universe: series,
|
|
26188
|
+
interval: interval4,
|
|
26189
|
+
candlesBySymbol,
|
|
26190
|
+
btcCandles: candlesBySymbol.BTCUSDT ?? await fetchCandles("BTCUSDT", warmup)
|
|
26191
|
+
});
|
|
26192
|
+
await (0, import_marketContext5.upsertMarketBreadthRows)(rows.filter(({ ts }) => missing(ts.getTime())));
|
|
26193
|
+
}
|
|
26194
|
+
async function main17() {
|
|
26195
|
+
const [userName3, dataset, series, day] = process.argv.slice(2);
|
|
26196
|
+
const request = { dataset, series, day: Number(day) };
|
|
26197
|
+
const target = (0, import_dataCoverage.resolveDataBackfill)(request);
|
|
26198
|
+
if (!target || !userName3)
|
|
26199
|
+
throw new Error(
|
|
26200
|
+
"Expected user, dataset, series and UTC day in milliseconds."
|
|
26201
|
+
);
|
|
26202
|
+
await (0, import_client5.waitForDbReady)();
|
|
26203
|
+
const before = await (0, import_dataCoverage.readDataBackfillSlots)(request, target.end);
|
|
26204
|
+
if (before.loaded.size < before.expected)
|
|
26205
|
+
await fetchTarget(userName3, request, target, before.loaded);
|
|
26206
|
+
const after = await (0, import_dataCoverage.readDataBackfillSlots)(request, target.end);
|
|
26207
|
+
const result = {
|
|
26208
|
+
loaded: after.loaded.size,
|
|
26209
|
+
added: Math.max(0, after.loaded.size - before.loaded.size),
|
|
26210
|
+
missing: Math.max(0, after.expected - after.loaded.size)
|
|
26211
|
+
};
|
|
26212
|
+
console.log(`TRADEJS_DATA_BACKFILL ${JSON.stringify(result)}`);
|
|
26213
|
+
}
|
|
26214
|
+
var import_connectors11, import_candles3, import_client5, import_dataCoverage, import_derivatives2, import_marketContext5, import_spread, import_strategies11, DAY_MS11;
|
|
26215
|
+
var init_coverageBackfill = __esm({
|
|
26216
|
+
"src/scripts/coverageBackfill.ts"() {
|
|
26217
|
+
"use strict";
|
|
26218
|
+
import_connectors11 = require("@tradejs/connectors");
|
|
26219
|
+
import_candles3 = require("@tradejs/infra/timescale/candles");
|
|
26220
|
+
import_client5 = require("@tradejs/infra/timescale/client");
|
|
26221
|
+
import_dataCoverage = require("@tradejs/infra/timescale/dataCoverage");
|
|
26222
|
+
import_derivatives2 = require("@tradejs/infra/timescale/derivatives");
|
|
26223
|
+
import_marketContext5 = require("@tradejs/infra/timescale/marketContext");
|
|
26224
|
+
import_spread = require("@tradejs/infra/timescale/spread");
|
|
26225
|
+
import_strategies11 = require("@tradejs/node/strategies");
|
|
26226
|
+
init_binanceMarketData();
|
|
26227
|
+
init_coinMarketCapContextBackfill();
|
|
26228
|
+
init_derivativesContextBackfill();
|
|
26229
|
+
DAY_MS11 = 864e5;
|
|
26230
|
+
}
|
|
26231
|
+
});
|
|
26232
|
+
|
|
25897
26233
|
// src/lib/continuity.ts
|
|
25898
26234
|
var import_types6, parseContinuityUniverse, resolveContinuityUniverses, findRepairableContinuityGap;
|
|
25899
26235
|
var init_continuity = __esm({
|
|
@@ -25932,22 +26268,22 @@ var init_continuity = __esm({
|
|
|
25932
26268
|
// src/scripts/continuity.ts
|
|
25933
26269
|
var continuity_exports = {};
|
|
25934
26270
|
__export(continuity_exports, {
|
|
25935
|
-
main: () =>
|
|
26271
|
+
main: () => main18
|
|
25936
26272
|
});
|
|
25937
|
-
var import_args14, import_progress9, import_chalk26,
|
|
26273
|
+
var import_args14, import_progress9, import_chalk26, import_connectors12, import_cli9, import_constants17, import_time10, import_logger4, import_candles4, import_client6, flags12, interval2, intervalKey, projectRoot5, parseProviders, runContinuity, main18;
|
|
25938
26274
|
var init_continuity2 = __esm({
|
|
25939
26275
|
"src/scripts/continuity.ts"() {
|
|
25940
26276
|
"use strict";
|
|
25941
26277
|
import_args14 = __toESM(require("args"));
|
|
25942
26278
|
import_progress9 = __toESM(require("progress"));
|
|
25943
26279
|
import_chalk26 = __toESM(require("chalk"));
|
|
25944
|
-
|
|
26280
|
+
import_connectors12 = require("@tradejs/node/connectors");
|
|
25945
26281
|
import_cli9 = require("@tradejs/node/cli");
|
|
25946
|
-
|
|
26282
|
+
import_constants17 = require("@tradejs/core/constants");
|
|
25947
26283
|
import_time10 = require("@tradejs/core/time");
|
|
25948
|
-
|
|
25949
|
-
|
|
25950
|
-
|
|
26284
|
+
import_logger4 = require("@tradejs/infra/logger");
|
|
26285
|
+
import_candles4 = require("@tradejs/infra/timescale/candles");
|
|
26286
|
+
import_client6 = require("@tradejs/infra/timescale/client");
|
|
25951
26287
|
init_continuity();
|
|
25952
26288
|
import_args14.default.option(["t", "tickers"], "Selected tickers");
|
|
25953
26289
|
import_args14.default.option(["f", "timeframe"], "Timeframe", 15);
|
|
@@ -25963,7 +26299,7 @@ var init_continuity2 = __esm({
|
|
|
25963
26299
|
intervalKey = flags12.timeframe.toString();
|
|
25964
26300
|
projectRoot5 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
|
|
25965
26301
|
parseProviders = async (value) => {
|
|
25966
|
-
const allProviders = await (0,
|
|
26302
|
+
const allProviders = await (0, import_connectors12.getAvailableConnectorProviders)(projectRoot5);
|
|
25967
26303
|
const raw = String(value || "").trim().toLowerCase();
|
|
25968
26304
|
if (!raw || raw === "all") {
|
|
25969
26305
|
return allProviders;
|
|
@@ -25972,7 +26308,7 @@ var init_continuity2 = __esm({
|
|
|
25972
26308
|
const uniqueSelected = [...new Set(selected)];
|
|
25973
26309
|
const invalid = uniqueSelected.filter((item) => !allProviders.includes(item));
|
|
25974
26310
|
if (invalid.length) {
|
|
25975
|
-
|
|
26311
|
+
import_logger4.logger.error(
|
|
25976
26312
|
"Unknown provider(s): %s. Supported: %s",
|
|
25977
26313
|
invalid.join(", "),
|
|
25978
26314
|
allProviders.join(", ")
|
|
@@ -26007,7 +26343,7 @@ var init_continuity2 = __esm({
|
|
|
26007
26343
|
let broken = 0;
|
|
26008
26344
|
let fixed = 0;
|
|
26009
26345
|
const expectedMs = interval2 * 60 * 1e3;
|
|
26010
|
-
|
|
26346
|
+
import_logger4.logger.info(
|
|
26011
26347
|
import_chalk26.default.yellow(`continuity ${connectorName}:${universe}: ${tickers.length}`)
|
|
26012
26348
|
);
|
|
26013
26349
|
for await (const symbol of tickers) {
|
|
@@ -26021,7 +26357,7 @@ var init_continuity2 = __esm({
|
|
|
26021
26357
|
let gap = findRepairableContinuityGap(data, expectedMs, universe);
|
|
26022
26358
|
if (gap) {
|
|
26023
26359
|
broken++;
|
|
26024
|
-
|
|
26360
|
+
import_logger4.logger.warn(
|
|
26025
26361
|
"[%s:%s] gap %s %s: %s -> %s (%ss)",
|
|
26026
26362
|
provider,
|
|
26027
26363
|
universe,
|
|
@@ -26031,7 +26367,7 @@ var init_continuity2 = __esm({
|
|
|
26031
26367
|
(0, import_time10.formatUnix)(gap.ts),
|
|
26032
26368
|
gap.diffSeconds
|
|
26033
26369
|
);
|
|
26034
|
-
await (0,
|
|
26370
|
+
await (0, import_candles4.deleteCandles)(provider, symbol, interval2);
|
|
26035
26371
|
const reloaded = await connector.kline({
|
|
26036
26372
|
symbol,
|
|
26037
26373
|
interval: intervalKey,
|
|
@@ -26050,47 +26386,47 @@ var init_continuity2 = __esm({
|
|
|
26050
26386
|
symbol: import_chalk26.default.gray(symbol)
|
|
26051
26387
|
});
|
|
26052
26388
|
}
|
|
26053
|
-
|
|
26389
|
+
import_logger4.logger.info(
|
|
26054
26390
|
import_chalk26.default.yellow(
|
|
26055
26391
|
`[${provider}:${universe}] broken: ${broken}/${tickers.length}, fixed: ${fixed}`
|
|
26056
26392
|
)
|
|
26057
26393
|
);
|
|
26058
26394
|
};
|
|
26059
|
-
|
|
26395
|
+
main18 = async () => {
|
|
26060
26396
|
if (!Number.isFinite(interval2) || interval2 <= 0) {
|
|
26061
|
-
|
|
26397
|
+
import_logger4.logger.error("Invalid timeframe: %s", flags12.timeframe);
|
|
26062
26398
|
process.exit(1);
|
|
26063
26399
|
}
|
|
26064
|
-
await (0,
|
|
26065
|
-
const reloadStart = (0, import_time10.getTimestamp)(
|
|
26400
|
+
await (0, import_client6.waitForDbReady)();
|
|
26401
|
+
const reloadStart = (0, import_time10.getTimestamp)(import_constants17.PRELOAD_DAYS);
|
|
26066
26402
|
const reloadEnd = (0, import_time10.getTimestamp)();
|
|
26067
26403
|
let requestedUniverse;
|
|
26068
26404
|
try {
|
|
26069
26405
|
requestedUniverse = parseContinuityUniverse(flags12.universe);
|
|
26070
26406
|
} catch (error) {
|
|
26071
|
-
|
|
26407
|
+
import_logger4.logger.error(error.message);
|
|
26072
26408
|
process.exit(1);
|
|
26073
26409
|
}
|
|
26074
26410
|
const providerIds = await parseProviders(flags12.provider);
|
|
26075
26411
|
const providers = await Promise.all(
|
|
26076
26412
|
providerIds.map(async (providerId) => {
|
|
26077
|
-
const connectorName = await (0,
|
|
26413
|
+
const connectorName = await (0, import_connectors12.getConnectorNameByProvider)(
|
|
26078
26414
|
providerId,
|
|
26079
26415
|
projectRoot5
|
|
26080
26416
|
);
|
|
26081
26417
|
if (!connectorName) {
|
|
26082
|
-
|
|
26418
|
+
import_logger4.logger.warn(
|
|
26083
26419
|
'Skip provider "%s": connector mapping is missing',
|
|
26084
26420
|
providerId
|
|
26085
26421
|
);
|
|
26086
26422
|
return null;
|
|
26087
26423
|
}
|
|
26088
|
-
const creator = await (0,
|
|
26424
|
+
const creator = await (0, import_connectors12.getConnectorCreatorByName)(
|
|
26089
26425
|
connectorName,
|
|
26090
26426
|
projectRoot5
|
|
26091
26427
|
);
|
|
26092
26428
|
if (!creator) {
|
|
26093
|
-
|
|
26429
|
+
import_logger4.logger.warn(
|
|
26094
26430
|
'Skip provider "%s": connector "%s" is not registered',
|
|
26095
26431
|
providerId,
|
|
26096
26432
|
connectorName
|
|
@@ -26106,7 +26442,7 @@ var init_continuity2 = __esm({
|
|
|
26106
26442
|
);
|
|
26107
26443
|
const activeProviders = providers.filter(Boolean);
|
|
26108
26444
|
if (!activeProviders.length) {
|
|
26109
|
-
|
|
26445
|
+
import_logger4.logger.error("No connector providers available");
|
|
26110
26446
|
process.exit(1);
|
|
26111
26447
|
}
|
|
26112
26448
|
for await (const provider of activeProviders) {
|
|
@@ -26118,7 +26454,7 @@ var init_continuity2 = __esm({
|
|
|
26118
26454
|
defaultConnector.capabilities.supportedUniverses
|
|
26119
26455
|
);
|
|
26120
26456
|
if (!universes.length) {
|
|
26121
|
-
|
|
26457
|
+
import_logger4.logger.warn(
|
|
26122
26458
|
'Skip provider "%s": universe "%s" is not supported',
|
|
26123
26459
|
provider.id,
|
|
26124
26460
|
requestedUniverse
|
|
@@ -26147,9 +26483,9 @@ var init_continuity2 = __esm({
|
|
|
26147
26483
|
// src/scripts/derivativesIngest.ts
|
|
26148
26484
|
var derivativesIngest_exports = {};
|
|
26149
26485
|
__export(derivativesIngest_exports, {
|
|
26150
|
-
main: () =>
|
|
26486
|
+
main: () => main19
|
|
26151
26487
|
});
|
|
26152
|
-
var import_config4, import_args15, import_chalk27, import_indicators3,
|
|
26488
|
+
var import_config4, import_args15, import_chalk27, import_indicators3, import_client7, import_derivatives3, import_spread2, import_userSettings5, import_connectors13, flags13, asInt5, main19;
|
|
26153
26489
|
var init_derivativesIngest = __esm({
|
|
26154
26490
|
"src/scripts/derivativesIngest.ts"() {
|
|
26155
26491
|
"use strict";
|
|
@@ -26157,11 +26493,11 @@ var init_derivativesIngest = __esm({
|
|
|
26157
26493
|
import_args15 = __toESM(require("args"));
|
|
26158
26494
|
import_chalk27 = __toESM(require("chalk"));
|
|
26159
26495
|
import_indicators3 = require("@tradejs/core/indicators");
|
|
26160
|
-
|
|
26161
|
-
|
|
26162
|
-
|
|
26496
|
+
import_client7 = require("@tradejs/infra/timescale/client");
|
|
26497
|
+
import_derivatives3 = require("@tradejs/infra/timescale/derivatives");
|
|
26498
|
+
import_spread2 = require("@tradejs/infra/timescale/spread");
|
|
26163
26499
|
import_userSettings5 = require("@tradejs/infra/userSettings");
|
|
26164
|
-
|
|
26500
|
+
import_connectors13 = require("@tradejs/connectors");
|
|
26165
26501
|
import_args15.default.example(
|
|
26166
26502
|
"yarn ts-node ./src/scripts/derivativesIngest --provider coinalyze --symbols BTCUSDT,ETHUSDT --intervals 15m --days 120",
|
|
26167
26503
|
"Ingest market features (derivatives/spread) into Timescale by provider"
|
|
@@ -26181,9 +26517,9 @@ var init_derivativesIngest = __esm({
|
|
|
26181
26517
|
const parsed = Number.parseInt(String(value ?? ""), 10);
|
|
26182
26518
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
26183
26519
|
};
|
|
26184
|
-
|
|
26520
|
+
main19 = async () => {
|
|
26185
26521
|
const providerName = String(flags13.provider || "coinalyze").trim().toLowerCase();
|
|
26186
|
-
const provider =
|
|
26522
|
+
const provider = import_connectors13.marketDataProviders[providerName];
|
|
26187
26523
|
if (!provider) {
|
|
26188
26524
|
throw new Error(`Unsupported provider: ${providerName}`);
|
|
26189
26525
|
}
|
|
@@ -26197,7 +26533,7 @@ var init_derivativesIngest = __esm({
|
|
|
26197
26533
|
const coinalyzeApiKey = providerName === "coinalyze" ? (await (0, import_userSettings5.getUserSettings)(userName3)).COINALYZE_API_KEY : void 0;
|
|
26198
26534
|
if (!symbols.length) throw new Error("No symbols provided");
|
|
26199
26535
|
if (!intervals.length) throw new Error("No intervals provided");
|
|
26200
|
-
await (0,
|
|
26536
|
+
await (0, import_client7.waitForDbReady)();
|
|
26201
26537
|
const now2 = Date.now();
|
|
26202
26538
|
const fromMs = now2 - days * 24 * 60 * 60 * 1e3;
|
|
26203
26539
|
let totalDerivativesRows = 0;
|
|
@@ -26226,12 +26562,12 @@ var init_derivativesIngest = __esm({
|
|
|
26226
26562
|
});
|
|
26227
26563
|
const derivativesRows = window.derivativesRows ?? [];
|
|
26228
26564
|
if (derivativesRows.length) {
|
|
26229
|
-
await (0,
|
|
26565
|
+
await (0, import_derivatives3.upsertDerivatives)(derivativesRows);
|
|
26230
26566
|
totalDerivativesRows += derivativesRows.length;
|
|
26231
26567
|
}
|
|
26232
26568
|
const spreadRows = window.spreadRows ?? [];
|
|
26233
26569
|
if (spreadRows.length) {
|
|
26234
|
-
await (0,
|
|
26570
|
+
await (0, import_spread2.upsertSpreadRows)(spreadRows);
|
|
26235
26571
|
totalSpreadRows += spreadRows.length;
|
|
26236
26572
|
}
|
|
26237
26573
|
cursor = toMs + 1;
|
|
@@ -26251,9 +26587,9 @@ var init_derivativesIngest = __esm({
|
|
|
26251
26587
|
// src/scripts/derivativesIngestCoinalyzeAll.ts
|
|
26252
26588
|
var derivativesIngestCoinalyzeAll_exports = {};
|
|
26253
26589
|
__export(derivativesIngestCoinalyzeAll_exports, {
|
|
26254
|
-
main: () =>
|
|
26590
|
+
main: () => main20
|
|
26255
26591
|
});
|
|
26256
|
-
var import_config5, import_args16, import_chalk28, import_progress10, import_lodash2,
|
|
26592
|
+
var import_config5, import_args16, import_chalk28, import_progress10, import_lodash2, import_connectors14, import_indicators4, import_async4, import_userSettings6, import_cli10, import_derivatives4, import_client8, coinalyzeIntervalMap2, flags14, asInt6, parseList2, coinalyzeBaseUrl, coinalyzeMaxRetries, lastRequestTs3, fetchJsonWithRateLimit2, fetchCoinalyzeMarkets2, selectBestMarket2, buildMatches2, normalizeMetricPoint2, toSeriesMap2, fetchMetricBatch2, main20;
|
|
26257
26593
|
var init_derivativesIngestCoinalyzeAll = __esm({
|
|
26258
26594
|
"src/scripts/derivativesIngestCoinalyzeAll.ts"() {
|
|
26259
26595
|
"use strict";
|
|
@@ -26262,13 +26598,13 @@ var init_derivativesIngestCoinalyzeAll = __esm({
|
|
|
26262
26598
|
import_chalk28 = __toESM(require("chalk"));
|
|
26263
26599
|
import_progress10 = __toESM(require("progress"));
|
|
26264
26600
|
import_lodash2 = __toESM(require("lodash"));
|
|
26265
|
-
|
|
26601
|
+
import_connectors14 = require("@tradejs/connectors");
|
|
26266
26602
|
import_indicators4 = require("@tradejs/core/indicators");
|
|
26267
26603
|
import_async4 = require("@tradejs/core/async");
|
|
26268
26604
|
import_userSettings6 = require("@tradejs/infra/userSettings");
|
|
26269
26605
|
import_cli10 = require("@tradejs/node/cli");
|
|
26270
|
-
|
|
26271
|
-
|
|
26606
|
+
import_derivatives4 = require("@tradejs/infra/timescale/derivatives");
|
|
26607
|
+
import_client8 = require("@tradejs/infra/timescale/client");
|
|
26272
26608
|
coinalyzeIntervalMap2 = {
|
|
26273
26609
|
"15m": "15min",
|
|
26274
26610
|
"1h": "1hour"
|
|
@@ -26462,7 +26798,7 @@ var init_derivativesIngestCoinalyzeAll = __esm({
|
|
|
26462
26798
|
const raw = await fetchJsonWithRateLimit2(url.toString(), apiKey);
|
|
26463
26799
|
return toSeriesMap2(raw, metric);
|
|
26464
26800
|
};
|
|
26465
|
-
|
|
26801
|
+
main20 = async () => {
|
|
26466
26802
|
const userName3 = String(flags14.user || "root").trim() || "root";
|
|
26467
26803
|
const intervals = (0, import_indicators4.normalizeDerivativesIntervals)(
|
|
26468
26804
|
flags14.intervals
|
|
@@ -26480,7 +26816,7 @@ var init_derivativesIngestCoinalyzeAll = __esm({
|
|
|
26480
26816
|
`Missing COINALYZE_API_KEY in user settings for user ${userName3}`
|
|
26481
26817
|
);
|
|
26482
26818
|
}
|
|
26483
|
-
const connectorFactory =
|
|
26819
|
+
const connectorFactory = import_connectors14.connectors[import_connectors14.ConnectorNames.ByBit];
|
|
26484
26820
|
const bybit = await connectorFactory({
|
|
26485
26821
|
userName: userName3
|
|
26486
26822
|
});
|
|
@@ -26532,7 +26868,7 @@ var init_derivativesIngestCoinalyzeAll = __esm({
|
|
|
26532
26868
|
);
|
|
26533
26869
|
return;
|
|
26534
26870
|
}
|
|
26535
|
-
await (0,
|
|
26871
|
+
await (0, import_client8.waitForDbReady)();
|
|
26536
26872
|
const now2 = Date.now();
|
|
26537
26873
|
const fromMs = now2 - days * 24 * 60 * 60 * 1e3;
|
|
26538
26874
|
const symbolBatches = import_lodash2.default.chunk(matches2, symbolBatchSize);
|
|
@@ -26600,7 +26936,7 @@ var init_derivativesIngestCoinalyzeAll = __esm({
|
|
|
26600
26936
|
return (0, import_indicators4.coinalyzePointsToRows)(points, interval4, "coinalyze");
|
|
26601
26937
|
});
|
|
26602
26938
|
if (rows.length) {
|
|
26603
|
-
await (0,
|
|
26939
|
+
await (0, import_derivatives4.upsertDerivatives)(rows);
|
|
26604
26940
|
totalRows += rows.length;
|
|
26605
26941
|
}
|
|
26606
26942
|
const confirmedLiquidationWindow = (0, import_indicators4.resolveCoinalyzeConfirmedIntradayCoverage)({
|
|
@@ -26610,7 +26946,7 @@ var init_derivativesIngestCoinalyzeAll = __esm({
|
|
|
26610
26946
|
nowMs: now2
|
|
26611
26947
|
});
|
|
26612
26948
|
if (confirmedLiquidationWindow) {
|
|
26613
|
-
await (0,
|
|
26949
|
+
await (0, import_derivatives4.applyDerivativesMetricCoverage)(
|
|
26614
26950
|
batch.map((item) => {
|
|
26615
26951
|
const marketSymbol = item.marketSymbol.toUpperCase();
|
|
26616
26952
|
const eventRowsCount = (liqMap.get(marketSymbol) ?? []).filter(
|
|
@@ -26669,9 +27005,9 @@ var init_derivativesIngestCoinalyzeAll = __esm({
|
|
|
26669
27005
|
// src/scripts/doctor.ts
|
|
26670
27006
|
var doctor_exports = {};
|
|
26671
27007
|
__export(doctor_exports, {
|
|
26672
|
-
main: () =>
|
|
27008
|
+
main: () => main21
|
|
26673
27009
|
});
|
|
26674
|
-
var import_config6, import_args17, import_chalk29, import_ioredis, import_pg2, import_node_net, okLabel, failLabel, infoLabel, toPort, parseAddress, checkRedis, checkPostgres, checkMlGrpc, flags15,
|
|
27010
|
+
var import_config6, import_args17, import_chalk29, import_ioredis, import_pg2, import_node_net, okLabel, failLabel, infoLabel, toPort, parseAddress, checkRedis, checkPostgres, checkMlGrpc, flags15, main21;
|
|
26675
27011
|
var init_doctor = __esm({
|
|
26676
27012
|
"src/scripts/doctor.ts"() {
|
|
26677
27013
|
"use strict";
|
|
@@ -26796,7 +27132,7 @@ var init_doctor = __esm({
|
|
|
26796
27132
|
};
|
|
26797
27133
|
import_args17.default.option("require-ml", "Treat ML gRPC connectivity as required", false).option("skip-ml", "Skip ML gRPC check", false);
|
|
26798
27134
|
flags15 = import_args17.default.parse(process.argv);
|
|
26799
|
-
|
|
27135
|
+
main21 = async () => {
|
|
26800
27136
|
const checks = [];
|
|
26801
27137
|
checks.push(await checkRedis());
|
|
26802
27138
|
checks.push(await checkPostgres());
|
|
@@ -26844,11 +27180,11 @@ var init_doctor = __esm({
|
|
|
26844
27180
|
});
|
|
26845
27181
|
|
|
26846
27182
|
// src/lib/executionCalibration.ts
|
|
26847
|
-
var
|
|
27183
|
+
var import_constants18, import_data8, import_trade3, roundMetric, asRecord3, asArray, finiteNumber2, finiteString, finiteDirection, metricValues, quantile2, summarizeNumbers, getIntervalMs, getSignalKey, addSignalToMap, getRuntimePayload, extractRuntimeTradeRows, normalizeReplayMatch, extractReplayMatches, buildReplayMatchMaps, getSignalCandles, adverseEntryBps, feeBps, latencyDelta, resolveTelemetryQuality, finiteTelemetryQuality, countBy, toLatencyBucket, toSpreadBucket, buildSample, buildReplayOnlySample, hasTelemetry, hasFullTelemetry, buildGroupSummary, groupSamples, positiveMetricValues, buildRecommendation, buildExecutionCalibrationReport;
|
|
26848
27184
|
var init_executionCalibration = __esm({
|
|
26849
27185
|
"src/lib/executionCalibration.ts"() {
|
|
26850
27186
|
"use strict";
|
|
26851
|
-
|
|
27187
|
+
import_constants18 = require("@tradejs/core/constants");
|
|
26852
27188
|
import_data8 = require("@tradejs/core/data");
|
|
26853
27189
|
import_trade3 = require("@tradejs/core/trade");
|
|
26854
27190
|
roundMetric = (value, decimals = 6) => typeof value === "number" && Number.isFinite(value) ? Number(value.toFixed(decimals)) : null;
|
|
@@ -27233,7 +27569,7 @@ var init_executionCalibration = __esm({
|
|
|
27233
27569
|
actualPrice: fillAvgPrice
|
|
27234
27570
|
});
|
|
27235
27571
|
const currentModelEntrySlippageBps = signalToFillAdverseBps != null ? roundMetric(
|
|
27236
|
-
|
|
27572
|
+
import_constants18.BACKTEST_BASE_SLIPPAGE_BPS + (spreadBps ?? 0) * import_constants18.BACKTEST_SPREAD_SLIPPAGE_MULTIPLIER + import_constants18.BACKTEST_MARKET_IMPACT_BPS + (currentDelayRiskBps ?? 0)
|
|
27237
27573
|
) : null;
|
|
27238
27574
|
const residualVsCurrentModelBps = signalToFillAdverseBps != null && currentModelEntrySlippageBps != null ? roundMetric(signalToFillAdverseBps - currentModelEntrySlippageBps) : null;
|
|
27239
27575
|
return {
|
|
@@ -27428,7 +27764,7 @@ var init_executionCalibration = __esm({
|
|
|
27428
27764
|
}
|
|
27429
27765
|
return Math.max(
|
|
27430
27766
|
0,
|
|
27431
|
-
sample.arrivalToFillAdverseBps - (sample.spreadBps ?? 0) * (spreadMultiplier ??
|
|
27767
|
+
sample.arrivalToFillAdverseBps - (sample.spreadBps ?? 0) * (spreadMultiplier ?? import_constants18.BACKTEST_SPREAD_SLIPPAGE_MULTIPLIER)
|
|
27432
27768
|
);
|
|
27433
27769
|
}).filter(
|
|
27434
27770
|
(value) => value != null && Number.isFinite(value)
|
|
@@ -27491,9 +27827,9 @@ var init_executionCalibration = __esm({
|
|
|
27491
27827
|
generatedAt: nowMs,
|
|
27492
27828
|
sources: sourcePaths,
|
|
27493
27829
|
currentModel: {
|
|
27494
|
-
baseSlippageBps:
|
|
27495
|
-
spreadMultiplier:
|
|
27496
|
-
marketImpactBps:
|
|
27830
|
+
baseSlippageBps: import_constants18.BACKTEST_BASE_SLIPPAGE_BPS,
|
|
27831
|
+
spreadMultiplier: import_constants18.BACKTEST_SPREAD_SLIPPAGE_MULTIPLIER,
|
|
27832
|
+
marketImpactBps: import_constants18.BACKTEST_MARKET_IMPACT_BPS
|
|
27497
27833
|
},
|
|
27498
27834
|
counts: {
|
|
27499
27835
|
runtimeTrades: runtimeRows.length,
|
|
@@ -27534,9 +27870,9 @@ var init_executionCalibration = __esm({
|
|
|
27534
27870
|
var executionCalibration_exports = {};
|
|
27535
27871
|
__export(executionCalibration_exports, {
|
|
27536
27872
|
executionCalibration: () => executionCalibration,
|
|
27537
|
-
main: () =>
|
|
27873
|
+
main: () => main22
|
|
27538
27874
|
});
|
|
27539
|
-
var import_promises21, import_node_path17, import_args18, import_chalk30, flags16, projectRoot6, readJsonFile, resolveInputPath, executionCalibration,
|
|
27875
|
+
var import_promises21, import_node_path17, import_args18, import_chalk30, flags16, projectRoot6, readJsonFile, resolveInputPath, executionCalibration, main22;
|
|
27540
27876
|
var init_executionCalibration2 = __esm({
|
|
27541
27877
|
"src/scripts/executionCalibration.ts"() {
|
|
27542
27878
|
"use strict";
|
|
@@ -27611,7 +27947,7 @@ var init_executionCalibration2 = __esm({
|
|
|
27611
27947
|
)
|
|
27612
27948
|
);
|
|
27613
27949
|
};
|
|
27614
|
-
|
|
27950
|
+
main22 = executionCalibration;
|
|
27615
27951
|
}
|
|
27616
27952
|
});
|
|
27617
27953
|
|
|
@@ -27729,15 +28065,15 @@ volumes:
|
|
|
27729
28065
|
// src/scripts/infraDown.ts
|
|
27730
28066
|
var infraDown_exports = {};
|
|
27731
28067
|
__export(infraDown_exports, {
|
|
27732
|
-
main: () =>
|
|
28068
|
+
main: () => main23
|
|
27733
28069
|
});
|
|
27734
|
-
var import_chalk32,
|
|
28070
|
+
var import_chalk32, main23;
|
|
27735
28071
|
var init_infraDown = __esm({
|
|
27736
28072
|
"src/scripts/infraDown.ts"() {
|
|
27737
28073
|
"use strict";
|
|
27738
28074
|
import_chalk32 = __toESM(require("chalk"));
|
|
27739
28075
|
init_infraCommon();
|
|
27740
|
-
|
|
28076
|
+
main23 = async () => {
|
|
27741
28077
|
const composePath = requireDevComposeFile();
|
|
27742
28078
|
console.log(import_chalk32.default.cyan("Stopping dev infra (timescale, redis)..."));
|
|
27743
28079
|
runDockerCompose(composePath, ["stop", "timescale", "redis"]);
|
|
@@ -27749,15 +28085,15 @@ var init_infraDown = __esm({
|
|
|
27749
28085
|
// src/scripts/infraInit.ts
|
|
27750
28086
|
var infraInit_exports = {};
|
|
27751
28087
|
__export(infraInit_exports, {
|
|
27752
|
-
main: () =>
|
|
28088
|
+
main: () => main24
|
|
27753
28089
|
});
|
|
27754
|
-
var import_chalk33,
|
|
28090
|
+
var import_chalk33, main24;
|
|
27755
28091
|
var init_infraInit = __esm({
|
|
27756
28092
|
"src/scripts/infraInit.ts"() {
|
|
27757
28093
|
"use strict";
|
|
27758
28094
|
import_chalk33 = __toESM(require("chalk"));
|
|
27759
28095
|
init_infraCommon();
|
|
27760
|
-
|
|
28096
|
+
main24 = async () => {
|
|
27761
28097
|
initDevComposeFile();
|
|
27762
28098
|
console.log(import_chalk33.default.green("Dev infra files are initialized."));
|
|
27763
28099
|
};
|
|
@@ -27767,15 +28103,15 @@ var init_infraInit = __esm({
|
|
|
27767
28103
|
// src/scripts/infraUp.ts
|
|
27768
28104
|
var infraUp_exports = {};
|
|
27769
28105
|
__export(infraUp_exports, {
|
|
27770
|
-
main: () =>
|
|
28106
|
+
main: () => main25
|
|
27771
28107
|
});
|
|
27772
|
-
var import_chalk34,
|
|
28108
|
+
var import_chalk34, main25;
|
|
27773
28109
|
var init_infraUp = __esm({
|
|
27774
28110
|
"src/scripts/infraUp.ts"() {
|
|
27775
28111
|
"use strict";
|
|
27776
28112
|
import_chalk34 = __toESM(require("chalk"));
|
|
27777
28113
|
init_infraCommon();
|
|
27778
|
-
|
|
28114
|
+
main25 = async () => {
|
|
27779
28115
|
const composePath = requireDevComposeFile();
|
|
27780
28116
|
console.log(import_chalk34.default.cyan("Starting dev infra (timescale, redis)..."));
|
|
27781
28117
|
runDockerCompose(composePath, [
|
|
@@ -27795,27 +28131,27 @@ var init_infraUp = __esm({
|
|
|
27795
28131
|
// src/scripts/cleanupMarketContext.ts
|
|
27796
28132
|
var cleanupMarketContext_exports = {};
|
|
27797
28133
|
__export(cleanupMarketContext_exports, {
|
|
27798
|
-
main: () =>
|
|
28134
|
+
main: () => main26
|
|
27799
28135
|
});
|
|
27800
|
-
var import_config7, import_args19, import_chalk35,
|
|
28136
|
+
var import_config7, import_args19, import_chalk35, import_client9, import_marketContext6, flags17, main26;
|
|
27801
28137
|
var init_cleanupMarketContext = __esm({
|
|
27802
28138
|
"src/scripts/cleanupMarketContext.ts"() {
|
|
27803
28139
|
"use strict";
|
|
27804
28140
|
import_config7 = require("dotenv/config");
|
|
27805
28141
|
import_args19 = __toESM(require("args"));
|
|
27806
28142
|
import_chalk35 = __toESM(require("chalk"));
|
|
27807
|
-
|
|
27808
|
-
|
|
28143
|
+
import_client9 = require("@tradejs/infra/timescale/client");
|
|
28144
|
+
import_marketContext6 = require("@tradejs/infra/timescale/marketContext");
|
|
27809
28145
|
import_args19.default.example(
|
|
27810
28146
|
"yarn cli maintenance:cleanup-market-context --apply",
|
|
27811
28147
|
"Remove deprecated snapshot-only market context data from Timescale"
|
|
27812
28148
|
);
|
|
27813
28149
|
import_args19.default.option(["a", "apply"], "Apply destructive cleanup; default is dry-run");
|
|
27814
28150
|
flags17 = import_args19.default.parse(process.argv);
|
|
27815
|
-
|
|
28151
|
+
main26 = async () => {
|
|
27816
28152
|
const apply = Boolean(flags17.apply);
|
|
27817
|
-
await (0,
|
|
27818
|
-
const items = await (0,
|
|
28153
|
+
await (0, import_client9.waitForDbReady)();
|
|
28154
|
+
const items = await (0, import_marketContext6.cleanupDeprecatedMarketContext)({ apply });
|
|
27819
28155
|
if (!items.length) {
|
|
27820
28156
|
console.log(import_chalk35.default.green("No deprecated market context data found."));
|
|
27821
28157
|
return;
|
|
@@ -27838,17 +28174,17 @@ var init_cleanupMarketContext = __esm({
|
|
|
27838
28174
|
// src/scripts/migration.ts
|
|
27839
28175
|
var migration_exports = {};
|
|
27840
28176
|
__export(migration_exports, {
|
|
27841
|
-
main: () =>
|
|
28177
|
+
main: () => main27
|
|
27842
28178
|
});
|
|
27843
|
-
var import_progress11, import_chalk36,
|
|
28179
|
+
var import_progress11, import_chalk36, import_logger5, import_files, import_candles5, DIR, re, BATCH, projectRoot7, migrateFile, main27;
|
|
27844
28180
|
var init_migration = __esm({
|
|
27845
28181
|
"src/scripts/migration.ts"() {
|
|
27846
28182
|
"use strict";
|
|
27847
28183
|
import_progress11 = __toESM(require("progress"));
|
|
27848
28184
|
import_chalk36 = __toESM(require("chalk"));
|
|
27849
|
-
|
|
28185
|
+
import_logger5 = require("@tradejs/infra/logger");
|
|
27850
28186
|
import_files = require("@tradejs/infra/files");
|
|
27851
|
-
|
|
28187
|
+
import_candles5 = require("@tradejs/infra/timescale/candles");
|
|
27852
28188
|
DIR = "data/history";
|
|
27853
28189
|
re = /^(.+?)_(\d+)\.json$/;
|
|
27854
28190
|
BATCH = 2e3;
|
|
@@ -27864,12 +28200,12 @@ var init_migration = __esm({
|
|
|
27864
28200
|
[],
|
|
27865
28201
|
projectRoot7
|
|
27866
28202
|
);
|
|
27867
|
-
const rows = (0,
|
|
28203
|
+
const rows = (0, import_candles5.toRows)("bybit", symbol, interval4, data);
|
|
27868
28204
|
for (let i = 0; i < rows.length; i += BATCH) {
|
|
27869
|
-
await (0,
|
|
28205
|
+
await (0, import_candles5.upsertCandles)(rows.slice(i, i + BATCH));
|
|
27870
28206
|
}
|
|
27871
28207
|
};
|
|
27872
|
-
|
|
28208
|
+
main27 = async () => {
|
|
27873
28209
|
const files = await (0, import_files.getFiles)(DIR, projectRoot7);
|
|
27874
28210
|
const bar = new import_progress11.default(
|
|
27875
28211
|
":current/:total [:bar][:percent] :eta(s) :file",
|
|
@@ -27882,7 +28218,7 @@ var init_migration = __esm({
|
|
|
27882
28218
|
try {
|
|
27883
28219
|
await migrateFile(file);
|
|
27884
28220
|
} catch (e) {
|
|
27885
|
-
|
|
28221
|
+
import_logger5.logger.error("Failed: %s %s", file, e);
|
|
27886
28222
|
} finally {
|
|
27887
28223
|
bar.tick(1, {
|
|
27888
28224
|
file: import_chalk36.default.gray(file)
|
|
@@ -27895,12 +28231,12 @@ var init_migration = __esm({
|
|
|
27895
28231
|
});
|
|
27896
28232
|
|
|
27897
28233
|
// src/lib/marketData/klineEvents.ts
|
|
27898
|
-
var import_ioredis2,
|
|
28234
|
+
var import_ioredis2, import_redis15, MARKET_KLINE_CHANNEL, positiveInt2, redisOptions, buildMarketKlineTopic, publishMarketKlineEvent, createMarketKlineSubscriber, parseMarketKlineEvent;
|
|
27899
28235
|
var init_klineEvents = __esm({
|
|
27900
28236
|
"src/lib/marketData/klineEvents.ts"() {
|
|
27901
28237
|
"use strict";
|
|
27902
28238
|
import_ioredis2 = __toESM(require("ioredis"));
|
|
27903
|
-
|
|
28239
|
+
import_redis15 = require("@tradejs/infra/redis");
|
|
27904
28240
|
MARKET_KLINE_CHANNEL = "tradejs:market:kline";
|
|
27905
28241
|
positiveInt2 = (value, fallback) => {
|
|
27906
28242
|
const parsed = Number(value);
|
|
@@ -27919,7 +28255,7 @@ var init_klineEvents = __esm({
|
|
|
27919
28255
|
event.symbol.trim().toUpperCase(),
|
|
27920
28256
|
event.interval
|
|
27921
28257
|
].join(":");
|
|
27922
|
-
publishMarketKlineEvent = (event) => (0,
|
|
28258
|
+
publishMarketKlineEvent = (event) => (0, import_redis15.publishData)(MARKET_KLINE_CHANNEL, event);
|
|
27923
28259
|
createMarketKlineSubscriber = () => new import_ioredis2.default(redisOptions());
|
|
27924
28260
|
parseMarketKlineEvent = (payload) => {
|
|
27925
28261
|
try {
|
|
@@ -27936,13 +28272,13 @@ var init_klineEvents = __esm({
|
|
|
27936
28272
|
});
|
|
27937
28273
|
|
|
27938
28274
|
// src/lib/marketData/marketWsGateway.ts
|
|
27939
|
-
var import_http, import_ws,
|
|
28275
|
+
var import_http, import_ws, import_logger6, MAX_TOPICS_PER_CLIENT, TOPIC_PATTERN, parseSubscriptionCommand, applySubscriptionCommand, startMarketWsGateway;
|
|
27940
28276
|
var init_marketWsGateway = __esm({
|
|
27941
28277
|
"src/lib/marketData/marketWsGateway.ts"() {
|
|
27942
28278
|
"use strict";
|
|
27943
28279
|
import_http = __toESM(require("http"));
|
|
27944
28280
|
import_ws = require("ws");
|
|
27945
|
-
|
|
28281
|
+
import_logger6 = require("@tradejs/infra/logger");
|
|
27946
28282
|
init_klineEvents();
|
|
27947
28283
|
MAX_TOPICS_PER_CLIENT = 20;
|
|
27948
28284
|
TOPIC_PATTERN = /^(bybit|binance|coinbase):(crypto|tradfi):[A-Z0-9._-]+:(1|3|5|15|30|60|120|240|360|720|D|W|M)$/;
|
|
@@ -28056,7 +28392,7 @@ var init_marketWsGateway = __esm({
|
|
|
28056
28392
|
resolve();
|
|
28057
28393
|
});
|
|
28058
28394
|
});
|
|
28059
|
-
|
|
28395
|
+
import_logger6.logger.info("market websocket gateway listening on %s:%s", host, port);
|
|
28060
28396
|
return {
|
|
28061
28397
|
close: async () => {
|
|
28062
28398
|
clearInterval(heartbeat);
|
|
@@ -28075,14 +28411,14 @@ var init_marketWsGateway = __esm({
|
|
|
28075
28411
|
// src/scripts/marketWs.ts
|
|
28076
28412
|
var marketWs_exports = {};
|
|
28077
28413
|
__export(marketWs_exports, {
|
|
28078
|
-
main: () =>
|
|
28414
|
+
main: () => main28
|
|
28079
28415
|
});
|
|
28080
|
-
var
|
|
28416
|
+
var main28;
|
|
28081
28417
|
var init_marketWs = __esm({
|
|
28082
28418
|
"src/scripts/marketWs.ts"() {
|
|
28083
28419
|
"use strict";
|
|
28084
28420
|
init_marketWsGateway();
|
|
28085
|
-
|
|
28421
|
+
main28 = async () => {
|
|
28086
28422
|
const gateway = await startMarketWsGateway();
|
|
28087
28423
|
const abortController = new AbortController();
|
|
28088
28424
|
const stop = () => abortController.abort();
|
|
@@ -28196,25 +28532,25 @@ const timer = setInterval(() => {
|
|
|
28196
28532
|
// src/scripts/mcpWorker.ts
|
|
28197
28533
|
var mcpWorker_exports = {};
|
|
28198
28534
|
__export(mcpWorker_exports, {
|
|
28199
|
-
main: () =>
|
|
28535
|
+
main: () => main29
|
|
28200
28536
|
});
|
|
28201
|
-
var import_node_child_process4, import_node_crypto15, import_promises23,
|
|
28537
|
+
var import_node_child_process4, import_node_crypto15, import_promises23, import_redis16, import_mcp, pause, leaseKey, LEASE_SECONDS, JOB_TIMEOUT_MS, main29;
|
|
28202
28538
|
var init_mcpWorker = __esm({
|
|
28203
28539
|
"src/scripts/mcpWorker.ts"() {
|
|
28204
28540
|
"use strict";
|
|
28205
28541
|
import_node_child_process4 = require("child_process");
|
|
28206
28542
|
import_node_crypto15 = require("crypto");
|
|
28207
28543
|
import_promises23 = require("fs/promises");
|
|
28208
|
-
|
|
28544
|
+
import_redis16 = require("@tradejs/infra/redis");
|
|
28209
28545
|
import_mcp = require("@tradejs/node/mcp");
|
|
28210
28546
|
init_mcpReplayProcess();
|
|
28211
28547
|
pause = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
28212
28548
|
leaseKey = "worker:lease";
|
|
28213
28549
|
LEASE_SECONDS = 15;
|
|
28214
28550
|
JOB_TIMEOUT_MS = 60 * 60 * 1e3;
|
|
28215
|
-
|
|
28551
|
+
main29 = async (options = {}) => {
|
|
28216
28552
|
const owner = (0, import_node_crypto15.randomUUID)();
|
|
28217
|
-
if (!await
|
|
28553
|
+
if (!await import_redis16.mcpStorage.put(leaseKey, owner, LEASE_SECONDS, true))
|
|
28218
28554
|
throw new Error("Another MCP worker owns this storage");
|
|
28219
28555
|
let stopping = false;
|
|
28220
28556
|
let child;
|
|
@@ -28278,10 +28614,10 @@ var init_mcpWorker = __esm({
|
|
|
28278
28614
|
if (renewing || leaseLost) return;
|
|
28279
28615
|
renewing = true;
|
|
28280
28616
|
try {
|
|
28281
|
-
if (!await
|
|
28617
|
+
if (!await import_redis16.mcpStorage.compare(leaseKey, owner, owner, LEASE_SECONDS))
|
|
28282
28618
|
throw new Error("Worker lease lost");
|
|
28283
28619
|
await updateReplayReady();
|
|
28284
|
-
await
|
|
28620
|
+
await import_redis16.mcpStorage.put("worker:heartbeat", heartbeatValue(), LEASE_SECONDS);
|
|
28285
28621
|
} catch {
|
|
28286
28622
|
leaseLost = true;
|
|
28287
28623
|
stop();
|
|
@@ -28292,15 +28628,15 @@ var init_mcpWorker = __esm({
|
|
|
28292
28628
|
try {
|
|
28293
28629
|
manifestHash = await (0, import_mcp.mcpPackageManifestHash)();
|
|
28294
28630
|
await updateReplayReady();
|
|
28295
|
-
await
|
|
28631
|
+
await import_redis16.mcpStorage.put("worker:heartbeat", heartbeatValue(), LEASE_SECONDS);
|
|
28296
28632
|
let cursor = "0";
|
|
28297
28633
|
do {
|
|
28298
|
-
const page = await
|
|
28634
|
+
const page = await import_redis16.mcpStorage.scan("jobs:", cursor);
|
|
28299
28635
|
cursor = page.cursor;
|
|
28300
28636
|
for (const key2 of page.ids) {
|
|
28301
|
-
const job = await
|
|
28637
|
+
const job = await import_redis16.mcpStorage.get(key2);
|
|
28302
28638
|
if (job?.status === "running")
|
|
28303
|
-
await
|
|
28639
|
+
await import_redis16.mcpStorage.compare(
|
|
28304
28640
|
key2,
|
|
28305
28641
|
job,
|
|
28306
28642
|
{
|
|
@@ -28321,10 +28657,10 @@ var init_mcpWorker = __esm({
|
|
|
28321
28657
|
let queued;
|
|
28322
28658
|
cursor = "0";
|
|
28323
28659
|
do {
|
|
28324
|
-
const page = await
|
|
28660
|
+
const page = await import_redis16.mcpStorage.scan("jobs:", cursor);
|
|
28325
28661
|
cursor = page.cursor;
|
|
28326
28662
|
for (const key2 of page.ids) {
|
|
28327
|
-
const job = await
|
|
28663
|
+
const job = await import_redis16.mcpStorage.get(key2);
|
|
28328
28664
|
if (job && ["queued", "waiting_resources", "waiting_executor"].includes(
|
|
28329
28665
|
job.status
|
|
28330
28666
|
) && (!queued || job.createdAt < queued.createdAt))
|
|
@@ -28342,10 +28678,10 @@ var init_mcpWorker = __esm({
|
|
|
28342
28678
|
...queued.kind === "runtime-feedback-replay" ? {} : { startedAt: Date.now() },
|
|
28343
28679
|
updatedAt: Date.now()
|
|
28344
28680
|
};
|
|
28345
|
-
if (!await
|
|
28681
|
+
if (!await import_redis16.mcpStorage.compare(jobKey, queued, started, import_mcp.MCP_JOB_TTL))
|
|
28346
28682
|
continue;
|
|
28347
28683
|
if (started.kind !== "runtime-feedback-replay" && started.packageManifestSha256 !== manifestHash) {
|
|
28348
|
-
await
|
|
28684
|
+
await import_redis16.mcpStorage.compare(
|
|
28349
28685
|
jobKey,
|
|
28350
28686
|
started,
|
|
28351
28687
|
{
|
|
@@ -28360,8 +28696,8 @@ var init_mcpWorker = __esm({
|
|
|
28360
28696
|
}
|
|
28361
28697
|
await (0, import_promises23.mkdir)((0, import_mcp.mcpJobDirectory)(started), { recursive: true });
|
|
28362
28698
|
if (started.kind === "backtest")
|
|
28363
|
-
await (0,
|
|
28364
|
-
|
|
28699
|
+
await (0, import_redis16.setDataStrict)(
|
|
28700
|
+
import_redis16.redisKeys.backtestConfig(
|
|
28365
28701
|
started.userName,
|
|
28366
28702
|
String(started.request.frozenConfigId)
|
|
28367
28703
|
),
|
|
@@ -28410,7 +28746,7 @@ var init_mcpWorker = __esm({
|
|
|
28410
28746
|
env: process.env
|
|
28411
28747
|
});
|
|
28412
28748
|
} catch (error) {
|
|
28413
|
-
await
|
|
28749
|
+
await import_redis16.mcpStorage.compare(
|
|
28414
28750
|
jobKey,
|
|
28415
28751
|
started,
|
|
28416
28752
|
{
|
|
@@ -28448,7 +28784,7 @@ var init_mcpWorker = __esm({
|
|
|
28448
28784
|
let killAt;
|
|
28449
28785
|
const monitor = setInterval(async () => {
|
|
28450
28786
|
try {
|
|
28451
|
-
const latest = await
|
|
28787
|
+
const latest = await import_redis16.mcpStorage.get(jobKey);
|
|
28452
28788
|
if (!latest || latest.cancelRequested || stopping || timedOut) {
|
|
28453
28789
|
killAt ??= Date.now();
|
|
28454
28790
|
signalChild(Date.now() - killAt > 8e3 ? "SIGKILL" : "SIGTERM");
|
|
@@ -28473,7 +28809,7 @@ var init_mcpWorker = __esm({
|
|
|
28473
28809
|
}
|
|
28474
28810
|
}
|
|
28475
28811
|
if (latest && !leaseLost)
|
|
28476
|
-
await
|
|
28812
|
+
await import_redis16.mcpStorage.compare(
|
|
28477
28813
|
jobKey,
|
|
28478
28814
|
latest,
|
|
28479
28815
|
{
|
|
@@ -28504,7 +28840,7 @@ var init_mcpWorker = __esm({
|
|
|
28504
28840
|
child = void 0;
|
|
28505
28841
|
if (!leaseLost) {
|
|
28506
28842
|
for (let attempt = 0; attempt < 4; attempt++) {
|
|
28507
|
-
const latest = await
|
|
28843
|
+
const latest = await import_redis16.mcpStorage.get(jobKey);
|
|
28508
28844
|
if (!latest) break;
|
|
28509
28845
|
const cancelled = latest.cancelRequested;
|
|
28510
28846
|
const next = {
|
|
@@ -28520,7 +28856,7 @@ var init_mcpWorker = __esm({
|
|
|
28520
28856
|
) || logs.at(-1) : void 0) || "Research process failed"
|
|
28521
28857
|
} : {}
|
|
28522
28858
|
};
|
|
28523
|
-
if (await
|
|
28859
|
+
if (await import_redis16.mcpStorage.compare(jobKey, latest, next, import_mcp.MCP_JOB_TTL))
|
|
28524
28860
|
break;
|
|
28525
28861
|
}
|
|
28526
28862
|
}
|
|
@@ -28530,8 +28866,8 @@ var init_mcpWorker = __esm({
|
|
|
28530
28866
|
options.signal?.removeEventListener("abort", stop);
|
|
28531
28867
|
process.removeListener("SIGINT", stop);
|
|
28532
28868
|
process.removeListener("SIGTERM", stop);
|
|
28533
|
-
if (await
|
|
28534
|
-
await
|
|
28869
|
+
if (await import_redis16.mcpStorage.release(leaseKey, owner))
|
|
28870
|
+
await import_redis16.mcpStorage.remove("worker:heartbeat");
|
|
28535
28871
|
}
|
|
28536
28872
|
if (leaseLost)
|
|
28537
28873
|
throw new Error("Worker lease lost; active computation was stopped");
|
|
@@ -28542,9 +28878,9 @@ var init_mcpWorker = __esm({
|
|
|
28542
28878
|
// src/scripts/hyperliquidWhaleBackfill.ts
|
|
28543
28879
|
var hyperliquidWhaleBackfill_exports = {};
|
|
28544
28880
|
__export(hyperliquidWhaleBackfill_exports, {
|
|
28545
|
-
main: () =>
|
|
28881
|
+
main: () => main30
|
|
28546
28882
|
});
|
|
28547
|
-
var import_args20, flags18, parseTime,
|
|
28883
|
+
var import_args20, flags18, parseTime, main30;
|
|
28548
28884
|
var init_hyperliquidWhaleBackfill2 = __esm({
|
|
28549
28885
|
"src/scripts/hyperliquidWhaleBackfill.ts"() {
|
|
28550
28886
|
"use strict";
|
|
@@ -28564,7 +28900,7 @@ var init_hyperliquidWhaleBackfill2 = __esm({
|
|
|
28564
28900
|
if (!Number.isFinite(parsed)) throw new Error(`Invalid timestamp: ${value}`);
|
|
28565
28901
|
return parsed;
|
|
28566
28902
|
};
|
|
28567
|
-
|
|
28903
|
+
main30 = async () => {
|
|
28568
28904
|
const toMs = parseTime(flags18.to, Date.now());
|
|
28569
28905
|
const days = Number(flags18.days);
|
|
28570
28906
|
const lookbackMs = (Number.isFinite(days) && days > 0 ? days : 1) * 864e5;
|
|
@@ -28582,13 +28918,13 @@ var init_hyperliquidWhaleBackfill2 = __esm({
|
|
|
28582
28918
|
});
|
|
28583
28919
|
|
|
28584
28920
|
// src/lib/hyperliquidWhaleStream.ts
|
|
28585
|
-
var import_ws2, import_hyperliquidWhales2,
|
|
28921
|
+
var import_ws2, import_hyperliquidWhales2, import_strategies12, DEFAULT_WS_URL, EVENT_BATCH_SIZE, FLUSH_INTERVAL_MS, FINALIZE_INTERVAL_MS, FINALIZE_LAG_MS, REBUILD_LOOKBACK_MS, RAW_EVENT_RETENTION_MS, sleep5, parseHyperliquidUserFillsMessage, runHyperliquidWhaleStream;
|
|
28586
28922
|
var init_hyperliquidWhaleStream = __esm({
|
|
28587
28923
|
"src/lib/hyperliquidWhaleStream.ts"() {
|
|
28588
28924
|
"use strict";
|
|
28589
28925
|
import_ws2 = require("ws");
|
|
28590
28926
|
import_hyperliquidWhales2 = require("@tradejs/infra/timescale/hyperliquidWhales");
|
|
28591
|
-
|
|
28927
|
+
import_strategies12 = require("@tradejs/node/strategies");
|
|
28592
28928
|
init_hyperliquidWhaleData();
|
|
28593
28929
|
DEFAULT_WS_URL = "wss://api.hyperliquid.xyz/ws";
|
|
28594
28930
|
EVENT_BATCH_SIZE = 500;
|
|
@@ -28629,8 +28965,8 @@ var init_hyperliquidWhaleStream = __esm({
|
|
|
28629
28965
|
}
|
|
28630
28966
|
};
|
|
28631
28967
|
runHyperliquidWhaleStream = async (params) => {
|
|
28632
|
-
const universe = (0,
|
|
28633
|
-
const whales = (0,
|
|
28968
|
+
const universe = (0, import_strategies12.getHyperliquidPerpUniverseSnapshot)();
|
|
28969
|
+
const whales = (0, import_strategies12.getHyperliquidWhaleRegistrySnapshot)();
|
|
28634
28970
|
const trackedSymbols = new Set(universe.symbols);
|
|
28635
28971
|
const identity = {
|
|
28636
28972
|
universeFingerprint: universe.fingerprint,
|
|
@@ -28773,14 +29109,14 @@ var init_hyperliquidWhaleStream = __esm({
|
|
|
28773
29109
|
// src/scripts/hyperliquidWhaleIngest.ts
|
|
28774
29110
|
var hyperliquidWhaleIngest_exports = {};
|
|
28775
29111
|
__export(hyperliquidWhaleIngest_exports, {
|
|
28776
|
-
main: () =>
|
|
29112
|
+
main: () => main31
|
|
28777
29113
|
});
|
|
28778
|
-
var
|
|
29114
|
+
var main31;
|
|
28779
29115
|
var init_hyperliquidWhaleIngest = __esm({
|
|
28780
29116
|
"src/scripts/hyperliquidWhaleIngest.ts"() {
|
|
28781
29117
|
"use strict";
|
|
28782
29118
|
init_hyperliquidWhaleStream();
|
|
28783
|
-
|
|
29119
|
+
main31 = async () => {
|
|
28784
29120
|
const controller = new AbortController();
|
|
28785
29121
|
const stop = () => controller.abort();
|
|
28786
29122
|
process.once("SIGINT", stop);
|
|
@@ -28892,21 +29228,21 @@ var init_hyperliquidWhaleSelection = __esm({
|
|
|
28892
29228
|
// src/scripts/hyperliquidWhalesUpdate.ts
|
|
28893
29229
|
var hyperliquidWhalesUpdate_exports = {};
|
|
28894
29230
|
__export(hyperliquidWhalesUpdate_exports, {
|
|
28895
|
-
main: () =>
|
|
29231
|
+
main: () => main32
|
|
28896
29232
|
});
|
|
28897
|
-
var import_config8, import_args21, import_node_crypto16,
|
|
29233
|
+
var import_config8, import_args21, import_node_crypto16, import_strategies13, LEADERBOARD_URL, DAY_MS12, CANDIDATE_LIMIT, flags19, fingerprint, runConcurrent2, main32;
|
|
28898
29234
|
var init_hyperliquidWhalesUpdate = __esm({
|
|
28899
29235
|
"src/scripts/hyperliquidWhalesUpdate.ts"() {
|
|
28900
29236
|
"use strict";
|
|
28901
29237
|
import_config8 = require("dotenv/config");
|
|
28902
29238
|
import_args21 = __toESM(require("args"));
|
|
28903
29239
|
import_node_crypto16 = require("crypto");
|
|
28904
|
-
|
|
29240
|
+
import_strategies13 = require("@tradejs/node/strategies");
|
|
28905
29241
|
init_hyperliquidWhaleBackfill();
|
|
28906
29242
|
init_hyperliquidRateLimiter();
|
|
28907
29243
|
init_hyperliquidWhaleSelection();
|
|
28908
29244
|
LEADERBOARD_URL = "https://stats-data.hyperliquid.xyz/Mainnet/leaderboard";
|
|
28909
|
-
|
|
29245
|
+
DAY_MS12 = 864e5;
|
|
28910
29246
|
CANDIDATE_LIMIT = 400;
|
|
28911
29247
|
import_args21.default.option(
|
|
28912
29248
|
["t", "to"],
|
|
@@ -28928,11 +29264,11 @@ var init_hyperliquidWhalesUpdate = __esm({
|
|
|
28928
29264
|
})
|
|
28929
29265
|
);
|
|
28930
29266
|
};
|
|
28931
|
-
|
|
29267
|
+
main32 = async () => {
|
|
28932
29268
|
const explicitTo = flags19.to == null ? Number.NaN : Date.parse(String(flags19.to));
|
|
28933
|
-
const calibrationToMs = Number.isFinite(explicitTo) ? explicitTo : Math.floor(Date.now() /
|
|
29269
|
+
const calibrationToMs = Number.isFinite(explicitTo) ? explicitTo : Math.floor(Date.now() / DAY_MS12) * DAY_MS12;
|
|
28934
29270
|
const calibrationDays = Math.max(1, Number(flags19.days) || 7);
|
|
28935
|
-
const calibrationFromMs = calibrationToMs - calibrationDays *
|
|
29271
|
+
const calibrationFromMs = calibrationToMs - calibrationDays * DAY_MS12;
|
|
28936
29272
|
const response = await fetch(LEADERBOARD_URL);
|
|
28937
29273
|
if (!response.ok) {
|
|
28938
29274
|
throw new Error(`Hyperliquid leaderboard ${response.status}`);
|
|
@@ -28954,7 +29290,7 @@ var init_hyperliquidWhalesUpdate = __esm({
|
|
|
28954
29290
|
).sort(
|
|
28955
29291
|
(left, right) => left.turnoverToEquity - right.turnoverToEquity || right.accountValueUsd - left.accountValueUsd || left.address.localeCompare(right.address)
|
|
28956
29292
|
).slice(0, CANDIDATE_LIMIT);
|
|
28957
|
-
const top30Symbols = new Set((0,
|
|
29293
|
+
const top30Symbols = new Set((0, import_strategies13.getHyperliquidPerpUniverseSnapshot)().symbols);
|
|
28958
29294
|
const limiter = new HyperliquidInfoRateLimiter();
|
|
28959
29295
|
const metrics = [];
|
|
28960
29296
|
let completed = 0;
|
|
@@ -29021,9 +29357,9 @@ var init_hyperliquidWhalesUpdate = __esm({
|
|
|
29021
29357
|
// src/scripts/mlExport.ts
|
|
29022
29358
|
var mlExport_exports = {};
|
|
29023
29359
|
__export(mlExport_exports, {
|
|
29024
|
-
main: () =>
|
|
29360
|
+
main: () => main33
|
|
29025
29361
|
});
|
|
29026
|
-
var import_args22, import_chalk37, import_promises24, import_path8, import_ml, flags20, resolveRunScopedMlChunks,
|
|
29362
|
+
var import_args22, import_chalk37, import_promises24, import_path8, import_ml, flags20, resolveRunScopedMlChunks, main33;
|
|
29027
29363
|
var init_mlExport = __esm({
|
|
29028
29364
|
"src/scripts/mlExport.ts"() {
|
|
29029
29365
|
"use strict";
|
|
@@ -29078,7 +29414,7 @@ var init_mlExport = __esm({
|
|
|
29078
29414
|
completedAttemptKeys: buildCompletedBacktestDatasetAttemptKeys(completed)
|
|
29079
29415
|
};
|
|
29080
29416
|
};
|
|
29081
|
-
|
|
29417
|
+
main33 = async () => {
|
|
29082
29418
|
const outDir = String(flags20.outDir || "data/ml/export");
|
|
29083
29419
|
await import_promises24.default.mkdir(outDir, { recursive: true });
|
|
29084
29420
|
const strategyName = await resolveExportStrategy({
|
|
@@ -29144,9 +29480,9 @@ var init_mlExport = __esm({
|
|
|
29144
29480
|
// src/scripts/mlInspect.ts
|
|
29145
29481
|
var mlInspect_exports = {};
|
|
29146
29482
|
__export(mlInspect_exports, {
|
|
29147
|
-
main: () =>
|
|
29483
|
+
main: () => main34
|
|
29148
29484
|
});
|
|
29149
|
-
var import_args23, import_chalk38, import_promises25, import_fs3, import_path9, import_readline2, import_child_process2, flags21, toMode, toInspectTool, selectInspectTool, asPositiveInt, readRowsHead, readRowsTail, readRowsSample, quantileSorted, mean2, std, findLatestDataset, buildNumericStats, formatNumber5, runQuickInspect, runYDataInspect,
|
|
29485
|
+
var import_args23, import_chalk38, import_promises25, import_fs3, import_path9, import_readline2, import_child_process2, flags21, toMode, toInspectTool, selectInspectTool, asPositiveInt, readRowsHead, readRowsTail, readRowsSample, quantileSorted, mean2, std, findLatestDataset, buildNumericStats, formatNumber5, runQuickInspect, runYDataInspect, main34;
|
|
29150
29486
|
var init_mlInspect = __esm({
|
|
29151
29487
|
"src/scripts/mlInspect.ts"() {
|
|
29152
29488
|
"use strict";
|
|
@@ -29638,7 +29974,7 @@ var init_mlInspect = __esm({
|
|
|
29638
29974
|
}
|
|
29639
29975
|
console.log(import_chalk38.default.green(`Profile report saved: ${reportPath}`));
|
|
29640
29976
|
};
|
|
29641
|
-
|
|
29977
|
+
main34 = async () => {
|
|
29642
29978
|
const dir = String(flags21.dir || "data/ml/export");
|
|
29643
29979
|
const rowsToInspect = asPositiveInt(flags21.rows, 1e4);
|
|
29644
29980
|
const mode = toMode(flags21.mode);
|
|
@@ -29680,9 +30016,9 @@ var init_mlInspect = __esm({
|
|
|
29680
30016
|
// src/scripts/mlTrainLatestSelect.ts
|
|
29681
30017
|
var mlTrainLatestSelect_exports = {};
|
|
29682
30018
|
__export(mlTrainLatestSelect_exports, {
|
|
29683
|
-
main: () =>
|
|
30019
|
+
main: () => main35
|
|
29684
30020
|
});
|
|
29685
|
-
var import_path10, import_promises26, import_fs4, import_crypto2, import_child_process3, import_events, import_readline3, import_args24, import_chalk39, import_ml2, toFileToken6, asBool, asInt7, asNonNegativeInt, formatBytes, getMlContainerMemUsage, MODEL_TYPES, STRATEGIES, flags22, parseStrategy, parseModelType, selectModelType, listDatasetFiles, concatFiles, pipeNormalized,
|
|
30021
|
+
var import_path10, import_promises26, import_fs4, import_crypto2, import_child_process3, import_events, import_readline3, import_args24, import_chalk39, import_ml2, toFileToken6, asBool, asInt7, asNonNegativeInt, formatBytes, getMlContainerMemUsage, MODEL_TYPES, STRATEGIES, flags22, parseStrategy, parseModelType, selectModelType, listDatasetFiles, concatFiles, pipeNormalized, DAY_MS13, SPLIT_PROGRESS_EVERY, parseTimestampMs, scanMaxLabeledTimestampMs, scanMaxTrainTimestampMs, hashFileNameSha1, prepareTrainWindowFiles, main35;
|
|
29686
30022
|
var init_mlTrainLatestSelect = __esm({
|
|
29687
30023
|
"src/scripts/mlTrainLatestSelect.ts"() {
|
|
29688
30024
|
"use strict";
|
|
@@ -29873,7 +30209,7 @@ var init_mlTrainLatestSelect = __esm({
|
|
|
29873
30209
|
}
|
|
29874
30210
|
};
|
|
29875
30211
|
};
|
|
29876
|
-
|
|
30212
|
+
DAY_MS13 = 24 * 60 * 60 * 1e3;
|
|
29877
30213
|
SPLIT_PROGRESS_EVERY = 2e5;
|
|
29878
30214
|
parseTimestampMs = (value) => {
|
|
29879
30215
|
const numeric = Number(value);
|
|
@@ -30090,7 +30426,7 @@ var init_mlTrainLatestSelect = __esm({
|
|
|
30090
30426
|
}
|
|
30091
30427
|
console.log("[split] phase 1/3: scanning max labeled timestamp...");
|
|
30092
30428
|
const maxLabeledTs = await scanMaxLabeledTimestampMs(inputPath);
|
|
30093
|
-
const holdoutCutoffMs = maxLabeledTs - testDays *
|
|
30429
|
+
const holdoutCutoffMs = maxLabeledTs - testDays * DAY_MS13;
|
|
30094
30430
|
console.log("[split] phase 2/3: scanning max train timestamp...");
|
|
30095
30431
|
const maxTrainTs = await scanMaxTrainTimestampMs(inputPath, holdoutCutoffMs);
|
|
30096
30432
|
const {
|
|
@@ -30403,7 +30739,7 @@ var init_mlTrainLatestSelect = __esm({
|
|
|
30403
30739
|
}
|
|
30404
30740
|
};
|
|
30405
30741
|
};
|
|
30406
|
-
|
|
30742
|
+
main35 = async () => {
|
|
30407
30743
|
const selectedFromCli = parseStrategy(flags22.strategy);
|
|
30408
30744
|
const selected = selectedFromCli ?? await selectStrategy();
|
|
30409
30745
|
const envModelType = (process.env.ML_MODEL_TYPE ?? "random_forest").trim().toLowerCase();
|
|
@@ -30667,7 +31003,7 @@ __export(researchAuto_exports, {
|
|
|
30667
31003
|
isProcessAlive: () => isProcessAlive,
|
|
30668
31004
|
listMergedFiles: () => listMergedFiles3,
|
|
30669
31005
|
listRuntimeStrategyNames: () => listRuntimeStrategyNames,
|
|
30670
|
-
main: () =>
|
|
31006
|
+
main: () => main36,
|
|
30671
31007
|
parseJsonOutput: () => parseJsonOutput,
|
|
30672
31008
|
releaseResearchAutoLock: () => releaseResearchAutoLock,
|
|
30673
31009
|
resolveHeapMbFromEnv: () => resolveHeapMbFromEnv,
|
|
@@ -30677,7 +31013,7 @@ __export(researchAuto_exports, {
|
|
|
30677
31013
|
toStrategyConfigGrid: () => toStrategyConfigGrid2,
|
|
30678
31014
|
trimTextTail: () => trimTextTail2
|
|
30679
31015
|
});
|
|
30680
|
-
var import_args25, import_chalk40, import_node_child_process5, import_promises27, import_node_os2, import_node_path20,
|
|
31016
|
+
var import_args25, import_chalk40, import_node_child_process5, import_promises27, import_node_os2, import_node_path20, import_constants19, import_ai8, import_logger7, import_redis17, import_registry4, flags23, projectRoot8, dotenvPath, getResearchAutoLockPath, readResearchAutoLock, isProcessAlive, acquireResearchAutoLock, releaseResearchAutoLock, resolvePositiveInteger, resolveHeapMbFromEnv, buildNodeOptions, RESEARCH_AUTO_PARENT_HEAP_MB, RESEARCH_AUTO_BACKTEST_PARENT_HEAP_MB, RESEARCH_AUTO_AI_TRAIN_PARENT_HEAP_MB, RESEARCH_AUTO_AGENT_PARENT_HEAP_MB, trimTextTail2, escapeHtml3, createEmptySteps, saveRun, listMergedFiles3, getBacktestResultsPrefix, listRuntimeStrategyNames, toStrategyConfigGrid2, formatMskDateTime, buildTelegramReport, runCliCommand, resolveTarget, parseJsonOutput, logResearch, executeNonBlockingStep, main36;
|
|
30681
31017
|
var init_researchAuto = __esm({
|
|
30682
31018
|
"src/scripts/researchAuto.ts"() {
|
|
30683
31019
|
"use strict";
|
|
@@ -30687,10 +31023,10 @@ var init_researchAuto = __esm({
|
|
|
30687
31023
|
import_promises27 = __toESM(require("fs/promises"));
|
|
30688
31024
|
import_node_os2 = __toESM(require("os"));
|
|
30689
31025
|
import_node_path20 = __toESM(require("path"));
|
|
30690
|
-
|
|
31026
|
+
import_constants19 = require("@tradejs/core/constants");
|
|
30691
31027
|
import_ai8 = require("@tradejs/infra/ai");
|
|
30692
|
-
|
|
30693
|
-
|
|
31028
|
+
import_logger7 = require("@tradejs/infra/logger");
|
|
31029
|
+
import_redis17 = require("@tradejs/infra/redis");
|
|
30694
31030
|
import_registry4 = require("@tradejs/node/registry");
|
|
30695
31031
|
init_runtimeRedis();
|
|
30696
31032
|
init_runtimeStrategyBacktest();
|
|
@@ -30892,11 +31228,11 @@ var init_researchAuto = __esm({
|
|
|
30892
31228
|
}
|
|
30893
31229
|
});
|
|
30894
31230
|
saveRun = async (run) => {
|
|
30895
|
-
await (0,
|
|
30896
|
-
expire:
|
|
31231
|
+
await (0, import_redis17.setData)(import_redis17.redisKeys.researchRun(run.userName, run.runId), run, {
|
|
31232
|
+
expire: import_constants19.TTL_1M
|
|
30897
31233
|
});
|
|
30898
|
-
await (0,
|
|
30899
|
-
expire:
|
|
31234
|
+
await (0, import_redis17.setData)(import_redis17.redisKeys.researchLatestRun(run.userName, run.strategy), run, {
|
|
31235
|
+
expire: import_constants19.TTL_1M
|
|
30900
31236
|
});
|
|
30901
31237
|
};
|
|
30902
31238
|
listMergedFiles3 = async (outDir, strategyName) => {
|
|
@@ -31057,13 +31393,13 @@ var init_researchAuto = __esm({
|
|
|
31057
31393
|
const emitLines = (source, text3) => {
|
|
31058
31394
|
const prefix = params.liveLogPrefix ? `[research:auto:${params.liveLogPrefix}:${source}] ` : `[research:auto:${source}] `;
|
|
31059
31395
|
for (const line of text3.split(/\r?\n/).map((value) => value.trimEnd()).filter(Boolean)) {
|
|
31060
|
-
|
|
31396
|
+
import_logger7.logger.info(import_chalk40.default.gray(`${prefix}${line}`));
|
|
31061
31397
|
}
|
|
31062
31398
|
};
|
|
31063
31399
|
if (params.heartbeatMs && params.heartbeatMs > 0) {
|
|
31064
31400
|
heartbeatTimer = setInterval(() => {
|
|
31065
31401
|
const elapsedMs = Date.now() - startedAt;
|
|
31066
|
-
|
|
31402
|
+
import_logger7.logger.info(
|
|
31067
31403
|
import_chalk40.default.gray(
|
|
31068
31404
|
`[research:auto:${params.liveLogPrefix || params.command}] still running after ${Math.round(elapsedMs / 1e3)}s`
|
|
31069
31405
|
)
|
|
@@ -31125,8 +31461,8 @@ var init_researchAuto = __esm({
|
|
|
31125
31461
|
const candidates = [];
|
|
31126
31462
|
for (const strategy of availableStrategies) {
|
|
31127
31463
|
const config2 = `${strategy}:research`;
|
|
31128
|
-
const latestRun = await (0,
|
|
31129
|
-
|
|
31464
|
+
const latestRun = await (0, import_redis17.getData)(
|
|
31465
|
+
import_redis17.redisKeys.researchLatestRun(userName3, strategy),
|
|
31130
31466
|
null
|
|
31131
31467
|
);
|
|
31132
31468
|
const lastFinishedAt = latestRun?.finishedAt ? Date.parse(latestRun.finishedAt) : 0;
|
|
@@ -31163,7 +31499,7 @@ var init_researchAuto = __esm({
|
|
|
31163
31499
|
return JSON.parse(trimmed);
|
|
31164
31500
|
};
|
|
31165
31501
|
logResearch = (message) => {
|
|
31166
|
-
|
|
31502
|
+
import_logger7.logger.info(import_chalk40.default.cyan(`[research:auto] ${message}`));
|
|
31167
31503
|
};
|
|
31168
31504
|
executeNonBlockingStep = async (run, stepName, command, commandArgs, options = {}) => {
|
|
31169
31505
|
logResearch(
|
|
@@ -31202,7 +31538,7 @@ var init_researchAuto = __esm({
|
|
|
31202
31538
|
);
|
|
31203
31539
|
return result;
|
|
31204
31540
|
};
|
|
31205
|
-
|
|
31541
|
+
main36 = async () => {
|
|
31206
31542
|
resolveRequiredResearchRoots({ projectRoot: projectRoot8 });
|
|
31207
31543
|
const userName3 = String(flags23.user || "root").trim() || "root";
|
|
31208
31544
|
const connector = String(flags23.connector || "bybit").trim() || "bybit";
|
|
@@ -31305,13 +31641,13 @@ var init_researchAuto = __esm({
|
|
|
31305
31641
|
startedAt
|
|
31306
31642
|
};
|
|
31307
31643
|
await saveRun(run);
|
|
31308
|
-
const strategyConfigKey =
|
|
31644
|
+
const strategyConfigKey = import_redis17.redisKeys.strategyConfig(
|
|
31309
31645
|
userName3,
|
|
31310
31646
|
target.strategy
|
|
31311
31647
|
);
|
|
31312
|
-
const backtestConfigKey =
|
|
31648
|
+
const backtestConfigKey = import_redis17.redisKeys.backtestConfig(userName3, target.config);
|
|
31313
31649
|
const defaults = await (0, import_registry4.getStrategyDefaults)(target.strategy, projectRoot8) || {};
|
|
31314
|
-
const userStrategyConfig = await (0,
|
|
31650
|
+
const userStrategyConfig = await (0, import_redis17.getData)(
|
|
31315
31651
|
strategyConfigKey,
|
|
31316
31652
|
{}
|
|
31317
31653
|
);
|
|
@@ -31325,7 +31661,7 @@ var init_researchAuto = __esm({
|
|
|
31325
31661
|
);
|
|
31326
31662
|
}
|
|
31327
31663
|
const backtestConfig = toStrategyConfigGrid2(strategyConfig);
|
|
31328
|
-
await (0,
|
|
31664
|
+
await (0, import_redis17.setData)(backtestConfigKey, backtestConfig, { expire: 0 });
|
|
31329
31665
|
logResearch(
|
|
31330
31666
|
`stored backtest config at ${backtestConfigKey} with ${Object.keys(strategyConfig).length} top-level fields`
|
|
31331
31667
|
);
|
|
@@ -31365,7 +31701,7 @@ var init_researchAuto = __esm({
|
|
|
31365
31701
|
`resource knobs: researchAutoHeapMb=${RESEARCH_AUTO_PARENT_HEAP_MB}, backtestParentHeapMb=${RESEARCH_AUTO_BACKTEST_PARENT_HEAP_MB}, aiTrainParentHeapMb=${RESEARCH_AUTO_AI_TRAIN_PARENT_HEAP_MB}, agentParentHeapMb=${RESEARCH_AUTO_AGENT_PARENT_HEAP_MB}, backtestWorkerHeapMb=${process.env.BACKTEST_WORKER_HEAP_MB || "auto"}, backtestMaxParallel=${process.env.BACKTEST_MAX_PARALLEL || "auto"}, klineConcurrency=${process.env.KLINE_CONCURRENCY_LIMIT || "default"}`
|
|
31366
31702
|
);
|
|
31367
31703
|
const backtestKeysBefore = new Set(
|
|
31368
|
-
await (0,
|
|
31704
|
+
await (0, import_redis17.getKeys)(getBacktestResultsPrefix(userName3, target.config))
|
|
31369
31705
|
);
|
|
31370
31706
|
const aiFilesBefore = new Set(
|
|
31371
31707
|
await listMergedFiles3(outDir, target.strategy)
|
|
@@ -31427,14 +31763,14 @@ var init_researchAuto = __esm({
|
|
|
31427
31763
|
captureMode: "full"
|
|
31428
31764
|
}
|
|
31429
31765
|
);
|
|
31430
|
-
const backtestKeysAfter = await (0,
|
|
31766
|
+
const backtestKeysAfter = await (0, import_redis17.getKeys)(
|
|
31431
31767
|
getBacktestResultsPrefix(userName3, target.config)
|
|
31432
31768
|
);
|
|
31433
31769
|
const newBacktestKeys = backtestKeysAfter.filter((key2) => !backtestKeysBefore.has(key2)).sort();
|
|
31434
31770
|
const backtestResultKey = newBacktestKeys[newBacktestKeys.length - 1] || backtestKeysAfter.sort().at(-1);
|
|
31435
31771
|
if (backtestResultKey) {
|
|
31436
31772
|
logResearch(`detected backtest result key ${backtestResultKey}`);
|
|
31437
|
-
const backtestResult = await (0,
|
|
31773
|
+
const backtestResult = await (0, import_redis17.getData)(backtestResultKey, null);
|
|
31438
31774
|
run.artifacts.backtestResultKey = backtestResultKey;
|
|
31439
31775
|
run.artifacts.backtestResult = backtestResult ? {
|
|
31440
31776
|
finishedAt: backtestResult.finishedAt,
|
|
@@ -32134,8 +32470,8 @@ var init_dataset2 = __esm({
|
|
|
32134
32470
|
for (const inputPath of variant.files) {
|
|
32135
32471
|
const filePath = import_node_path22.default.resolve(inputPath);
|
|
32136
32472
|
const input = (0, import_node_fs8.createReadStream)(filePath);
|
|
32137
|
-
const
|
|
32138
|
-
input.on("data", (chunk) =>
|
|
32473
|
+
const hash2 = (0, import_node_crypto17.createHash)("sha256");
|
|
32474
|
+
input.on("data", (chunk) => hash2.update(chunk));
|
|
32139
32475
|
const lines = import_node_readline3.default.createInterface({ input, crlfDelay: Infinity });
|
|
32140
32476
|
const fileTrades = [];
|
|
32141
32477
|
let lineNumber = 0;
|
|
@@ -32185,7 +32521,7 @@ var init_dataset2 = __esm({
|
|
|
32185
32521
|
trades.push(trade);
|
|
32186
32522
|
fileTrades.push(trade);
|
|
32187
32523
|
}
|
|
32188
|
-
const fileSha2562 =
|
|
32524
|
+
const fileSha2562 = hash2.digest("hex");
|
|
32189
32525
|
for (const trade of fileTrades) trade.sourceSha256 = fileSha2562;
|
|
32190
32526
|
sources.push({
|
|
32191
32527
|
path: filePath,
|
|
@@ -33373,9 +33709,9 @@ var init_orchestrator = __esm({
|
|
|
33373
33709
|
// src/scripts/coreResearch.ts
|
|
33374
33710
|
var coreResearch_exports = {};
|
|
33375
33711
|
__export(coreResearch_exports, {
|
|
33376
|
-
main: () =>
|
|
33712
|
+
main: () => main37
|
|
33377
33713
|
});
|
|
33378
|
-
var import_promises30, import_node_path24, import_chalk41, valueAfter, required, parseTimestamp, readSymbols, printUsage,
|
|
33714
|
+
var import_promises30, import_node_path24, import_chalk41, valueAfter, required, parseTimestamp, readSymbols, printUsage, main37;
|
|
33379
33715
|
var init_coreResearch = __esm({
|
|
33380
33716
|
"src/scripts/coreResearch.ts"() {
|
|
33381
33717
|
"use strict";
|
|
@@ -33424,7 +33760,7 @@ var init_coreResearch = __esm({
|
|
|
33424
33760
|
|
|
33425
33761
|
The run command executes only variants with an explicit command[] in the preregistered spec. Variants with files[] are analyzed without starting a backtest.`);
|
|
33426
33762
|
};
|
|
33427
|
-
|
|
33763
|
+
main37 = async () => {
|
|
33428
33764
|
const roots = resolveResearchRoots();
|
|
33429
33765
|
process.chdir(roots.projectRoot);
|
|
33430
33766
|
const argv2 = process.argv.slice(2);
|
|
@@ -33744,55 +34080,6 @@ var init_specification = __esm({
|
|
|
33744
34080
|
}
|
|
33745
34081
|
});
|
|
33746
34082
|
|
|
33747
|
-
// src/lib/researchMetricSnapshot.ts
|
|
33748
|
-
var import_node_crypto19, import_node_zlib2, MAX_BYTES, hash2, validatePermanentResearchMetrics, encodeResearchMetricSnapshot, decodeResearchMetricSnapshot;
|
|
33749
|
-
var init_researchMetricSnapshot = __esm({
|
|
33750
|
-
"src/lib/researchMetricSnapshot.ts"() {
|
|
33751
|
-
"use strict";
|
|
33752
|
-
import_node_crypto19 = require("crypto");
|
|
33753
|
-
import_node_zlib2 = require("zlib");
|
|
33754
|
-
MAX_BYTES = 256 * 1024 * 1024;
|
|
33755
|
-
hash2 = (bytes) => (0, import_node_crypto19.createHash)("sha256").update(bytes).digest("hex");
|
|
33756
|
-
validatePermanentResearchMetrics = (value) => {
|
|
33757
|
-
if (!value || typeof value !== "object") return;
|
|
33758
|
-
for (const [key2, child] of Object.entries(value)) {
|
|
33759
|
-
if (["matchedPairs", "tradeRows", "allProjectedLeaves"].includes(key2) && Array.isArray(child) && child.length)
|
|
33760
|
-
throw new Error(`Temporary payload ${key2} is not a permanent metric`);
|
|
33761
|
-
if (key2 === "trades" && Array.isArray(child) && child.some(
|
|
33762
|
-
(row) => row && typeof row === "object" && ("signalId" in row || "entryTimestamp" in row)
|
|
33763
|
-
))
|
|
33764
|
-
throw new Error("Temporary trade records are not permanent metrics");
|
|
33765
|
-
validatePermanentResearchMetrics(child);
|
|
33766
|
-
}
|
|
33767
|
-
};
|
|
33768
|
-
encodeResearchMetricSnapshot = (metrics) => {
|
|
33769
|
-
validatePermanentResearchMetrics(metrics);
|
|
33770
|
-
const bytes = Buffer.from(JSON.stringify(metrics));
|
|
33771
|
-
if (bytes.length > MAX_BYTES)
|
|
33772
|
-
throw new Error("Metric snapshot exceeds decoded size limit");
|
|
33773
|
-
return {
|
|
33774
|
-
schema: "tradejs-metric-snapshot/v1",
|
|
33775
|
-
encoding: "gzip+base64",
|
|
33776
|
-
decodedBytes: bytes.length,
|
|
33777
|
-
sha256: hash2(bytes),
|
|
33778
|
-
payload: (0, import_node_zlib2.gzipSync)(bytes, { level: 9 }).toString("base64")
|
|
33779
|
-
};
|
|
33780
|
-
};
|
|
33781
|
-
decodeResearchMetricSnapshot = (snapshot) => {
|
|
33782
|
-
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")
|
|
33783
|
-
throw new Error("Invalid metric snapshot envelope");
|
|
33784
|
-
const bytes = (0, import_node_zlib2.gunzipSync)(Buffer.from(snapshot.payload, "base64"), {
|
|
33785
|
-
maxOutputLength: snapshot.decodedBytes
|
|
33786
|
-
});
|
|
33787
|
-
if (bytes.length !== snapshot.decodedBytes || hash2(bytes) !== snapshot.sha256)
|
|
33788
|
-
throw new Error("Metric snapshot checksum or size mismatch");
|
|
33789
|
-
const metrics = JSON.parse(bytes.toString("utf8"));
|
|
33790
|
-
validatePermanentResearchMetrics(metrics);
|
|
33791
|
-
return metrics;
|
|
33792
|
-
};
|
|
33793
|
-
}
|
|
33794
|
-
});
|
|
33795
|
-
|
|
33796
34083
|
// src/lib/strategyResearch/io.ts
|
|
33797
34084
|
var io_exports = {};
|
|
33798
34085
|
__export(io_exports, {
|
|
@@ -33805,14 +34092,14 @@ __export(io_exports, {
|
|
|
33805
34092
|
verifyResearchState: () => verifyResearchState,
|
|
33806
34093
|
withResearchLock: () => withResearchLock
|
|
33807
34094
|
});
|
|
33808
|
-
var import_promises31, import_node_path25, import_node_os3,
|
|
34095
|
+
var import_promises31, import_node_path25, import_node_os3, import_node_crypto19, researchDirectory, readJson, boundResearchPath, withResearchLock, verifyResearchState, verifyCompletedResearch, initializeResearchState, isRetainedDeletion;
|
|
33809
34096
|
var init_io2 = __esm({
|
|
33810
34097
|
"src/lib/strategyResearch/io.ts"() {
|
|
33811
34098
|
"use strict";
|
|
33812
34099
|
import_promises31 = __toESM(require("fs/promises"));
|
|
33813
34100
|
import_node_path25 = __toESM(require("path"));
|
|
33814
34101
|
import_node_os3 = __toESM(require("os"));
|
|
33815
|
-
|
|
34102
|
+
import_node_crypto19 = require("crypto");
|
|
33816
34103
|
init_io();
|
|
33817
34104
|
researchDirectory = (projectRoot18, spec) => import_node_path25.default.join(projectRoot18, "data/research/strategy", spec.core.researchId);
|
|
33818
34105
|
readJson = async (file) => JSON.parse(await import_promises31.default.readFile(file, "utf8"));
|
|
@@ -33841,7 +34128,7 @@ var init_io2 = __esm({
|
|
|
33841
34128
|
"data/research/strategy/.lock"
|
|
33842
34129
|
);
|
|
33843
34130
|
await import_promises31.default.mkdir(import_node_path25.default.dirname(file), { recursive: true });
|
|
33844
|
-
const token = (0,
|
|
34131
|
+
const token = (0, import_node_crypto19.randomUUID)();
|
|
33845
34132
|
const acquire = () => import_promises31.default.writeFile(
|
|
33846
34133
|
file,
|
|
33847
34134
|
JSON.stringify({ pid: process.pid, host: import_node_os3.default.hostname(), token }),
|
|
@@ -33937,15 +34224,15 @@ var init_io2 = __esm({
|
|
|
33937
34224
|
await writeJsonAtomic(file, state);
|
|
33938
34225
|
return state;
|
|
33939
34226
|
};
|
|
33940
|
-
isRetainedDeletion = async (directory, file,
|
|
34227
|
+
isRetainedDeletion = async (directory, file, hash2) => {
|
|
33941
34228
|
try {
|
|
33942
34229
|
const inventory = await readJson(import_node_path25.default.join(directory, "retention.json"));
|
|
33943
34230
|
const index = inventory.entries.findIndex(
|
|
33944
|
-
(entry) => entry.path === file && entry.sha256 ===
|
|
34231
|
+
(entry) => entry.path === file && entry.sha256 === hash2
|
|
33945
34232
|
);
|
|
33946
34233
|
if (index < 0) return false;
|
|
33947
34234
|
const receipt = await readJson(import_node_path25.default.join(directory, "retention", `${index}.json`));
|
|
33948
|
-
return ["applying", "completed"].includes(receipt.status) && receipt.files[0]?.path === file && receipt.files[0]?.sha256 ===
|
|
34235
|
+
return ["applying", "completed"].includes(receipt.status) && receipt.files[0]?.path === file && receipt.files[0]?.sha256 === hash2;
|
|
33949
34236
|
} catch (error) {
|
|
33950
34237
|
if (error.code === "ENOENT") return false;
|
|
33951
34238
|
throw error;
|
|
@@ -35116,11 +35403,11 @@ print(json.dumps(sorted(opened)))
|
|
|
35116
35403
|
});
|
|
35117
35404
|
|
|
35118
35405
|
// src/lib/strategyRelease/evidenceRetention.ts
|
|
35119
|
-
var
|
|
35406
|
+
var DAY_MS14, isResearchRetired, planStrategyEvidenceRetention;
|
|
35120
35407
|
var init_evidenceRetention = __esm({
|
|
35121
35408
|
"src/lib/strategyRelease/evidenceRetention.ts"() {
|
|
35122
35409
|
"use strict";
|
|
35123
|
-
|
|
35410
|
+
DAY_MS14 = 864e5;
|
|
35124
35411
|
isResearchRetired = (research) => research?.status === "retired" && research.retirement?.policy === "discard-unrecoverable-without-rerun" && Boolean(research.retirement.reason.trim()) && Boolean(research.retirement.missingEvidence.length) && research.retirement.missingEvidence.every((item) => Boolean(item.trim()));
|
|
35125
35412
|
planStrategyEvidenceRetention = ({
|
|
35126
35413
|
now: now2,
|
|
@@ -35152,7 +35439,7 @@ var init_evidenceRetention = __esm({
|
|
|
35152
35439
|
const completedResearch = Boolean(
|
|
35153
35440
|
terminalResearch && research?.researchId === entry.researchId && /^[a-f0-9]{64}$/.test(entry.sha256 ?? "")
|
|
35154
35441
|
);
|
|
35155
|
-
if (isResearch && !completedResearch || days == null || !entry.verified || !entry.aggregated && !(isResearch && retired) || !isResearch && now2 - entry.createdAt <= days *
|
|
35442
|
+
if (isResearch && !completedResearch || days == null || !entry.verified || !entry.aggregated && !(isResearch && retired) || !isResearch && now2 - entry.createdAt <= days * DAY_MS14) {
|
|
35156
35443
|
keep.push(entry);
|
|
35157
35444
|
} else {
|
|
35158
35445
|
remove.push(entry);
|
|
@@ -35168,14 +35455,14 @@ var init_evidenceRetention = __esm({
|
|
|
35168
35455
|
});
|
|
35169
35456
|
|
|
35170
35457
|
// src/lib/strategyRelease/researchRetention.ts
|
|
35171
|
-
var import_promises32, import_node_path27,
|
|
35458
|
+
var import_promises32, import_researchMetricSnapshot, import_node_path27, import_node_crypto20, import_strategyReleaseEvidence2, SHA256_RE2, mapFiles, fileSha256, inside, applyResearchRetention;
|
|
35172
35459
|
var init_researchRetention = __esm({
|
|
35173
35460
|
"src/lib/strategyRelease/researchRetention.ts"() {
|
|
35174
35461
|
"use strict";
|
|
35175
35462
|
import_promises32 = __toESM(require("fs/promises"));
|
|
35176
|
-
|
|
35463
|
+
import_researchMetricSnapshot = require("@tradejs/infra/researchMetricSnapshot");
|
|
35177
35464
|
import_node_path27 = __toESM(require("path"));
|
|
35178
|
-
|
|
35465
|
+
import_node_crypto20 = require("crypto");
|
|
35179
35466
|
import_strategyReleaseEvidence2 = require("@tradejs/infra/strategyReleaseEvidence");
|
|
35180
35467
|
init_researchFileConsumers();
|
|
35181
35468
|
init_evidenceRetention();
|
|
@@ -35195,7 +35482,7 @@ var init_researchRetention = __esm({
|
|
|
35195
35482
|
if (worker.status === "rejected") throw worker.reason;
|
|
35196
35483
|
return results2;
|
|
35197
35484
|
};
|
|
35198
|
-
fileSha256 = async (file, bytes) => bytes <= 1024 * 1024 ? (0,
|
|
35485
|
+
fileSha256 = async (file, bytes) => bytes <= 1024 * 1024 ? (0, import_node_crypto20.createHash)("sha256").update(await import_promises32.default.readFile(file)).digest("hex") : (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(file);
|
|
35199
35486
|
inside = (root, file) => {
|
|
35200
35487
|
const relative = import_node_path27.default.relative(root, file);
|
|
35201
35488
|
return relative !== "" && !relative.startsWith(`..${import_node_path27.default.sep}`) && relative !== ".." && !import_node_path27.default.isAbsolute(relative);
|
|
@@ -35258,7 +35545,7 @@ var init_researchRetention = __esm({
|
|
|
35258
35545
|
throw new Error(
|
|
35259
35546
|
"Complete v2 note needs one verified metric snapshot"
|
|
35260
35547
|
);
|
|
35261
|
-
decodeResearchMetricSnapshot(JSON.parse(blocks[0][1]));
|
|
35548
|
+
(0, import_researchMetricSnapshot.decodeResearchMetricSnapshot)(JSON.parse(blocks[0][1]));
|
|
35262
35549
|
}
|
|
35263
35550
|
} finally {
|
|
35264
35551
|
await handle.close();
|
|
@@ -35382,11 +35669,11 @@ var init_retention = __esm({
|
|
|
35382
35669
|
}
|
|
35383
35670
|
const files = /* @__PURE__ */ new Map();
|
|
35384
35671
|
for (const stage of Object.values(state.stages)) {
|
|
35385
|
-
for (const [relative,
|
|
35672
|
+
for (const [relative, hash2] of Object.entries(stage.artifacts)) {
|
|
35386
35673
|
const file = await boundResearchPath(directory, relative);
|
|
35387
35674
|
if (relative.endsWith("/result.json")) {
|
|
35388
35675
|
const result = await readJson(file);
|
|
35389
|
-
if (result?.dataset) files.set(file,
|
|
35676
|
+
if (result?.dataset) files.set(file, hash2);
|
|
35390
35677
|
}
|
|
35391
35678
|
if (relative.endsWith("/sources.json") || relative.endsWith("/payloads.json")) {
|
|
35392
35679
|
const sources = await readJson(file);
|
|
@@ -35403,13 +35690,13 @@ var init_retention = __esm({
|
|
|
35403
35690
|
}
|
|
35404
35691
|
}
|
|
35405
35692
|
const entries = [];
|
|
35406
|
-
for (const [file,
|
|
35693
|
+
for (const [file, hash2] of files) {
|
|
35407
35694
|
const stat = await import_promises33.default.stat(file);
|
|
35408
35695
|
entries.push({
|
|
35409
35696
|
path: file,
|
|
35410
35697
|
kind: "research_payload",
|
|
35411
35698
|
researchId: spec.core.researchId,
|
|
35412
|
-
sha256:
|
|
35699
|
+
sha256: hash2,
|
|
35413
35700
|
bytes: stat.size,
|
|
35414
35701
|
createdAt: stat.birthtimeMs,
|
|
35415
35702
|
verified: true,
|
|
@@ -35493,12 +35780,12 @@ var init_retention = __esm({
|
|
|
35493
35780
|
});
|
|
35494
35781
|
|
|
35495
35782
|
// src/lib/strategyResearch/orchestrator.ts
|
|
35496
|
-
var import_promises34, import_node_path29, runStrategyResearch;
|
|
35783
|
+
var import_promises34, import_researchMetricSnapshot2, import_node_path29, runStrategyResearch;
|
|
35497
35784
|
var init_orchestrator2 = __esm({
|
|
35498
35785
|
"src/lib/strategyResearch/orchestrator.ts"() {
|
|
35499
35786
|
"use strict";
|
|
35500
35787
|
import_promises34 = __toESM(require("fs/promises"));
|
|
35501
|
-
|
|
35788
|
+
import_researchMetricSnapshot2 = require("@tradejs/infra/researchMetricSnapshot");
|
|
35502
35789
|
import_node_path29 = __toESM(require("path"));
|
|
35503
35790
|
init_metrics();
|
|
35504
35791
|
init_io();
|
|
@@ -35689,7 +35976,7 @@ var init_orchestrator2 = __esm({
|
|
|
35689
35976
|
});
|
|
35690
35977
|
let partitionControl;
|
|
35691
35978
|
if (spec.testSince === 0) {
|
|
35692
|
-
const
|
|
35979
|
+
const control = spec.core.variants.find(
|
|
35693
35980
|
(variant) => variant.role === "control"
|
|
35694
35981
|
);
|
|
35695
35982
|
partitionControl = await stage(
|
|
@@ -35706,7 +35993,7 @@ var init_orchestrator2 = __esm({
|
|
|
35706
35993
|
}
|
|
35707
35994
|
return backend.runVariant(
|
|
35708
35995
|
spec,
|
|
35709
|
-
|
|
35996
|
+
control,
|
|
35710
35997
|
folder,
|
|
35711
35998
|
async (runId) => writeJsonAtomic(import_node_path29.default.join(folder, "native-run.json"), {
|
|
35712
35999
|
runId
|
|
@@ -35728,9 +36015,6 @@ var init_orchestrator2 = __esm({
|
|
|
35728
36015
|
let frozenSelection;
|
|
35729
36016
|
const raw = {};
|
|
35730
36017
|
const discovered = [];
|
|
35731
|
-
const control = spec.core.variants.find(
|
|
35732
|
-
(variant) => variant.role === "control"
|
|
35733
|
-
);
|
|
35734
36018
|
const currentPolicy = {
|
|
35735
36019
|
schema: "tradejs-research-entry-policy/v1",
|
|
35736
36020
|
strategy: spec.core.strategy,
|
|
@@ -36206,7 +36490,7 @@ ${JSON.stringify(spec, null, 2)}
|
|
|
36206
36490
|
## Metrics snapshot (machine-readable)
|
|
36207
36491
|
|
|
36208
36492
|
\`\`\`json
|
|
36209
|
-
${JSON.stringify(encodeResearchMetricSnapshot(compact))}
|
|
36493
|
+
${JSON.stringify((0, import_researchMetricSnapshot2.encodeResearchMetricSnapshot)(compact))}
|
|
36210
36494
|
\`\`\`
|
|
36211
36495
|
|
|
36212
36496
|
## Reported metrics
|
|
@@ -36324,7 +36608,7 @@ ${conclusion.nextAction} Current-snapshot universe; no deployment authorization.
|
|
|
36324
36608
|
});
|
|
36325
36609
|
|
|
36326
36610
|
// src/lib/strategyResearch/native.ts
|
|
36327
|
-
var import_promises35, import_node_fs9, import_node_path30, import_node_os4, import_node_readline4, import_node_child_process8, import_node_module3,
|
|
36611
|
+
var import_promises35, import_node_fs9, import_node_path30, import_node_os4, import_node_readline4, import_node_child_process8, import_node_module3, import_redis18, import_ai9, import_backtest7, import_registry5, import_connectors15, import_data9, import_coreResearch2, import_jev6, validateResearchJevTraining, nativeConfig, runResearchCommand, createNativeStrategyResearchBackend;
|
|
36328
36612
|
var init_native = __esm({
|
|
36329
36613
|
"src/lib/strategyResearch/native.ts"() {
|
|
36330
36614
|
"use strict";
|
|
@@ -36335,11 +36619,11 @@ var init_native = __esm({
|
|
|
36335
36619
|
import_node_readline4 = __toESM(require("readline"));
|
|
36336
36620
|
import_node_child_process8 = require("child_process");
|
|
36337
36621
|
import_node_module3 = require("module");
|
|
36338
|
-
|
|
36622
|
+
import_redis18 = require("@tradejs/infra/redis");
|
|
36339
36623
|
import_ai9 = require("@tradejs/node/ai");
|
|
36340
36624
|
import_backtest7 = require("@tradejs/node/backtest");
|
|
36341
36625
|
import_registry5 = require("@tradejs/node/registry");
|
|
36342
|
-
|
|
36626
|
+
import_connectors15 = require("@tradejs/node/connectors");
|
|
36343
36627
|
init_dataset2();
|
|
36344
36628
|
init_reconciliation();
|
|
36345
36629
|
init_metrics();
|
|
@@ -36500,7 +36784,7 @@ var init_native = __esm({
|
|
|
36500
36784
|
let connector;
|
|
36501
36785
|
const getConnector = async (spec) => {
|
|
36502
36786
|
if (connector) return connector;
|
|
36503
|
-
const creator = await (0,
|
|
36787
|
+
const creator = await (0, import_connectors15.getConnectorCreatorByName)(
|
|
36504
36788
|
spec.core.execution.connector,
|
|
36505
36789
|
projectRoot18
|
|
36506
36790
|
);
|
|
@@ -36799,11 +37083,11 @@ var init_native = __esm({
|
|
|
36799
37083
|
const grid = Object.fromEntries(
|
|
36800
37084
|
Object.entries(config2).map(([key3, value]) => [key3, [value]])
|
|
36801
37085
|
);
|
|
36802
|
-
const key2 =
|
|
36803
|
-
const existing = await (0,
|
|
37086
|
+
const key2 = import_redis18.redisKeys.backtestConfig("root", configName);
|
|
37087
|
+
const existing = await (0, import_redis18.getData)(key2, null);
|
|
36804
37088
|
if (existing != null && sha256Json(existing) !== sha256Json(grid))
|
|
36805
37089
|
throw new Error(`Frozen research config changed: ${configName}`);
|
|
36806
|
-
if (existing == null) await (0,
|
|
37090
|
+
if (existing == null) await (0, import_redis18.setData)(key2, grid, { expire: 0 });
|
|
36807
37091
|
let runId = previousRunId ?? "";
|
|
36808
37092
|
const common = {
|
|
36809
37093
|
executable: process.execPath,
|
|
@@ -37235,9 +37519,9 @@ var init_strategyResearch = __esm({
|
|
|
37235
37519
|
// src/scripts/strategyResearch.ts
|
|
37236
37520
|
var strategyResearch_exports = {};
|
|
37237
37521
|
__export(strategyResearch_exports, {
|
|
37238
|
-
main: () =>
|
|
37522
|
+
main: () => main38
|
|
37239
37523
|
});
|
|
37240
|
-
var import_promises36, import_node_path31,
|
|
37524
|
+
var import_promises36, import_node_path31, import_redis19, usage, main38;
|
|
37241
37525
|
var init_strategyResearch2 = __esm({
|
|
37242
37526
|
"src/scripts/strategyResearch.ts"() {
|
|
37243
37527
|
"use strict";
|
|
@@ -37247,7 +37531,7 @@ var init_strategyResearch2 = __esm({
|
|
|
37247
37531
|
init_researchRoots();
|
|
37248
37532
|
init_io();
|
|
37249
37533
|
init_orchestrator();
|
|
37250
|
-
|
|
37534
|
+
import_redis19 = require("@tradejs/infra/redis");
|
|
37251
37535
|
init_io2();
|
|
37252
37536
|
usage = `Usage:
|
|
37253
37537
|
tradejs research:strategy init --coreSpec <core-spec.json> --out <workflow.json>
|
|
@@ -37262,7 +37546,7 @@ frozen rules, actual gated entries, non-fast and delayed-entry confirmation.
|
|
|
37262
37546
|
Resume with the same run command. No notifications, publication or live orders.
|
|
37263
37547
|
Revalidate keeps the frozen rule and evaluates a new period without fitting.
|
|
37264
37548
|
`;
|
|
37265
|
-
|
|
37549
|
+
main38 = async () => {
|
|
37266
37550
|
const argv2 = process.argv.slice(2);
|
|
37267
37551
|
const command = argv2.shift();
|
|
37268
37552
|
if (!command || command === "--help") {
|
|
@@ -37335,8 +37619,8 @@ Revalidate keeps the frozen rule and evaluates a new period without fitting.
|
|
|
37335
37619
|
throw new Error(
|
|
37336
37620
|
"Every config must belong to the selected strategy"
|
|
37337
37621
|
);
|
|
37338
|
-
const grid = await (0,
|
|
37339
|
-
|
|
37622
|
+
const grid = await (0, import_redis19.getData)(
|
|
37623
|
+
import_redis19.redisKeys.backtestConfig("root", configName),
|
|
37340
37624
|
null
|
|
37341
37625
|
);
|
|
37342
37626
|
if (!grid || typeof grid !== "object" || Array.isArray(grid) || !Object.keys(grid).length)
|
|
@@ -37473,18 +37757,18 @@ Revalidate keeps the frozen rule and evaluates a new period without fitting.
|
|
|
37473
37757
|
// src/scripts/results.ts
|
|
37474
37758
|
var results_exports = {};
|
|
37475
37759
|
__export(results_exports, {
|
|
37476
|
-
main: () =>
|
|
37760
|
+
main: () => main39,
|
|
37477
37761
|
results: () => results
|
|
37478
37762
|
});
|
|
37479
|
-
var import_args26, import_chalk42,
|
|
37763
|
+
var import_args26, import_chalk42, import_connectors16, import_cli11, import_redis20, ListIt4, flags24, MIN_PROFIT, MIN_WIN_RATE, MIN_ORDERS_PER_MONTH, createListIt4, formatPercent4, getMonthlyReturn, toStrategyResultEntry, toStrategyResults, getTestConfigs, buildBestResults, getSavedProfitsBySymbol, getCoverageRow, results, main39;
|
|
37480
37764
|
var init_results = __esm({
|
|
37481
37765
|
"src/scripts/results.ts"() {
|
|
37482
37766
|
"use strict";
|
|
37483
37767
|
import_args26 = __toESM(require("args"));
|
|
37484
37768
|
import_chalk42 = __toESM(require("chalk"));
|
|
37485
|
-
|
|
37769
|
+
import_connectors16 = require("@tradejs/connectors");
|
|
37486
37770
|
import_cli11 = require("@tradejs/node/cli");
|
|
37487
|
-
|
|
37771
|
+
import_redis20 = require("@tradejs/infra/redis");
|
|
37488
37772
|
ListIt4 = require("list-it");
|
|
37489
37773
|
import_args26.default.example(
|
|
37490
37774
|
"yarn results --strategy TrendLine --coverage",
|
|
@@ -37524,8 +37808,8 @@ var init_results = __esm({
|
|
|
37524
37808
|
[...rows].map((row) => [row.symbol, toStrategyResultEntry(row)])
|
|
37525
37809
|
);
|
|
37526
37810
|
getTestConfigs = async (userName3) => {
|
|
37527
|
-
const testSummariesKey = typeof
|
|
37528
|
-
const indexedItems = testSummariesKey ? await (0,
|
|
37811
|
+
const testSummariesKey = typeof import_redis20.redisKeys.testSummaries === "function" ? import_redis20.redisKeys.testSummaries(userName3) : null;
|
|
37812
|
+
const indexedItems = testSummariesKey ? await (0, import_redis20.getData)(testSummariesKey, null) : null;
|
|
37529
37813
|
if (Array.isArray(indexedItems) && indexedItems.length) {
|
|
37530
37814
|
return indexedItems.map((item) => {
|
|
37531
37815
|
const testName = typeof item?.value === "string" ? item.value : null;
|
|
@@ -37536,8 +37820,8 @@ var init_results = __esm({
|
|
|
37536
37820
|
return { strategyName, testName };
|
|
37537
37821
|
}).filter(Boolean);
|
|
37538
37822
|
}
|
|
37539
|
-
const testsPrefix =
|
|
37540
|
-
const keys = await (0,
|
|
37823
|
+
const testsPrefix = import_redis20.redisKeys.tests(userName3);
|
|
37824
|
+
const keys = await (0, import_redis20.getKeys)(testsPrefix);
|
|
37541
37825
|
const configKeys = keys.filter((key2) => key2.endsWith(":config"));
|
|
37542
37826
|
return configKeys.map((key2) => {
|
|
37543
37827
|
const parts = key2.split(":");
|
|
@@ -37556,15 +37840,15 @@ var init_results = __esm({
|
|
|
37556
37840
|
testName,
|
|
37557
37841
|
strategyName: strategyFromIndex
|
|
37558
37842
|
} of testConfigs) {
|
|
37559
|
-
const config2 = await (0,
|
|
37560
|
-
|
|
37843
|
+
const config2 = await (0, import_redis20.getData)(
|
|
37844
|
+
import_redis20.redisKeys.testConfig(userName3, strategyFromIndex, testName),
|
|
37561
37845
|
null
|
|
37562
37846
|
);
|
|
37563
37847
|
if (!config2 || config2.strategyName !== strategyName) {
|
|
37564
37848
|
continue;
|
|
37565
37849
|
}
|
|
37566
|
-
const stat = await (0,
|
|
37567
|
-
|
|
37850
|
+
const stat = await (0, import_redis20.getData)(
|
|
37851
|
+
import_redis20.redisKeys.testStat(userName3, strategyFromIndex, testName),
|
|
37568
37852
|
null
|
|
37569
37853
|
);
|
|
37570
37854
|
if (!stat) {
|
|
@@ -37609,8 +37893,8 @@ var init_results = __esm({
|
|
|
37609
37893
|
return savedProfitBySymbol;
|
|
37610
37894
|
};
|
|
37611
37895
|
getCoverageRow = async (strategyName, userName3, goodSymbols) => {
|
|
37612
|
-
const currentResults = await (0,
|
|
37613
|
-
|
|
37896
|
+
const currentResults = await (0, import_redis20.getData)(
|
|
37897
|
+
import_redis20.redisKeys.strategyResults(userName3, strategyName),
|
|
37614
37898
|
{}
|
|
37615
37899
|
);
|
|
37616
37900
|
const existingSymbols = new Set(Object.keys(currentResults));
|
|
@@ -37623,7 +37907,7 @@ var init_results = __esm({
|
|
|
37623
37907
|
goodMissing += 1;
|
|
37624
37908
|
}
|
|
37625
37909
|
}
|
|
37626
|
-
const byBitConnector = await
|
|
37910
|
+
const byBitConnector = await import_connectors16.connectors.ByBit({
|
|
37627
37911
|
userName: userName3
|
|
37628
37912
|
});
|
|
37629
37913
|
const tickers = await (0, import_cli11.getTickers)(byBitConnector);
|
|
@@ -37644,8 +37928,8 @@ var init_results = __esm({
|
|
|
37644
37928
|
const strategyName = flags24.strategy;
|
|
37645
37929
|
const userName3 = flags24.user;
|
|
37646
37930
|
if (flags24.clear) {
|
|
37647
|
-
const cleared = await (0,
|
|
37648
|
-
|
|
37931
|
+
const cleared = await (0, import_redis20.delKey)(
|
|
37932
|
+
import_redis20.redisKeys.strategyResults(userName3, strategyName)
|
|
37649
37933
|
);
|
|
37650
37934
|
console.log(
|
|
37651
37935
|
cleared ? import_chalk42.default.green(`Cleared results:${strategyName}`) : import_chalk42.default.yellow(`No results to clear for ${strategyName}`)
|
|
@@ -37693,8 +37977,8 @@ var init_results = __esm({
|
|
|
37693
37977
|
console.log(import_chalk42.default.yellow("No good results to merge."));
|
|
37694
37978
|
process.exit(0);
|
|
37695
37979
|
}
|
|
37696
|
-
const current = await (0,
|
|
37697
|
-
|
|
37980
|
+
const current = await (0, import_redis20.getData)(
|
|
37981
|
+
import_redis20.redisKeys.strategyResults(userName3, strategyName),
|
|
37698
37982
|
{}
|
|
37699
37983
|
);
|
|
37700
37984
|
const savedProfitBySymbol = await getSavedProfitsBySymbol(current);
|
|
@@ -37716,7 +38000,7 @@ var init_results = __esm({
|
|
|
37716
38000
|
...current,
|
|
37717
38001
|
...toStrategyResults(updates)
|
|
37718
38002
|
};
|
|
37719
|
-
await (0,
|
|
38003
|
+
await (0, import_redis20.setData)(import_redis20.redisKeys.strategyResults(userName3, strategyName), merged, {
|
|
37720
38004
|
expire: 0
|
|
37721
38005
|
});
|
|
37722
38006
|
if (flags24.verbose) {
|
|
@@ -37757,8 +38041,8 @@ var init_results = __esm({
|
|
|
37757
38041
|
);
|
|
37758
38042
|
process.exit(0);
|
|
37759
38043
|
}
|
|
37760
|
-
await (0,
|
|
37761
|
-
|
|
38044
|
+
await (0, import_redis20.setData)(
|
|
38045
|
+
import_redis20.redisKeys.strategyResults(userName3, strategyName),
|
|
37762
38046
|
resultsConfig,
|
|
37763
38047
|
{
|
|
37764
38048
|
expire: 0
|
|
@@ -37772,16 +38056,16 @@ var init_results = __esm({
|
|
|
37772
38056
|
}
|
|
37773
38057
|
process.exit();
|
|
37774
38058
|
};
|
|
37775
|
-
|
|
38059
|
+
main39 = results;
|
|
37776
38060
|
}
|
|
37777
38061
|
});
|
|
37778
38062
|
|
|
37779
38063
|
// src/lib/runtimeDebugEvidence.ts
|
|
37780
|
-
var
|
|
38064
|
+
var import_redis21, RUNTIME_DEBUG_TIMEZONE, RUNTIME_DEBUG_TIMEZONE_LABEL, formatRuntimeDebugDateTime, getRuntimeDebugDateParts, formatRuntimeDebugIsoDayKey, buildRuntimeDebugEvaluationId, filterByStrategies, collectRuntimeDebugEvidence, buildRuntimeDebugReportPayload, buildRuntimeEvidenceReportPayload, buildRuntimeDebugReportAttachment;
|
|
37781
38065
|
var init_runtimeDebugEvidence = __esm({
|
|
37782
38066
|
"src/lib/runtimeDebugEvidence.ts"() {
|
|
37783
38067
|
"use strict";
|
|
37784
|
-
|
|
38068
|
+
import_redis21 = require("@tradejs/infra/redis");
|
|
37785
38069
|
init_runtimeRedis();
|
|
37786
38070
|
init_runtimeSignalsLoader();
|
|
37787
38071
|
init_runtimeSignalsStorage();
|
|
@@ -37888,24 +38172,24 @@ var init_runtimeDebugEvidence = __esm({
|
|
|
37888
38172
|
const tradeDayKey = (0, import_time5.getRuntimeStorageDayKey)(trade.entryTimestamp);
|
|
37889
38173
|
const signalDayKey = signal != null ? (0, import_time5.getRuntimeStorageDayKey)(signal.timestamp) : tradeDayKey;
|
|
37890
38174
|
const evaluationDayKey = knownEvaluation != null ? (0, import_time5.getRuntimeStorageDayKey)(knownEvaluation.timestamp) : signalDayKey;
|
|
37891
|
-
const tradeKey =
|
|
37892
|
-
const tradeBucketKey =
|
|
38175
|
+
const tradeKey = import_redis21.redisKeys.runtimeTrade(userName3, trade.orderId);
|
|
38176
|
+
const tradeBucketKey = import_redis21.redisKeys.runtimeTradeBucket(
|
|
37893
38177
|
userName3,
|
|
37894
38178
|
tradeDayKey
|
|
37895
38179
|
);
|
|
37896
|
-
const activeTradeKey =
|
|
38180
|
+
const activeTradeKey = import_redis21.redisKeys.runtimeActiveTrade(
|
|
37897
38181
|
userName3,
|
|
37898
38182
|
trade.symbol,
|
|
37899
38183
|
trade.deploymentId ?? trade.accountId
|
|
37900
38184
|
);
|
|
37901
|
-
const signalKey = trade.signalId != null ?
|
|
37902
|
-
const evaluationBucketKey =
|
|
38185
|
+
const signalKey = trade.signalId != null ? import_redis21.redisKeys.storeSignal(trade.symbol, trade.signalId) : null;
|
|
38186
|
+
const evaluationBucketKey = import_redis21.redisKeys.runtimeSignalEvaluationBucket(
|
|
37903
38187
|
userName3,
|
|
37904
38188
|
evaluationDayKey,
|
|
37905
38189
|
knownEvaluation?.strategy ?? trade.strategy
|
|
37906
38190
|
);
|
|
37907
38191
|
const evaluationField = knownEvaluation?.evaluationId ?? evaluationId;
|
|
37908
|
-
const evaluationKey =
|
|
38192
|
+
const evaluationKey = import_redis21.redisKeys.runtimeSignalEvaluation(
|
|
37909
38193
|
userName3,
|
|
37910
38194
|
evaluationField
|
|
37911
38195
|
);
|
|
@@ -37916,11 +38200,11 @@ var init_runtimeDebugEvidence = __esm({
|
|
|
37916
38200
|
directEvaluationValue,
|
|
37917
38201
|
bucketEvaluationValue
|
|
37918
38202
|
] = await Promise.all([
|
|
37919
|
-
(0,
|
|
37920
|
-
(0,
|
|
37921
|
-
signalKey ? (0,
|
|
37922
|
-
(0,
|
|
37923
|
-
knownEvaluation ? Promise.resolve(knownEvaluation) : (0,
|
|
38203
|
+
(0, import_redis21.getData)(tradeKey, null),
|
|
38204
|
+
(0, import_redis21.getData)(activeTradeKey, null),
|
|
38205
|
+
signalKey ? (0, import_redis21.getData)(signalKey, null) : Promise.resolve(null),
|
|
38206
|
+
(0, import_redis21.getData)(evaluationKey, null),
|
|
38207
|
+
knownEvaluation ? Promise.resolve(knownEvaluation) : (0, import_redis21.getHashJsonField)(
|
|
37924
38208
|
evaluationBucketKey,
|
|
37925
38209
|
evaluationField,
|
|
37926
38210
|
null
|
|
@@ -37977,12 +38261,12 @@ var init_runtimeDebugEvidence = __esm({
|
|
|
37977
38261
|
dayKeys
|
|
37978
38262
|
},
|
|
37979
38263
|
redisPrefixes: {
|
|
37980
|
-
runtimeTrades:
|
|
37981
|
-
runtimeTradeBuckets:
|
|
37982
|
-
runtimeActiveTrades:
|
|
37983
|
-
runtimeSignals:
|
|
37984
|
-
runtimeSignalEvaluations:
|
|
37985
|
-
runtimeSignalEvaluationStats:
|
|
38264
|
+
runtimeTrades: import_redis21.redisKeys.runtimeTrades(userName3),
|
|
38265
|
+
runtimeTradeBuckets: import_redis21.redisKeys.runtimeTradeBuckets(userName3),
|
|
38266
|
+
runtimeActiveTrades: import_redis21.redisKeys.runtimeActiveTrades(userName3),
|
|
38267
|
+
runtimeSignals: import_redis21.redisKeys.runtimeSignalBuckets(userName3),
|
|
38268
|
+
runtimeSignalEvaluations: import_redis21.redisKeys.runtimeSignalEvaluationBuckets(userName3),
|
|
38269
|
+
runtimeSignalEvaluationStats: import_redis21.redisKeys.runtimeSignalEvaluationStatsBuckets(userName3)
|
|
37986
38270
|
},
|
|
37987
38271
|
counts: {
|
|
37988
38272
|
trades: trades.length,
|
|
@@ -37993,18 +38277,18 @@ var init_runtimeDebugEvidence = __esm({
|
|
|
37993
38277
|
},
|
|
37994
38278
|
trades: debugTrades,
|
|
37995
38279
|
signals: signals2.map((signal) => ({
|
|
37996
|
-
redisKey:
|
|
38280
|
+
redisKey: import_redis21.redisKeys.storeSignal(signal.symbol, signal.signalId),
|
|
37997
38281
|
signal
|
|
37998
38282
|
})),
|
|
37999
38283
|
evaluations: reportEvaluations.map((evaluation) => ({
|
|
38000
38284
|
redisDebug: {
|
|
38001
|
-
key:
|
|
38285
|
+
key: import_redis21.redisKeys.runtimeSignalEvaluationBucket(
|
|
38002
38286
|
userName3,
|
|
38003
38287
|
(0, import_time5.getRuntimeStorageDayKey)(evaluation.timestamp),
|
|
38004
38288
|
evaluation.strategy
|
|
38005
38289
|
),
|
|
38006
38290
|
field: evaluation.evaluationId,
|
|
38007
|
-
directKey:
|
|
38291
|
+
directKey: import_redis21.redisKeys.runtimeSignalEvaluation(
|
|
38008
38292
|
userName3,
|
|
38009
38293
|
evaluation.evaluationId
|
|
38010
38294
|
)
|
|
@@ -38065,11 +38349,11 @@ var init_runtimeDebugEvidence = __esm({
|
|
|
38065
38349
|
// src/scripts/replayRuntimeEvidence.ts
|
|
38066
38350
|
var replayRuntimeEvidence_exports = {};
|
|
38067
38351
|
__export(replayRuntimeEvidence_exports, {
|
|
38068
|
-
main: () =>
|
|
38352
|
+
main: () => main40,
|
|
38069
38353
|
replayRuntimeEvidence: () => replayRuntimeEvidence,
|
|
38070
38354
|
summarizeReplayComparison: () => summarizeReplayComparison
|
|
38071
38355
|
});
|
|
38072
|
-
var import_promises37, import_node_path32, import_args27, import_chalk43,
|
|
38356
|
+
var import_promises37, import_node_path32, import_args27, import_chalk43, import_redis22, toEpochMs2, resolveWindow, parseStrategyFilter, asRecord5, asArray2, sum, groupCount, compactMatched, resolveItemStrategy, summarizeReplayComparison, loadReplayResult, getReplayStrategies, loadRuntimePayload, replayRuntimeEvidence, main40;
|
|
38073
38357
|
var init_replayRuntimeEvidence = __esm({
|
|
38074
38358
|
"src/scripts/replayRuntimeEvidence.ts"() {
|
|
38075
38359
|
"use strict";
|
|
@@ -38079,7 +38363,7 @@ var init_replayRuntimeEvidence = __esm({
|
|
|
38079
38363
|
import_node_path32 = __toESM(require("path"));
|
|
38080
38364
|
import_args27 = __toESM(require("args"));
|
|
38081
38365
|
import_chalk43 = __toESM(require("chalk"));
|
|
38082
|
-
|
|
38366
|
+
import_redis22 = require("@tradejs/infra/redis");
|
|
38083
38367
|
init_runtimeDebugEvidence();
|
|
38084
38368
|
init_support2();
|
|
38085
38369
|
import_args27.default.option(["u", "user"], "Use user config", "root");
|
|
@@ -38168,6 +38452,8 @@ var init_replayRuntimeEvidence = __esm({
|
|
|
38168
38452
|
timestampDiffMs: item.timestampDiffMs ?? null,
|
|
38169
38453
|
backtestPrice: backtest2.price ?? null,
|
|
38170
38454
|
runtimePrice: runtime.price ?? null,
|
|
38455
|
+
backtestQty: backtest2.qty ?? null,
|
|
38456
|
+
runtimeQty: runtime.qty ?? null,
|
|
38171
38457
|
backtestExitPrice: backtest2.exitPrice ?? null,
|
|
38172
38458
|
runtimeExitPrice: runtime.exitPrice ?? null,
|
|
38173
38459
|
expectedPnl: pnl.expectedPnl ?? null,
|
|
@@ -38178,7 +38464,8 @@ var init_replayRuntimeEvidence = __esm({
|
|
|
38178
38464
|
totalSlippageCost: slippage.totalCost ?? null,
|
|
38179
38465
|
orderId: runtime.orderId ?? backtest2.orderId ?? null,
|
|
38180
38466
|
orderLinkId: runtime.orderLinkId ?? null,
|
|
38181
|
-
signalId: backtest2.signalId ?? null
|
|
38467
|
+
signalId: backtest2.signalId ?? null,
|
|
38468
|
+
runtimeSignalId: runtime.signalId ?? null
|
|
38182
38469
|
};
|
|
38183
38470
|
};
|
|
38184
38471
|
resolveItemStrategy = (item) => asRecord5(item.backtest).strategy ?? asRecord5(item.runtime).inferredStrategy ?? item.strategy ?? item.inferredStrategy ?? null;
|
|
@@ -38299,18 +38586,18 @@ var init_replayRuntimeEvidence = __esm({
|
|
|
38299
38586
|
return {
|
|
38300
38587
|
key: replayKey,
|
|
38301
38588
|
availableKeys: void 0,
|
|
38302
|
-
value: await (0,
|
|
38589
|
+
value: await (0, import_redis22.getData)(replayKey, null)
|
|
38303
38590
|
};
|
|
38304
38591
|
}
|
|
38305
|
-
const prefix =
|
|
38306
|
-
const keys = (await (0,
|
|
38592
|
+
const prefix = import_redis22.redisKeys.backtestResults(userName3, REPLAY_RESULTS_CONFIG, "");
|
|
38593
|
+
const keys = (await (0, import_redis22.getKeys)(prefix)).sort(
|
|
38307
38594
|
(left, right) => left.localeCompare(right)
|
|
38308
38595
|
);
|
|
38309
38596
|
const key2 = keys[keys.length - 1] ?? null;
|
|
38310
38597
|
return {
|
|
38311
38598
|
key: key2,
|
|
38312
38599
|
availableKeys: keys.slice(-10),
|
|
38313
|
-
value: key2 ? await (0,
|
|
38600
|
+
value: key2 ? await (0, import_redis22.getData)(key2, null) : null
|
|
38314
38601
|
};
|
|
38315
38602
|
};
|
|
38316
38603
|
getReplayStrategies = (replayValue) => {
|
|
@@ -38446,7 +38733,7 @@ var init_replayRuntimeEvidence = __esm({
|
|
|
38446
38733
|
)
|
|
38447
38734
|
);
|
|
38448
38735
|
};
|
|
38449
|
-
|
|
38736
|
+
main40 = replayRuntimeEvidence;
|
|
38450
38737
|
}
|
|
38451
38738
|
});
|
|
38452
38739
|
|
|
@@ -38754,10 +39041,10 @@ var init_runtimeFeedbackReplay = __esm({
|
|
|
38754
39041
|
// src/scripts/runtimeFeedbackReplay.ts
|
|
38755
39042
|
var runtimeFeedbackReplay_exports = {};
|
|
38756
39043
|
__export(runtimeFeedbackReplay_exports, {
|
|
38757
|
-
main: () =>
|
|
39044
|
+
main: () => main41,
|
|
38758
39045
|
runtimeFeedbackReplay: () => runtimeFeedbackReplay
|
|
38759
39046
|
});
|
|
38760
|
-
var import_node_path34, import_args28, import_chalk44, flags25, projectRoot9, runtimeFeedbackReplay,
|
|
39047
|
+
var import_node_path34, import_args28, import_chalk44, flags25, projectRoot9, runtimeFeedbackReplay, main41;
|
|
38761
39048
|
var init_runtimeFeedbackReplay2 = __esm({
|
|
38762
39049
|
"src/scripts/runtimeFeedbackReplay.ts"() {
|
|
38763
39050
|
"use strict";
|
|
@@ -38801,7 +39088,7 @@ var init_runtimeFeedbackReplay2 = __esm({
|
|
|
38801
39088
|
)
|
|
38802
39089
|
);
|
|
38803
39090
|
};
|
|
38804
|
-
|
|
39091
|
+
main41 = runtimeFeedbackReplay;
|
|
38805
39092
|
}
|
|
38806
39093
|
});
|
|
38807
39094
|
|
|
@@ -38939,10 +39226,10 @@ var init_runtimeFeedbackNotification = __esm({
|
|
|
38939
39226
|
// src/scripts/runtimeFeedbackNotify.ts
|
|
38940
39227
|
var runtimeFeedbackNotify_exports = {};
|
|
38941
39228
|
__export(runtimeFeedbackNotify_exports, {
|
|
38942
|
-
main: () =>
|
|
39229
|
+
main: () => main42,
|
|
38943
39230
|
runtimeFeedbackNotify: () => runtimeFeedbackNotify
|
|
38944
39231
|
});
|
|
38945
|
-
var import_node_path35, import_args29, import_chalk45, flags26, projectRoot10, runtimeFeedbackNotify,
|
|
39232
|
+
var import_node_path35, import_args29, import_chalk45, flags26, projectRoot10, runtimeFeedbackNotify, main42;
|
|
38946
39233
|
var init_runtimeFeedbackNotify = __esm({
|
|
38947
39234
|
"src/scripts/runtimeFeedbackNotify.ts"() {
|
|
38948
39235
|
"use strict";
|
|
@@ -38973,7 +39260,7 @@ var init_runtimeFeedbackNotify = __esm({
|
|
|
38973
39260
|
)
|
|
38974
39261
|
);
|
|
38975
39262
|
};
|
|
38976
|
-
|
|
39263
|
+
main42 = runtimeFeedbackNotify;
|
|
38977
39264
|
}
|
|
38978
39265
|
});
|
|
38979
39266
|
|
|
@@ -39945,13 +40232,13 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
39945
40232
|
});
|
|
39946
40233
|
|
|
39947
40234
|
// src/lib/runtimeFeedbackProcess.ts
|
|
39948
|
-
var import_promises40, import_node_path37,
|
|
40235
|
+
var import_promises40, import_node_path37, import_node_crypto21, import_diagnostics2, processRuntimeFeedbackPair;
|
|
39949
40236
|
var init_runtimeFeedbackProcess = __esm({
|
|
39950
40237
|
"src/lib/runtimeFeedbackProcess.ts"() {
|
|
39951
40238
|
"use strict";
|
|
39952
40239
|
import_promises40 = __toESM(require("fs/promises"));
|
|
39953
40240
|
import_node_path37 = __toESM(require("path"));
|
|
39954
|
-
|
|
40241
|
+
import_node_crypto21 = require("crypto");
|
|
39955
40242
|
import_diagnostics2 = require("@tradejs/node/diagnostics");
|
|
39956
40243
|
init_executionCalibration();
|
|
39957
40244
|
init_runtimeScorecard();
|
|
@@ -40010,7 +40297,7 @@ var init_runtimeFeedbackProcess = __esm({
|
|
|
40010
40297
|
if (historyDir)
|
|
40011
40298
|
for (const directory of await (0, import_diagnostics2.discoverRuntimeEvidenceBundles)(historyDir))
|
|
40012
40299
|
history.push((await (0, import_diagnostics2.verifyRuntimeEvidenceBundle)(directory)).artifact);
|
|
40013
|
-
const runId = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:.]/g, "") + "-" + (0,
|
|
40300
|
+
const runId = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:.]/g, "") + "-" + (0, import_node_crypto21.randomUUID)();
|
|
40014
40301
|
const runDir = import_node_path37.default.join(outputRoot, artifactId, runId);
|
|
40015
40302
|
await import_promises40.default.mkdir(runDir, { recursive: true });
|
|
40016
40303
|
const calibration = buildExecutionCalibrationReport({
|
|
@@ -40065,9 +40352,9 @@ var init_runtimeFeedbackProcess = __esm({
|
|
|
40065
40352
|
// src/scripts/runtimeFeedbackProcess.ts
|
|
40066
40353
|
var runtimeFeedbackProcess_exports = {};
|
|
40067
40354
|
__export(runtimeFeedbackProcess_exports, {
|
|
40068
|
-
main: () =>
|
|
40355
|
+
main: () => main43
|
|
40069
40356
|
});
|
|
40070
|
-
var import_args30, import_node_path38, flags27,
|
|
40357
|
+
var import_args30, import_node_path38, flags27, main43;
|
|
40071
40358
|
var init_runtimeFeedbackProcess2 = __esm({
|
|
40072
40359
|
"src/scripts/runtimeFeedbackProcess.ts"() {
|
|
40073
40360
|
"use strict";
|
|
@@ -40088,7 +40375,7 @@ var init_runtimeFeedbackProcess2 = __esm({
|
|
|
40088
40375
|
"data/runtime-evidence/artifacts/production"
|
|
40089
40376
|
);
|
|
40090
40377
|
flags27 = import_args30.default.parse(process.argv);
|
|
40091
|
-
|
|
40378
|
+
main43 = async () => {
|
|
40092
40379
|
if (!flags27.runtimeDir || !flags27.replayDir)
|
|
40093
40380
|
throw new Error("Provide --runtimeDir and --replayDir");
|
|
40094
40381
|
const root = process.env.PROJECT_CWD || process.cwd();
|
|
@@ -40201,10 +40488,10 @@ var init_runtimeFeedbackSync = __esm({
|
|
|
40201
40488
|
// src/scripts/runtimeFeedbackSync.ts
|
|
40202
40489
|
var runtimeFeedbackSync_exports = {};
|
|
40203
40490
|
__export(runtimeFeedbackSync_exports, {
|
|
40204
|
-
main: () =>
|
|
40491
|
+
main: () => main44,
|
|
40205
40492
|
runtimeFeedbackSync: () => runtimeFeedbackSync
|
|
40206
40493
|
});
|
|
40207
|
-
var import_node_path40, import_args31, import_chalk46, flags28, projectRoot11, runtimeFeedbackSync,
|
|
40494
|
+
var import_node_path40, import_args31, import_chalk46, flags28, projectRoot11, runtimeFeedbackSync, main44;
|
|
40208
40495
|
var init_runtimeFeedbackSync2 = __esm({
|
|
40209
40496
|
"src/scripts/runtimeFeedbackSync.ts"() {
|
|
40210
40497
|
"use strict";
|
|
@@ -40263,16 +40550,16 @@ var init_runtimeFeedbackSync2 = __esm({
|
|
|
40263
40550
|
)
|
|
40264
40551
|
);
|
|
40265
40552
|
};
|
|
40266
|
-
|
|
40553
|
+
main44 = runtimeFeedbackSync;
|
|
40267
40554
|
}
|
|
40268
40555
|
});
|
|
40269
40556
|
|
|
40270
40557
|
// src/lib/runtimeEvidenceCompositionSnapshots.ts
|
|
40271
|
-
var
|
|
40558
|
+
var import_node_crypto22, import_promises42, import_node_path41, SNAPSHOT_FILE, MANIFEST_FILE, COMPLETE_FILE, createRuntimeEvidenceCompositionSnapshotRecorder, isRecord2, sha256, safeSegment4, isExistingDestinationError3, parseManifest, verifyRuntimeEvidenceCompositionSnapshot, sameSnapshot, publishRuntimeEvidenceCompositionSnapshot, captureRuntimeEvidenceCompositionSnapshot, discoverRuntimeEvidenceCompositionSnapshots;
|
|
40272
40559
|
var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
40273
40560
|
"src/lib/runtimeEvidenceCompositionSnapshots.ts"() {
|
|
40274
40561
|
"use strict";
|
|
40275
|
-
|
|
40562
|
+
import_node_crypto22 = require("crypto");
|
|
40276
40563
|
import_promises42 = __toESM(require("fs/promises"));
|
|
40277
40564
|
import_node_path41 = __toESM(require("path"));
|
|
40278
40565
|
init_runtimeEvidenceDeployment();
|
|
@@ -40295,7 +40582,7 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
|
40295
40582
|
};
|
|
40296
40583
|
};
|
|
40297
40584
|
isRecord2 = (value) => value != null && typeof value === "object" && !Array.isArray(value);
|
|
40298
|
-
sha256 = (value) => (0,
|
|
40585
|
+
sha256 = (value) => (0, import_node_crypto22.createHash)("sha256").update(value).digest("hex");
|
|
40299
40586
|
safeSegment4 = (value, label) => {
|
|
40300
40587
|
const normalized = value.trim();
|
|
40301
40588
|
if (!normalized || !/^[a-zA-Z0-9._:-]+$/.test(normalized)) {
|
|
@@ -40387,7 +40674,7 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
|
40387
40674
|
const temporaryDir = import_node_path41.default.join(
|
|
40388
40675
|
evidenceRoot,
|
|
40389
40676
|
"incoming",
|
|
40390
|
-
`snapshot-${compositionId}.tmp-${(0,
|
|
40677
|
+
`snapshot-${compositionId}.tmp-${(0, import_node_crypto22.randomUUID)()}`
|
|
40391
40678
|
);
|
|
40392
40679
|
await import_promises42.default.mkdir(temporaryDir, { recursive: true });
|
|
40393
40680
|
try {
|
|
@@ -40670,10 +40957,10 @@ var init_runtimeEvidenceCompositions = __esm({
|
|
|
40670
40957
|
// src/scripts/runtimeEvidence.ts
|
|
40671
40958
|
var runtimeEvidence_exports = {};
|
|
40672
40959
|
__export(runtimeEvidence_exports, {
|
|
40673
|
-
main: () =>
|
|
40960
|
+
main: () => main45,
|
|
40674
40961
|
runtimeEvidence: () => runtimeEvidence
|
|
40675
40962
|
});
|
|
40676
|
-
var import_promises43, import_node_path42, import_args32, import_chalk47, flags29, projectRoot12, toEpochMs3, resolveWindow2, parseStrategyFilter2, runtimeEvidence,
|
|
40963
|
+
var import_promises43, import_node_path42, import_args32, import_chalk47, flags29, projectRoot12, toEpochMs3, resolveWindow2, parseStrategyFilter2, runtimeEvidence, main45;
|
|
40677
40964
|
var init_runtimeEvidence = __esm({
|
|
40678
40965
|
"src/scripts/runtimeEvidence.ts"() {
|
|
40679
40966
|
"use strict";
|
|
@@ -40902,17 +41189,17 @@ var init_runtimeEvidence = __esm({
|
|
|
40902
41189
|
)
|
|
40903
41190
|
);
|
|
40904
41191
|
};
|
|
40905
|
-
|
|
41192
|
+
main45 = runtimeEvidence;
|
|
40906
41193
|
}
|
|
40907
41194
|
});
|
|
40908
41195
|
|
|
40909
41196
|
// src/scripts/runtimeEvidenceSync.ts
|
|
40910
41197
|
var runtimeEvidenceSync_exports = {};
|
|
40911
41198
|
__export(runtimeEvidenceSync_exports, {
|
|
40912
|
-
main: () =>
|
|
41199
|
+
main: () => main46,
|
|
40913
41200
|
runtimeEvidenceSync: () => runtimeEvidenceSync
|
|
40914
41201
|
});
|
|
40915
|
-
var import_node_path43, import_args33, import_chalk48, flags30, projectRoot13, runtimeEvidenceSync,
|
|
41202
|
+
var import_node_path43, import_args33, import_chalk48, flags30, projectRoot13, runtimeEvidenceSync, main46;
|
|
40916
41203
|
var init_runtimeEvidenceSync2 = __esm({
|
|
40917
41204
|
"src/scripts/runtimeEvidenceSync.ts"() {
|
|
40918
41205
|
"use strict";
|
|
@@ -40976,7 +41263,7 @@ var init_runtimeEvidenceSync2 = __esm({
|
|
|
40976
41263
|
)
|
|
40977
41264
|
);
|
|
40978
41265
|
};
|
|
40979
|
-
|
|
41266
|
+
main46 = runtimeEvidenceSync;
|
|
40980
41267
|
}
|
|
40981
41268
|
});
|
|
40982
41269
|
|
|
@@ -41093,11 +41380,11 @@ var init_liveDiagnosis = __esm({
|
|
|
41093
41380
|
function assert2(condition, message) {
|
|
41094
41381
|
if (!condition) throw new Error(`Invalid strategy release: ${message}`);
|
|
41095
41382
|
}
|
|
41096
|
-
var
|
|
41383
|
+
var DAY_MS15, realizedDrawdown, lowerBoundExitTimestamp, percentile2, buildStrategyMonitoringProfile;
|
|
41097
41384
|
var init_monitoringProfile = __esm({
|
|
41098
41385
|
"src/lib/strategyRelease/monitoringProfile.ts"() {
|
|
41099
41386
|
"use strict";
|
|
41100
|
-
|
|
41387
|
+
DAY_MS15 = 864e5;
|
|
41101
41388
|
realizedDrawdown = (trades, startIndex = 0, endIndex = trades.length) => {
|
|
41102
41389
|
let equity = 0;
|
|
41103
41390
|
let peak = 0;
|
|
@@ -41150,13 +41437,13 @@ var init_monitoringProfile = __esm({
|
|
|
41150
41437
|
Number.isInteger(windowDays) && windowDays > 0,
|
|
41151
41438
|
"monitoring profile days must be positive integers"
|
|
41152
41439
|
);
|
|
41153
|
-
const duration = windowDays *
|
|
41440
|
+
const duration = windowDays * DAY_MS15;
|
|
41154
41441
|
assert2(
|
|
41155
41442
|
endTime - startTime >= duration,
|
|
41156
41443
|
`${windowDays}d monitoring window exceeds historical coverage`
|
|
41157
41444
|
);
|
|
41158
41445
|
const drawdowns = [];
|
|
41159
|
-
for (let windowStart = startTime; windowStart + duration <= endTime; windowStart +=
|
|
41446
|
+
for (let windowStart = startTime; windowStart + duration <= endTime; windowStart += DAY_MS15) {
|
|
41160
41447
|
const windowEnd = windowStart + duration;
|
|
41161
41448
|
drawdowns.push(
|
|
41162
41449
|
realizedDrawdown(
|
|
@@ -41354,11 +41641,11 @@ async function collectReleaseEvidenceReferences(references) {
|
|
|
41354
41641
|
})
|
|
41355
41642
|
);
|
|
41356
41643
|
}
|
|
41357
|
-
var
|
|
41644
|
+
var import_node_crypto23, import_promises44, import_node_path44, import_types9, import_strategyReleaseEvidence3, SHA256_RE3, LINEAGE_FINGERPRINT_RE, STRATEGY_REVISION_RE, DEPLOYMENT_COMPOSITION_ID_RE, REQUIRED_LONG_WINDOWS, REQUIRED_DIAGNOSTIC_TERMINAL_WINDOWS, MIN_RECENT_DIRECTION_REPAIR_EVENTS, safeSegment5, compactTimestamp, verifyFullPeriodChartArtifact, readVerifiedJsonArtifact, verifyResearchDecisionLineage, hasExactRuntimeTarget, deriveStrategyReleaseResearchDecision, canonicalStrategyReleaseJson, strategyReleaseSha256, assertFingerprint, assertLineageFingerprint, releaseReasons, deriveReleaseGates, verifyEvidenceComposition, createStrategyReleaseManifest, createStrategyReleaseEnvelope, verifyStrategyReleaseEnvelope, verifyStrategyEvidenceMarkerEnvelope, releaseMarkers, writeJsonAtomic2, publishStrategyRelease, publishStrategyLiveDiagnosis, finiteString3, finiteNumber7, finiteDirectionPolicy, uniqueStrings, incompleteEvidenceLineage, extractEvidenceLineage, verifyCompletedCoreResearchBundle;
|
|
41358
41645
|
var init_strategyRelease = __esm({
|
|
41359
41646
|
"src/lib/strategyRelease.ts"() {
|
|
41360
41647
|
"use strict";
|
|
41361
|
-
|
|
41648
|
+
import_node_crypto23 = require("crypto");
|
|
41362
41649
|
import_promises44 = __toESM(require("fs/promises"));
|
|
41363
41650
|
import_node_path44 = __toESM(require("path"));
|
|
41364
41651
|
import_types9 = require("@tradejs/types");
|
|
@@ -42376,7 +42663,7 @@ var init_strategyRelease = __esm({
|
|
|
42376
42663
|
const artifactHashes = manifest.artifactHashes != null && typeof manifest.artifactHashes === "object" && !Array.isArray(manifest.artifactHashes) ? manifest.artifactHashes : null;
|
|
42377
42664
|
const parsedSpec = JSON.parse(specBytes.toString("utf8"));
|
|
42378
42665
|
assert3(
|
|
42379
|
-
manifest.schema === "tradejs-core-research-manifest/v1" && manifest.status === "completed" && manifest.researchId === researchId && manifest.specSha256 === specSha256 && artifactHashes?.["result.json"] === resultSha256 && (0,
|
|
42666
|
+
manifest.schema === "tradejs-core-research-manifest/v1" && manifest.status === "completed" && manifest.researchId === researchId && manifest.specSha256 === specSha256 && artifactHashes?.["result.json"] === resultSha256 && (0, import_node_crypto23.createHash)("sha256").update(canonicalStrategyReleaseJson(parsedSpec)).digest("hex") === specSha256,
|
|
42380
42667
|
"core result is not bound by its completed core research manifest"
|
|
42381
42668
|
);
|
|
42382
42669
|
for (const [relativePath, expectedSha256] of Object.entries(
|
|
@@ -42405,15 +42692,15 @@ var init_strategyRelease = __esm({
|
|
|
42405
42692
|
// src/scripts/runtimeScorecard.ts
|
|
42406
42693
|
var runtimeScorecard_exports = {};
|
|
42407
42694
|
__export(runtimeScorecard_exports, {
|
|
42408
|
-
main: () =>
|
|
42695
|
+
main: () => main47,
|
|
42409
42696
|
runtimeScorecard: () => runtimeScorecard
|
|
42410
42697
|
});
|
|
42411
|
-
var import_promises45,
|
|
42698
|
+
var import_promises45, import_node_crypto24, import_node_path45, import_args34, import_chalk49, flags31, projectRoot14, resolveOptionalPath, readJson2, assertReportType, sha256File2, loadHistoryArtifacts, runtimeScorecard, main47;
|
|
42412
42699
|
var init_runtimeScorecard2 = __esm({
|
|
42413
42700
|
"src/scripts/runtimeScorecard.ts"() {
|
|
42414
42701
|
"use strict";
|
|
42415
42702
|
import_promises45 = __toESM(require("fs/promises"));
|
|
42416
|
-
|
|
42703
|
+
import_node_crypto24 = require("crypto");
|
|
42417
42704
|
import_node_path45 = __toESM(require("path"));
|
|
42418
42705
|
import_args34 = __toESM(require("args"));
|
|
42419
42706
|
import_chalk49 = __toESM(require("chalk"));
|
|
@@ -42492,7 +42779,7 @@ var init_runtimeScorecard2 = __esm({
|
|
|
42492
42779
|
throw new Error(`${label} must be a ${expected} artifact`);
|
|
42493
42780
|
}
|
|
42494
42781
|
};
|
|
42495
|
-
sha256File2 = async (filePath) => (0,
|
|
42782
|
+
sha256File2 = async (filePath) => (0, import_node_crypto24.createHash)("sha256").update(await import_promises45.default.readFile(filePath)).digest("hex");
|
|
42496
42783
|
loadHistoryArtifacts = async (historyDir) => {
|
|
42497
42784
|
if (!historyDir) return [];
|
|
42498
42785
|
const bundleDirs = await (0, runtimeEvidenceArtifacts_exports.discoverRuntimeEvidenceBundles)(historyDir);
|
|
@@ -42660,7 +42947,7 @@ var init_runtimeScorecard2 = __esm({
|
|
|
42660
42947
|
)
|
|
42661
42948
|
);
|
|
42662
42949
|
};
|
|
42663
|
-
|
|
42950
|
+
main47 = runtimeScorecard;
|
|
42664
42951
|
}
|
|
42665
42952
|
});
|
|
42666
42953
|
|
|
@@ -42668,10 +42955,10 @@ var init_runtimeScorecard2 = __esm({
|
|
|
42668
42955
|
var runtimeControl_exports = {};
|
|
42669
42956
|
__export(runtimeControl_exports, {
|
|
42670
42957
|
RUNTIME_CONTROL_ACTIONS: () => RUNTIME_CONTROL_ACTIONS,
|
|
42671
|
-
main: () =>
|
|
42958
|
+
main: () => main48,
|
|
42672
42959
|
runtimeControl: () => runtimeControl
|
|
42673
42960
|
});
|
|
42674
|
-
var import_config9, import_runtimeControls, import_runtimeStrategies5, argv, RUNTIME_CONTROL_ACTIONS, action, option, required2, projectRoot15, userName2, verify, inspect, updateControlState, runtimeControl,
|
|
42961
|
+
var import_config9, import_runtimeControls, import_runtimeStrategies5, argv, RUNTIME_CONTROL_ACTIONS, action, option, required2, projectRoot15, userName2, verify, inspect, updateControlState, runtimeControl, main48;
|
|
42675
42962
|
var init_runtimeControl = __esm({
|
|
42676
42963
|
"src/scripts/runtimeControl.ts"() {
|
|
42677
42964
|
"use strict";
|
|
@@ -42819,17 +43106,17 @@ var init_runtimeControl = __esm({
|
|
|
42819
43106
|
`Usage: tradejs runtime-control ${RUNTIME_CONTROL_ACTIONS.join("|")}`
|
|
42820
43107
|
);
|
|
42821
43108
|
};
|
|
42822
|
-
|
|
43109
|
+
main48 = runtimeControl;
|
|
42823
43110
|
}
|
|
42824
43111
|
});
|
|
42825
43112
|
|
|
42826
43113
|
// src/scripts/strategyRelease.ts
|
|
42827
43114
|
var strategyRelease_exports = {};
|
|
42828
43115
|
__export(strategyRelease_exports, {
|
|
42829
|
-
main: () =>
|
|
43116
|
+
main: () => main49,
|
|
42830
43117
|
runStrategyReleaseCommand: () => runStrategyReleaseCommand
|
|
42831
43118
|
});
|
|
42832
|
-
var import_promises46, import_node_fs10, import_node_readline5, import_node_path46, import_chalk50, valueAfter2, required3, writeJsonAtomic3, runStrategyReleaseCommand, printUsage2,
|
|
43119
|
+
var import_promises46, import_node_fs10, import_node_readline5, import_node_path46, import_chalk50, valueAfter2, required3, writeJsonAtomic3, runStrategyReleaseCommand, printUsage2, main49;
|
|
42833
43120
|
var init_strategyRelease2 = __esm({
|
|
42834
43121
|
"src/scripts/strategyRelease.ts"() {
|
|
42835
43122
|
"use strict";
|
|
@@ -42996,7 +43283,7 @@ var init_strategyRelease2 = __esm({
|
|
|
42996
43283
|
yarn strategy:release profile --input <trades.jsonl> --variant <id> --startTime <ms> --endTime <ms> [--days 7,30,90] [--out <profile.json>]
|
|
42997
43284
|
yarn strategy:release diagnose --input <diagnosis-input.json> [--out output/diagnosis.json]
|
|
42998
43285
|
yarn strategy:release retention --input <inventory.json> [--apply]`);
|
|
42999
|
-
|
|
43286
|
+
main49 = async () => {
|
|
43000
43287
|
const argv2 = process.argv.slice(2);
|
|
43001
43288
|
const command = argv2[0];
|
|
43002
43289
|
if (!command || ![
|
|
@@ -43035,10 +43322,10 @@ __export(serverHealth_exports, {
|
|
|
43035
43322
|
buildServerHealthDiagnostics: () => buildServerHealthDiagnostics,
|
|
43036
43323
|
collectServerHealthSnapshot: () => collectServerHealthSnapshot,
|
|
43037
43324
|
evaluateServerHealth: () => evaluateServerHealth,
|
|
43038
|
-
main: () =>
|
|
43325
|
+
main: () => main50,
|
|
43039
43326
|
resolveServerHealthThresholds: () => resolveServerHealthThresholds
|
|
43040
43327
|
});
|
|
43041
|
-
var import_config10, import_node_child_process12, import_node_os5, import_node_fs11, import_args35,
|
|
43328
|
+
var import_config10, import_node_child_process12, import_node_os5, import_node_fs11, import_args35, import_redis23, DEFAULT_STATE, DEFAULT_THRESHOLDS, escapeHtml6, formatPctValue, formatLoadPerCore, formatGiB, formatDuration2, readDiskUsage, parseMeminfoBytes, readMemorySnapshot, runDiagnosticCommand, runDiagnosticCommands, collectServerHealthSnapshot, buildHumanSummaryLines, evaluateServerHealth, shouldRecover, buildAlertMessage, buildRecoveryMessage, buildServerHealthDiagnostics, getStateKey, toFiniteNumber3, resolveServerHealthThresholds, main50;
|
|
43042
43329
|
var init_serverHealth = __esm({
|
|
43043
43330
|
"src/scripts/serverHealth.ts"() {
|
|
43044
43331
|
"use strict";
|
|
@@ -43047,7 +43334,7 @@ var init_serverHealth = __esm({
|
|
|
43047
43334
|
import_node_os5 = __toESM(require("os"));
|
|
43048
43335
|
import_node_fs11 = require("fs");
|
|
43049
43336
|
import_args35 = __toESM(require("args"));
|
|
43050
|
-
|
|
43337
|
+
import_redis23 = require("@tradejs/infra/redis");
|
|
43051
43338
|
init_telegramReports();
|
|
43052
43339
|
DEFAULT_STATE = {
|
|
43053
43340
|
status: "healthy",
|
|
@@ -43451,13 +43738,13 @@ var init_serverHealth = __esm({
|
|
|
43451
43738
|
"Recovery threshold for disk used percent",
|
|
43452
43739
|
String(DEFAULT_THRESHOLDS.diskRecoverPct)
|
|
43453
43740
|
);
|
|
43454
|
-
|
|
43741
|
+
main50 = async () => {
|
|
43455
43742
|
const flags36 = import_args35.default.parse(process.argv);
|
|
43456
43743
|
const thresholds = resolveServerHealthThresholds(flags36);
|
|
43457
43744
|
const diskPath = String(flags36.diskPath || "/");
|
|
43458
43745
|
const snapshot = collectServerHealthSnapshot(diskPath);
|
|
43459
43746
|
const stateKey = getStateKey(String(flags36.user), snapshot.hostname);
|
|
43460
|
-
const prevState = await (0,
|
|
43747
|
+
const prevState = await (0, import_redis23.getData)(stateKey, DEFAULT_STATE) ?? DEFAULT_STATE;
|
|
43461
43748
|
const evaluation = evaluateServerHealth(snapshot, thresholds);
|
|
43462
43749
|
const cooldownMs = Math.max(60, Number(flags36.cooldownSec)) * 1e3;
|
|
43463
43750
|
const now2 = snapshot.timestamp;
|
|
@@ -43470,7 +43757,7 @@ var init_serverHealth = __esm({
|
|
|
43470
43757
|
lastOkAt: prevState.lastOkAt,
|
|
43471
43758
|
activeIssueCodes: evaluation.issues.map((issue) => issue.code)
|
|
43472
43759
|
};
|
|
43473
|
-
await (0,
|
|
43760
|
+
await (0, import_redis23.setData)(stateKey, nextState2, { expire: 0 });
|
|
43474
43761
|
if (shouldSend) {
|
|
43475
43762
|
const message = buildAlertMessage({
|
|
43476
43763
|
evaluation,
|
|
@@ -43499,7 +43786,7 @@ var init_serverHealth = __esm({
|
|
|
43499
43786
|
lastOkAt: now2,
|
|
43500
43787
|
activeIssueCodes: []
|
|
43501
43788
|
};
|
|
43502
|
-
await (0,
|
|
43789
|
+
await (0, import_redis23.setData)(stateKey, nextState, { expire: 0 });
|
|
43503
43790
|
if (recovered) {
|
|
43504
43791
|
const message = buildRecoveryMessage({ snapshot, prevState });
|
|
43505
43792
|
if (flags36.printOnly) {
|
|
@@ -44843,24 +45130,24 @@ var init_reporting = __esm({
|
|
|
44843
45130
|
var runtimeParity_exports = {};
|
|
44844
45131
|
__export(runtimeParity_exports, {
|
|
44845
45132
|
buildRuntimeParityMessage: () => buildRuntimeParityMessage,
|
|
44846
|
-
main: () =>
|
|
45133
|
+
main: () => main51,
|
|
44847
45134
|
runtimeParity: () => runtimeParity
|
|
44848
45135
|
});
|
|
44849
|
-
var import_config11,
|
|
45136
|
+
var import_config11, import_node_crypto25, import_args36, import_chalk52, import_constants20, import_time13, import_logger8, import_redis24, import_cli12, import_backtest8, import_connectors17, flags32, interval3, projectRoot16, DEFAULT_LOOKBACK_DAYS, DETAIL_LIMIT2, DEFAULT_REPLAY_ENV, resolveParityConnectorName, createConnector, buildReplayAiAnalyses, formatReplayEnvSummary, buildReplayConfig, warmReplayHistory, runtimeParity, main51;
|
|
44850
45137
|
var init_runtimeParity2 = __esm({
|
|
44851
45138
|
"src/scripts/runtimeParity.ts"() {
|
|
44852
45139
|
"use strict";
|
|
44853
45140
|
import_config11 = require("dotenv/config");
|
|
44854
|
-
|
|
45141
|
+
import_node_crypto25 = require("crypto");
|
|
44855
45142
|
import_args36 = __toESM(require("args"));
|
|
44856
45143
|
import_chalk52 = __toESM(require("chalk"));
|
|
44857
|
-
|
|
45144
|
+
import_constants20 = require("@tradejs/core/constants");
|
|
44858
45145
|
import_time13 = require("@tradejs/core/time");
|
|
44859
|
-
|
|
44860
|
-
|
|
45146
|
+
import_logger8 = require("@tradejs/infra/logger");
|
|
45147
|
+
import_redis24 = require("@tradejs/infra/redis");
|
|
44861
45148
|
import_cli12 = require("@tradejs/node/cli");
|
|
44862
45149
|
import_backtest8 = require("@tradejs/node/backtest");
|
|
44863
|
-
|
|
45150
|
+
import_connectors17 = require("@tradejs/node/connectors");
|
|
44864
45151
|
init_runtimeParity();
|
|
44865
45152
|
init_cliArgs();
|
|
44866
45153
|
init_runtimeRedis();
|
|
@@ -44930,22 +45217,22 @@ var init_runtimeParity2 = __esm({
|
|
|
44930
45217
|
DETAIL_LIMIT2 = 10;
|
|
44931
45218
|
DEFAULT_REPLAY_ENV = flags32.runtimeGates ? "PARITY" : "BACKTEST";
|
|
44932
45219
|
resolveParityConnectorName = async (value) => {
|
|
44933
|
-
const connectorName = await (0,
|
|
45220
|
+
const connectorName = await (0, import_connectors17.resolveConnectorName)(value, projectRoot16);
|
|
44934
45221
|
if (connectorName) {
|
|
44935
45222
|
return connectorName;
|
|
44936
45223
|
}
|
|
44937
|
-
|
|
45224
|
+
import_logger8.logger.warn(
|
|
44938
45225
|
'Unknown connector "%s". Fallback to %s.',
|
|
44939
45226
|
String(value || "").trim() || String(value),
|
|
44940
|
-
|
|
45227
|
+
import_connectors17.DEFAULT_CONNECTOR_NAME
|
|
44941
45228
|
);
|
|
44942
|
-
return
|
|
45229
|
+
return import_connectors17.DEFAULT_CONNECTOR_NAME;
|
|
44943
45230
|
};
|
|
44944
45231
|
createConnector = async ({
|
|
44945
45232
|
userName: userName3,
|
|
44946
45233
|
connectorName
|
|
44947
45234
|
}) => {
|
|
44948
|
-
const connectorFactory = await (0,
|
|
45235
|
+
const connectorFactory = await (0, import_connectors17.getConnectorCreatorByName)(
|
|
44949
45236
|
connectorName,
|
|
44950
45237
|
projectRoot16
|
|
44951
45238
|
);
|
|
@@ -45017,8 +45304,8 @@ var init_runtimeParity2 = __esm({
|
|
|
45017
45304
|
toleranceMs
|
|
45018
45305
|
}) => {
|
|
45019
45306
|
const [userConfig, strategyResults] = await Promise.all([
|
|
45020
|
-
(0,
|
|
45021
|
-
(0,
|
|
45307
|
+
(0, import_redis24.getData)(import_redis24.redisKeys.strategyConfig(userName3, strategy), {}),
|
|
45308
|
+
(0, import_redis24.getData)(import_redis24.redisKeys.strategyResults(userName3, strategy), {})
|
|
45022
45309
|
]);
|
|
45023
45310
|
const typedResults = strategyResults ?? {};
|
|
45024
45311
|
const symbolResult = typedResults?.[symbol];
|
|
@@ -45068,7 +45355,7 @@ var init_runtimeParity2 = __esm({
|
|
|
45068
45355
|
userName: userName3,
|
|
45069
45356
|
projectRoot: projectRoot16,
|
|
45070
45357
|
shouldUseDedicatedReferences: true,
|
|
45071
|
-
warn: (message) =>
|
|
45358
|
+
warn: (message) => import_logger8.logger.warn(message)
|
|
45072
45359
|
});
|
|
45073
45360
|
await updateMarketHistoryWithBtcReferences({
|
|
45074
45361
|
marketConnector: connector,
|
|
@@ -45155,7 +45442,7 @@ var init_runtimeParity2 = __esm({
|
|
|
45155
45442
|
const sourceCounts = countReplayTargetSources(replayTargets);
|
|
45156
45443
|
const preloadStart = (0, import_time13.getBacktestPreloadStart)(
|
|
45157
45444
|
window.start,
|
|
45158
|
-
|
|
45445
|
+
import_constants20.BACKTEST_PRELOAD_DAYS
|
|
45159
45446
|
);
|
|
45160
45447
|
const replayStartedAt = Date.now();
|
|
45161
45448
|
const replaySymbolsCount = new Set(
|
|
@@ -45234,9 +45521,9 @@ var init_runtimeParity2 = __esm({
|
|
|
45234
45521
|
start: window.start,
|
|
45235
45522
|
end: window.end
|
|
45236
45523
|
},
|
|
45237
|
-
name: `${target.symbol}_${target.strategy}_${(0,
|
|
45238
|
-
testId: (0,
|
|
45239
|
-
testSuiteId: (0,
|
|
45524
|
+
name: `${target.symbol}_${target.strategy}_${(0, import_node_crypto25.randomUUID)().slice(0, 8)}`,
|
|
45525
|
+
testId: (0, import_node_crypto25.randomUUID)().slice(0, 8),
|
|
45526
|
+
testSuiteId: (0, import_node_crypto25.randomUUID)().slice(0, 8),
|
|
45240
45527
|
strategyName: target.strategy,
|
|
45241
45528
|
strategyConfig: replayConfig,
|
|
45242
45529
|
connectorName,
|
|
@@ -45385,7 +45672,7 @@ var init_runtimeParity2 = __esm({
|
|
|
45385
45672
|
(0, import_backtest8.resetTestingKlineCache)(projectRoot16);
|
|
45386
45673
|
}
|
|
45387
45674
|
};
|
|
45388
|
-
|
|
45675
|
+
main51 = runtimeParity;
|
|
45389
45676
|
}
|
|
45390
45677
|
});
|
|
45391
45678
|
|
|
@@ -45399,12 +45686,12 @@ var init_runtimeStrategies = __esm({
|
|
|
45399
45686
|
});
|
|
45400
45687
|
|
|
45401
45688
|
// src/lib/signals/skipStats.ts
|
|
45402
|
-
var import_chalk53,
|
|
45689
|
+
var import_chalk53, import_logger9, createStrategySkipStats, recordStrategyReason, logStrategySkipStats;
|
|
45403
45690
|
var init_skipStats = __esm({
|
|
45404
45691
|
"src/lib/signals/skipStats.ts"() {
|
|
45405
45692
|
"use strict";
|
|
45406
45693
|
import_chalk53 = __toESM(require("chalk"));
|
|
45407
|
-
|
|
45694
|
+
import_logger9 = require("@tradejs/infra/logger");
|
|
45408
45695
|
init_runtimeSignalsStorage();
|
|
45409
45696
|
createStrategySkipStats = (runtimeStrategies) => new Map(
|
|
45410
45697
|
runtimeStrategies.map(({ strategyName }) => [
|
|
@@ -45429,24 +45716,24 @@ var init_skipStats = __esm({
|
|
|
45429
45716
|
);
|
|
45430
45717
|
};
|
|
45431
45718
|
logStrategySkipStats = (runtimeStrategies, strategyStats) => {
|
|
45432
|
-
|
|
45719
|
+
import_logger9.logger.info(import_chalk53.default.yellow("skip stats:"));
|
|
45433
45720
|
for (const { strategyName } of runtimeStrategies) {
|
|
45434
45721
|
const stats = strategyStats.get(strategyName);
|
|
45435
45722
|
if (!stats) {
|
|
45436
45723
|
continue;
|
|
45437
45724
|
}
|
|
45438
|
-
|
|
45725
|
+
import_logger9.logger.info(
|
|
45439
45726
|
`${strategyName}: evaluated=${stats.evaluated}, signals=${stats.signals}`
|
|
45440
45727
|
);
|
|
45441
45728
|
const sortedReasons = [...stats.reasons.entries()].sort(
|
|
45442
45729
|
(left, right) => right[1] - left[1] || left[0].localeCompare(right[0])
|
|
45443
45730
|
);
|
|
45444
45731
|
if (!sortedReasons.length) {
|
|
45445
|
-
|
|
45732
|
+
import_logger9.logger.info(" none");
|
|
45446
45733
|
continue;
|
|
45447
45734
|
}
|
|
45448
45735
|
for (const [reason, count] of sortedReasons) {
|
|
45449
|
-
|
|
45736
|
+
import_logger9.logger.info(` ${reason}: ${count}`);
|
|
45450
45737
|
}
|
|
45451
45738
|
}
|
|
45452
45739
|
};
|
|
@@ -45454,11 +45741,11 @@ var init_skipStats = __esm({
|
|
|
45454
45741
|
});
|
|
45455
45742
|
|
|
45456
45743
|
// src/lib/signals/evaluations.ts
|
|
45457
|
-
var
|
|
45744
|
+
var import_redis25, runtimeLineageScopeCache, runtimeLineageScopeCacheDayKey, runtimeLineageScopeCacheLoaded, buildRuntimeSignalEvaluationId, buildLineageField, flushRuntimeSignalEvaluations, createRuntimeSignalEvaluationBuffer;
|
|
45458
45745
|
var init_evaluations = __esm({
|
|
45459
45746
|
"src/lib/signals/evaluations.ts"() {
|
|
45460
45747
|
"use strict";
|
|
45461
|
-
|
|
45748
|
+
import_redis25 = require("@tradejs/infra/redis");
|
|
45462
45749
|
init_runtimeSignalsStorage();
|
|
45463
45750
|
init_runtimeLineage();
|
|
45464
45751
|
runtimeLineageScopeCache = /* @__PURE__ */ new Map();
|
|
@@ -45509,7 +45796,7 @@ var init_evaluations = __esm({
|
|
|
45509
45796
|
runtimeLineageScopeCacheDayKey = dayKey;
|
|
45510
45797
|
runtimeLineageScopeCacheLoaded = false;
|
|
45511
45798
|
}
|
|
45512
|
-
const lineageBucket =
|
|
45799
|
+
const lineageBucket = import_redis25.redisKeys.runtimeLineageScopeBucket(
|
|
45513
45800
|
dayEvaluations[0].userName,
|
|
45514
45801
|
dayKey
|
|
45515
45802
|
);
|
|
@@ -45517,7 +45804,7 @@ var init_evaluations = __esm({
|
|
|
45517
45804
|
(evaluation) => evaluation.runtimeLineage != null
|
|
45518
45805
|
);
|
|
45519
45806
|
if (lineageEvaluations.length > 0 && !runtimeLineageScopeCacheLoaded) {
|
|
45520
|
-
const storedScopes = await (0,
|
|
45807
|
+
const storedScopes = await (0, import_redis25.getHashJsonValues)(lineageBucket);
|
|
45521
45808
|
for (const scope of storedScopes) {
|
|
45522
45809
|
const lineageField = buildLineageField(scope);
|
|
45523
45810
|
runtimeLineageScopeCache.set(`${lineageBucket}:${lineageField}`, scope);
|
|
@@ -45562,7 +45849,7 @@ var init_evaluations = __esm({
|
|
|
45562
45849
|
lineageWrites.set(lineageField, scope);
|
|
45563
45850
|
}
|
|
45564
45851
|
if (lineageWrites.size > 0) {
|
|
45565
|
-
await (0,
|
|
45852
|
+
await (0, import_redis25.setHashJsonFields)(
|
|
45566
45853
|
lineageBucket,
|
|
45567
45854
|
[...lineageWrites].map(([field, data]) => ({ field, data })),
|
|
45568
45855
|
{
|
|
@@ -45574,7 +45861,7 @@ var init_evaluations = __esm({
|
|
|
45574
45861
|
const statsIncrements = /* @__PURE__ */ new Map();
|
|
45575
45862
|
for (const evaluation of dayEvaluations) {
|
|
45576
45863
|
if (shouldStoreDetailedRuntimeSignalEvaluation(evaluation)) {
|
|
45577
|
-
const bucket =
|
|
45864
|
+
const bucket = import_redis25.redisKeys.runtimeSignalEvaluationBucket(
|
|
45578
45865
|
evaluation.userName,
|
|
45579
45866
|
dayKey,
|
|
45580
45867
|
evaluation.strategy
|
|
@@ -45586,7 +45873,7 @@ var init_evaluations = __esm({
|
|
|
45586
45873
|
});
|
|
45587
45874
|
detailedWrites.set(bucket, entries);
|
|
45588
45875
|
}
|
|
45589
|
-
const statsBucket =
|
|
45876
|
+
const statsBucket = import_redis25.redisKeys.runtimeSignalEvaluationStatsBucket(
|
|
45590
45877
|
evaluation.userName,
|
|
45591
45878
|
dayKey,
|
|
45592
45879
|
evaluation.strategy,
|
|
@@ -45602,12 +45889,12 @@ var init_evaluations = __esm({
|
|
|
45602
45889
|
}
|
|
45603
45890
|
await Promise.all([
|
|
45604
45891
|
...[...detailedWrites].map(
|
|
45605
|
-
([bucket, entries]) => (0,
|
|
45892
|
+
([bucket, entries]) => (0, import_redis25.setHashJsonFields)(bucket, entries, {
|
|
45606
45893
|
expire: runtimeSignalRetentionTtl
|
|
45607
45894
|
})
|
|
45608
45895
|
),
|
|
45609
45896
|
...[...statsIncrements].map(
|
|
45610
|
-
([bucket, increments]) => (0,
|
|
45897
|
+
([bucket, increments]) => (0, import_redis25.incrHashFields)(bucket, increments, {
|
|
45611
45898
|
expire: runtimeSignalRetentionTtl
|
|
45612
45899
|
})
|
|
45613
45900
|
)
|
|
@@ -45623,7 +45910,7 @@ var init_evaluations = __esm({
|
|
|
45623
45910
|
const runtimeSignalRetentionTtl = getRuntimeSignalRetentionTtlSeconds();
|
|
45624
45911
|
const signalRefsByBucket = /* @__PURE__ */ new Map();
|
|
45625
45912
|
for (const { userName: userName3, signal } of pendingSignals) {
|
|
45626
|
-
const bucket =
|
|
45913
|
+
const bucket = import_redis25.redisKeys.runtimeSignalBucket(
|
|
45627
45914
|
userName3,
|
|
45628
45915
|
(0, import_time5.getRuntimeStorageDayKey)(signal.timestamp),
|
|
45629
45916
|
signal.strategy
|
|
@@ -45637,14 +45924,14 @@ var init_evaluations = __esm({
|
|
|
45637
45924
|
}
|
|
45638
45925
|
await Promise.all([
|
|
45639
45926
|
...pendingSignals.map(
|
|
45640
|
-
({ signal }) => (0,
|
|
45641
|
-
|
|
45927
|
+
({ signal }) => (0, import_redis25.setData)(
|
|
45928
|
+
import_redis25.redisKeys.storeSignal(signal.symbol, signal.signalId),
|
|
45642
45929
|
toStoredRuntimeSignal(signal),
|
|
45643
45930
|
{ expire: runtimeSignalRetentionTtl }
|
|
45644
45931
|
)
|
|
45645
45932
|
),
|
|
45646
45933
|
...[...signalRefsByBucket].map(
|
|
45647
|
-
([bucket, entries]) => (0,
|
|
45934
|
+
([bucket, entries]) => (0, import_redis25.setHashJsonFields)(bucket, entries, {
|
|
45648
45935
|
expire: runtimeSignalRetentionTtl
|
|
45649
45936
|
})
|
|
45650
45937
|
)
|
|
@@ -45897,13 +46184,13 @@ var init_daemon = __esm({
|
|
|
45897
46184
|
});
|
|
45898
46185
|
|
|
45899
46186
|
// src/lib/signals/klineFeed.ts
|
|
45900
|
-
var
|
|
46187
|
+
var import_connectors18, import_logger10, import_candles6, FLUSH_DELAY_MS, normalizeSymbols2, createSignalsKlineFeed;
|
|
45901
46188
|
var init_klineFeed = __esm({
|
|
45902
46189
|
"src/lib/signals/klineFeed.ts"() {
|
|
45903
46190
|
"use strict";
|
|
45904
|
-
|
|
45905
|
-
|
|
45906
|
-
|
|
46191
|
+
import_connectors18 = require("@tradejs/connectors");
|
|
46192
|
+
import_logger10 = require("@tradejs/infra/logger");
|
|
46193
|
+
import_candles6 = require("@tradejs/infra/timescale/candles");
|
|
45907
46194
|
init_klineEvents();
|
|
45908
46195
|
FLUSH_DELAY_MS = 100;
|
|
45909
46196
|
normalizeSymbols2 = (symbols) => [...new Set(symbols.map((symbol) => symbol.trim().toUpperCase()))].filter(
|
|
@@ -45916,13 +46203,13 @@ var init_klineFeed = __esm({
|
|
|
45916
46203
|
publish = publishMarketKlineEvent,
|
|
45917
46204
|
persist = async (rows) => {
|
|
45918
46205
|
const intervalMinutes = Number(interval4);
|
|
45919
|
-
await (0,
|
|
46206
|
+
await (0, import_candles6.upsertCandles)(
|
|
45920
46207
|
rows.flatMap(
|
|
45921
|
-
({ symbol, candle }) => (0,
|
|
46208
|
+
({ symbol, candle }) => (0, import_candles6.toRows)("bybit", symbol, intervalMinutes, [candle])
|
|
45922
46209
|
)
|
|
45923
46210
|
);
|
|
45924
46211
|
},
|
|
45925
|
-
streamFactory =
|
|
46212
|
+
streamFactory = import_connectors18.createBybitKlineStream
|
|
45926
46213
|
}) => {
|
|
45927
46214
|
const pending = /* @__PURE__ */ new Map();
|
|
45928
46215
|
const lastClosedTimestamp = /* @__PURE__ */ new Map();
|
|
@@ -45956,7 +46243,7 @@ var init_klineFeed = __esm({
|
|
|
45956
46243
|
if (flushTimer || closed) return;
|
|
45957
46244
|
flushTimer = setTimeout(() => {
|
|
45958
46245
|
void flush().catch(
|
|
45959
|
-
(error) =>
|
|
46246
|
+
(error) => import_logger10.logger.error("websocket candle batch flush failed: %s", String(error))
|
|
45960
46247
|
);
|
|
45961
46248
|
}, FLUSH_DELAY_MS);
|
|
45962
46249
|
};
|
|
@@ -45973,7 +46260,7 @@ var init_klineFeed = __esm({
|
|
|
45973
46260
|
confirm: event.confirm,
|
|
45974
46261
|
receivedAt: event.receivedAt
|
|
45975
46262
|
}).catch(
|
|
45976
|
-
(error) =>
|
|
46263
|
+
(error) => import_logger10.logger.warn("websocket candle publish failed: %s", String(error))
|
|
45977
46264
|
);
|
|
45978
46265
|
if (!event.confirm) return;
|
|
45979
46266
|
pending.set(`${event.symbol}:${event.candle.timestamp}`, {
|
|
@@ -46028,12 +46315,12 @@ var init_klineFeed = __esm({
|
|
|
46028
46315
|
});
|
|
46029
46316
|
|
|
46030
46317
|
// src/lib/signals/tickerEvaluator.ts
|
|
46031
|
-
var
|
|
46318
|
+
var import_strategies14, import_logger11, createSignalsTickerEvaluator;
|
|
46032
46319
|
var init_tickerEvaluator = __esm({
|
|
46033
46320
|
"src/lib/signals/tickerEvaluator.ts"() {
|
|
46034
46321
|
"use strict";
|
|
46035
|
-
|
|
46036
|
-
|
|
46322
|
+
import_strategies14 = require("@tradejs/node/strategies");
|
|
46323
|
+
import_logger11 = require("@tradejs/infra/logger");
|
|
46037
46324
|
init_windows();
|
|
46038
46325
|
init_runtimeLineage();
|
|
46039
46326
|
init_runtimeModeConfig();
|
|
@@ -46193,7 +46480,7 @@ var init_tickerEvaluator = __esm({
|
|
|
46193
46480
|
continue;
|
|
46194
46481
|
}
|
|
46195
46482
|
if (evaluation.action.startsWith("rebuilt_")) {
|
|
46196
|
-
|
|
46483
|
+
import_logger11.logger.info(
|
|
46197
46484
|
"Rebuilt signals strategy state (%s): %s %s",
|
|
46198
46485
|
evaluation.action.slice("rebuilt_".length),
|
|
46199
46486
|
strategyName,
|
|
@@ -46249,7 +46536,7 @@ var init_tickerEvaluator = __esm({
|
|
|
46249
46536
|
if (signalRuntimeIdentity && !signal.signalId.endsWith(`:${signalRuntimeIdentity}`)) {
|
|
46250
46537
|
signal.signalId = `${signal.signalId}:${signalRuntimeIdentity}`;
|
|
46251
46538
|
}
|
|
46252
|
-
await (0,
|
|
46539
|
+
await (0, import_strategies14.enrichSignalWithBinanceMarketContext)({ signal, env: "CRON" });
|
|
46253
46540
|
if (signal.orderStatus === "skipped" && typeof signal.orderSkipReason === "string" && signal.orderSkipReason.trim()) {
|
|
46254
46541
|
recordStrategyReason(
|
|
46255
46542
|
strategyStats,
|
|
@@ -46296,7 +46583,7 @@ var init_tickerEvaluator = __esm({
|
|
|
46296
46583
|
...signal.riskDecision ? { riskDecision: signal.riskDecision } : {},
|
|
46297
46584
|
...signal.ml ? { ml: signal.ml } : {}
|
|
46298
46585
|
});
|
|
46299
|
-
|
|
46586
|
+
import_logger11.logger.info("Signal found %s by strategy %s", symbol, strategyName);
|
|
46300
46587
|
}
|
|
46301
46588
|
return strategySignals;
|
|
46302
46589
|
};
|
|
@@ -46445,19 +46732,19 @@ var init_configuredScopes = __esm({
|
|
|
46445
46732
|
});
|
|
46446
46733
|
|
|
46447
46734
|
// src/lib/signals/runner.ts
|
|
46448
|
-
var import_progress12, import_chalk54,
|
|
46735
|
+
var import_progress12, import_chalk54, import_connectors19, import_cli13, import_async5, import_strategies15, import_constants21, import_time14, import_logger12, import_runtimeDeploymentEvents, import_runtimeHeartbeats, import_runtimeStrategies7, SLOW_SIGNALS_WARNING_MS, formatDuration3, resolvePositiveInteger2, resolveNonNegativeInteger, createSignalsRunner;
|
|
46449
46736
|
var init_runner = __esm({
|
|
46450
46737
|
"src/lib/signals/runner.ts"() {
|
|
46451
46738
|
"use strict";
|
|
46452
46739
|
import_progress12 = __toESM(require("progress"));
|
|
46453
46740
|
import_chalk54 = __toESM(require("chalk"));
|
|
46454
|
-
|
|
46741
|
+
import_connectors19 = require("@tradejs/node/connectors");
|
|
46455
46742
|
import_cli13 = require("@tradejs/node/cli");
|
|
46456
46743
|
import_async5 = require("@tradejs/core/async");
|
|
46457
|
-
|
|
46458
|
-
|
|
46744
|
+
import_strategies15 = require("@tradejs/core/strategies");
|
|
46745
|
+
import_constants21 = require("@tradejs/core/constants");
|
|
46459
46746
|
import_time14 = require("@tradejs/core/time");
|
|
46460
|
-
|
|
46747
|
+
import_logger12 = require("@tradejs/infra/logger");
|
|
46461
46748
|
import_runtimeDeploymentEvents = require("@tradejs/infra/runtimeDeploymentEvents");
|
|
46462
46749
|
import_runtimeHeartbeats = require("@tradejs/infra/runtimeHeartbeats");
|
|
46463
46750
|
import_runtimeStrategies7 = require("@tradejs/node/runtimeStrategies");
|
|
@@ -46504,7 +46791,7 @@ var init_runner = __esm({
|
|
|
46504
46791
|
deploymentId: config2.deploymentId,
|
|
46505
46792
|
expectedCompositionId: compositionId
|
|
46506
46793
|
}),
|
|
46507
|
-
onError: (compositionId, error) =>
|
|
46794
|
+
onError: (compositionId, error) => import_logger12.logger.warn(
|
|
46508
46795
|
"runtime evidence snapshot unavailable; trading continues and the next cycle will retry (composition=%s): %s",
|
|
46509
46796
|
compositionId,
|
|
46510
46797
|
error instanceof Error ? error.message : String(error)
|
|
@@ -46513,7 +46800,7 @@ var init_runner = __esm({
|
|
|
46513
46800
|
const resolveSignalsDaemonMaxLiveBars = (runtimeInterval = interval4) => {
|
|
46514
46801
|
const intervalMinutes = Number(runtimeInterval);
|
|
46515
46802
|
const preloadBars = Math.ceil(
|
|
46516
|
-
|
|
46803
|
+
import_constants21.SIGNALS_CLI_PRELOAD_DAYS * 24 * 60 / intervalMinutes
|
|
46517
46804
|
);
|
|
46518
46805
|
return resolvePositiveInteger2(
|
|
46519
46806
|
process.env.SIGNALS_DAEMON_MAX_LIVE_BARS,
|
|
@@ -46527,12 +46814,12 @@ var init_runner = __esm({
|
|
|
46527
46814
|
const createDefaultSignalsLifecycle = (runtimeInterval = interval4) => createSignalsStrategyLifecycle({
|
|
46528
46815
|
intervalMs: Number(runtimeInterval) * 6e4,
|
|
46529
46816
|
maxLiveBars: resolveSignalsDaemonMaxLiveBars(runtimeInterval),
|
|
46530
|
-
releaseState:
|
|
46817
|
+
releaseState: import_strategies15.releaseStrategyReplayCache
|
|
46531
46818
|
});
|
|
46532
46819
|
const timeOperation3 = (label, operation) => timeOperation(
|
|
46533
46820
|
label,
|
|
46534
46821
|
operation,
|
|
46535
|
-
(message) =>
|
|
46822
|
+
(message) => import_logger12.logger.info(import_chalk54.default.gray(message))
|
|
46536
46823
|
);
|
|
46537
46824
|
const formatSlowSignalsWarning = (params) => [
|
|
46538
46825
|
"<b>Slow yarn signals run</b>",
|
|
@@ -46542,7 +46829,7 @@ var init_runner = __esm({
|
|
|
46542
46829
|
`Found signals: <b>${params.found}</b>`
|
|
46543
46830
|
].join("\n");
|
|
46544
46831
|
const resolveSignalsConnectorName = async (value) => {
|
|
46545
|
-
const connectorName = await (0,
|
|
46832
|
+
const connectorName = await (0, import_connectors19.resolveConnectorName)(value, projectRoot18);
|
|
46546
46833
|
if (!connectorName) {
|
|
46547
46834
|
throw new Error(
|
|
46548
46835
|
`Unknown runtime connector: ${String(value || "").trim() || String(value)}`
|
|
@@ -46570,7 +46857,7 @@ var init_runner = __esm({
|
|
|
46570
46857
|
);
|
|
46571
46858
|
const universe = scope.universe ?? config2.universe;
|
|
46572
46859
|
const requestedAccountId = deployment?.accountId ?? scope.accountId ?? config2.accountId;
|
|
46573
|
-
const connectorFactory = await (0,
|
|
46860
|
+
const connectorFactory = await (0, import_connectors19.getConnectorCreatorByName)(
|
|
46574
46861
|
connectorName,
|
|
46575
46862
|
projectRoot18
|
|
46576
46863
|
);
|
|
@@ -46588,8 +46875,8 @@ var init_runner = __esm({
|
|
|
46588
46875
|
marketConnector,
|
|
46589
46876
|
userName: config2.userName,
|
|
46590
46877
|
projectRoot: projectRoot18,
|
|
46591
|
-
shouldUseDedicatedReferences: universe === "crypto" && connectorName.toLowerCase() ===
|
|
46592
|
-
warn: (message) =>
|
|
46878
|
+
shouldUseDedicatedReferences: universe === "crypto" && connectorName.toLowerCase() === import_connectors19.DEFAULT_CONNECTOR_NAME.toLowerCase(),
|
|
46879
|
+
warn: (message) => import_logger12.logger.warn(message)
|
|
46593
46880
|
});
|
|
46594
46881
|
return {
|
|
46595
46882
|
connectorName,
|
|
@@ -46649,7 +46936,7 @@ var init_runner = __esm({
|
|
|
46649
46936
|
}) : [];
|
|
46650
46937
|
const selectedTickers = selection?.tickers ? [.../* @__PURE__ */ new Set([...selection.tickers, ...selectedActiveSymbols])] : void 0;
|
|
46651
46938
|
if (selectedActiveSymbols.length) {
|
|
46652
|
-
|
|
46939
|
+
import_logger12.logger.info(
|
|
46653
46940
|
import_chalk54.default.gray(
|
|
46654
46941
|
`runtime scope retained active symbols: ${selectedActiveSymbols.join(", ")}`
|
|
46655
46942
|
)
|
|
@@ -46687,7 +46974,7 @@ var init_runner = __esm({
|
|
|
46687
46974
|
const projectConfig = await (0, import_cli13.loadTradejsConfig)(projectRoot18);
|
|
46688
46975
|
projectHooks = projectConfig.hooks;
|
|
46689
46976
|
const currentTimestamp = (0, import_time14.getTimestamp)();
|
|
46690
|
-
const preloadStart = (0, import_time14.getTimestamp)(
|
|
46977
|
+
const preloadStart = (0, import_time14.getTimestamp)(import_constants21.SIGNALS_CLI_PRELOAD_DAYS);
|
|
46691
46978
|
if (!config2.cacheOnly && session.klineFeed) {
|
|
46692
46979
|
const expectedSymbols = universe === "crypto" ? [.../* @__PURE__ */ new Set([...tickers, "BTCUSDT", "ETHUSDT"])] : tickers;
|
|
46693
46980
|
session.klineFeed.setSubscriptions(expectedSymbols);
|
|
@@ -46701,7 +46988,7 @@ var init_runner = __esm({
|
|
|
46701
46988
|
})
|
|
46702
46989
|
);
|
|
46703
46990
|
await session.klineFeed.flush();
|
|
46704
|
-
|
|
46991
|
+
import_logger12.logger.info(
|
|
46705
46992
|
import_chalk54.default.gray(
|
|
46706
46993
|
`websocket candles: ready=${expectedSymbols.length - missingSymbols.length}/${expectedSymbols.length} missing=${missingSymbols.length}`
|
|
46707
46994
|
)
|
|
@@ -46711,17 +46998,17 @@ var init_runner = __esm({
|
|
|
46711
46998
|
connectorName,
|
|
46712
46999
|
interval: interval5,
|
|
46713
47000
|
symbols: missingSymbols,
|
|
46714
|
-
preloadDays:
|
|
47001
|
+
preloadDays: import_constants21.SIGNALS_CLI_PRELOAD_DAYS,
|
|
46715
47002
|
universe,
|
|
46716
|
-
log: (message) =>
|
|
47003
|
+
log: (message) => import_logger12.logger.info(import_chalk54.default.gray(message))
|
|
46717
47004
|
});
|
|
46718
47005
|
await updateBtcReferenceHistory({
|
|
46719
47006
|
marketConnector,
|
|
46720
47007
|
btcReferences,
|
|
46721
47008
|
interval: interval5,
|
|
46722
|
-
preloadDays:
|
|
47009
|
+
preloadDays: import_constants21.SIGNALS_CLI_PRELOAD_DAYS,
|
|
46723
47010
|
universe,
|
|
46724
|
-
log: (message) =>
|
|
47011
|
+
log: (message) => import_logger12.logger.info(import_chalk54.default.gray(message))
|
|
46725
47012
|
});
|
|
46726
47013
|
} else if (!config2.cacheOnly) {
|
|
46727
47014
|
await updateMarketHistoryWithBtcReferences({
|
|
@@ -46730,9 +47017,9 @@ var init_runner = __esm({
|
|
|
46730
47017
|
btcReferences,
|
|
46731
47018
|
interval: interval5,
|
|
46732
47019
|
symbols: tickers,
|
|
46733
|
-
preloadDays:
|
|
47020
|
+
preloadDays: import_constants21.SIGNALS_CLI_PRELOAD_DAYS,
|
|
46734
47021
|
universe,
|
|
46735
|
-
log: (message) =>
|
|
47022
|
+
log: (message) => import_logger12.logger.info(import_chalk54.default.gray(message))
|
|
46736
47023
|
});
|
|
46737
47024
|
}
|
|
46738
47025
|
await prepareMarketContextForRun({
|
|
@@ -46746,7 +47033,7 @@ var init_runner = __esm({
|
|
|
46746
47033
|
endMs: currentTimestamp,
|
|
46747
47034
|
preloadStartMs: preloadStart,
|
|
46748
47035
|
cacheOnly: config2.cacheOnly,
|
|
46749
|
-
log: (message) =>
|
|
47036
|
+
log: (message) => import_logger12.logger.info(import_chalk54.default.gray(message))
|
|
46750
47037
|
});
|
|
46751
47038
|
if (config2.updateOnly) {
|
|
46752
47039
|
return;
|
|
@@ -46816,7 +47103,7 @@ var init_runner = __esm({
|
|
|
46816
47103
|
) : configuredRuntimeStrategies;
|
|
46817
47104
|
if (!runtimeStrategies.length) {
|
|
46818
47105
|
lifecycle.clear();
|
|
46819
|
-
|
|
47106
|
+
import_logger12.logger.warn(
|
|
46820
47107
|
"No strategy releases are bound to deployment %s",
|
|
46821
47108
|
deployment?.id
|
|
46822
47109
|
);
|
|
@@ -46849,7 +47136,7 @@ var init_runner = __esm({
|
|
|
46849
47136
|
)
|
|
46850
47137
|
)
|
|
46851
47138
|
);
|
|
46852
|
-
|
|
47139
|
+
import_logger12.logger.info(
|
|
46853
47140
|
import_chalk54.default.yellow(
|
|
46854
47141
|
`loaded strategies (user=${config2.userName}): ${runtimeStrategies.map(formatConfiguredStrategyIdentity).join(", ")}`
|
|
46855
47142
|
)
|
|
@@ -46872,7 +47159,7 @@ var init_runner = __esm({
|
|
|
46872
47159
|
afterSignalsHookContext
|
|
46873
47160
|
);
|
|
46874
47161
|
if (beforeSignalsResult?.abort === true) {
|
|
46875
|
-
|
|
47162
|
+
import_logger12.logger.info(
|
|
46876
47163
|
"signals aborted before ticker evaluation: %s",
|
|
46877
47164
|
beforeSignalsResult.reason ?? "PROJECT_BEFORE_SIGNALS_ABORTED"
|
|
46878
47165
|
);
|
|
@@ -46886,9 +47173,9 @@ var init_runner = __esm({
|
|
|
46886
47173
|
width: 30
|
|
46887
47174
|
}
|
|
46888
47175
|
);
|
|
46889
|
-
|
|
47176
|
+
import_logger12.logger.info(import_chalk54.default.yellow(`tickers: ${tickers.length}`));
|
|
46890
47177
|
const signalsParallel = resolvePositiveInteger2(config2.parallel, 4);
|
|
46891
|
-
|
|
47178
|
+
import_logger12.logger.info(import_chalk54.default.yellow(`signal workers: ${signalsParallel}`));
|
|
46892
47179
|
const evaluateTicker = createSignalsTickerEvaluator({
|
|
46893
47180
|
userName: config2.userName,
|
|
46894
47181
|
makeOrders: config2.makeOrders,
|
|
@@ -46946,7 +47233,7 @@ var init_runner = __esm({
|
|
|
46946
47233
|
new Map(
|
|
46947
47234
|
runtimeStrategies.map(({ strategyName, strategyConfig }) => [
|
|
46948
47235
|
strategyName,
|
|
46949
|
-
(0,
|
|
47236
|
+
(0, import_strategies15.mapAiRuntimeFromConfig)({
|
|
46950
47237
|
AI_ENABLED: strategyConfig.AI_ENABLED,
|
|
46951
47238
|
AI_MODE: strategyConfig.AI_MODE,
|
|
46952
47239
|
MIN_AI_QUALITY: strategyConfig.MIN_AI_QUALITY
|
|
@@ -46959,7 +47246,7 @@ var init_runner = __esm({
|
|
|
46959
47246
|
config2.userName
|
|
46960
47247
|
);
|
|
46961
47248
|
}
|
|
46962
|
-
|
|
47249
|
+
import_logger12.logger.info(
|
|
46963
47250
|
JSON.stringify(
|
|
46964
47251
|
signals3.map((s) => s.symbol),
|
|
46965
47252
|
null,
|
|
@@ -46972,7 +47259,7 @@ var init_runner = __esm({
|
|
|
46972
47259
|
} catch (error) {
|
|
46973
47260
|
status = "failed";
|
|
46974
47261
|
failureMessage = error?.message || String(error);
|
|
46975
|
-
|
|
47262
|
+
import_logger12.logger.error(
|
|
46976
47263
|
"signals failed: %s",
|
|
46977
47264
|
error?.message || String(error)
|
|
46978
47265
|
);
|
|
@@ -46982,7 +47269,7 @@ var init_runner = __esm({
|
|
|
46982
47269
|
await runtimeSignalEvaluations.flush();
|
|
46983
47270
|
} catch (error) {
|
|
46984
47271
|
telemetryPersistence = "failed";
|
|
46985
|
-
|
|
47272
|
+
import_logger12.logger.error(
|
|
46986
47273
|
"runtime signal evaluation flush failed: %s",
|
|
46987
47274
|
error?.message || String(error)
|
|
46988
47275
|
);
|
|
@@ -47013,7 +47300,7 @@ var init_runner = __esm({
|
|
|
47013
47300
|
durationMs
|
|
47014
47301
|
});
|
|
47015
47302
|
} catch (error) {
|
|
47016
|
-
|
|
47303
|
+
import_logger12.logger.error(
|
|
47017
47304
|
"afterSignals hook failed: %s",
|
|
47018
47305
|
error?.message || String(error)
|
|
47019
47306
|
);
|
|
@@ -47030,20 +47317,20 @@ var init_runner = __esm({
|
|
|
47030
47317
|
{ userName: config2.userName }
|
|
47031
47318
|
);
|
|
47032
47319
|
} catch (error) {
|
|
47033
|
-
|
|
47320
|
+
import_logger12.logger.error(
|
|
47034
47321
|
"slow signals warning failed: %s",
|
|
47035
47322
|
error?.message || String(error)
|
|
47036
47323
|
);
|
|
47037
47324
|
}
|
|
47038
47325
|
}
|
|
47039
|
-
|
|
47326
|
+
import_logger12.logger.info(
|
|
47040
47327
|
import_chalk54.default.yellow(
|
|
47041
47328
|
`signals ${status} in ${formatDuration3(durationMs)} (found=${signals3.length})`
|
|
47042
47329
|
)
|
|
47043
47330
|
);
|
|
47044
|
-
|
|
47045
|
-
|
|
47046
|
-
|
|
47331
|
+
import_logger12.logger.info("");
|
|
47332
|
+
import_logger12.logger.info("");
|
|
47333
|
+
import_logger12.logger.info("");
|
|
47047
47334
|
}
|
|
47048
47335
|
};
|
|
47049
47336
|
const loadConfiguredSignalsScopes = async (deployment) => {
|
|
@@ -47118,14 +47405,14 @@ var init_runner = __esm({
|
|
|
47118
47405
|
const sessions = /* @__PURE__ */ new Map();
|
|
47119
47406
|
const lastBoundaryByScope = /* @__PURE__ */ new Map();
|
|
47120
47407
|
const stop = (signalName) => {
|
|
47121
|
-
|
|
47408
|
+
import_logger12.logger.info("signals daemon stopping by %s", signalName);
|
|
47122
47409
|
abortController.abort();
|
|
47123
47410
|
};
|
|
47124
47411
|
const stopOnSigint = () => stop("SIGINT");
|
|
47125
47412
|
const stopOnSigterm = () => stop("SIGTERM");
|
|
47126
47413
|
process.once("SIGINT", stopOnSigint);
|
|
47127
47414
|
process.once("SIGTERM", stopOnSigterm);
|
|
47128
|
-
|
|
47415
|
+
import_logger12.logger.info("signals daemon started (deployment-driven scopes)");
|
|
47129
47416
|
try {
|
|
47130
47417
|
await runSignalsDaemon({
|
|
47131
47418
|
intervalMs: 6e4,
|
|
@@ -47151,7 +47438,7 @@ var init_runner = __esm({
|
|
|
47151
47438
|
strategies
|
|
47152
47439
|
});
|
|
47153
47440
|
} catch (error) {
|
|
47154
|
-
|
|
47441
|
+
import_logger12.logger.warn(
|
|
47155
47442
|
"runtime deployment composition event unavailable; trading continues and the next cycle will retry (composition=%s): %s",
|
|
47156
47443
|
currentDeployment.deploymentCompositionId,
|
|
47157
47444
|
error instanceof Error ? error.message : String(error)
|
|
@@ -47187,7 +47474,7 @@ var init_runner = __esm({
|
|
|
47187
47474
|
interval: session.interval,
|
|
47188
47475
|
universe: session.universe
|
|
47189
47476
|
});
|
|
47190
|
-
|
|
47477
|
+
import_logger12.logger.info(
|
|
47191
47478
|
"Bybit websocket candle feed enabled (account=%s, universe=%s, interval=%s)",
|
|
47192
47479
|
session.accountId ?? "default",
|
|
47193
47480
|
session.universe,
|
|
@@ -47209,7 +47496,7 @@ var init_runner = __esm({
|
|
|
47209
47496
|
(sum3, session) => sum3 + session.lifecycle.size(),
|
|
47210
47497
|
0
|
|
47211
47498
|
);
|
|
47212
|
-
|
|
47499
|
+
import_logger12.logger.info(
|
|
47213
47500
|
"signals daemon resources: rss=%sMB heapUsed=%sMB heapTotal=%sMB stateKeys=%s scopes=%s",
|
|
47214
47501
|
(memory.rss / 1024 / 1024).toFixed(1),
|
|
47215
47502
|
(memory.heapUsed / 1024 / 1024).toFixed(1),
|
|
@@ -47219,7 +47506,7 @@ var init_runner = __esm({
|
|
|
47219
47506
|
);
|
|
47220
47507
|
},
|
|
47221
47508
|
onCycleError: (error) => {
|
|
47222
|
-
|
|
47509
|
+
import_logger12.logger.error(
|
|
47223
47510
|
"signals daemon cycle failed: %s",
|
|
47224
47511
|
error?.message || String(error)
|
|
47225
47512
|
);
|
|
@@ -47258,12 +47545,12 @@ var init_runner = __esm({
|
|
|
47258
47545
|
var signals_exports = {};
|
|
47259
47546
|
__export(signals_exports, {
|
|
47260
47547
|
createSignalsSession: () => createSignalsSession,
|
|
47261
|
-
main: () =>
|
|
47548
|
+
main: () => main52,
|
|
47262
47549
|
signals: () => signals,
|
|
47263
47550
|
signalsConfiguredScopesOnce: () => signalsConfiguredScopesOnce,
|
|
47264
47551
|
signalsDaemon: () => signalsDaemon
|
|
47265
47552
|
});
|
|
47266
|
-
var import_config12, import_args37, flags33, config, runner, createSignalsSession, signals, signalsConfiguredScopesOnce, signalsDaemon,
|
|
47553
|
+
var import_config12, import_args37, flags33, config, runner, createSignalsSession, signals, signalsConfiguredScopesOnce, signalsDaemon, main52;
|
|
47267
47554
|
var init_signals = __esm({
|
|
47268
47555
|
"src/scripts/signals.ts"() {
|
|
47269
47556
|
"use strict";
|
|
@@ -47335,39 +47622,39 @@ var init_signals = __esm({
|
|
|
47335
47622
|
signals = runner.runCycle;
|
|
47336
47623
|
signalsConfiguredScopesOnce = runner.runConfiguredScopesOnce;
|
|
47337
47624
|
signalsDaemon = runner.runDaemon;
|
|
47338
|
-
|
|
47625
|
+
main52 = () => config.watch ? signalsDaemon() : signalsConfiguredScopesOnce();
|
|
47339
47626
|
}
|
|
47340
47627
|
});
|
|
47341
47628
|
|
|
47342
47629
|
// src/scripts/signalsDaemon.ts
|
|
47343
47630
|
var signalsDaemon_exports = {};
|
|
47344
47631
|
__export(signalsDaemon_exports, {
|
|
47345
|
-
main: () =>
|
|
47632
|
+
main: () => main53
|
|
47346
47633
|
});
|
|
47347
|
-
var
|
|
47634
|
+
var main53;
|
|
47348
47635
|
var init_signalsDaemon = __esm({
|
|
47349
47636
|
"src/scripts/signalsDaemon.ts"() {
|
|
47350
47637
|
"use strict";
|
|
47351
47638
|
init_signals();
|
|
47352
|
-
|
|
47639
|
+
main53 = signalsDaemon;
|
|
47353
47640
|
}
|
|
47354
47641
|
});
|
|
47355
47642
|
|
|
47356
47643
|
// src/scripts/signalsSummary.ts
|
|
47357
47644
|
var signalsSummary_exports = {};
|
|
47358
47645
|
__export(signalsSummary_exports, {
|
|
47359
|
-
main: () =>
|
|
47646
|
+
main: () => main54,
|
|
47360
47647
|
signalsSummary: () => signalsSummary
|
|
47361
47648
|
});
|
|
47362
|
-
var import_config13, import_userSettings8, import_args38,
|
|
47649
|
+
var import_config13, import_userSettings8, import_args38, import_logger13, import_connectors20, import_runtimeStrategies9, flags34, projectRoot17, SUMMARY_TIMEZONE2, SUMMARY_TIMEZONE_LABEL2, escapeHtml8, formatMskDateTime4, formatSigned3, formatPnlMoneyText, formatWinRateText, resolveSummaryTitle, normalizeStatus, shouldAttachDebugReport, getSummaryDateParts, formatSummaryIsoDayKey, unescapeHtml, stripTelegramHtml, buildSignalsSummaryAttachment, appendReportAttachmentSummary, resolveSummaryConnectorName, groupRuntimeTradesByConnectorScope, syncRuntimeTradeScopes, createRuntimeSignalStats, mergeRuntimeSignalStats, buildSummaryPrelude, resolveTradeStatusEmoji, isTimestampInWindow, isRuntimeTradeClosedInWindow, buildSummaryMessages, signalsSummary, main54;
|
|
47363
47650
|
var init_signalsSummary = __esm({
|
|
47364
47651
|
"src/scripts/signalsSummary.ts"() {
|
|
47365
47652
|
"use strict";
|
|
47366
47653
|
import_config13 = require("dotenv/config");
|
|
47367
47654
|
import_userSettings8 = require("@tradejs/infra/userSettings");
|
|
47368
47655
|
import_args38 = __toESM(require("args"));
|
|
47369
|
-
|
|
47370
|
-
|
|
47656
|
+
import_logger13 = require("@tradejs/infra/logger");
|
|
47657
|
+
import_connectors20 = require("@tradejs/node/connectors");
|
|
47371
47658
|
init_runtimeRedis();
|
|
47372
47659
|
init_runtimeTradeSync();
|
|
47373
47660
|
init_telegramReports();
|
|
@@ -47478,16 +47765,16 @@ var init_signalsSummary = __esm({
|
|
|
47478
47765
|
return lines.join("\n");
|
|
47479
47766
|
};
|
|
47480
47767
|
resolveSummaryConnectorName = async (value) => {
|
|
47481
|
-
const connectorName = await (0,
|
|
47768
|
+
const connectorName = await (0, import_connectors20.resolveConnectorName)(value, projectRoot17);
|
|
47482
47769
|
if (connectorName) {
|
|
47483
47770
|
return connectorName;
|
|
47484
47771
|
}
|
|
47485
|
-
|
|
47772
|
+
import_logger13.logger.warn(
|
|
47486
47773
|
'Unknown connector "%s". Fallback to %s.',
|
|
47487
47774
|
String(value || "").trim() || String(value),
|
|
47488
|
-
|
|
47775
|
+
import_connectors20.DEFAULT_CONNECTOR_NAME
|
|
47489
47776
|
);
|
|
47490
|
-
return
|
|
47777
|
+
return import_connectors20.DEFAULT_CONNECTOR_NAME;
|
|
47491
47778
|
};
|
|
47492
47779
|
groupRuntimeTradesByConnectorScope = ({
|
|
47493
47780
|
trades,
|
|
@@ -47541,7 +47828,7 @@ var init_signalsSummary = __esm({
|
|
|
47541
47828
|
const connectorName = await resolveSummaryConnectorName(
|
|
47542
47829
|
scope.connectorName
|
|
47543
47830
|
);
|
|
47544
|
-
const connectorFactory = await (0,
|
|
47831
|
+
const connectorFactory = await (0, import_connectors20.getConnectorCreatorByName)(
|
|
47545
47832
|
connectorName,
|
|
47546
47833
|
projectRoot17
|
|
47547
47834
|
);
|
|
@@ -47564,7 +47851,7 @@ var init_signalsSummary = __esm({
|
|
|
47564
47851
|
endTime,
|
|
47565
47852
|
openPositionCallbacks: {
|
|
47566
47853
|
onError: (error) => {
|
|
47567
|
-
|
|
47854
|
+
import_logger13.logger.warn(
|
|
47568
47855
|
"signals summary: getOpenPositionPnl failed for scope account=%s deployment=%s: %s",
|
|
47569
47856
|
scope.accountId ?? "default",
|
|
47570
47857
|
scope.deploymentId ?? "default",
|
|
@@ -47574,7 +47861,7 @@ var init_signalsSummary = __esm({
|
|
|
47574
47861
|
},
|
|
47575
47862
|
closedPnlCallbacks: {
|
|
47576
47863
|
onError: (error) => {
|
|
47577
|
-
|
|
47864
|
+
import_logger13.logger.warn(
|
|
47578
47865
|
"signals summary: getClosedPnl failed for scope account=%s deployment=%s: %s",
|
|
47579
47866
|
scope.accountId ?? "default",
|
|
47580
47867
|
scope.deploymentId ?? "default",
|
|
@@ -47988,7 +48275,7 @@ none`
|
|
|
47988
48275
|
(sum3, stats) => sum3 + stats.evaluated,
|
|
47989
48276
|
0
|
|
47990
48277
|
);
|
|
47991
|
-
|
|
48278
|
+
import_logger13.logger.info(
|
|
47992
48279
|
"signals summary deployment=%s window=%sh signals=%s evaluations=%s trades=%s connectors=%s scopes=%s user=%s",
|
|
47993
48280
|
scope.deploymentId ?? "legacy",
|
|
47994
48281
|
hours,
|
|
@@ -48046,26 +48333,26 @@ none`
|
|
|
48046
48333
|
});
|
|
48047
48334
|
}
|
|
48048
48335
|
};
|
|
48049
|
-
|
|
48336
|
+
main54 = signalsSummary;
|
|
48050
48337
|
}
|
|
48051
48338
|
});
|
|
48052
48339
|
|
|
48053
48340
|
// src/scripts/test-ml.ts
|
|
48054
48341
|
var test_ml_exports = {};
|
|
48055
48342
|
__export(test_ml_exports, {
|
|
48056
|
-
main: () =>
|
|
48343
|
+
main: () => main55
|
|
48057
48344
|
});
|
|
48058
|
-
var import_config14,
|
|
48345
|
+
var import_config14, import_constants22, import_ml3, import_registry6, now, INTERVAL_MIN, CANDLES, makeSeries, makeCandles, buildTrendline, main55;
|
|
48059
48346
|
var init_test_ml = __esm({
|
|
48060
48347
|
"src/scripts/test-ml.ts"() {
|
|
48061
48348
|
"use strict";
|
|
48062
48349
|
import_config14 = require("dotenv/config");
|
|
48063
|
-
|
|
48350
|
+
import_constants22 = require("@tradejs/core/constants");
|
|
48064
48351
|
import_ml3 = require("@tradejs/infra/ml");
|
|
48065
48352
|
import_registry6 = require("@tradejs/node/registry");
|
|
48066
48353
|
now = Date.now();
|
|
48067
48354
|
INTERVAL_MIN = 15;
|
|
48068
|
-
CANDLES =
|
|
48355
|
+
CANDLES = import_constants22.ML_BASE_CANDLES_WINDOW;
|
|
48069
48356
|
makeSeries = (len, base, step = 0.1) => Array.from({ length: len }, (_3, i) => base + i * step);
|
|
48070
48357
|
makeCandles = (startPrice, startTs) => {
|
|
48071
48358
|
const candles = [];
|
|
@@ -48105,7 +48392,7 @@ var init_test_ml = __esm({
|
|
|
48105
48392
|
{ timestamp: entryTs - 2 * INTERVAL_MIN * 6e4, value: price * 0.995 }
|
|
48106
48393
|
]
|
|
48107
48394
|
});
|
|
48108
|
-
|
|
48395
|
+
main55 = async () => {
|
|
48109
48396
|
const defaultConfig = await (0, import_registry6.getStrategyDefaults)("TrendLine", process.cwd());
|
|
48110
48397
|
if (!defaultConfig) {
|
|
48111
48398
|
throw new Error(
|
|
@@ -48137,8 +48424,8 @@ var init_test_ml = __esm({
|
|
|
48137
48424
|
correlation: 0.18,
|
|
48138
48425
|
touches: 6,
|
|
48139
48426
|
distance: 0.7,
|
|
48140
|
-
candles15m: candles.slice(-
|
|
48141
|
-
btcCandles15m: btcCandles.slice(-
|
|
48427
|
+
candles15m: candles.slice(-import_constants22.ML_BASE_CANDLES_WINDOW),
|
|
48428
|
+
btcCandles15m: btcCandles.slice(-import_constants22.ML_BASE_CANDLES_WINDOW),
|
|
48142
48429
|
atr: makeSeries(10, 1.2, 0.02),
|
|
48143
48430
|
atrPct: makeSeries(10, 1.05, 5e-3),
|
|
48144
48431
|
maFast: makeSeries(10, currentPrice * 0.995, 0.01),
|
|
@@ -48198,20 +48485,20 @@ var init_test_ml = __esm({
|
|
|
48198
48485
|
// src/scripts/test.ts
|
|
48199
48486
|
var test_exports = {};
|
|
48200
48487
|
__export(test_exports, {
|
|
48201
|
-
main: () =>
|
|
48488
|
+
main: () => main56
|
|
48202
48489
|
});
|
|
48203
|
-
var import_config15,
|
|
48490
|
+
var import_config15, import_connectors21, getPositions, main56;
|
|
48204
48491
|
var init_test = __esm({
|
|
48205
48492
|
"src/scripts/test.ts"() {
|
|
48206
48493
|
"use strict";
|
|
48207
48494
|
import_config15 = require("dotenv/config");
|
|
48208
|
-
|
|
48495
|
+
import_connectors21 = require("@tradejs/connectors");
|
|
48209
48496
|
getPositions = async (connector) => {
|
|
48210
48497
|
const res = await connector.getPositions();
|
|
48211
48498
|
console.log("res", res);
|
|
48212
48499
|
};
|
|
48213
|
-
|
|
48214
|
-
const byBitConnector = await
|
|
48500
|
+
main56 = async () => {
|
|
48501
|
+
const byBitConnector = await import_connectors21.connectors.ByBit({
|
|
48215
48502
|
userName: "root"
|
|
48216
48503
|
});
|
|
48217
48504
|
await getPositions(byBitConnector);
|
|
@@ -48222,21 +48509,21 @@ var init_test = __esm({
|
|
|
48222
48509
|
// src/scripts/user-add.ts
|
|
48223
48510
|
var user_add_exports = {};
|
|
48224
48511
|
__export(user_add_exports, {
|
|
48225
|
-
main: () =>
|
|
48512
|
+
main: () => main57
|
|
48226
48513
|
});
|
|
48227
|
-
var import_args39, import_chalk55, import_bcryptjs,
|
|
48514
|
+
var import_args39, import_chalk55, import_bcryptjs, import_redis26, flags35, main57;
|
|
48228
48515
|
var init_user_add = __esm({
|
|
48229
48516
|
"src/scripts/user-add.ts"() {
|
|
48230
48517
|
"use strict";
|
|
48231
48518
|
import_args39 = __toESM(require("args"));
|
|
48232
48519
|
import_chalk55 = __toESM(require("chalk"));
|
|
48233
48520
|
import_bcryptjs = __toESM(require("bcryptjs"));
|
|
48234
|
-
|
|
48521
|
+
import_redis26 = require("@tradejs/infra/redis");
|
|
48235
48522
|
import_args39.default.example("yarn user-add -u myname -p 123456", "Create or update user");
|
|
48236
48523
|
import_args39.default.option(["u", "user"], "Username", "");
|
|
48237
48524
|
import_args39.default.option(["p", "password"], "Password (plain text)", "");
|
|
48238
48525
|
flags35 = import_args39.default.parse(process.argv);
|
|
48239
|
-
|
|
48526
|
+
main57 = async () => {
|
|
48240
48527
|
const userName3 = String(flags35.user || "").trim();
|
|
48241
48528
|
const password = String(flags35.password || "");
|
|
48242
48529
|
if (!userName3 || !password) {
|
|
@@ -48244,14 +48531,14 @@ var init_user_add = __esm({
|
|
|
48244
48531
|
process.exit(1);
|
|
48245
48532
|
}
|
|
48246
48533
|
const passwordHash = await import_bcryptjs.default.hash(password, 10);
|
|
48247
|
-
const existing = await (0,
|
|
48534
|
+
const existing = await (0, import_redis26.getData)(import_redis26.redisKeys.user(userName3), null);
|
|
48248
48535
|
const next = {
|
|
48249
48536
|
...existing ?? {},
|
|
48250
48537
|
passwordHash,
|
|
48251
48538
|
userName: userName3,
|
|
48252
48539
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
48253
48540
|
};
|
|
48254
|
-
await (0,
|
|
48541
|
+
await (0, import_redis26.setData)(import_redis26.redisKeys.user(userName3), next, {
|
|
48255
48542
|
expire: 0
|
|
48256
48543
|
});
|
|
48257
48544
|
console.log(import_chalk55.default.green(`User ${userName3} updated`));
|
|
@@ -48264,14 +48551,14 @@ var init_user_add = __esm({
|
|
|
48264
48551
|
var cli_exports = {};
|
|
48265
48552
|
__export(cli_exports, {
|
|
48266
48553
|
cleanupCliResources: () => cleanupCliResources,
|
|
48267
|
-
main: () =>
|
|
48554
|
+
main: () => main58,
|
|
48268
48555
|
printUsage: () => printUsage3,
|
|
48269
48556
|
runLoadedModule: () => runLoadedModule
|
|
48270
48557
|
});
|
|
48271
48558
|
module.exports = __toCommonJS(cli_exports);
|
|
48272
48559
|
var import_config16 = require("dotenv/config");
|
|
48273
|
-
var
|
|
48274
|
-
var
|
|
48560
|
+
var import_redis27 = require("@tradejs/infra/redis");
|
|
48561
|
+
var import_client10 = require("@tradejs/infra/timescale/client");
|
|
48275
48562
|
var scriptLoaders = {
|
|
48276
48563
|
"research-visuals": () => Promise.resolve().then(() => (init_researchVisuals2(), researchVisuals_exports)),
|
|
48277
48564
|
"agent-run": () => Promise.resolve().then(() => (init_agentRun(), agentRun_exports)),
|
|
@@ -48289,6 +48576,7 @@ var scriptLoaders = {
|
|
|
48289
48576
|
"clean-dir": () => Promise.resolve().then(() => (init_cleanDir(), cleanDir_exports)),
|
|
48290
48577
|
"clean-redis": () => Promise.resolve().then(() => (init_cleanRedis(), cleanRedis_exports)),
|
|
48291
48578
|
"clean-tests": () => Promise.resolve().then(() => (init_cleanTests(), cleanTests_exports)),
|
|
48579
|
+
"coverage:backfill": () => Promise.resolve().then(() => (init_coverageBackfill(), coverageBackfill_exports)),
|
|
48292
48580
|
continuity: () => Promise.resolve().then(() => (init_continuity2(), continuity_exports)),
|
|
48293
48581
|
"derivatives:ingest": () => Promise.resolve().then(() => (init_derivativesIngest(), derivativesIngest_exports)),
|
|
48294
48582
|
"derivatives:ingest:coinalyze:all": () => Promise.resolve().then(() => (init_derivativesIngestCoinalyzeAll(), derivativesIngestCoinalyzeAll_exports)),
|
|
@@ -48345,9 +48633,9 @@ var runLoadedModule = async (loaded) => {
|
|
|
48345
48633
|
}
|
|
48346
48634
|
};
|
|
48347
48635
|
var cleanupCliResources = async () => {
|
|
48348
|
-
await Promise.allSettled([(0,
|
|
48636
|
+
await Promise.allSettled([(0, import_redis27.closeRedisConnection)(), (0, import_client10.closeTimescalePool)()]);
|
|
48349
48637
|
};
|
|
48350
|
-
var
|
|
48638
|
+
var main58 = async () => {
|
|
48351
48639
|
const [, scriptPath, command = "", ...args40] = process.argv;
|
|
48352
48640
|
const loader = scriptLoaders[command];
|
|
48353
48641
|
if (!loader) {
|
|
@@ -48378,7 +48666,7 @@ var main57 = async () => {
|
|
|
48378
48666
|
}
|
|
48379
48667
|
};
|
|
48380
48668
|
if (require.main === module) {
|
|
48381
|
-
|
|
48669
|
+
main58().catch((error) => {
|
|
48382
48670
|
console.error(error);
|
|
48383
48671
|
process.exit(1);
|
|
48384
48672
|
});
|