@tradejs/cli 3.1.29-beta.292 → 3.1.29-beta.297
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +968 -680
- package/dist/lib/binanceMarketContextBackfill.js +2 -2
- package/dist/lib/coinMarketCapContextBackfill.js +22 -6
- package/dist/lib/derivativesContextBackfill.js +14 -0
- package/dist/lib/marketContextPrepare.js +24 -8
- package/dist/lib/strategyResearch.js +33 -79
- package/dist/scripts/backtest.js +213 -74
- package/dist/scripts/binanceMarketIngest.js +3 -3
- package/dist/scripts/coverageBackfill.js +1731 -0
- package/dist/scripts/replay.js +24 -8
- package/dist/scripts/replayRunner.js +24 -8
- package/dist/scripts/replayRuntimeEvidence.js +4 -1
- package/dist/scripts/runtimeParity.js +24 -8
- package/dist/scripts/signals.js +24 -8
- package/dist/scripts/signalsDaemon.js +24 -8
- package/dist/scripts/strategyRelease.js +6 -37
- package/dist/scripts/strategyResearch.js +36 -82
- package/package.json +7 -7
- package/dist/lib/researchMetricSnapshot.js +0 -74
package/dist/scripts/backtest.js
CHANGED
|
@@ -30,7 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/scripts/backtest.ts
|
|
31
31
|
var backtest_exports = {};
|
|
32
32
|
__export(backtest_exports, {
|
|
33
|
-
BACKTEST_PRELOAD_DAYS: () =>
|
|
33
|
+
BACKTEST_PRELOAD_DAYS: () => import_constants7.BACKTEST_PRELOAD_DAYS,
|
|
34
34
|
backtest: () => backtest,
|
|
35
35
|
chunkTestSuiteBySymbol: () => chunkTestSuiteBySymbol,
|
|
36
36
|
interval: () => interval,
|
|
@@ -62,8 +62,8 @@ var import_chalk10 = __toESM(require("chalk"));
|
|
|
62
62
|
var import_backtest3 = require("@tradejs/core/backtest");
|
|
63
63
|
var import_grid = require("@tradejs/core/grid");
|
|
64
64
|
var import_data = require("@tradejs/core/data");
|
|
65
|
-
var
|
|
66
|
-
var
|
|
65
|
+
var import_redis6 = require("@tradejs/infra/redis");
|
|
66
|
+
var import_constants7 = require("@tradejs/core/constants");
|
|
67
67
|
|
|
68
68
|
// src/lib/backtest/jevOptions.ts
|
|
69
69
|
var import_promises = __toESM(require("fs/promises"));
|
|
@@ -491,13 +491,12 @@ var getReferenceSymbols = () => {
|
|
|
491
491
|
};
|
|
492
492
|
var intervalToMarketFeatureInterval = (interval2) => {
|
|
493
493
|
const normalized = String(interval2).trim().toLowerCase();
|
|
494
|
-
if (normalized === "1" || normalized === "1m") return
|
|
494
|
+
if (normalized === "1" || normalized === "1m") return null;
|
|
495
495
|
if (normalized === "5" || normalized === "5m") return "5m";
|
|
496
496
|
if (normalized === "60" || normalized === "1h") return "1h";
|
|
497
497
|
return "15m";
|
|
498
498
|
};
|
|
499
499
|
var marketIntervalToConnectorInterval = (interval2) => {
|
|
500
|
-
if (interval2 === "1m") return "1";
|
|
501
500
|
if (interval2 === "5m") return "5";
|
|
502
501
|
if (interval2 === "1h") return "60";
|
|
503
502
|
return "15";
|
|
@@ -662,6 +661,7 @@ var backfillBinanceMarketContext = async (params, enabled) => {
|
|
|
662
661
|
return skippedBackfillResult();
|
|
663
662
|
}
|
|
664
663
|
const interval2 = intervalToMarketFeatureInterval(params.interval);
|
|
664
|
+
if (interval2 === null) return skippedBackfillResult();
|
|
665
665
|
const intervalMs = MARKET_FEATURE_INTERVAL_MS[interval2];
|
|
666
666
|
const { breadthStartMs, tradeFlowStartMs, endMs } = resolveBinanceMarketContextBackfillWindow(params);
|
|
667
667
|
if (endMs <= Math.min(breadthStartMs, tradeFlowStartMs)) {
|
|
@@ -2242,7 +2242,7 @@ var coinMarketCapFetch = async (params) => {
|
|
|
2242
2242
|
};
|
|
2243
2243
|
var fetchCoinMarketCapIndexRows = async (params) => {
|
|
2244
2244
|
const rows = [];
|
|
2245
|
-
const maxChunkDays =
|
|
2245
|
+
const maxChunkDays = 4;
|
|
2246
2246
|
const totalChunks = Math.max(
|
|
2247
2247
|
1,
|
|
2248
2248
|
Math.ceil(
|
|
@@ -2679,11 +2679,27 @@ var backfillCoinMarketCapContext = async (params) => {
|
|
|
2679
2679
|
toMs
|
|
2680
2680
|
})
|
|
2681
2681
|
);
|
|
2682
|
-
const
|
|
2683
|
-
const
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2682
|
+
const ready = (dataset, existing) => params.repairDataset ? params.repairDataset !== dataset : existing;
|
|
2683
|
+
const globalDailyReady = ready(
|
|
2684
|
+
"cmc-global-1d",
|
|
2685
|
+
globalDailyCached || globalDailyBackfillCovered
|
|
2686
|
+
);
|
|
2687
|
+
const referencesDailyReady = ready(
|
|
2688
|
+
"cmc-reference_asset-1d",
|
|
2689
|
+
referencesDailyCached || referencesDailyBackfillCovered
|
|
2690
|
+
);
|
|
2691
|
+
const exchangeLiquidityReady = ready(
|
|
2692
|
+
"cmc-exchange_liquidity-1d",
|
|
2693
|
+
exchangeLiquidityCached || !exchangeLiquidityEnabled || exchangeLiquidityBackfillCovered
|
|
2694
|
+
);
|
|
2695
|
+
const fearGreedReady = ready(
|
|
2696
|
+
"cmc-fear_greed-1d",
|
|
2697
|
+
fearGreedCached || !fearGreedEnabled || fearGreedBackfillCovered
|
|
2698
|
+
);
|
|
2699
|
+
const indexesReady = ready(
|
|
2700
|
+
"cmc-index-1d",
|
|
2701
|
+
indexesCached || indexesBackfillCovered
|
|
2702
|
+
);
|
|
2687
2703
|
let globalStatus = resolveBackfillStatus({
|
|
2688
2704
|
cached: globalDailyCached,
|
|
2689
2705
|
covered: globalDailyBackfillCovered
|
|
@@ -4777,7 +4793,9 @@ var executeBacktestWorkerPool = async ({
|
|
|
4777
4793
|
chunkTestSuite,
|
|
4778
4794
|
getProgressSnapshot,
|
|
4779
4795
|
initialCompletedTests = 0,
|
|
4780
|
-
totalTests
|
|
4796
|
+
totalTests,
|
|
4797
|
+
onProgress,
|
|
4798
|
+
onIncomplete
|
|
4781
4799
|
}) => {
|
|
4782
4800
|
const chunks = chunkTestSuite(testSuite);
|
|
4783
4801
|
const fastAiWorkerPgPoolMax = resolveFastAiWorkerPgPoolMax(
|
|
@@ -4793,7 +4811,9 @@ var executeBacktestWorkerPool = async ({
|
|
|
4793
4811
|
);
|
|
4794
4812
|
let completedTests = initialCompletedTests;
|
|
4795
4813
|
let renderedTests = 0;
|
|
4814
|
+
let pendingResults = 0;
|
|
4796
4815
|
let isFinishing = false;
|
|
4816
|
+
let isInterrupted = false;
|
|
4797
4817
|
let signalHandlersRemoved = false;
|
|
4798
4818
|
const workers = /* @__PURE__ */ new Set();
|
|
4799
4819
|
const stopWorkers = () => {
|
|
@@ -4804,6 +4824,7 @@ var executeBacktestWorkerPool = async ({
|
|
|
4804
4824
|
}
|
|
4805
4825
|
};
|
|
4806
4826
|
const handleInterrupt = (signal, exitCode) => {
|
|
4827
|
+
isInterrupted = true;
|
|
4807
4828
|
stopWorkers();
|
|
4808
4829
|
void Promise.resolve(onInterrupt?.(signal)).catch((error) => {
|
|
4809
4830
|
console.error(
|
|
@@ -4824,15 +4845,16 @@ var executeBacktestWorkerPool = async ({
|
|
|
4824
4845
|
process.removeListener("SIGTERM", handleSigterm);
|
|
4825
4846
|
};
|
|
4826
4847
|
const maybeFinish = async () => {
|
|
4827
|
-
if (isFinishing) {
|
|
4828
|
-
return;
|
|
4829
|
-
}
|
|
4830
|
-
if (completedTests !== totalExpectedTests || workers.size > 0) {
|
|
4848
|
+
if (isFinishing || isInterrupted || workers.size > 0 || pendingResults > 0) {
|
|
4831
4849
|
return;
|
|
4832
4850
|
}
|
|
4833
4851
|
isFinishing = true;
|
|
4834
4852
|
try {
|
|
4835
|
-
|
|
4853
|
+
if (completedTests === totalExpectedTests) {
|
|
4854
|
+
await onFinish();
|
|
4855
|
+
} else {
|
|
4856
|
+
await onIncomplete?.();
|
|
4857
|
+
}
|
|
4836
4858
|
} finally {
|
|
4837
4859
|
cleanupSignalHandlers();
|
|
4838
4860
|
}
|
|
@@ -4891,14 +4913,22 @@ var executeBacktestWorkerPool = async ({
|
|
|
4891
4913
|
return;
|
|
4892
4914
|
}
|
|
4893
4915
|
completedTests++;
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
|
|
4916
|
+
onProgress?.(completedTests);
|
|
4917
|
+
pendingResults++;
|
|
4918
|
+
try {
|
|
4919
|
+
await onMessage(msg);
|
|
4920
|
+
if (completedTests % progressStep2 === 0 || completedTests === totalExpectedTests) {
|
|
4921
|
+
tickProgress();
|
|
4922
|
+
}
|
|
4923
|
+
} finally {
|
|
4924
|
+
pendingResults--;
|
|
4897
4925
|
}
|
|
4926
|
+
await maybeFinish();
|
|
4898
4927
|
});
|
|
4899
4928
|
tester.on("error", (err) => {
|
|
4900
4929
|
workers.delete(tester);
|
|
4901
4930
|
onWorkerError(err?.message ?? String(err));
|
|
4931
|
+
void maybeFinish();
|
|
4902
4932
|
});
|
|
4903
4933
|
tester.on("exit", (code) => {
|
|
4904
4934
|
workers.delete(tester);
|
|
@@ -5285,7 +5315,9 @@ var executeTestSuite = async ({
|
|
|
5285
5315
|
onFinish,
|
|
5286
5316
|
initialCompletedTests = 0,
|
|
5287
5317
|
totalTests,
|
|
5288
|
-
backtestRunId
|
|
5318
|
+
backtestRunId,
|
|
5319
|
+
onProgress,
|
|
5320
|
+
onIncomplete
|
|
5289
5321
|
}) => {
|
|
5290
5322
|
markTestsStarted();
|
|
5291
5323
|
const { testerWorkerPath, testerNeedsTsRuntime } = resolveTesterWorker();
|
|
@@ -5309,6 +5341,8 @@ var executeTestSuite = async ({
|
|
|
5309
5341
|
chunkTestSuite: (suite) => chunkTestSuiteBySymbol(suite, effectiveParallel),
|
|
5310
5342
|
initialCompletedTests,
|
|
5311
5343
|
totalTests,
|
|
5344
|
+
onProgress,
|
|
5345
|
+
onIncomplete,
|
|
5312
5346
|
onInterrupt,
|
|
5313
5347
|
onMessage: async (msg) => {
|
|
5314
5348
|
if (msg.error) {
|
|
@@ -5362,6 +5396,106 @@ var printRunOutro = () => {
|
|
|
5362
5396
|
console.log("");
|
|
5363
5397
|
};
|
|
5364
5398
|
|
|
5399
|
+
// src/lib/backtest/observeRun.ts
|
|
5400
|
+
var import_constants6 = require("@tradejs/core/constants");
|
|
5401
|
+
var import_redis5 = require("@tradejs/infra/redis");
|
|
5402
|
+
var import_logger = require("@tradejs/infra/logger");
|
|
5403
|
+
var HEARTBEAT_MS = 2e3;
|
|
5404
|
+
var ACTIVE_TTL_SECONDS = 30;
|
|
5405
|
+
var LINKED_RUN_TTL_SECONDS = 30 * 24 * import_constants6.TTL_1H;
|
|
5406
|
+
var 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}$/;
|
|
5407
|
+
var MAX_VALUES_PER_PARAMETER = 12;
|
|
5408
|
+
var MAX_VALUE_LENGTH = 500;
|
|
5409
|
+
var summarizeBacktestParameters = (tests) => {
|
|
5410
|
+
const parameters = /* @__PURE__ */ new Map();
|
|
5411
|
+
for (const test of tests) {
|
|
5412
|
+
for (const [name, value] of Object.entries(test.strategyConfig)) {
|
|
5413
|
+
const serialized = JSON.stringify(value);
|
|
5414
|
+
if (serialized === void 0) continue;
|
|
5415
|
+
const parameter = parameters.get(name) ?? {
|
|
5416
|
+
values: /* @__PURE__ */ new Set(),
|
|
5417
|
+
truncated: false
|
|
5418
|
+
};
|
|
5419
|
+
parameters.set(name, parameter);
|
|
5420
|
+
if (parameter.values.has(serialized)) continue;
|
|
5421
|
+
if (parameter.values.size === MAX_VALUES_PER_PARAMETER || serialized.length > MAX_VALUE_LENGTH) {
|
|
5422
|
+
parameter.truncated = true;
|
|
5423
|
+
} else {
|
|
5424
|
+
parameter.values.add(serialized);
|
|
5425
|
+
}
|
|
5426
|
+
}
|
|
5427
|
+
}
|
|
5428
|
+
return [...parameters].map(([name, { values, truncated }]) => ({
|
|
5429
|
+
name,
|
|
5430
|
+
values: [...values],
|
|
5431
|
+
truncated
|
|
5432
|
+
}));
|
|
5433
|
+
};
|
|
5434
|
+
var observeBacktestRun = async (manifest, initialCompleted, parallel) => {
|
|
5435
|
+
if (process.env.TRADEJS_BACKTEST_WEB_JOB === "1") return;
|
|
5436
|
+
const researchStudy = process.env.TRADEJS_RESEARCH_STUDY?.trim();
|
|
5437
|
+
const linkedStudy = researchStudy && RESEARCH_STUDY.test(researchStudy) ? researchStudy : void 0;
|
|
5438
|
+
if (researchStudy && !linkedStudy) {
|
|
5439
|
+
import_logger.logger.warn(
|
|
5440
|
+
"invalid TRADEJS_RESEARCH_STUDY; expected Strategy/YYYY-MM-DD-slug"
|
|
5441
|
+
);
|
|
5442
|
+
}
|
|
5443
|
+
const { testSuite } = manifest;
|
|
5444
|
+
const firstTest = testSuite[0];
|
|
5445
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
5446
|
+
const run = {
|
|
5447
|
+
id: manifest.runId,
|
|
5448
|
+
...linkedStudy && { researchStudy: linkedStudy },
|
|
5449
|
+
userName: manifest.userName,
|
|
5450
|
+
strategyName: firstTest.strategyName,
|
|
5451
|
+
configId: manifest.config,
|
|
5452
|
+
connector: manifest.connectorName,
|
|
5453
|
+
interval: manifest.interval,
|
|
5454
|
+
startTime: manifest.window.start,
|
|
5455
|
+
endTime: manifest.window.end,
|
|
5456
|
+
symbols: [...new Set(testSuite.map((test) => test.symbol))],
|
|
5457
|
+
settings: {
|
|
5458
|
+
...manifest.flags,
|
|
5459
|
+
parallel,
|
|
5460
|
+
...firstTest.executionCosts && {
|
|
5461
|
+
executionCosts: JSON.stringify(firstTest.executionCosts)
|
|
5462
|
+
}
|
|
5463
|
+
},
|
|
5464
|
+
parameters: summarizeBacktestParameters(testSuite),
|
|
5465
|
+
status: "running",
|
|
5466
|
+
completed: initialCompleted,
|
|
5467
|
+
total: testSuite.length,
|
|
5468
|
+
startedAt,
|
|
5469
|
+
updatedAt: startedAt
|
|
5470
|
+
};
|
|
5471
|
+
const save = async (expire) => {
|
|
5472
|
+
run.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
5473
|
+
try {
|
|
5474
|
+
await import_redis5.cliBacktestRunStorage.put(run, expire);
|
|
5475
|
+
} catch (error) {
|
|
5476
|
+
import_logger.logger.warn("failed to publish CLI backtest progress: %s", String(error));
|
|
5477
|
+
}
|
|
5478
|
+
};
|
|
5479
|
+
await save(ACTIVE_TTL_SECONDS);
|
|
5480
|
+
let pending;
|
|
5481
|
+
const timer = setInterval(() => {
|
|
5482
|
+
pending ??= save(ACTIVE_TTL_SECONDS).finally(() => {
|
|
5483
|
+
pending = void 0;
|
|
5484
|
+
});
|
|
5485
|
+
}, HEARTBEAT_MS).unref();
|
|
5486
|
+
return {
|
|
5487
|
+
progress: (completed) => {
|
|
5488
|
+
run.completed = completed;
|
|
5489
|
+
},
|
|
5490
|
+
finish: async (status) => {
|
|
5491
|
+
clearInterval(timer);
|
|
5492
|
+
await pending;
|
|
5493
|
+
run.status = status;
|
|
5494
|
+
await save(linkedStudy ? LINKED_RUN_TTL_SECONDS : import_constants6.TTL_1H);
|
|
5495
|
+
}
|
|
5496
|
+
};
|
|
5497
|
+
};
|
|
5498
|
+
|
|
5365
5499
|
// src/scripts/backtest.ts
|
|
5366
5500
|
if (process.argv.some(
|
|
5367
5501
|
(arg) => arg === "--live" || String(arg).startsWith("--live=")
|
|
@@ -5497,8 +5631,8 @@ var loadBacktestConfig = async () => {
|
|
|
5497
5631
|
if (!strategyName) {
|
|
5498
5632
|
throw new Error("Strategy name not found");
|
|
5499
5633
|
}
|
|
5500
|
-
const backtestConfig = await (0,
|
|
5501
|
-
|
|
5634
|
+
const backtestConfig = await (0, import_redis6.getData)(
|
|
5635
|
+
import_redis6.redisKeys.backtestConfig(userName, flags.config),
|
|
5502
5636
|
null
|
|
5503
5637
|
);
|
|
5504
5638
|
if (!backtestConfig) {
|
|
@@ -5645,8 +5779,8 @@ var finishBacktest = async (testSuite) => {
|
|
|
5645
5779
|
console.log(import_chalk10.default.gray(`full report: ${markdownReportPath}`));
|
|
5646
5780
|
console.log("");
|
|
5647
5781
|
if (!isFastMode || flags.persistResults) {
|
|
5648
|
-
await (0,
|
|
5649
|
-
|
|
5782
|
+
await (0, import_redis6.setData)(
|
|
5783
|
+
import_redis6.redisKeys.backtestResults(userName, flags.config, timestamp),
|
|
5650
5784
|
{
|
|
5651
5785
|
config: flags.config,
|
|
5652
5786
|
mode: "config",
|
|
@@ -5666,11 +5800,10 @@ var finishBacktest = async (testSuite) => {
|
|
|
5666
5800
|
errorTests: errorTests2
|
|
5667
5801
|
},
|
|
5668
5802
|
{
|
|
5669
|
-
expire:
|
|
5803
|
+
expire: import_constants7.TTL_1M
|
|
5670
5804
|
}
|
|
5671
5805
|
);
|
|
5672
5806
|
}
|
|
5673
|
-
process.exit();
|
|
5674
5807
|
};
|
|
5675
5808
|
var restoreCompletedBacktestResults = (completed) => {
|
|
5676
5809
|
for (const { result } of completed) {
|
|
@@ -5751,6 +5884,56 @@ var prepareContinuedBacktestMarketContext = async ({
|
|
|
5751
5884
|
log: (message) => console.log(import_chalk10.default.gray(message))
|
|
5752
5885
|
});
|
|
5753
5886
|
};
|
|
5887
|
+
var runBacktestSuite = async (manifest, testSuite, initialCompletedTests = 0) => {
|
|
5888
|
+
const observation = await observeBacktestRun(
|
|
5889
|
+
manifest,
|
|
5890
|
+
initialCompletedTests,
|
|
5891
|
+
effectiveParallel
|
|
5892
|
+
);
|
|
5893
|
+
try {
|
|
5894
|
+
await executeTestSuite({
|
|
5895
|
+
testSuite,
|
|
5896
|
+
window: manifest.window,
|
|
5897
|
+
preloadStart: manifest.preloadStart,
|
|
5898
|
+
backtestRunId: manifest.runId,
|
|
5899
|
+
initialCompletedTests,
|
|
5900
|
+
totalTests: manifest.testSuite.length,
|
|
5901
|
+
onProgress: observation?.progress,
|
|
5902
|
+
onIncomplete: async () => {
|
|
5903
|
+
await observation?.finish("failed");
|
|
5904
|
+
await markBacktestRunStatus({ run: manifest, status: "interrupted" });
|
|
5905
|
+
process.exit(1);
|
|
5906
|
+
},
|
|
5907
|
+
onResult: async (result) => {
|
|
5908
|
+
await saveBacktestCheckpointResult({
|
|
5909
|
+
result,
|
|
5910
|
+
runId: manifest.runId,
|
|
5911
|
+
userName
|
|
5912
|
+
});
|
|
5913
|
+
trackTopResult(result);
|
|
5914
|
+
updateBestTickerResult(result);
|
|
5915
|
+
},
|
|
5916
|
+
onInterrupt: async () => {
|
|
5917
|
+
await observation?.finish("cancelled");
|
|
5918
|
+
await markBacktestRunStatus({ run: manifest, status: "interrupted" });
|
|
5919
|
+
},
|
|
5920
|
+
onFinish: async () => {
|
|
5921
|
+
try {
|
|
5922
|
+
await markBacktestRunStatus({ run: manifest, status: "completed" });
|
|
5923
|
+
await finishBacktest(manifest.testSuite);
|
|
5924
|
+
await observation?.finish("completed");
|
|
5925
|
+
process.exit();
|
|
5926
|
+
} catch (error) {
|
|
5927
|
+
await observation?.finish("failed");
|
|
5928
|
+
throw error;
|
|
5929
|
+
}
|
|
5930
|
+
}
|
|
5931
|
+
});
|
|
5932
|
+
} catch (error) {
|
|
5933
|
+
await observation?.finish("failed");
|
|
5934
|
+
throw error;
|
|
5935
|
+
}
|
|
5936
|
+
};
|
|
5754
5937
|
var backtest = async () => {
|
|
5755
5938
|
resetRunState();
|
|
5756
5939
|
const config = await loadBacktestConfig();
|
|
@@ -5765,33 +5948,10 @@ var backtest = async () => {
|
|
|
5765
5948
|
if (!remainingSuite.length) {
|
|
5766
5949
|
await markBacktestRunStatus({ run: manifest2, status: "completed" });
|
|
5767
5950
|
await finishBacktest(manifest2.testSuite);
|
|
5768
|
-
|
|
5951
|
+
process.exit();
|
|
5769
5952
|
}
|
|
5770
5953
|
await prepareContinuedBacktestMarketContext({ manifest: manifest2, remainingSuite });
|
|
5771
|
-
await
|
|
5772
|
-
testSuite: remainingSuite,
|
|
5773
|
-
window: manifest2.window,
|
|
5774
|
-
preloadStart: manifest2.preloadStart,
|
|
5775
|
-
backtestRunId: manifest2.runId,
|
|
5776
|
-
initialCompletedTests: completed.length,
|
|
5777
|
-
totalTests: manifest2.testSuite.length,
|
|
5778
|
-
onResult: async (result) => {
|
|
5779
|
-
await saveBacktestCheckpointResult({
|
|
5780
|
-
result,
|
|
5781
|
-
runId: manifest2.runId,
|
|
5782
|
-
userName
|
|
5783
|
-
});
|
|
5784
|
-
trackTopResult(result);
|
|
5785
|
-
updateBestTickerResult(result);
|
|
5786
|
-
},
|
|
5787
|
-
onInterrupt: async () => {
|
|
5788
|
-
await markBacktestRunStatus({ run: manifest2, status: "interrupted" });
|
|
5789
|
-
},
|
|
5790
|
-
onFinish: async () => {
|
|
5791
|
-
await markBacktestRunStatus({ run: manifest2, status: "completed" });
|
|
5792
|
-
await finishBacktest(manifest2.testSuite);
|
|
5793
|
-
}
|
|
5794
|
-
});
|
|
5954
|
+
await runBacktestSuite(manifest2, remainingSuite, completed.length);
|
|
5795
5955
|
return;
|
|
5796
5956
|
}
|
|
5797
5957
|
const preparedRun = await prepareRunEnvironment2(config.strategyName);
|
|
@@ -5852,28 +6012,7 @@ var backtest = async () => {
|
|
|
5852
6012
|
testSuite
|
|
5853
6013
|
});
|
|
5854
6014
|
console.log(import_chalk10.default.gray(`backtest run id: ${manifest.runId}`));
|
|
5855
|
-
await
|
|
5856
|
-
testSuite,
|
|
5857
|
-
window: preparedRun.window,
|
|
5858
|
-
preloadStart: preparedRun.preloadStart,
|
|
5859
|
-
backtestRunId: manifest.runId,
|
|
5860
|
-
onResult: async (result) => {
|
|
5861
|
-
await saveBacktestCheckpointResult({
|
|
5862
|
-
result,
|
|
5863
|
-
runId: manifest.runId,
|
|
5864
|
-
userName
|
|
5865
|
-
});
|
|
5866
|
-
trackTopResult(result);
|
|
5867
|
-
updateBestTickerResult(result);
|
|
5868
|
-
},
|
|
5869
|
-
onInterrupt: async () => {
|
|
5870
|
-
await markBacktestRunStatus({ run: manifest, status: "interrupted" });
|
|
5871
|
-
},
|
|
5872
|
-
onFinish: async () => {
|
|
5873
|
-
await markBacktestRunStatus({ run: manifest, status: "completed" });
|
|
5874
|
-
await finishBacktest(testSuite);
|
|
5875
|
-
}
|
|
5876
|
-
});
|
|
6015
|
+
await runBacktestSuite(manifest, testSuite);
|
|
5877
6016
|
};
|
|
5878
6017
|
var main = backtest;
|
|
5879
6018
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -352,7 +352,7 @@ var buildMarketBreadthRows = ({
|
|
|
352
352
|
|
|
353
353
|
// src/scripts/binanceMarketIngest.ts
|
|
354
354
|
import_args.default.example(
|
|
355
|
-
"yarn cli:node8g binance:market-ingest --all --symbols BTCUSDT,ETHUSDT --days 0.05 --interval
|
|
355
|
+
"yarn cli:node8g binance:market-ingest --all --symbols BTCUSDT,ETHUSDT --days 0.05 --interval 15m --write",
|
|
356
356
|
"Ingest Binance public market breadth and historical aggTrades buckets"
|
|
357
357
|
);
|
|
358
358
|
import_args.default.option(
|
|
@@ -360,7 +360,7 @@ import_args.default.option(
|
|
|
360
360
|
"Comma-separated target symbols",
|
|
361
361
|
"BTCUSDT,ETHUSDT"
|
|
362
362
|
);
|
|
363
|
-
import_args.default.option(["i", "interval"], "Aggregation interval:
|
|
363
|
+
import_args.default.option(["i", "interval"], "Aggregation interval: 5m,15m,1h", "15m");
|
|
364
364
|
import_args.default.option(["d", "days"], "Lookback window in days", "1");
|
|
365
365
|
import_args.default.option(["h", "hours"], "Lookback window in hours; overrides --days");
|
|
366
366
|
import_args.default.option(["a", "aggTrades"], "Fetch and bucket Binance aggTrades");
|
|
@@ -394,7 +394,6 @@ var asInt = (value, fallback) => {
|
|
|
394
394
|
};
|
|
395
395
|
var sleep = (ms) => ms > 0 ? new Promise((resolve) => setTimeout(resolve, ms)) : Promise.resolve();
|
|
396
396
|
var intervalToConnectorInterval = (interval) => {
|
|
397
|
-
if (interval === "1m") return "1";
|
|
398
397
|
if (interval === "5m") return "5";
|
|
399
398
|
if (interval === "15m") return "15";
|
|
400
399
|
return "60";
|
|
@@ -450,6 +449,7 @@ var printEstimate = (estimate) => {
|
|
|
450
449
|
var main = async () => {
|
|
451
450
|
const symbols = normalizeBinanceSymbols(flags.symbols);
|
|
452
451
|
const interval = normalizeMarketFeatureInterval(flags.interval);
|
|
452
|
+
if (interval === "1m") throw new Error("Use interval 5m, 15m, or 1h");
|
|
453
453
|
const hours = flags.hours == null ? null : asFloat(flags.hours, 0);
|
|
454
454
|
const days = hours != null && hours > 0 ? hours / 24 : asFloat(flags.days, 1);
|
|
455
455
|
const breadthUniverses = (0, import_strategies.getBinanceBreadthUniverses)();
|