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