@tradejs/cli 2.0.16 → 2.0.18
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 +271 -68
- package/dist/lib/hyperliquidWhaleBackfill.js +37 -1
- package/dist/lib/marketContextPrepare.js +27 -1
- package/dist/lib/runtimeEvidenceArtifacts.js +13 -1
- package/dist/scripts/backtest.js +53 -3
- package/dist/scripts/hyperliquidWhaleBackfill.js +27 -1
- package/dist/scripts/hyperliquidWhalesUpdate.js +1 -0
- package/dist/scripts/replay.js +189 -30
- package/dist/scripts/replayRunner.js +189 -30
- package/dist/scripts/runtimeEvidence.js +13 -1
- package/dist/scripts/runtimeParity.js +27 -1
- package/dist/scripts/signals.js +29 -3
- package/dist/scripts/signalsDaemon.js +29 -3
- package/package.json +9 -9
|
@@ -4352,27 +4352,27 @@ var createCoinMarketCapFetchStats = () => ({
|
|
|
4352
4352
|
totalCredits: 0,
|
|
4353
4353
|
byPath: /* @__PURE__ */ new Map()
|
|
4354
4354
|
});
|
|
4355
|
-
var getCoinMarketCapPathLabel = (
|
|
4356
|
-
if (
|
|
4357
|
-
if (
|
|
4358
|
-
if (
|
|
4359
|
-
if (
|
|
4360
|
-
if (
|
|
4361
|
-
if (
|
|
4362
|
-
return
|
|
4363
|
-
};
|
|
4364
|
-
var recordCoinMarketCapFetchStats = (stats,
|
|
4355
|
+
var getCoinMarketCapPathLabel = (path4) => {
|
|
4356
|
+
if (path4.includes("global-metrics")) return "global";
|
|
4357
|
+
if (path4.includes("cryptocurrency/quotes")) return "reference";
|
|
4358
|
+
if (path4.includes("exchange/quotes")) return "exchangeLiquidity";
|
|
4359
|
+
if (path4.includes("fear-and-greed")) return "fearGreed";
|
|
4360
|
+
if (path4.includes("cmc100")) return "cmc100";
|
|
4361
|
+
if (path4.includes("cmc20")) return "cmc20";
|
|
4362
|
+
return path4;
|
|
4363
|
+
};
|
|
4364
|
+
var recordCoinMarketCapFetchStats = (stats, path4, creditCount) => {
|
|
4365
4365
|
if (!stats) return;
|
|
4366
|
-
const existing = stats.byPath.get(
|
|
4366
|
+
const existing = stats.byPath.get(path4) ?? { requests: 0, credits: 0 };
|
|
4367
4367
|
existing.requests += 1;
|
|
4368
4368
|
existing.credits += creditCount ?? 0;
|
|
4369
4369
|
stats.requests += 1;
|
|
4370
4370
|
stats.totalCredits += creditCount ?? 0;
|
|
4371
|
-
stats.byPath.set(
|
|
4371
|
+
stats.byPath.set(path4, existing);
|
|
4372
4372
|
};
|
|
4373
4373
|
var formatCoinMarketCapFetchStats = (stats) => {
|
|
4374
4374
|
const byPath = [...stats.byPath.entries()].map(
|
|
4375
|
-
([
|
|
4375
|
+
([path4, item]) => `${getCoinMarketCapPathLabel(path4)}=${item.requests}req/${item.credits}cr`
|
|
4376
4376
|
).join(" ");
|
|
4377
4377
|
return `apiRequests=${stats.requests} apiCredits=${stats.totalCredits}${byPath ? ` ${byPath}` : ""}`;
|
|
4378
4378
|
};
|
|
@@ -5186,6 +5186,7 @@ var backfillCoinMarketCapContextForReplay = backfillCoinMarketCapContext;
|
|
|
5186
5186
|
var backfillCoinMarketCapContextForSignals = (params) => backfillCoinMarketCapContext({ ...params, refreshStaleFearGreed: true });
|
|
5187
5187
|
|
|
5188
5188
|
// src/lib/hyperliquidWhaleBackfill.ts
|
|
5189
|
+
var import_progress3 = __toESM(require("progress"));
|
|
5189
5190
|
var import_timescale4 = require("@tradejs/infra/timescale");
|
|
5190
5191
|
var import_strategies2 = require("@tradejs/node/strategies");
|
|
5191
5192
|
|
|
@@ -5560,11 +5561,36 @@ var backfillHyperliquidWhaleContext = async (params) => {
|
|
|
5560
5561
|
toMs,
|
|
5561
5562
|
...identity
|
|
5562
5563
|
});
|
|
5564
|
+
const totalCoverageBuckets = Math.ceil(
|
|
5565
|
+
(toMs - fromMs) / HYPERLIQUID_WHALE_BUCKET_MS
|
|
5566
|
+
);
|
|
5567
|
+
const coverageBar = new import_progress3.default(
|
|
5568
|
+
"Hyperliquid coverage :current/:total [:bar][:percent] :eta(s) rows=:rows chunk=:chunk",
|
|
5569
|
+
{
|
|
5570
|
+
total: Math.max(1, totalCoverageBuckets),
|
|
5571
|
+
width: 24
|
|
5572
|
+
}
|
|
5573
|
+
);
|
|
5574
|
+
let displayedCoverageBuckets = 0;
|
|
5563
5575
|
const coverageBuckets = await (0, import_timescale4.rebuildHyperliquidWhaleCoverageRows)({
|
|
5564
5576
|
fromMs,
|
|
5565
5577
|
toMs,
|
|
5566
5578
|
expectedWhales: whales.addresses.length,
|
|
5567
|
-
...identity
|
|
5579
|
+
...identity,
|
|
5580
|
+
onProgress: (progress) => {
|
|
5581
|
+
const next = Math.max(
|
|
5582
|
+
displayedCoverageBuckets,
|
|
5583
|
+
Math.min(progress.completedBuckets, coverageBar.total)
|
|
5584
|
+
);
|
|
5585
|
+
const delta = next - displayedCoverageBuckets;
|
|
5586
|
+
if (delta > 0) {
|
|
5587
|
+
coverageBar.tick(delta, {
|
|
5588
|
+
rows: progress.rows,
|
|
5589
|
+
chunk: `${progress.chunkIndex}/${progress.totalChunks}`
|
|
5590
|
+
});
|
|
5591
|
+
displayedCoverageBuckets = next;
|
|
5592
|
+
}
|
|
5593
|
+
}
|
|
5568
5594
|
});
|
|
5569
5595
|
const result = {
|
|
5570
5596
|
cached: false,
|
|
@@ -5926,6 +5952,10 @@ import_args.default.option(["f", "timeframe"], "Timeframe", 15);
|
|
|
5926
5952
|
import_args.default.option(["d", "days"], "Run replay only for the last N days");
|
|
5927
5953
|
import_args.default.option("startTime", "Explicit replay start timestamp (ms or seconds)");
|
|
5928
5954
|
import_args.default.option("endTime", "Explicit replay end timestamp (ms or seconds)");
|
|
5955
|
+
import_args.default.option(
|
|
5956
|
+
"runtimeEvidence",
|
|
5957
|
+
"Immutable runtime evidence JSON used for offline runtime comparison"
|
|
5958
|
+
);
|
|
5929
5959
|
import_args.default.option(["u", "updateOnly"], "Only update tickers history", false);
|
|
5930
5960
|
import_args.default.option(["C", "cacheOnly"], "Do not update tickers history", false);
|
|
5931
5961
|
import_args.default.option(
|
|
@@ -5951,6 +5981,7 @@ var replayFlags = import_args.default.parse(replayNormalizedArgv);
|
|
|
5951
5981
|
var replayInterval = String(replayFlags.timeframe ?? 15);
|
|
5952
5982
|
var replayUserName = String(replayFlags.user ?? "root");
|
|
5953
5983
|
var replayProjectRoot = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
|
|
5984
|
+
var replayRuntimeEvidencePath = typeof replayFlags.runtimeEvidence === "string" && replayFlags.runtimeEvidence.trim() ? replayFlags.runtimeEvidence.trim() : null;
|
|
5954
5985
|
var isReplayUpdateOnlyRun = Boolean(replayFlags.updateOnly);
|
|
5955
5986
|
|
|
5956
5987
|
// src/lib/replay/support.ts
|
|
@@ -6062,7 +6093,7 @@ var compactReplaySignal = (signal) => {
|
|
|
6062
6093
|
|
|
6063
6094
|
// src/lib/replay/historicalSignalsReplay.ts
|
|
6064
6095
|
var import_chalk9 = __toESM(require("chalk"));
|
|
6065
|
-
var
|
|
6096
|
+
var import_progress4 = __toESM(require("progress"));
|
|
6066
6097
|
var import_backtest = require("@tradejs/core/backtest");
|
|
6067
6098
|
var import_strategies4 = require("@tradejs/core/strategies");
|
|
6068
6099
|
var import_time3 = require("@tradejs/core/time");
|
|
@@ -6946,7 +6977,7 @@ var runHistoricalSignalsReplay = async ({
|
|
|
6946
6977
|
const sharedReplayKeyPrefixes = [];
|
|
6947
6978
|
let preparedSymbols = 0;
|
|
6948
6979
|
let skippedSymbols = 0;
|
|
6949
|
-
const prepareBar = new
|
|
6980
|
+
const prepareBar = new import_progress4.default(
|
|
6950
6981
|
"prepare :current/:total [:bar][:percent] skipped=:skipped :etas(s) :symbol",
|
|
6951
6982
|
{
|
|
6952
6983
|
total: preparedRun.tickers.length,
|
|
@@ -7068,7 +7099,7 @@ var runHistoricalSignalsReplay = async ({
|
|
|
7068
7099
|
interval
|
|
7069
7100
|
});
|
|
7070
7101
|
let abortedCycles = 0;
|
|
7071
|
-
const cycleBar = new
|
|
7102
|
+
const cycleBar = new import_progress4.default(
|
|
7072
7103
|
"cycles :current/:total [:bar][:percent] sig=:signals abort=:aborted :etas(s) :ts",
|
|
7073
7104
|
{
|
|
7074
7105
|
total: orderedTimestamps.length,
|
|
@@ -8783,6 +8814,114 @@ var buildReplayExchangeComparisonDetails = ({
|
|
|
8783
8814
|
};
|
|
8784
8815
|
};
|
|
8785
8816
|
|
|
8817
|
+
// src/lib/replay/runtimeEvidenceSource.ts
|
|
8818
|
+
var import_promises2 = __toESM(require("fs/promises"));
|
|
8819
|
+
var import_node_path2 = __toESM(require("path"));
|
|
8820
|
+
var asRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
8821
|
+
var asFiniteNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
8822
|
+
var unwrapRows = (value, field) => (Array.isArray(value) ? value : []).map((item) => {
|
|
8823
|
+
const row = asRecord(item);
|
|
8824
|
+
return asRecord(row?.[field]) ?? row;
|
|
8825
|
+
}).filter((item) => item != null);
|
|
8826
|
+
var buildRuntimeEvidenceLineageScopes = ({
|
|
8827
|
+
signals,
|
|
8828
|
+
evaluations
|
|
8829
|
+
}) => {
|
|
8830
|
+
const scopes = /* @__PURE__ */ new Map();
|
|
8831
|
+
const add = ({
|
|
8832
|
+
strategy,
|
|
8833
|
+
symbol,
|
|
8834
|
+
runtimeConfigId,
|
|
8835
|
+
timestamp,
|
|
8836
|
+
lineage
|
|
8837
|
+
}) => {
|
|
8838
|
+
if (!lineage || !Number.isFinite(timestamp)) {
|
|
8839
|
+
return;
|
|
8840
|
+
}
|
|
8841
|
+
const key = `${strategy}::${symbol}::${runtimeLineageKey(lineage)}`;
|
|
8842
|
+
const existing = scopes.get(key);
|
|
8843
|
+
scopes.set(key, {
|
|
8844
|
+
strategy,
|
|
8845
|
+
symbol,
|
|
8846
|
+
...runtimeConfigId ? { runtimeConfigId } : {},
|
|
8847
|
+
lineage,
|
|
8848
|
+
firstTimestamp: existing ? Math.min(existing.firstTimestamp, timestamp) : timestamp,
|
|
8849
|
+
lastTimestamp: existing ? Math.max(existing.lastTimestamp, timestamp) : timestamp
|
|
8850
|
+
});
|
|
8851
|
+
};
|
|
8852
|
+
for (const signal of signals) {
|
|
8853
|
+
add({
|
|
8854
|
+
strategy: signal.strategy,
|
|
8855
|
+
symbol: signal.symbol,
|
|
8856
|
+
runtimeConfigId: signal.runtimeConfigId,
|
|
8857
|
+
timestamp: signal.timestamp,
|
|
8858
|
+
lineage: signal.runtimeLineage
|
|
8859
|
+
});
|
|
8860
|
+
}
|
|
8861
|
+
for (const evaluation of evaluations) {
|
|
8862
|
+
add({
|
|
8863
|
+
strategy: evaluation.strategy,
|
|
8864
|
+
symbol: evaluation.symbol,
|
|
8865
|
+
runtimeConfigId: evaluation.runtimeConfigId,
|
|
8866
|
+
timestamp: evaluation.timestamp,
|
|
8867
|
+
lineage: evaluation.runtimeLineage
|
|
8868
|
+
});
|
|
8869
|
+
}
|
|
8870
|
+
return [...scopes.values()].sort(
|
|
8871
|
+
(left, right) => left.strategy.localeCompare(right.strategy) || left.symbol.localeCompare(right.symbol) || left.firstTimestamp - right.firstTimestamp
|
|
8872
|
+
);
|
|
8873
|
+
};
|
|
8874
|
+
var loadReplayRuntimeEvidenceSource = async ({
|
|
8875
|
+
filePath,
|
|
8876
|
+
projectRoot,
|
|
8877
|
+
expectedUserName,
|
|
8878
|
+
expectedWindow
|
|
8879
|
+
}) => {
|
|
8880
|
+
const resolvedPath = import_node_path2.default.resolve(projectRoot, filePath);
|
|
8881
|
+
const root = asRecord(
|
|
8882
|
+
JSON.parse(await import_promises2.default.readFile(resolvedPath, "utf8"))
|
|
8883
|
+
);
|
|
8884
|
+
const runtime = asRecord(root?.runtime) ?? root;
|
|
8885
|
+
if (!root || !runtime) {
|
|
8886
|
+
throw new Error(`Invalid runtime evidence JSON: ${resolvedPath}`);
|
|
8887
|
+
}
|
|
8888
|
+
const rootWindow = asRecord(root.window);
|
|
8889
|
+
const runtimeWindow = asRecord(runtime.window);
|
|
8890
|
+
const startTime = asFiniteNumber(rootWindow?.startTime) ?? asFiniteNumber(runtimeWindow?.startTime);
|
|
8891
|
+
const endTime = asFiniteNumber(rootWindow?.endTime) ?? asFiniteNumber(runtimeWindow?.endTime);
|
|
8892
|
+
const userName = String(root.userName ?? runtime.userName ?? "").trim();
|
|
8893
|
+
if (!userName || userName !== expectedUserName) {
|
|
8894
|
+
throw new Error(
|
|
8895
|
+
`Runtime evidence user mismatch: expected=${expectedUserName}, actual=${userName || "missing"}`
|
|
8896
|
+
);
|
|
8897
|
+
}
|
|
8898
|
+
const endTimeMatches = endTime === expectedWindow.end || endTime === expectedWindow.end + 1;
|
|
8899
|
+
if (startTime !== expectedWindow.start || !endTimeMatches) {
|
|
8900
|
+
throw new Error(
|
|
8901
|
+
`Runtime evidence window mismatch: expected=${expectedWindow.start}..${expectedWindow.end}, actual=${startTime ?? "missing"}..${endTime ?? "missing"}`
|
|
8902
|
+
);
|
|
8903
|
+
}
|
|
8904
|
+
const trades = unwrapRows(runtime.trades, "trade");
|
|
8905
|
+
const signals = unwrapRows(runtime.signals, "signal");
|
|
8906
|
+
const evaluations = unwrapRows(
|
|
8907
|
+
runtime.evaluations,
|
|
8908
|
+
"evaluation"
|
|
8909
|
+
);
|
|
8910
|
+
return {
|
|
8911
|
+
path: resolvedPath,
|
|
8912
|
+
userName,
|
|
8913
|
+
startTime,
|
|
8914
|
+
endTime,
|
|
8915
|
+
trades,
|
|
8916
|
+
signals,
|
|
8917
|
+
evaluations,
|
|
8918
|
+
lineageScopes: buildRuntimeEvidenceLineageScopes({
|
|
8919
|
+
signals,
|
|
8920
|
+
evaluations
|
|
8921
|
+
})
|
|
8922
|
+
};
|
|
8923
|
+
};
|
|
8924
|
+
|
|
8786
8925
|
// src/lib/replay/runtimeComparison.ts
|
|
8787
8926
|
var getReplayEntryTimestampCompareOffsetMs = () => {
|
|
8788
8927
|
const intervalMinutes = Number(replayInterval);
|
|
@@ -9552,7 +9691,8 @@ var saveAndPrintReplayRuntimeComparison = async ({
|
|
|
9552
9691
|
liveStrategySummaries,
|
|
9553
9692
|
backtestEntries,
|
|
9554
9693
|
replaySignals,
|
|
9555
|
-
replayLineages
|
|
9694
|
+
replayLineages,
|
|
9695
|
+
runtimeEvidencePath
|
|
9556
9696
|
}) => {
|
|
9557
9697
|
const { connector, connectorName, window: window2 } = getRuntimeCompareContext();
|
|
9558
9698
|
if (!connector || !window2) {
|
|
@@ -9562,12 +9702,23 @@ var saveAndPrintReplayRuntimeComparison = async ({
|
|
|
9562
9702
|
liveStrategySummaries.map((summary) => summary.strategyName)
|
|
9563
9703
|
);
|
|
9564
9704
|
const replaySignalEvaluations = buildReplaySignalEvaluations(replaySignals);
|
|
9705
|
+
const runtimeEvidence = runtimeEvidencePath ? await loadReplayRuntimeEvidenceSource({
|
|
9706
|
+
filePath: runtimeEvidencePath,
|
|
9707
|
+
projectRoot: replayProjectRoot,
|
|
9708
|
+
expectedUserName: replayUserName,
|
|
9709
|
+
expectedWindow: window2
|
|
9710
|
+
}) : null;
|
|
9565
9711
|
const [
|
|
9566
9712
|
rawRuntimeTrades,
|
|
9567
9713
|
runtimeSignals,
|
|
9568
9714
|
runtimeSignalEvaluations,
|
|
9569
9715
|
runtimeLineageScopes
|
|
9570
|
-
] =
|
|
9716
|
+
] = runtimeEvidence ? [
|
|
9717
|
+
runtimeEvidence.trades,
|
|
9718
|
+
runtimeEvidence.signals,
|
|
9719
|
+
runtimeEvidence.evaluations,
|
|
9720
|
+
runtimeEvidence.lineageScopes
|
|
9721
|
+
] : await Promise.all([
|
|
9571
9722
|
loadRuntimeTrades(replayUserName, {
|
|
9572
9723
|
startTime: window2.start,
|
|
9573
9724
|
endTime: window2.end
|
|
@@ -9585,7 +9736,14 @@ var saveAndPrintReplayRuntimeComparison = async ({
|
|
|
9585
9736
|
endTime: window2.end
|
|
9586
9737
|
})
|
|
9587
9738
|
]);
|
|
9588
|
-
|
|
9739
|
+
if (runtimeEvidence) {
|
|
9740
|
+
console.log(
|
|
9741
|
+
import_chalk11.default.gray(
|
|
9742
|
+
`runtime compare: using immutable evidence ${runtimeEvidence.path}`
|
|
9743
|
+
)
|
|
9744
|
+
);
|
|
9745
|
+
}
|
|
9746
|
+
const syncedRuntimeTrades = runtimeEvidence ? rawRuntimeTrades : await syncRuntimeTrades({
|
|
9589
9747
|
userName: replayUserName,
|
|
9590
9748
|
connector,
|
|
9591
9749
|
trades: rawRuntimeTrades,
|
|
@@ -9636,7 +9794,7 @@ var saveAndPrintReplayRuntimeComparison = async ({
|
|
|
9636
9794
|
const windowRuntimeTrades = comparable.runtimeTrades.filter(
|
|
9637
9795
|
(trade) => trade.entryTimestamp >= window2.start && trade.entryTimestamp < window2.end && relevantStrategies.has(trade.strategy)
|
|
9638
9796
|
);
|
|
9639
|
-
if (!windowRuntimeTrades.length) {
|
|
9797
|
+
if (!windowRuntimeTrades.length && !runtimeEvidence) {
|
|
9640
9798
|
console.log("");
|
|
9641
9799
|
console.log(
|
|
9642
9800
|
import_chalk11.default.yellow(
|
|
@@ -9768,8 +9926,8 @@ var saveAndPrintReplayRuntimeComparison = async ({
|
|
|
9768
9926
|
};
|
|
9769
9927
|
|
|
9770
9928
|
// src/lib/replay/outputReport.ts
|
|
9771
|
-
var
|
|
9772
|
-
var
|
|
9929
|
+
var import_promises3 = __toESM(require("fs/promises"));
|
|
9930
|
+
var import_node_path3 = __toESM(require("path"));
|
|
9773
9931
|
var import_data = require("@tradejs/core/data");
|
|
9774
9932
|
var formatMsk = (timestamp) => typeof timestamp === "number" && Number.isFinite(timestamp) ? new Intl.DateTimeFormat("ru-RU", {
|
|
9775
9933
|
timeZone: "Europe/Moscow",
|
|
@@ -10073,8 +10231,8 @@ var writeReplayOutputReport = async ({
|
|
|
10073
10231
|
strategySnapshot,
|
|
10074
10232
|
runtimeComparison
|
|
10075
10233
|
}) => {
|
|
10076
|
-
const outputDir =
|
|
10077
|
-
await
|
|
10234
|
+
const outputDir = import_node_path3.default.resolve(projectRoot, "data/replay/output");
|
|
10235
|
+
await import_promises3.default.mkdir(outputDir, { recursive: true });
|
|
10078
10236
|
const perTradeAnalysis = buildPerTradeAnalysis(runtimeComparison);
|
|
10079
10237
|
const report = {
|
|
10080
10238
|
reportType: "replay-output",
|
|
@@ -10109,8 +10267,8 @@ var writeReplayOutputReport = async ({
|
|
|
10109
10267
|
runtimeComparison,
|
|
10110
10268
|
perTradeAnalysis
|
|
10111
10269
|
};
|
|
10112
|
-
const markdownPath =
|
|
10113
|
-
const jsonPath =
|
|
10270
|
+
const markdownPath = import_node_path3.default.join(outputDir, `${timestamp}-replay-report.md`);
|
|
10271
|
+
const jsonPath = import_node_path3.default.join(outputDir, `${timestamp}-replay-report.json`);
|
|
10114
10272
|
const lines = [
|
|
10115
10273
|
"# Replay Report",
|
|
10116
10274
|
"",
|
|
@@ -10176,8 +10334,8 @@ var writeReplayOutputReport = async ({
|
|
|
10176
10334
|
""
|
|
10177
10335
|
];
|
|
10178
10336
|
await Promise.all([
|
|
10179
|
-
|
|
10180
|
-
|
|
10337
|
+
import_promises3.default.writeFile(markdownPath, lines.join("\n"), "utf8"),
|
|
10338
|
+
import_promises3.default.writeFile(jsonPath, `${(0, import_data.toJson)(report, true)}
|
|
10181
10339
|
`, "utf8")
|
|
10182
10340
|
]);
|
|
10183
10341
|
return {
|
|
@@ -10218,7 +10376,8 @@ var finishReplay = async ({
|
|
|
10218
10376
|
liveStrategySummaries: replayStrategySnapshot.summaries,
|
|
10219
10377
|
backtestEntries: replayStrategySnapshot.backtestEntries,
|
|
10220
10378
|
replaySignals: replayResult.signals,
|
|
10221
|
-
replayLineages: replayResult.runtimeLineages
|
|
10379
|
+
replayLineages: replayResult.runtimeLineages,
|
|
10380
|
+
runtimeEvidencePath: replayRuntimeEvidencePath
|
|
10222
10381
|
});
|
|
10223
10382
|
const finishedAt = /* @__PURE__ */ new Date();
|
|
10224
10383
|
const durationSeconds = Number(
|
|
@@ -417,6 +417,17 @@ var RUNTIME_EVIDENCE_PAYLOAD_FILE = "runtime-evidence.json";
|
|
|
417
417
|
var RUNTIME_EVIDENCE_COMPLETE_FILE = ".complete";
|
|
418
418
|
var asRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
419
419
|
var sha256 = (value) => (0, import_node_crypto.createHash)("sha256").update(value).digest("hex");
|
|
420
|
+
var runtimeEvidenceIdentitySha256 = (artifact) => {
|
|
421
|
+
const identityArtifact = { ...artifact };
|
|
422
|
+
delete identityArtifact.generatedAt;
|
|
423
|
+
const runtime = asRecord(identityArtifact.runtime);
|
|
424
|
+
if (runtime) {
|
|
425
|
+
const identityRuntime = { ...runtime };
|
|
426
|
+
delete identityRuntime.generatedAt;
|
|
427
|
+
identityArtifact.runtime = identityRuntime;
|
|
428
|
+
}
|
|
429
|
+
return sha256(JSON.stringify(identityArtifact));
|
|
430
|
+
};
|
|
420
431
|
var isExistingDestinationError = (error) => {
|
|
421
432
|
const code = error.code;
|
|
422
433
|
return code === "EEXIST" || code === "ENOTEMPTY";
|
|
@@ -487,11 +498,12 @@ var publishRuntimeEvidenceBundle = async ({
|
|
|
487
498
|
const payload = `${JSON.stringify(artifact, null, 2)}
|
|
488
499
|
`;
|
|
489
500
|
const payloadSha256 = sha256(payload);
|
|
501
|
+
const identitySha256 = runtimeEvidenceIdentitySha256(artifact);
|
|
490
502
|
const safeDeploymentId = safeSegment(deploymentId, "default");
|
|
491
503
|
const artifactId = [
|
|
492
504
|
compactTimestamp(startTime),
|
|
493
505
|
compactTimestamp(endTime),
|
|
494
|
-
|
|
506
|
+
identitySha256.slice(0, 16)
|
|
495
507
|
].join("_");
|
|
496
508
|
const createdAt = Date.now();
|
|
497
509
|
const manifest = {
|
|
@@ -5188,6 +5188,7 @@ var backfillCoinMarketCapContextForReplay = backfillCoinMarketCapContext;
|
|
|
5188
5188
|
var backfillCoinMarketCapContextForSignals = (params) => backfillCoinMarketCapContext({ ...params, refreshStaleFearGreed: true });
|
|
5189
5189
|
|
|
5190
5190
|
// src/lib/hyperliquidWhaleBackfill.ts
|
|
5191
|
+
var import_progress3 = __toESM(require("progress"));
|
|
5191
5192
|
var import_timescale4 = require("@tradejs/infra/timescale");
|
|
5192
5193
|
var import_strategies2 = require("@tradejs/node/strategies");
|
|
5193
5194
|
|
|
@@ -5562,11 +5563,36 @@ var backfillHyperliquidWhaleContext = async (params) => {
|
|
|
5562
5563
|
toMs,
|
|
5563
5564
|
...identity
|
|
5564
5565
|
});
|
|
5566
|
+
const totalCoverageBuckets = Math.ceil(
|
|
5567
|
+
(toMs - fromMs) / HYPERLIQUID_WHALE_BUCKET_MS
|
|
5568
|
+
);
|
|
5569
|
+
const coverageBar = new import_progress3.default(
|
|
5570
|
+
"Hyperliquid coverage :current/:total [:bar][:percent] :eta(s) rows=:rows chunk=:chunk",
|
|
5571
|
+
{
|
|
5572
|
+
total: Math.max(1, totalCoverageBuckets),
|
|
5573
|
+
width: 24
|
|
5574
|
+
}
|
|
5575
|
+
);
|
|
5576
|
+
let displayedCoverageBuckets = 0;
|
|
5565
5577
|
const coverageBuckets = await (0, import_timescale4.rebuildHyperliquidWhaleCoverageRows)({
|
|
5566
5578
|
fromMs,
|
|
5567
5579
|
toMs,
|
|
5568
5580
|
expectedWhales: whales.addresses.length,
|
|
5569
|
-
...identity
|
|
5581
|
+
...identity,
|
|
5582
|
+
onProgress: (progress) => {
|
|
5583
|
+
const next = Math.max(
|
|
5584
|
+
displayedCoverageBuckets,
|
|
5585
|
+
Math.min(progress.completedBuckets, coverageBar.total)
|
|
5586
|
+
);
|
|
5587
|
+
const delta = next - displayedCoverageBuckets;
|
|
5588
|
+
if (delta > 0) {
|
|
5589
|
+
coverageBar.tick(delta, {
|
|
5590
|
+
rows: progress.rows,
|
|
5591
|
+
chunk: `${progress.chunkIndex}/${progress.totalChunks}`
|
|
5592
|
+
});
|
|
5593
|
+
displayedCoverageBuckets = next;
|
|
5594
|
+
}
|
|
5595
|
+
}
|
|
5570
5596
|
});
|
|
5571
5597
|
const result = {
|
|
5572
5598
|
cached: false,
|
package/dist/scripts/signals.js
CHANGED
|
@@ -1645,7 +1645,7 @@ __export(signals_exports, {
|
|
|
1645
1645
|
module.exports = __toCommonJS(signals_exports);
|
|
1646
1646
|
var import_config = require("dotenv/config");
|
|
1647
1647
|
var import_args = __toESM(require("args"));
|
|
1648
|
-
var
|
|
1648
|
+
var import_progress4 = __toESM(require("progress"));
|
|
1649
1649
|
var import_chalk7 = __toESM(require("chalk"));
|
|
1650
1650
|
var import_connectors6 = require("@tradejs/node/connectors");
|
|
1651
1651
|
var import_cli2 = require("@tradejs/node/cli");
|
|
@@ -4553,6 +4553,7 @@ var backfillCoinMarketCapContextForReplay = backfillCoinMarketCapContext;
|
|
|
4553
4553
|
var backfillCoinMarketCapContextForSignals = (params) => backfillCoinMarketCapContext({ ...params, refreshStaleFearGreed: true });
|
|
4554
4554
|
|
|
4555
4555
|
// src/lib/hyperliquidWhaleBackfill.ts
|
|
4556
|
+
var import_progress3 = __toESM(require("progress"));
|
|
4556
4557
|
var import_timescale4 = require("@tradejs/infra/timescale");
|
|
4557
4558
|
var import_strategies2 = require("@tradejs/node/strategies");
|
|
4558
4559
|
|
|
@@ -4927,11 +4928,36 @@ var backfillHyperliquidWhaleContext = async (params) => {
|
|
|
4927
4928
|
toMs,
|
|
4928
4929
|
...identity
|
|
4929
4930
|
});
|
|
4931
|
+
const totalCoverageBuckets = Math.ceil(
|
|
4932
|
+
(toMs - fromMs) / HYPERLIQUID_WHALE_BUCKET_MS
|
|
4933
|
+
);
|
|
4934
|
+
const coverageBar = new import_progress3.default(
|
|
4935
|
+
"Hyperliquid coverage :current/:total [:bar][:percent] :eta(s) rows=:rows chunk=:chunk",
|
|
4936
|
+
{
|
|
4937
|
+
total: Math.max(1, totalCoverageBuckets),
|
|
4938
|
+
width: 24
|
|
4939
|
+
}
|
|
4940
|
+
);
|
|
4941
|
+
let displayedCoverageBuckets = 0;
|
|
4930
4942
|
const coverageBuckets = await (0, import_timescale4.rebuildHyperliquidWhaleCoverageRows)({
|
|
4931
4943
|
fromMs,
|
|
4932
4944
|
toMs,
|
|
4933
4945
|
expectedWhales: whales.addresses.length,
|
|
4934
|
-
...identity
|
|
4946
|
+
...identity,
|
|
4947
|
+
onProgress: (progress) => {
|
|
4948
|
+
const next = Math.max(
|
|
4949
|
+
displayedCoverageBuckets,
|
|
4950
|
+
Math.min(progress.completedBuckets, coverageBar.total)
|
|
4951
|
+
);
|
|
4952
|
+
const delta = next - displayedCoverageBuckets;
|
|
4953
|
+
if (delta > 0) {
|
|
4954
|
+
coverageBar.tick(delta, {
|
|
4955
|
+
rows: progress.rows,
|
|
4956
|
+
chunk: `${progress.chunkIndex}/${progress.totalChunks}`
|
|
4957
|
+
});
|
|
4958
|
+
displayedCoverageBuckets = next;
|
|
4959
|
+
}
|
|
4960
|
+
}
|
|
4935
4961
|
});
|
|
4936
4962
|
const result = {
|
|
4937
4963
|
cached: false,
|
|
@@ -7029,7 +7055,7 @@ var signals = async (options = {}) => {
|
|
|
7029
7055
|
return;
|
|
7030
7056
|
}
|
|
7031
7057
|
const strategyStats = createStrategySkipStats(runtimeStrategies);
|
|
7032
|
-
const bar = new
|
|
7058
|
+
const bar = new import_progress4.default(
|
|
7033
7059
|
":current/:total [:bar][:percent] :found :eta(s) :symbol",
|
|
7034
7060
|
{
|
|
7035
7061
|
total: tickers.length,
|
|
@@ -1643,7 +1643,7 @@ module.exports = __toCommonJS(signalsDaemon_exports);
|
|
|
1643
1643
|
// src/scripts/signals.ts
|
|
1644
1644
|
var import_config = require("dotenv/config");
|
|
1645
1645
|
var import_args = __toESM(require("args"));
|
|
1646
|
-
var
|
|
1646
|
+
var import_progress4 = __toESM(require("progress"));
|
|
1647
1647
|
var import_chalk7 = __toESM(require("chalk"));
|
|
1648
1648
|
var import_connectors6 = require("@tradejs/node/connectors");
|
|
1649
1649
|
var import_cli2 = require("@tradejs/node/cli");
|
|
@@ -4551,6 +4551,7 @@ var backfillCoinMarketCapContextForReplay = backfillCoinMarketCapContext;
|
|
|
4551
4551
|
var backfillCoinMarketCapContextForSignals = (params) => backfillCoinMarketCapContext({ ...params, refreshStaleFearGreed: true });
|
|
4552
4552
|
|
|
4553
4553
|
// src/lib/hyperliquidWhaleBackfill.ts
|
|
4554
|
+
var import_progress3 = __toESM(require("progress"));
|
|
4554
4555
|
var import_timescale4 = require("@tradejs/infra/timescale");
|
|
4555
4556
|
var import_strategies2 = require("@tradejs/node/strategies");
|
|
4556
4557
|
|
|
@@ -4925,11 +4926,36 @@ var backfillHyperliquidWhaleContext = async (params) => {
|
|
|
4925
4926
|
toMs,
|
|
4926
4927
|
...identity
|
|
4927
4928
|
});
|
|
4929
|
+
const totalCoverageBuckets = Math.ceil(
|
|
4930
|
+
(toMs - fromMs) / HYPERLIQUID_WHALE_BUCKET_MS
|
|
4931
|
+
);
|
|
4932
|
+
const coverageBar = new import_progress3.default(
|
|
4933
|
+
"Hyperliquid coverage :current/:total [:bar][:percent] :eta(s) rows=:rows chunk=:chunk",
|
|
4934
|
+
{
|
|
4935
|
+
total: Math.max(1, totalCoverageBuckets),
|
|
4936
|
+
width: 24
|
|
4937
|
+
}
|
|
4938
|
+
);
|
|
4939
|
+
let displayedCoverageBuckets = 0;
|
|
4928
4940
|
const coverageBuckets = await (0, import_timescale4.rebuildHyperliquidWhaleCoverageRows)({
|
|
4929
4941
|
fromMs,
|
|
4930
4942
|
toMs,
|
|
4931
4943
|
expectedWhales: whales.addresses.length,
|
|
4932
|
-
...identity
|
|
4944
|
+
...identity,
|
|
4945
|
+
onProgress: (progress) => {
|
|
4946
|
+
const next = Math.max(
|
|
4947
|
+
displayedCoverageBuckets,
|
|
4948
|
+
Math.min(progress.completedBuckets, coverageBar.total)
|
|
4949
|
+
);
|
|
4950
|
+
const delta = next - displayedCoverageBuckets;
|
|
4951
|
+
if (delta > 0) {
|
|
4952
|
+
coverageBar.tick(delta, {
|
|
4953
|
+
rows: progress.rows,
|
|
4954
|
+
chunk: `${progress.chunkIndex}/${progress.totalChunks}`
|
|
4955
|
+
});
|
|
4956
|
+
displayedCoverageBuckets = next;
|
|
4957
|
+
}
|
|
4958
|
+
}
|
|
4933
4959
|
});
|
|
4934
4960
|
const result = {
|
|
4935
4961
|
cached: false,
|
|
@@ -7027,7 +7053,7 @@ var signals = async (options = {}) => {
|
|
|
7027
7053
|
return;
|
|
7028
7054
|
}
|
|
7029
7055
|
const strategyStats = createStrategySkipStats(runtimeStrategies);
|
|
7030
|
-
const bar = new
|
|
7056
|
+
const bar = new import_progress4.default(
|
|
7031
7057
|
":current/:total [:bar][:percent] :found :eta(s) :symbol",
|
|
7032
7058
|
{
|
|
7033
7059
|
total: tickers.length,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradejs/cli",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.18",
|
|
4
4
|
"description": "Official CLI for the TradeJS TypeScript framework: infra setup, backtests, signals, bots, and ML workflows.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tradejs",
|
|
@@ -29,14 +29,14 @@
|
|
|
29
29
|
"tradejs": "dist/cli.js"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@tradejs/base": "^2.0.
|
|
33
|
-
"@tradejs/connectors": "^2.0.
|
|
34
|
-
"@tradejs/core": "^2.0.
|
|
35
|
-
"@tradejs/indicators": "^2.0.
|
|
36
|
-
"@tradejs/infra": "^2.0.
|
|
37
|
-
"@tradejs/node": "^2.0.
|
|
38
|
-
"@tradejs/strategies": "^2.0.
|
|
39
|
-
"@tradejs/types": "^2.0.
|
|
32
|
+
"@tradejs/base": "^2.0.18",
|
|
33
|
+
"@tradejs/connectors": "^2.0.18",
|
|
34
|
+
"@tradejs/core": "^2.0.18",
|
|
35
|
+
"@tradejs/indicators": "^2.0.18",
|
|
36
|
+
"@tradejs/infra": "^2.0.18",
|
|
37
|
+
"@tradejs/node": "^2.0.18",
|
|
38
|
+
"@tradejs/strategies": "^2.0.18",
|
|
39
|
+
"@tradejs/types": "^2.0.18",
|
|
40
40
|
"args": "^5.0.3",
|
|
41
41
|
"bcryptjs": "^2.4.3",
|
|
42
42
|
"chalk": "4.1.2",
|