@tradejs/cli 3.1.29-beta.291 → 3.1.29-beta.296
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 +7150 -6352
- package/dist/lib/binanceMarketContextBackfill.js +2 -2
- package/dist/lib/coinMarketCapContextBackfill.js +1 -1
- package/dist/lib/coreResearch.js +261 -115
- package/dist/lib/marketContextPrepare.js +3 -3
- package/dist/lib/researchVisuals.js +27 -6
- package/dist/lib/strategyResearch.js +234 -245
- package/dist/scripts/aiPocketSearch.js +3343 -3029
- package/dist/scripts/backtest.js +192 -69
- package/dist/scripts/binanceMarketIngest.js +3 -3
- package/dist/scripts/coreResearch.js +263 -115
- package/dist/scripts/replay.js +483 -114
- package/dist/scripts/replayRunner.js +483 -114
- package/dist/scripts/researchVisuals.js +27 -6
- package/dist/scripts/runtimeParity.js +3 -3
- package/dist/scripts/signals.js +3 -3
- package/dist/scripts/signalsDaemon.js +3 -3
- package/dist/scripts/strategyRelease.js +6 -37
- package/dist/scripts/strategyResearch.js +239 -249
- 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(
|
|
@@ -4777,7 +4777,9 @@ var executeBacktestWorkerPool = async ({
|
|
|
4777
4777
|
chunkTestSuite,
|
|
4778
4778
|
getProgressSnapshot,
|
|
4779
4779
|
initialCompletedTests = 0,
|
|
4780
|
-
totalTests
|
|
4780
|
+
totalTests,
|
|
4781
|
+
onProgress,
|
|
4782
|
+
onIncomplete
|
|
4781
4783
|
}) => {
|
|
4782
4784
|
const chunks = chunkTestSuite(testSuite);
|
|
4783
4785
|
const fastAiWorkerPgPoolMax = resolveFastAiWorkerPgPoolMax(
|
|
@@ -4793,7 +4795,9 @@ var executeBacktestWorkerPool = async ({
|
|
|
4793
4795
|
);
|
|
4794
4796
|
let completedTests = initialCompletedTests;
|
|
4795
4797
|
let renderedTests = 0;
|
|
4798
|
+
let pendingResults = 0;
|
|
4796
4799
|
let isFinishing = false;
|
|
4800
|
+
let isInterrupted = false;
|
|
4797
4801
|
let signalHandlersRemoved = false;
|
|
4798
4802
|
const workers = /* @__PURE__ */ new Set();
|
|
4799
4803
|
const stopWorkers = () => {
|
|
@@ -4804,6 +4808,7 @@ var executeBacktestWorkerPool = async ({
|
|
|
4804
4808
|
}
|
|
4805
4809
|
};
|
|
4806
4810
|
const handleInterrupt = (signal, exitCode) => {
|
|
4811
|
+
isInterrupted = true;
|
|
4807
4812
|
stopWorkers();
|
|
4808
4813
|
void Promise.resolve(onInterrupt?.(signal)).catch((error) => {
|
|
4809
4814
|
console.error(
|
|
@@ -4824,15 +4829,16 @@ var executeBacktestWorkerPool = async ({
|
|
|
4824
4829
|
process.removeListener("SIGTERM", handleSigterm);
|
|
4825
4830
|
};
|
|
4826
4831
|
const maybeFinish = async () => {
|
|
4827
|
-
if (isFinishing) {
|
|
4828
|
-
return;
|
|
4829
|
-
}
|
|
4830
|
-
if (completedTests !== totalExpectedTests || workers.size > 0) {
|
|
4832
|
+
if (isFinishing || isInterrupted || workers.size > 0 || pendingResults > 0) {
|
|
4831
4833
|
return;
|
|
4832
4834
|
}
|
|
4833
4835
|
isFinishing = true;
|
|
4834
4836
|
try {
|
|
4835
|
-
|
|
4837
|
+
if (completedTests === totalExpectedTests) {
|
|
4838
|
+
await onFinish();
|
|
4839
|
+
} else {
|
|
4840
|
+
await onIncomplete?.();
|
|
4841
|
+
}
|
|
4836
4842
|
} finally {
|
|
4837
4843
|
cleanupSignalHandlers();
|
|
4838
4844
|
}
|
|
@@ -4891,14 +4897,22 @@ var executeBacktestWorkerPool = async ({
|
|
|
4891
4897
|
return;
|
|
4892
4898
|
}
|
|
4893
4899
|
completedTests++;
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
|
|
4900
|
+
onProgress?.(completedTests);
|
|
4901
|
+
pendingResults++;
|
|
4902
|
+
try {
|
|
4903
|
+
await onMessage(msg);
|
|
4904
|
+
if (completedTests % progressStep2 === 0 || completedTests === totalExpectedTests) {
|
|
4905
|
+
tickProgress();
|
|
4906
|
+
}
|
|
4907
|
+
} finally {
|
|
4908
|
+
pendingResults--;
|
|
4897
4909
|
}
|
|
4910
|
+
await maybeFinish();
|
|
4898
4911
|
});
|
|
4899
4912
|
tester.on("error", (err) => {
|
|
4900
4913
|
workers.delete(tester);
|
|
4901
4914
|
onWorkerError(err?.message ?? String(err));
|
|
4915
|
+
void maybeFinish();
|
|
4902
4916
|
});
|
|
4903
4917
|
tester.on("exit", (code) => {
|
|
4904
4918
|
workers.delete(tester);
|
|
@@ -5285,7 +5299,9 @@ var executeTestSuite = async ({
|
|
|
5285
5299
|
onFinish,
|
|
5286
5300
|
initialCompletedTests = 0,
|
|
5287
5301
|
totalTests,
|
|
5288
|
-
backtestRunId
|
|
5302
|
+
backtestRunId,
|
|
5303
|
+
onProgress,
|
|
5304
|
+
onIncomplete
|
|
5289
5305
|
}) => {
|
|
5290
5306
|
markTestsStarted();
|
|
5291
5307
|
const { testerWorkerPath, testerNeedsTsRuntime } = resolveTesterWorker();
|
|
@@ -5309,6 +5325,8 @@ var executeTestSuite = async ({
|
|
|
5309
5325
|
chunkTestSuite: (suite) => chunkTestSuiteBySymbol(suite, effectiveParallel),
|
|
5310
5326
|
initialCompletedTests,
|
|
5311
5327
|
totalTests,
|
|
5328
|
+
onProgress,
|
|
5329
|
+
onIncomplete,
|
|
5312
5330
|
onInterrupt,
|
|
5313
5331
|
onMessage: async (msg) => {
|
|
5314
5332
|
if (msg.error) {
|
|
@@ -5362,6 +5380,106 @@ var printRunOutro = () => {
|
|
|
5362
5380
|
console.log("");
|
|
5363
5381
|
};
|
|
5364
5382
|
|
|
5383
|
+
// src/lib/backtest/observeRun.ts
|
|
5384
|
+
var import_constants6 = require("@tradejs/core/constants");
|
|
5385
|
+
var import_redis5 = require("@tradejs/infra/redis");
|
|
5386
|
+
var import_logger = require("@tradejs/infra/logger");
|
|
5387
|
+
var HEARTBEAT_MS = 2e3;
|
|
5388
|
+
var ACTIVE_TTL_SECONDS = 30;
|
|
5389
|
+
var LINKED_RUN_TTL_SECONDS = 30 * 24 * import_constants6.TTL_1H;
|
|
5390
|
+
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}$/;
|
|
5391
|
+
var MAX_VALUES_PER_PARAMETER = 12;
|
|
5392
|
+
var MAX_VALUE_LENGTH = 500;
|
|
5393
|
+
var summarizeBacktestParameters = (tests) => {
|
|
5394
|
+
const parameters = /* @__PURE__ */ new Map();
|
|
5395
|
+
for (const test of tests) {
|
|
5396
|
+
for (const [name, value] of Object.entries(test.strategyConfig)) {
|
|
5397
|
+
const serialized = JSON.stringify(value);
|
|
5398
|
+
if (serialized === void 0) continue;
|
|
5399
|
+
const parameter = parameters.get(name) ?? {
|
|
5400
|
+
values: /* @__PURE__ */ new Set(),
|
|
5401
|
+
truncated: false
|
|
5402
|
+
};
|
|
5403
|
+
parameters.set(name, parameter);
|
|
5404
|
+
if (parameter.values.has(serialized)) continue;
|
|
5405
|
+
if (parameter.values.size === MAX_VALUES_PER_PARAMETER || serialized.length > MAX_VALUE_LENGTH) {
|
|
5406
|
+
parameter.truncated = true;
|
|
5407
|
+
} else {
|
|
5408
|
+
parameter.values.add(serialized);
|
|
5409
|
+
}
|
|
5410
|
+
}
|
|
5411
|
+
}
|
|
5412
|
+
return [...parameters].map(([name, { values, truncated }]) => ({
|
|
5413
|
+
name,
|
|
5414
|
+
values: [...values],
|
|
5415
|
+
truncated
|
|
5416
|
+
}));
|
|
5417
|
+
};
|
|
5418
|
+
var observeBacktestRun = async (manifest, initialCompleted, parallel) => {
|
|
5419
|
+
if (process.env.TRADEJS_BACKTEST_WEB_JOB === "1") return;
|
|
5420
|
+
const researchStudy = process.env.TRADEJS_RESEARCH_STUDY?.trim();
|
|
5421
|
+
const linkedStudy = researchStudy && RESEARCH_STUDY.test(researchStudy) ? researchStudy : void 0;
|
|
5422
|
+
if (researchStudy && !linkedStudy) {
|
|
5423
|
+
import_logger.logger.warn(
|
|
5424
|
+
"invalid TRADEJS_RESEARCH_STUDY; expected Strategy/YYYY-MM-DD-slug"
|
|
5425
|
+
);
|
|
5426
|
+
}
|
|
5427
|
+
const { testSuite } = manifest;
|
|
5428
|
+
const firstTest = testSuite[0];
|
|
5429
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
5430
|
+
const run = {
|
|
5431
|
+
id: manifest.runId,
|
|
5432
|
+
...linkedStudy && { researchStudy: linkedStudy },
|
|
5433
|
+
userName: manifest.userName,
|
|
5434
|
+
strategyName: firstTest.strategyName,
|
|
5435
|
+
configId: manifest.config,
|
|
5436
|
+
connector: manifest.connectorName,
|
|
5437
|
+
interval: manifest.interval,
|
|
5438
|
+
startTime: manifest.window.start,
|
|
5439
|
+
endTime: manifest.window.end,
|
|
5440
|
+
symbols: [...new Set(testSuite.map((test) => test.symbol))],
|
|
5441
|
+
settings: {
|
|
5442
|
+
...manifest.flags,
|
|
5443
|
+
parallel,
|
|
5444
|
+
...firstTest.executionCosts && {
|
|
5445
|
+
executionCosts: JSON.stringify(firstTest.executionCosts)
|
|
5446
|
+
}
|
|
5447
|
+
},
|
|
5448
|
+
parameters: summarizeBacktestParameters(testSuite),
|
|
5449
|
+
status: "running",
|
|
5450
|
+
completed: initialCompleted,
|
|
5451
|
+
total: testSuite.length,
|
|
5452
|
+
startedAt,
|
|
5453
|
+
updatedAt: startedAt
|
|
5454
|
+
};
|
|
5455
|
+
const save = async (expire) => {
|
|
5456
|
+
run.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
5457
|
+
try {
|
|
5458
|
+
await import_redis5.cliBacktestRunStorage.put(run, expire);
|
|
5459
|
+
} catch (error) {
|
|
5460
|
+
import_logger.logger.warn("failed to publish CLI backtest progress: %s", String(error));
|
|
5461
|
+
}
|
|
5462
|
+
};
|
|
5463
|
+
await save(ACTIVE_TTL_SECONDS);
|
|
5464
|
+
let pending;
|
|
5465
|
+
const timer = setInterval(() => {
|
|
5466
|
+
pending ??= save(ACTIVE_TTL_SECONDS).finally(() => {
|
|
5467
|
+
pending = void 0;
|
|
5468
|
+
});
|
|
5469
|
+
}, HEARTBEAT_MS).unref();
|
|
5470
|
+
return {
|
|
5471
|
+
progress: (completed) => {
|
|
5472
|
+
run.completed = completed;
|
|
5473
|
+
},
|
|
5474
|
+
finish: async (status) => {
|
|
5475
|
+
clearInterval(timer);
|
|
5476
|
+
await pending;
|
|
5477
|
+
run.status = status;
|
|
5478
|
+
await save(linkedStudy ? LINKED_RUN_TTL_SECONDS : import_constants6.TTL_1H);
|
|
5479
|
+
}
|
|
5480
|
+
};
|
|
5481
|
+
};
|
|
5482
|
+
|
|
5365
5483
|
// src/scripts/backtest.ts
|
|
5366
5484
|
if (process.argv.some(
|
|
5367
5485
|
(arg) => arg === "--live" || String(arg).startsWith("--live=")
|
|
@@ -5497,8 +5615,8 @@ var loadBacktestConfig = async () => {
|
|
|
5497
5615
|
if (!strategyName) {
|
|
5498
5616
|
throw new Error("Strategy name not found");
|
|
5499
5617
|
}
|
|
5500
|
-
const backtestConfig = await (0,
|
|
5501
|
-
|
|
5618
|
+
const backtestConfig = await (0, import_redis6.getData)(
|
|
5619
|
+
import_redis6.redisKeys.backtestConfig(userName, flags.config),
|
|
5502
5620
|
null
|
|
5503
5621
|
);
|
|
5504
5622
|
if (!backtestConfig) {
|
|
@@ -5645,8 +5763,8 @@ var finishBacktest = async (testSuite) => {
|
|
|
5645
5763
|
console.log(import_chalk10.default.gray(`full report: ${markdownReportPath}`));
|
|
5646
5764
|
console.log("");
|
|
5647
5765
|
if (!isFastMode || flags.persistResults) {
|
|
5648
|
-
await (0,
|
|
5649
|
-
|
|
5766
|
+
await (0, import_redis6.setData)(
|
|
5767
|
+
import_redis6.redisKeys.backtestResults(userName, flags.config, timestamp),
|
|
5650
5768
|
{
|
|
5651
5769
|
config: flags.config,
|
|
5652
5770
|
mode: "config",
|
|
@@ -5666,11 +5784,10 @@ var finishBacktest = async (testSuite) => {
|
|
|
5666
5784
|
errorTests: errorTests2
|
|
5667
5785
|
},
|
|
5668
5786
|
{
|
|
5669
|
-
expire:
|
|
5787
|
+
expire: import_constants7.TTL_1M
|
|
5670
5788
|
}
|
|
5671
5789
|
);
|
|
5672
5790
|
}
|
|
5673
|
-
process.exit();
|
|
5674
5791
|
};
|
|
5675
5792
|
var restoreCompletedBacktestResults = (completed) => {
|
|
5676
5793
|
for (const { result } of completed) {
|
|
@@ -5751,6 +5868,56 @@ var prepareContinuedBacktestMarketContext = async ({
|
|
|
5751
5868
|
log: (message) => console.log(import_chalk10.default.gray(message))
|
|
5752
5869
|
});
|
|
5753
5870
|
};
|
|
5871
|
+
var runBacktestSuite = async (manifest, testSuite, initialCompletedTests = 0) => {
|
|
5872
|
+
const observation = await observeBacktestRun(
|
|
5873
|
+
manifest,
|
|
5874
|
+
initialCompletedTests,
|
|
5875
|
+
effectiveParallel
|
|
5876
|
+
);
|
|
5877
|
+
try {
|
|
5878
|
+
await executeTestSuite({
|
|
5879
|
+
testSuite,
|
|
5880
|
+
window: manifest.window,
|
|
5881
|
+
preloadStart: manifest.preloadStart,
|
|
5882
|
+
backtestRunId: manifest.runId,
|
|
5883
|
+
initialCompletedTests,
|
|
5884
|
+
totalTests: manifest.testSuite.length,
|
|
5885
|
+
onProgress: observation?.progress,
|
|
5886
|
+
onIncomplete: async () => {
|
|
5887
|
+
await observation?.finish("failed");
|
|
5888
|
+
await markBacktestRunStatus({ run: manifest, status: "interrupted" });
|
|
5889
|
+
process.exit(1);
|
|
5890
|
+
},
|
|
5891
|
+
onResult: async (result) => {
|
|
5892
|
+
await saveBacktestCheckpointResult({
|
|
5893
|
+
result,
|
|
5894
|
+
runId: manifest.runId,
|
|
5895
|
+
userName
|
|
5896
|
+
});
|
|
5897
|
+
trackTopResult(result);
|
|
5898
|
+
updateBestTickerResult(result);
|
|
5899
|
+
},
|
|
5900
|
+
onInterrupt: async () => {
|
|
5901
|
+
await observation?.finish("cancelled");
|
|
5902
|
+
await markBacktestRunStatus({ run: manifest, status: "interrupted" });
|
|
5903
|
+
},
|
|
5904
|
+
onFinish: async () => {
|
|
5905
|
+
try {
|
|
5906
|
+
await markBacktestRunStatus({ run: manifest, status: "completed" });
|
|
5907
|
+
await finishBacktest(manifest.testSuite);
|
|
5908
|
+
await observation?.finish("completed");
|
|
5909
|
+
process.exit();
|
|
5910
|
+
} catch (error) {
|
|
5911
|
+
await observation?.finish("failed");
|
|
5912
|
+
throw error;
|
|
5913
|
+
}
|
|
5914
|
+
}
|
|
5915
|
+
});
|
|
5916
|
+
} catch (error) {
|
|
5917
|
+
await observation?.finish("failed");
|
|
5918
|
+
throw error;
|
|
5919
|
+
}
|
|
5920
|
+
};
|
|
5754
5921
|
var backtest = async () => {
|
|
5755
5922
|
resetRunState();
|
|
5756
5923
|
const config = await loadBacktestConfig();
|
|
@@ -5765,33 +5932,10 @@ var backtest = async () => {
|
|
|
5765
5932
|
if (!remainingSuite.length) {
|
|
5766
5933
|
await markBacktestRunStatus({ run: manifest2, status: "completed" });
|
|
5767
5934
|
await finishBacktest(manifest2.testSuite);
|
|
5768
|
-
|
|
5935
|
+
process.exit();
|
|
5769
5936
|
}
|
|
5770
5937
|
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
|
-
});
|
|
5938
|
+
await runBacktestSuite(manifest2, remainingSuite, completed.length);
|
|
5795
5939
|
return;
|
|
5796
5940
|
}
|
|
5797
5941
|
const preparedRun = await prepareRunEnvironment2(config.strategyName);
|
|
@@ -5852,28 +5996,7 @@ var backtest = async () => {
|
|
|
5852
5996
|
testSuite
|
|
5853
5997
|
});
|
|
5854
5998
|
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
|
-
});
|
|
5999
|
+
await runBacktestSuite(manifest, testSuite);
|
|
5877
6000
|
};
|
|
5878
6001
|
var main = backtest;
|
|
5879
6002
|
// 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)();
|