@tradejs/cli 2.0.6 → 2.0.7
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 +2448 -1374
- package/dist/lib/aiExport.js +1822 -0
- package/dist/lib/binanceMarketContextBackfill.js +97 -88
- package/dist/lib/binanceMarketData.js +6 -3
- package/dist/lib/marketContextPrepare.js +97 -88
- package/dist/lib/runEnvironment.js +48 -18
- package/dist/lib/runtimeLineage.js +255 -0
- package/dist/lib/runtimeParityDetails.js +24 -1
- package/dist/lib/runtimeSignalsLoader.js +19 -0
- package/dist/lib/runtimeSignalsStorage.js +3 -0
- package/dist/lib/runtimeTradeSync.js +40 -11
- package/dist/lib/timeWindow.js +44 -16
- package/dist/scripts/aiExport.js +200 -88
- package/dist/scripts/backtest.js +170 -107
- package/dist/scripts/binanceBreadthUniversesUpdate.js +120 -0
- package/dist/scripts/binanceMarketIngest.js +32 -33
- package/dist/scripts/mlExport.js +5 -2
- package/dist/scripts/replay.js +988 -218
- package/dist/scripts/replayRunner.js +988 -218
- package/dist/scripts/replayRuntimeEvidence.js +3 -1
- package/dist/scripts/resolveExportStrategy.js +7 -2
- package/dist/scripts/runtimeParity.js +141 -104
- package/dist/scripts/signals.js +381 -107
- package/dist/scripts/signalsDaemon.js +381 -107
- package/dist/scripts/signalsSummary.js +40 -11
- package/package.json +10 -9
package/dist/scripts/aiExport.js
CHANGED
|
@@ -1641,6 +1641,11 @@ __export(aiExport_exports, {
|
|
|
1641
1641
|
module.exports = __toCommonJS(aiExport_exports);
|
|
1642
1642
|
var import_args = __toESM(require("args"));
|
|
1643
1643
|
var import_chalk2 = __toESM(require("chalk"));
|
|
1644
|
+
var import_promises2 = __toESM(require("fs/promises"));
|
|
1645
|
+
var import_progress = __toESM(require("progress"));
|
|
1646
|
+
var import_ai2 = require("@tradejs/infra/ai");
|
|
1647
|
+
|
|
1648
|
+
// src/lib/aiExport.ts
|
|
1644
1649
|
var import_promises = __toESM(require("fs/promises"));
|
|
1645
1650
|
var import_path = __toESM(require("path"));
|
|
1646
1651
|
var import_ai = require("@tradejs/infra/ai");
|
|
@@ -1684,6 +1689,139 @@ var loadBacktestCheckpointResults = async ({
|
|
|
1684
1689
|
import_redis.redisKeys.backtestRunResults(userName, runId)
|
|
1685
1690
|
);
|
|
1686
1691
|
|
|
1692
|
+
// src/lib/aiExport.ts
|
|
1693
|
+
var resolveRunScopedAiChunks = async ({
|
|
1694
|
+
outDir,
|
|
1695
|
+
requestedRunId,
|
|
1696
|
+
strategyName,
|
|
1697
|
+
userName
|
|
1698
|
+
}) => {
|
|
1699
|
+
const resolvedRunId = String(requestedRunId || "").trim();
|
|
1700
|
+
const runIds = resolvedRunId ? [resolvedRunId] : await (0, import_ai.listAiChunkRunIds)({ strategyName, outDir });
|
|
1701
|
+
const runId = runIds.at(-1) ?? "";
|
|
1702
|
+
if (!runId) {
|
|
1703
|
+
return null;
|
|
1704
|
+
}
|
|
1705
|
+
const chunkFiles = await (0, import_ai.listAiChunkFiles)({ strategyName, outDir, runId });
|
|
1706
|
+
if (!chunkFiles.length) {
|
|
1707
|
+
return {
|
|
1708
|
+
runId,
|
|
1709
|
+
chunkFiles,
|
|
1710
|
+
completedAttemptKeys: /* @__PURE__ */ new Set()
|
|
1711
|
+
};
|
|
1712
|
+
}
|
|
1713
|
+
const completed = await loadBacktestCheckpointResults({ runId, userName });
|
|
1714
|
+
return {
|
|
1715
|
+
runId,
|
|
1716
|
+
chunkFiles,
|
|
1717
|
+
completedAttemptKeys: buildCompletedBacktestDatasetAttemptKeys(completed)
|
|
1718
|
+
};
|
|
1719
|
+
};
|
|
1720
|
+
var exportAiStrategy = async (params) => {
|
|
1721
|
+
const {
|
|
1722
|
+
outDir,
|
|
1723
|
+
strategyName,
|
|
1724
|
+
keepChunks,
|
|
1725
|
+
requestedRunId,
|
|
1726
|
+
userName,
|
|
1727
|
+
now = Date.now
|
|
1728
|
+
} = params;
|
|
1729
|
+
const partMonths = Math.max(0, Math.trunc(Number(params.partMonths) || 0));
|
|
1730
|
+
const runScopedChunks = await resolveRunScopedAiChunks({
|
|
1731
|
+
outDir,
|
|
1732
|
+
requestedRunId,
|
|
1733
|
+
strategyName,
|
|
1734
|
+
userName
|
|
1735
|
+
});
|
|
1736
|
+
const chunkFiles = runScopedChunks ? runScopedChunks.chunkFiles : await (0, import_ai.listAiChunkFiles)({ strategyName, outDir });
|
|
1737
|
+
if (!chunkFiles.length) {
|
|
1738
|
+
return null;
|
|
1739
|
+
}
|
|
1740
|
+
if (runScopedChunks && runScopedChunks.completedAttemptKeys.size === 0) {
|
|
1741
|
+
throw new Error(
|
|
1742
|
+
`No completed checkpoint attempts found for AI export run "${runScopedChunks.runId}"`
|
|
1743
|
+
);
|
|
1744
|
+
}
|
|
1745
|
+
const completedAttemptCount = runScopedChunks?.completedAttemptKeys.size ?? void 0;
|
|
1746
|
+
const mergedPath = import_path.default.join(
|
|
1747
|
+
outDir,
|
|
1748
|
+
`ai-dataset-${(0, import_ai.toFileToken)(strategyName)}-merged-${now()}.jsonl`
|
|
1749
|
+
);
|
|
1750
|
+
await (0, import_ai.mergeAiJsonlFiles)({
|
|
1751
|
+
filePaths: chunkFiles,
|
|
1752
|
+
outPath: mergedPath,
|
|
1753
|
+
shouldIncludeRow: runScopedChunks ? (row) => isBacktestDatasetRowForCompletedAttempt(
|
|
1754
|
+
row,
|
|
1755
|
+
runScopedChunks.completedAttemptKeys
|
|
1756
|
+
) : void 0
|
|
1757
|
+
});
|
|
1758
|
+
runScopedChunks?.completedAttemptKeys.clear();
|
|
1759
|
+
const splitResult = partMonths > 0 ? await (0, import_ai.splitAiMergedDatasetFile)({
|
|
1760
|
+
filePath: mergedPath,
|
|
1761
|
+
monthsPerPart: partMonths
|
|
1762
|
+
}) : {
|
|
1763
|
+
partPaths: [mergedPath],
|
|
1764
|
+
partCount: 1,
|
|
1765
|
+
splitApplied: false
|
|
1766
|
+
};
|
|
1767
|
+
const shouldDeleteChunks = !keepChunks;
|
|
1768
|
+
if (shouldDeleteChunks) {
|
|
1769
|
+
for (const filePath of chunkFiles) {
|
|
1770
|
+
await import_promises.default.rm(filePath, { force: true });
|
|
1771
|
+
}
|
|
1772
|
+
}
|
|
1773
|
+
return {
|
|
1774
|
+
strategyName,
|
|
1775
|
+
sourceChunkCount: chunkFiles.length,
|
|
1776
|
+
deleteChunks: shouldDeleteChunks,
|
|
1777
|
+
partMonths,
|
|
1778
|
+
partPaths: splitResult.partPaths,
|
|
1779
|
+
partCount: splitResult.partCount,
|
|
1780
|
+
splitApplied: splitResult.splitApplied,
|
|
1781
|
+
runId: runScopedChunks?.runId,
|
|
1782
|
+
completedAttemptCount
|
|
1783
|
+
};
|
|
1784
|
+
};
|
|
1785
|
+
var exportAiStrategiesSequentially = async (params, dependencies = {}) => {
|
|
1786
|
+
const { strategyNames, onProgress, ...strategyParams } = params;
|
|
1787
|
+
const runExport = dependencies.exportStrategy ?? exportAiStrategy;
|
|
1788
|
+
const results = [];
|
|
1789
|
+
const total = strategyNames.length;
|
|
1790
|
+
for (let index = 0; index < strategyNames.length; index += 1) {
|
|
1791
|
+
const strategyName = strategyNames[index];
|
|
1792
|
+
onProgress?.({
|
|
1793
|
+
strategyName,
|
|
1794
|
+
current: index,
|
|
1795
|
+
total,
|
|
1796
|
+
status: "started"
|
|
1797
|
+
});
|
|
1798
|
+
try {
|
|
1799
|
+
const result = await runExport({
|
|
1800
|
+
...strategyParams,
|
|
1801
|
+
strategyName
|
|
1802
|
+
});
|
|
1803
|
+
if (result) {
|
|
1804
|
+
results.push(result);
|
|
1805
|
+
}
|
|
1806
|
+
onProgress?.({
|
|
1807
|
+
strategyName,
|
|
1808
|
+
current: index + 1,
|
|
1809
|
+
total,
|
|
1810
|
+
status: result ? "completed" : "skipped"
|
|
1811
|
+
});
|
|
1812
|
+
} catch (error) {
|
|
1813
|
+
onProgress?.({
|
|
1814
|
+
strategyName,
|
|
1815
|
+
current: index,
|
|
1816
|
+
total,
|
|
1817
|
+
status: "failed"
|
|
1818
|
+
});
|
|
1819
|
+
throw error;
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
return results;
|
|
1823
|
+
};
|
|
1824
|
+
|
|
1687
1825
|
// src/scripts/selectStrategy.ts
|
|
1688
1826
|
var import_readline = __toESM(require("readline"));
|
|
1689
1827
|
var import_chalk = __toESM(require("chalk"));
|
|
@@ -1750,12 +1888,14 @@ var selectStrategy = async (promptLabel = "Select strategy", options) => {
|
|
|
1750
1888
|
};
|
|
1751
1889
|
|
|
1752
1890
|
// src/scripts/resolveExportStrategy.ts
|
|
1891
|
+
var ALL_EXPORT_STRATEGIES = "all";
|
|
1753
1892
|
var resolveExportStrategy = async ({
|
|
1754
1893
|
explicitStrategy,
|
|
1755
1894
|
outDir,
|
|
1756
1895
|
datasetLabel,
|
|
1757
1896
|
promptLabel,
|
|
1758
|
-
listStrategies
|
|
1897
|
+
listStrategies,
|
|
1898
|
+
includeAllOption = false
|
|
1759
1899
|
}) => {
|
|
1760
1900
|
const raw = String(explicitStrategy || "").trim();
|
|
1761
1901
|
if (raw) {
|
|
@@ -1773,8 +1913,9 @@ var resolveExportStrategy = async ({
|
|
|
1773
1913
|
`Multiple ${datasetLabel} chunk strategies found in ${outDir}: ${availableStrategies.join(", ")}. Pass --strategy.`
|
|
1774
1914
|
);
|
|
1775
1915
|
}
|
|
1916
|
+
const promptStrategies = includeAllOption ? [...availableStrategies, ALL_EXPORT_STRATEGIES] : availableStrategies;
|
|
1776
1917
|
return selectStrategy(promptLabel, {
|
|
1777
|
-
strategies:
|
|
1918
|
+
strategies: promptStrategies,
|
|
1778
1919
|
defaultStrategy: availableStrategies[0]
|
|
1779
1920
|
});
|
|
1780
1921
|
};
|
|
@@ -1803,110 +1944,81 @@ import_args.default.option(
|
|
|
1803
1944
|
"root"
|
|
1804
1945
|
);
|
|
1805
1946
|
var flags = import_args.default.parse(process.argv);
|
|
1806
|
-
var
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
}
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
runId,
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
};
|
|
1823
|
-
}
|
|
1824
|
-
const userName = String(flags.user || "root");
|
|
1825
|
-
const completed = await loadBacktestCheckpointResults({ runId, userName });
|
|
1826
|
-
return {
|
|
1827
|
-
runId,
|
|
1828
|
-
chunkFiles,
|
|
1829
|
-
completedAttemptKeys: buildCompletedBacktestDatasetAttemptKeys(completed)
|
|
1830
|
-
};
|
|
1947
|
+
var printExportResult = (result) => {
|
|
1948
|
+
console.log(
|
|
1949
|
+
import_chalk2.default.green(
|
|
1950
|
+
result.splitApplied ? `Merged AI dataset for ${result.strategyName} saved as ${result.partCount} part files` : `Merged AI dataset saved: ${result.partPaths[0]}`
|
|
1951
|
+
)
|
|
1952
|
+
);
|
|
1953
|
+
result.partPaths.forEach((filePath, index) => {
|
|
1954
|
+
console.log(import_chalk2.default.gray(`part${index + 1}: ${filePath}`));
|
|
1955
|
+
});
|
|
1956
|
+
console.log(
|
|
1957
|
+
import_chalk2.default.gray(
|
|
1958
|
+
`strategy=${result.strategyName}, source_chunks=${result.sourceChunkCount}, deleteChunks=${Boolean(
|
|
1959
|
+
result.deleteChunks
|
|
1960
|
+
)}, partMonths=${result.partMonths}, partCount=${result.partCount}${result.runId ? `, runId=${result.runId}, completedAttempts=${result.completedAttemptCount}` : ""}`
|
|
1961
|
+
)
|
|
1962
|
+
);
|
|
1831
1963
|
};
|
|
1832
1964
|
var main = async () => {
|
|
1833
1965
|
const outDir = String(flags.outDir || "data/ai/export");
|
|
1834
|
-
await
|
|
1966
|
+
await import_promises2.default.mkdir(outDir, { recursive: true });
|
|
1835
1967
|
const strategyName = await resolveExportStrategy({
|
|
1836
1968
|
explicitStrategy: String(flags.strategy || ""),
|
|
1837
1969
|
outDir,
|
|
1838
1970
|
datasetLabel: "AI",
|
|
1839
1971
|
promptLabel: "Select AI export strategy",
|
|
1840
|
-
listStrategies:
|
|
1972
|
+
listStrategies: import_ai2.listAiChunkStrategies,
|
|
1973
|
+
includeAllOption: true
|
|
1841
1974
|
});
|
|
1842
1975
|
if (!strategyName) {
|
|
1843
1976
|
console.log(import_chalk2.default.yellow(`No AI chunk files found in ${outDir}`));
|
|
1844
|
-
|
|
1977
|
+
return;
|
|
1845
1978
|
}
|
|
1846
|
-
const
|
|
1847
|
-
|
|
1848
|
-
outDir
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1979
|
+
const strategyNames = strategyName === ALL_EXPORT_STRATEGIES ? await (0, import_ai2.listAiChunkStrategies)({ outDir }) : [strategyName];
|
|
1980
|
+
if (!strategyNames.length) {
|
|
1981
|
+
console.log(import_chalk2.default.yellow(`No AI chunk files found in ${outDir}`));
|
|
1982
|
+
return;
|
|
1983
|
+
}
|
|
1984
|
+
const progressBar = strategyNames.length > 1 ? new import_progress.default(":current/:total [:bar] :percent :strategy :status", {
|
|
1985
|
+
total: strategyNames.length,
|
|
1986
|
+
width: 30
|
|
1987
|
+
}) : null;
|
|
1988
|
+
const results = await exportAiStrategiesSequentially({
|
|
1989
|
+
outDir,
|
|
1990
|
+
strategyNames,
|
|
1991
|
+
keepChunks: Boolean(flags.keepChunks),
|
|
1992
|
+
partMonths: Number(flags.partMonths),
|
|
1993
|
+
requestedRunId: typeof flags.runId === "string" ? flags.runId.trim() : void 0,
|
|
1994
|
+
userName: String(flags.user || "root"),
|
|
1995
|
+
onProgress: progressBar ? ({ strategyName: currentStrategy, status }) => {
|
|
1996
|
+
const progressStatus = status === "started" ? "exporting" : status;
|
|
1997
|
+
if (status === "started" || status === "failed") {
|
|
1998
|
+
progressBar.tick(0, {
|
|
1999
|
+
strategy: currentStrategy,
|
|
2000
|
+
status: progressStatus
|
|
2001
|
+
});
|
|
2002
|
+
if (status === "failed") {
|
|
2003
|
+
progressBar.terminate();
|
|
2004
|
+
}
|
|
2005
|
+
return;
|
|
2006
|
+
}
|
|
2007
|
+
progressBar.tick(1, {
|
|
2008
|
+
strategy: currentStrategy,
|
|
2009
|
+
status: progressStatus
|
|
2010
|
+
});
|
|
2011
|
+
} : void 0
|
|
1853
2012
|
});
|
|
1854
|
-
if (!
|
|
2013
|
+
if (!results.length) {
|
|
1855
2014
|
console.log(
|
|
1856
2015
|
import_chalk2.default.yellow(
|
|
1857
|
-
`No chunk files found for strategy "${
|
|
2016
|
+
strategyNames.length === 1 ? `No chunk files found for strategy "${strategyNames[0]}" in ${outDir}` : `No AI chunk files were exported from ${outDir}`
|
|
1858
2017
|
)
|
|
1859
2018
|
);
|
|
1860
|
-
|
|
2019
|
+
return;
|
|
1861
2020
|
}
|
|
1862
|
-
|
|
1863
|
-
throw new Error(
|
|
1864
|
-
`No completed checkpoint attempts found for AI export run "${runScopedChunks.runId}"`
|
|
1865
|
-
);
|
|
1866
|
-
}
|
|
1867
|
-
const mergedPath = import_path.default.join(
|
|
1868
|
-
outDir,
|
|
1869
|
-
`ai-dataset-${(0, import_ai.toFileToken)(strategyName)}-merged-${Date.now()}.jsonl`
|
|
1870
|
-
);
|
|
1871
|
-
await (0, import_ai.mergeAiJsonlFiles)({
|
|
1872
|
-
filePaths: chunkFiles,
|
|
1873
|
-
outPath: mergedPath,
|
|
1874
|
-
shouldIncludeRow: runScopedChunks ? (row) => isBacktestDatasetRowForCompletedAttempt(
|
|
1875
|
-
row,
|
|
1876
|
-
runScopedChunks.completedAttemptKeys
|
|
1877
|
-
) : void 0
|
|
1878
|
-
});
|
|
1879
|
-
const partMonths = Math.max(0, Math.trunc(Number(flags.partMonths) || 0));
|
|
1880
|
-
const splitResult = partMonths > 0 ? await (0, import_ai.splitAiMergedDatasetFile)({
|
|
1881
|
-
filePath: mergedPath,
|
|
1882
|
-
monthsPerPart: partMonths
|
|
1883
|
-
}) : {
|
|
1884
|
-
partPaths: [mergedPath],
|
|
1885
|
-
partCount: 1,
|
|
1886
|
-
splitApplied: false
|
|
1887
|
-
};
|
|
1888
|
-
const shouldDeleteChunks = !Boolean(flags.keepChunks);
|
|
1889
|
-
if (shouldDeleteChunks) {
|
|
1890
|
-
for (const filePath of chunkFiles) {
|
|
1891
|
-
await import_promises.default.rm(filePath, { force: true });
|
|
1892
|
-
}
|
|
1893
|
-
}
|
|
1894
|
-
console.log(
|
|
1895
|
-
import_chalk2.default.green(
|
|
1896
|
-
splitResult.splitApplied ? `Merged AI dataset saved as ${splitResult.partCount} part files` : `Merged AI dataset saved: ${splitResult.partPaths[0]}`
|
|
1897
|
-
)
|
|
1898
|
-
);
|
|
1899
|
-
splitResult.partPaths.forEach((filePath, index) => {
|
|
1900
|
-
console.log(import_chalk2.default.gray(`part${index + 1}: ${filePath}`));
|
|
1901
|
-
});
|
|
1902
|
-
console.log(
|
|
1903
|
-
import_chalk2.default.gray(
|
|
1904
|
-
`strategy=${strategyName}, source_chunks=${chunkFiles.length}, deleteChunks=${Boolean(
|
|
1905
|
-
shouldDeleteChunks
|
|
1906
|
-
)}, partMonths=${partMonths}, partCount=${splitResult.partCount}${runScopedChunks ? `, runId=${runScopedChunks.runId}, completedAttempts=${runScopedChunks.completedAttemptKeys.size}` : ""}`
|
|
1907
|
-
)
|
|
1908
|
-
);
|
|
1909
|
-
process.exit(0);
|
|
2021
|
+
results.forEach(printExportResult);
|
|
1910
2022
|
};
|
|
1911
2023
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1912
2024
|
0 && (module.exports = {
|