@tradejs/cli 2.0.8 → 2.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +297 -134
- package/dist/lib/aiPocketSearchCli.js +54 -0
- package/dist/lib/marketContextPrepare.js +2 -2
- package/dist/scripts/aiPocketSearch.js +56 -8
- package/dist/scripts/backtest.js +2 -2
- package/dist/scripts/replay.js +2 -2
- package/dist/scripts/replayRunner.js +2 -2
- package/dist/scripts/runtimeParity.js +2 -2
- package/dist/scripts/signals.js +233 -125
- package/dist/scripts/signalsDaemon.js +233 -125
- package/package.json +9 -9
package/dist/cli.js
CHANGED
|
@@ -4868,6 +4868,37 @@ var init_aiPocketSearch = __esm({
|
|
|
4868
4868
|
}
|
|
4869
4869
|
});
|
|
4870
4870
|
|
|
4871
|
+
// src/lib/aiPocketSearchCli.ts
|
|
4872
|
+
var AI_POCKET_SEARCH_CLI_DECIMAL_DEFAULTS, readAiPocketSearchCliOption;
|
|
4873
|
+
var init_aiPocketSearchCli = __esm({
|
|
4874
|
+
"src/lib/aiPocketSearchCli.ts"() {
|
|
4875
|
+
"use strict";
|
|
4876
|
+
AI_POCKET_SEARCH_CLI_DECIMAL_DEFAULTS = {
|
|
4877
|
+
minProfitFactor: "1.2",
|
|
4878
|
+
minWinRate: "0",
|
|
4879
|
+
minTotalProfit: "0",
|
|
4880
|
+
validationSplit: "0.25"
|
|
4881
|
+
};
|
|
4882
|
+
readAiPocketSearchCliOption = ({
|
|
4883
|
+
argv,
|
|
4884
|
+
longName,
|
|
4885
|
+
shortName
|
|
4886
|
+
}) => {
|
|
4887
|
+
const longPrefix = `--${longName}=`;
|
|
4888
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
4889
|
+
const arg = argv[index];
|
|
4890
|
+
if (arg.startsWith(longPrefix)) {
|
|
4891
|
+
return arg.slice(longPrefix.length);
|
|
4892
|
+
}
|
|
4893
|
+
if (arg === `--${longName}` || shortName != null && arg === `-${shortName}`) {
|
|
4894
|
+
return argv[index + 1];
|
|
4895
|
+
}
|
|
4896
|
+
}
|
|
4897
|
+
return void 0;
|
|
4898
|
+
};
|
|
4899
|
+
}
|
|
4900
|
+
});
|
|
4901
|
+
|
|
4871
4902
|
// src/scripts/aiPocketSearch.ts
|
|
4872
4903
|
var aiPocketSearch_exports = {};
|
|
4873
4904
|
__export(aiPocketSearch_exports, {
|
|
@@ -4888,6 +4919,7 @@ var init_aiPocketSearch2 = __esm({
|
|
|
4888
4919
|
init_aiTrainMetrics();
|
|
4889
4920
|
init_aiTrainOptions();
|
|
4890
4921
|
init_aiPocketSearch();
|
|
4922
|
+
init_aiPocketSearchCli();
|
|
4891
4923
|
ListIt2 = require_list_it();
|
|
4892
4924
|
import_args3.default.example(
|
|
4893
4925
|
"yarn ai-pocket-search --strategy LiquidityZones -n 0 --maxDepth 2 --minSupport 25",
|
|
@@ -4941,17 +4973,17 @@ var init_aiPocketSearch2 = __esm({
|
|
|
4941
4973
|
import_args3.default.option(
|
|
4942
4974
|
["F", "minProfitFactor"],
|
|
4943
4975
|
"Minimum profit factor required for positive pockets",
|
|
4944
|
-
|
|
4976
|
+
AI_POCKET_SEARCH_CLI_DECIMAL_DEFAULTS.minProfitFactor
|
|
4945
4977
|
);
|
|
4946
4978
|
import_args3.default.option(
|
|
4947
4979
|
["W", "minWinRate"],
|
|
4948
4980
|
"Minimum win rate required for positive pockets",
|
|
4949
|
-
|
|
4981
|
+
AI_POCKET_SEARCH_CLI_DECIMAL_DEFAULTS.minWinRate
|
|
4950
4982
|
);
|
|
4951
4983
|
import_args3.default.option(
|
|
4952
4984
|
["R", "minTotalProfit"],
|
|
4953
4985
|
"Minimum total PnL required for positive pockets",
|
|
4954
|
-
|
|
4986
|
+
AI_POCKET_SEARCH_CLI_DECIMAL_DEFAULTS.minTotalProfit
|
|
4955
4987
|
);
|
|
4956
4988
|
import_args3.default.option(
|
|
4957
4989
|
["a", "maxAtomicPredicates"],
|
|
@@ -4966,7 +4998,7 @@ var init_aiPocketSearch2 = __esm({
|
|
|
4966
4998
|
import_args3.default.option(
|
|
4967
4999
|
["V", "validationSplit"],
|
|
4968
5000
|
"Trailing time-ordered scope share reserved for validation (0 disables)",
|
|
4969
|
-
|
|
5001
|
+
AI_POCKET_SEARCH_CLI_DECIMAL_DEFAULTS.validationSplit
|
|
4970
5002
|
);
|
|
4971
5003
|
import_args3.default.option(
|
|
4972
5004
|
["N", "minValidationSupport"],
|
|
@@ -5383,17 +5415,40 @@ var init_aiPocketSearch2 = __esm({
|
|
|
5383
5415
|
const maxDepth = normalizePositiveInt(flags3.maxDepth, 2);
|
|
5384
5416
|
const minSupport = normalizePositiveInt(flags3.minSupport, 20);
|
|
5385
5417
|
const minProfitFactor = normalizeNonNegativeNumber(
|
|
5386
|
-
|
|
5418
|
+
readAiPocketSearchCliOption({
|
|
5419
|
+
argv: process.argv,
|
|
5420
|
+
longName: "minProfitFactor",
|
|
5421
|
+
shortName: "F"
|
|
5422
|
+
}) ?? flags3.minProfitFactor,
|
|
5387
5423
|
1.2
|
|
5388
5424
|
);
|
|
5389
|
-
const minWinRate = normalizeNonNegativeNumber(
|
|
5390
|
-
|
|
5425
|
+
const minWinRate = normalizeNonNegativeNumber(
|
|
5426
|
+
readAiPocketSearchCliOption({
|
|
5427
|
+
argv: process.argv,
|
|
5428
|
+
longName: "minWinRate",
|
|
5429
|
+
shortName: "W"
|
|
5430
|
+
}) ?? flags3.minWinRate,
|
|
5431
|
+
0
|
|
5432
|
+
);
|
|
5433
|
+
const minTotalProfitValue = readAiPocketSearchCliOption({
|
|
5434
|
+
argv: process.argv,
|
|
5435
|
+
longName: "minTotalProfit",
|
|
5436
|
+
shortName: "R"
|
|
5437
|
+
}) ?? flags3.minTotalProfit;
|
|
5438
|
+
const minTotalProfit = Number.isFinite(Number(minTotalProfitValue)) ? Number(minTotalProfitValue) : 0;
|
|
5391
5439
|
const maxAtomicPredicates = normalizePositiveInt(
|
|
5392
5440
|
flags3.maxAtomicPredicates,
|
|
5393
5441
|
180
|
|
5394
5442
|
);
|
|
5395
5443
|
const maxCombinations = normalizePositiveInt(flags3.maxCombinations, 6e4);
|
|
5396
|
-
const validationSplit = hasCliOption2("validationSplit", "V") ? normalizeRatio(
|
|
5444
|
+
const validationSplit = hasCliOption2("validationSplit", "V") ? normalizeRatio(
|
|
5445
|
+
readAiPocketSearchCliOption({
|
|
5446
|
+
argv: process.argv,
|
|
5447
|
+
longName: "validationSplit",
|
|
5448
|
+
shortName: "V"
|
|
5449
|
+
}) ?? flags3.validationSplit,
|
|
5450
|
+
0.25
|
|
5451
|
+
) : 0.25;
|
|
5397
5452
|
const explicitMinValidationSupport = normalizeInt(
|
|
5398
5453
|
flags3.minValidationSupport,
|
|
5399
5454
|
0
|
|
@@ -10947,7 +11002,7 @@ var init_marketContextPrepare = __esm({
|
|
|
10947
11002
|
userName: params.userName,
|
|
10948
11003
|
startMs: params.startMs,
|
|
10949
11004
|
endMs: params.endMs,
|
|
10950
|
-
preloadStartMs: params.preloadStartMs
|
|
11005
|
+
preloadStartMs: params.mode === "signals" ? void 0 : params.preloadStartMs
|
|
10951
11006
|
});
|
|
10952
11007
|
buildBinanceMarketBackfillParams = (params) => ({
|
|
10953
11008
|
userName: params.userName,
|
|
@@ -10956,7 +11011,7 @@ var init_marketContextPrepare = __esm({
|
|
|
10956
11011
|
interval: params.interval,
|
|
10957
11012
|
startMs: params.startMs,
|
|
10958
11013
|
endMs: params.endMs,
|
|
10959
|
-
preloadStartMs: params.preloadStartMs
|
|
11014
|
+
preloadStartMs: params.mode === "signals" ? void 0 : params.preloadStartMs
|
|
10960
11015
|
});
|
|
10961
11016
|
buildDerivativesBackfillParams = (params) => ({
|
|
10962
11017
|
userName: params.userName,
|
|
@@ -28353,6 +28408,7 @@ var init_runtimeStrategies = __esm({
|
|
|
28353
28408
|
universe: configUniverse,
|
|
28354
28409
|
accountId: effectiveAccountId,
|
|
28355
28410
|
strategyCreator,
|
|
28411
|
+
sourceStrategyConfig: strategyConfig,
|
|
28356
28412
|
strategyConfig: {
|
|
28357
28413
|
...strategyConfig,
|
|
28358
28414
|
...deploymentStrategy?.config,
|
|
@@ -28652,7 +28708,7 @@ var init_runtimeLineage = __esm({
|
|
|
28652
28708
|
});
|
|
28653
28709
|
|
|
28654
28710
|
// src/lib/signals/evaluations.ts
|
|
28655
|
-
var import_redis19, runtimeLineageScopeCache, runtimeLineageScopeCacheDayKey, buildRuntimeSignalEvaluationId,
|
|
28711
|
+
var import_redis19, runtimeLineageScopeCache, runtimeLineageScopeCacheDayKey, runtimeLineageScopeCacheLoaded, buildRuntimeSignalEvaluationId, buildLineageField, flushRuntimeSignalEvaluations, createRuntimeSignalEvaluationBuffer;
|
|
28656
28712
|
var init_evaluations = __esm({
|
|
28657
28713
|
"src/lib/signals/evaluations.ts"() {
|
|
28658
28714
|
"use strict";
|
|
@@ -28661,79 +28717,140 @@ var init_evaluations = __esm({
|
|
|
28661
28717
|
init_runtimeLineage();
|
|
28662
28718
|
runtimeLineageScopeCache = /* @__PURE__ */ new Map();
|
|
28663
28719
|
runtimeLineageScopeCacheDayKey = "";
|
|
28720
|
+
runtimeLineageScopeCacheLoaded = false;
|
|
28664
28721
|
buildRuntimeSignalEvaluationId = ({
|
|
28665
28722
|
strategyName,
|
|
28666
28723
|
symbol,
|
|
28667
28724
|
timestamp,
|
|
28668
28725
|
runtimeConfigId
|
|
28669
28726
|
}) => runtimeConfigId && runtimeConfigId !== "config" ? [strategyName, runtimeConfigId, symbol, timestamp].join(":") : [strategyName, symbol, timestamp].join(":");
|
|
28670
|
-
|
|
28671
|
-
|
|
28672
|
-
|
|
28673
|
-
|
|
28674
|
-
|
|
28727
|
+
buildLineageField = (scope) => [
|
|
28728
|
+
scope.strategy,
|
|
28729
|
+
scope.runtimeConfigId ?? "config",
|
|
28730
|
+
scope.symbol,
|
|
28731
|
+
runtimeLineageKey(scope.lineage)
|
|
28732
|
+
].join(":");
|
|
28733
|
+
flushRuntimeSignalEvaluations = async (evaluations) => {
|
|
28734
|
+
if (evaluations.length === 0) return;
|
|
28735
|
+
const evaluationsByDay = /* @__PURE__ */ new Map();
|
|
28736
|
+
for (const evaluation of evaluations) {
|
|
28737
|
+
const dayKey = (0, import_time6.getRuntimeStorageDayKey)(evaluation.timestamp);
|
|
28738
|
+
const dayEvaluations = evaluationsByDay.get(dayKey) ?? [];
|
|
28739
|
+
dayEvaluations.push(evaluation);
|
|
28740
|
+
evaluationsByDay.set(dayKey, dayEvaluations);
|
|
28675
28741
|
}
|
|
28676
28742
|
const runtimeSignalRetentionTtl = getRuntimeSignalRetentionTtlSeconds();
|
|
28677
|
-
|
|
28678
|
-
|
|
28679
|
-
|
|
28680
|
-
|
|
28681
|
-
|
|
28682
|
-
|
|
28683
|
-
].join(":");
|
|
28743
|
+
for (const [dayKey, dayEvaluations] of evaluationsByDay) {
|
|
28744
|
+
if (runtimeLineageScopeCacheDayKey !== dayKey) {
|
|
28745
|
+
runtimeLineageScopeCache.clear();
|
|
28746
|
+
runtimeLineageScopeCacheDayKey = dayKey;
|
|
28747
|
+
runtimeLineageScopeCacheLoaded = false;
|
|
28748
|
+
}
|
|
28684
28749
|
const lineageBucket = import_redis19.redisKeys.runtimeLineageScopeBucket(
|
|
28685
|
-
|
|
28750
|
+
dayEvaluations[0].userName,
|
|
28686
28751
|
dayKey
|
|
28687
28752
|
);
|
|
28688
|
-
const
|
|
28689
|
-
|
|
28690
|
-
lineageBucket,
|
|
28691
|
-
lineageField
|
|
28753
|
+
const lineageEvaluations = dayEvaluations.filter(
|
|
28754
|
+
(evaluation) => evaluation.runtimeLineage != null
|
|
28692
28755
|
);
|
|
28693
|
-
|
|
28694
|
-
|
|
28695
|
-
|
|
28696
|
-
|
|
28697
|
-
|
|
28698
|
-
|
|
28699
|
-
|
|
28700
|
-
|
|
28701
|
-
|
|
28702
|
-
|
|
28703
|
-
|
|
28704
|
-
evaluation.
|
|
28705
|
-
|
|
28706
|
-
|
|
28707
|
-
|
|
28708
|
-
|
|
28709
|
-
|
|
28710
|
-
|
|
28711
|
-
|
|
28712
|
-
|
|
28713
|
-
|
|
28714
|
-
|
|
28756
|
+
if (lineageEvaluations.length > 0 && !runtimeLineageScopeCacheLoaded) {
|
|
28757
|
+
const storedScopes = await (0, import_redis19.getHashJsonValues)(lineageBucket);
|
|
28758
|
+
for (const scope of storedScopes) {
|
|
28759
|
+
const lineageField = buildLineageField(scope);
|
|
28760
|
+
runtimeLineageScopeCache.set(`${lineageBucket}:${lineageField}`, scope);
|
|
28761
|
+
}
|
|
28762
|
+
runtimeLineageScopeCacheLoaded = true;
|
|
28763
|
+
}
|
|
28764
|
+
const lineageWrites = /* @__PURE__ */ new Map();
|
|
28765
|
+
for (const evaluation of lineageEvaluations) {
|
|
28766
|
+
const lineageField = buildLineageField({
|
|
28767
|
+
strategy: evaluation.strategy,
|
|
28768
|
+
runtimeConfigId: evaluation.runtimeConfigId,
|
|
28769
|
+
symbol: evaluation.symbol,
|
|
28770
|
+
lineage: evaluation.runtimeLineage
|
|
28771
|
+
});
|
|
28772
|
+
const cacheKey = `${lineageBucket}:${lineageField}`;
|
|
28773
|
+
const existing = runtimeLineageScopeCache.get(cacheKey);
|
|
28774
|
+
const scope = {
|
|
28775
|
+
strategy: evaluation.strategy,
|
|
28776
|
+
symbol: evaluation.symbol,
|
|
28777
|
+
runtimeConfigId: evaluation.runtimeConfigId,
|
|
28778
|
+
lineage: evaluation.runtimeLineage,
|
|
28779
|
+
firstTimestamp: Math.min(
|
|
28780
|
+
existing?.firstTimestamp ?? evaluation.timestamp,
|
|
28781
|
+
evaluation.timestamp
|
|
28782
|
+
),
|
|
28783
|
+
lastTimestamp: Math.max(
|
|
28784
|
+
existing?.lastTimestamp ?? evaluation.timestamp,
|
|
28785
|
+
evaluation.timestamp
|
|
28786
|
+
)
|
|
28787
|
+
};
|
|
28788
|
+
runtimeLineageScopeCache.set(cacheKey, scope);
|
|
28789
|
+
lineageWrites.set(lineageField, scope);
|
|
28790
|
+
}
|
|
28791
|
+
if (lineageWrites.size > 0) {
|
|
28792
|
+
await (0, import_redis19.setHashJsonFields)(
|
|
28793
|
+
lineageBucket,
|
|
28794
|
+
[...lineageWrites].map(([field, data]) => ({ field, data })),
|
|
28795
|
+
{
|
|
28796
|
+
expire: RUNTIME_LINEAGE_SCOPE_RETENTION_TTL_SECONDS
|
|
28797
|
+
}
|
|
28798
|
+
);
|
|
28799
|
+
}
|
|
28800
|
+
const detailedWrites = /* @__PURE__ */ new Map();
|
|
28801
|
+
const statsIncrements = /* @__PURE__ */ new Map();
|
|
28802
|
+
for (const evaluation of dayEvaluations) {
|
|
28803
|
+
if (shouldStoreDetailedRuntimeSignalEvaluation(evaluation)) {
|
|
28804
|
+
const bucket = import_redis19.redisKeys.runtimeSignalEvaluationBucket(
|
|
28805
|
+
evaluation.userName,
|
|
28806
|
+
dayKey,
|
|
28807
|
+
evaluation.strategy
|
|
28808
|
+
);
|
|
28809
|
+
const entries = detailedWrites.get(bucket) ?? [];
|
|
28810
|
+
entries.push({
|
|
28811
|
+
field: evaluation.evaluationId,
|
|
28812
|
+
data: evaluation
|
|
28813
|
+
});
|
|
28814
|
+
detailedWrites.set(bucket, entries);
|
|
28815
|
+
}
|
|
28816
|
+
const statsBucket = import_redis19.redisKeys.runtimeSignalEvaluationStatsBucket(
|
|
28715
28817
|
evaluation.userName,
|
|
28716
28818
|
dayKey,
|
|
28717
28819
|
evaluation.strategy
|
|
28718
|
-
)
|
|
28719
|
-
|
|
28720
|
-
|
|
28721
|
-
|
|
28722
|
-
|
|
28820
|
+
);
|
|
28821
|
+
const increments = statsIncrements.get(statsBucket) ?? {};
|
|
28822
|
+
for (const [field, increment] of Object.entries(
|
|
28823
|
+
buildRuntimeSignalStatsIncrements(evaluation)
|
|
28824
|
+
)) {
|
|
28825
|
+
increments[field] = (increments[field] ?? 0) + increment;
|
|
28723
28826
|
}
|
|
28724
|
-
|
|
28827
|
+
statsIncrements.set(statsBucket, increments);
|
|
28828
|
+
}
|
|
28829
|
+
await Promise.all([
|
|
28830
|
+
...[...detailedWrites].map(
|
|
28831
|
+
([bucket, entries]) => (0, import_redis19.setHashJsonFields)(bucket, entries, {
|
|
28832
|
+
expire: runtimeSignalRetentionTtl
|
|
28833
|
+
})
|
|
28834
|
+
),
|
|
28835
|
+
...[...statsIncrements].map(
|
|
28836
|
+
([bucket, increments]) => (0, import_redis19.incrHashFields)(bucket, increments, {
|
|
28837
|
+
expire: runtimeSignalRetentionTtl
|
|
28838
|
+
})
|
|
28839
|
+
)
|
|
28840
|
+
]);
|
|
28725
28841
|
}
|
|
28726
|
-
|
|
28727
|
-
|
|
28728
|
-
|
|
28729
|
-
|
|
28730
|
-
|
|
28731
|
-
|
|
28732
|
-
|
|
28733
|
-
{
|
|
28734
|
-
|
|
28842
|
+
};
|
|
28843
|
+
createRuntimeSignalEvaluationBuffer = () => {
|
|
28844
|
+
const evaluations = [];
|
|
28845
|
+
return {
|
|
28846
|
+
save: async (evaluation) => {
|
|
28847
|
+
evaluations.push(evaluation);
|
|
28848
|
+
},
|
|
28849
|
+
flush: async () => {
|
|
28850
|
+
const pending = evaluations.splice(0);
|
|
28851
|
+
await flushRuntimeSignalEvaluations(pending);
|
|
28735
28852
|
}
|
|
28736
|
-
|
|
28853
|
+
};
|
|
28737
28854
|
};
|
|
28738
28855
|
}
|
|
28739
28856
|
});
|
|
@@ -28840,8 +28957,8 @@ var init_runtimeLifecycle = __esm({
|
|
|
28840
28957
|
}
|
|
28841
28958
|
try {
|
|
28842
28959
|
const strategy = await create({
|
|
28843
|
-
btcBinanceData:
|
|
28844
|
-
btcCoinbaseData:
|
|
28960
|
+
btcBinanceData: btcBinanceData ?? [],
|
|
28961
|
+
btcCoinbaseData: btcCoinbaseData ?? [],
|
|
28845
28962
|
onRuntimeClose
|
|
28846
28963
|
});
|
|
28847
28964
|
strategy.__tradejsUpdateReferenceData?.({
|
|
@@ -29295,7 +29412,7 @@ var init_signals = __esm({
|
|
|
29295
29412
|
lifecycle
|
|
29296
29413
|
};
|
|
29297
29414
|
};
|
|
29298
|
-
findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCoinbaseData, runtimeStrategies, strategyStats, runtimeCloseNotifications, lifecycle, preloadStart, currentTimestamp, persistStrategyState, universe, interval5, intervalMs2, accountId, deploymentId, instrument, runtimeScopeUniverse) => {
|
|
29415
|
+
findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCoinbaseData, primaryBtcClosedData, primaryEthClosedData, primaryEthByTimestamp, runtimeStrategies, strategyStats, runtimeCloseNotifications, lifecycle, preloadStart, currentTimestamp, persistStrategyState, universe, interval5, intervalMs2, accountId, deploymentId, instrument, runtimeScopeUniverse, saveRuntimeSignalEvaluation) => {
|
|
29299
29416
|
const strategySignals = [];
|
|
29300
29417
|
const loadCached = (cachedSymbol) => connector.kline({
|
|
29301
29418
|
symbol: cachedSymbol,
|
|
@@ -29304,36 +29421,21 @@ var init_signals = __esm({
|
|
|
29304
29421
|
cacheOnly: true,
|
|
29305
29422
|
interval: interval5
|
|
29306
29423
|
});
|
|
29307
|
-
const
|
|
29308
|
-
loadCached(symbol),
|
|
29309
|
-
loadCached("BTCUSDT"),
|
|
29310
|
-
loadCached("ETHUSDT")
|
|
29311
|
-
]) : [await loadCached(symbol), [], []];
|
|
29424
|
+
const cachedData = universe === "crypto" && symbol === "BTCUSDT" ? primaryBtcClosedData : universe === "crypto" && symbol === "ETHUSDT" ? primaryEthClosedData : await loadCached(symbol);
|
|
29312
29425
|
const closedData = getClosedCandlesForInterval(
|
|
29313
29426
|
cachedData,
|
|
29314
29427
|
currentTimestamp,
|
|
29315
29428
|
intervalMs2
|
|
29316
29429
|
);
|
|
29317
|
-
const closedBtcData =
|
|
29318
|
-
|
|
29319
|
-
currentTimestamp,
|
|
29320
|
-
intervalMs2
|
|
29321
|
-
);
|
|
29322
|
-
const closedEthData = getClosedCandlesForInterval(
|
|
29323
|
-
ethCachedData,
|
|
29324
|
-
currentTimestamp,
|
|
29325
|
-
intervalMs2
|
|
29326
|
-
);
|
|
29430
|
+
const closedBtcData = primaryBtcClosedData;
|
|
29431
|
+
const closedEthData = primaryEthClosedData;
|
|
29327
29432
|
const { alignedCoinCandles, alignedBtcCandles } = universe === "crypto" ? alignSymbolWithBtcReference(closedData, closedBtcData) : { alignedCoinCandles: closedData, alignedBtcCandles: closedData };
|
|
29328
|
-
const
|
|
29329
|
-
closedEthData.map((candle) => [candle.timestamp, candle])
|
|
29330
|
-
);
|
|
29331
|
-
const alignedEthCandles = alignedCoinCandles.map((candle) => ethByTimestamp.get(candle.timestamp)).filter(
|
|
29433
|
+
const alignedEthCandles = alignedCoinCandles.map((candle) => primaryEthByTimestamp.get(candle.timestamp)).filter(
|
|
29332
29434
|
(candle) => Boolean(candle)
|
|
29333
29435
|
);
|
|
29334
29436
|
const lastCandle = alignedCoinCandles.at(-1);
|
|
29335
29437
|
const btcLastCandle = alignedBtcCandles.at(-1);
|
|
29336
|
-
const ethLastCandle = lastCandle == null ? void 0 :
|
|
29438
|
+
const ethLastCandle = lastCandle == null ? void 0 : primaryEthByTimestamp.get(lastCandle.timestamp);
|
|
29337
29439
|
if (!lastCandle || !btcLastCandle) {
|
|
29338
29440
|
return strategySignals;
|
|
29339
29441
|
}
|
|
@@ -29347,6 +29449,7 @@ var init_signals = __esm({
|
|
|
29347
29449
|
strategyName,
|
|
29348
29450
|
configId,
|
|
29349
29451
|
strategyCreator,
|
|
29452
|
+
sourceStrategyConfig,
|
|
29350
29453
|
strategyConfig,
|
|
29351
29454
|
strategyResults
|
|
29352
29455
|
} = runtimeStrategy;
|
|
@@ -29381,46 +29484,61 @@ var init_signals = __esm({
|
|
|
29381
29484
|
configId
|
|
29382
29485
|
});
|
|
29383
29486
|
const stats = strategyStats.get(strategyName);
|
|
29384
|
-
const
|
|
29385
|
-
|
|
29386
|
-
|
|
29387
|
-
|
|
29388
|
-
|
|
29389
|
-
|
|
29390
|
-
|
|
29391
|
-
|
|
29392
|
-
|
|
29393
|
-
|
|
29394
|
-
|
|
29395
|
-
|
|
29396
|
-
|
|
29397
|
-
btcBinanceData
|
|
29398
|
-
btcCoinbaseData
|
|
29399
|
-
onRuntimeClose
|
|
29400
|
-
|
|
29401
|
-
|
|
29402
|
-
|
|
29403
|
-
|
|
29404
|
-
|
|
29405
|
-
|
|
29406
|
-
|
|
29407
|
-
|
|
29408
|
-
|
|
29409
|
-
|
|
29410
|
-
|
|
29411
|
-
|
|
29412
|
-
|
|
29413
|
-
|
|
29414
|
-
|
|
29415
|
-
|
|
29416
|
-
|
|
29417
|
-
|
|
29418
|
-
|
|
29419
|
-
|
|
29420
|
-
|
|
29421
|
-
|
|
29422
|
-
|
|
29423
|
-
|
|
29487
|
+
const initialDataLength = previousData.length;
|
|
29488
|
+
const initialBtcDataLength = previousBtcData.length;
|
|
29489
|
+
const initialEthDataLength = previousEthData.length;
|
|
29490
|
+
let evaluation;
|
|
29491
|
+
try {
|
|
29492
|
+
evaluation = await lifecycle.evaluate({
|
|
29493
|
+
key: lifecycleKey,
|
|
29494
|
+
timestamp: lastCandle.timestamp,
|
|
29495
|
+
config: {
|
|
29496
|
+
runtimeConfig,
|
|
29497
|
+
sourceStrategyConfig,
|
|
29498
|
+
symbolResultConfig: strategyResults?.[symbol]?.config ?? null
|
|
29499
|
+
},
|
|
29500
|
+
btcBinanceData,
|
|
29501
|
+
btcCoinbaseData,
|
|
29502
|
+
onRuntimeClose: (event) => {
|
|
29503
|
+
runtimeCloseNotifications.push(event);
|
|
29504
|
+
},
|
|
29505
|
+
create: async ({
|
|
29506
|
+
btcBinanceData: lifecycleBtcBinanceData,
|
|
29507
|
+
btcCoinbaseData: lifecycleBtcCoinbaseData,
|
|
29508
|
+
onRuntimeClose
|
|
29509
|
+
}) => strategyCreator({
|
|
29510
|
+
userName: flags26.user,
|
|
29511
|
+
connectorName,
|
|
29512
|
+
runtimeConfigId: configId,
|
|
29513
|
+
runtimeConfigSnapshot: {
|
|
29514
|
+
userConfig: sourceStrategyConfig,
|
|
29515
|
+
symbolResultConfig: strategyResults?.[symbol]?.config ?? null
|
|
29516
|
+
},
|
|
29517
|
+
connector,
|
|
29518
|
+
symbol,
|
|
29519
|
+
...runtimeScopeUniverse ? {
|
|
29520
|
+
universe,
|
|
29521
|
+
assetClass: instrument?.assetClass,
|
|
29522
|
+
instrument,
|
|
29523
|
+
accountId,
|
|
29524
|
+
deploymentId
|
|
29525
|
+
} : {},
|
|
29526
|
+
data: previousData,
|
|
29527
|
+
btcData: universe === "crypto" ? previousBtcData : [],
|
|
29528
|
+
ethData: universe === "crypto" ? previousEthData : [],
|
|
29529
|
+
btcBinanceData: lifecycleBtcBinanceData,
|
|
29530
|
+
btcCoinbaseData: lifecycleBtcCoinbaseData,
|
|
29531
|
+
config: runtimeConfig,
|
|
29532
|
+
...persistStrategyState ? { sharedStrategyStateKey: lifecycleKey } : {},
|
|
29533
|
+
onRuntimeClose
|
|
29534
|
+
}),
|
|
29535
|
+
run: (strategy) => strategy(lastCandle, btcLastCandle, ethLastCandle)
|
|
29536
|
+
});
|
|
29537
|
+
} finally {
|
|
29538
|
+
previousData.length = initialDataLength;
|
|
29539
|
+
previousBtcData.length = initialBtcDataLength;
|
|
29540
|
+
previousEthData.length = initialEthDataLength;
|
|
29541
|
+
}
|
|
29424
29542
|
if (evaluation.action === "duplicate" || evaluation.action === "stale") {
|
|
29425
29543
|
continue;
|
|
29426
29544
|
}
|
|
@@ -29441,7 +29559,7 @@ var init_signals = __esm({
|
|
|
29441
29559
|
if (typeof signal === "string") {
|
|
29442
29560
|
recordStrategyReason(strategyStats, strategyName, signal, "core");
|
|
29443
29561
|
}
|
|
29444
|
-
await saveRuntimeSignalEvaluation({
|
|
29562
|
+
await saveRuntimeSignalEvaluation?.({
|
|
29445
29563
|
evaluationId: buildRuntimeSignalEvaluationId({
|
|
29446
29564
|
strategyName,
|
|
29447
29565
|
symbol,
|
|
@@ -29507,7 +29625,7 @@ var init_signals = __esm({
|
|
|
29507
29625
|
expire: runtimeSignalRetentionTtl
|
|
29508
29626
|
}
|
|
29509
29627
|
);
|
|
29510
|
-
await saveRuntimeSignalEvaluation({
|
|
29628
|
+
await saveRuntimeSignalEvaluation?.({
|
|
29511
29629
|
evaluationId: buildRuntimeSignalEvaluationId({
|
|
29512
29630
|
strategyName,
|
|
29513
29631
|
symbol,
|
|
@@ -29549,6 +29667,7 @@ var init_signals = __esm({
|
|
|
29549
29667
|
let activeSession;
|
|
29550
29668
|
let projectHooks;
|
|
29551
29669
|
let afterSignalsHookContext = null;
|
|
29670
|
+
const runtimeSignalEvaluations = createRuntimeSignalEvaluationBuffer();
|
|
29552
29671
|
try {
|
|
29553
29672
|
const session = options.session ?? await createSignalsSession(createDefaultSignalsLifecycle());
|
|
29554
29673
|
activeSession = session;
|
|
@@ -29660,7 +29779,12 @@ var init_signals = __esm({
|
|
|
29660
29779
|
if (flags26.updateOnly) {
|
|
29661
29780
|
return;
|
|
29662
29781
|
}
|
|
29663
|
-
const [
|
|
29782
|
+
const [
|
|
29783
|
+
btcBinanceData,
|
|
29784
|
+
btcCoinbaseData,
|
|
29785
|
+
primaryBtcCachedData,
|
|
29786
|
+
primaryEthCachedData
|
|
29787
|
+
] = universe === "crypto" ? await timeOperation3(
|
|
29664
29788
|
"reference candles load",
|
|
29665
29789
|
() => Promise.all([
|
|
29666
29790
|
btcReferences.binance.kline({
|
|
@@ -29676,9 +29800,36 @@ var init_signals = __esm({
|
|
|
29676
29800
|
end: currentTimestamp,
|
|
29677
29801
|
cacheOnly: true,
|
|
29678
29802
|
interval: interval5
|
|
29803
|
+
}),
|
|
29804
|
+
marketConnector.kline({
|
|
29805
|
+
symbol: "BTCUSDT",
|
|
29806
|
+
start: preloadStart,
|
|
29807
|
+
end: currentTimestamp,
|
|
29808
|
+
cacheOnly: true,
|
|
29809
|
+
interval: interval5
|
|
29810
|
+
}),
|
|
29811
|
+
marketConnector.kline({
|
|
29812
|
+
symbol: "ETHUSDT",
|
|
29813
|
+
start: preloadStart,
|
|
29814
|
+
end: currentTimestamp,
|
|
29815
|
+
cacheOnly: true,
|
|
29816
|
+
interval: interval5
|
|
29679
29817
|
})
|
|
29680
29818
|
])
|
|
29681
|
-
) : [[], []];
|
|
29819
|
+
) : [[], [], [], []];
|
|
29820
|
+
const primaryBtcClosedData = getClosedCandlesForInterval(
|
|
29821
|
+
primaryBtcCachedData,
|
|
29822
|
+
currentTimestamp,
|
|
29823
|
+
intervalMs2
|
|
29824
|
+
);
|
|
29825
|
+
const primaryEthClosedData = getClosedCandlesForInterval(
|
|
29826
|
+
primaryEthCachedData,
|
|
29827
|
+
currentTimestamp,
|
|
29828
|
+
intervalMs2
|
|
29829
|
+
);
|
|
29830
|
+
const primaryEthByTimestamp = new Map(
|
|
29831
|
+
primaryEthClosedData.map((candle) => [candle.timestamp, candle])
|
|
29832
|
+
);
|
|
29682
29833
|
const runtimeStrategies = await loadRuntimeStrategies({
|
|
29683
29834
|
userName: flags26.user,
|
|
29684
29835
|
projectRoot: projectRoot12,
|
|
@@ -29762,6 +29913,9 @@ var init_signals = __esm({
|
|
|
29762
29913
|
marketConnector,
|
|
29763
29914
|
btcBinanceData,
|
|
29764
29915
|
btcCoinbaseData,
|
|
29916
|
+
primaryBtcClosedData,
|
|
29917
|
+
primaryEthClosedData,
|
|
29918
|
+
primaryEthByTimestamp,
|
|
29765
29919
|
runtimeStrategies,
|
|
29766
29920
|
strategyStats,
|
|
29767
29921
|
runtimeCloseNotifications,
|
|
@@ -29775,7 +29929,8 @@ var init_signals = __esm({
|
|
|
29775
29929
|
accountId,
|
|
29776
29930
|
deployment?.id,
|
|
29777
29931
|
instrumentsBySymbol.get(symbol),
|
|
29778
|
-
sessionUniverse
|
|
29932
|
+
sessionUniverse,
|
|
29933
|
+
runtimeSignalEvaluations.save
|
|
29779
29934
|
);
|
|
29780
29935
|
if (strategySignals.length > 0) {
|
|
29781
29936
|
signals2.push(...strategySignals);
|
|
@@ -29816,6 +29971,14 @@ var init_signals = __esm({
|
|
|
29816
29971
|
);
|
|
29817
29972
|
throw error;
|
|
29818
29973
|
} finally {
|
|
29974
|
+
try {
|
|
29975
|
+
await runtimeSignalEvaluations.flush();
|
|
29976
|
+
} catch (error) {
|
|
29977
|
+
import_logger10.logger.error(
|
|
29978
|
+
"runtime signal evaluation flush failed: %s",
|
|
29979
|
+
error?.message || String(error)
|
|
29980
|
+
);
|
|
29981
|
+
}
|
|
29819
29982
|
const durationMs = Date.now() - startedAt;
|
|
29820
29983
|
if (activeSession?.deployment) {
|
|
29821
29984
|
await (0, import_tradingAccounts3.saveRuntimeDeploymentHeartbeat)(flags26.user, {
|