@tradejs/cli 3.0.1 → 3.1.1
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/README.md +2 -0
- package/dist/cli.js +3707 -2983
- package/dist/lib/aiPocketSearch.js +10 -0
- package/dist/lib/aiTrainResearch.js +24 -15
- package/dist/lib/coreResearch.js +52 -20
- package/dist/lib/researchAgent.js +16 -2
- package/dist/lib/researchRoots.js +59 -0
- package/dist/lib/runtimeLineage.js +43 -19
- package/dist/lib/runtimeModeConfig.js +1 -1
- package/dist/lib/runtimeSignalsStorage.js +2 -1
- package/dist/lib/strategyGateFingerprint.js +26 -15
- package/dist/lib/strategyRelease.js +266 -253
- package/dist/scripts/agentRun.js +83 -52
- package/dist/scripts/aiPocketSearch.js +2269 -1972
- package/dist/scripts/aiTrain.js +24 -15
- package/dist/scripts/coreResearch.js +91 -30
- package/dist/scripts/replay.js +69 -27
- package/dist/scripts/replayRunner.js +69 -27
- package/dist/scripts/researchAuto.js +34 -13
- package/dist/scripts/runtimeConfig.js +290 -0
- package/dist/scripts/runtimeEvidence.js +2 -1
- package/dist/scripts/runtimeParity.js +1 -1
- package/dist/scripts/runtimeScorecard.js +108 -103
- package/dist/scripts/signals.js +162 -224
- package/dist/scripts/signalsDaemon.js +162 -224
- package/dist/scripts/strategyRelease.js +222 -209
- package/dist/scripts/test-ml.js +8 -2
- package/package.json +13 -10
|
@@ -44,10 +44,10 @@ var import_chalk7 = __toESM(require("chalk"));
|
|
|
44
44
|
var import_connectors6 = require("@tradejs/node/connectors");
|
|
45
45
|
var import_cli2 = require("@tradejs/node/cli");
|
|
46
46
|
var import_async3 = require("@tradejs/core/async");
|
|
47
|
-
var
|
|
47
|
+
var import_strategies5 = require("@tradejs/core/strategies");
|
|
48
48
|
var import_constants3 = require("@tradejs/core/constants");
|
|
49
|
-
var
|
|
50
|
-
var
|
|
49
|
+
var import_time2 = require("@tradejs/core/time");
|
|
50
|
+
var import_logger4 = require("@tradejs/infra/logger");
|
|
51
51
|
var import_runtimeDeployments = require("@tradejs/infra/runtimeDeployments");
|
|
52
52
|
|
|
53
53
|
// src/lib/marketData/windows.ts
|
|
@@ -3735,125 +3735,15 @@ var updateBtcReferenceHistory = async ({
|
|
|
3735
3735
|
};
|
|
3736
3736
|
|
|
3737
3737
|
// src/lib/signals/runtimeStrategies.ts
|
|
3738
|
-
var
|
|
3739
|
-
var import_redis2 = require("@tradejs/infra/redis");
|
|
3740
|
-
var import_tradingAccounts = require("@tradejs/infra/tradingAccounts");
|
|
3741
|
-
var import_strategies3 = require("@tradejs/node/strategies");
|
|
3742
|
-
|
|
3743
|
-
// src/lib/runtimeRedis.ts
|
|
3744
|
-
var import_redis = require("@tradejs/infra/redis");
|
|
3745
|
-
var import_time = require("@tradejs/core/time");
|
|
3746
|
-
var import_runtimeStrategyConfigs = require("@tradejs/infra/runtimeStrategyConfigs");
|
|
3747
|
-
var isRuntimeStrategyEnabled = (strategyConfig) => {
|
|
3748
|
-
const enabled = strategyConfig.ENABLE;
|
|
3749
|
-
return enabled !== false;
|
|
3750
|
-
};
|
|
3751
|
-
|
|
3752
|
-
// src/lib/signals/runtimeStrategies.ts
|
|
3753
|
-
var loadRuntimeStrategies = async ({
|
|
3754
|
-
userName,
|
|
3755
|
-
projectRoot,
|
|
3756
|
-
deployment,
|
|
3757
|
-
connectorName = "bybit",
|
|
3758
|
-
universe,
|
|
3759
|
-
accountId,
|
|
3760
|
-
interval
|
|
3761
|
-
}) => {
|
|
3762
|
-
const deploymentStrategies = new Map(
|
|
3763
|
-
(deployment?.strategies ?? []).map((strategy) => [
|
|
3764
|
-
strategy.strategyName,
|
|
3765
|
-
strategy
|
|
3766
|
-
])
|
|
3767
|
-
);
|
|
3768
|
-
const strategyConfigs = await Promise.all(
|
|
3769
|
-
(await (0, import_runtimeStrategyConfigs.loadRuntimeStrategyConfigs)(userName)).map(
|
|
3770
|
-
async ({
|
|
3771
|
-
key,
|
|
3772
|
-
strategyName,
|
|
3773
|
-
configId,
|
|
3774
|
-
strategyConfig
|
|
3775
|
-
}) => {
|
|
3776
|
-
const deploymentStrategy = deployment ? deploymentStrategies.get(strategyName) : void 0;
|
|
3777
|
-
if (deploymentStrategy?.enabled === false) {
|
|
3778
|
-
import_logger.logger.info(
|
|
3779
|
-
"Skip deployment-disabled strategy config: %s",
|
|
3780
|
-
strategyName
|
|
3781
|
-
);
|
|
3782
|
-
return null;
|
|
3783
|
-
}
|
|
3784
|
-
if (!isRuntimeStrategyEnabled(strategyConfig)) {
|
|
3785
|
-
import_logger.logger.info(
|
|
3786
|
-
"Skip inactive strategy config by ENABLE=false: %s",
|
|
3787
|
-
strategyName
|
|
3788
|
-
);
|
|
3789
|
-
return null;
|
|
3790
|
-
}
|
|
3791
|
-
const configUniverse = deployment?.universe ?? (strategyConfig.UNIVERSE === "tradfi" ? "tradfi" : "crypto");
|
|
3792
|
-
const configInterval = String(
|
|
3793
|
-
deployment?.interval ?? strategyConfig.INTERVAL ?? "15"
|
|
3794
|
-
);
|
|
3795
|
-
const requestedAccountId = deployment?.accountId ?? (typeof strategyConfig.ACCOUNT_ID === "string" && strategyConfig.ACCOUNT_ID.trim() ? strategyConfig.ACCOUNT_ID.trim() : void 0);
|
|
3796
|
-
const resolvedAccount = await (0, import_tradingAccounts.resolveTradingAccount)({
|
|
3797
|
-
userName,
|
|
3798
|
-
accountId: requestedAccountId,
|
|
3799
|
-
provider: deployment?.provider ?? connectorName,
|
|
3800
|
-
universe: configUniverse
|
|
3801
|
-
});
|
|
3802
|
-
const effectiveAccountId = resolvedAccount?.id ?? requestedAccountId;
|
|
3803
|
-
const [strategyCreator, strategyResults] = await Promise.all([
|
|
3804
|
-
(0, import_strategies3.getStrategyCreator)(strategyName, projectRoot),
|
|
3805
|
-
(0, import_redis2.getData)(import_redis2.redisKeys.strategyResults(userName, strategyName), {})
|
|
3806
|
-
]);
|
|
3807
|
-
if (!strategyCreator) {
|
|
3808
|
-
import_logger.logger.warn("Skip unknown strategy config key: %s", key);
|
|
3809
|
-
return null;
|
|
3810
|
-
}
|
|
3811
|
-
return {
|
|
3812
|
-
strategyName,
|
|
3813
|
-
configId,
|
|
3814
|
-
interval: configInterval,
|
|
3815
|
-
universe: configUniverse,
|
|
3816
|
-
accountId: effectiveAccountId,
|
|
3817
|
-
releaseCompositionId: deploymentStrategy?.releaseCompositionId,
|
|
3818
|
-
strategyCreator,
|
|
3819
|
-
sourceStrategyConfig: strategyConfig,
|
|
3820
|
-
strategyConfig: {
|
|
3821
|
-
...strategyConfig,
|
|
3822
|
-
...deploymentStrategy?.config,
|
|
3823
|
-
INTERVAL: configInterval,
|
|
3824
|
-
UNIVERSE: configUniverse,
|
|
3825
|
-
...effectiveAccountId ? { ACCOUNT_ID: effectiveAccountId } : {},
|
|
3826
|
-
...deploymentStrategy?.policyProfileId ? { POLICY_PROFILE_ID: deploymentStrategy.policyProfileId } : {}
|
|
3827
|
-
},
|
|
3828
|
-
strategyResults: strategyResults ?? {}
|
|
3829
|
-
};
|
|
3830
|
-
}
|
|
3831
|
-
)
|
|
3832
|
-
);
|
|
3833
|
-
const active = strategyConfigs.filter(Boolean);
|
|
3834
|
-
const byStrategyAndAccount = /* @__PURE__ */ new Map();
|
|
3835
|
-
for (const candidate of active) {
|
|
3836
|
-
const conflictKey = `${candidate.strategyName}:${candidate.accountId ?? "default"}`;
|
|
3837
|
-
const existing = byStrategyAndAccount.get(conflictKey);
|
|
3838
|
-
if (existing) {
|
|
3839
|
-
throw new Error(
|
|
3840
|
-
`Runtime strategy conflict: ${candidate.strategyName} configs "${existing.configId}" and "${candidate.configId}" resolve to account "${candidate.accountId ?? "default"}". Disable one config or select another account.`
|
|
3841
|
-
);
|
|
3842
|
-
}
|
|
3843
|
-
byStrategyAndAccount.set(conflictKey, candidate);
|
|
3844
|
-
}
|
|
3845
|
-
return active.filter(
|
|
3846
|
-
(candidate) => (!universe || candidate.universe === universe) && (!interval || String(candidate.interval) === String(interval)) && (!accountId || candidate.accountId === accountId)
|
|
3847
|
-
);
|
|
3848
|
-
};
|
|
3738
|
+
var import_runtimeStrategies = require("@tradejs/node/runtimeStrategies");
|
|
3849
3739
|
|
|
3850
3740
|
// src/lib/signals/skipStats.ts
|
|
3851
3741
|
var import_chalk6 = __toESM(require("chalk"));
|
|
3852
|
-
var
|
|
3742
|
+
var import_logger = require("@tradejs/infra/logger");
|
|
3853
3743
|
|
|
3854
3744
|
// src/lib/runtimeSignalsStorage.ts
|
|
3855
3745
|
var import_constants2 = require("@tradejs/core/constants");
|
|
3856
|
-
var
|
|
3746
|
+
var import_time = require("@tradejs/core/time");
|
|
3857
3747
|
var SECONDS_PER_DAY = 86400;
|
|
3858
3748
|
var RUNTIME_SIGNAL_RETENTION_DAYS_ENV = "RUNTIME_SIGNAL_RETENTION_DAYS";
|
|
3859
3749
|
var DEFAULT_RUNTIME_SIGNAL_RETENTION_TTL_SECONDS = import_constants2.TTL_3D;
|
|
@@ -3879,7 +3769,8 @@ var toRuntimeSignalBucketRef = (signal) => ({
|
|
|
3879
3769
|
symbol: signal.symbol,
|
|
3880
3770
|
strategy: signal.strategy,
|
|
3881
3771
|
timestamp: signal.timestamp,
|
|
3882
|
-
...signal.runtimeConfigId && signal.runtimeConfigId !== "config" ? { runtimeConfigId: signal.runtimeConfigId } : {}
|
|
3772
|
+
...signal.runtimeConfigId && signal.runtimeConfigId !== "config" ? { runtimeConfigId: signal.runtimeConfigId } : {},
|
|
3773
|
+
...signal.runtimeReleaseVersion ? { runtimeReleaseVersion: signal.runtimeReleaseVersion } : {}
|
|
3883
3774
|
});
|
|
3884
3775
|
var shouldStoreRuntimeSignalDiagnostics = (signal) => signal.orderStatus === "completed" || signal.orderStatus === "failed";
|
|
3885
3776
|
var toStoredRuntimeSignal = (signal) => {
|
|
@@ -3978,30 +3869,30 @@ var recordStrategyReason = (strategyStats, strategyName, reason, fallbackSource
|
|
|
3978
3869
|
);
|
|
3979
3870
|
};
|
|
3980
3871
|
var logStrategySkipStats = (runtimeStrategies, strategyStats) => {
|
|
3981
|
-
|
|
3872
|
+
import_logger.logger.info(import_chalk6.default.yellow("skip stats:"));
|
|
3982
3873
|
for (const { strategyName } of runtimeStrategies) {
|
|
3983
3874
|
const stats = strategyStats.get(strategyName);
|
|
3984
3875
|
if (!stats) {
|
|
3985
3876
|
continue;
|
|
3986
3877
|
}
|
|
3987
|
-
|
|
3878
|
+
import_logger.logger.info(
|
|
3988
3879
|
`${strategyName}: evaluated=${stats.evaluated}, signals=${stats.signals}`
|
|
3989
3880
|
);
|
|
3990
3881
|
const sortedReasons = [...stats.reasons.entries()].sort(
|
|
3991
3882
|
(left, right) => right[1] - left[1] || left[0].localeCompare(right[0])
|
|
3992
3883
|
);
|
|
3993
3884
|
if (!sortedReasons.length) {
|
|
3994
|
-
|
|
3885
|
+
import_logger.logger.info(" none");
|
|
3995
3886
|
continue;
|
|
3996
3887
|
}
|
|
3997
3888
|
for (const [reason, count] of sortedReasons) {
|
|
3998
|
-
|
|
3889
|
+
import_logger.logger.info(` ${reason}: ${count}`);
|
|
3999
3890
|
}
|
|
4000
3891
|
}
|
|
4001
3892
|
};
|
|
4002
3893
|
|
|
4003
3894
|
// src/lib/signals/evaluations.ts
|
|
4004
|
-
var
|
|
3895
|
+
var import_redis = require("@tradejs/infra/redis");
|
|
4005
3896
|
|
|
4006
3897
|
// src/lib/runtimeLineage.ts
|
|
4007
3898
|
var import_node_child_process = require("child_process");
|
|
@@ -4009,33 +3900,42 @@ var import_node_crypto2 = require("crypto");
|
|
|
4009
3900
|
var import_promises2 = __toESM(require("fs/promises"));
|
|
4010
3901
|
var import_node_path2 = __toESM(require("path"));
|
|
4011
3902
|
var import_types = require("@tradejs/types");
|
|
4012
|
-
var
|
|
3903
|
+
var import_strategies3 = require("@tradejs/node/strategies");
|
|
4013
3904
|
var import_strategyReleaseEvidence = require("@tradejs/infra/strategyReleaseEvidence");
|
|
4014
3905
|
|
|
4015
3906
|
// src/lib/strategyGateFingerprint.ts
|
|
4016
3907
|
var import_node_crypto = require("crypto");
|
|
3908
|
+
var import_node_module = require("module");
|
|
4017
3909
|
var import_promises = __toESM(require("fs/promises"));
|
|
4018
3910
|
var import_node_path = __toESM(require("path"));
|
|
4019
|
-
var
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
"
|
|
4025
|
-
"
|
|
4026
|
-
"packages/core/src/utils/strategyHelpers/signalBuilders.ts"
|
|
3911
|
+
var toPackageToken = (strategyName) => strategyName.replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2").replace(/([a-z\d])([A-Z])/g, "$1-$2").toLowerCase();
|
|
3912
|
+
var getStrategyPackageName = (strategyName) => strategyName === "TrendLine" || strategyName === "ReverseTrendLine" ? "@tradejs/strategy-trend-line" : `@tradejs/strategy-${toPackageToken(strategyName)}`;
|
|
3913
|
+
var gateFingerprintSpecifiers = (strategyName) => [
|
|
3914
|
+
getStrategyPackageName(strategyName),
|
|
3915
|
+
"@tradejs/strategy-kit/ai-gate",
|
|
3916
|
+
"@tradejs/node/ai",
|
|
3917
|
+
"@tradejs/core/strategies"
|
|
4027
3918
|
];
|
|
4028
3919
|
var resolveStrategyGateFingerprint = async ({
|
|
4029
3920
|
projectRoot,
|
|
4030
3921
|
strategyName,
|
|
4031
3922
|
gitSha
|
|
4032
3923
|
}) => {
|
|
4033
|
-
const
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
3924
|
+
const projectManifestPath = import_node_path.default.join(projectRoot, "package.json");
|
|
3925
|
+
const projectExists = await import_promises.default.access(projectManifestPath).then(() => true).catch(() => false);
|
|
3926
|
+
const requireFromProject = projectExists ? (0, import_node_module.createRequire)(projectManifestPath) : null;
|
|
3927
|
+
const candidates = requireFromProject ? await Promise.all(
|
|
3928
|
+
gateFingerprintSpecifiers(strategyName).map(async (specifier) => {
|
|
3929
|
+
let resolvedPath;
|
|
3930
|
+
try {
|
|
3931
|
+
resolvedPath = requireFromProject.resolve(specifier);
|
|
3932
|
+
} catch {
|
|
3933
|
+
return null;
|
|
3934
|
+
}
|
|
3935
|
+
const content = await import_promises.default.readFile(resolvedPath).catch(() => null);
|
|
3936
|
+
return content == null ? null : { specifier, content };
|
|
4037
3937
|
})
|
|
4038
|
-
);
|
|
3938
|
+
) : [];
|
|
4039
3939
|
const sourceEntries = candidates.filter(
|
|
4040
3940
|
(entry) => entry != null
|
|
4041
3941
|
);
|
|
@@ -4043,7 +3943,7 @@ var resolveStrategyGateFingerprint = async ({
|
|
|
4043
3943
|
hash.update(strategyName);
|
|
4044
3944
|
if (sourceEntries.length) {
|
|
4045
3945
|
for (const entry of sourceEntries) {
|
|
4046
|
-
hash.update(entry.
|
|
3946
|
+
hash.update(entry.specifier);
|
|
4047
3947
|
hash.update(entry.content);
|
|
4048
3948
|
}
|
|
4049
3949
|
} else {
|
|
@@ -4051,7 +3951,7 @@ var resolveStrategyGateFingerprint = async ({
|
|
|
4051
3951
|
}
|
|
4052
3952
|
return {
|
|
4053
3953
|
gateFingerprint: hash.digest("hex").slice(0, 16),
|
|
4054
|
-
gateFingerprintFiles: sourceEntries.map((entry) => entry.
|
|
3954
|
+
gateFingerprintFiles: sourceEntries.map((entry) => entry.specifier)
|
|
4055
3955
|
};
|
|
4056
3956
|
};
|
|
4057
3957
|
|
|
@@ -4230,20 +4130,35 @@ var resolveRuntimeGateFingerprint = async ({
|
|
|
4230
4130
|
gateFingerprintCache.set(cacheKey, result);
|
|
4231
4131
|
return result;
|
|
4232
4132
|
};
|
|
4233
|
-
|
|
4133
|
+
async function buildRuntimeLineage({
|
|
4234
4134
|
projectRoot,
|
|
4235
4135
|
strategyName,
|
|
4236
4136
|
compositionId,
|
|
4137
|
+
releaseVersion,
|
|
4138
|
+
strategyPackageVersion,
|
|
4139
|
+
runtimePackageVersion,
|
|
4237
4140
|
config: config2,
|
|
4238
4141
|
runContext,
|
|
4239
4142
|
env = process.env
|
|
4240
|
-
})
|
|
4143
|
+
}) {
|
|
4144
|
+
if (releaseVersion != null) {
|
|
4145
|
+
if (!Number.isSafeInteger(releaseVersion) || releaseVersion <= 0) {
|
|
4146
|
+
throw new Error(`Invalid runtime releaseVersion: ${releaseVersion}`);
|
|
4147
|
+
}
|
|
4148
|
+
return {
|
|
4149
|
+
schemaVersion: 2,
|
|
4150
|
+
releaseVersion,
|
|
4151
|
+
strategyPackageVersion,
|
|
4152
|
+
runtimePackageVersion,
|
|
4153
|
+
maxLossValue: resolveRuntimeMaxLossValue(config2)
|
|
4154
|
+
};
|
|
4155
|
+
}
|
|
4241
4156
|
const git = resolveGitLineage(projectRoot);
|
|
4242
|
-
const hyperliquidPerpUniverseFingerprint = typeof
|
|
4157
|
+
const hyperliquidPerpUniverseFingerprint = typeof import_strategies3.getHyperliquidPerpUniverseSnapshot === "function" ? (0, import_strategies3.getHyperliquidPerpUniverseSnapshot)().fingerprint : await resolveSnapshotFingerprint(
|
|
4243
4158
|
projectRoot,
|
|
4244
4159
|
"packages/node/src/config/hyperliquidPerpUniverse.json"
|
|
4245
4160
|
);
|
|
4246
|
-
const hyperliquidWhaleRegistryFingerprint = typeof
|
|
4161
|
+
const hyperliquidWhaleRegistryFingerprint = typeof import_strategies3.getHyperliquidWhaleRegistrySnapshot === "function" ? (0, import_strategies3.getHyperliquidWhaleRegistrySnapshot)().fingerprint : await resolveSnapshotFingerprint(
|
|
4247
4162
|
projectRoot,
|
|
4248
4163
|
"packages/node/src/config/hyperliquidWhales.json"
|
|
4249
4164
|
);
|
|
@@ -4272,8 +4187,8 @@ var buildRuntimeLineage = async ({
|
|
|
4272
4187
|
contextFingerprint: fingerprintRuntimeValue(context),
|
|
4273
4188
|
maxLossValue: resolveRuntimeMaxLossValue(config2)
|
|
4274
4189
|
};
|
|
4275
|
-
}
|
|
4276
|
-
var runtimeLineageKey = (lineage) => [
|
|
4190
|
+
}
|
|
4191
|
+
var runtimeLineageKey = (lineage) => lineage.schemaVersion === 2 ? ["v2", lineage.releaseVersion].join(":") : [
|
|
4277
4192
|
lineage.schemaVersion,
|
|
4278
4193
|
lineage.compositionId ?? "unbound-composition",
|
|
4279
4194
|
lineage.gitSha ?? "unknown",
|
|
@@ -4291,11 +4206,13 @@ var buildRuntimeSignalEvaluationId = ({
|
|
|
4291
4206
|
strategyName,
|
|
4292
4207
|
symbol,
|
|
4293
4208
|
timestamp,
|
|
4294
|
-
runtimeConfigId
|
|
4295
|
-
|
|
4209
|
+
runtimeConfigId,
|
|
4210
|
+
runtimeReleaseVersion
|
|
4211
|
+
}) => runtimeReleaseVersion ? [strategyName, `v${runtimeReleaseVersion}`, symbol, timestamp].join(":") : runtimeConfigId && runtimeConfigId !== "config" ? [strategyName, runtimeConfigId, symbol, timestamp].join(":") : [strategyName, symbol, timestamp].join(":");
|
|
4296
4212
|
var buildLineageField = (scope) => [
|
|
4297
4213
|
scope.strategy,
|
|
4298
4214
|
scope.runtimeConfigId ?? "config",
|
|
4215
|
+
scope.runtimeReleaseVersion ? `v${scope.runtimeReleaseVersion}` : "legacy",
|
|
4299
4216
|
scope.symbol,
|
|
4300
4217
|
runtimeLineageKey(scope.lineage)
|
|
4301
4218
|
].join(":");
|
|
@@ -4303,7 +4220,7 @@ var flushRuntimeSignalEvaluations = async (evaluations) => {
|
|
|
4303
4220
|
if (evaluations.length === 0) return;
|
|
4304
4221
|
const evaluationsByDay = /* @__PURE__ */ new Map();
|
|
4305
4222
|
for (const evaluation of evaluations) {
|
|
4306
|
-
const dayKey = (0,
|
|
4223
|
+
const dayKey = (0, import_time.getRuntimeStorageDayKey)(evaluation.timestamp);
|
|
4307
4224
|
const dayEvaluations = evaluationsByDay.get(dayKey) ?? [];
|
|
4308
4225
|
dayEvaluations.push(evaluation);
|
|
4309
4226
|
evaluationsByDay.set(dayKey, dayEvaluations);
|
|
@@ -4315,7 +4232,7 @@ var flushRuntimeSignalEvaluations = async (evaluations) => {
|
|
|
4315
4232
|
runtimeLineageScopeCacheDayKey = dayKey;
|
|
4316
4233
|
runtimeLineageScopeCacheLoaded = false;
|
|
4317
4234
|
}
|
|
4318
|
-
const lineageBucket =
|
|
4235
|
+
const lineageBucket = import_redis.redisKeys.runtimeLineageScopeBucket(
|
|
4319
4236
|
dayEvaluations[0].userName,
|
|
4320
4237
|
dayKey
|
|
4321
4238
|
);
|
|
@@ -4323,7 +4240,7 @@ var flushRuntimeSignalEvaluations = async (evaluations) => {
|
|
|
4323
4240
|
(evaluation) => evaluation.runtimeLineage != null
|
|
4324
4241
|
);
|
|
4325
4242
|
if (lineageEvaluations.length > 0 && !runtimeLineageScopeCacheLoaded) {
|
|
4326
|
-
const storedScopes = await (0,
|
|
4243
|
+
const storedScopes = await (0, import_redis.getHashJsonValues)(lineageBucket);
|
|
4327
4244
|
for (const scope of storedScopes) {
|
|
4328
4245
|
const lineageField = buildLineageField(scope);
|
|
4329
4246
|
runtimeLineageScopeCache.set(`${lineageBucket}:${lineageField}`, scope);
|
|
@@ -4335,6 +4252,7 @@ var flushRuntimeSignalEvaluations = async (evaluations) => {
|
|
|
4335
4252
|
const lineageField = buildLineageField({
|
|
4336
4253
|
strategy: evaluation.strategy,
|
|
4337
4254
|
runtimeConfigId: evaluation.runtimeConfigId,
|
|
4255
|
+
runtimeReleaseVersion: evaluation.runtimeReleaseVersion,
|
|
4338
4256
|
symbol: evaluation.symbol,
|
|
4339
4257
|
lineage: evaluation.runtimeLineage
|
|
4340
4258
|
});
|
|
@@ -4344,6 +4262,7 @@ var flushRuntimeSignalEvaluations = async (evaluations) => {
|
|
|
4344
4262
|
strategy: evaluation.strategy,
|
|
4345
4263
|
symbol: evaluation.symbol,
|
|
4346
4264
|
runtimeConfigId: evaluation.runtimeConfigId,
|
|
4265
|
+
runtimeReleaseVersion: evaluation.runtimeReleaseVersion,
|
|
4347
4266
|
lineage: evaluation.runtimeLineage,
|
|
4348
4267
|
firstTimestamp: Math.min(
|
|
4349
4268
|
existing?.firstTimestamp ?? evaluation.timestamp,
|
|
@@ -4358,7 +4277,7 @@ var flushRuntimeSignalEvaluations = async (evaluations) => {
|
|
|
4358
4277
|
lineageWrites.set(lineageField, scope);
|
|
4359
4278
|
}
|
|
4360
4279
|
if (lineageWrites.size > 0) {
|
|
4361
|
-
await (0,
|
|
4280
|
+
await (0, import_redis.setHashJsonFields)(
|
|
4362
4281
|
lineageBucket,
|
|
4363
4282
|
[...lineageWrites].map(([field, data]) => ({ field, data })),
|
|
4364
4283
|
{
|
|
@@ -4370,7 +4289,7 @@ var flushRuntimeSignalEvaluations = async (evaluations) => {
|
|
|
4370
4289
|
const statsIncrements = /* @__PURE__ */ new Map();
|
|
4371
4290
|
for (const evaluation of dayEvaluations) {
|
|
4372
4291
|
if (shouldStoreDetailedRuntimeSignalEvaluation(evaluation)) {
|
|
4373
|
-
const bucket =
|
|
4292
|
+
const bucket = import_redis.redisKeys.runtimeSignalEvaluationBucket(
|
|
4374
4293
|
evaluation.userName,
|
|
4375
4294
|
dayKey,
|
|
4376
4295
|
evaluation.strategy
|
|
@@ -4382,7 +4301,7 @@ var flushRuntimeSignalEvaluations = async (evaluations) => {
|
|
|
4382
4301
|
});
|
|
4383
4302
|
detailedWrites.set(bucket, entries);
|
|
4384
4303
|
}
|
|
4385
|
-
const statsBucket =
|
|
4304
|
+
const statsBucket = import_redis.redisKeys.runtimeSignalEvaluationStatsBucket(
|
|
4386
4305
|
evaluation.userName,
|
|
4387
4306
|
dayKey,
|
|
4388
4307
|
evaluation.strategy
|
|
@@ -4397,12 +4316,12 @@ var flushRuntimeSignalEvaluations = async (evaluations) => {
|
|
|
4397
4316
|
}
|
|
4398
4317
|
await Promise.all([
|
|
4399
4318
|
...[...detailedWrites].map(
|
|
4400
|
-
([bucket, entries]) => (0,
|
|
4319
|
+
([bucket, entries]) => (0, import_redis.setHashJsonFields)(bucket, entries, {
|
|
4401
4320
|
expire: runtimeSignalRetentionTtl
|
|
4402
4321
|
})
|
|
4403
4322
|
),
|
|
4404
4323
|
...[...statsIncrements].map(
|
|
4405
|
-
([bucket, increments]) => (0,
|
|
4324
|
+
([bucket, increments]) => (0, import_redis.incrHashFields)(bucket, increments, {
|
|
4406
4325
|
expire: runtimeSignalRetentionTtl
|
|
4407
4326
|
})
|
|
4408
4327
|
)
|
|
@@ -4418,9 +4337,9 @@ var createRuntimeSignalEvaluationBuffer = () => {
|
|
|
4418
4337
|
const runtimeSignalRetentionTtl = getRuntimeSignalRetentionTtlSeconds();
|
|
4419
4338
|
const signalRefsByBucket = /* @__PURE__ */ new Map();
|
|
4420
4339
|
for (const { userName, signal } of pendingSignals) {
|
|
4421
|
-
const bucket =
|
|
4340
|
+
const bucket = import_redis.redisKeys.runtimeSignalBucket(
|
|
4422
4341
|
userName,
|
|
4423
|
-
(0,
|
|
4342
|
+
(0, import_time.getRuntimeStorageDayKey)(signal.timestamp),
|
|
4424
4343
|
signal.strategy
|
|
4425
4344
|
);
|
|
4426
4345
|
const entries = signalRefsByBucket.get(bucket) ?? [];
|
|
@@ -4432,14 +4351,14 @@ var createRuntimeSignalEvaluationBuffer = () => {
|
|
|
4432
4351
|
}
|
|
4433
4352
|
await Promise.all([
|
|
4434
4353
|
...pendingSignals.map(
|
|
4435
|
-
({ signal }) => (0,
|
|
4436
|
-
|
|
4354
|
+
({ signal }) => (0, import_redis.setData)(
|
|
4355
|
+
import_redis.redisKeys.storeSignal(signal.symbol, signal.signalId),
|
|
4437
4356
|
toStoredRuntimeSignal(signal),
|
|
4438
4357
|
{ expire: runtimeSignalRetentionTtl }
|
|
4439
4358
|
)
|
|
4440
4359
|
),
|
|
4441
4360
|
...[...signalRefsByBucket].map(
|
|
4442
|
-
([bucket, entries]) => (0,
|
|
4361
|
+
([bucket, entries]) => (0, import_redis.setHashJsonFields)(bucket, entries, {
|
|
4443
4362
|
expire: runtimeSignalRetentionTtl
|
|
4444
4363
|
})
|
|
4445
4364
|
)
|
|
@@ -4673,14 +4592,14 @@ var runSignalsDaemon = async ({
|
|
|
4673
4592
|
|
|
4674
4593
|
// src/lib/signals/klineFeed.ts
|
|
4675
4594
|
var import_connectors5 = require("@tradejs/connectors");
|
|
4676
|
-
var
|
|
4595
|
+
var import_logger2 = require("@tradejs/infra/logger");
|
|
4677
4596
|
var import_candles = require("@tradejs/infra/timescale/candles");
|
|
4678
4597
|
|
|
4679
4598
|
// src/lib/marketData/klineEvents.ts
|
|
4680
4599
|
var import_ioredis = __toESM(require("ioredis"));
|
|
4681
|
-
var
|
|
4600
|
+
var import_redis2 = require("@tradejs/infra/redis");
|
|
4682
4601
|
var MARKET_KLINE_CHANNEL = "tradejs:market:kline";
|
|
4683
|
-
var publishMarketKlineEvent = (event) => (0,
|
|
4602
|
+
var publishMarketKlineEvent = (event) => (0, import_redis2.publishData)(MARKET_KLINE_CHANNEL, event);
|
|
4684
4603
|
|
|
4685
4604
|
// src/lib/signals/klineFeed.ts
|
|
4686
4605
|
var FLUSH_DELAY_MS = 100;
|
|
@@ -4734,7 +4653,7 @@ var createSignalsKlineFeed = async ({
|
|
|
4734
4653
|
if (flushTimer || closed) return;
|
|
4735
4654
|
flushTimer = setTimeout(() => {
|
|
4736
4655
|
void flush().catch(
|
|
4737
|
-
(error) =>
|
|
4656
|
+
(error) => import_logger2.logger.error("websocket candle batch flush failed: %s", String(error))
|
|
4738
4657
|
);
|
|
4739
4658
|
}, FLUSH_DELAY_MS);
|
|
4740
4659
|
};
|
|
@@ -4751,7 +4670,7 @@ var createSignalsKlineFeed = async ({
|
|
|
4751
4670
|
confirm: event.confirm,
|
|
4752
4671
|
receivedAt: event.receivedAt
|
|
4753
4672
|
}).catch(
|
|
4754
|
-
(error) =>
|
|
4673
|
+
(error) => import_logger2.logger.warn("websocket candle publish failed: %s", String(error))
|
|
4755
4674
|
);
|
|
4756
4675
|
if (!event.confirm) return;
|
|
4757
4676
|
pending.set(`${event.symbol}:${event.candle.timestamp}`, {
|
|
@@ -4804,8 +4723,8 @@ var createSignalsKlineFeed = async ({
|
|
|
4804
4723
|
};
|
|
4805
4724
|
|
|
4806
4725
|
// src/lib/signals/tickerEvaluator.ts
|
|
4807
|
-
var
|
|
4808
|
-
var
|
|
4726
|
+
var import_strategies4 = require("@tradejs/node/strategies");
|
|
4727
|
+
var import_logger3 = require("@tradejs/infra/logger");
|
|
4809
4728
|
|
|
4810
4729
|
// src/lib/runtimeModeConfig.ts
|
|
4811
4730
|
var buildRuntimeModeStrategyConfig = ({
|
|
@@ -4819,7 +4738,7 @@ var buildRuntimeModeStrategyConfig = ({
|
|
|
4819
4738
|
...strategyConfig,
|
|
4820
4739
|
ENV: env,
|
|
4821
4740
|
MAKE_ORDERS: makeOrders,
|
|
4822
|
-
INTERVAL: interval,
|
|
4741
|
+
INTERVAL: strategyConfig.INTERVAL ?? interval,
|
|
4823
4742
|
...typeof recordRuntimeTrades === "boolean" ? { RECORD_RUNTIME_TRADES: recordRuntimeTrades } : {},
|
|
4824
4743
|
...aiReplayAnalyses?.length ? { AI_REPLAY_ANALYSES: aiReplayAnalyses } : {}
|
|
4825
4744
|
});
|
|
@@ -4883,12 +4802,16 @@ var createSignalsTickerEvaluator = ({
|
|
|
4883
4802
|
const {
|
|
4884
4803
|
strategyName,
|
|
4885
4804
|
configId,
|
|
4805
|
+
releaseVersion,
|
|
4806
|
+
controlState,
|
|
4807
|
+
strategyPackageVersion,
|
|
4808
|
+
runtimePackageVersion,
|
|
4886
4809
|
strategyCreator,
|
|
4887
|
-
releaseCompositionId,
|
|
4888
4810
|
sourceStrategyConfig,
|
|
4889
4811
|
strategyConfig,
|
|
4890
4812
|
strategyResults
|
|
4891
4813
|
} = runtimeStrategy;
|
|
4814
|
+
const runtimeIdentity = releaseVersion ? `v${releaseVersion}` : configId ?? "config";
|
|
4892
4815
|
const symbolResultConfig = strategyResults?.[symbol]?.config ?? null;
|
|
4893
4816
|
const runtimeConfig = buildRuntimeModeStrategyConfig({
|
|
4894
4817
|
strategyConfig,
|
|
@@ -4899,7 +4822,9 @@ var createSignalsTickerEvaluator = ({
|
|
|
4899
4822
|
const runtimeLineage = await buildRuntimeLineage({
|
|
4900
4823
|
projectRoot,
|
|
4901
4824
|
strategyName,
|
|
4902
|
-
|
|
4825
|
+
releaseVersion,
|
|
4826
|
+
strategyPackageVersion,
|
|
4827
|
+
runtimePackageVersion,
|
|
4903
4828
|
config: { configId, strategyConfig, symbolResultConfig },
|
|
4904
4829
|
runContext: {
|
|
4905
4830
|
connectorName: connectorName.toLowerCase(),
|
|
@@ -4915,7 +4840,7 @@ var createSignalsTickerEvaluator = ({
|
|
|
4915
4840
|
symbol,
|
|
4916
4841
|
interval,
|
|
4917
4842
|
strategyName,
|
|
4918
|
-
configId
|
|
4843
|
+
configId: runtimeIdentity
|
|
4919
4844
|
});
|
|
4920
4845
|
const stats = strategyStats.get(strategyName);
|
|
4921
4846
|
const initialLengths = [
|
|
@@ -4940,6 +4865,9 @@ var createSignalsTickerEvaluator = ({
|
|
|
4940
4865
|
userName,
|
|
4941
4866
|
connectorName,
|
|
4942
4867
|
runtimeConfigId: configId,
|
|
4868
|
+
runtimeReleaseVersion: releaseVersion,
|
|
4869
|
+
entriesPaused: controlState === "entries_paused",
|
|
4870
|
+
runtimeLineage,
|
|
4943
4871
|
runtimeConfigSnapshot: {
|
|
4944
4872
|
userConfig: sourceStrategyConfig,
|
|
4945
4873
|
symbolResultConfig
|
|
@@ -4973,7 +4901,7 @@ var createSignalsTickerEvaluator = ({
|
|
|
4973
4901
|
continue;
|
|
4974
4902
|
}
|
|
4975
4903
|
if (evaluation.action.startsWith("rebuilt_")) {
|
|
4976
|
-
|
|
4904
|
+
import_logger3.logger.info(
|
|
4977
4905
|
"Rebuilt signals strategy state (%s): %s %s",
|
|
4978
4906
|
evaluation.action.slice("rebuilt_".length),
|
|
4979
4907
|
strategyName,
|
|
@@ -4992,11 +4920,13 @@ var createSignalsTickerEvaluator = ({
|
|
|
4992
4920
|
strategyName,
|
|
4993
4921
|
symbol,
|
|
4994
4922
|
timestamp: lastCandle.timestamp,
|
|
4995
|
-
runtimeConfigId: configId
|
|
4923
|
+
runtimeConfigId: configId,
|
|
4924
|
+
runtimeReleaseVersion: releaseVersion
|
|
4996
4925
|
}),
|
|
4997
4926
|
userName,
|
|
4998
4927
|
strategy: strategyName,
|
|
4999
4928
|
runtimeConfigId: configId,
|
|
4929
|
+
runtimeReleaseVersion: releaseVersion,
|
|
5000
4930
|
runtimeLineage,
|
|
5001
4931
|
symbol,
|
|
5002
4932
|
interval,
|
|
@@ -5014,11 +4944,15 @@ var createSignalsTickerEvaluator = ({
|
|
|
5014
4944
|
}
|
|
5015
4945
|
if (stats) stats.signals += 1;
|
|
5016
4946
|
signal.runtimeConfigId = configId;
|
|
4947
|
+
signal.runtimeReleaseVersion = releaseVersion;
|
|
5017
4948
|
signal.runtimeLineage = runtimeLineage;
|
|
5018
4949
|
if (configId && configId !== "config" && !signal.signalId.endsWith(`:${configId}`)) {
|
|
5019
4950
|
signal.signalId = `${signal.signalId}:${configId}`;
|
|
5020
4951
|
}
|
|
5021
|
-
|
|
4952
|
+
if (releaseVersion && !signal.signalId.endsWith(`:v${releaseVersion}`)) {
|
|
4953
|
+
signal.signalId = `${signal.signalId}:v${releaseVersion}`;
|
|
4954
|
+
}
|
|
4955
|
+
await (0, import_strategies4.enrichSignalWithBinanceMarketContext)({ signal, env: "CRON" });
|
|
5022
4956
|
if (signal.orderStatus === "skipped" && typeof signal.orderSkipReason === "string" && signal.orderSkipReason.trim()) {
|
|
5023
4957
|
recordStrategyReason(
|
|
5024
4958
|
strategyStats,
|
|
@@ -5034,11 +4968,13 @@ var createSignalsTickerEvaluator = ({
|
|
|
5034
4968
|
strategyName,
|
|
5035
4969
|
symbol,
|
|
5036
4970
|
timestamp: lastCandle.timestamp,
|
|
5037
|
-
runtimeConfigId: configId
|
|
4971
|
+
runtimeConfigId: configId,
|
|
4972
|
+
runtimeReleaseVersion: releaseVersion
|
|
5038
4973
|
}),
|
|
5039
4974
|
userName,
|
|
5040
4975
|
strategy: strategyName,
|
|
5041
4976
|
runtimeConfigId: configId,
|
|
4977
|
+
runtimeReleaseVersion: releaseVersion,
|
|
5042
4978
|
runtimeLineage,
|
|
5043
4979
|
symbol,
|
|
5044
4980
|
interval,
|
|
@@ -5058,7 +4994,7 @@ var createSignalsTickerEvaluator = ({
|
|
|
5058
4994
|
...signal.aiAnalysis ? { aiAnalysis: signal.aiAnalysis } : {},
|
|
5059
4995
|
...signal.ml ? { ml: signal.ml } : {}
|
|
5060
4996
|
});
|
|
5061
|
-
|
|
4997
|
+
import_logger3.logger.info("Signal found %s by strategy %s", symbol, strategyName);
|
|
5062
4998
|
}
|
|
5063
4999
|
return strategySignals;
|
|
5064
5000
|
};
|
|
@@ -5101,12 +5037,12 @@ var createSignalsRunner = (config2) => {
|
|
|
5101
5037
|
const createDefaultSignalsLifecycle = (runtimeInterval = interval) => createSignalsStrategyLifecycle({
|
|
5102
5038
|
intervalMs: Number(runtimeInterval) * 6e4,
|
|
5103
5039
|
maxLiveBars: resolveSignalsDaemonMaxLiveBars(runtimeInterval),
|
|
5104
|
-
releaseState:
|
|
5040
|
+
releaseState: import_strategies5.releaseStrategyReplayCache
|
|
5105
5041
|
});
|
|
5106
5042
|
const timeOperation2 = (label, operation) => timeOperation(
|
|
5107
5043
|
label,
|
|
5108
5044
|
operation,
|
|
5109
|
-
(message) =>
|
|
5045
|
+
(message) => import_logger4.logger.info(import_chalk7.default.gray(message))
|
|
5110
5046
|
);
|
|
5111
5047
|
const formatSlowSignalsWarning = (params) => [
|
|
5112
5048
|
"<b>Slow yarn signals run</b>",
|
|
@@ -5120,7 +5056,7 @@ var createSignalsRunner = (config2) => {
|
|
|
5120
5056
|
if (connectorName) {
|
|
5121
5057
|
return connectorName;
|
|
5122
5058
|
}
|
|
5123
|
-
|
|
5059
|
+
import_logger4.logger.warn(
|
|
5124
5060
|
'Unknown connector "%s". Fallback to %s.',
|
|
5125
5061
|
String(value || "").trim() || String(value),
|
|
5126
5062
|
import_connectors6.DEFAULT_CONNECTOR_NAME
|
|
@@ -5136,12 +5072,17 @@ var createSignalsRunner = (config2) => {
|
|
|
5136
5072
|
throw new Error(`Runtime deployment is disabled: ${deployment.id}`);
|
|
5137
5073
|
}
|
|
5138
5074
|
const requestedRuntimeInterval = scope.interval ?? interval;
|
|
5139
|
-
const
|
|
5075
|
+
const versionedDeployment = Boolean(
|
|
5076
|
+
deployment?.strategies.some(
|
|
5077
|
+
(strategy) => strategy.releaseVersion != null
|
|
5078
|
+
)
|
|
5079
|
+
);
|
|
5080
|
+
const runtimeInterval = versionedDeployment ? requestedRuntimeInterval : deployment?.interval ?? requestedRuntimeInterval;
|
|
5140
5081
|
const runtimeIntervalMs = Number(runtimeInterval) * 6e4;
|
|
5141
5082
|
if (!Number.isFinite(runtimeIntervalMs) || runtimeIntervalMs <= 0) {
|
|
5142
5083
|
throw new Error(`Invalid runtime timeframe: ${runtimeInterval}`);
|
|
5143
5084
|
}
|
|
5144
|
-
if (deployment && String(deployment.interval) !== String(requestedRuntimeInterval)) {
|
|
5085
|
+
if (deployment && !versionedDeployment && String(deployment.interval) !== String(requestedRuntimeInterval)) {
|
|
5145
5086
|
throw new Error(
|
|
5146
5087
|
`Deployment ${deployment.id} requires timeframe ${deployment.interval}; received ${requestedRuntimeInterval}`
|
|
5147
5088
|
);
|
|
@@ -5149,7 +5090,7 @@ var createSignalsRunner = (config2) => {
|
|
|
5149
5090
|
const connectorName = await resolveSignalsConnectorName(
|
|
5150
5091
|
deployment?.connectorName ?? scope.connectorName ?? config2.connectorName
|
|
5151
5092
|
);
|
|
5152
|
-
const universe = deployment?.universe ?? scope.universe ?? config2.universe;
|
|
5093
|
+
const universe = versionedDeployment ? scope.universe ?? config2.universe : deployment?.universe ?? scope.universe ?? config2.universe;
|
|
5153
5094
|
const requestedAccountId = deployment?.accountId ?? scope.accountId ?? config2.accountId;
|
|
5154
5095
|
const connectorFactory = await (0, import_connectors6.getConnectorCreatorByName)(
|
|
5155
5096
|
connectorName,
|
|
@@ -5170,7 +5111,7 @@ var createSignalsRunner = (config2) => {
|
|
|
5170
5111
|
userName: config2.userName,
|
|
5171
5112
|
projectRoot,
|
|
5172
5113
|
shouldUseDedicatedReferences: universe === "crypto" && connectorName.toLowerCase() === import_connectors6.DEFAULT_CONNECTOR_NAME.toLowerCase(),
|
|
5173
|
-
warn: (message) =>
|
|
5114
|
+
warn: (message) => import_logger4.logger.warn(message)
|
|
5174
5115
|
});
|
|
5175
5116
|
return {
|
|
5176
5117
|
connectorName,
|
|
@@ -5241,8 +5182,8 @@ var createSignalsRunner = (config2) => {
|
|
|
5241
5182
|
}
|
|
5242
5183
|
const projectConfig = await (0, import_cli2.loadTradejsConfig)(projectRoot);
|
|
5243
5184
|
projectHooks = projectConfig.hooks;
|
|
5244
|
-
const currentTimestamp = (0,
|
|
5245
|
-
const preloadStart = (0,
|
|
5185
|
+
const currentTimestamp = (0, import_time2.getTimestamp)();
|
|
5186
|
+
const preloadStart = (0, import_time2.getTimestamp)(import_constants3.SIGNALS_CLI_PRELOAD_DAYS);
|
|
5246
5187
|
if (!config2.cacheOnly && session.klineFeed) {
|
|
5247
5188
|
const expectedSymbols = universe === "crypto" ? [.../* @__PURE__ */ new Set([...tickers, "BTCUSDT", "ETHUSDT"])] : tickers;
|
|
5248
5189
|
session.klineFeed.setSubscriptions(expectedSymbols);
|
|
@@ -5256,7 +5197,7 @@ var createSignalsRunner = (config2) => {
|
|
|
5256
5197
|
})
|
|
5257
5198
|
);
|
|
5258
5199
|
await session.klineFeed.flush();
|
|
5259
|
-
|
|
5200
|
+
import_logger4.logger.info(
|
|
5260
5201
|
import_chalk7.default.gray(
|
|
5261
5202
|
`websocket candles: ready=${expectedSymbols.length - missingSymbols.length}/${expectedSymbols.length} missing=${missingSymbols.length}`
|
|
5262
5203
|
)
|
|
@@ -5268,7 +5209,7 @@ var createSignalsRunner = (config2) => {
|
|
|
5268
5209
|
symbols: missingSymbols,
|
|
5269
5210
|
preloadDays: import_constants3.SIGNALS_CLI_PRELOAD_DAYS,
|
|
5270
5211
|
universe,
|
|
5271
|
-
log: (message) =>
|
|
5212
|
+
log: (message) => import_logger4.logger.info(import_chalk7.default.gray(message))
|
|
5272
5213
|
});
|
|
5273
5214
|
await updateBtcReferenceHistory({
|
|
5274
5215
|
marketConnector,
|
|
@@ -5276,7 +5217,7 @@ var createSignalsRunner = (config2) => {
|
|
|
5276
5217
|
interval: interval2,
|
|
5277
5218
|
preloadDays: import_constants3.SIGNALS_CLI_PRELOAD_DAYS,
|
|
5278
5219
|
universe,
|
|
5279
|
-
log: (message) =>
|
|
5220
|
+
log: (message) => import_logger4.logger.info(import_chalk7.default.gray(message))
|
|
5280
5221
|
});
|
|
5281
5222
|
} else if (!config2.cacheOnly) {
|
|
5282
5223
|
await updateMarketHistoryWithBtcReferences({
|
|
@@ -5287,7 +5228,7 @@ var createSignalsRunner = (config2) => {
|
|
|
5287
5228
|
symbols: tickers,
|
|
5288
5229
|
preloadDays: import_constants3.SIGNALS_CLI_PRELOAD_DAYS,
|
|
5289
5230
|
universe,
|
|
5290
|
-
log: (message) =>
|
|
5231
|
+
log: (message) => import_logger4.logger.info(import_chalk7.default.gray(message))
|
|
5291
5232
|
});
|
|
5292
5233
|
}
|
|
5293
5234
|
await prepareMarketContextForRun({
|
|
@@ -5301,7 +5242,7 @@ var createSignalsRunner = (config2) => {
|
|
|
5301
5242
|
endMs: currentTimestamp,
|
|
5302
5243
|
preloadStartMs: preloadStart,
|
|
5303
5244
|
cacheOnly: config2.cacheOnly,
|
|
5304
|
-
log: (message) =>
|
|
5245
|
+
log: (message) => import_logger4.logger.info(import_chalk7.default.gray(message))
|
|
5305
5246
|
});
|
|
5306
5247
|
if (config2.updateOnly) {
|
|
5307
5248
|
return;
|
|
@@ -5357,7 +5298,7 @@ var createSignalsRunner = (config2) => {
|
|
|
5357
5298
|
const primaryEthByTimestamp = new Map(
|
|
5358
5299
|
primaryEthClosedData.map((candle) => [candle.timestamp, candle])
|
|
5359
5300
|
);
|
|
5360
|
-
const runtimeStrategies = await
|
|
5301
|
+
const runtimeStrategies = await (0, import_runtimeStrategies.loadResolvedRuntimeStrategies)({
|
|
5361
5302
|
userName: config2.userName,
|
|
5362
5303
|
projectRoot,
|
|
5363
5304
|
deployment,
|
|
@@ -5368,7 +5309,7 @@ var createSignalsRunner = (config2) => {
|
|
|
5368
5309
|
});
|
|
5369
5310
|
if (!runtimeStrategies.length) {
|
|
5370
5311
|
lifecycle.clear();
|
|
5371
|
-
|
|
5312
|
+
import_logger4.logger.warn(
|
|
5372
5313
|
"No strategy configs found by users:%s:strategies:*:config",
|
|
5373
5314
|
config2.userName
|
|
5374
5315
|
);
|
|
@@ -5378,7 +5319,7 @@ var createSignalsRunner = (config2) => {
|
|
|
5378
5319
|
new Set(
|
|
5379
5320
|
tickers.flatMap(
|
|
5380
5321
|
(symbol) => runtimeStrategies.map(
|
|
5381
|
-
({ strategyName, configId }) => buildSignalsStrategyLifecycleKey({
|
|
5322
|
+
({ strategyName, configId, releaseVersion }) => buildSignalsStrategyLifecycleKey({
|
|
5382
5323
|
connectorName,
|
|
5383
5324
|
universe: sessionUniverse,
|
|
5384
5325
|
accountId,
|
|
@@ -5386,13 +5327,13 @@ var createSignalsRunner = (config2) => {
|
|
|
5386
5327
|
symbol,
|
|
5387
5328
|
interval: interval2,
|
|
5388
5329
|
strategyName,
|
|
5389
|
-
configId
|
|
5330
|
+
configId: releaseVersion ? `v${releaseVersion}` : configId
|
|
5390
5331
|
})
|
|
5391
5332
|
)
|
|
5392
5333
|
)
|
|
5393
5334
|
)
|
|
5394
5335
|
);
|
|
5395
|
-
|
|
5336
|
+
import_logger4.logger.info(
|
|
5396
5337
|
import_chalk7.default.yellow(
|
|
5397
5338
|
`loaded strategies (user=${config2.userName}): ${runtimeStrategies.map((s) => s.strategyName).join(", ")}`
|
|
5398
5339
|
)
|
|
@@ -5415,7 +5356,7 @@ var createSignalsRunner = (config2) => {
|
|
|
5415
5356
|
afterSignalsHookContext
|
|
5416
5357
|
);
|
|
5417
5358
|
if (beforeSignalsResult?.abort === true) {
|
|
5418
|
-
|
|
5359
|
+
import_logger4.logger.info(
|
|
5419
5360
|
"signals aborted before ticker evaluation: %s",
|
|
5420
5361
|
beforeSignalsResult.reason ?? "PROJECT_BEFORE_SIGNALS_ABORTED"
|
|
5421
5362
|
);
|
|
@@ -5429,9 +5370,9 @@ var createSignalsRunner = (config2) => {
|
|
|
5429
5370
|
width: 30
|
|
5430
5371
|
}
|
|
5431
5372
|
);
|
|
5432
|
-
|
|
5373
|
+
import_logger4.logger.info(import_chalk7.default.yellow(`tickers: ${tickers.length}`));
|
|
5433
5374
|
const signalsParallel = resolvePositiveInteger(config2.parallel, 4);
|
|
5434
|
-
|
|
5375
|
+
import_logger4.logger.info(import_chalk7.default.yellow(`signal workers: ${signalsParallel}`));
|
|
5435
5376
|
const evaluateTicker = createSignalsTickerEvaluator({
|
|
5436
5377
|
userName: config2.userName,
|
|
5437
5378
|
makeOrders: config2.makeOrders,
|
|
@@ -5488,7 +5429,7 @@ var createSignalsRunner = (config2) => {
|
|
|
5488
5429
|
config2.userName
|
|
5489
5430
|
);
|
|
5490
5431
|
}
|
|
5491
|
-
|
|
5432
|
+
import_logger4.logger.info(
|
|
5492
5433
|
JSON.stringify(
|
|
5493
5434
|
signals3.map((s) => s.symbol),
|
|
5494
5435
|
null,
|
|
@@ -5501,7 +5442,7 @@ var createSignalsRunner = (config2) => {
|
|
|
5501
5442
|
} catch (error) {
|
|
5502
5443
|
status = "failed";
|
|
5503
5444
|
failureMessage = error?.message || String(error);
|
|
5504
|
-
|
|
5445
|
+
import_logger4.logger.error(
|
|
5505
5446
|
"signals failed: %s",
|
|
5506
5447
|
error?.message || String(error)
|
|
5507
5448
|
);
|
|
@@ -5510,7 +5451,7 @@ var createSignalsRunner = (config2) => {
|
|
|
5510
5451
|
try {
|
|
5511
5452
|
await runtimeSignalEvaluations.flush();
|
|
5512
5453
|
} catch (error) {
|
|
5513
|
-
|
|
5454
|
+
import_logger4.logger.error(
|
|
5514
5455
|
"runtime signal evaluation flush failed: %s",
|
|
5515
5456
|
error?.message || String(error)
|
|
5516
5457
|
);
|
|
@@ -5538,7 +5479,7 @@ var createSignalsRunner = (config2) => {
|
|
|
5538
5479
|
durationMs
|
|
5539
5480
|
});
|
|
5540
5481
|
} catch (error) {
|
|
5541
|
-
|
|
5482
|
+
import_logger4.logger.error(
|
|
5542
5483
|
"afterSignals hook failed: %s",
|
|
5543
5484
|
error?.message || String(error)
|
|
5544
5485
|
);
|
|
@@ -5555,24 +5496,24 @@ var createSignalsRunner = (config2) => {
|
|
|
5555
5496
|
{ userName: config2.userName }
|
|
5556
5497
|
);
|
|
5557
5498
|
} catch (error) {
|
|
5558
|
-
|
|
5499
|
+
import_logger4.logger.error(
|
|
5559
5500
|
"slow signals warning failed: %s",
|
|
5560
5501
|
error?.message || String(error)
|
|
5561
5502
|
);
|
|
5562
5503
|
}
|
|
5563
5504
|
}
|
|
5564
|
-
|
|
5505
|
+
import_logger4.logger.info(
|
|
5565
5506
|
import_chalk7.default.yellow(
|
|
5566
5507
|
`signals ${status} in ${formatDuration2(durationMs)} (found=${signals3.length})`
|
|
5567
5508
|
)
|
|
5568
5509
|
);
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5510
|
+
import_logger4.logger.info("");
|
|
5511
|
+
import_logger4.logger.info("");
|
|
5512
|
+
import_logger4.logger.info("");
|
|
5572
5513
|
}
|
|
5573
5514
|
};
|
|
5574
5515
|
const loadConfiguredSignalsScopes = async (deployment) => {
|
|
5575
|
-
const configuredStrategies = await
|
|
5516
|
+
const configuredStrategies = await (0, import_runtimeStrategies.loadResolvedRuntimeStrategies)({
|
|
5576
5517
|
userName: config2.userName,
|
|
5577
5518
|
projectRoot,
|
|
5578
5519
|
deployment,
|
|
@@ -5600,10 +5541,14 @@ var createSignalsRunner = (config2) => {
|
|
|
5600
5541
|
};
|
|
5601
5542
|
const hasExplicitSignalsScope = () => Boolean(config2.hasExplicitScope);
|
|
5602
5543
|
const signalsConfiguredScopesOnce2 = async () => {
|
|
5603
|
-
if (config2.updateOnly || config2.showTickersList ||
|
|
5544
|
+
if (config2.updateOnly || config2.showTickersList || hasExplicitSignalsScope()) {
|
|
5604
5545
|
return signals2();
|
|
5605
5546
|
}
|
|
5606
|
-
const
|
|
5547
|
+
const configuredDeployment = config2.deploymentId ? await (0, import_runtimeDeployments.getRuntimeDeployment)(config2.userName, config2.deploymentId) : null;
|
|
5548
|
+
if (config2.deploymentId && !configuredDeployment) {
|
|
5549
|
+
throw new Error(`Runtime deployment not found: ${config2.deploymentId}`);
|
|
5550
|
+
}
|
|
5551
|
+
const scopes = await loadConfiguredSignalsScopes(configuredDeployment);
|
|
5607
5552
|
if (!scopes.size) return signals2();
|
|
5608
5553
|
for (const scope of scopes.values()) {
|
|
5609
5554
|
const session = await createSignalsSession2(
|
|
@@ -5632,14 +5577,14 @@ var createSignalsRunner = (config2) => {
|
|
|
5632
5577
|
const sessions = /* @__PURE__ */ new Map();
|
|
5633
5578
|
const lastBoundaryByScope = /* @__PURE__ */ new Map();
|
|
5634
5579
|
const stop = (signalName) => {
|
|
5635
|
-
|
|
5580
|
+
import_logger4.logger.info("signals daemon stopping by %s", signalName);
|
|
5636
5581
|
abortController.abort();
|
|
5637
5582
|
};
|
|
5638
5583
|
const stopOnSigint = () => stop("SIGINT");
|
|
5639
5584
|
const stopOnSigterm = () => stop("SIGTERM");
|
|
5640
5585
|
process.once("SIGINT", stopOnSigint);
|
|
5641
5586
|
process.once("SIGTERM", stopOnSigterm);
|
|
5642
|
-
|
|
5587
|
+
import_logger4.logger.info(
|
|
5643
5588
|
"signals daemon started (config-driven scopes, fallback interval=%s)",
|
|
5644
5589
|
interval
|
|
5645
5590
|
);
|
|
@@ -5680,7 +5625,7 @@ var createSignalsRunner = (config2) => {
|
|
|
5680
5625
|
interval: session.interval,
|
|
5681
5626
|
universe: session.universe
|
|
5682
5627
|
});
|
|
5683
|
-
|
|
5628
|
+
import_logger4.logger.info(
|
|
5684
5629
|
"Bybit websocket candle feed enabled (account=%s, universe=%s, interval=%s)",
|
|
5685
5630
|
session.accountId ?? "default",
|
|
5686
5631
|
session.universe,
|
|
@@ -5702,7 +5647,7 @@ var createSignalsRunner = (config2) => {
|
|
|
5702
5647
|
(sum, session) => sum + session.lifecycle.size(),
|
|
5703
5648
|
0
|
|
5704
5649
|
);
|
|
5705
|
-
|
|
5650
|
+
import_logger4.logger.info(
|
|
5706
5651
|
"signals daemon resources: rss=%sMB heapUsed=%sMB heapTotal=%sMB stateKeys=%s scopes=%s",
|
|
5707
5652
|
(memory.rss / 1024 / 1024).toFixed(1),
|
|
5708
5653
|
(memory.heapUsed / 1024 / 1024).toFixed(1),
|
|
@@ -5712,7 +5657,7 @@ var createSignalsRunner = (config2) => {
|
|
|
5712
5657
|
);
|
|
5713
5658
|
},
|
|
5714
5659
|
onCycleError: (error) => {
|
|
5715
|
-
|
|
5660
|
+
import_logger4.logger.error(
|
|
5716
5661
|
"signals daemon cycle failed: %s",
|
|
5717
5662
|
error?.message || String(error)
|
|
5718
5663
|
);
|
|
@@ -5783,16 +5728,9 @@ import_args.default.option(["A", "account"], "Trading account id");
|
|
|
5783
5728
|
import_args.default.option(["D", "deployment"], "Runtime deployment id");
|
|
5784
5729
|
var flags = import_args.default.parse(process.argv);
|
|
5785
5730
|
var hasExplicitScope = process.argv.some(
|
|
5786
|
-
(argument) => [
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
"-V",
|
|
5790
|
-
"--universe",
|
|
5791
|
-
"-A",
|
|
5792
|
-
"--account",
|
|
5793
|
-
"-D",
|
|
5794
|
-
"--deployment"
|
|
5795
|
-
].some((option) => argument === option || argument.startsWith(`${option}=`))
|
|
5731
|
+
(argument) => ["-f", "--timeframe", "-V", "--universe", "-A", "--account"].some(
|
|
5732
|
+
(option) => argument === option || argument.startsWith(`${option}=`)
|
|
5733
|
+
)
|
|
5796
5734
|
);
|
|
5797
5735
|
var config = {
|
|
5798
5736
|
projectRoot: String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd(),
|