@tradejs/cli 2.0.14 → 2.0.16
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 +2916 -978
- package/dist/lib/aiPocketSearch.js +493 -24
- package/dist/lib/aiTrainResearch.js +19 -2
- package/dist/lib/marketContextPrepare.js +85 -8
- package/dist/lib/researchAgent.js +3 -30
- package/dist/lib/runtimeDebugEvidence.js +76 -1
- package/dist/lib/runtimeEvidenceArtifacts.js +255 -0
- package/dist/lib/runtimeEvidenceSync.js +308 -0
- package/dist/lib/runtimeRedis.js +25 -0
- package/dist/lib/runtimeScorecard.js +442 -0
- package/dist/lib/runtimeTradeSync.js +9 -0
- package/dist/scripts/agentRun.js +16 -31
- package/dist/scripts/aiPocketSearch.js +717 -29
- package/dist/scripts/aiTrain.js +32 -2
- package/dist/scripts/backtest.js +83 -8
- package/dist/scripts/replay.js +92 -8
- package/dist/scripts/replayRunner.js +92 -8
- package/dist/scripts/replayRuntimeEvidence.js +68 -161
- package/dist/scripts/runtimeEvidence.js +316 -161
- package/dist/scripts/runtimeEvidenceSync.js +335 -0
- package/dist/scripts/runtimeParity.js +83 -8
- package/dist/scripts/runtimeScorecard.js +731 -0
- package/dist/scripts/signals.js +234 -142
- package/dist/scripts/signalsDaemon.js +234 -142
- package/dist/scripts/signalsSummary.js +9 -0
- package/dist/workers/testerWorker.js +2 -0
- package/package.json +11 -9
|
@@ -1653,112 +1653,8 @@ var import_constants3 = require("@tradejs/core/constants");
|
|
|
1653
1653
|
var import_strategies6 = require("@tradejs/node/strategies");
|
|
1654
1654
|
var import_time3 = require("@tradejs/core/time");
|
|
1655
1655
|
var import_logger4 = require("@tradejs/infra/logger");
|
|
1656
|
-
var import_redis5 = require("@tradejs/infra/redis");
|
|
1657
1656
|
var import_tradingAccounts2 = require("@tradejs/infra/tradingAccounts");
|
|
1658
1657
|
|
|
1659
|
-
// src/lib/runtimeSignalsStorage.ts
|
|
1660
|
-
var import_constants = require("@tradejs/core/constants");
|
|
1661
|
-
var import_time = require("@tradejs/core/time");
|
|
1662
|
-
var SECONDS_PER_DAY = 86400;
|
|
1663
|
-
var RUNTIME_SIGNAL_RETENTION_DAYS_ENV = "RUNTIME_SIGNAL_RETENTION_DAYS";
|
|
1664
|
-
var DEFAULT_RUNTIME_SIGNAL_RETENTION_TTL_SECONDS = import_constants.TTL_3D;
|
|
1665
|
-
var RUNTIME_LINEAGE_SCOPE_RETENTION_TTL_SECONDS = import_constants.TTL_1M;
|
|
1666
|
-
var parsePositiveNumber = (value) => {
|
|
1667
|
-
if (value == null || value === "") {
|
|
1668
|
-
return null;
|
|
1669
|
-
}
|
|
1670
|
-
const parsed = Number(value);
|
|
1671
|
-
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
1672
|
-
};
|
|
1673
|
-
var getRuntimeSignalRetentionTtlSeconds = () => {
|
|
1674
|
-
const explicitDays = parsePositiveNumber(
|
|
1675
|
-
process.env[RUNTIME_SIGNAL_RETENTION_DAYS_ENV]
|
|
1676
|
-
);
|
|
1677
|
-
if (explicitDays != null) {
|
|
1678
|
-
return Math.ceil(explicitDays * SECONDS_PER_DAY);
|
|
1679
|
-
}
|
|
1680
|
-
return DEFAULT_RUNTIME_SIGNAL_RETENTION_TTL_SECONDS;
|
|
1681
|
-
};
|
|
1682
|
-
var toRuntimeSignalBucketRef = (signal) => ({
|
|
1683
|
-
signalId: signal.signalId,
|
|
1684
|
-
symbol: signal.symbol,
|
|
1685
|
-
strategy: signal.strategy,
|
|
1686
|
-
timestamp: signal.timestamp,
|
|
1687
|
-
...signal.runtimeConfigId && signal.runtimeConfigId !== "config" ? { runtimeConfigId: signal.runtimeConfigId } : {}
|
|
1688
|
-
});
|
|
1689
|
-
var shouldStoreRuntimeSignalDiagnostics = (signal) => signal.orderStatus === "completed" || signal.orderStatus === "failed";
|
|
1690
|
-
var toStoredRuntimeSignal = (signal) => {
|
|
1691
|
-
if (shouldStoreRuntimeSignalDiagnostics(signal)) {
|
|
1692
|
-
return signal;
|
|
1693
|
-
}
|
|
1694
|
-
const stored = { ...signal };
|
|
1695
|
-
delete stored.figures;
|
|
1696
|
-
delete stored.indicators;
|
|
1697
|
-
delete stored.additionalIndicators;
|
|
1698
|
-
return stored;
|
|
1699
|
-
};
|
|
1700
|
-
var normalizeRuntimeSignalSkipReason = (reason, fallbackSource) => {
|
|
1701
|
-
let source = fallbackSource;
|
|
1702
|
-
let normalizedReason = reason;
|
|
1703
|
-
if (reason.startsWith("AI_QUALITY_BELOW_MIN")) {
|
|
1704
|
-
source = "AI";
|
|
1705
|
-
normalizedReason = "MIN_AI_QUALITY";
|
|
1706
|
-
} else if (reason === "AI_QUALITY_UNAVAILABLE") {
|
|
1707
|
-
source = "AI";
|
|
1708
|
-
normalizedReason = "QUALITY_UNAVAILABLE";
|
|
1709
|
-
} else if (reason === "ML_RESULT_UNAVAILABLE") {
|
|
1710
|
-
source = "ML";
|
|
1711
|
-
normalizedReason = "RESULT_UNAVAILABLE";
|
|
1712
|
-
} else if (reason.startsWith("ML_THRESHOLD_NOT_MET")) {
|
|
1713
|
-
source = "ML";
|
|
1714
|
-
normalizedReason = "ML_THRESHOLD";
|
|
1715
|
-
} else if (reason.startsWith("HOOK_BEFORE_ENTRY_GATE:")) {
|
|
1716
|
-
source = "hook";
|
|
1717
|
-
normalizedReason = `BEFORE_ENTRY_GATE:${reason.slice(
|
|
1718
|
-
"HOOK_BEFORE_ENTRY_GATE:".length
|
|
1719
|
-
)}`;
|
|
1720
|
-
} else if (reason === "HOOK_BEFORE_ENTRY_GATE") {
|
|
1721
|
-
source = "hook";
|
|
1722
|
-
normalizedReason = "BEFORE_ENTRY_GATE";
|
|
1723
|
-
} else if (reason === "MAKE_ORDERS_DISABLED" || reason === "ENTRY_POLICY_BLOCKED") {
|
|
1724
|
-
source = "policy";
|
|
1725
|
-
}
|
|
1726
|
-
return {
|
|
1727
|
-
source: `skip from ${source}`,
|
|
1728
|
-
reason: normalizedReason
|
|
1729
|
-
};
|
|
1730
|
-
};
|
|
1731
|
-
var buildStatsReasonField = (source, reason) => `reason:${source}:${reason}`;
|
|
1732
|
-
var buildRuntimeSignalStatsIncrements = (evaluation) => {
|
|
1733
|
-
const increments = {
|
|
1734
|
-
evaluated: 1
|
|
1735
|
-
};
|
|
1736
|
-
if (evaluation.status === "signal") {
|
|
1737
|
-
increments.signals = 1;
|
|
1738
|
-
}
|
|
1739
|
-
let skipReason = null;
|
|
1740
|
-
let fallbackSource = "core";
|
|
1741
|
-
if (evaluation.status === "skip") {
|
|
1742
|
-
skipReason = evaluation.reason || "NO_SIGNAL";
|
|
1743
|
-
fallbackSource = "core";
|
|
1744
|
-
} else if (evaluation.status === "signal" && (evaluation.orderStatus === "skipped" || evaluation.orderStatus === "canceled")) {
|
|
1745
|
-
skipReason = evaluation.orderSkipReason || evaluation.reason || `orderStatus=${evaluation.orderStatus}`;
|
|
1746
|
-
fallbackSource = "runtime";
|
|
1747
|
-
} else if (evaluation.status === "error") {
|
|
1748
|
-
skipReason = evaluation.reason || "EVALUATION_ERROR";
|
|
1749
|
-
fallbackSource = "runtime";
|
|
1750
|
-
}
|
|
1751
|
-
if (skipReason) {
|
|
1752
|
-
const normalized = normalizeRuntimeSignalSkipReason(
|
|
1753
|
-
skipReason,
|
|
1754
|
-
fallbackSource
|
|
1755
|
-
);
|
|
1756
|
-
increments[buildStatsReasonField(normalized.source, normalized.reason)] = 1;
|
|
1757
|
-
}
|
|
1758
|
-
return increments;
|
|
1759
|
-
};
|
|
1760
|
-
var shouldStoreDetailedRuntimeSignalEvaluation = (evaluation) => evaluation.status !== "skip";
|
|
1761
|
-
|
|
1762
1658
|
// src/lib/marketData/windows.ts
|
|
1763
1659
|
var import_indicators = require("@tradejs/core/indicators");
|
|
1764
1660
|
var resolveOpenTimestamp = (timestamp, intervalMs2) => Number.isFinite(intervalMs2) && intervalMs2 > 0 ? Math.floor(timestamp / intervalMs2) * intervalMs2 : timestamp;
|
|
@@ -1818,6 +1714,8 @@ var invokeAfterSignalsHooks = async (hooks, params) => {
|
|
|
1818
1714
|
|
|
1819
1715
|
// src/lib/marketContextPrepare.ts
|
|
1820
1716
|
var import_chalk4 = __toESM(require("chalk"));
|
|
1717
|
+
var import_timescale5 = require("@tradejs/infra/timescale");
|
|
1718
|
+
var import_registry = require("@tradejs/node/registry");
|
|
1821
1719
|
|
|
1822
1720
|
// src/lib/binanceMarketContextBackfill.ts
|
|
1823
1721
|
var import_progress = __toESM(require("progress"));
|
|
@@ -2618,7 +2516,7 @@ var backfillBinanceMarketContextForReplay = (params) => backfillBinanceMarketCon
|
|
|
2618
2516
|
var import_chalk2 = __toESM(require("chalk"));
|
|
2619
2517
|
var import_progress2 = __toESM(require("progress"));
|
|
2620
2518
|
var import_async = require("@tradejs/core/async");
|
|
2621
|
-
var
|
|
2519
|
+
var import_constants = require("@tradejs/core/constants");
|
|
2622
2520
|
var import_indicators2 = require("@tradejs/core/indicators");
|
|
2623
2521
|
var import_timescale2 = require("@tradejs/infra/timescale");
|
|
2624
2522
|
var import_userSettings = require("@tradejs/infra/userSettings");
|
|
@@ -2653,7 +2551,7 @@ var normalizeSymbols = (symbols) => [
|
|
|
2653
2551
|
];
|
|
2654
2552
|
var isDerivativesTargetContextEnabled = () => parseBooleanFlag(process.env.DERIVATIVES_CONTEXT_TARGET_ENABLED, false);
|
|
2655
2553
|
var resolveDerivativesContextBackfillSymbols = (requestedSymbols = []) => {
|
|
2656
|
-
const referenceSymbols = (0,
|
|
2554
|
+
const referenceSymbols = (0, import_constants.resolveDerivativesContextReferenceSymbols)(
|
|
2657
2555
|
process.env.DERIVATIVES_CONTEXT_EXTRA_REFERENCE_SYMBOLS
|
|
2658
2556
|
);
|
|
2659
2557
|
return isDerivativesTargetContextEnabled() ? normalizeSymbols([...referenceSymbols, ...requestedSymbols]) : referenceSymbols;
|
|
@@ -5059,6 +4957,9 @@ var backfillHyperliquidWhaleContext = async (params) => {
|
|
|
5059
4957
|
};
|
|
5060
4958
|
|
|
5061
4959
|
// src/lib/marketContextPrepare.ts
|
|
4960
|
+
var uniqueReasons = (reasons) => [
|
|
4961
|
+
...new Set(reasons)
|
|
4962
|
+
];
|
|
5062
4963
|
var shouldPrepareDerivativesContextForRun = (params) => {
|
|
5063
4964
|
if (params.universe === "tradfi") return false;
|
|
5064
4965
|
if (params.mode === "signals") {
|
|
@@ -5066,6 +4967,9 @@ var shouldPrepareDerivativesContextForRun = (params) => {
|
|
|
5066
4967
|
cacheOnly: params.cacheOnly
|
|
5067
4968
|
});
|
|
5068
4969
|
}
|
|
4970
|
+
if (params.mode === "backtest" && !params.aiEnabled && !params.mlEnabled) {
|
|
4971
|
+
return false;
|
|
4972
|
+
}
|
|
5069
4973
|
return shouldBackfillDerivativesContextForBacktest({
|
|
5070
4974
|
aiEnabled: Boolean(params.aiEnabled),
|
|
5071
4975
|
cacheOnly: params.cacheOnly,
|
|
@@ -5075,6 +4979,7 @@ var shouldPrepareDerivativesContextForRun = (params) => {
|
|
|
5075
4979
|
var shouldPrepareBinanceMarketContextForRun = (params) => {
|
|
5076
4980
|
if (params.universe === "tradfi") return false;
|
|
5077
4981
|
if (params.mode === "backtest") {
|
|
4982
|
+
if (!params.aiEnabled && !params.mlEnabled) return false;
|
|
5078
4983
|
return shouldBackfillBinanceMarketContextForBacktest({
|
|
5079
4984
|
aiEnabled: Boolean(params.aiEnabled),
|
|
5080
4985
|
cacheOnly: params.cacheOnly,
|
|
@@ -5093,6 +4998,7 @@ var shouldPrepareBinanceMarketContextForRun = (params) => {
|
|
|
5093
4998
|
var shouldPrepareCoinMarketCapContextForRun = (params) => {
|
|
5094
4999
|
if (params.universe === "tradfi") return false;
|
|
5095
5000
|
if (params.mode === "backtest") {
|
|
5001
|
+
if (!params.aiEnabled && !params.mlEnabled) return false;
|
|
5096
5002
|
return shouldBackfillCoinMarketCapContextForBacktest({
|
|
5097
5003
|
aiEnabled: Boolean(params.aiEnabled),
|
|
5098
5004
|
cacheOnly: params.cacheOnly,
|
|
@@ -5108,10 +5014,8 @@ var shouldPrepareCoinMarketCapContextForRun = (params) => {
|
|
|
5108
5014
|
cacheOnly: params.cacheOnly
|
|
5109
5015
|
});
|
|
5110
5016
|
};
|
|
5111
|
-
var shouldPrepareHyperliquidWhaleContextForRun = (params) => {
|
|
5112
|
-
const strategyRequiresContext =
|
|
5113
|
-
"HyperliquidConsensus"
|
|
5114
|
-
);
|
|
5017
|
+
var shouldPrepareHyperliquidWhaleContextForRun = (params, coreContextSources = []) => {
|
|
5018
|
+
const strategyRequiresContext = coreContextSources.includes("hyperliquidWhales");
|
|
5115
5019
|
if (params.universe === "tradfi" || params.mode === "signals" || params.cacheOnly || !params.aiEnabled && !params.mlEnabled && !strategyRequiresContext) {
|
|
5116
5020
|
return false;
|
|
5117
5021
|
}
|
|
@@ -5122,6 +5026,64 @@ var shouldPrepareHyperliquidWhaleContextForRun = (params) => {
|
|
|
5122
5026
|
if (strategyRequiresContext) return true;
|
|
5123
5027
|
return ["1", "true", "yes", "on"].includes(configured);
|
|
5124
5028
|
};
|
|
5029
|
+
var resolveCoreContextSources = async (params) => {
|
|
5030
|
+
const strategyNames = [...new Set(params.strategyNames ?? [])];
|
|
5031
|
+
if (!strategyNames.length) return [];
|
|
5032
|
+
await (0, import_registry.ensureStrategyPluginsLoaded)(params.projectRoot);
|
|
5033
|
+
return [
|
|
5034
|
+
...new Set(
|
|
5035
|
+
strategyNames.flatMap(
|
|
5036
|
+
(strategyName) => (0, import_registry.getStrategyManifest)(strategyName, params.projectRoot)?.contextRequirements?.core ?? []
|
|
5037
|
+
)
|
|
5038
|
+
)
|
|
5039
|
+
];
|
|
5040
|
+
};
|
|
5041
|
+
var resolveMarketContextRunRequirements = async (params) => {
|
|
5042
|
+
const coreContextSources = await resolveCoreContextSources(params);
|
|
5043
|
+
const paramsWithCoreDemand = (source) => coreContextSources.includes(source) ? { ...params, aiEnabled: true } : params;
|
|
5044
|
+
const isCrypto = params.universe !== "tradfi";
|
|
5045
|
+
const capturesPayload = Boolean(params.aiEnabled || params.mlEnabled);
|
|
5046
|
+
const runtimeReadsContext = params.mode !== "backtest";
|
|
5047
|
+
const reasonsFor = (source) => uniqueReasons([
|
|
5048
|
+
...coreContextSources.includes(source) ? ["core"] : [],
|
|
5049
|
+
...params.aiEnabled ? ["ai"] : [],
|
|
5050
|
+
...params.mlEnabled ? ["ml"] : [],
|
|
5051
|
+
...runtimeReadsContext ? ["runtime"] : []
|
|
5052
|
+
]);
|
|
5053
|
+
const readsStandardContext = isCrypto && (capturesPayload || runtimeReadsContext);
|
|
5054
|
+
const readsHyperliquid = isCrypto && (readsStandardContext || coreContextSources.includes("hyperliquidWhales"));
|
|
5055
|
+
return {
|
|
5056
|
+
binance: {
|
|
5057
|
+
read: readsStandardContext || coreContextSources.includes("binance"),
|
|
5058
|
+
backfill: shouldPrepareBinanceMarketContextForRun(
|
|
5059
|
+
paramsWithCoreDemand("binance")
|
|
5060
|
+
),
|
|
5061
|
+
requiredBy: reasonsFor("binance")
|
|
5062
|
+
},
|
|
5063
|
+
coinmarketcap: {
|
|
5064
|
+
read: readsStandardContext || coreContextSources.includes("coinmarketcap"),
|
|
5065
|
+
backfill: shouldPrepareCoinMarketCapContextForRun(
|
|
5066
|
+
paramsWithCoreDemand("coinmarketcap")
|
|
5067
|
+
),
|
|
5068
|
+
requiredBy: reasonsFor("coinmarketcap")
|
|
5069
|
+
},
|
|
5070
|
+
derivatives: {
|
|
5071
|
+
read: readsStandardContext || coreContextSources.includes("derivatives"),
|
|
5072
|
+
backfill: shouldPrepareDerivativesContextForRun(
|
|
5073
|
+
paramsWithCoreDemand("derivatives")
|
|
5074
|
+
),
|
|
5075
|
+
requiredBy: reasonsFor("derivatives")
|
|
5076
|
+
},
|
|
5077
|
+
hyperliquidWhales: {
|
|
5078
|
+
read: readsHyperliquid,
|
|
5079
|
+
backfill: shouldPrepareHyperliquidWhaleContextForRun(
|
|
5080
|
+
params,
|
|
5081
|
+
coreContextSources
|
|
5082
|
+
),
|
|
5083
|
+
requiredBy: reasonsFor("hyperliquidWhales")
|
|
5084
|
+
}
|
|
5085
|
+
};
|
|
5086
|
+
};
|
|
5125
5087
|
var resolveCoinMarketCapBackfillForMode = (mode) => mode === "backtest" ? backfillCoinMarketCapContextForBacktest : mode === "signals" ? backfillCoinMarketCapContextForSignals : backfillCoinMarketCapContextForReplay;
|
|
5126
5088
|
var buildCoinMarketCapBackfillParams = (params) => ({
|
|
5127
5089
|
userName: params.userName,
|
|
@@ -5150,7 +5112,15 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5150
5112
|
console.log(import_chalk4.default.gray(message));
|
|
5151
5113
|
});
|
|
5152
5114
|
const timeOperation3 = (label, operation) => timeOperation(label, operation, log);
|
|
5153
|
-
|
|
5115
|
+
const requirements = await resolveMarketContextRunRequirements(params);
|
|
5116
|
+
const readableSources = Object.entries(requirements).filter(([, requirement]) => requirement.read).map(([source]) => source);
|
|
5117
|
+
if (readableSources.length) {
|
|
5118
|
+
await timeOperation3(
|
|
5119
|
+
"market context schema ensure",
|
|
5120
|
+
() => (0, import_timescale5.ensureMarketContextSchemas)(readableSources)
|
|
5121
|
+
);
|
|
5122
|
+
}
|
|
5123
|
+
if (requirements.derivatives.backfill) {
|
|
5154
5124
|
await timeOperation3(
|
|
5155
5125
|
"derivatives context backfill",
|
|
5156
5126
|
() => (params.mode === "signals" ? backfillDerivativesContextForSignals : backfillDerivativesContextForBacktest)(
|
|
@@ -5158,7 +5128,7 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5158
5128
|
)
|
|
5159
5129
|
);
|
|
5160
5130
|
}
|
|
5161
|
-
if (
|
|
5131
|
+
if (requirements.hyperliquidWhales.backfill) {
|
|
5162
5132
|
await timeOperation3(
|
|
5163
5133
|
"hyperliquid whale context backfill",
|
|
5164
5134
|
() => backfillHyperliquidWhaleContext({
|
|
@@ -5170,13 +5140,13 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5170
5140
|
})
|
|
5171
5141
|
);
|
|
5172
5142
|
}
|
|
5173
|
-
if (
|
|
5143
|
+
if (requirements.binance.backfill) {
|
|
5174
5144
|
await timeOperation3("binance market context backfill", () => {
|
|
5175
5145
|
const backfill = params.mode === "backtest" ? backfillBinanceMarketContextForBacktest : params.mode === "signals" ? backfillBinanceMarketContextForSignals : backfillBinanceMarketContextForReplay;
|
|
5176
5146
|
return backfill(buildBinanceMarketBackfillParams(params));
|
|
5177
5147
|
});
|
|
5178
5148
|
}
|
|
5179
|
-
if (
|
|
5149
|
+
if (requirements.coinmarketcap.backfill) {
|
|
5180
5150
|
await timeOperation3(
|
|
5181
5151
|
"coinmarketcap historical context backfill",
|
|
5182
5152
|
() => resolveCoinMarketCapBackfillForMode(params.mode)(
|
|
@@ -5184,6 +5154,7 @@ var prepareMarketContextForRun = async (params) => {
|
|
|
5184
5154
|
)
|
|
5185
5155
|
);
|
|
5186
5156
|
}
|
|
5157
|
+
return requirements;
|
|
5187
5158
|
};
|
|
5188
5159
|
|
|
5189
5160
|
// src/lib/marketData/historyPrepare.ts
|
|
@@ -5347,7 +5318,7 @@ var import_strategies3 = require("@tradejs/node/strategies");
|
|
|
5347
5318
|
|
|
5348
5319
|
// src/lib/runtimeRedis.ts
|
|
5349
5320
|
var import_redis = require("@tradejs/infra/redis");
|
|
5350
|
-
var
|
|
5321
|
+
var import_time = require("@tradejs/core/time");
|
|
5351
5322
|
var RESERVED_STRATEGY_NAMES = /* @__PURE__ */ new Set(["charts"]);
|
|
5352
5323
|
var RESERVED_CONFIG_IDS = /* @__PURE__ */ new Set(["results"]);
|
|
5353
5324
|
var resolveStrategyConfigIdentityByKey = (userName, key) => {
|
|
@@ -5491,6 +5462,111 @@ var loadRuntimeStrategies = async ({
|
|
|
5491
5462
|
// src/lib/signals/skipStats.ts
|
|
5492
5463
|
var import_chalk6 = __toESM(require("chalk"));
|
|
5493
5464
|
var import_logger2 = require("@tradejs/infra/logger");
|
|
5465
|
+
|
|
5466
|
+
// src/lib/runtimeSignalsStorage.ts
|
|
5467
|
+
var import_constants2 = require("@tradejs/core/constants");
|
|
5468
|
+
var import_time2 = require("@tradejs/core/time");
|
|
5469
|
+
var SECONDS_PER_DAY = 86400;
|
|
5470
|
+
var RUNTIME_SIGNAL_RETENTION_DAYS_ENV = "RUNTIME_SIGNAL_RETENTION_DAYS";
|
|
5471
|
+
var DEFAULT_RUNTIME_SIGNAL_RETENTION_TTL_SECONDS = import_constants2.TTL_3D;
|
|
5472
|
+
var RUNTIME_LINEAGE_SCOPE_RETENTION_TTL_SECONDS = import_constants2.TTL_1M;
|
|
5473
|
+
var parsePositiveNumber = (value) => {
|
|
5474
|
+
if (value == null || value === "") {
|
|
5475
|
+
return null;
|
|
5476
|
+
}
|
|
5477
|
+
const parsed = Number(value);
|
|
5478
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
5479
|
+
};
|
|
5480
|
+
var getRuntimeSignalRetentionTtlSeconds = () => {
|
|
5481
|
+
const explicitDays = parsePositiveNumber(
|
|
5482
|
+
process.env[RUNTIME_SIGNAL_RETENTION_DAYS_ENV]
|
|
5483
|
+
);
|
|
5484
|
+
if (explicitDays != null) {
|
|
5485
|
+
return Math.ceil(explicitDays * SECONDS_PER_DAY);
|
|
5486
|
+
}
|
|
5487
|
+
return DEFAULT_RUNTIME_SIGNAL_RETENTION_TTL_SECONDS;
|
|
5488
|
+
};
|
|
5489
|
+
var toRuntimeSignalBucketRef = (signal) => ({
|
|
5490
|
+
signalId: signal.signalId,
|
|
5491
|
+
symbol: signal.symbol,
|
|
5492
|
+
strategy: signal.strategy,
|
|
5493
|
+
timestamp: signal.timestamp,
|
|
5494
|
+
...signal.runtimeConfigId && signal.runtimeConfigId !== "config" ? { runtimeConfigId: signal.runtimeConfigId } : {}
|
|
5495
|
+
});
|
|
5496
|
+
var shouldStoreRuntimeSignalDiagnostics = (signal) => signal.orderStatus === "completed" || signal.orderStatus === "failed";
|
|
5497
|
+
var toStoredRuntimeSignal = (signal) => {
|
|
5498
|
+
if (shouldStoreRuntimeSignalDiagnostics(signal)) {
|
|
5499
|
+
return signal;
|
|
5500
|
+
}
|
|
5501
|
+
const stored = { ...signal };
|
|
5502
|
+
delete stored.figures;
|
|
5503
|
+
delete stored.indicators;
|
|
5504
|
+
delete stored.additionalIndicators;
|
|
5505
|
+
return stored;
|
|
5506
|
+
};
|
|
5507
|
+
var normalizeRuntimeSignalSkipReason = (reason, fallbackSource) => {
|
|
5508
|
+
let source = fallbackSource;
|
|
5509
|
+
let normalizedReason = reason;
|
|
5510
|
+
if (reason.startsWith("AI_QUALITY_BELOW_MIN")) {
|
|
5511
|
+
source = "AI";
|
|
5512
|
+
normalizedReason = "MIN_AI_QUALITY";
|
|
5513
|
+
} else if (reason === "AI_QUALITY_UNAVAILABLE") {
|
|
5514
|
+
source = "AI";
|
|
5515
|
+
normalizedReason = "QUALITY_UNAVAILABLE";
|
|
5516
|
+
} else if (reason === "ML_RESULT_UNAVAILABLE") {
|
|
5517
|
+
source = "ML";
|
|
5518
|
+
normalizedReason = "RESULT_UNAVAILABLE";
|
|
5519
|
+
} else if (reason.startsWith("ML_THRESHOLD_NOT_MET")) {
|
|
5520
|
+
source = "ML";
|
|
5521
|
+
normalizedReason = "ML_THRESHOLD";
|
|
5522
|
+
} else if (reason.startsWith("HOOK_BEFORE_ENTRY_GATE:")) {
|
|
5523
|
+
source = "hook";
|
|
5524
|
+
normalizedReason = `BEFORE_ENTRY_GATE:${reason.slice(
|
|
5525
|
+
"HOOK_BEFORE_ENTRY_GATE:".length
|
|
5526
|
+
)}`;
|
|
5527
|
+
} else if (reason === "HOOK_BEFORE_ENTRY_GATE") {
|
|
5528
|
+
source = "hook";
|
|
5529
|
+
normalizedReason = "BEFORE_ENTRY_GATE";
|
|
5530
|
+
} else if (reason === "MAKE_ORDERS_DISABLED" || reason === "ENTRY_POLICY_BLOCKED") {
|
|
5531
|
+
source = "policy";
|
|
5532
|
+
}
|
|
5533
|
+
return {
|
|
5534
|
+
source: `skip from ${source}`,
|
|
5535
|
+
reason: normalizedReason
|
|
5536
|
+
};
|
|
5537
|
+
};
|
|
5538
|
+
var buildStatsReasonField = (source, reason) => `reason:${source}:${reason}`;
|
|
5539
|
+
var buildRuntimeSignalStatsIncrements = (evaluation) => {
|
|
5540
|
+
const increments = {
|
|
5541
|
+
evaluated: 1
|
|
5542
|
+
};
|
|
5543
|
+
if (evaluation.status === "signal") {
|
|
5544
|
+
increments.signals = 1;
|
|
5545
|
+
}
|
|
5546
|
+
let skipReason = null;
|
|
5547
|
+
let fallbackSource = "core";
|
|
5548
|
+
if (evaluation.status === "skip") {
|
|
5549
|
+
skipReason = evaluation.reason || "NO_SIGNAL";
|
|
5550
|
+
fallbackSource = "core";
|
|
5551
|
+
} else if (evaluation.status === "signal" && (evaluation.orderStatus === "skipped" || evaluation.orderStatus === "canceled")) {
|
|
5552
|
+
skipReason = evaluation.orderSkipReason || evaluation.reason || `orderStatus=${evaluation.orderStatus}`;
|
|
5553
|
+
fallbackSource = "runtime";
|
|
5554
|
+
} else if (evaluation.status === "error") {
|
|
5555
|
+
skipReason = evaluation.reason || "EVALUATION_ERROR";
|
|
5556
|
+
fallbackSource = "runtime";
|
|
5557
|
+
}
|
|
5558
|
+
if (skipReason) {
|
|
5559
|
+
const normalized = normalizeRuntimeSignalSkipReason(
|
|
5560
|
+
skipReason,
|
|
5561
|
+
fallbackSource
|
|
5562
|
+
);
|
|
5563
|
+
increments[buildStatsReasonField(normalized.source, normalized.reason)] = 1;
|
|
5564
|
+
}
|
|
5565
|
+
return increments;
|
|
5566
|
+
};
|
|
5567
|
+
var shouldStoreDetailedRuntimeSignalEvaluation = (evaluation) => evaluation.status !== "skip";
|
|
5568
|
+
|
|
5569
|
+
// src/lib/signals/skipStats.ts
|
|
5494
5570
|
var createStrategySkipStats = (runtimeStrategies) => new Map(
|
|
5495
5571
|
runtimeStrategies.map(({ strategyName }) => [
|
|
5496
5572
|
strategyName,
|
|
@@ -5818,7 +5894,7 @@ var flushRuntimeSignalEvaluations = async (evaluations) => {
|
|
|
5818
5894
|
if (evaluations.length === 0) return;
|
|
5819
5895
|
const evaluationsByDay = /* @__PURE__ */ new Map();
|
|
5820
5896
|
for (const evaluation of evaluations) {
|
|
5821
|
-
const dayKey = (0,
|
|
5897
|
+
const dayKey = (0, import_time2.getRuntimeStorageDayKey)(evaluation.timestamp);
|
|
5822
5898
|
const dayEvaluations = evaluationsByDay.get(dayKey) ?? [];
|
|
5823
5899
|
dayEvaluations.push(evaluation);
|
|
5824
5900
|
evaluationsByDay.set(dayKey, dayEvaluations);
|
|
@@ -5926,13 +6002,47 @@ var flushRuntimeSignalEvaluations = async (evaluations) => {
|
|
|
5926
6002
|
};
|
|
5927
6003
|
var createRuntimeSignalEvaluationBuffer = () => {
|
|
5928
6004
|
const evaluations = [];
|
|
6005
|
+
const signals2 = [];
|
|
5929
6006
|
return {
|
|
5930
6007
|
save: async (evaluation) => {
|
|
5931
6008
|
evaluations.push(evaluation);
|
|
5932
6009
|
},
|
|
6010
|
+
saveSignal: (userName, signal) => {
|
|
6011
|
+
signals2.push({ userName, signal });
|
|
6012
|
+
},
|
|
5933
6013
|
flush: async () => {
|
|
5934
6014
|
const pending = evaluations.splice(0);
|
|
5935
|
-
|
|
6015
|
+
const pendingSignals = signals2.splice(0);
|
|
6016
|
+
const runtimeSignalRetentionTtl = getRuntimeSignalRetentionTtlSeconds();
|
|
6017
|
+
const signalRefsByBucket = /* @__PURE__ */ new Map();
|
|
6018
|
+
for (const { userName, signal } of pendingSignals) {
|
|
6019
|
+
const bucket = import_redis3.redisKeys.runtimeSignalBucket(
|
|
6020
|
+
userName,
|
|
6021
|
+
(0, import_time2.getRuntimeStorageDayKey)(signal.timestamp),
|
|
6022
|
+
signal.strategy
|
|
6023
|
+
);
|
|
6024
|
+
const entries = signalRefsByBucket.get(bucket) ?? [];
|
|
6025
|
+
entries.push({
|
|
6026
|
+
field: signal.signalId,
|
|
6027
|
+
data: toRuntimeSignalBucketRef(signal)
|
|
6028
|
+
});
|
|
6029
|
+
signalRefsByBucket.set(bucket, entries);
|
|
6030
|
+
}
|
|
6031
|
+
await Promise.all([
|
|
6032
|
+
flushRuntimeSignalEvaluations(pending),
|
|
6033
|
+
...pendingSignals.map(
|
|
6034
|
+
({ signal }) => (0, import_redis3.setData)(
|
|
6035
|
+
import_redis3.redisKeys.storeSignal(signal.symbol, signal.signalId),
|
|
6036
|
+
toStoredRuntimeSignal(signal),
|
|
6037
|
+
{ expire: runtimeSignalRetentionTtl }
|
|
6038
|
+
)
|
|
6039
|
+
),
|
|
6040
|
+
...[...signalRefsByBucket].map(
|
|
6041
|
+
([bucket, entries]) => (0, import_redis3.setHashJsonFields)(bucket, entries, {
|
|
6042
|
+
expire: runtimeSignalRetentionTtl
|
|
6043
|
+
})
|
|
6044
|
+
)
|
|
6045
|
+
]);
|
|
5936
6046
|
}
|
|
5937
6047
|
};
|
|
5938
6048
|
};
|
|
@@ -6165,7 +6275,7 @@ var runSignalsDaemon = async ({
|
|
|
6165
6275
|
// src/lib/signals/klineFeed.ts
|
|
6166
6276
|
var import_connectors5 = require("@tradejs/connectors");
|
|
6167
6277
|
var import_logger3 = require("@tradejs/infra/logger");
|
|
6168
|
-
var
|
|
6278
|
+
var import_timescale6 = require("@tradejs/infra/timescale");
|
|
6169
6279
|
|
|
6170
6280
|
// src/lib/marketData/klineEvents.ts
|
|
6171
6281
|
var import_ioredis = __toESM(require("ioredis"));
|
|
@@ -6185,9 +6295,9 @@ var createSignalsKlineFeed = async ({
|
|
|
6185
6295
|
publish = publishMarketKlineEvent,
|
|
6186
6296
|
persist = async (rows) => {
|
|
6187
6297
|
const intervalMinutes = Number(interval2);
|
|
6188
|
-
await (0,
|
|
6298
|
+
await (0, import_timescale6.upsertCandles)(
|
|
6189
6299
|
rows.flatMap(
|
|
6190
|
-
({ symbol, candle }) => (0,
|
|
6300
|
+
({ symbol, candle }) => (0, import_timescale6.toRows)("bybit", symbol, intervalMinutes, [candle])
|
|
6191
6301
|
)
|
|
6192
6302
|
);
|
|
6193
6303
|
},
|
|
@@ -6453,7 +6563,7 @@ var createSignalsSession = async (lifecycle, scope = {}) => {
|
|
|
6453
6563
|
lifecycle
|
|
6454
6564
|
};
|
|
6455
6565
|
};
|
|
6456
|
-
var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCoinbaseData, primaryBtcClosedData, primaryEthClosedData, primaryEthByTimestamp, runtimeStrategies, strategyStats, runtimeCloseNotifications, lifecycle, preloadStart, currentTimestamp, persistStrategyState, universe, interval2, intervalMs2, accountId, deploymentId, instrument, runtimeScopeUniverse, saveRuntimeSignalEvaluation) => {
|
|
6566
|
+
var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCoinbaseData, primaryBtcClosedData, primaryEthClosedData, primaryEthByTimestamp, runtimeStrategies, strategyStats, runtimeCloseNotifications, lifecycle, preloadStart, currentTimestamp, persistStrategyState, universe, interval2, intervalMs2, accountId, deploymentId, instrument, runtimeScopeUniverse, saveRuntimeSignalEvaluation, saveRuntimeSignal) => {
|
|
6457
6567
|
const strategySignals = [];
|
|
6458
6568
|
const loadCached = (cachedSymbol) => connector.kline({
|
|
6459
6569
|
symbol: cachedSymbol,
|
|
@@ -6646,26 +6756,7 @@ var findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCo
|
|
|
6646
6756
|
);
|
|
6647
6757
|
}
|
|
6648
6758
|
strategySignals.push(signal);
|
|
6649
|
-
|
|
6650
|
-
await (0, import_redis5.setData)(
|
|
6651
|
-
import_redis5.redisKeys.storeSignal(symbol, signal.signalId),
|
|
6652
|
-
toStoredRuntimeSignal(signal),
|
|
6653
|
-
{
|
|
6654
|
-
expire: runtimeSignalRetentionTtl
|
|
6655
|
-
}
|
|
6656
|
-
);
|
|
6657
|
-
await (0, import_redis5.setHashJsonField)(
|
|
6658
|
-
import_redis5.redisKeys.runtimeSignalBucket(
|
|
6659
|
-
flags.user,
|
|
6660
|
-
(0, import_time.getRuntimeStorageDayKey)(signal.timestamp),
|
|
6661
|
-
signal.strategy
|
|
6662
|
-
),
|
|
6663
|
-
signal.signalId,
|
|
6664
|
-
toRuntimeSignalBucketRef(signal),
|
|
6665
|
-
{
|
|
6666
|
-
expire: runtimeSignalRetentionTtl
|
|
6667
|
-
}
|
|
6668
|
-
);
|
|
6759
|
+
saveRuntimeSignal?.(flags.user, signal);
|
|
6669
6760
|
await saveRuntimeSignalEvaluation?.({
|
|
6670
6761
|
evaluationId: buildRuntimeSignalEvaluationId({
|
|
6671
6762
|
strategyName,
|
|
@@ -6971,7 +7062,8 @@ var signals = async (options = {}) => {
|
|
|
6971
7062
|
deployment?.id,
|
|
6972
7063
|
instrumentsBySymbol.get(symbol),
|
|
6973
7064
|
sessionUniverse,
|
|
6974
|
-
runtimeSignalEvaluations.save
|
|
7065
|
+
runtimeSignalEvaluations.save,
|
|
7066
|
+
runtimeSignalEvaluations.saveSignal
|
|
6975
7067
|
);
|
|
6976
7068
|
if (strategySignals.length > 0) {
|
|
6977
7069
|
signals2.push(...strategySignals);
|
|
@@ -370,6 +370,15 @@ var syncRuntimeTrades = async ({
|
|
|
370
370
|
nextTrade,
|
|
371
371
|
{ expire: import_constants.TTL_1M }
|
|
372
372
|
),
|
|
373
|
+
(0, import_redis2.setHashJsonField)(
|
|
374
|
+
import_redis2.redisKeys.runtimeClosedTradeBucket(
|
|
375
|
+
userName,
|
|
376
|
+
(0, import_time2.getRuntimeStorageDayKey)(nextTrade.exitTimestamp)
|
|
377
|
+
),
|
|
378
|
+
trade.orderId,
|
|
379
|
+
nextTrade,
|
|
380
|
+
{ expire: import_constants.TTL_1M }
|
|
381
|
+
),
|
|
373
382
|
...isCurrentActiveTrade ? [(0, import_redis2.delKey)(activeTradeKey)] : []
|
|
374
383
|
]);
|
|
375
384
|
syncedTrades.push(nextTrade);
|
|
@@ -8,7 +8,9 @@ var import_ai = require("@tradejs/infra/ai");
|
|
|
8
8
|
var import_logger = require("@tradejs/infra/logger");
|
|
9
9
|
var import_ml = require("@tradejs/infra/ml");
|
|
10
10
|
var import_redis = require("@tradejs/infra/redis");
|
|
11
|
+
var import_timescale = require("@tradejs/infra/timescale");
|
|
11
12
|
var isProcessing = false;
|
|
13
|
+
(0, import_timescale.configureTimescaleMarketContextSchemaMode)("verify");
|
|
12
14
|
var resolveTestSuite = async ({
|
|
13
15
|
chunk,
|
|
14
16
|
chunkId,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradejs/cli",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.16",
|
|
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.16",
|
|
33
|
+
"@tradejs/connectors": "^2.0.16",
|
|
34
|
+
"@tradejs/core": "^2.0.16",
|
|
35
|
+
"@tradejs/indicators": "^2.0.16",
|
|
36
|
+
"@tradejs/infra": "^2.0.16",
|
|
37
|
+
"@tradejs/node": "^2.0.16",
|
|
38
|
+
"@tradejs/strategies": "^2.0.16",
|
|
39
|
+
"@tradejs/types": "^2.0.16",
|
|
40
40
|
"args": "^5.0.3",
|
|
41
41
|
"bcryptjs": "^2.4.3",
|
|
42
42
|
"chalk": "4.1.2",
|
|
@@ -77,6 +77,8 @@
|
|
|
77
77
|
"results": "yarn run run:dist results",
|
|
78
78
|
"replay-runtime-evidence": "yarn run run:dist replay-runtime-evidence",
|
|
79
79
|
"runtime-evidence": "yarn run run:dist runtime-evidence",
|
|
80
|
+
"runtime-evidence-sync": "yarn run run:dist runtime-evidence-sync",
|
|
81
|
+
"runtime-scorecard": "yarn run run:dist runtime-scorecard",
|
|
80
82
|
"continuity": "yarn run run:dist continuity",
|
|
81
83
|
"derivatives:ingest": "yarn run run:dist derivatives:ingest",
|
|
82
84
|
"derivatives:ingest:coinalyze:all": "yarn run run:dist derivatives:ingest:coinalyze:all",
|