@tradejs/cli 3.1.28-beta.257 → 3.1.28-beta.258
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 +868 -701
- package/dist/lib/runtimeFeedbackNotification.js +412 -0
- package/dist/scripts/runtimeFeedbackNotify.js +438 -0
- package/package.json +7 -7
package/dist/cli.js
CHANGED
|
@@ -255,7 +255,7 @@ var init_researchRoots = __esm({
|
|
|
255
255
|
resolveResearchRoots = (options = {}) => {
|
|
256
256
|
const cwd = import_node_path.default.resolve(options.cwd || process.cwd());
|
|
257
257
|
const env = options.env || process.env;
|
|
258
|
-
const
|
|
258
|
+
const projectRoot18 = import_node_path.default.resolve(
|
|
259
259
|
firstNonEmpty(options.projectRoot, env.PROJECT_CWD, cwd) || cwd
|
|
260
260
|
);
|
|
261
261
|
const sourceRepositoryRoot = firstNonEmpty(
|
|
@@ -263,7 +263,7 @@ var init_researchRoots = __esm({
|
|
|
263
263
|
env[SOURCE_REPOSITORY_ROOT_ENV]
|
|
264
264
|
);
|
|
265
265
|
return {
|
|
266
|
-
projectRoot:
|
|
266
|
+
projectRoot: projectRoot18,
|
|
267
267
|
...sourceRepositoryRoot ? { sourceRepositoryRoot: import_node_path.default.resolve(sourceRepositoryRoot) } : {}
|
|
268
268
|
};
|
|
269
269
|
};
|
|
@@ -1967,32 +1967,32 @@ var init_commandOptions = __esm({
|
|
|
1967
1967
|
(arg) => arg === `--${longName}` || arg.startsWith(`--${longName}=`) || (shortName ? arg === `-${shortName}` : false)
|
|
1968
1968
|
);
|
|
1969
1969
|
resolveAiPocketSearchCommandOptions = ({
|
|
1970
|
-
flags:
|
|
1970
|
+
flags: flags35,
|
|
1971
1971
|
argv: argv2
|
|
1972
1972
|
}) => {
|
|
1973
|
-
const outDir = String(
|
|
1974
|
-
const strategyName = String(
|
|
1975
|
-
const explicitFile = String(
|
|
1976
|
-
const skip = normalizeInt(
|
|
1977
|
-
const minQuality = normalizeInt(
|
|
1978
|
-
const sinceInput = parseTimestampFilter(
|
|
1979
|
-
const untilTimestamp = parseTimestampFilter(
|
|
1980
|
-
const trailingPeriodMs = parseTrailingPeriodMs(
|
|
1981
|
-
const periodLabel = String(
|
|
1973
|
+
const outDir = String(flags35.outDir || "data/ai/export");
|
|
1974
|
+
const strategyName = String(flags35.strategy || "").trim() || void 0;
|
|
1975
|
+
const explicitFile = String(flags35.file || "").trim();
|
|
1976
|
+
const skip = normalizeInt(flags35.skip, 0);
|
|
1977
|
+
const minQuality = normalizeInt(flags35.minQuality, 4);
|
|
1978
|
+
const sinceInput = parseTimestampFilter(flags35.since);
|
|
1979
|
+
const untilTimestamp = parseTimestampFilter(flags35.until);
|
|
1980
|
+
const trailingPeriodMs = parseTrailingPeriodMs(flags35.period);
|
|
1981
|
+
const periodLabel = String(flags35.period || "").trim() || null;
|
|
1982
1982
|
const hasDateFilter = trailingPeriodMs != null || sinceInput != null || untilTimestamp != null;
|
|
1983
1983
|
const recent = resolveAiTrainRecentLimit({
|
|
1984
1984
|
argv: argv2,
|
|
1985
|
-
recentValue:
|
|
1985
|
+
recentValue: flags35.recent,
|
|
1986
1986
|
hasDateFilter
|
|
1987
1987
|
});
|
|
1988
|
-
const qualityThresholds = parseQualityThresholds(
|
|
1989
|
-
const scope = String(
|
|
1988
|
+
const qualityThresholds = parseQualityThresholds(flags35.qualityThresholds);
|
|
1989
|
+
const scope = String(flags35.scope || "all").trim().toLowerCase();
|
|
1990
1990
|
if (!["all", "approved", "rejected", "candidates"].includes(scope)) {
|
|
1991
1991
|
throw new Error(
|
|
1992
1992
|
`Unsupported --scope "${scope}". Use all, approved, rejected, or candidates.`
|
|
1993
1993
|
);
|
|
1994
1994
|
}
|
|
1995
|
-
const direction = String(
|
|
1995
|
+
const direction = String(flags35.direction || "").trim().toUpperCase();
|
|
1996
1996
|
if (direction && !["LONG", "SHORT"].includes(direction)) {
|
|
1997
1997
|
throw new Error(
|
|
1998
1998
|
`Unsupported --direction "${direction}". Use LONG or SHORT.`
|
|
@@ -2003,14 +2003,14 @@ var init_commandOptions = __esm({
|
|
|
2003
2003
|
"maxEventCountShare",
|
|
2004
2004
|
"U"
|
|
2005
2005
|
);
|
|
2006
|
-
const maxDepth = normalizePositiveInt(
|
|
2007
|
-
const explicitMinSupport = hasCliOption2(argv2, "minSupport", "m") ? normalizePositiveInt(
|
|
2006
|
+
const maxDepth = normalizePositiveInt(flags35.maxDepth, 2);
|
|
2007
|
+
const explicitMinSupport = hasCliOption2(argv2, "minSupport", "m") ? normalizePositiveInt(flags35.minSupport, 20) : void 0;
|
|
2008
2008
|
const minProfitFactor = normalizeNonNegativeNumber(
|
|
2009
2009
|
readAiPocketSearchCliOption({
|
|
2010
2010
|
argv: argv2,
|
|
2011
2011
|
longName: "minProfitFactor",
|
|
2012
2012
|
shortName: "F"
|
|
2013
|
-
}) ??
|
|
2013
|
+
}) ?? flags35.minProfitFactor,
|
|
2014
2014
|
1.2
|
|
2015
2015
|
);
|
|
2016
2016
|
const minWinRate = normalizeNonNegativeNumber(
|
|
@@ -2018,21 +2018,21 @@ var init_commandOptions = __esm({
|
|
|
2018
2018
|
argv: argv2,
|
|
2019
2019
|
longName: "minWinRate",
|
|
2020
2020
|
shortName: "W"
|
|
2021
|
-
}) ??
|
|
2021
|
+
}) ?? flags35.minWinRate,
|
|
2022
2022
|
0
|
|
2023
2023
|
);
|
|
2024
2024
|
const minTotalProfitValue = readAiPocketSearchCliOption({
|
|
2025
2025
|
argv: argv2,
|
|
2026
2026
|
longName: "minTotalProfit",
|
|
2027
2027
|
shortName: "R"
|
|
2028
|
-
}) ??
|
|
2028
|
+
}) ?? flags35.minTotalProfit;
|
|
2029
2029
|
const minTotalProfit = Number.isFinite(Number(minTotalProfitValue)) ? Number(minTotalProfitValue) : 0;
|
|
2030
2030
|
const validationSplit = hasCliOption2(argv2, "validationSplit", "V") ? normalizeRatio(
|
|
2031
2031
|
readAiPocketSearchCliOption({
|
|
2032
2032
|
argv: argv2,
|
|
2033
2033
|
longName: "validationSplit",
|
|
2034
2034
|
shortName: "V"
|
|
2035
|
-
}) ??
|
|
2035
|
+
}) ?? flags35.validationSplit,
|
|
2036
2036
|
0.25
|
|
2037
2037
|
) : 0.25;
|
|
2038
2038
|
const testSplit = hasCliOption2(argv2, "testSplit", "T") ? normalizeRatio(
|
|
@@ -2040,10 +2040,10 @@ var init_commandOptions = __esm({
|
|
|
2040
2040
|
argv: argv2,
|
|
2041
2041
|
longName: "testSplit",
|
|
2042
2042
|
shortName: "T"
|
|
2043
|
-
}) ??
|
|
2043
|
+
}) ?? flags35.testSplit,
|
|
2044
2044
|
0
|
|
2045
2045
|
) : 0;
|
|
2046
|
-
const sealTest = Boolean(
|
|
2046
|
+
const sealTest = Boolean(flags35.sealTest);
|
|
2047
2047
|
if (sealTest && testSplit <= 0) {
|
|
2048
2048
|
throw new Error("--sealTest requires a positive --testSplit");
|
|
2049
2049
|
}
|
|
@@ -2052,7 +2052,7 @@ var init_commandOptions = __esm({
|
|
|
2052
2052
|
argv: argv2,
|
|
2053
2053
|
longName: "maxEventCountShare",
|
|
2054
2054
|
shortName: "U"
|
|
2055
|
-
}) ??
|
|
2055
|
+
}) ?? flags35.maxEventCountShare,
|
|
2056
2056
|
0.25
|
|
2057
2057
|
);
|
|
2058
2058
|
const maxSymbolCountShare = normalizeUnitRatio(
|
|
@@ -2060,10 +2060,10 @@ var init_commandOptions = __esm({
|
|
|
2060
2060
|
argv: argv2,
|
|
2061
2061
|
longName: "maxSymbolCountShare",
|
|
2062
2062
|
shortName: "Z"
|
|
2063
|
-
}) ??
|
|
2063
|
+
}) ?? flags35.maxSymbolCountShare,
|
|
2064
2064
|
0.5
|
|
2065
2065
|
);
|
|
2066
|
-
const objective = normalizeObjective(
|
|
2066
|
+
const objective = normalizeObjective(flags35.objective, scope);
|
|
2067
2067
|
return {
|
|
2068
2068
|
outDir,
|
|
2069
2069
|
strategyName,
|
|
@@ -2083,36 +2083,36 @@ var init_commandOptions = __esm({
|
|
|
2083
2083
|
minProfitFactor,
|
|
2084
2084
|
minWinRate,
|
|
2085
2085
|
minTotalProfit,
|
|
2086
|
-
maxAtomicPredicates: normalizePositiveInt(
|
|
2087
|
-
maxCombinations: normalizePositiveInt(
|
|
2086
|
+
maxAtomicPredicates: normalizePositiveInt(flags35.maxAtomicPredicates, 180),
|
|
2087
|
+
maxCombinations: normalizePositiveInt(flags35.maxCombinations, 6e4),
|
|
2088
2088
|
validationSplit,
|
|
2089
2089
|
testSplit,
|
|
2090
2090
|
sealTest,
|
|
2091
|
-
explicitMinValidationSupport: normalizeInt(
|
|
2092
|
-
explicitMinEvents: normalizeInt(
|
|
2093
|
-
explicitMinValidationEvents: normalizeInt(
|
|
2094
|
-
maxBatch: normalizeInt(
|
|
2091
|
+
explicitMinValidationSupport: normalizeInt(flags35.minValidationSupport, 0),
|
|
2092
|
+
explicitMinEvents: normalizeInt(flags35.minEvents, 0),
|
|
2093
|
+
explicitMinValidationEvents: normalizeInt(flags35.minValidationEvents, 0),
|
|
2094
|
+
maxBatch: normalizeInt(flags35.maxBatch, 5),
|
|
2095
2095
|
maxEventCountShare,
|
|
2096
2096
|
explicitMaxEventCountShare,
|
|
2097
2097
|
maxSymbolCountShare,
|
|
2098
2098
|
objective,
|
|
2099
|
-
allowRiskRegression: Boolean(
|
|
2100
|
-
requireValidationEligibility: !Boolean(
|
|
2101
|
-
dedupeEquivalentSelections: Boolean(
|
|
2102
|
-
top: normalizePositiveInt(
|
|
2103
|
-
includeSymbol: Boolean(
|
|
2104
|
-
includeGateContext: Boolean(
|
|
2105
|
-
featureProfile: normalizeFeatureProfile(
|
|
2106
|
-
featurePolicy: normalizeFeaturePolicy(
|
|
2099
|
+
allowRiskRegression: Boolean(flags35.allowRiskRegression),
|
|
2100
|
+
requireValidationEligibility: !Boolean(flags35.allowValidationRegression),
|
|
2101
|
+
dedupeEquivalentSelections: Boolean(flags35.dedupeEquivalentSelections),
|
|
2102
|
+
top: normalizePositiveInt(flags35.top, 30),
|
|
2103
|
+
includeSymbol: Boolean(flags35.includeSymbol),
|
|
2104
|
+
includeGateContext: Boolean(flags35.includeGateContext),
|
|
2105
|
+
featureProfile: normalizeFeatureProfile(flags35.featureProfile),
|
|
2106
|
+
featurePolicy: normalizeFeaturePolicy(flags35.featurePolicy),
|
|
2107
2107
|
excludeFeaturePattern: normalizeExcludeFeaturePattern(
|
|
2108
|
-
|
|
2108
|
+
flags35.excludeFeaturePattern
|
|
2109
2109
|
),
|
|
2110
|
-
coverageMode: normalizeCoverageMode(
|
|
2111
|
-
cadenceMode: normalizeCadenceMode(
|
|
2112
|
-
jsonOutput: Boolean(
|
|
2113
|
-
outputPath: String(
|
|
2114
|
-
reportDir: String(
|
|
2115
|
-
explicitReportFile: String(
|
|
2110
|
+
coverageMode: normalizeCoverageMode(flags35.coverageMode),
|
|
2111
|
+
cadenceMode: normalizeCadenceMode(flags35.cadenceMode),
|
|
2112
|
+
jsonOutput: Boolean(flags35.json),
|
|
2113
|
+
outputPath: String(flags35.output || "").trim(),
|
|
2114
|
+
reportDir: String(flags35.reportDir || "data/ai/output").trim(),
|
|
2115
|
+
explicitReportFile: String(flags35.reportFile || "").trim()
|
|
2116
2116
|
};
|
|
2117
2117
|
};
|
|
2118
2118
|
}
|
|
@@ -2212,9 +2212,9 @@ var init_features = __esm({
|
|
|
2212
2212
|
"targetsymbol",
|
|
2213
2213
|
"universe"
|
|
2214
2214
|
]);
|
|
2215
|
-
normalizeFeaturePath = (
|
|
2216
|
-
classifyAiPocketCoverageFeaturePath = (
|
|
2217
|
-
const segments = normalizeFeaturePath(
|
|
2215
|
+
normalizeFeaturePath = (path45) => (Array.isArray(path45) ? path45 : path45.split(".")).filter(Boolean).map((segment) => segment.toLowerCase());
|
|
2216
|
+
classifyAiPocketCoverageFeaturePath = (path45) => {
|
|
2217
|
+
const segments = normalizeFeaturePath(path45);
|
|
2218
2218
|
const normalizedPath = segments.join(".");
|
|
2219
2219
|
if (segments.some(
|
|
2220
2220
|
(segment) => segment.includes("cmc") || segment.includes("coinmarketcap")
|
|
@@ -2388,8 +2388,8 @@ var init_features = __esm({
|
|
|
2388
2388
|
"volumeusd",
|
|
2389
2389
|
"vwap"
|
|
2390
2390
|
]);
|
|
2391
|
-
classifyAiPocketFeaturePath = (
|
|
2392
|
-
const segments = (Array.isArray(
|
|
2391
|
+
classifyAiPocketFeaturePath = (path45) => {
|
|
2392
|
+
const segments = (Array.isArray(path45) ? path45 : path45.split(".")).filter(
|
|
2393
2393
|
Boolean
|
|
2394
2394
|
);
|
|
2395
2395
|
const normalized = segments.map((segment) => segment.toLowerCase());
|
|
@@ -2706,11 +2706,11 @@ var init_features = __esm({
|
|
|
2706
2706
|
excludeFeaturePattern.source,
|
|
2707
2707
|
excludeFeaturePattern.flags.replace(/[gy]/g, "")
|
|
2708
2708
|
) : void 0;
|
|
2709
|
-
const isOperatorExcluded = (
|
|
2710
|
-
if (!exclusion?.test(
|
|
2709
|
+
const isOperatorExcluded = (path45) => {
|
|
2710
|
+
if (!exclusion?.test(path45)) {
|
|
2711
2711
|
return false;
|
|
2712
2712
|
}
|
|
2713
|
-
onFeatureExcluded?.({ path:
|
|
2713
|
+
onFeatureExcluded?.({ path: path45, classification: "operator-excluded" });
|
|
2714
2714
|
return true;
|
|
2715
2715
|
};
|
|
2716
2716
|
const signal = payload.signal ?? {};
|
|
@@ -6043,10 +6043,10 @@ var init_command = __esm({
|
|
|
6043
6043
|
init_dataset();
|
|
6044
6044
|
init_research();
|
|
6045
6045
|
runAiPocketSearchCommand = async ({
|
|
6046
|
-
flags:
|
|
6046
|
+
flags: flags35
|
|
6047
6047
|
}) => {
|
|
6048
6048
|
const options = resolveAiPocketSearchCommandOptions({
|
|
6049
|
-
flags:
|
|
6049
|
+
flags: flags35,
|
|
6050
6050
|
argv: process.argv
|
|
6051
6051
|
});
|
|
6052
6052
|
const {
|
|
@@ -6958,11 +6958,11 @@ var init_strategyGateFingerprint = __esm({
|
|
|
6958
6958
|
"@tradejs/core/strategies"
|
|
6959
6959
|
];
|
|
6960
6960
|
resolveStrategyGateFingerprint = async ({
|
|
6961
|
-
projectRoot:
|
|
6961
|
+
projectRoot: projectRoot18,
|
|
6962
6962
|
strategyName,
|
|
6963
6963
|
gitSha
|
|
6964
6964
|
}) => {
|
|
6965
|
-
const projectManifestPath = import_node_path3.default.join(
|
|
6965
|
+
const projectManifestPath = import_node_path3.default.join(projectRoot18, "package.json");
|
|
6966
6966
|
const projectExists = await import_promises6.default.access(projectManifestPath).then(() => true).catch(() => false);
|
|
6967
6967
|
const requireFromProject = projectExists ? (0, import_node_module.createRequire)(projectManifestPath) : null;
|
|
6968
6968
|
const candidates = requireFromProject ? await Promise.all(
|
|
@@ -7141,10 +7141,10 @@ var init_aiTrainResearch = __esm({
|
|
|
7141
7141
|
};
|
|
7142
7142
|
});
|
|
7143
7143
|
};
|
|
7144
|
-
getGitLineage = (
|
|
7144
|
+
getGitLineage = (projectRoot18) => {
|
|
7145
7145
|
try {
|
|
7146
7146
|
const gitSha = (0, import_node_child_process2.execFileSync)("git", ["rev-parse", "HEAD"], {
|
|
7147
|
-
cwd:
|
|
7147
|
+
cwd: projectRoot18,
|
|
7148
7148
|
encoding: "utf8",
|
|
7149
7149
|
stdio: ["ignore", "pipe", "ignore"]
|
|
7150
7150
|
}).trim();
|
|
@@ -7152,7 +7152,7 @@ var init_aiTrainResearch = __esm({
|
|
|
7152
7152
|
"git",
|
|
7153
7153
|
["status", "--porcelain", "--untracked-files=no"],
|
|
7154
7154
|
{
|
|
7155
|
-
cwd:
|
|
7155
|
+
cwd: projectRoot18,
|
|
7156
7156
|
encoding: "utf8",
|
|
7157
7157
|
stdio: ["ignore", "pipe", "ignore"]
|
|
7158
7158
|
}
|
|
@@ -7163,16 +7163,16 @@ var init_aiTrainResearch = __esm({
|
|
|
7163
7163
|
}
|
|
7164
7164
|
};
|
|
7165
7165
|
buildAiTrainLineage = async ({
|
|
7166
|
-
projectRoot:
|
|
7166
|
+
projectRoot: projectRoot18,
|
|
7167
7167
|
strategyName,
|
|
7168
7168
|
configIds,
|
|
7169
7169
|
runContext,
|
|
7170
7170
|
sourceSha256s = [],
|
|
7171
7171
|
env = process.env
|
|
7172
7172
|
}) => {
|
|
7173
|
-
const { gitSha, gitDirty } = getGitLineage(
|
|
7173
|
+
const { gitSha, gitDirty } = getGitLineage(projectRoot18);
|
|
7174
7174
|
const gate = await resolveStrategyGateFingerprint({
|
|
7175
|
-
projectRoot:
|
|
7175
|
+
projectRoot: projectRoot18,
|
|
7176
7176
|
strategyName,
|
|
7177
7177
|
gitSha
|
|
7178
7178
|
});
|
|
@@ -9203,12 +9203,12 @@ var init_binanceMarketContextBackfill = __esm({
|
|
|
9203
9203
|
return rows;
|
|
9204
9204
|
};
|
|
9205
9205
|
getBinanceConnector = async ({
|
|
9206
|
-
projectRoot:
|
|
9206
|
+
projectRoot: projectRoot18,
|
|
9207
9207
|
userName: userName3
|
|
9208
9208
|
}) => {
|
|
9209
9209
|
const creator = await (0, import_connectors2.getConnectorCreatorByName)(
|
|
9210
9210
|
import_connectors.ConnectorNames.Binance,
|
|
9211
|
-
|
|
9211
|
+
projectRoot18
|
|
9212
9212
|
);
|
|
9213
9213
|
if (!creator) {
|
|
9214
9214
|
throw new Error(
|
|
@@ -10755,27 +10755,27 @@ var init_coinMarketCapContextBackfill = __esm({
|
|
|
10755
10755
|
totalCredits: 0,
|
|
10756
10756
|
byPath: /* @__PURE__ */ new Map()
|
|
10757
10757
|
});
|
|
10758
|
-
getCoinMarketCapPathLabel = (
|
|
10759
|
-
if (
|
|
10760
|
-
if (
|
|
10761
|
-
if (
|
|
10762
|
-
if (
|
|
10763
|
-
if (
|
|
10764
|
-
if (
|
|
10765
|
-
return
|
|
10766
|
-
};
|
|
10767
|
-
recordCoinMarketCapFetchStats = (stats,
|
|
10758
|
+
getCoinMarketCapPathLabel = (path45) => {
|
|
10759
|
+
if (path45.includes("global-metrics")) return "global";
|
|
10760
|
+
if (path45.includes("cryptocurrency/quotes")) return "reference";
|
|
10761
|
+
if (path45.includes("exchange/quotes")) return "exchangeLiquidity";
|
|
10762
|
+
if (path45.includes("fear-and-greed")) return "fearGreed";
|
|
10763
|
+
if (path45.includes("cmc100")) return "cmc100";
|
|
10764
|
+
if (path45.includes("cmc20")) return "cmc20";
|
|
10765
|
+
return path45;
|
|
10766
|
+
};
|
|
10767
|
+
recordCoinMarketCapFetchStats = (stats, path45, creditCount) => {
|
|
10768
10768
|
if (!stats) return;
|
|
10769
|
-
const existing = stats.byPath.get(
|
|
10769
|
+
const existing = stats.byPath.get(path45) ?? { requests: 0, credits: 0 };
|
|
10770
10770
|
existing.requests += 1;
|
|
10771
10771
|
existing.credits += creditCount ?? 0;
|
|
10772
10772
|
stats.requests += 1;
|
|
10773
10773
|
stats.totalCredits += creditCount ?? 0;
|
|
10774
|
-
stats.byPath.set(
|
|
10774
|
+
stats.byPath.set(path45, existing);
|
|
10775
10775
|
};
|
|
10776
10776
|
formatCoinMarketCapFetchStats = (stats) => {
|
|
10777
10777
|
const byPath = [...stats.byPath.entries()].map(
|
|
10778
|
-
([
|
|
10778
|
+
([path45, item]) => `${getCoinMarketCapPathLabel(path45)}=${item.requests}req/${item.credits}cr`
|
|
10779
10779
|
).join(" ");
|
|
10780
10780
|
return `apiRequests=${stats.requests} apiCredits=${stats.totalCredits}${byPath ? ` ${byPath}` : ""}`;
|
|
10781
10781
|
};
|
|
@@ -12533,7 +12533,7 @@ var init_historyPrepare = __esm({
|
|
|
12533
12533
|
connectorName,
|
|
12534
12534
|
marketConnector,
|
|
12535
12535
|
userName: userName3,
|
|
12536
|
-
projectRoot:
|
|
12536
|
+
projectRoot: projectRoot18,
|
|
12537
12537
|
shouldUseDedicatedReferences,
|
|
12538
12538
|
requireDedicatedReferences = false,
|
|
12539
12539
|
warn
|
|
@@ -12545,8 +12545,8 @@ var init_historyPrepare = __esm({
|
|
|
12545
12545
|
};
|
|
12546
12546
|
}
|
|
12547
12547
|
const [binanceFactory, coinbaseFactory] = await Promise.all([
|
|
12548
|
-
(0, import_connectors4.getConnectorCreatorByName)(import_connectors3.ConnectorNames.Binance,
|
|
12549
|
-
(0, import_connectors4.getConnectorCreatorByName)(import_connectors3.ConnectorNames.Coinbase,
|
|
12548
|
+
(0, import_connectors4.getConnectorCreatorByName)(import_connectors3.ConnectorNames.Binance, projectRoot18),
|
|
12549
|
+
(0, import_connectors4.getConnectorCreatorByName)(import_connectors3.ConnectorNames.Coinbase, projectRoot18)
|
|
12550
12550
|
]);
|
|
12551
12551
|
const binance = binanceFactory ? await binanceFactory({ userName: userName3 }) : marketConnector;
|
|
12552
12552
|
if (!binanceFactory) {
|
|
@@ -12804,9 +12804,9 @@ var init_runEnvironment = __esm({
|
|
|
12804
12804
|
};
|
|
12805
12805
|
resolveRunConnectorName = async ({
|
|
12806
12806
|
value,
|
|
12807
|
-
projectRoot:
|
|
12807
|
+
projectRoot: projectRoot18
|
|
12808
12808
|
}) => {
|
|
12809
|
-
const connectorName = await (0, import_connectors5.resolveConnectorName)(value,
|
|
12809
|
+
const connectorName = await (0, import_connectors5.resolveConnectorName)(value, projectRoot18);
|
|
12810
12810
|
if (connectorName) {
|
|
12811
12811
|
return connectorName;
|
|
12812
12812
|
}
|
|
@@ -12831,12 +12831,12 @@ var init_runEnvironment = __esm({
|
|
|
12831
12831
|
};
|
|
12832
12832
|
loadDeploymentReplayStrategies = async ({
|
|
12833
12833
|
userName: userName3,
|
|
12834
|
-
projectRoot:
|
|
12834
|
+
projectRoot: projectRoot18,
|
|
12835
12835
|
deploymentId
|
|
12836
12836
|
}) => {
|
|
12837
12837
|
const [deployment, runtimeStrategies] = await Promise.all([
|
|
12838
|
-
(0, import_runtimeStrategies.getRuntimeDeployment)({ userName: userName3, projectRoot:
|
|
12839
|
-
(0, import_runtimeStrategies.loadResolvedRuntimeStrategies)({ userName: userName3, projectRoot:
|
|
12838
|
+
(0, import_runtimeStrategies.getRuntimeDeployment)({ userName: userName3, projectRoot: projectRoot18, deploymentId }),
|
|
12839
|
+
(0, import_runtimeStrategies.loadResolvedRuntimeStrategies)({ userName: userName3, projectRoot: projectRoot18, deploymentId })
|
|
12840
12840
|
]);
|
|
12841
12841
|
if (!deployment) {
|
|
12842
12842
|
throw new Error(`Runtime deployment not found: ${deploymentId}`);
|
|
@@ -12885,7 +12885,7 @@ var init_runEnvironment = __esm({
|
|
|
12885
12885
|
endTime,
|
|
12886
12886
|
cacheOnly,
|
|
12887
12887
|
interval: interval4,
|
|
12888
|
-
projectRoot:
|
|
12888
|
+
projectRoot: projectRoot18,
|
|
12889
12889
|
universe = "crypto",
|
|
12890
12890
|
accountId,
|
|
12891
12891
|
deploymentId,
|
|
@@ -12895,11 +12895,11 @@ var init_runEnvironment = __esm({
|
|
|
12895
12895
|
}) => {
|
|
12896
12896
|
const connectorName = await resolveRunConnectorName({
|
|
12897
12897
|
value: connector,
|
|
12898
|
-
projectRoot:
|
|
12898
|
+
projectRoot: projectRoot18
|
|
12899
12899
|
});
|
|
12900
12900
|
const connectorFactory = await (0, import_connectors5.getConnectorCreatorByName)(
|
|
12901
12901
|
connectorName,
|
|
12902
|
-
|
|
12902
|
+
projectRoot18
|
|
12903
12903
|
);
|
|
12904
12904
|
if (!connectorFactory) {
|
|
12905
12905
|
throw new Error(`Connector "${connectorName}" is not registered`);
|
|
@@ -12966,7 +12966,7 @@ var init_runEnvironment = __esm({
|
|
|
12966
12966
|
connectorName,
|
|
12967
12967
|
marketConnector,
|
|
12968
12968
|
userName: userName3,
|
|
12969
|
-
projectRoot:
|
|
12969
|
+
projectRoot: projectRoot18,
|
|
12970
12970
|
shouldUseDedicatedReferences: universe === "crypto",
|
|
12971
12971
|
requireDedicatedReferences: universe === "crypto",
|
|
12972
12972
|
warn: (message) => console.log(import_chalk12.default.yellow(message))
|
|
@@ -15063,12 +15063,12 @@ var init_runtimeEvidenceDeployment = __esm({
|
|
|
15063
15063
|
});
|
|
15064
15064
|
resolveRuntimeEvidenceDeploymentSnapshot = async ({
|
|
15065
15065
|
userName: userName3,
|
|
15066
|
-
projectRoot:
|
|
15066
|
+
projectRoot: projectRoot18,
|
|
15067
15067
|
deploymentId
|
|
15068
15068
|
}) => {
|
|
15069
15069
|
const [deployment, strategies] = await Promise.all([
|
|
15070
|
-
(0, import_runtimeStrategies3.getRuntimeDeployment)({ userName: userName3, projectRoot:
|
|
15071
|
-
(0, import_runtimeStrategies3.loadResolvedRuntimeStrategies)({ userName: userName3, projectRoot:
|
|
15070
|
+
(0, import_runtimeStrategies3.getRuntimeDeployment)({ userName: userName3, projectRoot: projectRoot18, deploymentId }),
|
|
15071
|
+
(0, import_runtimeStrategies3.loadResolvedRuntimeStrategies)({ userName: userName3, projectRoot: projectRoot18, deploymentId })
|
|
15072
15072
|
]);
|
|
15073
15073
|
if (!deployment) {
|
|
15074
15074
|
throw new Error(`Runtime deployment not found: ${deploymentId}`);
|
|
@@ -15155,9 +15155,9 @@ var init_runtimeEvidenceSource = __esm({
|
|
|
15155
15155
|
};
|
|
15156
15156
|
readRuntimeEvidenceArtifact = async ({
|
|
15157
15157
|
filePath,
|
|
15158
|
-
projectRoot:
|
|
15158
|
+
projectRoot: projectRoot18
|
|
15159
15159
|
}) => {
|
|
15160
|
-
const resolvedPath = import_node_path5.default.resolve(
|
|
15160
|
+
const resolvedPath = import_node_path5.default.resolve(projectRoot18, filePath);
|
|
15161
15161
|
const root = asRecord2(
|
|
15162
15162
|
JSON.parse(await import_promises9.default.readFile(resolvedPath, "utf8"))
|
|
15163
15163
|
);
|
|
@@ -15256,11 +15256,11 @@ var init_runtimeEvidenceSource = __esm({
|
|
|
15256
15256
|
};
|
|
15257
15257
|
loadReplayRuntimeEvidenceSource = async ({
|
|
15258
15258
|
filePath,
|
|
15259
|
-
projectRoot:
|
|
15259
|
+
projectRoot: projectRoot18,
|
|
15260
15260
|
expectedUserName,
|
|
15261
15261
|
expectedWindow
|
|
15262
15262
|
}) => {
|
|
15263
|
-
const { resolvedPath, runtime, userName: userName3, startTime, endTime, deployment } = await readRuntimeEvidenceArtifact({ filePath, projectRoot:
|
|
15263
|
+
const { resolvedPath, runtime, userName: userName3, startTime, endTime, deployment } = await readRuntimeEvidenceArtifact({ filePath, projectRoot: projectRoot18 });
|
|
15264
15264
|
if (!userName3 || userName3 !== expectedUserName) {
|
|
15265
15265
|
throw new Error(
|
|
15266
15266
|
`Runtime evidence user mismatch: expected=${expectedUserName}, actual=${userName3 || "missing"}`
|
|
@@ -15993,7 +15993,7 @@ var init_historicalSignalsReplayPreparation = __esm({
|
|
|
15993
15993
|
prepareHistoricalReplay = async (context, adapters) => {
|
|
15994
15994
|
const {
|
|
15995
15995
|
userName: userName3,
|
|
15996
|
-
projectRoot:
|
|
15996
|
+
projectRoot: projectRoot18,
|
|
15997
15997
|
preparedRun,
|
|
15998
15998
|
interval: interval4,
|
|
15999
15999
|
connectorName,
|
|
@@ -16047,7 +16047,7 @@ var init_historicalSignalsReplayPreparation = __esm({
|
|
|
16047
16047
|
interval: interval4
|
|
16048
16048
|
});
|
|
16049
16049
|
const runtimeLineage = await adapters.buildLineage({
|
|
16050
|
-
projectRoot:
|
|
16050
|
+
projectRoot: projectRoot18,
|
|
16051
16051
|
strategyName: strategy.strategyName,
|
|
16052
16052
|
strategyRevision: strategy.strategyRevision,
|
|
16053
16053
|
deploymentCompositionId: strategy.deploymentCompositionId,
|
|
@@ -20110,7 +20110,7 @@ var init_outputReport = __esm({
|
|
|
20110
20110
|
) : "_No replay lineage records._";
|
|
20111
20111
|
};
|
|
20112
20112
|
writeReplayOutputReport = async ({
|
|
20113
|
-
projectRoot:
|
|
20113
|
+
projectRoot: projectRoot18,
|
|
20114
20114
|
timestamp,
|
|
20115
20115
|
replayKey,
|
|
20116
20116
|
userName: userName3,
|
|
@@ -20123,7 +20123,7 @@ var init_outputReport = __esm({
|
|
|
20123
20123
|
strategySnapshot,
|
|
20124
20124
|
runtimeComparison
|
|
20125
20125
|
}) => {
|
|
20126
|
-
const outputDir = import_node_path7.default.resolve(
|
|
20126
|
+
const outputDir = import_node_path7.default.resolve(projectRoot18, "data/replay/output");
|
|
20127
20127
|
await import_promises10.default.mkdir(outputDir, { recursive: true });
|
|
20128
20128
|
const perTradeAnalysis = buildPerTradeAnalysis(runtimeComparison);
|
|
20129
20129
|
const report = {
|
|
@@ -20416,14 +20416,14 @@ var init_portfolioReport = __esm({
|
|
|
20416
20416
|
)
|
|
20417
20417
|
].join("\n");
|
|
20418
20418
|
writePortfolioReport = async ({
|
|
20419
|
-
projectRoot:
|
|
20419
|
+
projectRoot: projectRoot18,
|
|
20420
20420
|
timestamp,
|
|
20421
20421
|
replayResult,
|
|
20422
20422
|
window,
|
|
20423
20423
|
lineage,
|
|
20424
20424
|
command
|
|
20425
20425
|
}) => {
|
|
20426
|
-
const outputDir = import_node_path8.default.resolve(
|
|
20426
|
+
const outputDir = import_node_path8.default.resolve(projectRoot18, "data/replay/output");
|
|
20427
20427
|
await import_promises11.default.mkdir(outputDir, { recursive: true });
|
|
20428
20428
|
const trades = replayResult.strategies.flatMap(
|
|
20429
20429
|
(strategy) => tradesFromPositionLog(strategy.strategyName, strategy.positionLog)
|
|
@@ -21122,10 +21122,10 @@ var init_binanceBreadthUniversesUpdate = __esm({
|
|
|
21122
21122
|
flags6 = import_args7.default.parse(process.argv);
|
|
21123
21123
|
BINANCE_BREADTH_UNIVERSES_RELATIVE_PATH = "packages/node/src/config/binanceBreadthUniverses.json";
|
|
21124
21124
|
main7 = async () => {
|
|
21125
|
-
const
|
|
21125
|
+
const projectRoot18 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
|
|
21126
21126
|
const connectorCreator = await (0, import_connectors8.getConnectorCreatorByName)(
|
|
21127
21127
|
import_connectors7.ConnectorNames.Binance,
|
|
21128
|
-
|
|
21128
|
+
projectRoot18
|
|
21129
21129
|
);
|
|
21130
21130
|
if (!connectorCreator) {
|
|
21131
21131
|
throw new Error("Binance connector is not registered");
|
|
@@ -21158,7 +21158,7 @@ var init_binanceBreadthUniversesUpdate = __esm({
|
|
|
21158
21158
|
return snapshot;
|
|
21159
21159
|
}
|
|
21160
21160
|
const outputPath = import_node_path9.default.join(
|
|
21161
|
-
|
|
21161
|
+
projectRoot18,
|
|
21162
21162
|
BINANCE_BREADTH_UNIVERSES_RELATIVE_PATH
|
|
21163
21163
|
);
|
|
21164
21164
|
await import_promises12.default.writeFile(outputPath, serialized, "utf8");
|
|
@@ -21992,14 +21992,14 @@ var init_cleanTests = __esm({
|
|
|
21992
21992
|
cleanUserTests = async (userName3) => {
|
|
21993
21993
|
const testsPrefix = `users:${userName3}:tests:`;
|
|
21994
21994
|
const testsCachePrefix = `users:${userName3}:cache:tests:`;
|
|
21995
|
-
const
|
|
21995
|
+
const projectRoot18 = process.env.PROJECT_CWD || process.cwd();
|
|
21996
21996
|
const persistedArtifactsDir = import_path7.default.relative(
|
|
21997
|
-
|
|
21998
|
-
(0, import_backtestArtifacts2.getPersistedBacktestArtifactsDirForUser)(userName3,
|
|
21997
|
+
projectRoot18,
|
|
21998
|
+
(0, import_backtestArtifacts2.getPersistedBacktestArtifactsDirForUser)(userName3, projectRoot18)
|
|
21999
21999
|
);
|
|
22000
22000
|
const cacheArtifactsDir = import_path7.default.relative(
|
|
22001
|
-
|
|
22002
|
-
(0, import_backtestArtifacts2.getBacktestCacheArtifactsDirForUser)(userName3,
|
|
22001
|
+
projectRoot18,
|
|
22002
|
+
(0, import_backtestArtifacts2.getBacktestCacheArtifactsDirForUser)(userName3, projectRoot18)
|
|
22003
22003
|
);
|
|
22004
22004
|
if (flags11.cache) {
|
|
22005
22005
|
console.log(import_chalk25.default.yellow(`clean user cache: ${userName3}`));
|
|
@@ -22012,11 +22012,11 @@ var init_cleanTests = __esm({
|
|
|
22012
22012
|
await (0, import_cli8.cleanRedis)(testsCachePrefix);
|
|
22013
22013
|
await (0, import_cli8.cleanFiles)(persistedArtifactsDir);
|
|
22014
22014
|
await (0, import_cli8.cleanFiles)(cacheArtifactsDir);
|
|
22015
|
-
await import_promises13.default.rm(import_path7.default.join(
|
|
22015
|
+
await import_promises13.default.rm(import_path7.default.join(projectRoot18, persistedArtifactsDir), {
|
|
22016
22016
|
recursive: true,
|
|
22017
22017
|
force: true
|
|
22018
22018
|
});
|
|
22019
|
-
await import_promises13.default.rm(import_path7.default.join(
|
|
22019
|
+
await import_promises13.default.rm(import_path7.default.join(projectRoot18, cacheArtifactsDir), {
|
|
22020
22020
|
recursive: true,
|
|
22021
22021
|
force: true
|
|
22022
22022
|
});
|
|
@@ -23853,8 +23853,8 @@ volumes:
|
|
|
23853
23853
|
`${DEV_COMPOSE_FILE} not found in project root. Run "npx @tradejs/cli infra-init" first.`
|
|
23854
23854
|
);
|
|
23855
23855
|
};
|
|
23856
|
-
runDockerCompose = (composePath,
|
|
23857
|
-
const result = (0, import_node_child_process3.spawnSync)("docker", ["compose", "-f", composePath, ...
|
|
23856
|
+
runDockerCompose = (composePath, args38) => {
|
|
23857
|
+
const result = (0, import_node_child_process3.spawnSync)("docker", ["compose", "-f", composePath, ...args38], {
|
|
23858
23858
|
stdio: "inherit"
|
|
23859
23859
|
});
|
|
23860
23860
|
if (result.error) {
|
|
@@ -30166,11 +30166,11 @@ var init_coreResearch = __esm({
|
|
|
30166
30166
|
if (!Number.isFinite(numeric)) throw new Error(`${name} is invalid: ${text}`);
|
|
30167
30167
|
return numeric;
|
|
30168
30168
|
};
|
|
30169
|
-
readSymbols = async (argv2,
|
|
30169
|
+
readSymbols = async (argv2, projectRoot18) => {
|
|
30170
30170
|
const symbolsFile = valueAfter(argv2, "--symbolsFile");
|
|
30171
30171
|
if (symbolsFile) {
|
|
30172
30172
|
const parsed = JSON.parse(
|
|
30173
|
-
await import_promises23.default.readFile(import_node_path18.default.resolve(
|
|
30173
|
+
await import_promises23.default.readFile(import_node_path18.default.resolve(projectRoot18, symbolsFile), "utf8")
|
|
30174
30174
|
);
|
|
30175
30175
|
if (!Array.isArray(parsed) || parsed.some((symbol) => typeof symbol !== "string")) {
|
|
30176
30176
|
throw new Error("--symbolsFile must contain a JSON string array");
|
|
@@ -30940,13 +30940,13 @@ var init_replayRuntimeEvidence = __esm({
|
|
|
30940
30940
|
const parsed = Date.parse(raw);
|
|
30941
30941
|
return Number.isFinite(parsed) ? parsed : null;
|
|
30942
30942
|
};
|
|
30943
|
-
resolveWindow = (
|
|
30944
|
-
const endTime = toEpochMs2(
|
|
30943
|
+
resolveWindow = (flags35) => {
|
|
30944
|
+
const endTime = toEpochMs2(flags35.endTime) ?? Date.now();
|
|
30945
30945
|
const hours = Math.max(
|
|
30946
30946
|
1,
|
|
30947
|
-
Number.parseInt(String(
|
|
30947
|
+
Number.parseInt(String(flags35.hours ?? 24), 10) || 24
|
|
30948
30948
|
);
|
|
30949
|
-
const startTime = toEpochMs2(
|
|
30949
|
+
const startTime = toEpochMs2(flags35.startTime) ?? endTime - hours * 60 * 60 * 1e3;
|
|
30950
30950
|
if (startTime >= endTime) {
|
|
30951
30951
|
throw new Error(
|
|
30952
30952
|
`Invalid window: startTime (${startTime}) must be less than endTime (${endTime})`
|
|
@@ -30955,7 +30955,7 @@ var init_replayRuntimeEvidence = __esm({
|
|
|
30955
30955
|
return {
|
|
30956
30956
|
startTime,
|
|
30957
30957
|
endTime,
|
|
30958
|
-
source:
|
|
30958
|
+
source: flags35.startTime != null || flags35.endTime != null ? "explicit" : "hours"
|
|
30959
30959
|
};
|
|
30960
30960
|
};
|
|
30961
30961
|
parseStrategyFilter = (value) => String(value ?? "").split(",").map((item) => item.trim()).filter(Boolean);
|
|
@@ -31157,9 +31157,9 @@ var init_replayRuntimeEvidence = __esm({
|
|
|
31157
31157
|
strategies,
|
|
31158
31158
|
userName: userName3,
|
|
31159
31159
|
runtimeEvidenceFile,
|
|
31160
|
-
projectRoot:
|
|
31160
|
+
projectRoot: projectRoot18
|
|
31161
31161
|
}) => {
|
|
31162
|
-
const runtimeEvidencePath = typeof runtimeEvidenceFile === "string" && runtimeEvidenceFile.trim() ? import_node_path19.default.resolve(
|
|
31162
|
+
const runtimeEvidencePath = typeof runtimeEvidenceFile === "string" && runtimeEvidenceFile.trim() ? import_node_path19.default.resolve(projectRoot18, runtimeEvidenceFile.trim()) : null;
|
|
31163
31163
|
if (runtimeEvidencePath) {
|
|
31164
31164
|
const artifact = JSON.parse(
|
|
31165
31165
|
await import_promises24.default.readFile(runtimeEvidencePath, "utf8")
|
|
@@ -31193,23 +31193,23 @@ var init_replayRuntimeEvidence = __esm({
|
|
|
31193
31193
|
};
|
|
31194
31194
|
};
|
|
31195
31195
|
replayRuntimeEvidence = async () => {
|
|
31196
|
-
const
|
|
31197
|
-
const
|
|
31198
|
-
const userName3 = String(
|
|
31199
|
-
const { startTime, endTime, source } = resolveWindow(
|
|
31196
|
+
const flags35 = import_args26.default.parse(process.argv);
|
|
31197
|
+
const projectRoot18 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
|
|
31198
|
+
const userName3 = String(flags35.user ?? "root");
|
|
31199
|
+
const { startTime, endTime, source } = resolveWindow(flags35);
|
|
31200
31200
|
const replay = await loadReplayResult({
|
|
31201
31201
|
userName: userName3,
|
|
31202
|
-
replayKey: typeof
|
|
31202
|
+
replayKey: typeof flags35.replayKey === "string" && flags35.replayKey.trim() ? flags35.replayKey.trim() : void 0
|
|
31203
31203
|
});
|
|
31204
|
-
const explicitStrategies = parseStrategyFilter(
|
|
31204
|
+
const explicitStrategies = parseStrategyFilter(flags35.strategy);
|
|
31205
31205
|
const strategies = explicitStrategies.length ? explicitStrategies : getReplayStrategies(replay.value);
|
|
31206
31206
|
const runtime = await loadRuntimePayload({
|
|
31207
31207
|
startTime,
|
|
31208
31208
|
endTime,
|
|
31209
31209
|
strategies,
|
|
31210
31210
|
userName: userName3,
|
|
31211
|
-
runtimeEvidenceFile:
|
|
31212
|
-
projectRoot:
|
|
31211
|
+
runtimeEvidenceFile: flags35.runtimeEvidence,
|
|
31212
|
+
projectRoot: projectRoot18
|
|
31213
31213
|
});
|
|
31214
31214
|
const replayValue = asRecord5(replay.value);
|
|
31215
31215
|
const artifact = {
|
|
@@ -31248,7 +31248,7 @@ var init_replayRuntimeEvidence = __esm({
|
|
|
31248
31248
|
},
|
|
31249
31249
|
runtime: runtime.payload
|
|
31250
31250
|
};
|
|
31251
|
-
const outPath = import_node_path19.default.resolve(
|
|
31251
|
+
const outPath = import_node_path19.default.resolve(projectRoot18, String(flags35.out));
|
|
31252
31252
|
await import_promises24.default.mkdir(import_node_path19.default.dirname(outPath), { recursive: true });
|
|
31253
31253
|
await import_promises24.default.writeFile(outPath, `${JSON.stringify(artifact, null, 2)}
|
|
31254
31254
|
`, "utf8");
|
|
@@ -31523,7 +31523,7 @@ var init_runtimeEvidenceProducer = __esm({
|
|
|
31523
31523
|
return producer;
|
|
31524
31524
|
};
|
|
31525
31525
|
resolveRuntimeEvidenceProducer = async ({
|
|
31526
|
-
projectRoot:
|
|
31526
|
+
projectRoot: projectRoot18,
|
|
31527
31527
|
required: required4
|
|
31528
31528
|
}) => {
|
|
31529
31529
|
const projectSha = String(process.env.TRADEJS_PROJECT_SHA ?? "").trim();
|
|
@@ -31543,7 +31543,7 @@ var init_runtimeEvidenceProducer = __esm({
|
|
|
31543
31543
|
"TRADEJS_PROJECT_IMAGE_DIGEST must be an immutable sha256 digest before publishing runtime evidence"
|
|
31544
31544
|
);
|
|
31545
31545
|
}
|
|
31546
|
-
const manifestPath = import_node_path21.default.join(
|
|
31546
|
+
const manifestPath = import_node_path21.default.join(projectRoot18, "runtime-package-manifest.json");
|
|
31547
31547
|
let manifest;
|
|
31548
31548
|
try {
|
|
31549
31549
|
manifest = await import_promises26.default.readFile(manifestPath);
|
|
@@ -32001,7 +32001,7 @@ $ ${[executable, ...command].join(" ")}
|
|
|
32001
32001
|
runtimeEvidencePath,
|
|
32002
32002
|
outDir,
|
|
32003
32003
|
runId = `${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}-${process.pid}`,
|
|
32004
|
-
projectRoot:
|
|
32004
|
+
projectRoot: projectRoot18,
|
|
32005
32005
|
env = process.env,
|
|
32006
32006
|
executable = process.execPath,
|
|
32007
32007
|
cliPath = process.argv[1]
|
|
@@ -32022,7 +32022,7 @@ $ ${[executable, ...command].join(" ")}
|
|
|
32022
32022
|
runtimeEvidenceBundle.artifact.producer
|
|
32023
32023
|
);
|
|
32024
32024
|
const currentProducer = await resolveRuntimeEvidenceProducer({
|
|
32025
|
-
projectRoot:
|
|
32025
|
+
projectRoot: projectRoot18,
|
|
32026
32026
|
required: true
|
|
32027
32027
|
});
|
|
32028
32028
|
if (!currentProducer || currentProducer.projectSha !== deployedProducer.projectSha || currentProducer.imageDigest !== deployedProducer.imageDigest || currentProducer.runtimePackageManifest.sha256 !== deployedProducer.runtimePackageManifest.sha256) {
|
|
@@ -32070,7 +32070,7 @@ $ ${[executable, ...command].join(" ")}
|
|
|
32070
32070
|
await runLoggedCommand({
|
|
32071
32071
|
executable,
|
|
32072
32072
|
command,
|
|
32073
|
-
cwd:
|
|
32073
|
+
cwd: projectRoot18,
|
|
32074
32074
|
env,
|
|
32075
32075
|
logHandle
|
|
32076
32076
|
});
|
|
@@ -32141,14 +32141,180 @@ var init_runtimeFeedbackReplay2 = __esm({
|
|
|
32141
32141
|
}
|
|
32142
32142
|
});
|
|
32143
32143
|
|
|
32144
|
+
// src/lib/runtimeFeedbackNotification.ts
|
|
32145
|
+
var isRecord4, asRecord7, asArray3, finiteNumber5, requiredTimestamp, escapeHtml5, formatMskDateTime2, formatConnectorName, sumRows, buildRuntimeFeedbackTelegramMessage, notifyRuntimeFeedbackBundle;
|
|
32146
|
+
var init_runtimeFeedbackNotification = __esm({
|
|
32147
|
+
"src/lib/runtimeFeedbackNotification.ts"() {
|
|
32148
|
+
"use strict";
|
|
32149
|
+
init_runtimeFeedbackArtifacts();
|
|
32150
|
+
init_telegramReports();
|
|
32151
|
+
isRecord4 = (value) => value != null && typeof value === "object" && !Array.isArray(value);
|
|
32152
|
+
asRecord7 = (value) => isRecord4(value) ? value : {};
|
|
32153
|
+
asArray3 = (value) => Array.isArray(value) ? value.map(asRecord7) : [];
|
|
32154
|
+
finiteNumber5 = (value, fallback = 0) => {
|
|
32155
|
+
const number = Number(value);
|
|
32156
|
+
return Number.isFinite(number) ? number : fallback;
|
|
32157
|
+
};
|
|
32158
|
+
requiredTimestamp = (value, field) => {
|
|
32159
|
+
const timestamp = Number(value);
|
|
32160
|
+
if (!Number.isFinite(timestamp)) {
|
|
32161
|
+
throw new Error(`Runtime feedback replay is missing ${field}`);
|
|
32162
|
+
}
|
|
32163
|
+
return timestamp;
|
|
32164
|
+
};
|
|
32165
|
+
escapeHtml5 = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
32166
|
+
formatMskDateTime2 = (timestamp) => new Intl.DateTimeFormat("ru-RU", {
|
|
32167
|
+
timeZone: "Europe/Moscow",
|
|
32168
|
+
year: "numeric",
|
|
32169
|
+
month: "2-digit",
|
|
32170
|
+
day: "2-digit",
|
|
32171
|
+
hour: "2-digit",
|
|
32172
|
+
minute: "2-digit",
|
|
32173
|
+
hour12: false
|
|
32174
|
+
}).format(new Date(timestamp));
|
|
32175
|
+
formatConnectorName = (value) => {
|
|
32176
|
+
const connectorName = String(value ?? "unknown").trim() || "unknown";
|
|
32177
|
+
return connectorName.toLowerCase() === "bybit" ? "ByBit" : connectorName;
|
|
32178
|
+
};
|
|
32179
|
+
sumRows = (rows, field) => rows.reduce((total, row) => total + finiteNumber5(row[field]), 0);
|
|
32180
|
+
buildRuntimeFeedbackTelegramMessage = (replayEvidence) => {
|
|
32181
|
+
if (replayEvidence.reportType !== "replay-runtime-evidence") {
|
|
32182
|
+
throw new Error("Invalid runtime feedback replay evidence payload");
|
|
32183
|
+
}
|
|
32184
|
+
const window = asRecord7(replayEvidence.window);
|
|
32185
|
+
const startTime = requiredTimestamp(window.startTime, "window.startTime");
|
|
32186
|
+
const endTime = requiredTimestamp(window.endTime, "window.endTime");
|
|
32187
|
+
const deployment = asRecord7(replayEvidence.deployment);
|
|
32188
|
+
const replay = asRecord7(replayEvidence.replay);
|
|
32189
|
+
if (!isRecord4(replay.runtimeComparison) || !isRecord4(replay.runtimeComparison.counts) || !Array.isArray(replay.runtimeComparison.rows) || !isRecord4(replay.runtimeComparison.lineage)) {
|
|
32190
|
+
throw new Error("Runtime feedback replay comparison is missing");
|
|
32191
|
+
}
|
|
32192
|
+
const comparison = asRecord7(replay.runtimeComparison);
|
|
32193
|
+
const comparisonCounts = asRecord7(comparison.counts);
|
|
32194
|
+
const runtimeCounts = asRecord7(asRecord7(replayEvidence.runtime).counts);
|
|
32195
|
+
const lineage = asRecord7(comparison.lineage);
|
|
32196
|
+
const rows = asArray3(comparison.rows);
|
|
32197
|
+
const matched = finiteNumber5(comparisonCounts.matched);
|
|
32198
|
+
const runtimeOnly = finiteNumber5(comparisonCounts.runtimeOnly);
|
|
32199
|
+
const backtestOnly = finiteNumber5(comparisonCounts.backtestOnly);
|
|
32200
|
+
const orderFailed = sumRows(rows, "orderFailed");
|
|
32201
|
+
const runtimeEntries = sumRows(rows, "runtimeTrades");
|
|
32202
|
+
const backtestEntries = sumRows(rows, "backtestEntries");
|
|
32203
|
+
const replayScopes = finiteNumber5(lineage.replayScopes);
|
|
32204
|
+
const comparableScopes = finiteNumber5(lineage.comparableScopes);
|
|
32205
|
+
const excludedRuntimeTrades = finiteNumber5(lineage.excludedRuntimeTrades);
|
|
32206
|
+
const issueRows = rows.filter(
|
|
32207
|
+
(row) => finiteNumber5(row.runtimeOnly) > 0 || finiteNumber5(row.backtestOnly) > 0 || finiteNumber5(row.orderFailed) > 0
|
|
32208
|
+
);
|
|
32209
|
+
const lines = [
|
|
32210
|
+
"\u{1F9EA} <b>TradeJS runtime parity</b>",
|
|
32211
|
+
"",
|
|
32212
|
+
"\u{1F552} <b>Window</b>",
|
|
32213
|
+
`<b>${escapeHtml5(formatMskDateTime2(startTime))} - ${escapeHtml5(formatMskDateTime2(endTime))} MSK</b>`,
|
|
32214
|
+
"",
|
|
32215
|
+
`\u{1F50C} Connector: <b>${escapeHtml5(formatConnectorName(deployment.connectorName ?? deployment.provider))}</b>`,
|
|
32216
|
+
"\u{1F9EC} Source: <b>verified runtime feedback</b>",
|
|
32217
|
+
`\u{1F4E6} Deployment: <b>${escapeHtml5(String(deployment.id ?? "unknown"))}</b>`,
|
|
32218
|
+
`\u{1F510} Composition: <code>${escapeHtml5(String(deployment.deploymentCompositionId ?? "unknown"))}</code>`,
|
|
32219
|
+
"",
|
|
32220
|
+
"\u{1F4CC} <b>Overview</b>",
|
|
32221
|
+
`\u2022 Runtime evidence: trades=<b>${finiteNumber5(runtimeCounts.trades)}</b>, signals=<b>${finiteNumber5(runtimeCounts.signals)}</b>, evaluations=<b>${finiteNumber5(runtimeCounts.evaluations)}</b>`,
|
|
32222
|
+
`\u2022 Comparable entries: runtime=<b>${runtimeEntries}</b> / backtest=<b>${backtestEntries}</b>`,
|
|
32223
|
+
`\u2022 Matched: <b>${matched}</b> / order failed: <b>${orderFailed}</b>`,
|
|
32224
|
+
`\u2022 Runtime only: <b>${runtimeOnly}</b> / Backtest only: <b>${backtestOnly}</b>`,
|
|
32225
|
+
`\u2022 Lineage scopes: <b>${comparableScopes} / ${replayScopes}</b>`
|
|
32226
|
+
];
|
|
32227
|
+
if (excludedRuntimeTrades > 0) {
|
|
32228
|
+
lines.push(
|
|
32229
|
+
`\u2022 Excluded runtime trades outside comparable lineage: <b>${excludedRuntimeTrades}</b>`
|
|
32230
|
+
);
|
|
32231
|
+
}
|
|
32232
|
+
if (issueRows.length) {
|
|
32233
|
+
lines.push("", "\u{1F4CA} <b>Strategy issues</b>");
|
|
32234
|
+
for (const row of issueRows.slice(0, 10)) {
|
|
32235
|
+
const issues = [
|
|
32236
|
+
finiteNumber5(row.orderFailed) > 0 ? `orderFailed=${finiteNumber5(row.orderFailed)}` : null,
|
|
32237
|
+
finiteNumber5(row.runtimeOnly) > 0 ? `runtimeOnly=${finiteNumber5(row.runtimeOnly)}` : null,
|
|
32238
|
+
finiteNumber5(row.backtestOnly) > 0 ? `backtestOnly=${finiteNumber5(row.backtestOnly)}` : null
|
|
32239
|
+
].filter((value) => value != null);
|
|
32240
|
+
lines.push(
|
|
32241
|
+
`\u2022 ${escapeHtml5(String(row.strategyName ?? "[unknown]"))}: ${issues.join(", ")}`
|
|
32242
|
+
);
|
|
32243
|
+
}
|
|
32244
|
+
if (issueRows.length > 10) {
|
|
32245
|
+
lines.push(`... <b>${issueRows.length - 10}</b> more`);
|
|
32246
|
+
}
|
|
32247
|
+
} else if (rows.length) {
|
|
32248
|
+
lines.push(
|
|
32249
|
+
"",
|
|
32250
|
+
`\u{1F4CA} <b>Strategies</b>: clean <b>${rows.length}</b> / total <b>${rows.length}</b>`
|
|
32251
|
+
);
|
|
32252
|
+
}
|
|
32253
|
+
return lines.join("\n");
|
|
32254
|
+
};
|
|
32255
|
+
notifyRuntimeFeedbackBundle = async ({
|
|
32256
|
+
bundleDir,
|
|
32257
|
+
send = sendTelegramReport
|
|
32258
|
+
}) => {
|
|
32259
|
+
const verified = await verifyRuntimeFeedbackReplayBundle(bundleDir);
|
|
32260
|
+
const message = buildRuntimeFeedbackTelegramMessage(verified.replayEvidence);
|
|
32261
|
+
await send(message, { userName: verified.manifest.userName });
|
|
32262
|
+
return {
|
|
32263
|
+
artifactId: verified.manifest.artifactId,
|
|
32264
|
+
userName: verified.manifest.userName,
|
|
32265
|
+
message
|
|
32266
|
+
};
|
|
32267
|
+
};
|
|
32268
|
+
}
|
|
32269
|
+
});
|
|
32270
|
+
|
|
32271
|
+
// src/scripts/runtimeFeedbackNotify.ts
|
|
32272
|
+
var runtimeFeedbackNotify_exports = {};
|
|
32273
|
+
__export(runtimeFeedbackNotify_exports, {
|
|
32274
|
+
main: () => main36,
|
|
32275
|
+
runtimeFeedbackNotify: () => runtimeFeedbackNotify
|
|
32276
|
+
});
|
|
32277
|
+
var import_node_path25, import_args28, import_chalk45, flags26, projectRoot10, runtimeFeedbackNotify, main36;
|
|
32278
|
+
var init_runtimeFeedbackNotify = __esm({
|
|
32279
|
+
"src/scripts/runtimeFeedbackNotify.ts"() {
|
|
32280
|
+
"use strict";
|
|
32281
|
+
import_node_path25 = __toESM(require("path"));
|
|
32282
|
+
import_args28 = __toESM(require("args"));
|
|
32283
|
+
import_chalk45 = __toESM(require("chalk"));
|
|
32284
|
+
init_runtimeFeedbackNotification();
|
|
32285
|
+
init_runtimeFeedbackArtifacts();
|
|
32286
|
+
import_args28.default.option("bundle", "Verified runtime feedback replay bundle directory");
|
|
32287
|
+
import_args28.default.option("dryRun", "Verify and print the message without sending it", false);
|
|
32288
|
+
flags26 = import_args28.default.parse(process.argv);
|
|
32289
|
+
projectRoot10 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
|
|
32290
|
+
runtimeFeedbackNotify = async () => {
|
|
32291
|
+
const bundle = String(flags26.bundle ?? "").trim();
|
|
32292
|
+
if (!bundle) {
|
|
32293
|
+
throw new Error("Provide --bundle for runtime feedback notification.");
|
|
32294
|
+
}
|
|
32295
|
+
const bundleDir = import_node_path25.default.resolve(projectRoot10, bundle);
|
|
32296
|
+
if (flags26.dryRun) {
|
|
32297
|
+
const verified = await verifyRuntimeFeedbackReplayBundle(bundleDir);
|
|
32298
|
+
console.log(buildRuntimeFeedbackTelegramMessage(verified.replayEvidence));
|
|
32299
|
+
return;
|
|
32300
|
+
}
|
|
32301
|
+
const result = await notifyRuntimeFeedbackBundle({ bundleDir });
|
|
32302
|
+
console.log(
|
|
32303
|
+
import_chalk45.default.green(`Runtime feedback notification sent: ${result.artifactId}`)
|
|
32304
|
+
);
|
|
32305
|
+
};
|
|
32306
|
+
main36 = runtimeFeedbackNotify;
|
|
32307
|
+
}
|
|
32308
|
+
});
|
|
32309
|
+
|
|
32144
32310
|
// src/lib/runtimeEvidenceSync.ts
|
|
32145
|
-
var import_node_child_process7, import_promises29,
|
|
32311
|
+
var import_node_child_process7, import_promises29, import_node_path26, import_node_util, execFileAsync, isExistingDestinationError2, safeSegment4, withTrailingSlash, dateParts2, buildRuntimeEvidenceRsyncArgs, receiptPath, compareBundles, listPendingRuntimeEvidenceBundles, markRuntimeEvidenceBundleProcessed, syncRuntimeEvidenceBundles;
|
|
32146
32312
|
var init_runtimeEvidenceSync = __esm({
|
|
32147
32313
|
"src/lib/runtimeEvidenceSync.ts"() {
|
|
32148
32314
|
"use strict";
|
|
32149
32315
|
import_node_child_process7 = require("child_process");
|
|
32150
32316
|
import_promises29 = __toESM(require("fs/promises"));
|
|
32151
|
-
|
|
32317
|
+
import_node_path26 = __toESM(require("path"));
|
|
32152
32318
|
import_node_util = require("util");
|
|
32153
32319
|
init_runtimeEvidenceArtifacts();
|
|
32154
32320
|
init_runtimeEvidenceDeployment();
|
|
@@ -32182,15 +32348,15 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
32182
32348
|
withTrailingSlash(source),
|
|
32183
32349
|
withTrailingSlash(destination)
|
|
32184
32350
|
];
|
|
32185
|
-
receiptPath = (receiptsRoot, artifactId) =>
|
|
32351
|
+
receiptPath = (receiptsRoot, artifactId) => import_node_path26.default.join(receiptsRoot, `${safeSegment4(artifactId, "artifact")}.json`);
|
|
32186
32352
|
compareBundles = (left, right) => left.manifest.window.endTime - right.manifest.window.endTime || left.manifest.createdAt - right.manifest.createdAt;
|
|
32187
32353
|
listPendingRuntimeEvidenceBundles = async ({
|
|
32188
32354
|
evidenceRoot,
|
|
32189
32355
|
deploymentId
|
|
32190
32356
|
}) => {
|
|
32191
32357
|
const safeDeploymentId = safeSegment4(deploymentId, "production");
|
|
32192
|
-
const artifactsRoot =
|
|
32193
|
-
const receiptsRoot =
|
|
32358
|
+
const artifactsRoot = import_node_path26.default.join(evidenceRoot, "artifacts", safeDeploymentId);
|
|
32359
|
+
const receiptsRoot = import_node_path26.default.join(evidenceRoot, "receipts", safeDeploymentId);
|
|
32194
32360
|
const bundles = await discoverRuntimeEvidenceBundles(artifactsRoot);
|
|
32195
32361
|
const pending = [];
|
|
32196
32362
|
for (const bundleDir of bundles) {
|
|
@@ -32221,7 +32387,7 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
32221
32387
|
`Artifact deployment mismatch: expected ${safeDeploymentId}, received ${verified.manifest.deploymentId}`
|
|
32222
32388
|
);
|
|
32223
32389
|
}
|
|
32224
|
-
const receiptsRoot =
|
|
32390
|
+
const receiptsRoot = import_node_path26.default.join(evidenceRoot, "receipts", safeDeploymentId);
|
|
32225
32391
|
const finalPath = receiptPath(receiptsRoot, verified.manifest.artifactId);
|
|
32226
32392
|
const temporaryPath = `${finalPath}.tmp-${process.pid}`;
|
|
32227
32393
|
const receipt = {
|
|
@@ -32249,16 +32415,16 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
32249
32415
|
source,
|
|
32250
32416
|
evidenceRoot,
|
|
32251
32417
|
deploymentId,
|
|
32252
|
-
runRsync = async (
|
|
32253
|
-
const result = await execFileAsync("rsync",
|
|
32418
|
+
runRsync = async (args38) => {
|
|
32419
|
+
const result = await execFileAsync("rsync", args38, {
|
|
32254
32420
|
maxBuffer: 10 * 1024 * 1024
|
|
32255
32421
|
});
|
|
32256
32422
|
return { stdout: result.stdout, stderr: result.stderr };
|
|
32257
32423
|
}
|
|
32258
32424
|
}) => {
|
|
32259
32425
|
const safeDeploymentId = safeSegment4(deploymentId, "production");
|
|
32260
|
-
const inboxRoot =
|
|
32261
|
-
const artifactsRoot =
|
|
32426
|
+
const inboxRoot = import_node_path26.default.join(evidenceRoot, "inbox", safeDeploymentId);
|
|
32427
|
+
const artifactsRoot = import_node_path26.default.join(evidenceRoot, "artifacts", safeDeploymentId);
|
|
32262
32428
|
await Promise.all([
|
|
32263
32429
|
import_promises29.default.mkdir(inboxRoot, { recursive: true }),
|
|
32264
32430
|
import_promises29.default.mkdir(artifactsRoot, { recursive: true })
|
|
@@ -32278,12 +32444,12 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
32278
32444
|
);
|
|
32279
32445
|
}
|
|
32280
32446
|
assertCurrentRuntimeEvidenceArtifact(verified.artifact);
|
|
32281
|
-
const destinationDir =
|
|
32447
|
+
const destinationDir = import_node_path26.default.join(
|
|
32282
32448
|
artifactsRoot,
|
|
32283
32449
|
...dateParts2(verified.manifest.window.endTime),
|
|
32284
32450
|
safeSegment4(verified.manifest.artifactId, "artifact")
|
|
32285
32451
|
);
|
|
32286
|
-
await import_promises29.default.mkdir(
|
|
32452
|
+
await import_promises29.default.mkdir(import_node_path26.default.dirname(destinationDir), { recursive: true });
|
|
32287
32453
|
try {
|
|
32288
32454
|
await import_promises29.default.rename(bundleDir, destinationDir);
|
|
32289
32455
|
} catch (error) {
|
|
@@ -32314,13 +32480,13 @@ var init_runtimeEvidenceSync = __esm({
|
|
|
32314
32480
|
});
|
|
32315
32481
|
|
|
32316
32482
|
// src/lib/runtimeFeedbackSync.ts
|
|
32317
|
-
var import_node_child_process8, import_promises30,
|
|
32483
|
+
var import_node_child_process8, import_promises30, import_node_path27, import_node_util2, execFileAsync2, isExistingDestinationError3, safeSegment5, dateParts3, syncRuntimeFeedbackReplayBundles;
|
|
32318
32484
|
var init_runtimeFeedbackSync = __esm({
|
|
32319
32485
|
"src/lib/runtimeFeedbackSync.ts"() {
|
|
32320
32486
|
"use strict";
|
|
32321
32487
|
import_node_child_process8 = require("child_process");
|
|
32322
32488
|
import_promises30 = __toESM(require("fs/promises"));
|
|
32323
|
-
|
|
32489
|
+
import_node_path27 = __toESM(require("path"));
|
|
32324
32490
|
import_node_util2 = require("util");
|
|
32325
32491
|
init_runtimeFeedbackArtifacts();
|
|
32326
32492
|
init_runtimeEvidenceSync();
|
|
@@ -32345,16 +32511,16 @@ var init_runtimeFeedbackSync = __esm({
|
|
|
32345
32511
|
source,
|
|
32346
32512
|
feedbackRoot,
|
|
32347
32513
|
deploymentId,
|
|
32348
|
-
runRsync = async (
|
|
32349
|
-
const result = await execFileAsync2("rsync",
|
|
32514
|
+
runRsync = async (args38) => {
|
|
32515
|
+
const result = await execFileAsync2("rsync", args38, {
|
|
32350
32516
|
maxBuffer: 10 * 1024 * 1024
|
|
32351
32517
|
});
|
|
32352
32518
|
return { stdout: result.stdout, stderr: result.stderr };
|
|
32353
32519
|
}
|
|
32354
32520
|
}) => {
|
|
32355
32521
|
const safeDeploymentId = safeSegment5(deploymentId, "production");
|
|
32356
|
-
const inboxRoot =
|
|
32357
|
-
const artifactsRoot =
|
|
32522
|
+
const inboxRoot = import_node_path27.default.join(feedbackRoot, "inbox", safeDeploymentId);
|
|
32523
|
+
const artifactsRoot = import_node_path27.default.join(feedbackRoot, "artifacts", safeDeploymentId);
|
|
32358
32524
|
await Promise.all([
|
|
32359
32525
|
import_promises30.default.mkdir(inboxRoot, { recursive: true }),
|
|
32360
32526
|
import_promises30.default.mkdir(artifactsRoot, { recursive: true })
|
|
@@ -32373,13 +32539,13 @@ var init_runtimeFeedbackSync = __esm({
|
|
|
32373
32539
|
`Runtime feedback deployment mismatch: expected ${safeDeploymentId}, received ${verified.manifest.deploymentId}`
|
|
32374
32540
|
);
|
|
32375
32541
|
}
|
|
32376
|
-
const destinationDir =
|
|
32542
|
+
const destinationDir = import_node_path27.default.join(
|
|
32377
32543
|
artifactsRoot,
|
|
32378
32544
|
...dateParts3(verified.manifest.window.endTime),
|
|
32379
32545
|
safeSegment5(verified.manifest.runtimeEvidence.artifactId, "artifact"),
|
|
32380
32546
|
safeSegment5(verified.manifest.runId, "run")
|
|
32381
32547
|
);
|
|
32382
|
-
await import_promises30.default.mkdir(
|
|
32548
|
+
await import_promises30.default.mkdir(import_node_path27.default.dirname(destinationDir), { recursive: true });
|
|
32383
32549
|
try {
|
|
32384
32550
|
await import_promises30.default.rename(bundleDir, destinationDir);
|
|
32385
32551
|
} catch (error) {
|
|
@@ -32407,49 +32573,49 @@ var init_runtimeFeedbackSync = __esm({
|
|
|
32407
32573
|
// src/scripts/runtimeFeedbackSync.ts
|
|
32408
32574
|
var runtimeFeedbackSync_exports = {};
|
|
32409
32575
|
__export(runtimeFeedbackSync_exports, {
|
|
32410
|
-
main: () =>
|
|
32576
|
+
main: () => main37,
|
|
32411
32577
|
runtimeFeedbackSync: () => runtimeFeedbackSync
|
|
32412
32578
|
});
|
|
32413
|
-
var
|
|
32579
|
+
var import_node_path28, import_args29, import_chalk46, flags27, projectRoot11, runtimeFeedbackSync, main37;
|
|
32414
32580
|
var init_runtimeFeedbackSync2 = __esm({
|
|
32415
32581
|
"src/scripts/runtimeFeedbackSync.ts"() {
|
|
32416
32582
|
"use strict";
|
|
32417
|
-
|
|
32418
|
-
|
|
32419
|
-
|
|
32583
|
+
import_node_path28 = __toESM(require("path"));
|
|
32584
|
+
import_args29 = __toESM(require("args"));
|
|
32585
|
+
import_chalk46 = __toESM(require("chalk"));
|
|
32420
32586
|
init_runtimeFeedbackSync();
|
|
32421
|
-
|
|
32587
|
+
import_args29.default.option(
|
|
32422
32588
|
"source",
|
|
32423
32589
|
"Rsync source ending at the runtime feedback ready directory",
|
|
32424
32590
|
process.env.RUNTIME_FEEDBACK_RSYNC_SOURCE
|
|
32425
32591
|
);
|
|
32426
|
-
|
|
32592
|
+
import_args29.default.option(
|
|
32427
32593
|
"deployment",
|
|
32428
32594
|
"Deployment id expected in runtime feedback manifests",
|
|
32429
32595
|
process.env.RUNTIME_EVIDENCE_DEPLOYMENT_ID || "production"
|
|
32430
32596
|
);
|
|
32431
|
-
|
|
32597
|
+
import_args29.default.option(
|
|
32432
32598
|
"dir",
|
|
32433
32599
|
"Local runtime feedback storage root",
|
|
32434
32600
|
process.env.RUNTIME_FEEDBACK_LOCAL_DIR || "data/runtime-feedback"
|
|
32435
32601
|
);
|
|
32436
|
-
|
|
32437
|
-
|
|
32602
|
+
flags27 = import_args29.default.parse(process.argv);
|
|
32603
|
+
projectRoot11 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
|
|
32438
32604
|
runtimeFeedbackSync = async () => {
|
|
32439
|
-
const source = String(
|
|
32605
|
+
const source = String(flags27.source ?? "").trim();
|
|
32440
32606
|
if (!source) {
|
|
32441
32607
|
throw new Error(
|
|
32442
32608
|
"Provide --source or RUNTIME_FEEDBACK_RSYNC_SOURCE for runtime feedback sync."
|
|
32443
32609
|
);
|
|
32444
32610
|
}
|
|
32445
|
-
const feedbackRoot =
|
|
32611
|
+
const feedbackRoot = import_node_path28.default.resolve(projectRoot11, String(flags27.dir));
|
|
32446
32612
|
const result = await syncRuntimeFeedbackReplayBundles({
|
|
32447
32613
|
source,
|
|
32448
32614
|
feedbackRoot,
|
|
32449
|
-
deploymentId: String(
|
|
32615
|
+
deploymentId: String(flags27.deployment)
|
|
32450
32616
|
});
|
|
32451
32617
|
console.log(
|
|
32452
|
-
|
|
32618
|
+
import_chalk46.default.green(
|
|
32453
32619
|
`Runtime feedback sync completed: received=${result.received.length}`
|
|
32454
32620
|
)
|
|
32455
32621
|
);
|
|
@@ -32469,18 +32635,18 @@ var init_runtimeFeedbackSync2 = __esm({
|
|
|
32469
32635
|
)
|
|
32470
32636
|
);
|
|
32471
32637
|
};
|
|
32472
|
-
|
|
32638
|
+
main37 = runtimeFeedbackSync;
|
|
32473
32639
|
}
|
|
32474
32640
|
});
|
|
32475
32641
|
|
|
32476
32642
|
// src/lib/runtimeEvidenceCompositionSnapshots.ts
|
|
32477
|
-
var import_node_crypto15, import_promises31,
|
|
32643
|
+
var import_node_crypto15, import_promises31, import_node_path29, SNAPSHOT_FILE, MANIFEST_FILE, COMPLETE_FILE, createRuntimeEvidenceCompositionSnapshotRecorder, isRecord5, sha2564, safeSegment6, isExistingDestinationError4, parseManifest3, verifyRuntimeEvidenceCompositionSnapshot, sameSnapshot, publishRuntimeEvidenceCompositionSnapshot, captureRuntimeEvidenceCompositionSnapshot, discoverRuntimeEvidenceCompositionSnapshots;
|
|
32478
32644
|
var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
32479
32645
|
"src/lib/runtimeEvidenceCompositionSnapshots.ts"() {
|
|
32480
32646
|
"use strict";
|
|
32481
32647
|
import_node_crypto15 = require("crypto");
|
|
32482
32648
|
import_promises31 = __toESM(require("fs/promises"));
|
|
32483
|
-
|
|
32649
|
+
import_node_path29 = __toESM(require("path"));
|
|
32484
32650
|
init_runtimeEvidenceDeployment();
|
|
32485
32651
|
init_runtimeEvidenceProducer();
|
|
32486
32652
|
SNAPSHOT_FILE = "snapshot.json";
|
|
@@ -32500,7 +32666,7 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
|
32500
32666
|
}
|
|
32501
32667
|
};
|
|
32502
32668
|
};
|
|
32503
|
-
|
|
32669
|
+
isRecord5 = (value) => value != null && typeof value === "object" && !Array.isArray(value);
|
|
32504
32670
|
sha2564 = (value) => (0, import_node_crypto15.createHash)("sha256").update(value).digest("hex");
|
|
32505
32671
|
safeSegment6 = (value, label) => {
|
|
32506
32672
|
const normalized = value.trim();
|
|
@@ -32514,8 +32680,8 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
|
32514
32680
|
return code === "EEXIST" || code === "ENOTEMPTY";
|
|
32515
32681
|
};
|
|
32516
32682
|
parseManifest3 = (value) => {
|
|
32517
|
-
const manifest =
|
|
32518
|
-
const payload =
|
|
32683
|
+
const manifest = isRecord5(value) ? value : null;
|
|
32684
|
+
const payload = isRecord5(manifest?.payload) ? manifest.payload : null;
|
|
32519
32685
|
if (manifest?.schemaVersion !== 1 || manifest.reportType !== "runtime-evidence-composition-snapshot" || typeof manifest.createdAt !== "number" || typeof manifest.userName !== "string" || typeof manifest.deploymentId !== "string" || typeof manifest.deploymentCompositionId !== "string" || payload?.file !== SNAPSHOT_FILE || typeof payload.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(payload.sha256) || typeof payload.bytes !== "number") {
|
|
32520
32686
|
throw new Error("Invalid runtime evidence composition snapshot manifest");
|
|
32521
32687
|
}
|
|
@@ -32523,9 +32689,9 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
|
32523
32689
|
};
|
|
32524
32690
|
verifyRuntimeEvidenceCompositionSnapshot = async (bundleDir) => {
|
|
32525
32691
|
const [manifestText, payload, completeText] = await Promise.all([
|
|
32526
|
-
import_promises31.default.readFile(
|
|
32527
|
-
import_promises31.default.readFile(
|
|
32528
|
-
import_promises31.default.readFile(
|
|
32692
|
+
import_promises31.default.readFile(import_node_path29.default.join(bundleDir, MANIFEST_FILE), "utf8"),
|
|
32693
|
+
import_promises31.default.readFile(import_node_path29.default.join(bundleDir, SNAPSHOT_FILE)),
|
|
32694
|
+
import_promises31.default.readFile(import_node_path29.default.join(bundleDir, COMPLETE_FILE), "utf8")
|
|
32529
32695
|
]);
|
|
32530
32696
|
const manifest = parseManifest3(JSON.parse(manifestText));
|
|
32531
32697
|
if (completeText.trim() !== manifest.deploymentCompositionId) {
|
|
@@ -32537,7 +32703,7 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
|
32537
32703
|
);
|
|
32538
32704
|
}
|
|
32539
32705
|
const value = JSON.parse(payload.toString("utf8"));
|
|
32540
|
-
const record =
|
|
32706
|
+
const record = isRecord5(value) ? value : null;
|
|
32541
32707
|
if (record?.schemaVersion !== 1 || record.reportType !== "runtime-evidence-composition-snapshot" || record.userName !== manifest.userName) {
|
|
32542
32708
|
throw new Error(
|
|
32543
32709
|
`Invalid runtime evidence snapshot payload in ${bundleDir}`
|
|
@@ -32588,9 +32754,9 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
|
32588
32754
|
bytes: Buffer.byteLength(payload)
|
|
32589
32755
|
}
|
|
32590
32756
|
};
|
|
32591
|
-
const snapshotsRoot =
|
|
32592
|
-
const bundleDir =
|
|
32593
|
-
const temporaryDir =
|
|
32757
|
+
const snapshotsRoot = import_node_path29.default.join(evidenceRoot, "snapshots", deploymentId);
|
|
32758
|
+
const bundleDir = import_node_path29.default.join(snapshotsRoot, compositionId);
|
|
32759
|
+
const temporaryDir = import_node_path29.default.join(
|
|
32594
32760
|
evidenceRoot,
|
|
32595
32761
|
"incoming",
|
|
32596
32762
|
`snapshot-${compositionId}.tmp-${(0, import_node_crypto15.randomUUID)()}`
|
|
@@ -32598,16 +32764,16 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
|
32598
32764
|
await import_promises31.default.mkdir(temporaryDir, { recursive: true });
|
|
32599
32765
|
try {
|
|
32600
32766
|
await Promise.all([
|
|
32601
|
-
import_promises31.default.writeFile(
|
|
32767
|
+
import_promises31.default.writeFile(import_node_path29.default.join(temporaryDir, SNAPSHOT_FILE), payload, "utf8"),
|
|
32602
32768
|
import_promises31.default.writeFile(
|
|
32603
|
-
|
|
32769
|
+
import_node_path29.default.join(temporaryDir, MANIFEST_FILE),
|
|
32604
32770
|
`${JSON.stringify(manifest, null, 2)}
|
|
32605
32771
|
`,
|
|
32606
32772
|
"utf8"
|
|
32607
32773
|
)
|
|
32608
32774
|
]);
|
|
32609
32775
|
await import_promises31.default.writeFile(
|
|
32610
|
-
|
|
32776
|
+
import_node_path29.default.join(temporaryDir, COMPLETE_FILE),
|
|
32611
32777
|
`${compositionId}
|
|
32612
32778
|
`,
|
|
32613
32779
|
"utf8"
|
|
@@ -32632,7 +32798,7 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
|
32632
32798
|
return verified;
|
|
32633
32799
|
};
|
|
32634
32800
|
captureRuntimeEvidenceCompositionSnapshot = async ({
|
|
32635
|
-
projectRoot:
|
|
32801
|
+
projectRoot: projectRoot18,
|
|
32636
32802
|
userName: userName3,
|
|
32637
32803
|
deploymentId,
|
|
32638
32804
|
expectedCompositionId
|
|
@@ -32640,10 +32806,10 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
|
32640
32806
|
const [deployment, producer] = await Promise.all([
|
|
32641
32807
|
resolveRuntimeEvidenceDeploymentSnapshot({
|
|
32642
32808
|
userName: userName3,
|
|
32643
|
-
projectRoot:
|
|
32809
|
+
projectRoot: projectRoot18,
|
|
32644
32810
|
deploymentId
|
|
32645
32811
|
}),
|
|
32646
|
-
resolveRuntimeEvidenceProducer({ projectRoot:
|
|
32812
|
+
resolveRuntimeEvidenceProducer({ projectRoot: projectRoot18, required: true })
|
|
32647
32813
|
]);
|
|
32648
32814
|
if (!producer) {
|
|
32649
32815
|
throw new Error("Runtime evidence producer identity is required");
|
|
@@ -32654,14 +32820,14 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
|
32654
32820
|
);
|
|
32655
32821
|
}
|
|
32656
32822
|
await publishRuntimeEvidenceCompositionSnapshot({
|
|
32657
|
-
evidenceRoot:
|
|
32823
|
+
evidenceRoot: import_node_path29.default.join(projectRoot18, "data", "runtime-evidence"),
|
|
32658
32824
|
userName: userName3,
|
|
32659
32825
|
deployment,
|
|
32660
32826
|
producer
|
|
32661
32827
|
});
|
|
32662
32828
|
};
|
|
32663
32829
|
discoverRuntimeEvidenceCompositionSnapshots = async (evidenceRoot) => {
|
|
32664
|
-
const rootDir =
|
|
32830
|
+
const rootDir = import_node_path29.default.join(evidenceRoot, "snapshots");
|
|
32665
32831
|
const bundleDirs = [];
|
|
32666
32832
|
let deployments;
|
|
32667
32833
|
try {
|
|
@@ -32671,14 +32837,14 @@ var init_runtimeEvidenceCompositionSnapshots = __esm({
|
|
|
32671
32837
|
throw error;
|
|
32672
32838
|
}
|
|
32673
32839
|
for (const deployment of deployments.filter((entry) => entry.isDirectory())) {
|
|
32674
|
-
const deploymentDir =
|
|
32840
|
+
const deploymentDir = import_node_path29.default.join(rootDir, deployment.name);
|
|
32675
32841
|
const compositions = await import_promises31.default.readdir(deploymentDir, {
|
|
32676
32842
|
withFileTypes: true
|
|
32677
32843
|
});
|
|
32678
32844
|
bundleDirs.push(
|
|
32679
32845
|
...compositions.filter(
|
|
32680
32846
|
(entry) => entry.isDirectory() && !entry.name.startsWith(".") && !entry.name.includes(".tmp-")
|
|
32681
|
-
).map((entry) =>
|
|
32847
|
+
).map((entry) => import_node_path29.default.join(deploymentDir, entry.name))
|
|
32682
32848
|
);
|
|
32683
32849
|
}
|
|
32684
32850
|
return Promise.all(
|
|
@@ -32847,52 +33013,52 @@ var init_runtimeEvidenceCompositions = __esm({
|
|
|
32847
33013
|
// src/scripts/runtimeEvidence.ts
|
|
32848
33014
|
var runtimeEvidence_exports = {};
|
|
32849
33015
|
__export(runtimeEvidence_exports, {
|
|
32850
|
-
main: () =>
|
|
33016
|
+
main: () => main38,
|
|
32851
33017
|
runtimeEvidence: () => runtimeEvidence
|
|
32852
33018
|
});
|
|
32853
|
-
var import_promises32,
|
|
33019
|
+
var import_promises32, import_node_path30, import_args30, import_chalk47, flags28, projectRoot12, toEpochMs3, resolveWindow2, parseStrategyFilter2, runtimeEvidence, main38;
|
|
32854
33020
|
var init_runtimeEvidence = __esm({
|
|
32855
33021
|
"src/scripts/runtimeEvidence.ts"() {
|
|
32856
33022
|
"use strict";
|
|
32857
33023
|
import_promises32 = __toESM(require("fs/promises"));
|
|
32858
|
-
|
|
32859
|
-
|
|
32860
|
-
|
|
33024
|
+
import_node_path30 = __toESM(require("path"));
|
|
33025
|
+
import_args30 = __toESM(require("args"));
|
|
33026
|
+
import_chalk47 = __toESM(require("chalk"));
|
|
32861
33027
|
init_runtimeDebugEvidence();
|
|
32862
33028
|
init_runtimeEvidenceArtifacts();
|
|
32863
33029
|
init_runtimeEvidenceCompositions();
|
|
32864
33030
|
init_runtimeLineage();
|
|
32865
33031
|
init_runtimeEvidenceProducer();
|
|
32866
33032
|
init_runtimeEvidenceDeployment();
|
|
32867
|
-
|
|
32868
|
-
|
|
33033
|
+
import_args30.default.option(["u", "user"], "Use user config", "root");
|
|
33034
|
+
import_args30.default.option(
|
|
32869
33035
|
["S", "startTime"],
|
|
32870
33036
|
"Window start timestamp, seconds/ms, or ISO date"
|
|
32871
33037
|
);
|
|
32872
|
-
|
|
32873
|
-
|
|
33038
|
+
import_args30.default.option(["E", "endTime"], "Window end timestamp, seconds/ms, or ISO date");
|
|
33039
|
+
import_args30.default.option(
|
|
32874
33040
|
["H", "hours"],
|
|
32875
33041
|
"Fallback window in hours when start/end are omitted",
|
|
32876
33042
|
24
|
|
32877
33043
|
);
|
|
32878
|
-
|
|
33044
|
+
import_args30.default.option(
|
|
32879
33045
|
"daily",
|
|
32880
33046
|
"Use the latest complete 21:00 MSK to 21:00 MSK window",
|
|
32881
33047
|
false
|
|
32882
33048
|
);
|
|
32883
|
-
|
|
32884
|
-
|
|
32885
|
-
|
|
33049
|
+
import_args30.default.option(["s", "strategy"], "Strategy filter, comma-separated");
|
|
33050
|
+
import_args30.default.option(["o", "out"], "Output JSON path", "output/runtime-evidence.json");
|
|
33051
|
+
import_args30.default.option(
|
|
32886
33052
|
"publishDir",
|
|
32887
33053
|
"Publish an immutable bundle under <dir>/ready/<deployment>"
|
|
32888
33054
|
);
|
|
32889
|
-
|
|
33055
|
+
import_args30.default.option(
|
|
32890
33056
|
"deployment",
|
|
32891
33057
|
"Deployment id used by immutable evidence bundles",
|
|
32892
33058
|
process.env.RUNTIME_EVIDENCE_DEPLOYMENT_ID || "production"
|
|
32893
33059
|
);
|
|
32894
|
-
|
|
32895
|
-
|
|
33060
|
+
flags28 = import_args30.default.parse(process.argv);
|
|
33061
|
+
projectRoot12 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
|
|
32896
33062
|
toEpochMs3 = (value) => {
|
|
32897
33063
|
if (value == null || value === "") {
|
|
32898
33064
|
return null;
|
|
@@ -32906,11 +33072,11 @@ var init_runtimeEvidence = __esm({
|
|
|
32906
33072
|
return Number.isFinite(parsed) ? parsed : null;
|
|
32907
33073
|
};
|
|
32908
33074
|
resolveWindow2 = () => {
|
|
32909
|
-
const explicitStartTime = toEpochMs3(
|
|
32910
|
-
const explicitEndTime = toEpochMs3(
|
|
33075
|
+
const explicitStartTime = toEpochMs3(flags28.startTime);
|
|
33076
|
+
const explicitEndTime = toEpochMs3(flags28.endTime);
|
|
32911
33077
|
const now2 = Date.now();
|
|
32912
33078
|
const dailyEndTime = (() => {
|
|
32913
|
-
if (!
|
|
33079
|
+
if (!flags28.daily || explicitStartTime != null || explicitEndTime != null) {
|
|
32914
33080
|
return null;
|
|
32915
33081
|
}
|
|
32916
33082
|
const date = new Date(now2);
|
|
@@ -32925,7 +33091,7 @@ var init_runtimeEvidence = __esm({
|
|
|
32925
33091
|
const endTime = explicitEndTime ?? dailyEndTime ?? now2;
|
|
32926
33092
|
const hours = Math.max(
|
|
32927
33093
|
1,
|
|
32928
|
-
Number.parseInt(String(
|
|
33094
|
+
Number.parseInt(String(flags28.hours ?? 24), 10) || 24
|
|
32929
33095
|
);
|
|
32930
33096
|
const startTime = explicitStartTime ?? endTime - hours * 60 * 60 * 1e3;
|
|
32931
33097
|
if (startTime >= endTime) {
|
|
@@ -32942,27 +33108,27 @@ var init_runtimeEvidence = __esm({
|
|
|
32942
33108
|
parseStrategyFilter2 = (value) => String(value ?? "").split(",").map((item) => item.trim()).filter(Boolean);
|
|
32943
33109
|
runtimeEvidence = async () => {
|
|
32944
33110
|
const { startTime, endTime, source } = resolveWindow2();
|
|
32945
|
-
const deploymentId = String(
|
|
32946
|
-
const publishDir = String(
|
|
33111
|
+
const deploymentId = String(flags28.deployment);
|
|
33112
|
+
const publishDir = String(flags28.publishDir ?? "").trim();
|
|
32947
33113
|
const producer = await resolveRuntimeEvidenceProducer({
|
|
32948
|
-
projectRoot:
|
|
33114
|
+
projectRoot: projectRoot12,
|
|
32949
33115
|
required: Boolean(publishDir)
|
|
32950
33116
|
});
|
|
32951
33117
|
const deploymentSnapshot = await resolveRuntimeEvidenceDeploymentSnapshot({
|
|
32952
|
-
userName: String(
|
|
32953
|
-
projectRoot:
|
|
33118
|
+
userName: String(flags28.user),
|
|
33119
|
+
projectRoot: projectRoot12,
|
|
32954
33120
|
deploymentId
|
|
32955
33121
|
});
|
|
32956
|
-
const requestedStrategies = parseStrategyFilter2(
|
|
33122
|
+
const requestedStrategies = parseStrategyFilter2(flags28.strategy);
|
|
32957
33123
|
const evidence = await collectRuntimeDebugEvidence({
|
|
32958
|
-
userName:
|
|
33124
|
+
userName: flags28.user,
|
|
32959
33125
|
startTime,
|
|
32960
33126
|
endTime,
|
|
32961
33127
|
strategies: requestedStrategies.length ? requestedStrategies : void 0,
|
|
32962
33128
|
deploymentId
|
|
32963
33129
|
});
|
|
32964
33130
|
const snapshots = publishDir && producer ? await loadRuntimeEvidenceCompositionSnapshots({
|
|
32965
|
-
publishRoot:
|
|
33131
|
+
publishRoot: import_node_path30.default.resolve(projectRoot12, publishDir),
|
|
32966
33132
|
currentDeployment: deploymentSnapshot,
|
|
32967
33133
|
currentProducer: producer
|
|
32968
33134
|
}) : /* @__PURE__ */ new Map([
|
|
@@ -32995,7 +33161,7 @@ var init_runtimeEvidence = __esm({
|
|
|
32995
33161
|
(strategyName) => !requestedStrategies.length || requestedStrategies.includes(strategyName)
|
|
32996
33162
|
);
|
|
32997
33163
|
const runtime = buildRuntimeEvidenceReportPayload({
|
|
32998
|
-
userName:
|
|
33164
|
+
userName: flags28.user,
|
|
32999
33165
|
startTime,
|
|
33000
33166
|
endTime,
|
|
33001
33167
|
signals: composition.signals,
|
|
@@ -33014,7 +33180,7 @@ var init_runtimeEvidence = __esm({
|
|
|
33014
33180
|
generatedAt: Date.now(),
|
|
33015
33181
|
...composition.producer ? { producer: composition.producer } : {},
|
|
33016
33182
|
...producer && composition.producer && composition.producer !== producer ? { collector: producer } : {},
|
|
33017
|
-
userName:
|
|
33183
|
+
userName: flags28.user,
|
|
33018
33184
|
window: {
|
|
33019
33185
|
startTime,
|
|
33020
33186
|
endTime,
|
|
@@ -33036,16 +33202,16 @@ var init_runtimeEvidence = __esm({
|
|
|
33036
33202
|
throw new Error("Runtime evidence window has no versioned runtime rows");
|
|
33037
33203
|
}
|
|
33038
33204
|
const artifact = current.artifact;
|
|
33039
|
-
const outPath =
|
|
33040
|
-
await import_promises32.default.mkdir(
|
|
33205
|
+
const outPath = import_node_path30.default.resolve(projectRoot12, String(flags28.out));
|
|
33206
|
+
await import_promises32.default.mkdir(import_node_path30.default.dirname(outPath), { recursive: true });
|
|
33041
33207
|
await import_promises32.default.writeFile(outPath, `${JSON.stringify(artifact, null, 2)}
|
|
33042
33208
|
`, "utf8");
|
|
33043
33209
|
const published = publishDir ? await Promise.all(
|
|
33044
33210
|
artifacts.map(
|
|
33045
33211
|
({ artifact: artifact2, composition }) => publishRuntimeEvidenceBundle({
|
|
33046
|
-
publishRoot:
|
|
33212
|
+
publishRoot: import_node_path30.default.resolve(projectRoot12, publishDir),
|
|
33047
33213
|
deploymentId,
|
|
33048
|
-
userName: String(
|
|
33214
|
+
userName: String(flags28.user),
|
|
33049
33215
|
startTime,
|
|
33050
33216
|
endTime,
|
|
33051
33217
|
artifact: artifact2,
|
|
@@ -33061,9 +33227,9 @@ var init_runtimeEvidence = __esm({
|
|
|
33061
33227
|
})
|
|
33062
33228
|
)
|
|
33063
33229
|
) : [];
|
|
33064
|
-
console.log(
|
|
33230
|
+
console.log(import_chalk47.default.green(`Wrote ${outPath}`));
|
|
33065
33231
|
for (const bundle of published) {
|
|
33066
|
-
console.log(
|
|
33232
|
+
console.log(import_chalk47.default.green(`Published ${bundle.bundleDir}`));
|
|
33067
33233
|
}
|
|
33068
33234
|
console.log(
|
|
33069
33235
|
JSON.stringify(
|
|
@@ -33079,56 +33245,56 @@ var init_runtimeEvidence = __esm({
|
|
|
33079
33245
|
)
|
|
33080
33246
|
);
|
|
33081
33247
|
};
|
|
33082
|
-
|
|
33248
|
+
main38 = runtimeEvidence;
|
|
33083
33249
|
}
|
|
33084
33250
|
});
|
|
33085
33251
|
|
|
33086
33252
|
// src/scripts/runtimeEvidenceSync.ts
|
|
33087
33253
|
var runtimeEvidenceSync_exports = {};
|
|
33088
33254
|
__export(runtimeEvidenceSync_exports, {
|
|
33089
|
-
main: () =>
|
|
33255
|
+
main: () => main39,
|
|
33090
33256
|
runtimeEvidenceSync: () => runtimeEvidenceSync
|
|
33091
33257
|
});
|
|
33092
|
-
var
|
|
33258
|
+
var import_node_path31, import_args31, import_chalk48, flags29, projectRoot13, runtimeEvidenceSync, main39;
|
|
33093
33259
|
var init_runtimeEvidenceSync2 = __esm({
|
|
33094
33260
|
"src/scripts/runtimeEvidenceSync.ts"() {
|
|
33095
33261
|
"use strict";
|
|
33096
|
-
|
|
33097
|
-
|
|
33098
|
-
|
|
33262
|
+
import_node_path31 = __toESM(require("path"));
|
|
33263
|
+
import_args31 = __toESM(require("args"));
|
|
33264
|
+
import_chalk48 = __toESM(require("chalk"));
|
|
33099
33265
|
init_runtimeEvidenceSync();
|
|
33100
|
-
|
|
33266
|
+
import_args31.default.option(
|
|
33101
33267
|
"source",
|
|
33102
33268
|
"Rsync source ending at the deployment ready directory",
|
|
33103
33269
|
process.env.RUNTIME_EVIDENCE_RSYNC_SOURCE
|
|
33104
33270
|
);
|
|
33105
|
-
|
|
33271
|
+
import_args31.default.option(
|
|
33106
33272
|
"deployment",
|
|
33107
33273
|
"Deployment id expected in artifact manifests",
|
|
33108
33274
|
process.env.RUNTIME_EVIDENCE_DEPLOYMENT_ID || "production"
|
|
33109
33275
|
);
|
|
33110
|
-
|
|
33276
|
+
import_args31.default.option(
|
|
33111
33277
|
"dir",
|
|
33112
33278
|
"Local evidence storage root",
|
|
33113
33279
|
process.env.RUNTIME_EVIDENCE_LOCAL_DIR || "data/runtime-evidence"
|
|
33114
33280
|
);
|
|
33115
|
-
|
|
33116
|
-
|
|
33281
|
+
flags29 = import_args31.default.parse(process.argv);
|
|
33282
|
+
projectRoot13 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
|
|
33117
33283
|
runtimeEvidenceSync = async () => {
|
|
33118
|
-
const source = String(
|
|
33284
|
+
const source = String(flags29.source ?? "").trim();
|
|
33119
33285
|
if (!source) {
|
|
33120
33286
|
throw new Error(
|
|
33121
33287
|
"Provide --source or RUNTIME_EVIDENCE_RSYNC_SOURCE for runtime evidence sync."
|
|
33122
33288
|
);
|
|
33123
33289
|
}
|
|
33124
|
-
const evidenceRoot =
|
|
33290
|
+
const evidenceRoot = import_node_path31.default.resolve(projectRoot13, String(flags29.dir));
|
|
33125
33291
|
const result = await syncRuntimeEvidenceBundles({
|
|
33126
33292
|
source,
|
|
33127
33293
|
evidenceRoot,
|
|
33128
|
-
deploymentId: String(
|
|
33294
|
+
deploymentId: String(flags29.deployment)
|
|
33129
33295
|
});
|
|
33130
33296
|
console.log(
|
|
33131
|
-
|
|
33297
|
+
import_chalk48.default.green(
|
|
33132
33298
|
`Runtime evidence sync completed: received=${result.received.length} pending=${result.pending.length}`
|
|
33133
33299
|
)
|
|
33134
33300
|
);
|
|
@@ -33153,23 +33319,23 @@ var init_runtimeEvidenceSync2 = __esm({
|
|
|
33153
33319
|
)
|
|
33154
33320
|
);
|
|
33155
33321
|
};
|
|
33156
|
-
|
|
33322
|
+
main39 = runtimeEvidenceSync;
|
|
33157
33323
|
}
|
|
33158
33324
|
});
|
|
33159
33325
|
|
|
33160
33326
|
// src/lib/runtimeScorecard.ts
|
|
33161
|
-
var
|
|
33327
|
+
var asRecord8, asArray4, finiteNumber6, finiteString2, packageVersionMap, round3, unwrapRows2, runtimePayload, runtimeWindow, extractRuntimeRows, buildEmbeddedLineageScope, runtimeDeploymentBinding, belongsToRuntimeDeployment, belongsToStrategy, filterArtifactByStrategy, countBy2, resolveGateDecision, buildDistributions, buildDistributionDelta, sum2, tradeTimestamp, dedupeTrades, maxDrawdown2, buildRollingPerformance, getReplayComparison, replayCountsForStrategy, getProspectiveSummary, buildRuntimeScorecard, formatRuntimeScorecardMarkdown;
|
|
33162
33328
|
var init_runtimeScorecard = __esm({
|
|
33163
33329
|
"src/lib/runtimeScorecard.ts"() {
|
|
33164
33330
|
"use strict";
|
|
33165
33331
|
init_runtimeLineage();
|
|
33166
33332
|
init_runtimeEvidenceDeployment();
|
|
33167
|
-
|
|
33168
|
-
|
|
33169
|
-
|
|
33333
|
+
asRecord8 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
33334
|
+
asArray4 = (value) => Array.isArray(value) ? value : [];
|
|
33335
|
+
finiteNumber6 = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
33170
33336
|
finiteString2 = (value) => typeof value === "string" && value.trim() ? value.trim() : null;
|
|
33171
33337
|
packageVersionMap = (value) => {
|
|
33172
|
-
const record =
|
|
33338
|
+
const record = asRecord8(value);
|
|
33173
33339
|
if (!record || Object.keys(record).length === 0) return null;
|
|
33174
33340
|
const entries = Object.entries(record);
|
|
33175
33341
|
if (entries.some(
|
|
@@ -33182,14 +33348,14 @@ var init_runtimeScorecard = __esm({
|
|
|
33182
33348
|
);
|
|
33183
33349
|
};
|
|
33184
33350
|
round3 = (value, decimals = 6) => Number(value.toFixed(decimals));
|
|
33185
|
-
unwrapRows2 = (value, key) =>
|
|
33351
|
+
unwrapRows2 = (value, key) => asArray4(value).map((item) => asRecord8(asRecord8(item)?.[key]) ?? asRecord8(item)).filter((item) => item != null);
|
|
33186
33352
|
runtimePayload = (artifact) => {
|
|
33187
|
-
const root =
|
|
33188
|
-
return
|
|
33353
|
+
const root = asRecord8(artifact) ?? {};
|
|
33354
|
+
return asRecord8(root.runtime) ?? root;
|
|
33189
33355
|
};
|
|
33190
33356
|
runtimeWindow = (artifact) => {
|
|
33191
|
-
const root =
|
|
33192
|
-
return
|
|
33357
|
+
const root = asRecord8(artifact) ?? {};
|
|
33358
|
+
return asRecord8(root.window) ?? asRecord8(runtimePayload(artifact).window) ?? {};
|
|
33193
33359
|
};
|
|
33194
33360
|
extractRuntimeRows = (artifact) => {
|
|
33195
33361
|
const runtime = runtimePayload(artifact);
|
|
@@ -33205,15 +33371,15 @@ var init_runtimeScorecard = __esm({
|
|
|
33205
33371
|
rows,
|
|
33206
33372
|
strategy
|
|
33207
33373
|
}) => {
|
|
33208
|
-
const deployment =
|
|
33209
|
-
if (
|
|
33374
|
+
const deployment = asRecord8(asRecord8(artifact)?.deployment);
|
|
33375
|
+
if (finiteNumber6(deployment?.schemaVersion) !== 2) return null;
|
|
33210
33376
|
const deploymentId = finiteString2(deployment?.id);
|
|
33211
33377
|
const accountId = finiteString2(deployment?.accountId);
|
|
33212
33378
|
const deploymentCompositionId = finiteString2(
|
|
33213
33379
|
deployment?.deploymentCompositionId
|
|
33214
33380
|
);
|
|
33215
33381
|
if (!deploymentId || !accountId || !deploymentCompositionId) return null;
|
|
33216
|
-
const snapshots =
|
|
33382
|
+
const snapshots = asArray4(deployment?.strategies).map(asRecord8).filter((item) => item != null).filter((item) => item.enabled === true).filter(
|
|
33217
33383
|
(item) => !strategy || finiteString2(item.strategyName) === strategy
|
|
33218
33384
|
);
|
|
33219
33385
|
const targetSeeds = snapshots.map((snapshot) => {
|
|
@@ -33251,14 +33417,14 @@ var init_runtimeScorecard = __esm({
|
|
|
33251
33417
|
runtimeLineage: scope.lineage
|
|
33252
33418
|
}))
|
|
33253
33419
|
];
|
|
33254
|
-
const identityMatches = (lineage, target) =>
|
|
33420
|
+
const identityMatches = (lineage, target) => finiteNumber6(lineage?.schemaVersion) === 3 && finiteString2(lineage?.strategyRevision) === target.strategyRevision && finiteString2(lineage?.deploymentCompositionId) === target.deploymentCompositionId && finiteString2(lineage?.strategyPackageVersion) === target.strategyPackageVersion && JSON.stringify(packageVersionMap(lineage?.strategyDependencyVersions)) === JSON.stringify(target.strategyDependencyVersions) && finiteString2(lineage?.runtimePackageVersion) === target.runtimePackageVersion;
|
|
33255
33421
|
const targets = /* @__PURE__ */ new Map();
|
|
33256
33422
|
for (const seed of targetSeeds) {
|
|
33257
33423
|
const matchingRows = lineageRows.filter(
|
|
33258
|
-
(row) => finiteString2(row.strategy) === seed.strategyName && finiteString2(row.deploymentId) === deploymentId && finiteString2(row.accountId) === accountId && identityMatches(
|
|
33424
|
+
(row) => finiteString2(row.strategy) === seed.strategyName && finiteString2(row.deploymentId) === deploymentId && finiteString2(row.accountId) === accountId && identityMatches(asRecord8(row.runtimeLineage), seed)
|
|
33259
33425
|
);
|
|
33260
33426
|
const riskValues = new Set(
|
|
33261
|
-
matchingRows.map((row) =>
|
|
33427
|
+
matchingRows.map((row) => finiteNumber6(asRecord8(row.runtimeLineage)?.maxLossValue)).filter((value) => value != null)
|
|
33262
33428
|
);
|
|
33263
33429
|
targets.set(seed.strategyName, {
|
|
33264
33430
|
...seed,
|
|
@@ -33270,9 +33436,9 @@ var init_runtimeScorecard = __esm({
|
|
|
33270
33436
|
const belongs = (row) => {
|
|
33271
33437
|
const strategyName = finiteString2(row.strategy);
|
|
33272
33438
|
const target = strategyName ? targets.get(strategyName) : null;
|
|
33273
|
-
const lineage =
|
|
33439
|
+
const lineage = asRecord8(row.runtimeLineage);
|
|
33274
33440
|
return Boolean(
|
|
33275
|
-
target && target.maxLossValue != null && identityMatches(lineage, target) &&
|
|
33441
|
+
target && target.maxLossValue != null && identityMatches(lineage, target) && finiteNumber6(lineage?.maxLossValue) === target.maxLossValue
|
|
33276
33442
|
);
|
|
33277
33443
|
};
|
|
33278
33444
|
const targetValues = [...targets.values()];
|
|
@@ -33327,7 +33493,7 @@ var init_runtimeScorecard = __esm({
|
|
|
33327
33493
|
};
|
|
33328
33494
|
};
|
|
33329
33495
|
runtimeDeploymentBinding = (artifact) => {
|
|
33330
|
-
const deployment =
|
|
33496
|
+
const deployment = asRecord8(asRecord8(artifact)?.deployment);
|
|
33331
33497
|
return {
|
|
33332
33498
|
deploymentId: finiteString2(deployment?.id),
|
|
33333
33499
|
accountId: finiteString2(deployment?.accountId)
|
|
@@ -33337,32 +33503,32 @@ var init_runtimeScorecard = __esm({
|
|
|
33337
33503
|
belongsToStrategy = (row, strategy) => strategy == null || finiteString2(row.strategy) === strategy;
|
|
33338
33504
|
filterArtifactByStrategy = (artifact, strategy) => {
|
|
33339
33505
|
if (!strategy) return artifact;
|
|
33340
|
-
const root =
|
|
33506
|
+
const root = asRecord8(artifact) ?? {};
|
|
33341
33507
|
const runtime = runtimePayload(artifact);
|
|
33342
33508
|
return {
|
|
33343
33509
|
...root,
|
|
33344
33510
|
runtime: {
|
|
33345
33511
|
...runtime,
|
|
33346
|
-
evaluations:
|
|
33512
|
+
evaluations: asArray4(runtime.evaluations).filter(
|
|
33347
33513
|
(item) => belongsToStrategy(
|
|
33348
|
-
|
|
33514
|
+
asRecord8(asRecord8(item)?.evaluation) ?? asRecord8(item) ?? {},
|
|
33349
33515
|
strategy
|
|
33350
33516
|
)
|
|
33351
33517
|
),
|
|
33352
|
-
signals:
|
|
33518
|
+
signals: asArray4(runtime.signals).filter(
|
|
33353
33519
|
(item) => belongsToStrategy(
|
|
33354
|
-
|
|
33520
|
+
asRecord8(asRecord8(item)?.signal) ?? asRecord8(item) ?? {},
|
|
33355
33521
|
strategy
|
|
33356
33522
|
)
|
|
33357
33523
|
),
|
|
33358
|
-
trades:
|
|
33524
|
+
trades: asArray4(runtime.trades).filter(
|
|
33359
33525
|
(item) => belongsToStrategy(
|
|
33360
|
-
|
|
33526
|
+
asRecord8(asRecord8(item)?.trade) ?? asRecord8(item) ?? {},
|
|
33361
33527
|
strategy
|
|
33362
33528
|
)
|
|
33363
33529
|
),
|
|
33364
|
-
lineageScopes:
|
|
33365
|
-
(item) => belongsToStrategy(
|
|
33530
|
+
lineageScopes: asArray4(runtime.lineageScopes).filter(
|
|
33531
|
+
(item) => belongsToStrategy(asRecord8(item) ?? {}, strategy)
|
|
33366
33532
|
)
|
|
33367
33533
|
}
|
|
33368
33534
|
};
|
|
@@ -33379,7 +33545,7 @@ var init_runtimeScorecard = __esm({
|
|
|
33379
33545
|
);
|
|
33380
33546
|
};
|
|
33381
33547
|
resolveGateDecision = (evaluation) => {
|
|
33382
|
-
const analysis =
|
|
33548
|
+
const analysis = asRecord8(evaluation.aiAnalysis);
|
|
33383
33549
|
const explicit = finiteString2(analysis?.gateDecision);
|
|
33384
33550
|
if (explicit === "approved" || explicit === "rejected") {
|
|
33385
33551
|
return { decision: explicit, source: "gate_decision" };
|
|
@@ -33410,7 +33576,7 @@ var init_runtimeScorecard = __esm({
|
|
|
33410
33576
|
(signal) => finiteString2(signal.orderSkipReason)
|
|
33411
33577
|
),
|
|
33412
33578
|
aiQuality: countBy2(candidates, (evaluation) => {
|
|
33413
|
-
const quality =
|
|
33579
|
+
const quality = finiteNumber6(asRecord8(evaluation.aiAnalysis)?.quality);
|
|
33414
33580
|
return quality == null ? null : String(quality);
|
|
33415
33581
|
})
|
|
33416
33582
|
};
|
|
@@ -33447,7 +33613,7 @@ var init_runtimeScorecard = __esm({
|
|
|
33447
33613
|
);
|
|
33448
33614
|
};
|
|
33449
33615
|
sum2 = (values) => round3(values.reduce((total, value) => total + (value ?? 0), 0));
|
|
33450
|
-
tradeTimestamp = (trade) =>
|
|
33616
|
+
tradeTimestamp = (trade) => finiteNumber6(trade.exitTimestamp) ?? finiteNumber6(trade.lastSyncedAt) ?? finiteNumber6(trade.entryTimestamp) ?? 0;
|
|
33451
33617
|
dedupeTrades = (artifacts) => {
|
|
33452
33618
|
const tradesByOrderId = /* @__PURE__ */ new Map();
|
|
33453
33619
|
for (const artifact of artifacts) {
|
|
@@ -33469,7 +33635,7 @@ var init_runtimeScorecard = __esm({
|
|
|
33469
33635
|
for (const trade of trades.sort(
|
|
33470
33636
|
(left, right) => tradeTimestamp(left) - tradeTimestamp(right)
|
|
33471
33637
|
)) {
|
|
33472
|
-
cumulative +=
|
|
33638
|
+
cumulative += finiteNumber6(trade.closedPnl) ?? 0;
|
|
33473
33639
|
peak = Math.max(peak, cumulative);
|
|
33474
33640
|
drawdown = Math.max(drawdown, peak - cumulative);
|
|
33475
33641
|
}
|
|
@@ -33482,10 +33648,10 @@ var init_runtimeScorecard = __esm({
|
|
|
33482
33648
|
}) => {
|
|
33483
33649
|
const startTime = anchorTime - days * 24 * 60 * 60 * 1e3;
|
|
33484
33650
|
const closed = trades.filter((trade) => {
|
|
33485
|
-
const exitTimestamp =
|
|
33651
|
+
const exitTimestamp = finiteNumber6(trade.exitTimestamp);
|
|
33486
33652
|
return trade.status === "closed" && exitTimestamp != null && exitTimestamp >= startTime && exitTimestamp < anchorTime;
|
|
33487
33653
|
});
|
|
33488
|
-
const realizedPnl = sum2(closed.map((trade) =>
|
|
33654
|
+
const realizedPnl = sum2(closed.map((trade) => finiteNumber6(trade.closedPnl)));
|
|
33489
33655
|
return {
|
|
33490
33656
|
days,
|
|
33491
33657
|
closedTrades: closed.length,
|
|
@@ -33495,35 +33661,35 @@ var init_runtimeScorecard = __esm({
|
|
|
33495
33661
|
};
|
|
33496
33662
|
};
|
|
33497
33663
|
getReplayComparison = (artifact) => {
|
|
33498
|
-
const root =
|
|
33499
|
-
return
|
|
33664
|
+
const root = asRecord8(artifact) ?? {};
|
|
33665
|
+
return asRecord8(asRecord8(root.replay)?.runtimeComparison) ?? null;
|
|
33500
33666
|
};
|
|
33501
33667
|
replayCountsForStrategy = (replayComparison, strategy) => {
|
|
33502
33668
|
if (strategy) {
|
|
33503
|
-
const byStrategy =
|
|
33504
|
-
const strategyCounts =
|
|
33669
|
+
const byStrategy = asRecord8(replayComparison?.byStrategy);
|
|
33670
|
+
const strategyCounts = asRecord8(byStrategy?.[strategy]);
|
|
33505
33671
|
if (strategyCounts) {
|
|
33506
33672
|
return {
|
|
33507
|
-
matched:
|
|
33508
|
-
backtestOnly:
|
|
33509
|
-
runtimeOnly:
|
|
33673
|
+
matched: finiteNumber6(strategyCounts.matched) ?? 0,
|
|
33674
|
+
backtestOnly: finiteNumber6(strategyCounts.backtestOnly) ?? 0,
|
|
33675
|
+
runtimeOnly: finiteNumber6(strategyCounts.runtimeOnly) ?? 0
|
|
33510
33676
|
};
|
|
33511
33677
|
}
|
|
33512
33678
|
}
|
|
33513
|
-
const counts =
|
|
33679
|
+
const counts = asRecord8(replayComparison?.counts);
|
|
33514
33680
|
return {
|
|
33515
|
-
matched:
|
|
33516
|
-
backtestOnly:
|
|
33517
|
-
runtimeOnly:
|
|
33681
|
+
matched: finiteNumber6(counts?.matched) ?? 0,
|
|
33682
|
+
backtestOnly: finiteNumber6(counts?.backtestOnly) ?? 0,
|
|
33683
|
+
runtimeOnly: finiteNumber6(counts?.runtimeOnly) ?? 0
|
|
33518
33684
|
};
|
|
33519
33685
|
};
|
|
33520
33686
|
getProspectiveSummary = (artifact) => {
|
|
33521
|
-
const root =
|
|
33687
|
+
const root = asRecord8(artifact);
|
|
33522
33688
|
if (!root || root.reportType !== "strategy-prospective-evidence") return null;
|
|
33523
33689
|
return {
|
|
33524
|
-
rawCoreExpectancy:
|
|
33525
|
-
aiGateExpectancy:
|
|
33526
|
-
regimeCoverage:
|
|
33690
|
+
rawCoreExpectancy: finiteNumber6(root.rawCoreExpectancy),
|
|
33691
|
+
aiGateExpectancy: finiteNumber6(root.aiGateExpectancy),
|
|
33692
|
+
regimeCoverage: finiteNumber6(root.regimeCoverage)
|
|
33527
33693
|
};
|
|
33528
33694
|
};
|
|
33529
33695
|
buildRuntimeScorecard = ({
|
|
@@ -33567,8 +33733,8 @@ var init_runtimeScorecard = __esm({
|
|
|
33567
33733
|
}
|
|
33568
33734
|
const runtimeLineage = embeddedLineageScope.summary;
|
|
33569
33735
|
const window = runtimeWindow(runtimeArtifact);
|
|
33570
|
-
const startTime =
|
|
33571
|
-
const endTime =
|
|
33736
|
+
const startTime = finiteNumber6(window.startTime) ?? generatedAt - 864e5;
|
|
33737
|
+
const endTime = finiteNumber6(window.endTime) ?? generatedAt;
|
|
33572
33738
|
const signalEvaluations = rows.evaluations.filter(
|
|
33573
33739
|
(evaluation) => evaluation.status === "signal"
|
|
33574
33740
|
);
|
|
@@ -33579,7 +33745,7 @@ var init_runtimeScorecard = __esm({
|
|
|
33579
33745
|
(evaluation) => resolveGateDecision(evaluation)?.decision === "approved"
|
|
33580
33746
|
) : signalEvaluations;
|
|
33581
33747
|
const gateComparisons = llmEligibleEvaluations.map((evaluation) => {
|
|
33582
|
-
const analysis =
|
|
33748
|
+
const analysis = asRecord8(evaluation.aiAnalysis);
|
|
33583
33749
|
const gateDecision = resolveGateDecision(evaluation)?.decision ?? null;
|
|
33584
33750
|
const llmDecision = finiteString2(analysis?.llmDecision);
|
|
33585
33751
|
if (gateDecision !== "approved" && gateDecision !== "rejected" || llmDecision !== "approved" && llmDecision !== "rejected") {
|
|
@@ -33589,13 +33755,13 @@ var init_runtimeScorecard = __esm({
|
|
|
33589
33755
|
}).filter(
|
|
33590
33756
|
(comparison) => Boolean(comparison)
|
|
33591
33757
|
);
|
|
33592
|
-
const allocatorDecisions = signalEvaluations.map((evaluation) =>
|
|
33593
|
-
const riskDecisions = signalEvaluations.map((evaluation) =>
|
|
33758
|
+
const allocatorDecisions = signalEvaluations.map((evaluation) => asRecord8(evaluation.allocatorDecision)).filter((item) => item != null);
|
|
33759
|
+
const riskDecisions = signalEvaluations.map((evaluation) => asRecord8(evaluation.riskDecision)).filter((item) => item != null);
|
|
33594
33760
|
const orderAttempts = rows.signals.filter(
|
|
33595
33761
|
(signal) => signal.orderStatus === "completed" || signal.orderStatus === "failed"
|
|
33596
33762
|
);
|
|
33597
33763
|
const currentClosedTrades = rows.trades.filter((trade) => {
|
|
33598
|
-
const exitTimestamp =
|
|
33764
|
+
const exitTimestamp = finiteNumber6(trade.exitTimestamp);
|
|
33599
33765
|
return trade.status === "closed" && exitTimestamp != null && exitTimestamp >= startTime && exitTimestamp < endTime;
|
|
33600
33766
|
});
|
|
33601
33767
|
const replayComparison = getReplayComparison(replayEvidenceArtifact);
|
|
@@ -33605,12 +33771,12 @@ var init_runtimeScorecard = __esm({
|
|
|
33605
33771
|
const runtimeOnly = replayCounts.runtimeOnly;
|
|
33606
33772
|
const comparisonTotal = matched + backtestOnly + runtimeOnly;
|
|
33607
33773
|
const parityRatio = comparisonTotal > 0 ? matched / comparisonTotal : null;
|
|
33608
|
-
const lineage =
|
|
33774
|
+
const lineage = asRecord8(replayComparison?.lineage);
|
|
33609
33775
|
const lineageReason = finiteString2(lineage?.reason);
|
|
33610
|
-
const calibrationRoot =
|
|
33611
|
-
const calibrationSamples =
|
|
33776
|
+
const calibrationRoot = asRecord8(calibrationArtifact) ?? {};
|
|
33777
|
+
const calibrationSamples = asArray4(calibrationRoot.samples).map(asRecord8).filter((item) => item != null).filter((item) => !strategy || finiteString2(item.strategy) === strategy).filter((item) => embeddedLineageScope.belongs(item));
|
|
33612
33778
|
const averageSampleMetric = (field) => {
|
|
33613
|
-
const values = calibrationSamples.map((sample) =>
|
|
33779
|
+
const values = calibrationSamples.map((sample) => finiteNumber6(sample[field])).filter((value) => value != null);
|
|
33614
33780
|
return values.length ? round3(sum2(values) / values.length) : null;
|
|
33615
33781
|
};
|
|
33616
33782
|
const actualSlippageBps = averageSampleMetric("signalToFillAdverseBps");
|
|
@@ -33629,7 +33795,7 @@ var init_runtimeScorecard = __esm({
|
|
|
33629
33795
|
(sample) => finiteString2(sample.telemetryQuality) === "full"
|
|
33630
33796
|
).length;
|
|
33631
33797
|
const arrivalQuoteTrades = calibrationSamples.filter(
|
|
33632
|
-
(sample) =>
|
|
33798
|
+
(sample) => finiteNumber6(sample.arrivalMid) != null
|
|
33633
33799
|
).length;
|
|
33634
33800
|
const arrivalQuoteCoverage = calibrationSamples.length ? round3(arrivalQuoteTrades / calibrationSamples.length) : null;
|
|
33635
33801
|
const hasTelemetryQuality = calibrationSamples.some(
|
|
@@ -33652,10 +33818,10 @@ var init_runtimeScorecard = __esm({
|
|
|
33652
33818
|
);
|
|
33653
33819
|
const currentDistributions = buildDistributions(rows);
|
|
33654
33820
|
const previousArtifact = scopedHistoryArtifacts.map((artifact) => ({ artifact, window: runtimeWindow(artifact) })).filter(({ window: candidateWindow }) => {
|
|
33655
|
-
const candidateEndTime =
|
|
33821
|
+
const candidateEndTime = finiteNumber6(candidateWindow.endTime);
|
|
33656
33822
|
return candidateEndTime != null && candidateEndTime <= startTime;
|
|
33657
33823
|
}).sort(
|
|
33658
|
-
(left, right) => (
|
|
33824
|
+
(left, right) => (finiteNumber6(right.window.endTime) ?? 0) - (finiteNumber6(left.window.endTime) ?? 0)
|
|
33659
33825
|
)[0];
|
|
33660
33826
|
const previousDistributions = previousArtifact ? buildDistributions(extractRuntimeRows(previousArtifact.artifact)) : null;
|
|
33661
33827
|
const rolling = [7, 30, 90].map(
|
|
@@ -33808,17 +33974,17 @@ var init_runtimeScorecard = __esm({
|
|
|
33808
33974
|
realized: {
|
|
33809
33975
|
pnl: sum2(
|
|
33810
33976
|
comparableCurrentClosedTrades.map(
|
|
33811
|
-
(trade) =>
|
|
33977
|
+
(trade) => finiteNumber6(trade.closedPnl)
|
|
33812
33978
|
)
|
|
33813
33979
|
),
|
|
33814
33980
|
fees: sum2(
|
|
33815
33981
|
comparableCurrentClosedTrades.map(
|
|
33816
|
-
(trade) =>
|
|
33982
|
+
(trade) => finiteNumber6(trade.totalFee)
|
|
33817
33983
|
)
|
|
33818
33984
|
),
|
|
33819
33985
|
funding: sum2(
|
|
33820
33986
|
comparableCurrentClosedTrades.map(
|
|
33821
|
-
(trade) =>
|
|
33987
|
+
(trade) => finiteNumber6(trade.fundingFee)
|
|
33822
33988
|
)
|
|
33823
33989
|
)
|
|
33824
33990
|
},
|
|
@@ -33867,8 +34033,8 @@ var init_runtimeScorecard = __esm({
|
|
|
33867
34033
|
distributionChanges: {
|
|
33868
34034
|
available: previousDistributions != null,
|
|
33869
34035
|
baselineWindow: previousArtifact ? {
|
|
33870
|
-
startTime:
|
|
33871
|
-
endTime:
|
|
34036
|
+
startTime: finiteNumber6(previousArtifact.window.startTime),
|
|
34037
|
+
endTime: finiteNumber6(previousArtifact.window.endTime)
|
|
33872
34038
|
} : null,
|
|
33873
34039
|
metrics: previousDistributions ? Object.fromEntries(
|
|
33874
34040
|
Object.entries(currentDistributions).map(([name, current]) => [
|
|
@@ -34355,13 +34521,13 @@ async function collectReleaseEvidenceReferences(references) {
|
|
|
34355
34521
|
})
|
|
34356
34522
|
);
|
|
34357
34523
|
}
|
|
34358
|
-
var import_node_crypto16, import_promises33,
|
|
34524
|
+
var import_node_crypto16, import_promises33, import_node_path32, import_types9, import_strategyReleaseEvidence2, SHA256_RE2, LINEAGE_FINGERPRINT_RE, STRATEGY_REVISION_RE, DEPLOYMENT_COMPOSITION_ID_RE, REQUIRED_LONG_WINDOWS, REQUIRED_DIAGNOSTIC_TERMINAL_WINDOWS, MIN_RECENT_DIRECTION_REPAIR_EVENTS, safeSegment7, compactTimestamp2, verifyFullPeriodChartArtifact, readVerifiedJsonArtifact, verifyResearchDecisionLineage, hasExactRuntimeTarget, deriveStrategyReleaseResearchDecision, canonicalStrategyReleaseJson, strategyReleaseSha256, assertFingerprint, assertLineageFingerprint, releaseReasons, deriveReleaseGates, verifyEvidenceComposition, createStrategyReleaseManifest, createStrategyReleaseEnvelope, verifyStrategyReleaseEnvelope, verifyStrategyEvidenceMarkerEnvelope, releaseMarkers, writeJsonAtomic2, publishStrategyRelease, publishStrategyLiveDiagnosis, finiteString3, finiteNumber7, finiteDirectionPolicy, uniqueStrings, incompleteEvidenceLineage, extractEvidenceLineage, verifyCompletedCoreResearchBundle;
|
|
34359
34525
|
var init_strategyRelease = __esm({
|
|
34360
34526
|
"src/lib/strategyRelease.ts"() {
|
|
34361
34527
|
"use strict";
|
|
34362
34528
|
import_node_crypto16 = require("crypto");
|
|
34363
34529
|
import_promises33 = __toESM(require("fs/promises"));
|
|
34364
|
-
|
|
34530
|
+
import_node_path32 = __toESM(require("path"));
|
|
34365
34531
|
import_types9 = require("@tradejs/types");
|
|
34366
34532
|
import_strategyReleaseEvidence2 = require("@tradejs/infra/strategyReleaseEvidence");
|
|
34367
34533
|
init_liveDiagnosis();
|
|
@@ -34380,7 +34546,7 @@ var init_strategyRelease = __esm({
|
|
|
34380
34546
|
const artifact = input.chartArtifact;
|
|
34381
34547
|
if (!artifact?.path || !SHA256_RE2.test(artifact.sha256)) return false;
|
|
34382
34548
|
try {
|
|
34383
|
-
const artifactPath =
|
|
34549
|
+
const artifactPath = import_node_path32.default.resolve(artifact.path);
|
|
34384
34550
|
if (await (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(artifactPath) !== artifact.sha256) {
|
|
34385
34551
|
return false;
|
|
34386
34552
|
}
|
|
@@ -34395,7 +34561,7 @@ var init_strategyRelease = __esm({
|
|
|
34395
34561
|
readVerifiedJsonArtifact = async (artifact) => {
|
|
34396
34562
|
if (!artifact?.path || !SHA256_RE2.test(artifact.sha256)) return null;
|
|
34397
34563
|
try {
|
|
34398
|
-
const artifactPath =
|
|
34564
|
+
const artifactPath = import_node_path32.default.resolve(artifact.path);
|
|
34399
34565
|
if (await (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(artifactPath) !== artifact.sha256) {
|
|
34400
34566
|
return null;
|
|
34401
34567
|
}
|
|
@@ -35058,7 +35224,7 @@ var init_strategyRelease = __esm({
|
|
|
35058
35224
|
};
|
|
35059
35225
|
writeJsonAtomic2 = async (filePath, value) => {
|
|
35060
35226
|
const temporaryPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
35061
|
-
await import_promises33.default.mkdir(
|
|
35227
|
+
await import_promises33.default.mkdir(import_node_path32.default.dirname(filePath), { recursive: true });
|
|
35062
35228
|
await import_promises33.default.writeFile(
|
|
35063
35229
|
temporaryPath,
|
|
35064
35230
|
`${canonicalStrategyReleaseJson(value)}
|
|
@@ -35082,13 +35248,13 @@ var init_strategyRelease = __esm({
|
|
|
35082
35248
|
path: entry.path
|
|
35083
35249
|
}))
|
|
35084
35250
|
});
|
|
35085
|
-
const releasePath =
|
|
35251
|
+
const releasePath = import_node_path32.default.join(
|
|
35086
35252
|
rootDir,
|
|
35087
35253
|
"releases",
|
|
35088
35254
|
safeSegment7(manifest.strategy, "strategy"),
|
|
35089
35255
|
`${manifest.releaseId}.json`
|
|
35090
35256
|
);
|
|
35091
|
-
const markerPath =
|
|
35257
|
+
const markerPath = import_node_path32.default.join(
|
|
35092
35258
|
rootDir,
|
|
35093
35259
|
"markers",
|
|
35094
35260
|
safeSegment7(manifest.strategy, "strategy"),
|
|
@@ -35168,13 +35334,13 @@ var init_strategyRelease = __esm({
|
|
|
35168
35334
|
markers,
|
|
35169
35335
|
sourceArtifacts
|
|
35170
35336
|
});
|
|
35171
|
-
const diagnosisPath =
|
|
35337
|
+
const diagnosisPath = import_node_path32.default.join(
|
|
35172
35338
|
rootDir,
|
|
35173
35339
|
"diagnoses",
|
|
35174
35340
|
safeSegment7(diagnosis.strategy, "strategy"),
|
|
35175
35341
|
`${diagnosisId}.json`
|
|
35176
35342
|
);
|
|
35177
|
-
const markerPath =
|
|
35343
|
+
const markerPath = import_node_path32.default.join(
|
|
35178
35344
|
rootDir,
|
|
35179
35345
|
"markers",
|
|
35180
35346
|
safeSegment7(diagnosis.strategy, "strategy"),
|
|
@@ -35188,7 +35354,7 @@ var init_strategyRelease = __esm({
|
|
|
35188
35354
|
return { diagnosisPath, markerPath, envelope, markerEnvelope };
|
|
35189
35355
|
};
|
|
35190
35356
|
finiteString3 = (value) => typeof value === "string" && value.trim() ? value.trim() : null;
|
|
35191
|
-
|
|
35357
|
+
finiteNumber7 = (value) => {
|
|
35192
35358
|
const number = Number(value);
|
|
35193
35359
|
return Number.isFinite(number) ? number : null;
|
|
35194
35360
|
};
|
|
@@ -35235,7 +35401,7 @@ var init_strategyRelease = __esm({
|
|
|
35235
35401
|
const maxLossValues = [
|
|
35236
35402
|
...new Set(
|
|
35237
35403
|
selectedVariants.map(
|
|
35238
|
-
(variant) =>
|
|
35404
|
+
(variant) => finiteNumber7(
|
|
35239
35405
|
nested(nested(variant.variant)?.resolvedConfig)?.MAX_LOSS_VALUE
|
|
35240
35406
|
)
|
|
35241
35407
|
).filter((value) => value != null)
|
|
@@ -35285,7 +35451,7 @@ var init_strategyRelease = __esm({
|
|
|
35285
35451
|
};
|
|
35286
35452
|
const maxLossValues = [
|
|
35287
35453
|
...new Set(
|
|
35288
|
-
replayLineages.map((entry) =>
|
|
35454
|
+
replayLineages.map((entry) => finiteNumber7(entry.maxLossValue)).filter((value) => value != null)
|
|
35289
35455
|
)
|
|
35290
35456
|
];
|
|
35291
35457
|
const dirtyValues = [
|
|
@@ -35329,7 +35495,7 @@ var init_strategyRelease = __esm({
|
|
|
35329
35495
|
];
|
|
35330
35496
|
const maxLossValues = [
|
|
35331
35497
|
...new Set(
|
|
35332
|
-
lineages.map((lineage) =>
|
|
35498
|
+
lineages.map((lineage) => finiteNumber7(lineage.maxLossValue)).filter((value) => value != null)
|
|
35333
35499
|
)
|
|
35334
35500
|
];
|
|
35335
35501
|
return {
|
|
@@ -35364,9 +35530,9 @@ var init_strategyRelease = __esm({
|
|
|
35364
35530
|
const specSha256 = finiteString3(artifact.specSha256);
|
|
35365
35531
|
assert3(researchId != null, "core result researchId is required");
|
|
35366
35532
|
assert3(specSha256 != null, "core result specSha256 is required");
|
|
35367
|
-
const researchDir =
|
|
35368
|
-
const manifestPath =
|
|
35369
|
-
const specPath =
|
|
35533
|
+
const researchDir = import_node_path32.default.dirname(resultPath);
|
|
35534
|
+
const manifestPath = import_node_path32.default.join(researchDir, "manifest.json");
|
|
35535
|
+
const specPath = import_node_path32.default.join(researchDir, "spec.json");
|
|
35370
35536
|
const manifestBytes = await import_promises33.default.readFile(manifestPath).catch(() => null);
|
|
35371
35537
|
const specBytes = await import_promises33.default.readFile(specPath).catch(() => null);
|
|
35372
35538
|
assert3(
|
|
@@ -35384,7 +35550,7 @@ var init_strategyRelease = __esm({
|
|
|
35384
35550
|
artifactHashes ?? {}
|
|
35385
35551
|
)) {
|
|
35386
35552
|
assert3(
|
|
35387
|
-
!
|
|
35553
|
+
!import_node_path32.default.isAbsolute(relativePath) && !relativePath.split(/[\\/]/).includes(".."),
|
|
35388
35554
|
`core bundle artifact ${relativePath} escapes its research directory`
|
|
35389
35555
|
);
|
|
35390
35556
|
assert3(
|
|
@@ -35392,7 +35558,7 @@ var init_strategyRelease = __esm({
|
|
|
35392
35558
|
`core bundle artifact ${relativePath} has an invalid checksum`
|
|
35393
35559
|
);
|
|
35394
35560
|
const actualSha256 = await (0, import_strategyReleaseEvidence2.strategyEvidenceFileSha256)(
|
|
35395
|
-
|
|
35561
|
+
import_node_path32.default.join(researchDir, relativePath)
|
|
35396
35562
|
);
|
|
35397
35563
|
assert3(
|
|
35398
35564
|
actualSha256 === expectedSha256,
|
|
@@ -35406,86 +35572,86 @@ var init_strategyRelease = __esm({
|
|
|
35406
35572
|
// src/scripts/runtimeScorecard.ts
|
|
35407
35573
|
var runtimeScorecard_exports = {};
|
|
35408
35574
|
__export(runtimeScorecard_exports, {
|
|
35409
|
-
main: () =>
|
|
35575
|
+
main: () => main40,
|
|
35410
35576
|
runtimeScorecard: () => runtimeScorecard
|
|
35411
35577
|
});
|
|
35412
|
-
var import_promises34, import_node_crypto17,
|
|
35578
|
+
var import_promises34, import_node_crypto17, import_node_path33, import_args32, import_chalk49, flags30, projectRoot14, resolveOptionalPath, readJson, assertReportType, sha256File2, loadHistoryArtifacts, runtimeScorecard, main40;
|
|
35413
35579
|
var init_runtimeScorecard2 = __esm({
|
|
35414
35580
|
"src/scripts/runtimeScorecard.ts"() {
|
|
35415
35581
|
"use strict";
|
|
35416
35582
|
import_promises34 = __toESM(require("fs/promises"));
|
|
35417
35583
|
import_node_crypto17 = require("crypto");
|
|
35418
|
-
|
|
35419
|
-
|
|
35420
|
-
|
|
35584
|
+
import_node_path33 = __toESM(require("path"));
|
|
35585
|
+
import_args32 = __toESM(require("args"));
|
|
35586
|
+
import_chalk49 = __toESM(require("chalk"));
|
|
35421
35587
|
init_runtimeEvidenceArtifacts();
|
|
35422
35588
|
init_runtimeFeedbackArtifacts();
|
|
35423
35589
|
init_runtimeEvidenceSync();
|
|
35424
35590
|
init_runtimeScorecard();
|
|
35425
35591
|
init_strategyRelease();
|
|
35426
|
-
|
|
35427
|
-
|
|
35428
|
-
|
|
35429
|
-
|
|
35592
|
+
import_args32.default.option(["u", "runtimeEvidence"], "Verified runtime evidence JSON");
|
|
35593
|
+
import_args32.default.option(["r", "replayEvidence"], "Replay runtime evidence JSON");
|
|
35594
|
+
import_args32.default.option(["c", "calibration"], "Execution calibration JSON");
|
|
35595
|
+
import_args32.default.option(
|
|
35430
35596
|
["q", "prospectiveEvidence"],
|
|
35431
35597
|
"Verified prospective raw-core/gate/regime summary JSON"
|
|
35432
35598
|
);
|
|
35433
|
-
|
|
35434
|
-
|
|
35599
|
+
import_args32.default.option(["s", "strategy"], "Exact strategy to isolate in the scorecard");
|
|
35600
|
+
import_args32.default.option(
|
|
35435
35601
|
["H", "historyDir"],
|
|
35436
35602
|
"Directory containing verified evidence bundles"
|
|
35437
35603
|
);
|
|
35438
|
-
|
|
35604
|
+
import_args32.default.option(
|
|
35439
35605
|
["E", "evidenceDir"],
|
|
35440
35606
|
"Local evidence storage root used for processing receipts",
|
|
35441
35607
|
process.env.RUNTIME_EVIDENCE_LOCAL_DIR || "data/runtime-evidence"
|
|
35442
35608
|
);
|
|
35443
|
-
|
|
35609
|
+
import_args32.default.option(
|
|
35444
35610
|
["d", "deployment"],
|
|
35445
35611
|
"Deployment id used for processing receipts",
|
|
35446
35612
|
process.env.RUNTIME_EVIDENCE_DEPLOYMENT_ID || "production"
|
|
35447
35613
|
);
|
|
35448
|
-
|
|
35614
|
+
import_args32.default.option(
|
|
35449
35615
|
["M", "markProcessed"],
|
|
35450
35616
|
"Write a processing receipt on success",
|
|
35451
35617
|
false
|
|
35452
35618
|
);
|
|
35453
|
-
|
|
35619
|
+
import_args32.default.option(
|
|
35454
35620
|
["P", "minimumParityRatio"],
|
|
35455
35621
|
"Minimum acceptable replay parity",
|
|
35456
35622
|
0.95
|
|
35457
35623
|
);
|
|
35458
|
-
|
|
35624
|
+
import_args32.default.option(
|
|
35459
35625
|
["S", "maximumSlippageResidualBps"],
|
|
35460
35626
|
"Maximum acceptable execution residual in bps",
|
|
35461
35627
|
3
|
|
35462
35628
|
);
|
|
35463
|
-
|
|
35629
|
+
import_args32.default.option(
|
|
35464
35630
|
["L", "maximumSignalCloseToSubmitMs"],
|
|
35465
35631
|
"Maximum acceptable average signal-close-to-submit latency in milliseconds",
|
|
35466
35632
|
3e4
|
|
35467
35633
|
);
|
|
35468
|
-
|
|
35634
|
+
import_args32.default.option(
|
|
35469
35635
|
["T", "minimumClosedTrades"],
|
|
35470
35636
|
"Minimum 7d closed trades for expectancy reactions",
|
|
35471
35637
|
20
|
|
35472
35638
|
);
|
|
35473
|
-
|
|
35474
|
-
|
|
35475
|
-
|
|
35639
|
+
import_args32.default.option(["X", "minimumExpectancy"], "Minimum acceptable 7d expectancy", 0);
|
|
35640
|
+
import_args32.default.option(["o", "out"], "Output JSON path", "output/runtime-scorecard.json");
|
|
35641
|
+
import_args32.default.option(
|
|
35476
35642
|
["m", "releaseManifest"],
|
|
35477
35643
|
"Verified strategy release envelope JSON"
|
|
35478
35644
|
);
|
|
35479
|
-
|
|
35480
|
-
|
|
35645
|
+
import_args32.default.option(["D", "diagnosisDays"], "Equal-length release drawdown window", 7);
|
|
35646
|
+
import_args32.default.option(
|
|
35481
35647
|
["z", "strategyReleaseRoot"],
|
|
35482
35648
|
"Publish advisory diagnosis and immutable chart markers under this root"
|
|
35483
35649
|
);
|
|
35484
|
-
|
|
35485
|
-
|
|
35650
|
+
flags30 = import_args32.default.parse(process.argv);
|
|
35651
|
+
projectRoot14 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
|
|
35486
35652
|
resolveOptionalPath = (value) => {
|
|
35487
35653
|
const raw = String(value ?? "").trim();
|
|
35488
|
-
return raw ?
|
|
35654
|
+
return raw ? import_node_path33.default.resolve(projectRoot14, raw) : null;
|
|
35489
35655
|
};
|
|
35490
35656
|
readJson = async (filePath) => filePath ? JSON.parse(await import_promises34.default.readFile(filePath, "utf8")) : void 0;
|
|
35491
35657
|
assertReportType = (artifact, expected, label) => {
|
|
@@ -35504,17 +35670,17 @@ var init_runtimeScorecard2 = __esm({
|
|
|
35504
35670
|
return bundles.map((bundle) => bundle.artifact);
|
|
35505
35671
|
};
|
|
35506
35672
|
runtimeScorecard = async () => {
|
|
35507
|
-
const runtimeEvidencePath = resolveOptionalPath(
|
|
35673
|
+
const runtimeEvidencePath = resolveOptionalPath(flags30.runtimeEvidence);
|
|
35508
35674
|
if (!runtimeEvidencePath) {
|
|
35509
35675
|
throw new Error("Provide --runtimeEvidence for the runtime scorecard.");
|
|
35510
35676
|
}
|
|
35511
|
-
const replayEvidencePath = resolveOptionalPath(
|
|
35512
|
-
const calibrationPath = resolveOptionalPath(
|
|
35677
|
+
const replayEvidencePath = resolveOptionalPath(flags30.replayEvidence);
|
|
35678
|
+
const calibrationPath = resolveOptionalPath(flags30.calibration);
|
|
35513
35679
|
const prospectiveEvidencePath = resolveOptionalPath(
|
|
35514
|
-
|
|
35680
|
+
flags30.prospectiveEvidence
|
|
35515
35681
|
);
|
|
35516
|
-
const historyDir = resolveOptionalPath(
|
|
35517
|
-
const releaseManifestPath = resolveOptionalPath(
|
|
35682
|
+
const historyDir = resolveOptionalPath(flags30.historyDir);
|
|
35683
|
+
const releaseManifestPath = resolveOptionalPath(flags30.releaseManifest);
|
|
35518
35684
|
const [
|
|
35519
35685
|
runtimeArtifact,
|
|
35520
35686
|
replayEvidenceArtifact,
|
|
@@ -35541,7 +35707,7 @@ var init_runtimeScorecard2 = __esm({
|
|
|
35541
35707
|
"prospectiveEvidence"
|
|
35542
35708
|
);
|
|
35543
35709
|
const verifiedRelease = releaseManifestPath ? await verifyStrategyReleaseEnvelope(releaseManifestPath) : null;
|
|
35544
|
-
const requestedStrategy = String(
|
|
35710
|
+
const requestedStrategy = String(flags30.strategy ?? "").trim() || null;
|
|
35545
35711
|
if (verifiedRelease && requestedStrategy && requestedStrategy !== verifiedRelease.manifest.strategy) {
|
|
35546
35712
|
throw new Error(
|
|
35547
35713
|
`Requested strategy ${requestedStrategy} does not match release ${verifiedRelease.manifest.strategy}`
|
|
@@ -35555,18 +35721,18 @@ var init_runtimeScorecard2 = __esm({
|
|
|
35555
35721
|
prospectiveEvidenceArtifact,
|
|
35556
35722
|
historyRuntimeArtifacts: history,
|
|
35557
35723
|
thresholds: {
|
|
35558
|
-
minimumParityRatio: Number(
|
|
35559
|
-
maximumSlippageResidualBps: Number(
|
|
35560
|
-
maximumSignalCloseToSubmitMs: Number(
|
|
35561
|
-
minimumClosedTrades: Number(
|
|
35562
|
-
minimumExpectancy: Number(
|
|
35724
|
+
minimumParityRatio: Number(flags30.minimumParityRatio),
|
|
35725
|
+
maximumSlippageResidualBps: Number(flags30.maximumSlippageResidualBps),
|
|
35726
|
+
maximumSignalCloseToSubmitMs: Number(flags30.maximumSignalCloseToSubmitMs),
|
|
35727
|
+
minimumClosedTrades: Number(flags30.minimumClosedTrades),
|
|
35728
|
+
minimumExpectancy: Number(flags30.minimumExpectancy)
|
|
35563
35729
|
},
|
|
35564
35730
|
strategy: scorecardStrategy,
|
|
35565
35731
|
llmComparatorPolicy: verifiedRelease?.manifest.prospective.llmComparatorPolicy ?? "ai_approved_only"
|
|
35566
35732
|
});
|
|
35567
|
-
const outPath =
|
|
35733
|
+
const outPath = import_node_path33.default.resolve(projectRoot14, String(flags30.out));
|
|
35568
35734
|
const markdownPath = outPath.replace(/\.json$/i, "") + ".md";
|
|
35569
|
-
await import_promises34.default.mkdir(
|
|
35735
|
+
await import_promises34.default.mkdir(import_node_path33.default.dirname(outPath), { recursive: true });
|
|
35570
35736
|
await Promise.all([
|
|
35571
35737
|
import_promises34.default.writeFile(outPath, `${JSON.stringify(scorecard, null, 2)}
|
|
35572
35738
|
`, "utf8"),
|
|
@@ -35579,10 +35745,10 @@ var init_runtimeScorecard2 = __esm({
|
|
|
35579
35745
|
const diagnosis = verifiedRelease ? buildStrategyLiveDiagnosisFromScorecard({
|
|
35580
35746
|
manifest: verifiedRelease.manifest,
|
|
35581
35747
|
scorecard,
|
|
35582
|
-
days: Number(
|
|
35748
|
+
days: Number(flags30.diagnosisDays)
|
|
35583
35749
|
}) : null;
|
|
35584
35750
|
const diagnosisPath = diagnosis ? outPath.replace(/\.json$/i, "") + ".diagnosis.json" : null;
|
|
35585
|
-
const strategyReleaseRoot = resolveOptionalPath(
|
|
35751
|
+
const strategyReleaseRoot = resolveOptionalPath(flags30.strategyReleaseRoot);
|
|
35586
35752
|
if (diagnosis && diagnosisPath) {
|
|
35587
35753
|
await import_promises34.default.writeFile(
|
|
35588
35754
|
diagnosisPath,
|
|
@@ -35605,7 +35771,7 @@ var init_runtimeScorecard2 = __esm({
|
|
|
35605
35771
|
composition: verifiedRelease?.manifest.composition,
|
|
35606
35772
|
sourceArtifacts: await Promise.all(
|
|
35607
35773
|
sourcePaths.map(async (sourcePath) => ({
|
|
35608
|
-
artifactId:
|
|
35774
|
+
artifactId: import_node_path33.default.basename(sourcePath),
|
|
35609
35775
|
path: sourcePath,
|
|
35610
35776
|
sha256: await sha256File2(sourcePath)
|
|
35611
35777
|
}))
|
|
@@ -35614,13 +35780,13 @@ var init_runtimeScorecard2 = __esm({
|
|
|
35614
35780
|
}
|
|
35615
35781
|
}
|
|
35616
35782
|
let receiptPath2 = null;
|
|
35617
|
-
if (
|
|
35783
|
+
if (flags30.markProcessed) {
|
|
35618
35784
|
const runtimeEvidenceBundle = await verifyRuntimeEvidenceBundle(
|
|
35619
|
-
|
|
35785
|
+
import_node_path33.default.dirname(runtimeEvidencePath)
|
|
35620
35786
|
);
|
|
35621
35787
|
const feedbackSource = replayEvidencePath ? await verifyRuntimeFeedbackReplaySource({
|
|
35622
|
-
bundleDir:
|
|
35623
|
-
runtimeEvidenceBundleDir:
|
|
35788
|
+
bundleDir: import_node_path33.default.dirname(replayEvidencePath),
|
|
35789
|
+
runtimeEvidenceBundleDir: import_node_path33.default.dirname(runtimeEvidencePath)
|
|
35624
35790
|
}).catch((error) => {
|
|
35625
35791
|
if (runtimeEvidenceBundle.artifact.producer) throw error;
|
|
35626
35792
|
return null;
|
|
@@ -35631,9 +35797,9 @@ var init_runtimeScorecard2 = __esm({
|
|
|
35631
35797
|
);
|
|
35632
35798
|
}
|
|
35633
35799
|
receiptPath2 = await markRuntimeEvidenceBundleProcessed({
|
|
35634
|
-
evidenceRoot:
|
|
35635
|
-
deploymentId: String(
|
|
35636
|
-
bundleDir:
|
|
35800
|
+
evidenceRoot: import_node_path33.default.resolve(projectRoot14, String(flags30.evidenceDir)),
|
|
35801
|
+
deploymentId: String(flags30.deployment),
|
|
35802
|
+
bundleDir: import_node_path33.default.dirname(runtimeEvidencePath),
|
|
35637
35803
|
scorecardPath: outPath,
|
|
35638
35804
|
runtimeFeedback: feedbackSource ? {
|
|
35639
35805
|
artifactId: feedbackSource.feedback.manifest.artifactId,
|
|
@@ -35641,8 +35807,8 @@ var init_runtimeScorecard2 = __esm({
|
|
|
35641
35807
|
} : null
|
|
35642
35808
|
});
|
|
35643
35809
|
}
|
|
35644
|
-
console.log(
|
|
35645
|
-
console.log(
|
|
35810
|
+
console.log(import_chalk49.default.green(`Wrote ${outPath}`));
|
|
35811
|
+
console.log(import_chalk49.default.green(`Wrote ${markdownPath}`));
|
|
35646
35812
|
console.log(
|
|
35647
35813
|
JSON.stringify(
|
|
35648
35814
|
{
|
|
@@ -35661,7 +35827,7 @@ var init_runtimeScorecard2 = __esm({
|
|
|
35661
35827
|
)
|
|
35662
35828
|
);
|
|
35663
35829
|
};
|
|
35664
|
-
|
|
35830
|
+
main40 = runtimeScorecard;
|
|
35665
35831
|
}
|
|
35666
35832
|
});
|
|
35667
35833
|
|
|
@@ -35669,10 +35835,10 @@ var init_runtimeScorecard2 = __esm({
|
|
|
35669
35835
|
var runtimeControl_exports = {};
|
|
35670
35836
|
__export(runtimeControl_exports, {
|
|
35671
35837
|
RUNTIME_CONTROL_ACTIONS: () => RUNTIME_CONTROL_ACTIONS,
|
|
35672
|
-
main: () =>
|
|
35838
|
+
main: () => main41,
|
|
35673
35839
|
runtimeControl: () => runtimeControl
|
|
35674
35840
|
});
|
|
35675
|
-
var import_config9, import_runtimeControls, import_runtimeStrategies6, argv, RUNTIME_CONTROL_ACTIONS, action, option, required2,
|
|
35841
|
+
var import_config9, import_runtimeControls, import_runtimeStrategies6, argv, RUNTIME_CONTROL_ACTIONS, action, option, required2, projectRoot15, userName2, verify, inspect, updateControlState, runtimeControl, main41;
|
|
35676
35842
|
var init_runtimeControl = __esm({
|
|
35677
35843
|
"src/scripts/runtimeControl.ts"() {
|
|
35678
35844
|
"use strict";
|
|
@@ -35696,10 +35862,10 @@ var init_runtimeControl = __esm({
|
|
|
35696
35862
|
if (!value) throw new Error(`--${name} is required`);
|
|
35697
35863
|
return value;
|
|
35698
35864
|
};
|
|
35699
|
-
|
|
35865
|
+
projectRoot15 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
|
|
35700
35866
|
userName2 = String(option("user") ?? process.env.USER_NAME ?? "root");
|
|
35701
35867
|
verify = async () => {
|
|
35702
|
-
const deployments = await (0, import_runtimeStrategies6.listRuntimeDeployments)({ userName: userName2, projectRoot:
|
|
35868
|
+
const deployments = await (0, import_runtimeStrategies6.listRuntimeDeployments)({ userName: userName2, projectRoot: projectRoot15 });
|
|
35703
35869
|
const requestedDeployment = option("deployment");
|
|
35704
35870
|
const selected = requestedDeployment ? deployments.filter((deployment) => deployment.id === requestedDeployment) : deployments;
|
|
35705
35871
|
if (requestedDeployment && !selected.length) {
|
|
@@ -35710,7 +35876,7 @@ var init_runtimeControl = __esm({
|
|
|
35710
35876
|
try {
|
|
35711
35877
|
const strategies = await (0, import_runtimeStrategies6.loadResolvedRuntimeStrategies)({
|
|
35712
35878
|
userName: userName2,
|
|
35713
|
-
projectRoot:
|
|
35879
|
+
projectRoot: projectRoot15,
|
|
35714
35880
|
deploymentId: deployment.id
|
|
35715
35881
|
});
|
|
35716
35882
|
results2.push({
|
|
@@ -35743,7 +35909,7 @@ var init_runtimeControl = __esm({
|
|
|
35743
35909
|
inspect = async () => {
|
|
35744
35910
|
const requestedDeployment = option("deployment");
|
|
35745
35911
|
const requestedStrategy = option("strategy");
|
|
35746
|
-
const deployments = (await (0, import_runtimeStrategies6.listRuntimeDeployments)({ userName: userName2, projectRoot:
|
|
35912
|
+
const deployments = (await (0, import_runtimeStrategies6.listRuntimeDeployments)({ userName: userName2, projectRoot: projectRoot15 })).filter(
|
|
35747
35913
|
(deployment) => !requestedDeployment || deployment.id === requestedDeployment
|
|
35748
35914
|
).map((deployment) => ({
|
|
35749
35915
|
...deployment,
|
|
@@ -35758,7 +35924,7 @@ var init_runtimeControl = __esm({
|
|
|
35758
35924
|
const strategyName = required2("strategy");
|
|
35759
35925
|
const deployment = await (0, import_runtimeStrategies6.getRuntimeDeployment)({
|
|
35760
35926
|
userName: userName2,
|
|
35761
|
-
projectRoot:
|
|
35927
|
+
projectRoot: projectRoot15,
|
|
35762
35928
|
deploymentId
|
|
35763
35929
|
});
|
|
35764
35930
|
if (!deployment) {
|
|
@@ -35788,7 +35954,7 @@ var init_runtimeControl = __esm({
|
|
|
35788
35954
|
}
|
|
35789
35955
|
const updated = await (0, import_runtimeStrategies6.getRuntimeDeployment)({
|
|
35790
35956
|
userName: userName2,
|
|
35791
|
-
projectRoot:
|
|
35957
|
+
projectRoot: projectRoot15,
|
|
35792
35958
|
deploymentId
|
|
35793
35959
|
});
|
|
35794
35960
|
const updatedReference = updated?.strategies.find(
|
|
@@ -35820,25 +35986,25 @@ var init_runtimeControl = __esm({
|
|
|
35820
35986
|
`Usage: tradejs runtime-control ${RUNTIME_CONTROL_ACTIONS.join("|")}`
|
|
35821
35987
|
);
|
|
35822
35988
|
};
|
|
35823
|
-
|
|
35989
|
+
main41 = runtimeControl;
|
|
35824
35990
|
}
|
|
35825
35991
|
});
|
|
35826
35992
|
|
|
35827
35993
|
// src/scripts/strategyRelease.ts
|
|
35828
35994
|
var strategyRelease_exports = {};
|
|
35829
35995
|
__export(strategyRelease_exports, {
|
|
35830
|
-
main: () =>
|
|
35996
|
+
main: () => main42,
|
|
35831
35997
|
runStrategyReleaseCommand: () => runStrategyReleaseCommand
|
|
35832
35998
|
});
|
|
35833
|
-
var import_promises35, import_node_fs5, import_node_readline2,
|
|
35999
|
+
var import_promises35, import_node_fs5, import_node_readline2, import_node_path34, import_chalk50, valueAfter2, required3, writeJsonAtomic3, runStrategyReleaseCommand, printUsage2, main42;
|
|
35834
36000
|
var init_strategyRelease2 = __esm({
|
|
35835
36001
|
"src/scripts/strategyRelease.ts"() {
|
|
35836
36002
|
"use strict";
|
|
35837
36003
|
import_promises35 = __toESM(require("fs/promises"));
|
|
35838
36004
|
import_node_fs5 = require("fs");
|
|
35839
36005
|
import_node_readline2 = require("readline");
|
|
35840
|
-
|
|
35841
|
-
|
|
36006
|
+
import_node_path34 = __toESM(require("path"));
|
|
36007
|
+
import_chalk50 = __toESM(require("chalk"));
|
|
35842
36008
|
init_strategyRelease();
|
|
35843
36009
|
valueAfter2 = (argv2, name) => {
|
|
35844
36010
|
const index = argv2.indexOf(name);
|
|
@@ -35850,7 +36016,7 @@ var init_strategyRelease2 = __esm({
|
|
|
35850
36016
|
};
|
|
35851
36017
|
writeJsonAtomic3 = async (filePath, value) => {
|
|
35852
36018
|
const temporaryPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
35853
|
-
await import_promises35.default.mkdir(
|
|
36019
|
+
await import_promises35.default.mkdir(import_node_path34.default.dirname(filePath), { recursive: true });
|
|
35854
36020
|
await import_promises35.default.writeFile(
|
|
35855
36021
|
temporaryPath,
|
|
35856
36022
|
`${JSON.stringify(value, null, 2)}
|
|
@@ -35860,7 +36026,7 @@ var init_strategyRelease2 = __esm({
|
|
|
35860
36026
|
await import_promises35.default.rename(temporaryPath, filePath);
|
|
35861
36027
|
};
|
|
35862
36028
|
runStrategyReleaseCommand = async (options) => {
|
|
35863
|
-
const inputPath =
|
|
36029
|
+
const inputPath = import_node_path34.default.resolve(options.inputPath);
|
|
35864
36030
|
if (options.command === "verify") {
|
|
35865
36031
|
const envelope = await verifyStrategyReleaseEnvelope(inputPath);
|
|
35866
36032
|
return {
|
|
@@ -35898,7 +36064,7 @@ var init_strategyRelease2 = __esm({
|
|
|
35898
36064
|
endTime,
|
|
35899
36065
|
days: options.days?.length ? options.days : [7, 30, 90]
|
|
35900
36066
|
});
|
|
35901
|
-
const outputPath =
|
|
36067
|
+
const outputPath = import_node_path34.default.resolve(
|
|
35902
36068
|
options.outputPath ?? "output/strategy-monitoring-profile.json"
|
|
35903
36069
|
);
|
|
35904
36070
|
await writeJsonAtomic3(outputPath, profile);
|
|
@@ -35913,12 +36079,12 @@ var init_strategyRelease2 = __esm({
|
|
|
35913
36079
|
if (options.command === "decide") {
|
|
35914
36080
|
const decision = await deriveStrategyReleaseResearchDecision(input);
|
|
35915
36081
|
if (options.outputPath) {
|
|
35916
|
-
await writeJsonAtomic3(
|
|
36082
|
+
await writeJsonAtomic3(import_node_path34.default.resolve(options.outputPath), decision);
|
|
35917
36083
|
}
|
|
35918
36084
|
return {
|
|
35919
36085
|
kind: "decided",
|
|
35920
36086
|
...decision,
|
|
35921
|
-
outputPath: options.outputPath ?
|
|
36087
|
+
outputPath: options.outputPath ? import_node_path34.default.resolve(options.outputPath) : null
|
|
35922
36088
|
};
|
|
35923
36089
|
}
|
|
35924
36090
|
if (options.command === "retention") {
|
|
@@ -35937,12 +36103,12 @@ var init_strategyRelease2 = __esm({
|
|
|
35937
36103
|
}
|
|
35938
36104
|
if (options.command === "diagnose") {
|
|
35939
36105
|
const diagnosis = buildStrategyLiveDiagnosis(input);
|
|
35940
|
-
const outputPath =
|
|
36106
|
+
const outputPath = import_node_path34.default.resolve(
|
|
35941
36107
|
options.outputPath ?? "output/strategy-live-diagnosis.json"
|
|
35942
36108
|
);
|
|
35943
36109
|
await writeJsonAtomic3(outputPath, diagnosis);
|
|
35944
36110
|
const published2 = options.rootDir ? await publishStrategyLiveDiagnosis({
|
|
35945
|
-
rootDir:
|
|
36111
|
+
rootDir: import_node_path34.default.resolve(options.rootDir),
|
|
35946
36112
|
diagnosis,
|
|
35947
36113
|
sourceArtifacts: input.sourceArtifacts ?? []
|
|
35948
36114
|
}) : null;
|
|
@@ -35959,7 +36125,7 @@ var init_strategyRelease2 = __esm({
|
|
|
35959
36125
|
evidence: await collectReleaseEvidenceReferences(input.evidence ?? [])
|
|
35960
36126
|
});
|
|
35961
36127
|
const published = await publishStrategyRelease({
|
|
35962
|
-
rootDir:
|
|
36128
|
+
rootDir: import_node_path34.default.resolve(options.rootDir ?? "data/strategy-release"),
|
|
35963
36129
|
manifest
|
|
35964
36130
|
});
|
|
35965
36131
|
return {
|
|
@@ -35977,7 +36143,7 @@ var init_strategyRelease2 = __esm({
|
|
|
35977
36143
|
yarn strategy:release profile --input <trades.jsonl> --variant <id> --startTime <ms> --endTime <ms> [--days 7,30,90] [--out <profile.json>]
|
|
35978
36144
|
yarn strategy:release diagnose --input <diagnosis-input.json> [--out output/diagnosis.json]
|
|
35979
36145
|
yarn strategy:release retention --input <inventory.json> [--apply]`);
|
|
35980
|
-
|
|
36146
|
+
main42 = async () => {
|
|
35981
36147
|
const argv2 = process.argv.slice(2);
|
|
35982
36148
|
const command = argv2[0];
|
|
35983
36149
|
if (!command || ![
|
|
@@ -36003,7 +36169,7 @@ var init_strategyRelease2 = __esm({
|
|
|
36003
36169
|
endTime: Number(valueAfter2(argv2, "--endTime")),
|
|
36004
36170
|
days: valueAfter2(argv2, "--days")?.split(",").map((entry) => Number(entry.trim()))
|
|
36005
36171
|
});
|
|
36006
|
-
console.log(
|
|
36172
|
+
console.log(import_chalk50.default.green(JSON.stringify(result, null, 2)));
|
|
36007
36173
|
};
|
|
36008
36174
|
}
|
|
36009
36175
|
});
|
|
@@ -36016,10 +36182,10 @@ __export(serverHealth_exports, {
|
|
|
36016
36182
|
buildServerHealthDiagnostics: () => buildServerHealthDiagnostics,
|
|
36017
36183
|
collectServerHealthSnapshot: () => collectServerHealthSnapshot,
|
|
36018
36184
|
evaluateServerHealth: () => evaluateServerHealth,
|
|
36019
|
-
main: () =>
|
|
36185
|
+
main: () => main43,
|
|
36020
36186
|
resolveServerHealthThresholds: () => resolveServerHealthThresholds
|
|
36021
36187
|
});
|
|
36022
|
-
var import_config10, import_node_child_process9, import_node_os3, import_node_fs6,
|
|
36188
|
+
var import_config10, import_node_child_process9, import_node_os3, import_node_fs6, import_args33, import_redis19, DEFAULT_STATE, DEFAULT_THRESHOLDS, escapeHtml6, formatPctValue, formatLoadPerCore, formatGiB, formatDuration2, readDiskUsage, parseMeminfoBytes, readMemorySnapshot, runDiagnosticCommand, runDiagnosticCommands, collectServerHealthSnapshot, buildHumanSummaryLines, evaluateServerHealth, shouldRecover, buildAlertMessage, buildRecoveryMessage, buildServerHealthDiagnostics, getStateKey, toFiniteNumber3, resolveServerHealthThresholds, main43;
|
|
36023
36189
|
var init_serverHealth = __esm({
|
|
36024
36190
|
"src/scripts/serverHealth.ts"() {
|
|
36025
36191
|
"use strict";
|
|
@@ -36027,7 +36193,7 @@ var init_serverHealth = __esm({
|
|
|
36027
36193
|
import_node_child_process9 = require("child_process");
|
|
36028
36194
|
import_node_os3 = __toESM(require("os"));
|
|
36029
36195
|
import_node_fs6 = require("fs");
|
|
36030
|
-
|
|
36196
|
+
import_args33 = __toESM(require("args"));
|
|
36031
36197
|
import_redis19 = require("@tradejs/infra/redis");
|
|
36032
36198
|
init_telegramReports();
|
|
36033
36199
|
DEFAULT_STATE = {
|
|
@@ -36044,7 +36210,7 @@ var init_serverHealth = __esm({
|
|
|
36044
36210
|
diskWarnPct: 95,
|
|
36045
36211
|
diskRecoverPct: 92
|
|
36046
36212
|
};
|
|
36047
|
-
|
|
36213
|
+
escapeHtml6 = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
36048
36214
|
formatPctValue = (value) => `${value.toFixed(1)}%`;
|
|
36049
36215
|
formatLoadPerCore = (value) => value.toFixed(2);
|
|
36050
36216
|
formatGiB = (bytes) => `${(bytes / 1024 ** 3).toFixed(1)} GB`;
|
|
@@ -36061,21 +36227,21 @@ var init_serverHealth = __esm({
|
|
|
36061
36227
|
}
|
|
36062
36228
|
return `${minutes}m`;
|
|
36063
36229
|
};
|
|
36064
|
-
readDiskUsage = (
|
|
36230
|
+
readDiskUsage = (path45) => {
|
|
36065
36231
|
try {
|
|
36066
|
-
const stats = (0, import_node_fs6.statfsSync)(
|
|
36232
|
+
const stats = (0, import_node_fs6.statfsSync)(path45);
|
|
36067
36233
|
const totalBlocks = Number(stats.blocks ?? 0);
|
|
36068
36234
|
const availableBlocks = Number(stats.bavail ?? 0);
|
|
36069
36235
|
if (totalBlocks <= 0) {
|
|
36070
|
-
return { path:
|
|
36236
|
+
return { path: path45, usedPct: null };
|
|
36071
36237
|
}
|
|
36072
36238
|
const usedPct = (totalBlocks - Math.max(0, availableBlocks)) / totalBlocks * 100;
|
|
36073
36239
|
return {
|
|
36074
|
-
path:
|
|
36240
|
+
path: path45,
|
|
36075
36241
|
usedPct: Number.isFinite(usedPct) ? usedPct : null
|
|
36076
36242
|
};
|
|
36077
36243
|
} catch {
|
|
36078
|
-
return { path:
|
|
36244
|
+
return { path: path45, usedPct: null };
|
|
36079
36245
|
}
|
|
36080
36246
|
};
|
|
36081
36247
|
parseMeminfoBytes = (value) => {
|
|
@@ -36139,8 +36305,8 @@ var init_serverHealth = __esm({
|
|
|
36139
36305
|
};
|
|
36140
36306
|
}
|
|
36141
36307
|
};
|
|
36142
|
-
runDiagnosticCommand = (command,
|
|
36143
|
-
const output = (0, import_node_child_process9.execFileSync)(command,
|
|
36308
|
+
runDiagnosticCommand = (command, args38) => {
|
|
36309
|
+
const output = (0, import_node_child_process9.execFileSync)(command, args38, {
|
|
36144
36310
|
encoding: "utf8",
|
|
36145
36311
|
timeout: 5e3,
|
|
36146
36312
|
maxBuffer: 1024 * 1024,
|
|
@@ -36187,11 +36353,11 @@ var init_serverHealth = __esm({
|
|
|
36187
36353
|
snapshot.memory.totalBytes - snapshot.memory.availableBytes
|
|
36188
36354
|
);
|
|
36189
36355
|
return [
|
|
36190
|
-
`\u2022 vCPU: <b>${
|
|
36191
|
-
`\u2022 RAM: <b>${
|
|
36356
|
+
`\u2022 vCPU: <b>${escapeHtml6(formatPctValue(Math.min(100, snapshot.loadPerCpu1 * 100)))}</b>`,
|
|
36357
|
+
`\u2022 RAM: <b>${escapeHtml6(formatPctValue(snapshot.memoryUsedPct))}</b> (${escapeHtml6(
|
|
36192
36358
|
`${formatGiB(usedMem)} / ${formatGiB(snapshot.memory.totalBytes)}`
|
|
36193
36359
|
)})`,
|
|
36194
|
-
`\u2022 Storage: <b>${
|
|
36360
|
+
`\u2022 Storage: <b>${escapeHtml6(
|
|
36195
36361
|
snapshot.disk.usedPct == null ? "n/a" : formatPctValue(snapshot.disk.usedPct)
|
|
36196
36362
|
)}</b>`
|
|
36197
36363
|
];
|
|
@@ -36235,22 +36401,22 @@ var init_serverHealth = __esm({
|
|
|
36235
36401
|
return [
|
|
36236
36402
|
title,
|
|
36237
36403
|
"",
|
|
36238
|
-
`Host: <b>${
|
|
36239
|
-
`Time: <b>${
|
|
36240
|
-
`Uptime: <b>${
|
|
36404
|
+
`Host: <b>${escapeHtml6(snapshot.hostname)}</b>`,
|
|
36405
|
+
`Time: <b>${escapeHtml6(new Date(snapshot.timestamp).toISOString())}</b>`,
|
|
36406
|
+
`Uptime: <b>${escapeHtml6(formatDuration2(snapshot.uptimeSec))}</b>`,
|
|
36241
36407
|
"",
|
|
36242
36408
|
"Summary:",
|
|
36243
36409
|
...buildHumanSummaryLines(snapshot),
|
|
36244
36410
|
"",
|
|
36245
36411
|
"Issues:",
|
|
36246
|
-
...issues.map((issue) => `\u2022 ${
|
|
36412
|
+
...issues.map((issue) => `\u2022 ${escapeHtml6(issue.summary)}`),
|
|
36247
36413
|
"",
|
|
36248
36414
|
"Pressure:",
|
|
36249
36415
|
`\u2022 Load avg: <b>${snapshot.load1.toFixed(2)} / ${snapshot.load5.toFixed(2)} / ${snapshot.load15.toFixed(2)}</b>`,
|
|
36250
36416
|
`\u2022 Load per core: <b>${formatLoadPerCore(
|
|
36251
36417
|
snapshot.loadPerCpu1
|
|
36252
36418
|
)}</b> (1m), <b>${formatLoadPerCore(snapshot.loadPerCpu5)}</b> (5m)`,
|
|
36253
|
-
prevState.lastAlertAt ? `\u2022 Previous alert: <b>${
|
|
36419
|
+
prevState.lastAlertAt ? `\u2022 Previous alert: <b>${escapeHtml6(new Date(prevState.lastAlertAt).toISOString())}</b>` : "\u2022 Previous alert: <b>none</b>"
|
|
36254
36420
|
].join("\n");
|
|
36255
36421
|
};
|
|
36256
36422
|
buildRecoveryMessage = ({
|
|
@@ -36259,9 +36425,9 @@ var init_serverHealth = __esm({
|
|
|
36259
36425
|
}) => [
|
|
36260
36426
|
"\u2705 <b>TradeJS server health recovered</b>",
|
|
36261
36427
|
"",
|
|
36262
|
-
`Host: <b>${
|
|
36263
|
-
`Time: <b>${
|
|
36264
|
-
`Uptime: <b>${
|
|
36428
|
+
`Host: <b>${escapeHtml6(snapshot.hostname)}</b>`,
|
|
36429
|
+
`Time: <b>${escapeHtml6(new Date(snapshot.timestamp).toISOString())}</b>`,
|
|
36430
|
+
`Uptime: <b>${escapeHtml6(formatDuration2(snapshot.uptimeSec))}</b>`,
|
|
36265
36431
|
"",
|
|
36266
36432
|
"Summary:",
|
|
36267
36433
|
...buildHumanSummaryLines(snapshot),
|
|
@@ -36271,7 +36437,7 @@ var init_serverHealth = __esm({
|
|
|
36271
36437
|
`\u2022 Load per core: <b>${formatLoadPerCore(
|
|
36272
36438
|
snapshot.loadPerCpu1
|
|
36273
36439
|
)}</b> (1m), <b>${formatLoadPerCore(snapshot.loadPerCpu5)}</b> (5m)`,
|
|
36274
|
-
prevState.lastAlertAt ? `\u2022 Alert started: <b>${
|
|
36440
|
+
prevState.lastAlertAt ? `\u2022 Alert started: <b>${escapeHtml6(new Date(prevState.lastAlertAt).toISOString())}</b>` : "\u2022 Alert started: <b>unknown</b>"
|
|
36275
36441
|
].join("\n");
|
|
36276
36442
|
buildServerHealthDiagnostics = ({
|
|
36277
36443
|
snapshot,
|
|
@@ -36390,57 +36556,57 @@ var init_serverHealth = __esm({
|
|
|
36390
36556
|
diskRecoverPct: diskRecoverPct != null && diskRecoverPct > 0 ? diskRecoverPct : DEFAULT_THRESHOLDS.diskRecoverPct
|
|
36391
36557
|
};
|
|
36392
36558
|
};
|
|
36393
|
-
|
|
36394
|
-
|
|
36395
|
-
|
|
36559
|
+
import_args33.default.option(["u", "user"], "Use user config", "root");
|
|
36560
|
+
import_args33.default.option(["P", "printOnly"], "Print report instead of Telegram", false);
|
|
36561
|
+
import_args33.default.option(
|
|
36396
36562
|
["d", "diskPath"],
|
|
36397
36563
|
"Filesystem path to inspect for disk pressure",
|
|
36398
36564
|
"/"
|
|
36399
36565
|
);
|
|
36400
|
-
|
|
36566
|
+
import_args33.default.option(
|
|
36401
36567
|
["c", "cooldownSec"],
|
|
36402
36568
|
"Minimum seconds between repeated unhealthy reminders",
|
|
36403
36569
|
900
|
|
36404
36570
|
);
|
|
36405
|
-
|
|
36571
|
+
import_args33.default.option(
|
|
36406
36572
|
["l", "loadPerCpuWarn"],
|
|
36407
36573
|
"Alert when 1m load per CPU reaches this value",
|
|
36408
36574
|
String(DEFAULT_THRESHOLDS.loadPerCpuWarn)
|
|
36409
36575
|
);
|
|
36410
|
-
|
|
36576
|
+
import_args33.default.option(
|
|
36411
36577
|
["L", "loadPerCpuRecover"],
|
|
36412
36578
|
"Recovery threshold for 1m load per CPU",
|
|
36413
36579
|
String(DEFAULT_THRESHOLDS.loadPerCpuRecover)
|
|
36414
36580
|
);
|
|
36415
|
-
|
|
36581
|
+
import_args33.default.option(
|
|
36416
36582
|
["m", "memoryWarnPct"],
|
|
36417
36583
|
"Alert when memory used percent reaches this value",
|
|
36418
36584
|
String(DEFAULT_THRESHOLDS.memoryWarnPct)
|
|
36419
36585
|
);
|
|
36420
|
-
|
|
36586
|
+
import_args33.default.option(
|
|
36421
36587
|
["M", "memoryRecoverPct"],
|
|
36422
36588
|
"Recovery threshold for memory used percent",
|
|
36423
36589
|
String(DEFAULT_THRESHOLDS.memoryRecoverPct)
|
|
36424
36590
|
);
|
|
36425
|
-
|
|
36591
|
+
import_args33.default.option(
|
|
36426
36592
|
["D", "diskWarnPct"],
|
|
36427
36593
|
"Alert when disk used percent reaches this value",
|
|
36428
36594
|
String(DEFAULT_THRESHOLDS.diskWarnPct)
|
|
36429
36595
|
);
|
|
36430
|
-
|
|
36596
|
+
import_args33.default.option(
|
|
36431
36597
|
["R", "diskRecoverPct"],
|
|
36432
36598
|
"Recovery threshold for disk used percent",
|
|
36433
36599
|
String(DEFAULT_THRESHOLDS.diskRecoverPct)
|
|
36434
36600
|
);
|
|
36435
|
-
|
|
36436
|
-
const
|
|
36437
|
-
const thresholds = resolveServerHealthThresholds(
|
|
36438
|
-
const diskPath = String(
|
|
36601
|
+
main43 = async () => {
|
|
36602
|
+
const flags35 = import_args33.default.parse(process.argv);
|
|
36603
|
+
const thresholds = resolveServerHealthThresholds(flags35);
|
|
36604
|
+
const diskPath = String(flags35.diskPath || "/");
|
|
36439
36605
|
const snapshot = collectServerHealthSnapshot(diskPath);
|
|
36440
|
-
const stateKey = getStateKey(String(
|
|
36606
|
+
const stateKey = getStateKey(String(flags35.user), snapshot.hostname);
|
|
36441
36607
|
const prevState = await (0, import_redis19.getData)(stateKey, DEFAULT_STATE) ?? DEFAULT_STATE;
|
|
36442
36608
|
const evaluation = evaluateServerHealth(snapshot, thresholds);
|
|
36443
|
-
const cooldownMs = Math.max(60, Number(
|
|
36609
|
+
const cooldownMs = Math.max(60, Number(flags35.cooldownSec)) * 1e3;
|
|
36444
36610
|
const now2 = snapshot.timestamp;
|
|
36445
36611
|
if (!evaluation.isHealthy) {
|
|
36446
36612
|
const reminder = prevState.status === "alerting" && typeof prevState.lastAlertAt === "number" && now2 - prevState.lastAlertAt < cooldownMs ? false : prevState.status === "alerting";
|
|
@@ -36458,7 +36624,7 @@ var init_serverHealth = __esm({
|
|
|
36458
36624
|
prevState,
|
|
36459
36625
|
reminder
|
|
36460
36626
|
});
|
|
36461
|
-
if (
|
|
36627
|
+
if (flags35.printOnly) {
|
|
36462
36628
|
console.log(message);
|
|
36463
36629
|
console.log("");
|
|
36464
36630
|
console.log(
|
|
@@ -36468,7 +36634,7 @@ var init_serverHealth = __esm({
|
|
|
36468
36634
|
})
|
|
36469
36635
|
);
|
|
36470
36636
|
} else {
|
|
36471
|
-
await sendTelegramReport(message, { userName:
|
|
36637
|
+
await sendTelegramReport(message, { userName: flags35.user });
|
|
36472
36638
|
}
|
|
36473
36639
|
}
|
|
36474
36640
|
return;
|
|
@@ -36483,10 +36649,10 @@ var init_serverHealth = __esm({
|
|
|
36483
36649
|
await (0, import_redis19.setData)(stateKey, nextState, { expire: 0 });
|
|
36484
36650
|
if (recovered) {
|
|
36485
36651
|
const message = buildRecoveryMessage({ snapshot, prevState });
|
|
36486
|
-
if (
|
|
36652
|
+
if (flags35.printOnly) {
|
|
36487
36653
|
console.log(message);
|
|
36488
36654
|
} else {
|
|
36489
|
-
await sendTelegramReport(message, { userName:
|
|
36655
|
+
await sendTelegramReport(message, { userName: flags35.user });
|
|
36490
36656
|
}
|
|
36491
36657
|
}
|
|
36492
36658
|
};
|
|
@@ -37533,11 +37699,11 @@ var init_reportingJson = __esm({
|
|
|
37533
37699
|
});
|
|
37534
37700
|
|
|
37535
37701
|
// src/lib/runtimeParity/reportingTerminal.ts
|
|
37536
|
-
var
|
|
37702
|
+
var import_chalk51, import_time12, DETAIL_LIMIT, buildRuntimeParityTerminalReport, writeRuntimeParityTerminalReport, printRuntimeDuplicateDetails, printClassifiedBacktestOnlyDetails, printClassifiedRuntimeOnlyDetails;
|
|
37537
37703
|
var init_reportingTerminal = __esm({
|
|
37538
37704
|
"src/lib/runtimeParity/reportingTerminal.ts"() {
|
|
37539
37705
|
"use strict";
|
|
37540
|
-
|
|
37706
|
+
import_chalk51 = __toESM(require("chalk"));
|
|
37541
37707
|
import_time12 = require("@tradejs/core/time");
|
|
37542
37708
|
init_classification();
|
|
37543
37709
|
init_reportingShared();
|
|
@@ -37546,7 +37712,7 @@ var init_reportingTerminal = __esm({
|
|
|
37546
37712
|
const mismatchRows = buildMismatchSummaryRows(context);
|
|
37547
37713
|
const strategyIssueRows = buildStrategyIssueRows(context.strategyRows);
|
|
37548
37714
|
const lines = [
|
|
37549
|
-
|
|
37715
|
+
import_chalk51.default.cyan("TradeJS runtime parity"),
|
|
37550
37716
|
`Window: ${(0, import_time12.formatUnix)(context.window.start)} -> ${(0, import_time12.formatUnix)(context.window.end)} (${context.window.source})`,
|
|
37551
37717
|
`Connector: ${context.connectorName}`,
|
|
37552
37718
|
`Replay env: ${context.replayEnv}${context.runtimeGatesEnabled ? " (runtime AI/ML gates enabled)" : " (core/backtest gates only)"}`,
|
|
@@ -37575,7 +37741,7 @@ var init_reportingTerminal = __esm({
|
|
|
37575
37741
|
lines.push(`Runtime evaluations: ${context.runtimeSignalEvaluationsCount}`);
|
|
37576
37742
|
}
|
|
37577
37743
|
if (mismatchRows.length) {
|
|
37578
|
-
lines.push("",
|
|
37744
|
+
lines.push("", import_chalk51.default.yellow("Signal mismatches"));
|
|
37579
37745
|
for (const item of mismatchRows.slice(0, context.detailLimit)) {
|
|
37580
37746
|
lines.push(`- ${item.line}`);
|
|
37581
37747
|
}
|
|
@@ -37585,14 +37751,14 @@ var init_reportingTerminal = __esm({
|
|
|
37585
37751
|
}
|
|
37586
37752
|
lines.push("");
|
|
37587
37753
|
if (strategyIssueRows.length) {
|
|
37588
|
-
lines.push(
|
|
37754
|
+
lines.push(import_chalk51.default.cyan("Strategy issues"), ...strategyIssueRows);
|
|
37589
37755
|
} else if (context.strategyRows.length) {
|
|
37590
37756
|
lines.push(
|
|
37591
37757
|
`Strategies: clean ${context.strategyRows.length}/${context.strategyRows.length}`
|
|
37592
37758
|
);
|
|
37593
37759
|
}
|
|
37594
37760
|
if (context.runtimeGateWarningCounts.size && !context.runtimeGatesRequested) {
|
|
37595
|
-
lines.push("",
|
|
37761
|
+
lines.push("", import_chalk51.default.yellow("Warnings"));
|
|
37596
37762
|
for (const [strategy, count] of [
|
|
37597
37763
|
...context.runtimeGateWarningCounts.entries()
|
|
37598
37764
|
].sort(([left], [right]) => left.localeCompare(right))) {
|
|
@@ -37602,7 +37768,7 @@ var init_reportingTerminal = __esm({
|
|
|
37602
37768
|
}
|
|
37603
37769
|
}
|
|
37604
37770
|
if (context.replayErrors.length) {
|
|
37605
|
-
lines.push("",
|
|
37771
|
+
lines.push("", import_chalk51.default.red("Replay errors"));
|
|
37606
37772
|
for (const error of context.replayErrors.slice(0, context.detailLimit)) {
|
|
37607
37773
|
lines.push(`- ${error.strategy} ${error.symbol}: ${error.message}`);
|
|
37608
37774
|
}
|
|
@@ -37620,7 +37786,7 @@ var init_reportingTerminal = __esm({
|
|
|
37620
37786
|
printRuntimeDuplicateDetails = (groups) => {
|
|
37621
37787
|
if (!groups.length) return;
|
|
37622
37788
|
console.log("");
|
|
37623
|
-
console.log(
|
|
37789
|
+
console.log(import_chalk51.default.yellow("Runtime duplicates"));
|
|
37624
37790
|
for (const group of groups.slice(0, DETAIL_LIMIT)) {
|
|
37625
37791
|
const ids = group.entries.map((entry) => entry.orderId ?? entry.id);
|
|
37626
37792
|
console.log(
|
|
@@ -37634,7 +37800,7 @@ var init_reportingTerminal = __esm({
|
|
|
37634
37800
|
printClassifiedBacktestOnlyDetails = (classifiedEntries) => {
|
|
37635
37801
|
if (!classifiedEntries.length) return;
|
|
37636
37802
|
console.log("");
|
|
37637
|
-
console.log(
|
|
37803
|
+
console.log(import_chalk51.default.yellow("Backtest only"));
|
|
37638
37804
|
for (const item of classifiedEntries.slice(0, DETAIL_LIMIT)) {
|
|
37639
37805
|
const evidenceSuffix = item.signal ? ` signalId=${item.signal.signalId} signalDrift=${formatMinutes2(item.signalTimestampDiffMs ?? null)}` : item.evaluation ? ` evaluationId=${item.evaluation.evaluationId} evaluationDrift=${formatMinutes2(item.evaluationTimestampDiffMs ?? null)}` : "";
|
|
37640
37806
|
const price = item.entry.price == null ? "n/a" : item.entry.price.toFixed(6);
|
|
@@ -37649,7 +37815,7 @@ var init_reportingTerminal = __esm({
|
|
|
37649
37815
|
printClassifiedRuntimeOnlyDetails = (classifiedEntries) => {
|
|
37650
37816
|
if (!classifiedEntries.length) return;
|
|
37651
37817
|
console.log("");
|
|
37652
|
-
console.log(
|
|
37818
|
+
console.log(import_chalk51.default.yellow("Runtime only"));
|
|
37653
37819
|
for (const item of classifiedEntries.slice(0, DETAIL_LIMIT)) {
|
|
37654
37820
|
const evidenceSuffix = item.nearestBacktestEntry ? ` nearestBacktestId=${item.nearestBacktestEntry.id} backtestDrift=${formatMinutes2(item.nearestBacktestEntryTimestampDiffMs ?? null)}` : item.evaluation ? ` replayEvaluationId=${item.evaluation.evaluationId} replayDrift=${formatMinutes2(item.evaluationTimestampDiffMs ?? null)} status=${item.evaluation.status}` : "";
|
|
37655
37821
|
const price = item.entry.price == null ? "n/a" : item.entry.price.toFixed(6);
|
|
@@ -37665,7 +37831,7 @@ var init_reportingTerminal = __esm({
|
|
|
37665
37831
|
});
|
|
37666
37832
|
|
|
37667
37833
|
// src/lib/runtimeParity/reportingTelegram.ts
|
|
37668
|
-
var TELEGRAM_DETAIL_LIMIT, SUMMARY_TIMEZONE, SUMMARY_TIMEZONE_LABEL,
|
|
37834
|
+
var TELEGRAM_DETAIL_LIMIT, SUMMARY_TIMEZONE, SUMMARY_TIMEZONE_LABEL, escapeHtml7, formatMskDateTime3, buildRuntimeParityMessage, buildRuntimeParityNoTargetsMessage;
|
|
37669
37835
|
var init_reportingTelegram = __esm({
|
|
37670
37836
|
"src/lib/runtimeParity/reportingTelegram.ts"() {
|
|
37671
37837
|
"use strict";
|
|
@@ -37674,8 +37840,8 @@ var init_reportingTelegram = __esm({
|
|
|
37674
37840
|
TELEGRAM_DETAIL_LIMIT = 5;
|
|
37675
37841
|
SUMMARY_TIMEZONE = "Europe/Moscow";
|
|
37676
37842
|
SUMMARY_TIMEZONE_LABEL = "MSK";
|
|
37677
|
-
|
|
37678
|
-
|
|
37843
|
+
escapeHtml7 = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
37844
|
+
formatMskDateTime3 = (timestamp) => new Intl.DateTimeFormat("ru-RU", {
|
|
37679
37845
|
timeZone: SUMMARY_TIMEZONE,
|
|
37680
37846
|
year: "numeric",
|
|
37681
37847
|
month: "2-digit",
|
|
@@ -37694,11 +37860,11 @@ var init_reportingTelegram = __esm({
|
|
|
37694
37860
|
lines.push("");
|
|
37695
37861
|
lines.push("\u{1F552} <b>Window</b>");
|
|
37696
37862
|
lines.push(
|
|
37697
|
-
`<b>${
|
|
37863
|
+
`<b>${escapeHtml7(formatMskDateTime3(context.window.start))} - ${escapeHtml7(formatMskDateTime3(context.window.end))} ${SUMMARY_TIMEZONE_LABEL}</b>`
|
|
37698
37864
|
);
|
|
37699
37865
|
lines.push("");
|
|
37700
|
-
lines.push(`\u{1F50C} Connector: <b>${
|
|
37701
|
-
lines.push(`\u{1F9EC} Replay env: <b>${
|
|
37866
|
+
lines.push(`\u{1F50C} Connector: <b>${escapeHtml7(context.connectorName)}</b>`);
|
|
37867
|
+
lines.push(`\u{1F9EC} Replay env: <b>${escapeHtml7(context.replayEnv)}</b>`);
|
|
37702
37868
|
lines.push(
|
|
37703
37869
|
`\u{1F3AF} Tolerance: <b>${context.toleranceBars} bar(s) / ${(context.toleranceMs / 6e4).toFixed(0)}m</b>`
|
|
37704
37870
|
);
|
|
@@ -37708,28 +37874,28 @@ var init_reportingTelegram = __esm({
|
|
|
37708
37874
|
`\u2022 Targets: <b>${context.replayTargetsCount}</b> / compared <b>${context.comparedTargetsCount}</b> / errors <b>${context.replayErrors.length}</b>`
|
|
37709
37875
|
);
|
|
37710
37876
|
lines.push(
|
|
37711
|
-
`\u2022 Sources: <b>${
|
|
37877
|
+
`\u2022 Sources: <b>${escapeHtml7(formatSourceCountsSummary(context.sourceCounts))}</b>`
|
|
37712
37878
|
);
|
|
37713
37879
|
lines.push("");
|
|
37714
37880
|
lines.push("\u{1F4C8} <b>Entries</b>");
|
|
37715
37881
|
lines.push(
|
|
37716
|
-
`\u2022 Runtime: <b>${
|
|
37882
|
+
`\u2022 Runtime: <b>${escapeHtml7(formatRuntimeEntriesSummary(context))}</b>`
|
|
37717
37883
|
);
|
|
37718
37884
|
lines.push(`\u2022 Backtest: <b>${context.backtestEntriesCount}</b>`);
|
|
37719
37885
|
lines.push(
|
|
37720
37886
|
`\u2022 Runtime only: <b>${context.runtimeOnlyCount}</b> / Backtest only: <b>${context.backtestOnlyCount}</b>`
|
|
37721
37887
|
);
|
|
37722
37888
|
lines.push(
|
|
37723
|
-
`\u2022 Matched deltas: price avg/max=<b>${
|
|
37889
|
+
`\u2022 Matched deltas: price avg/max=<b>${escapeHtml7(formatPercent5(context.matchedSummary.avgPriceDeltaPct))} / ${escapeHtml7(formatPercent5(context.matchedSummary.maxPriceDeltaPct))}</b>, time avg/max=<b>${escapeHtml7(formatMinutes2(context.matchedSummary.avgTimestampDiffMs))} / ${escapeHtml7(formatMinutes2(context.matchedSummary.maxTimestampDiffMs))}</b>`
|
|
37724
37890
|
);
|
|
37725
37891
|
if (context.classifiedRuntimeOnly.length) {
|
|
37726
37892
|
lines.push(
|
|
37727
|
-
`\u2022 Runtime-only classes: <code>${
|
|
37893
|
+
`\u2022 Runtime-only classes: <code>${escapeHtml7(summarizeRuntimeOnlyClassifications(context.classifiedRuntimeOnly))}</code>`
|
|
37728
37894
|
);
|
|
37729
37895
|
}
|
|
37730
37896
|
if (context.classifiedBacktestOnly.length) {
|
|
37731
37897
|
lines.push(
|
|
37732
|
-
`\u2022 Backtest-only classes: <code>${
|
|
37898
|
+
`\u2022 Backtest-only classes: <code>${escapeHtml7(summarizeBacktestOnlyClassifications(context.classifiedBacktestOnly))}</code>`
|
|
37733
37899
|
);
|
|
37734
37900
|
}
|
|
37735
37901
|
if (context.runtimeSignalEvaluationsCount) {
|
|
@@ -37742,7 +37908,7 @@ var init_reportingTelegram = __esm({
|
|
|
37742
37908
|
lines.push("");
|
|
37743
37909
|
lines.push("\u{1F50E} <b>Mismatches</b>");
|
|
37744
37910
|
for (const item of mismatchRows.slice(0, TELEGRAM_DETAIL_LIMIT)) {
|
|
37745
|
-
lines.push(`\u2022 <code>${
|
|
37911
|
+
lines.push(`\u2022 <code>${escapeHtml7(item.line)}</code>`);
|
|
37746
37912
|
}
|
|
37747
37913
|
if (mismatchRows.length > TELEGRAM_DETAIL_LIMIT) {
|
|
37748
37914
|
lines.push(
|
|
@@ -37755,7 +37921,7 @@ var init_reportingTelegram = __esm({
|
|
|
37755
37921
|
lines.push("");
|
|
37756
37922
|
lines.push("\u{1F4CA} <b>Strategy issues</b>");
|
|
37757
37923
|
for (const line of strategyIssueRows) {
|
|
37758
|
-
lines.push(`\u2022 ${
|
|
37924
|
+
lines.push(`\u2022 ${escapeHtml7(line.slice(2))}`);
|
|
37759
37925
|
}
|
|
37760
37926
|
} else if (context.strategyRows.length) {
|
|
37761
37927
|
lines.push("");
|
|
@@ -37770,7 +37936,7 @@ var init_reportingTelegram = __esm({
|
|
|
37770
37936
|
...runtimeGateWarningCounts.entries()
|
|
37771
37937
|
].sort(([left], [right]) => left.localeCompare(right))) {
|
|
37772
37938
|
lines.push(
|
|
37773
|
-
`\u2022 <b>${
|
|
37939
|
+
`\u2022 <b>${escapeHtml7(strategy)}</b>: AI/ML runtime gates configured on <b>${count}</b> target(s); BACKTEST replay covers core execution only.`
|
|
37774
37940
|
);
|
|
37775
37941
|
}
|
|
37776
37942
|
}
|
|
@@ -37779,7 +37945,7 @@ var init_reportingTelegram = __esm({
|
|
|
37779
37945
|
lines.push("\u274C <b>Replay errors</b>");
|
|
37780
37946
|
for (const error of context.replayErrors.slice(0, TELEGRAM_DETAIL_LIMIT)) {
|
|
37781
37947
|
lines.push(
|
|
37782
|
-
`\u2022 <b>${
|
|
37948
|
+
`\u2022 <b>${escapeHtml7(error.strategy)}</b> ${escapeHtml7(error.symbol)}: <code>${escapeHtml7(error.message)}</code>`
|
|
37783
37949
|
);
|
|
37784
37950
|
}
|
|
37785
37951
|
if (context.replayErrors.length > TELEGRAM_DETAIL_LIMIT) {
|
|
@@ -37799,12 +37965,12 @@ var init_reportingTelegram = __esm({
|
|
|
37799
37965
|
"\u{1F9EA} <b>TradeJS runtime parity</b>",
|
|
37800
37966
|
"",
|
|
37801
37967
|
"\u{1F552} <b>Window</b>",
|
|
37802
|
-
`<b>${
|
|
37968
|
+
`<b>${escapeHtml7(formatMskDateTime3(window.start))} - ${escapeHtml7(formatMskDateTime3(window.end))} ${SUMMARY_TIMEZONE_LABEL}</b>`,
|
|
37803
37969
|
"",
|
|
37804
|
-
`\u{1F50C} Connector: <b>${
|
|
37805
|
-
`\u{1F9EC} Replay env: <b>${
|
|
37970
|
+
`\u{1F50C} Connector: <b>${escapeHtml7(connectorName)}</b>`,
|
|
37971
|
+
`\u{1F9EC} Replay env: <b>${escapeHtml7(replayEnv)}</b>`,
|
|
37806
37972
|
"",
|
|
37807
|
-
`\u26A0\uFE0F No replay targets found for user <b>${
|
|
37973
|
+
`\u26A0\uFE0F No replay targets found for user <b>${escapeHtml7(userName3)}</b>.`
|
|
37808
37974
|
].join("\n");
|
|
37809
37975
|
}
|
|
37810
37976
|
});
|
|
@@ -37824,17 +37990,17 @@ var init_reporting = __esm({
|
|
|
37824
37990
|
var runtimeParity_exports = {};
|
|
37825
37991
|
__export(runtimeParity_exports, {
|
|
37826
37992
|
buildRuntimeParityMessage: () => buildRuntimeParityMessage,
|
|
37827
|
-
main: () =>
|
|
37993
|
+
main: () => main44,
|
|
37828
37994
|
runtimeParity: () => runtimeParity
|
|
37829
37995
|
});
|
|
37830
|
-
var import_config11, import_node_crypto18,
|
|
37996
|
+
var import_config11, import_node_crypto18, import_args34, import_chalk52, import_constants19, import_time13, import_logger7, import_redis20, import_cli12, import_backtest7, import_connectors15, flags31, interval3, projectRoot16, DEFAULT_LOOKBACK_DAYS, DETAIL_LIMIT2, DEFAULT_REPLAY_ENV, resolveParityConnectorName, createConnector, buildReplayAiAnalyses, formatReplayEnvSummary, buildReplayConfig, warmReplayHistory, runtimeParity, main44;
|
|
37831
37997
|
var init_runtimeParity2 = __esm({
|
|
37832
37998
|
"src/scripts/runtimeParity.ts"() {
|
|
37833
37999
|
"use strict";
|
|
37834
38000
|
import_config11 = require("dotenv/config");
|
|
37835
38001
|
import_node_crypto18 = require("crypto");
|
|
37836
|
-
|
|
37837
|
-
|
|
38002
|
+
import_args34 = __toESM(require("args"));
|
|
38003
|
+
import_chalk52 = __toESM(require("chalk"));
|
|
37838
38004
|
import_constants19 = require("@tradejs/core/constants");
|
|
37839
38005
|
import_time13 = require("@tradejs/core/time");
|
|
37840
38006
|
import_logger7 = require("@tradejs/infra/logger");
|
|
@@ -37857,45 +38023,45 @@ var init_runtimeParity2 = __esm({
|
|
|
37857
38023
|
init_reporting();
|
|
37858
38024
|
init_reporting();
|
|
37859
38025
|
init_runtimeModeConfig();
|
|
37860
|
-
|
|
37861
|
-
|
|
38026
|
+
import_args34.default.option(["u", "user"], "Use user config", "root");
|
|
38027
|
+
import_args34.default.option(
|
|
37862
38028
|
["o", "connector"],
|
|
37863
38029
|
"Connector provider or name for parity replay (e.g. bybit, binance, coinbase, custom)",
|
|
37864
38030
|
"bybit"
|
|
37865
38031
|
);
|
|
37866
|
-
|
|
37867
|
-
|
|
38032
|
+
import_args34.default.option(["d", "days"], "Replay window in days", 3);
|
|
38033
|
+
import_args34.default.option(
|
|
37868
38034
|
["b", "startTime"],
|
|
37869
38035
|
"Explicit replay start timestamp (ms or seconds)"
|
|
37870
38036
|
);
|
|
37871
|
-
|
|
37872
|
-
|
|
37873
|
-
|
|
38037
|
+
import_args34.default.option(["e", "endTime"], "Explicit replay end timestamp (ms or seconds)");
|
|
38038
|
+
import_args34.default.option(["s", "strategy"], "Only compare one strategy");
|
|
38039
|
+
import_args34.default.option(
|
|
37874
38040
|
["t", "tickers"],
|
|
37875
38041
|
"Replay comma-separated symbols for all configured strategies"
|
|
37876
38042
|
);
|
|
37877
|
-
|
|
38043
|
+
import_args34.default.option(
|
|
37878
38044
|
["C", "cacheOnly"],
|
|
37879
38045
|
"Do not refresh market history before replay",
|
|
37880
38046
|
false
|
|
37881
38047
|
);
|
|
37882
|
-
|
|
38048
|
+
import_args34.default.option(
|
|
37883
38049
|
["a", "toleranceBars"],
|
|
37884
38050
|
"Allowed entry timestamp drift in bars when matching runtime vs backtest",
|
|
37885
38051
|
1
|
|
37886
38052
|
);
|
|
37887
|
-
|
|
38053
|
+
import_args34.default.option(
|
|
37888
38054
|
"fullUniverse",
|
|
37889
38055
|
"Replay every configured strategy across the full connector universe. By default parity replays only runtime-traded and strategy-results symbols unless --tickers is provided.",
|
|
37890
38056
|
false
|
|
37891
38057
|
);
|
|
37892
|
-
|
|
38058
|
+
import_args34.default.option(
|
|
37893
38059
|
"runtimeGates",
|
|
37894
38060
|
"Force runtime AI/ML gates for all replay targets. Runtime-gated configs are replayed with gates by default.",
|
|
37895
38061
|
false
|
|
37896
38062
|
);
|
|
37897
|
-
|
|
37898
|
-
|
|
38063
|
+
import_args34.default.option(["N", "notify"], "Send parity summary to Telegram", false);
|
|
38064
|
+
import_args34.default.option(["D", "details"], "Print unmatched entry details (capped)", false);
|
|
37899
38065
|
process.argv = normalizeCliArgv(process.argv, {
|
|
37900
38066
|
"-C": "--cacheOnly",
|
|
37901
38067
|
"-D": "--details",
|
|
@@ -37904,14 +38070,14 @@ var init_runtimeParity2 = __esm({
|
|
|
37904
38070
|
"-S": "--startTime",
|
|
37905
38071
|
"-T": "--toleranceBars"
|
|
37906
38072
|
});
|
|
37907
|
-
|
|
38073
|
+
flags31 = import_args34.default.parse(process.argv);
|
|
37908
38074
|
interval3 = "15";
|
|
37909
|
-
|
|
38075
|
+
projectRoot16 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
|
|
37910
38076
|
DEFAULT_LOOKBACK_DAYS = 3;
|
|
37911
38077
|
DETAIL_LIMIT2 = 10;
|
|
37912
|
-
DEFAULT_REPLAY_ENV =
|
|
38078
|
+
DEFAULT_REPLAY_ENV = flags31.runtimeGates ? "PARITY" : "BACKTEST";
|
|
37913
38079
|
resolveParityConnectorName = async (value) => {
|
|
37914
|
-
const connectorName = await (0, import_connectors15.resolveConnectorName)(value,
|
|
38080
|
+
const connectorName = await (0, import_connectors15.resolveConnectorName)(value, projectRoot16);
|
|
37915
38081
|
if (connectorName) {
|
|
37916
38082
|
return connectorName;
|
|
37917
38083
|
}
|
|
@@ -37928,7 +38094,7 @@ var init_runtimeParity2 = __esm({
|
|
|
37928
38094
|
}) => {
|
|
37929
38095
|
const connectorFactory = await (0, import_connectors15.getConnectorCreatorByName)(
|
|
37930
38096
|
connectorName,
|
|
37931
|
-
|
|
38097
|
+
projectRoot16
|
|
37932
38098
|
);
|
|
37933
38099
|
if (!connectorFactory) {
|
|
37934
38100
|
throw new Error(`Connector "${connectorName}" is not registered`);
|
|
@@ -38020,7 +38186,7 @@ var init_runtimeParity2 = __esm({
|
|
|
38020
38186
|
strategyConfig,
|
|
38021
38187
|
env: resolveReplayStrategyEnv({
|
|
38022
38188
|
strategyConfig,
|
|
38023
|
-
forceRuntimeGates: Boolean(
|
|
38189
|
+
forceRuntimeGates: Boolean(flags31.runtimeGates)
|
|
38024
38190
|
}),
|
|
38025
38191
|
interval: interval3,
|
|
38026
38192
|
makeOrders: true,
|
|
@@ -38039,7 +38205,7 @@ var init_runtimeParity2 = __esm({
|
|
|
38039
38205
|
const symbols = [...new Set(targets.map((target) => target.symbol))];
|
|
38040
38206
|
const warmStartedAt = Date.now();
|
|
38041
38207
|
console.log(
|
|
38042
|
-
|
|
38208
|
+
import_chalk52.default.gray(
|
|
38043
38209
|
`Warm history: ${symbols.length} symbol(s) on ${connectorName}, preload ${(0, import_time13.formatUnix)(preloadStart)} -> ${(0, import_time13.formatUnix)(preloadEnd)}`
|
|
38044
38210
|
)
|
|
38045
38211
|
);
|
|
@@ -38047,7 +38213,7 @@ var init_runtimeParity2 = __esm({
|
|
|
38047
38213
|
connectorName,
|
|
38048
38214
|
marketConnector: connector,
|
|
38049
38215
|
userName: userName3,
|
|
38050
|
-
projectRoot:
|
|
38216
|
+
projectRoot: projectRoot16,
|
|
38051
38217
|
shouldUseDedicatedReferences: true,
|
|
38052
38218
|
warn: (message) => import_logger7.logger.warn(message)
|
|
38053
38219
|
});
|
|
@@ -38059,39 +38225,39 @@ var init_runtimeParity2 = __esm({
|
|
|
38059
38225
|
symbols,
|
|
38060
38226
|
preloadStart,
|
|
38061
38227
|
preloadEnd,
|
|
38062
|
-
log: (message) => console.log(
|
|
38228
|
+
log: (message) => console.log(import_chalk52.default.gray(message))
|
|
38063
38229
|
});
|
|
38064
38230
|
console.log(
|
|
38065
|
-
|
|
38231
|
+
import_chalk52.default.gray(`Warm history: done in ${formatDuration(warmStartedAt)}`)
|
|
38066
38232
|
);
|
|
38067
38233
|
};
|
|
38068
38234
|
runtimeParity = async () => {
|
|
38069
38235
|
const window = resolveTimeWindow({
|
|
38070
|
-
days:
|
|
38071
|
-
startTime:
|
|
38072
|
-
endTime:
|
|
38236
|
+
days: flags31.days ?? DEFAULT_LOOKBACK_DAYS,
|
|
38237
|
+
startTime: flags31.startTime,
|
|
38238
|
+
endTime: flags31.endTime,
|
|
38073
38239
|
defaultStartMs: Date.now() - DEFAULT_LOOKBACK_DAYS * 24 * 60 * 60 * 1e3,
|
|
38074
38240
|
defaultEndMs: Date.now()
|
|
38075
38241
|
});
|
|
38076
38242
|
const toleranceBars = Math.max(
|
|
38077
38243
|
0,
|
|
38078
|
-
Number.parseInt(String(
|
|
38244
|
+
Number.parseInt(String(flags31.toleranceBars ?? 1), 10) || 0
|
|
38079
38245
|
);
|
|
38080
38246
|
const toleranceMs = toleranceBars * 15 * 60 * 1e3;
|
|
38081
|
-
const connectorName = await resolveParityConnectorName(
|
|
38082
|
-
const requestedSymbols = parseSymbolsFromCLI2(String(
|
|
38247
|
+
const connectorName = await resolveParityConnectorName(flags31.connector);
|
|
38248
|
+
const requestedSymbols = parseSymbolsFromCLI2(String(flags31.tickers || ""));
|
|
38083
38249
|
const requestedSymbolSet = requestedSymbols.length ? new Set(requestedSymbols) : null;
|
|
38084
38250
|
let replayErrors = [];
|
|
38085
38251
|
try {
|
|
38086
38252
|
const parityConnector = await createConnector({
|
|
38087
|
-
userName:
|
|
38253
|
+
userName: flags31.user,
|
|
38088
38254
|
connectorName
|
|
38089
38255
|
});
|
|
38090
38256
|
const { runtimeTrades, runtimeSignals, runtimeSignalEvaluations } = await loadRuntimeParityEvidence(
|
|
38091
38257
|
{
|
|
38092
|
-
userName:
|
|
38258
|
+
userName: flags31.user,
|
|
38093
38259
|
window,
|
|
38094
|
-
strategy:
|
|
38260
|
+
strategy: flags31.strategy,
|
|
38095
38261
|
symbols: requestedSymbolSet
|
|
38096
38262
|
},
|
|
38097
38263
|
{
|
|
@@ -38106,29 +38272,29 @@ var init_runtimeParity2 = __esm({
|
|
|
38106
38272
|
runtimeSignalEvaluations
|
|
38107
38273
|
});
|
|
38108
38274
|
const replayTargets = await buildReplayTargets({
|
|
38109
|
-
userName:
|
|
38275
|
+
userName: flags31.user,
|
|
38110
38276
|
runtimeTrades,
|
|
38111
38277
|
connectorSymbols,
|
|
38112
|
-
strategyFilter: String(
|
|
38278
|
+
strategyFilter: String(flags31.strategy || "").trim() || void 0,
|
|
38113
38279
|
explicitSymbols: requestedSymbols,
|
|
38114
|
-
includeConnectorUniverse: Boolean(
|
|
38280
|
+
includeConnectorUniverse: Boolean(flags31.fullUniverse)
|
|
38115
38281
|
});
|
|
38116
38282
|
if (!replayTargets.length) {
|
|
38117
38283
|
console.log(
|
|
38118
|
-
|
|
38119
|
-
`No replay targets found for ${
|
|
38284
|
+
import_chalk52.default.yellow(
|
|
38285
|
+
`No replay targets found for ${flags31.user} in ${(0, import_time13.formatUnix)(window.start)} -> ${(0, import_time13.formatUnix)(window.end)}.`
|
|
38120
38286
|
)
|
|
38121
38287
|
);
|
|
38122
|
-
if (
|
|
38288
|
+
if (flags31.notify) {
|
|
38123
38289
|
await sendTelegramReport(
|
|
38124
38290
|
buildRuntimeParityNoTargetsMessage({
|
|
38125
38291
|
window,
|
|
38126
38292
|
connectorName,
|
|
38127
38293
|
replayEnv: DEFAULT_REPLAY_ENV,
|
|
38128
|
-
runtimeGatesEnabled: Boolean(
|
|
38129
|
-
userName: String(
|
|
38294
|
+
runtimeGatesEnabled: Boolean(flags31.runtimeGates),
|
|
38295
|
+
userName: String(flags31.user)
|
|
38130
38296
|
}),
|
|
38131
|
-
{ userName:
|
|
38297
|
+
{ userName: flags31.user }
|
|
38132
38298
|
);
|
|
38133
38299
|
}
|
|
38134
38300
|
return;
|
|
@@ -38143,14 +38309,14 @@ var init_runtimeParity2 = __esm({
|
|
|
38143
38309
|
replayTargets.map((target) => target.symbol)
|
|
38144
38310
|
).size;
|
|
38145
38311
|
console.log(
|
|
38146
|
-
|
|
38147
|
-
`Replay queue: ${replayTargets.length} target(s), ${replaySymbolsCount} symbol(s), mode=${
|
|
38312
|
+
import_chalk52.default.gray(
|
|
38313
|
+
`Replay queue: ${replayTargets.length} target(s), ${replaySymbolsCount} symbol(s), mode=${flags31.fullUniverse ? "full-universe" : requestedSymbols.length ? "explicit-tickers" : "runtime+results"}`
|
|
38148
38314
|
)
|
|
38149
38315
|
);
|
|
38150
38316
|
const replayConfigs = /* @__PURE__ */ new Map();
|
|
38151
38317
|
for (const target of replayTargets) {
|
|
38152
38318
|
const replayConfig = await buildReplayConfig({
|
|
38153
|
-
userName:
|
|
38319
|
+
userName: flags31.user,
|
|
38154
38320
|
strategy: target.strategy,
|
|
38155
38321
|
symbol: target.symbol,
|
|
38156
38322
|
replayInputsIndex,
|
|
@@ -38167,22 +38333,22 @@ var init_runtimeParity2 = __esm({
|
|
|
38167
38333
|
);
|
|
38168
38334
|
await prepareMarketContextForRun({
|
|
38169
38335
|
mode: "parity",
|
|
38170
|
-
userName:
|
|
38171
|
-
projectRoot:
|
|
38336
|
+
userName: flags31.user,
|
|
38337
|
+
projectRoot: projectRoot16,
|
|
38172
38338
|
symbols: replayTargets.map((target) => target.symbol),
|
|
38173
38339
|
interval: interval3,
|
|
38174
38340
|
startMs: window.start,
|
|
38175
38341
|
endMs: window.end,
|
|
38176
38342
|
preloadStartMs: preloadStart,
|
|
38177
|
-
cacheOnly: Boolean(
|
|
38343
|
+
cacheOnly: Boolean(flags31.cacheOnly),
|
|
38178
38344
|
aiEnabled: hasParityAiTargets,
|
|
38179
38345
|
mlEnabled: hasParityMlTargets,
|
|
38180
38346
|
strategyNames: replayTargets.map((target) => target.strategy),
|
|
38181
|
-
log: (message) => console.log(
|
|
38347
|
+
log: (message) => console.log(import_chalk52.default.gray(message))
|
|
38182
38348
|
});
|
|
38183
|
-
if (!
|
|
38349
|
+
if (!flags31.cacheOnly) {
|
|
38184
38350
|
await warmReplayHistory({
|
|
38185
|
-
userName:
|
|
38351
|
+
userName: flags31.user,
|
|
38186
38352
|
connectorName,
|
|
38187
38353
|
targets: replayTargets,
|
|
38188
38354
|
preloadStart,
|
|
@@ -38209,7 +38375,7 @@ var init_runtimeParity2 = __esm({
|
|
|
38209
38375
|
);
|
|
38210
38376
|
}
|
|
38211
38377
|
const result = await (0, import_backtest7.testing)({
|
|
38212
|
-
userName:
|
|
38378
|
+
userName: flags31.user,
|
|
38213
38379
|
symbol: target.symbol,
|
|
38214
38380
|
options: {
|
|
38215
38381
|
start: window.start,
|
|
@@ -38238,15 +38404,15 @@ var init_runtimeParity2 = __esm({
|
|
|
38238
38404
|
});
|
|
38239
38405
|
} finally {
|
|
38240
38406
|
(0, import_backtest7.releaseTestingSymbolCache)({
|
|
38241
|
-
cwd:
|
|
38242
|
-
userName:
|
|
38407
|
+
cwd: projectRoot16,
|
|
38408
|
+
userName: flags31.user,
|
|
38243
38409
|
connectorName,
|
|
38244
38410
|
symbol: target.symbol
|
|
38245
38411
|
});
|
|
38246
38412
|
}
|
|
38247
38413
|
if (progressPosition === 1 || progressPosition === replayTargets.length || progressPosition % 25 === 0) {
|
|
38248
38414
|
console.log(
|
|
38249
|
-
|
|
38415
|
+
import_chalk52.default.gray(
|
|
38250
38416
|
`Replay progress: ${progressPosition}/${replayTargets.length}, ok=${successfulTargetKeys.size}, errors=${replayErrors.length}, current=${target.strategy} ${target.symbol}, elapsed=${formatDuration(replayStartedAt)}`
|
|
38251
38417
|
)
|
|
38252
38418
|
);
|
|
@@ -38277,8 +38443,8 @@ var init_runtimeParity2 = __esm({
|
|
|
38277
38443
|
window,
|
|
38278
38444
|
connectorName,
|
|
38279
38445
|
replayEnv: replayEnvSummary,
|
|
38280
|
-
runtimeGatesEnabled: Boolean(
|
|
38281
|
-
runtimeGatesRequested: Boolean(
|
|
38446
|
+
runtimeGatesEnabled: Boolean(flags31.runtimeGates) || replayEnvSummary.includes("PARITY"),
|
|
38447
|
+
runtimeGatesRequested: Boolean(flags31.runtimeGates),
|
|
38282
38448
|
toleranceBars,
|
|
38283
38449
|
toleranceMs,
|
|
38284
38450
|
replayTargetsCount: replayTargets.length,
|
|
@@ -38301,12 +38467,12 @@ var init_runtimeParity2 = __esm({
|
|
|
38301
38467
|
detailLimit: DETAIL_LIMIT2
|
|
38302
38468
|
})
|
|
38303
38469
|
);
|
|
38304
|
-
if (
|
|
38470
|
+
if (flags31.details) {
|
|
38305
38471
|
printRuntimeDuplicateDetails(runtimeDedupe.duplicateGroups);
|
|
38306
38472
|
printClassifiedRuntimeOnlyDetails(classifiedRuntimeOnly);
|
|
38307
38473
|
printClassifiedBacktestOnlyDetails(classifiedBacktestOnly);
|
|
38308
38474
|
}
|
|
38309
|
-
if (
|
|
38475
|
+
if (flags31.notify) {
|
|
38310
38476
|
const mismatchAttachment = buildRuntimeParityMismatchAttachment({
|
|
38311
38477
|
window,
|
|
38312
38478
|
connectorName,
|
|
@@ -38335,7 +38501,7 @@ var init_runtimeParity2 = __esm({
|
|
|
38335
38501
|
window,
|
|
38336
38502
|
connectorName,
|
|
38337
38503
|
replayEnv: replayEnvSummary,
|
|
38338
|
-
runtimeGatesEnabled: Boolean(
|
|
38504
|
+
runtimeGatesEnabled: Boolean(flags31.runtimeGates) || replayEnvSummary.includes("PARITY"),
|
|
38339
38505
|
toleranceBars,
|
|
38340
38506
|
toleranceMs,
|
|
38341
38507
|
replayTargetsCount: replayTargets.length,
|
|
@@ -38357,16 +38523,16 @@ var init_runtimeParity2 = __esm({
|
|
|
38357
38523
|
runtimeGateWarningCounts
|
|
38358
38524
|
}),
|
|
38359
38525
|
{
|
|
38360
|
-
userName:
|
|
38526
|
+
userName: flags31.user,
|
|
38361
38527
|
attachments: mismatchAttachment ? [mismatchAttachment] : void 0
|
|
38362
38528
|
}
|
|
38363
38529
|
);
|
|
38364
38530
|
}
|
|
38365
38531
|
} finally {
|
|
38366
|
-
(0, import_backtest7.resetTestingKlineCache)(
|
|
38532
|
+
(0, import_backtest7.resetTestingKlineCache)(projectRoot16);
|
|
38367
38533
|
}
|
|
38368
38534
|
};
|
|
38369
|
-
|
|
38535
|
+
main44 = runtimeParity;
|
|
38370
38536
|
}
|
|
38371
38537
|
});
|
|
38372
38538
|
|
|
@@ -38380,11 +38546,11 @@ var init_runtimeStrategies = __esm({
|
|
|
38380
38546
|
});
|
|
38381
38547
|
|
|
38382
38548
|
// src/lib/signals/skipStats.ts
|
|
38383
|
-
var
|
|
38549
|
+
var import_chalk53, import_logger8, createStrategySkipStats, recordStrategyReason, logStrategySkipStats;
|
|
38384
38550
|
var init_skipStats = __esm({
|
|
38385
38551
|
"src/lib/signals/skipStats.ts"() {
|
|
38386
38552
|
"use strict";
|
|
38387
|
-
|
|
38553
|
+
import_chalk53 = __toESM(require("chalk"));
|
|
38388
38554
|
import_logger8 = require("@tradejs/infra/logger");
|
|
38389
38555
|
init_runtimeSignalsStorage();
|
|
38390
38556
|
createStrategySkipStats = (runtimeStrategies) => new Map(
|
|
@@ -38410,7 +38576,7 @@ var init_skipStats = __esm({
|
|
|
38410
38576
|
);
|
|
38411
38577
|
};
|
|
38412
38578
|
logStrategySkipStats = (runtimeStrategies, strategyStats) => {
|
|
38413
|
-
import_logger8.logger.info(
|
|
38579
|
+
import_logger8.logger.info(import_chalk53.default.yellow("skip stats:"));
|
|
38414
38580
|
for (const { strategyName } of runtimeStrategies) {
|
|
38415
38581
|
const stats = strategyStats.get(strategyName);
|
|
38416
38582
|
if (!stats) {
|
|
@@ -39425,12 +39591,12 @@ var init_configuredScopes = __esm({
|
|
|
39425
39591
|
});
|
|
39426
39592
|
|
|
39427
39593
|
// src/lib/signals/runner.ts
|
|
39428
|
-
var import_progress12,
|
|
39594
|
+
var import_progress12, import_chalk54, import_connectors17, import_cli13, import_async5, import_strategies14, import_constants20, import_time14, import_logger11, import_runtimeDeploymentEvents, import_runtimeHeartbeats, import_runtimeStrategies8, SLOW_SIGNALS_WARNING_MS, formatDuration3, resolvePositiveInteger2, resolveNonNegativeInteger, createSignalsRunner;
|
|
39429
39595
|
var init_runner = __esm({
|
|
39430
39596
|
"src/lib/signals/runner.ts"() {
|
|
39431
39597
|
"use strict";
|
|
39432
39598
|
import_progress12 = __toESM(require("progress"));
|
|
39433
|
-
|
|
39599
|
+
import_chalk54 = __toESM(require("chalk"));
|
|
39434
39600
|
import_connectors17 = require("@tradejs/node/connectors");
|
|
39435
39601
|
import_cli13 = require("@tradejs/node/cli");
|
|
39436
39602
|
import_async5 = require("@tradejs/core/async");
|
|
@@ -39476,10 +39642,10 @@ var init_runner = __esm({
|
|
|
39476
39642
|
};
|
|
39477
39643
|
createSignalsRunner = (config2) => {
|
|
39478
39644
|
const interval4 = config2.interval;
|
|
39479
|
-
const
|
|
39645
|
+
const projectRoot18 = config2.projectRoot?.trim() || String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
|
|
39480
39646
|
const compositionSnapshotRecorder = process.env.TRADEJS_PROJECT_SHA && process.env.TRADEJS_PROJECT_IMAGE_DIGEST && config2.deploymentId ? createRuntimeEvidenceCompositionSnapshotRecorder({
|
|
39481
39647
|
persist: (compositionId) => captureRuntimeEvidenceCompositionSnapshot({
|
|
39482
|
-
projectRoot:
|
|
39648
|
+
projectRoot: projectRoot18,
|
|
39483
39649
|
userName: config2.userName,
|
|
39484
39650
|
deploymentId: config2.deploymentId,
|
|
39485
39651
|
expectedCompositionId: compositionId
|
|
@@ -39512,7 +39678,7 @@ var init_runner = __esm({
|
|
|
39512
39678
|
const timeOperation3 = (label, operation) => timeOperation(
|
|
39513
39679
|
label,
|
|
39514
39680
|
operation,
|
|
39515
|
-
(message) => import_logger11.logger.info(
|
|
39681
|
+
(message) => import_logger11.logger.info(import_chalk54.default.gray(message))
|
|
39516
39682
|
);
|
|
39517
39683
|
const formatSlowSignalsWarning = (params) => [
|
|
39518
39684
|
"<b>Slow yarn signals run</b>",
|
|
@@ -39522,7 +39688,7 @@ var init_runner = __esm({
|
|
|
39522
39688
|
`Found signals: <b>${params.found}</b>`
|
|
39523
39689
|
].join("\n");
|
|
39524
39690
|
const resolveSignalsConnectorName = async (value) => {
|
|
39525
|
-
const connectorName = await (0, import_connectors17.resolveConnectorName)(value,
|
|
39691
|
+
const connectorName = await (0, import_connectors17.resolveConnectorName)(value, projectRoot18);
|
|
39526
39692
|
if (!connectorName) {
|
|
39527
39693
|
throw new Error(
|
|
39528
39694
|
`Unknown runtime connector: ${String(value || "").trim() || String(value)}`
|
|
@@ -39533,7 +39699,7 @@ var init_runner = __esm({
|
|
|
39533
39699
|
const createSignalsSession2 = async (lifecycle, scope = {}) => {
|
|
39534
39700
|
const deployment = config2.deploymentId ? await (0, import_runtimeStrategies8.getRuntimeDeployment)({
|
|
39535
39701
|
userName: config2.userName,
|
|
39536
|
-
projectRoot:
|
|
39702
|
+
projectRoot: projectRoot18,
|
|
39537
39703
|
deploymentId: config2.deploymentId
|
|
39538
39704
|
}) : null;
|
|
39539
39705
|
if (config2.deploymentId && !deployment) {
|
|
@@ -39552,7 +39718,7 @@ var init_runner = __esm({
|
|
|
39552
39718
|
const requestedAccountId = deployment?.accountId ?? scope.accountId ?? config2.accountId;
|
|
39553
39719
|
const connectorFactory = await (0, import_connectors17.getConnectorCreatorByName)(
|
|
39554
39720
|
connectorName,
|
|
39555
|
-
|
|
39721
|
+
projectRoot18
|
|
39556
39722
|
);
|
|
39557
39723
|
if (!connectorFactory) {
|
|
39558
39724
|
throw new Error(`Connector "${connectorName}" is not registered`);
|
|
@@ -39567,7 +39733,7 @@ var init_runner = __esm({
|
|
|
39567
39733
|
connectorName,
|
|
39568
39734
|
marketConnector,
|
|
39569
39735
|
userName: config2.userName,
|
|
39570
|
-
projectRoot:
|
|
39736
|
+
projectRoot: projectRoot18,
|
|
39571
39737
|
shouldUseDedicatedReferences: universe === "crypto" && connectorName.toLowerCase() === import_connectors17.DEFAULT_CONNECTOR_NAME.toLowerCase(),
|
|
39572
39738
|
warn: (message) => import_logger11.logger.warn(message)
|
|
39573
39739
|
});
|
|
@@ -39629,7 +39795,7 @@ var init_runner = __esm({
|
|
|
39629
39795
|
const selectedTickers = selection?.tickers ? [.../* @__PURE__ */ new Set([...selection.tickers, ...selectedActiveSymbols])] : void 0;
|
|
39630
39796
|
if (selectedActiveSymbols.length) {
|
|
39631
39797
|
import_logger11.logger.info(
|
|
39632
|
-
|
|
39798
|
+
import_chalk54.default.gray(
|
|
39633
39799
|
`runtime scope retained active symbols: ${selectedActiveSymbols.join(", ")}`
|
|
39634
39800
|
)
|
|
39635
39801
|
);
|
|
@@ -39660,10 +39826,10 @@ var init_runner = __esm({
|
|
|
39660
39826
|
instruments.map((instrument) => [instrument.symbol, instrument])
|
|
39661
39827
|
);
|
|
39662
39828
|
if (config2.showTickersList) {
|
|
39663
|
-
console.log(
|
|
39829
|
+
console.log(import_chalk54.default.gray(JSON.stringify(tickers.sort(), null, 2)));
|
|
39664
39830
|
return;
|
|
39665
39831
|
}
|
|
39666
|
-
const projectConfig = await (0, import_cli13.loadTradejsConfig)(
|
|
39832
|
+
const projectConfig = await (0, import_cli13.loadTradejsConfig)(projectRoot18);
|
|
39667
39833
|
projectHooks = projectConfig.hooks;
|
|
39668
39834
|
const currentTimestamp = (0, import_time14.getTimestamp)();
|
|
39669
39835
|
const preloadStart = (0, import_time14.getTimestamp)(import_constants20.SIGNALS_CLI_PRELOAD_DAYS);
|
|
@@ -39681,7 +39847,7 @@ var init_runner = __esm({
|
|
|
39681
39847
|
);
|
|
39682
39848
|
await session.klineFeed.flush();
|
|
39683
39849
|
import_logger11.logger.info(
|
|
39684
|
-
|
|
39850
|
+
import_chalk54.default.gray(
|
|
39685
39851
|
`websocket candles: ready=${expectedSymbols.length - missingSymbols.length}/${expectedSymbols.length} missing=${missingSymbols.length}`
|
|
39686
39852
|
)
|
|
39687
39853
|
);
|
|
@@ -39692,7 +39858,7 @@ var init_runner = __esm({
|
|
|
39692
39858
|
symbols: missingSymbols,
|
|
39693
39859
|
preloadDays: import_constants20.SIGNALS_CLI_PRELOAD_DAYS,
|
|
39694
39860
|
universe,
|
|
39695
|
-
log: (message) => import_logger11.logger.info(
|
|
39861
|
+
log: (message) => import_logger11.logger.info(import_chalk54.default.gray(message))
|
|
39696
39862
|
});
|
|
39697
39863
|
await updateBtcReferenceHistory({
|
|
39698
39864
|
marketConnector,
|
|
@@ -39700,7 +39866,7 @@ var init_runner = __esm({
|
|
|
39700
39866
|
interval: interval5,
|
|
39701
39867
|
preloadDays: import_constants20.SIGNALS_CLI_PRELOAD_DAYS,
|
|
39702
39868
|
universe,
|
|
39703
|
-
log: (message) => import_logger11.logger.info(
|
|
39869
|
+
log: (message) => import_logger11.logger.info(import_chalk54.default.gray(message))
|
|
39704
39870
|
});
|
|
39705
39871
|
} else if (!config2.cacheOnly) {
|
|
39706
39872
|
await updateMarketHistoryWithBtcReferences({
|
|
@@ -39711,13 +39877,13 @@ var init_runner = __esm({
|
|
|
39711
39877
|
symbols: tickers,
|
|
39712
39878
|
preloadDays: import_constants20.SIGNALS_CLI_PRELOAD_DAYS,
|
|
39713
39879
|
universe,
|
|
39714
|
-
log: (message) => import_logger11.logger.info(
|
|
39880
|
+
log: (message) => import_logger11.logger.info(import_chalk54.default.gray(message))
|
|
39715
39881
|
});
|
|
39716
39882
|
}
|
|
39717
39883
|
await prepareMarketContextForRun({
|
|
39718
39884
|
mode: "signals",
|
|
39719
39885
|
userName: config2.userName,
|
|
39720
|
-
projectRoot:
|
|
39886
|
+
projectRoot: projectRoot18,
|
|
39721
39887
|
symbols: tickers,
|
|
39722
39888
|
universe,
|
|
39723
39889
|
interval: interval5,
|
|
@@ -39725,7 +39891,7 @@ var init_runner = __esm({
|
|
|
39725
39891
|
endMs: currentTimestamp,
|
|
39726
39892
|
preloadStartMs: preloadStart,
|
|
39727
39893
|
cacheOnly: config2.cacheOnly,
|
|
39728
|
-
log: (message) => import_logger11.logger.info(
|
|
39894
|
+
log: (message) => import_logger11.logger.info(import_chalk54.default.gray(message))
|
|
39729
39895
|
});
|
|
39730
39896
|
if (config2.updateOnly) {
|
|
39731
39897
|
return;
|
|
@@ -39783,7 +39949,7 @@ var init_runner = __esm({
|
|
|
39783
39949
|
);
|
|
39784
39950
|
const configuredRuntimeStrategies = await (0, import_runtimeStrategies7.loadResolvedRuntimeStrategies)({
|
|
39785
39951
|
userName: config2.userName,
|
|
39786
|
-
projectRoot:
|
|
39952
|
+
projectRoot: projectRoot18,
|
|
39787
39953
|
deploymentId: deployment?.id ?? "",
|
|
39788
39954
|
universe,
|
|
39789
39955
|
accountId,
|
|
@@ -39829,7 +39995,7 @@ var init_runner = __esm({
|
|
|
39829
39995
|
)
|
|
39830
39996
|
);
|
|
39831
39997
|
import_logger11.logger.info(
|
|
39832
|
-
|
|
39998
|
+
import_chalk54.default.yellow(
|
|
39833
39999
|
`loaded strategies (user=${config2.userName}): ${runtimeStrategies.map(formatConfiguredStrategyIdentity).join(", ")}`
|
|
39834
40000
|
)
|
|
39835
40001
|
);
|
|
@@ -39865,9 +40031,9 @@ var init_runner = __esm({
|
|
|
39865
40031
|
width: 30
|
|
39866
40032
|
}
|
|
39867
40033
|
);
|
|
39868
|
-
import_logger11.logger.info(
|
|
40034
|
+
import_logger11.logger.info(import_chalk54.default.yellow(`tickers: ${tickers.length}`));
|
|
39869
40035
|
const signalsParallel = resolvePositiveInteger2(config2.parallel, 4);
|
|
39870
|
-
import_logger11.logger.info(
|
|
40036
|
+
import_logger11.logger.info(import_chalk54.default.yellow(`signal workers: ${signalsParallel}`));
|
|
39871
40037
|
const evaluateTicker = createSignalsTickerEvaluator({
|
|
39872
40038
|
userName: config2.userName,
|
|
39873
40039
|
makeOrders: config2.makeOrders,
|
|
@@ -39907,8 +40073,8 @@ var init_runner = __esm({
|
|
|
39907
40073
|
signals3.push(...strategySignals);
|
|
39908
40074
|
}
|
|
39909
40075
|
bar.tick(1, {
|
|
39910
|
-
found:
|
|
39911
|
-
symbol:
|
|
40076
|
+
found: import_chalk54.default.cyan(signals3.length),
|
|
40077
|
+
symbol: import_chalk54.default.gray(symbol)
|
|
39912
40078
|
});
|
|
39913
40079
|
});
|
|
39914
40080
|
});
|
|
@@ -40012,7 +40178,7 @@ var init_runner = __esm({
|
|
|
40012
40178
|
}
|
|
40013
40179
|
}
|
|
40014
40180
|
import_logger11.logger.info(
|
|
40015
|
-
|
|
40181
|
+
import_chalk54.default.yellow(
|
|
40016
40182
|
`signals ${status} in ${formatDuration3(durationMs)} (found=${signals3.length})`
|
|
40017
40183
|
)
|
|
40018
40184
|
);
|
|
@@ -40024,7 +40190,7 @@ var init_runner = __esm({
|
|
|
40024
40190
|
const loadConfiguredSignalsScopes = async (deployment) => {
|
|
40025
40191
|
const configuredStrategies = await (0, import_runtimeStrategies7.loadResolvedRuntimeStrategies)({
|
|
40026
40192
|
userName: config2.userName,
|
|
40027
|
-
projectRoot:
|
|
40193
|
+
projectRoot: projectRoot18,
|
|
40028
40194
|
deploymentId: deployment.id
|
|
40029
40195
|
});
|
|
40030
40196
|
const connectorName = await resolveSignalsConnectorName(
|
|
@@ -40050,7 +40216,7 @@ var init_runner = __esm({
|
|
|
40050
40216
|
}
|
|
40051
40217
|
const configuredDeployment = await (0, import_runtimeStrategies8.getRuntimeDeployment)({
|
|
40052
40218
|
userName: config2.userName,
|
|
40053
|
-
projectRoot:
|
|
40219
|
+
projectRoot: projectRoot18,
|
|
40054
40220
|
deploymentId: config2.deploymentId
|
|
40055
40221
|
});
|
|
40056
40222
|
if (!configuredDeployment) {
|
|
@@ -40084,7 +40250,7 @@ var init_runner = __esm({
|
|
|
40084
40250
|
const deploymentId = config2.deploymentId;
|
|
40085
40251
|
const initialDeployment = await (0, import_runtimeStrategies8.getRuntimeDeployment)({
|
|
40086
40252
|
userName: config2.userName,
|
|
40087
|
-
projectRoot:
|
|
40253
|
+
projectRoot: projectRoot18,
|
|
40088
40254
|
deploymentId
|
|
40089
40255
|
});
|
|
40090
40256
|
if (!initialDeployment) {
|
|
@@ -40109,7 +40275,7 @@ var init_runner = __esm({
|
|
|
40109
40275
|
runCycle: async () => {
|
|
40110
40276
|
const currentDeployment = await (0, import_runtimeStrategies8.getRuntimeDeployment)({
|
|
40111
40277
|
userName: config2.userName,
|
|
40112
|
-
projectRoot:
|
|
40278
|
+
projectRoot: projectRoot18,
|
|
40113
40279
|
deploymentId
|
|
40114
40280
|
});
|
|
40115
40281
|
if (!currentDeployment) {
|
|
@@ -40232,113 +40398,113 @@ var init_runner = __esm({
|
|
|
40232
40398
|
var signals_exports = {};
|
|
40233
40399
|
__export(signals_exports, {
|
|
40234
40400
|
createSignalsSession: () => createSignalsSession,
|
|
40235
|
-
main: () =>
|
|
40401
|
+
main: () => main45,
|
|
40236
40402
|
signals: () => signals,
|
|
40237
40403
|
signalsConfiguredScopesOnce: () => signalsConfiguredScopesOnce,
|
|
40238
40404
|
signalsDaemon: () => signalsDaemon
|
|
40239
40405
|
});
|
|
40240
|
-
var import_config12,
|
|
40406
|
+
var import_config12, import_args35, flags32, config, runner, createSignalsSession, signals, signalsConfiguredScopesOnce, signalsDaemon, main45;
|
|
40241
40407
|
var init_signals = __esm({
|
|
40242
40408
|
"src/scripts/signals.ts"() {
|
|
40243
40409
|
"use strict";
|
|
40244
40410
|
import_config12 = require("dotenv/config");
|
|
40245
|
-
|
|
40411
|
+
import_args35 = __toESM(require("args"));
|
|
40246
40412
|
init_runner();
|
|
40247
|
-
|
|
40248
|
-
|
|
40249
|
-
|
|
40250
|
-
|
|
40251
|
-
|
|
40252
|
-
|
|
40253
|
-
|
|
40254
|
-
|
|
40255
|
-
|
|
40256
|
-
|
|
40257
|
-
|
|
40413
|
+
import_args35.default.option(["t", "tickers"], "Selected tickers");
|
|
40414
|
+
import_args35.default.option(["e", "exclude"], "Exclude tickers from tests");
|
|
40415
|
+
import_args35.default.option(["l", "tickersLimit"], "Tickers limit");
|
|
40416
|
+
import_args35.default.option(["f", "timeframe"], "Timeframe", 15);
|
|
40417
|
+
import_args35.default.option(["m", "makeOrders"], "Make orders");
|
|
40418
|
+
import_args35.default.option(["N", "notify"], "Send message in Telegram", false);
|
|
40419
|
+
import_args35.default.option(["S", "skipScreenshots"], "Skip screenshot generation", false);
|
|
40420
|
+
import_args35.default.option(["u", "updateOnly"], "Only update tickers history", false);
|
|
40421
|
+
import_args35.default.option(["C", "cacheOnly"], "Do not update tickers history", false);
|
|
40422
|
+
import_args35.default.option(["L", "showTickersList"], "Just show only ticker list", false);
|
|
40423
|
+
import_args35.default.option(
|
|
40258
40424
|
["p", "parallel"],
|
|
40259
40425
|
"Signal evaluation worker count",
|
|
40260
40426
|
Number(process.env.SIGNALS_PARALLEL || 4)
|
|
40261
40427
|
);
|
|
40262
|
-
|
|
40428
|
+
import_args35.default.option(
|
|
40263
40429
|
["R", "showSkipStats"],
|
|
40264
40430
|
"Show aggregated skip stats by strategy",
|
|
40265
40431
|
false
|
|
40266
40432
|
);
|
|
40267
|
-
|
|
40268
|
-
|
|
40269
|
-
|
|
40270
|
-
|
|
40433
|
+
import_args35.default.option(["c", "chunk"], "Split by chunks, ex. 1/3");
|
|
40434
|
+
import_args35.default.option(["U", "user"], "Use user confg", "root");
|
|
40435
|
+
import_args35.default.option(["w", "watch"], "Keep signals running on candle boundaries", false);
|
|
40436
|
+
import_args35.default.option(
|
|
40271
40437
|
["d", "settleDelayMs"],
|
|
40272
40438
|
"Delay after candle close before a daemon cycle",
|
|
40273
40439
|
Number(process.env.SIGNALS_DAEMON_SETTLE_DELAY_MS || 5e3)
|
|
40274
40440
|
);
|
|
40275
|
-
|
|
40441
|
+
import_args35.default.option(
|
|
40276
40442
|
["o", "connector"],
|
|
40277
40443
|
"Connector provider or name for signals (e.g. bybit, binance, coinbase, custom)",
|
|
40278
40444
|
"bybit"
|
|
40279
40445
|
);
|
|
40280
|
-
|
|
40281
|
-
|
|
40282
|
-
|
|
40283
|
-
|
|
40446
|
+
import_args35.default.option(["V", "universe"], "Market universe (crypto or tradfi)", "crypto");
|
|
40447
|
+
import_args35.default.option(["A", "account"], "Trading account id");
|
|
40448
|
+
import_args35.default.option(["D", "deployment"], "Runtime deployment id");
|
|
40449
|
+
flags32 = import_args35.default.parse(process.argv);
|
|
40284
40450
|
config = {
|
|
40285
40451
|
projectRoot: String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd(),
|
|
40286
|
-
userName: String(
|
|
40287
|
-
interval: String(
|
|
40288
|
-
connectorName: String(
|
|
40289
|
-
universe:
|
|
40290
|
-
accountId:
|
|
40291
|
-
deploymentId:
|
|
40292
|
-
tickers:
|
|
40293
|
-
exclude:
|
|
40294
|
-
tickersLimit:
|
|
40295
|
-
chunk:
|
|
40296
|
-
makeOrders: Boolean(
|
|
40297
|
-
notify: Boolean(
|
|
40298
|
-
skipScreenshots: Boolean(
|
|
40299
|
-
updateOnly: Boolean(
|
|
40300
|
-
cacheOnly: Boolean(
|
|
40301
|
-
showTickersList: Boolean(
|
|
40302
|
-
showSkipStats: Boolean(
|
|
40303
|
-
parallel:
|
|
40304
|
-
watch: Boolean(
|
|
40305
|
-
settleDelayMs:
|
|
40452
|
+
userName: String(flags32.user || "root"),
|
|
40453
|
+
interval: String(flags32.timeframe ?? 15),
|
|
40454
|
+
connectorName: String(flags32.connector || "bybit"),
|
|
40455
|
+
universe: flags32.universe,
|
|
40456
|
+
accountId: flags32.account ? String(flags32.account) : void 0,
|
|
40457
|
+
deploymentId: flags32.deployment ? String(flags32.deployment) : void 0,
|
|
40458
|
+
tickers: flags32.tickers,
|
|
40459
|
+
exclude: flags32.exclude,
|
|
40460
|
+
tickersLimit: flags32.tickersLimit,
|
|
40461
|
+
chunk: flags32.chunk,
|
|
40462
|
+
makeOrders: Boolean(flags32.makeOrders),
|
|
40463
|
+
notify: Boolean(flags32.notify),
|
|
40464
|
+
skipScreenshots: Boolean(flags32.skipScreenshots),
|
|
40465
|
+
updateOnly: Boolean(flags32.updateOnly),
|
|
40466
|
+
cacheOnly: Boolean(flags32.cacheOnly),
|
|
40467
|
+
showTickersList: Boolean(flags32.showTickersList),
|
|
40468
|
+
showSkipStats: Boolean(flags32.showSkipStats),
|
|
40469
|
+
parallel: flags32.parallel,
|
|
40470
|
+
watch: Boolean(flags32.watch),
|
|
40471
|
+
settleDelayMs: flags32.settleDelayMs
|
|
40306
40472
|
};
|
|
40307
40473
|
runner = createSignalsRunner(config);
|
|
40308
40474
|
createSignalsSession = runner.createSession;
|
|
40309
40475
|
signals = runner.runCycle;
|
|
40310
40476
|
signalsConfiguredScopesOnce = runner.runConfiguredScopesOnce;
|
|
40311
40477
|
signalsDaemon = runner.runDaemon;
|
|
40312
|
-
|
|
40478
|
+
main45 = () => config.watch ? signalsDaemon() : signalsConfiguredScopesOnce();
|
|
40313
40479
|
}
|
|
40314
40480
|
});
|
|
40315
40481
|
|
|
40316
40482
|
// src/scripts/signalsDaemon.ts
|
|
40317
40483
|
var signalsDaemon_exports = {};
|
|
40318
40484
|
__export(signalsDaemon_exports, {
|
|
40319
|
-
main: () =>
|
|
40485
|
+
main: () => main46
|
|
40320
40486
|
});
|
|
40321
|
-
var
|
|
40487
|
+
var main46;
|
|
40322
40488
|
var init_signalsDaemon = __esm({
|
|
40323
40489
|
"src/scripts/signalsDaemon.ts"() {
|
|
40324
40490
|
"use strict";
|
|
40325
40491
|
init_signals();
|
|
40326
|
-
|
|
40492
|
+
main46 = signalsDaemon;
|
|
40327
40493
|
}
|
|
40328
40494
|
});
|
|
40329
40495
|
|
|
40330
40496
|
// src/scripts/signalsSummary.ts
|
|
40331
40497
|
var signalsSummary_exports = {};
|
|
40332
40498
|
__export(signalsSummary_exports, {
|
|
40333
|
-
main: () =>
|
|
40499
|
+
main: () => main47,
|
|
40334
40500
|
signalsSummary: () => signalsSummary
|
|
40335
40501
|
});
|
|
40336
|
-
var import_config13,
|
|
40502
|
+
var import_config13, import_args36, import_logger12, import_connectors18, import_runtimeStrategies10, flags33, projectRoot17, SUMMARY_TIMEZONE2, SUMMARY_TIMEZONE_LABEL2, escapeHtml8, formatMskDateTime4, formatSigned3, formatPnlMoneyText, formatWinRateText, resolveSummaryTitle, normalizeStatus, shouldAttachDebugReport, getSummaryDateParts, formatSummaryIsoDayKey, unescapeHtml, stripTelegramHtml, buildSignalsSummaryAttachment, appendReportAttachmentSummary, resolveSummaryConnectorName, groupRuntimeTradesByConnectorScope, syncRuntimeTradeScopes, createRuntimeSignalStats, mergeRuntimeSignalStats, buildSummaryPrelude, resolveTradeStatusEmoji, isTimestampInWindow, isRuntimeTradeClosedInWindow, buildSummaryMessages, signalsSummary, main47;
|
|
40337
40503
|
var init_signalsSummary = __esm({
|
|
40338
40504
|
"src/scripts/signalsSummary.ts"() {
|
|
40339
40505
|
"use strict";
|
|
40340
40506
|
import_config13 = require("dotenv/config");
|
|
40341
|
-
|
|
40507
|
+
import_args36 = __toESM(require("args"));
|
|
40342
40508
|
import_logger12 = require("@tradejs/infra/logger");
|
|
40343
40509
|
import_connectors18 = require("@tradejs/node/connectors");
|
|
40344
40510
|
init_runtimeRedis();
|
|
@@ -40348,25 +40514,25 @@ var init_signalsSummary = __esm({
|
|
|
40348
40514
|
init_runtimeSignalsStorage();
|
|
40349
40515
|
init_runtimeDebugEvidence();
|
|
40350
40516
|
import_runtimeStrategies10 = require("@tradejs/node/runtimeStrategies");
|
|
40351
|
-
|
|
40352
|
-
|
|
40517
|
+
import_args36.default.option(["u", "user"], "Use user config", "root");
|
|
40518
|
+
import_args36.default.option(
|
|
40353
40519
|
"connector",
|
|
40354
40520
|
"Connector provider or name for summary (e.g. bybit, binance, coinbase, custom)",
|
|
40355
40521
|
"bybit"
|
|
40356
40522
|
);
|
|
40357
|
-
|
|
40358
|
-
|
|
40359
|
-
|
|
40523
|
+
import_args36.default.option(["H", "hours"], "Summary window in hours", 24);
|
|
40524
|
+
import_args36.default.option(["P", "printOnly"], "Print summary instead of Telegram", false);
|
|
40525
|
+
import_args36.default.option(
|
|
40360
40526
|
"debugAttachment",
|
|
40361
40527
|
"Attach runtime Redis debug JSON for replay diagnostics",
|
|
40362
40528
|
true
|
|
40363
40529
|
);
|
|
40364
|
-
|
|
40365
|
-
|
|
40530
|
+
flags33 = import_args36.default.parse(process.argv);
|
|
40531
|
+
projectRoot17 = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
|
|
40366
40532
|
SUMMARY_TIMEZONE2 = "Europe/Moscow";
|
|
40367
40533
|
SUMMARY_TIMEZONE_LABEL2 = "MSK";
|
|
40368
|
-
|
|
40369
|
-
|
|
40534
|
+
escapeHtml8 = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
40535
|
+
formatMskDateTime4 = (timestamp) => new Intl.DateTimeFormat("ru-RU", {
|
|
40370
40536
|
timeZone: SUMMARY_TIMEZONE2,
|
|
40371
40537
|
year: "numeric",
|
|
40372
40538
|
month: "2-digit",
|
|
@@ -40435,13 +40601,13 @@ var init_signalsSummary = __esm({
|
|
|
40435
40601
|
message,
|
|
40436
40602
|
"",
|
|
40437
40603
|
"\u{1F4CE} <b>Signal report file</b>",
|
|
40438
|
-
`File: <code>${
|
|
40604
|
+
`File: <code>${escapeHtml8(signalsFilename)}</code>`
|
|
40439
40605
|
];
|
|
40440
40606
|
if (filename) {
|
|
40441
40607
|
lines.push(
|
|
40442
40608
|
"",
|
|
40443
40609
|
"\u{1F4CE} <b>Replay debug file</b>",
|
|
40444
|
-
`File: <code>${
|
|
40610
|
+
`File: <code>${escapeHtml8(filename)}</code>`,
|
|
40445
40611
|
`Inside: trades=<b>${tradesCount ?? 0}</b>, signals=<b>${signalsCount ?? 0}</b>, evaluations=<b>${evaluationsCount ?? 0}</b>`,
|
|
40446
40612
|
"Redis refs: <code>trade</code>, <code>tradeBucket</code>, <code>activeTrade</code>, <code>signal</code>, <code>evaluation</code>"
|
|
40447
40613
|
);
|
|
@@ -40449,7 +40615,7 @@ var init_signalsSummary = __esm({
|
|
|
40449
40615
|
return lines.join("\n");
|
|
40450
40616
|
};
|
|
40451
40617
|
resolveSummaryConnectorName = async (value) => {
|
|
40452
|
-
const connectorName = await (0, import_connectors18.resolveConnectorName)(value,
|
|
40618
|
+
const connectorName = await (0, import_connectors18.resolveConnectorName)(value, projectRoot17);
|
|
40453
40619
|
if (connectorName) {
|
|
40454
40620
|
return connectorName;
|
|
40455
40621
|
}
|
|
@@ -40514,7 +40680,7 @@ var init_signalsSummary = __esm({
|
|
|
40514
40680
|
);
|
|
40515
40681
|
const connectorFactory = await (0, import_connectors18.getConnectorCreatorByName)(
|
|
40516
40682
|
connectorName,
|
|
40517
|
-
|
|
40683
|
+
projectRoot17
|
|
40518
40684
|
);
|
|
40519
40685
|
if (!connectorFactory) {
|
|
40520
40686
|
throw new Error(`Connector "${connectorName}" is not registered`);
|
|
@@ -40591,16 +40757,16 @@ var init_signalsSummary = __esm({
|
|
|
40591
40757
|
}) => {
|
|
40592
40758
|
const windowPnlLabel = hours === 24 ? "24h Realized PnL" : `${hours}h Realized PnL`;
|
|
40593
40759
|
return [
|
|
40594
|
-
`\u{1F4CB} <b>${
|
|
40760
|
+
`\u{1F4CB} <b>${escapeHtml8(resolveSummaryTitle(hours))}</b>`,
|
|
40595
40761
|
"",
|
|
40596
40762
|
"\u{1F552} <b>Window</b>",
|
|
40597
|
-
`<b>${
|
|
40763
|
+
`<b>${escapeHtml8(formatMskDateTime4(startTime))} - ${escapeHtml8(formatMskDateTime4(endTime))} ${SUMMARY_TIMEZONE_LABEL2}</b>`,
|
|
40598
40764
|
"",
|
|
40599
40765
|
`\u23F1 Range: <b>${hours}h</b>`,
|
|
40600
|
-
`\u{1F4B0} <b>${windowPnlLabel}:</b> <b>${
|
|
40601
|
-
`\u{1F3C6} <b>WinRate:</b> <b>${
|
|
40766
|
+
`\u{1F4B0} <b>${windowPnlLabel}:</b> <b>${escapeHtml8(realizedWindowPnlText)}</b>`,
|
|
40767
|
+
`\u{1F3C6} <b>WinRate:</b> <b>${escapeHtml8(winRateText)}</b>`,
|
|
40602
40768
|
`\u2197\uFE0F <b>LONG:</b> <b>${longCount}</b>, \u2198\uFE0F <b>SHORT:</b> <b>${shortCount}</b>`,
|
|
40603
|
-
`\u{1F4CD} <b>Open positions:</b> <b>${openCount}</b>, Unrealized PnL: <b>${
|
|
40769
|
+
`\u{1F4CD} <b>Open positions:</b> <b>${openCount}</b>, Unrealized PnL: <b>${escapeHtml8(openPnlText)}</b>`
|
|
40604
40770
|
];
|
|
40605
40771
|
};
|
|
40606
40772
|
resolveTradeStatusEmoji = (status, pnl) => {
|
|
@@ -40781,12 +40947,12 @@ var init_signalsSummary = __esm({
|
|
|
40781
40947
|
}
|
|
40782
40948
|
);
|
|
40783
40949
|
for (const [source, reasons] of sortedReasonGroups) {
|
|
40784
|
-
signalLines.push(`<b>${
|
|
40950
|
+
signalLines.push(`<b>${escapeHtml8(source)}</b>:`);
|
|
40785
40951
|
const sortedReasons = [...reasons.entries()].sort(
|
|
40786
40952
|
(left, right) => right[1] - left[1] || left[0].localeCompare(right[0])
|
|
40787
40953
|
);
|
|
40788
40954
|
for (const [reason, count] of sortedReasons) {
|
|
40789
|
-
signalLines.push(`${
|
|
40955
|
+
signalLines.push(`${escapeHtml8(reason)}: <b>${count}</b>`);
|
|
40790
40956
|
}
|
|
40791
40957
|
}
|
|
40792
40958
|
};
|
|
@@ -40796,8 +40962,8 @@ var init_signalsSummary = __esm({
|
|
|
40796
40962
|
const evaluation = evaluationStatsByStrategy.get(strategyName);
|
|
40797
40963
|
signalLines.push("");
|
|
40798
40964
|
signalLines.push(
|
|
40799
|
-
evaluation?.evaluated ? `<b>${
|
|
40800
|
-
signals=<b>0</b>` : `<b>${
|
|
40965
|
+
evaluation?.evaluated ? `<b>${escapeHtml8(strategyName)}</b>
|
|
40966
|
+
signals=<b>0</b>` : `<b>${escapeHtml8(strategyName)}</b>
|
|
40801
40967
|
none`
|
|
40802
40968
|
);
|
|
40803
40969
|
appendEvaluationDetails(strategyName);
|
|
@@ -40808,7 +40974,7 @@ none`
|
|
|
40808
40974
|
return count > 0 ? `${status}=<b>${count}</b>` : null;
|
|
40809
40975
|
}).filter(Boolean);
|
|
40810
40976
|
signalLines.push("");
|
|
40811
|
-
signalLines.push(`<b>${
|
|
40977
|
+
signalLines.push(`<b>${escapeHtml8(strategyName)}</b>`);
|
|
40812
40978
|
signalLines.push(parts.join(", "));
|
|
40813
40979
|
appendEvaluationDetails(strategyName);
|
|
40814
40980
|
}
|
|
@@ -40821,17 +40987,17 @@ none`
|
|
|
40821
40987
|
if (!stats) continue;
|
|
40822
40988
|
tradeLines.push("");
|
|
40823
40989
|
tradeLines.push(
|
|
40824
|
-
`<b>${
|
|
40990
|
+
`<b>${escapeHtml8(strategyName)}</b> (<b>${stats.closed}</b>)`
|
|
40825
40991
|
);
|
|
40826
40992
|
tradeLines.push(
|
|
40827
|
-
`Closed PnL: <b>${
|
|
40993
|
+
`Closed PnL: <b>${escapeHtml8(formatPnlMoneyText(stats.closedPnl, stats.closedPnlKnown))}</b> (<b>${stats.closed}</b>)`
|
|
40828
40994
|
);
|
|
40829
40995
|
const sortedTrades = stats.trades.filter((trade) => trade.status === "closed").sort(
|
|
40830
40996
|
(left, right) => left.entryTimestamp - right.entryTimestamp || left.symbol.localeCompare(right.symbol) || left.orderId.localeCompare(right.orderId)
|
|
40831
40997
|
);
|
|
40832
40998
|
for (const trade of sortedTrades) {
|
|
40833
40999
|
tradeLines.push(
|
|
40834
|
-
`- ${
|
|
41000
|
+
`- ${escapeHtml8(trade.symbol)}: PnL <b>${escapeHtml8(trade.pnlText)}</b> ${resolveTradeStatusEmoji(trade.status, trade.pnl)}`
|
|
40835
41001
|
);
|
|
40836
41002
|
}
|
|
40837
41003
|
}
|
|
@@ -40845,17 +41011,17 @@ none`
|
|
|
40845
41011
|
if (!stats) continue;
|
|
40846
41012
|
tradeLines.push("");
|
|
40847
41013
|
tradeLines.push(
|
|
40848
|
-
`<b>${
|
|
41014
|
+
`<b>${escapeHtml8(strategyName)}</b> (<b>${stats.active}</b>)`
|
|
40849
41015
|
);
|
|
40850
41016
|
tradeLines.push(
|
|
40851
|
-
`Unrealized PnL: <b>${
|
|
41017
|
+
`Unrealized PnL: <b>${escapeHtml8(formatPnlMoneyText(stats.activePnl, stats.activePnlKnown))}</b> (<b>${stats.active}</b>)`
|
|
40852
41018
|
);
|
|
40853
41019
|
const sortedTrades = stats.trades.filter((trade) => trade.status === "active").sort(
|
|
40854
41020
|
(left, right) => left.entryTimestamp - right.entryTimestamp || left.symbol.localeCompare(right.symbol) || left.orderId.localeCompare(right.orderId)
|
|
40855
41021
|
);
|
|
40856
41022
|
for (const trade of sortedTrades) {
|
|
40857
41023
|
tradeLines.push(
|
|
40858
|
-
`- ${
|
|
41024
|
+
`- ${escapeHtml8(trade.symbol)}: PnL <b>${escapeHtml8(trade.pnlText)}</b> ${resolveTradeStatusEmoji(trade.status, trade.pnl)}`
|
|
40859
41025
|
);
|
|
40860
41026
|
}
|
|
40861
41027
|
}
|
|
@@ -40867,12 +41033,12 @@ none`
|
|
|
40867
41033
|
signalsSummary = async () => {
|
|
40868
41034
|
const hours = Math.max(
|
|
40869
41035
|
1,
|
|
40870
|
-
Number.parseInt(String(
|
|
41036
|
+
Number.parseInt(String(flags33.hours ?? 24), 10) || 24
|
|
40871
41037
|
);
|
|
40872
41038
|
const endTime = Date.now();
|
|
40873
41039
|
const startTime = endTime - hours * 60 * 60 * 1e3;
|
|
40874
41040
|
const fallbackConnectorName = await resolveSummaryConnectorName(
|
|
40875
|
-
|
|
41041
|
+
flags33.connector
|
|
40876
41042
|
);
|
|
40877
41043
|
const [
|
|
40878
41044
|
configuredStrategyNames,
|
|
@@ -40881,25 +41047,25 @@ none`
|
|
|
40881
41047
|
trades,
|
|
40882
41048
|
runtimeDeployments
|
|
40883
41049
|
] = await Promise.all([
|
|
40884
|
-
(0, import_runtimeStrategyConfigs.loadRuntimeStrategyNames)(
|
|
40885
|
-
loadRuntimeSignals(
|
|
40886
|
-
loadRuntimeSignalEvaluationStatsBuckets(
|
|
40887
|
-
loadRuntimeTrades(
|
|
40888
|
-
(0, import_runtimeStrategies10.listRuntimeDeployments)({ userName:
|
|
41050
|
+
(0, import_runtimeStrategyConfigs.loadRuntimeStrategyNames)(flags33.user),
|
|
41051
|
+
loadRuntimeSignals(flags33.user, { startTime, endTime }),
|
|
41052
|
+
loadRuntimeSignalEvaluationStatsBuckets(flags33.user),
|
|
41053
|
+
loadRuntimeTrades(flags33.user),
|
|
41054
|
+
(0, import_runtimeStrategies10.listRuntimeDeployments)({ userName: flags33.user, projectRoot: projectRoot17 })
|
|
40889
41055
|
]);
|
|
40890
41056
|
const {
|
|
40891
41057
|
trades: syncedTrades,
|
|
40892
41058
|
connectorNames,
|
|
40893
41059
|
scopesCount
|
|
40894
41060
|
} = await syncRuntimeTradeScopes({
|
|
40895
|
-
userName:
|
|
41061
|
+
userName: flags33.user,
|
|
40896
41062
|
startTime,
|
|
40897
41063
|
endTime,
|
|
40898
41064
|
fallbackConnectorName,
|
|
40899
41065
|
trades,
|
|
40900
41066
|
deployments: runtimeDeployments
|
|
40901
41067
|
});
|
|
40902
|
-
const activeTradeOrderIds = await loadRuntimeActiveTradeOrderIds(
|
|
41068
|
+
const activeTradeOrderIds = await loadRuntimeActiveTradeOrderIds(flags33.user);
|
|
40903
41069
|
const windowSignals = signals2.filter(
|
|
40904
41070
|
(signal) => signal.timestamp >= startTime && signal.timestamp < endTime
|
|
40905
41071
|
);
|
|
@@ -40947,10 +41113,10 @@ none`
|
|
|
40947
41113
|
windowClosedTrades.length,
|
|
40948
41114
|
connectorNames.join(",") || fallbackConnectorName,
|
|
40949
41115
|
scopesCount,
|
|
40950
|
-
|
|
41116
|
+
flags33.user
|
|
40951
41117
|
);
|
|
40952
|
-
const debugAttachment = shouldAttachDebugReport(
|
|
40953
|
-
userName:
|
|
41118
|
+
const debugAttachment = shouldAttachDebugReport(flags33.debugAttachment) ? await buildRuntimeDebugReportAttachment({
|
|
41119
|
+
userName: flags33.user,
|
|
40954
41120
|
startTime,
|
|
40955
41121
|
endTime,
|
|
40956
41122
|
signals: debugSignals,
|
|
@@ -40958,7 +41124,7 @@ none`
|
|
|
40958
41124
|
trades: windowTrades
|
|
40959
41125
|
}) : null;
|
|
40960
41126
|
const signalsAttachment = buildSignalsSummaryAttachment({
|
|
40961
|
-
userName:
|
|
41127
|
+
userName: flags33.user,
|
|
40962
41128
|
endTime,
|
|
40963
41129
|
content: signalsMessage
|
|
40964
41130
|
});
|
|
@@ -40974,7 +41140,7 @@ none`
|
|
|
40974
41140
|
signalsAttachment,
|
|
40975
41141
|
...debugAttachment ? [debugAttachment] : []
|
|
40976
41142
|
];
|
|
40977
|
-
if (
|
|
41143
|
+
if (flags33.printOnly) {
|
|
40978
41144
|
console.log(tradesMessageWithAttachmentSummary);
|
|
40979
41145
|
console.log("");
|
|
40980
41146
|
console.log(`Signals attachment: ${signalsAttachment.filename}`);
|
|
@@ -40987,20 +41153,20 @@ none`
|
|
|
40987
41153
|
return;
|
|
40988
41154
|
}
|
|
40989
41155
|
await sendTelegramReport(tradesMessageWithAttachmentSummary, {
|
|
40990
|
-
userName:
|
|
41156
|
+
userName: flags33.user,
|
|
40991
41157
|
attachments
|
|
40992
41158
|
});
|
|
40993
41159
|
};
|
|
40994
|
-
|
|
41160
|
+
main47 = signalsSummary;
|
|
40995
41161
|
}
|
|
40996
41162
|
});
|
|
40997
41163
|
|
|
40998
41164
|
// src/scripts/test-ml.ts
|
|
40999
41165
|
var test_ml_exports = {};
|
|
41000
41166
|
__export(test_ml_exports, {
|
|
41001
|
-
main: () =>
|
|
41167
|
+
main: () => main48
|
|
41002
41168
|
});
|
|
41003
|
-
var import_config14, import_constants21, import_ml3, import_registry5, now, INTERVAL_MIN, CANDLES, makeSeries, makeCandles, buildTrendline,
|
|
41169
|
+
var import_config14, import_constants21, import_ml3, import_registry5, now, INTERVAL_MIN, CANDLES, makeSeries, makeCandles, buildTrendline, main48;
|
|
41004
41170
|
var init_test_ml = __esm({
|
|
41005
41171
|
"src/scripts/test-ml.ts"() {
|
|
41006
41172
|
"use strict";
|
|
@@ -41050,7 +41216,7 @@ var init_test_ml = __esm({
|
|
|
41050
41216
|
{ timestamp: entryTs - 2 * INTERVAL_MIN * 6e4, value: price * 0.995 }
|
|
41051
41217
|
]
|
|
41052
41218
|
});
|
|
41053
|
-
|
|
41219
|
+
main48 = async () => {
|
|
41054
41220
|
const defaultConfig = await (0, import_registry5.getStrategyDefaults)("TrendLine", process.cwd());
|
|
41055
41221
|
if (!defaultConfig) {
|
|
41056
41222
|
throw new Error(
|
|
@@ -41143,9 +41309,9 @@ var init_test_ml = __esm({
|
|
|
41143
41309
|
// src/scripts/test.ts
|
|
41144
41310
|
var test_exports = {};
|
|
41145
41311
|
__export(test_exports, {
|
|
41146
|
-
main: () =>
|
|
41312
|
+
main: () => main49
|
|
41147
41313
|
});
|
|
41148
|
-
var import_config15, import_connectors19, getPositions,
|
|
41314
|
+
var import_config15, import_connectors19, getPositions, main49;
|
|
41149
41315
|
var init_test = __esm({
|
|
41150
41316
|
"src/scripts/test.ts"() {
|
|
41151
41317
|
"use strict";
|
|
@@ -41155,7 +41321,7 @@ var init_test = __esm({
|
|
|
41155
41321
|
const res = await connector.getPositions();
|
|
41156
41322
|
console.log("res", res);
|
|
41157
41323
|
};
|
|
41158
|
-
|
|
41324
|
+
main49 = async () => {
|
|
41159
41325
|
const byBitConnector = await import_connectors19.connectors.ByBit({
|
|
41160
41326
|
userName: "root"
|
|
41161
41327
|
});
|
|
@@ -41167,25 +41333,25 @@ var init_test = __esm({
|
|
|
41167
41333
|
// src/scripts/user-add.ts
|
|
41168
41334
|
var user_add_exports = {};
|
|
41169
41335
|
__export(user_add_exports, {
|
|
41170
|
-
main: () =>
|
|
41336
|
+
main: () => main50
|
|
41171
41337
|
});
|
|
41172
|
-
var
|
|
41338
|
+
var import_args37, import_chalk55, import_bcryptjs, import_redis22, flags34, main50;
|
|
41173
41339
|
var init_user_add = __esm({
|
|
41174
41340
|
"src/scripts/user-add.ts"() {
|
|
41175
41341
|
"use strict";
|
|
41176
|
-
|
|
41177
|
-
|
|
41342
|
+
import_args37 = __toESM(require("args"));
|
|
41343
|
+
import_chalk55 = __toESM(require("chalk"));
|
|
41178
41344
|
import_bcryptjs = __toESM(require("bcryptjs"));
|
|
41179
41345
|
import_redis22 = require("@tradejs/infra/redis");
|
|
41180
|
-
|
|
41181
|
-
|
|
41182
|
-
|
|
41183
|
-
|
|
41184
|
-
|
|
41185
|
-
const userName3 = String(
|
|
41186
|
-
const password = String(
|
|
41346
|
+
import_args37.default.example("yarn user-add -u myname -p 123456", "Create or update user");
|
|
41347
|
+
import_args37.default.option(["u", "user"], "Username", "");
|
|
41348
|
+
import_args37.default.option(["p", "password"], "Password (plain text)", "");
|
|
41349
|
+
flags34 = import_args37.default.parse(process.argv);
|
|
41350
|
+
main50 = async () => {
|
|
41351
|
+
const userName3 = String(flags34.user || "").trim();
|
|
41352
|
+
const password = String(flags34.password || "");
|
|
41187
41353
|
if (!userName3 || !password) {
|
|
41188
|
-
console.error(
|
|
41354
|
+
console.error(import_chalk55.default.red("Missing -U <user> or -P <password>"));
|
|
41189
41355
|
process.exit(1);
|
|
41190
41356
|
}
|
|
41191
41357
|
const passwordHash = await import_bcryptjs.default.hash(password, 10);
|
|
@@ -41199,7 +41365,7 @@ var init_user_add = __esm({
|
|
|
41199
41365
|
await (0, import_redis22.setData)(import_redis22.redisKeys.user(userName3), next, {
|
|
41200
41366
|
expire: 0
|
|
41201
41367
|
});
|
|
41202
|
-
console.log(
|
|
41368
|
+
console.log(import_chalk55.default.green(`User ${userName3} updated`));
|
|
41203
41369
|
process.exit(0);
|
|
41204
41370
|
};
|
|
41205
41371
|
}
|
|
@@ -41209,7 +41375,7 @@ var init_user_add = __esm({
|
|
|
41209
41375
|
var cli_exports = {};
|
|
41210
41376
|
__export(cli_exports, {
|
|
41211
41377
|
cleanupCliResources: () => cleanupCliResources,
|
|
41212
|
-
main: () =>
|
|
41378
|
+
main: () => main51,
|
|
41213
41379
|
printUsage: () => printUsage3,
|
|
41214
41380
|
runLoadedModule: () => runLoadedModule
|
|
41215
41381
|
});
|
|
@@ -41253,6 +41419,7 @@ var scriptLoaders = {
|
|
|
41253
41419
|
results: () => Promise.resolve().then(() => (init_results(), results_exports)),
|
|
41254
41420
|
"replay-runtime-evidence": () => Promise.resolve().then(() => (init_replayRuntimeEvidence(), replayRuntimeEvidence_exports)),
|
|
41255
41421
|
"runtime-feedback-replay": () => Promise.resolve().then(() => (init_runtimeFeedbackReplay2(), runtimeFeedbackReplay_exports)),
|
|
41422
|
+
"runtime-feedback-notify": () => Promise.resolve().then(() => (init_runtimeFeedbackNotify(), runtimeFeedbackNotify_exports)),
|
|
41256
41423
|
"runtime-feedback-sync": () => Promise.resolve().then(() => (init_runtimeFeedbackSync2(), runtimeFeedbackSync_exports)),
|
|
41257
41424
|
"runtime-evidence": () => Promise.resolve().then(() => (init_runtimeEvidence(), runtimeEvidence_exports)),
|
|
41258
41425
|
"runtime-evidence-sync": () => Promise.resolve().then(() => (init_runtimeEvidenceSync2(), runtimeEvidenceSync_exports)),
|
|
@@ -41285,14 +41452,14 @@ var runLoadedModule = async (loaded) => {
|
|
|
41285
41452
|
var cleanupCliResources = async () => {
|
|
41286
41453
|
await Promise.allSettled([(0, import_redis23.closeRedisConnection)(), (0, import_client9.closeTimescalePool)()]);
|
|
41287
41454
|
};
|
|
41288
|
-
var
|
|
41289
|
-
const [, scriptPath, command = "", ...
|
|
41455
|
+
var main51 = async () => {
|
|
41456
|
+
const [, scriptPath, command = "", ...args38] = process.argv;
|
|
41290
41457
|
const loader = scriptLoaders[command];
|
|
41291
41458
|
if (!loader) {
|
|
41292
41459
|
printUsage3();
|
|
41293
41460
|
process.exit(command ? 1 : 0);
|
|
41294
41461
|
}
|
|
41295
|
-
const nextArgs = [...
|
|
41462
|
+
const nextArgs = [...args38];
|
|
41296
41463
|
if (command === "spread:ingest") {
|
|
41297
41464
|
nextArgs.push("--provider", "binance_coinbase_spread");
|
|
41298
41465
|
}
|
|
@@ -41316,7 +41483,7 @@ var main50 = async () => {
|
|
|
41316
41483
|
}
|
|
41317
41484
|
};
|
|
41318
41485
|
if (require.main === module) {
|
|
41319
|
-
|
|
41486
|
+
main51().catch((error) => {
|
|
41320
41487
|
console.error(error);
|
|
41321
41488
|
process.exit(1);
|
|
41322
41489
|
});
|