@tradejs/cli 2.0.8 → 2.0.10
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 +437 -171
- package/dist/lib/aiPocketSearchCli.js +54 -0
- package/dist/lib/marketContextPrepare.js +2 -2
- package/dist/lib/runtimeDebugEvidence.js +2 -1
- package/dist/lib/runtimeRedis.js +11 -0
- 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/replayRuntimeEvidence.js +2 -1
- package/dist/scripts/runtimeEvidence.js +2 -1
- package/dist/scripts/runtimeParity.js +2 -2
- package/dist/scripts/signals.js +233 -125
- package/dist/scripts/signalsDaemon.js +233 -125
- package/dist/scripts/signalsSummary.js +138 -35
- 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,
|
|
@@ -11105,7 +11160,7 @@ var init_timeWindow = __esm({
|
|
|
11105
11160
|
});
|
|
11106
11161
|
|
|
11107
11162
|
// src/lib/runtimeRedis.ts
|
|
11108
|
-
var import_redis4, import_time, RESERVED_STRATEGY_NAMES, RESERVED_CONFIG_IDS, resolveStrategyConfigIdentityByKey, isRuntimeStrategyEnabled, isRuntimeTradeRecord, resolveStrategyNameByConfigKey, getRuntimeStrategyConfigKeys, loadRuntimeStrategyNames, loadRuntimeStrategyConfigs, loadRuntimeTrades, loadStrategyResultSymbols;
|
|
11163
|
+
var import_redis4, import_time, RESERVED_STRATEGY_NAMES, RESERVED_CONFIG_IDS, resolveStrategyConfigIdentityByKey, isRuntimeStrategyEnabled, isRuntimeTradeRecord, resolveStrategyNameByConfigKey, getRuntimeStrategyConfigKeys, loadRuntimeStrategyNames, loadRuntimeStrategyConfigs, loadRuntimeTrades, loadRuntimeActiveTradeOrderIds, loadStrategyResultSymbols;
|
|
11109
11164
|
var init_runtimeRedis = __esm({
|
|
11110
11165
|
"src/lib/runtimeRedis.ts"() {
|
|
11111
11166
|
"use strict";
|
|
@@ -11209,6 +11264,15 @@ var init_runtimeRedis = __esm({
|
|
|
11209
11264
|
const trades = await Promise.all(keys.map((key) => (0, import_redis4.getData)(key, null)));
|
|
11210
11265
|
return trades.filter(isRuntimeTradeRecord).filter(filterByWindow).sort((left, right) => left.entryTimestamp - right.entryTimestamp);
|
|
11211
11266
|
};
|
|
11267
|
+
loadRuntimeActiveTradeOrderIds = async (userName2) => {
|
|
11268
|
+
const keys = await (0, import_redis4.getKeys)(import_redis4.redisKeys.runtimeActiveTrades(userName2));
|
|
11269
|
+
const refs = await Promise.all(keys.map((key) => (0, import_redis4.getData)(key, null)));
|
|
11270
|
+
return new Set(
|
|
11271
|
+
refs.map(
|
|
11272
|
+
(ref) => ref && typeof ref === "object" && "orderId" in ref && typeof ref.orderId === "string" && ref.orderId.trim() ? ref.orderId.trim() : null
|
|
11273
|
+
).filter((orderId) => orderId != null)
|
|
11274
|
+
);
|
|
11275
|
+
};
|
|
11212
11276
|
loadStrategyResultSymbols = async ({
|
|
11213
11277
|
userName: userName2,
|
|
11214
11278
|
strategy
|
|
@@ -24837,7 +24901,8 @@ var init_runtimeDebugEvidence = __esm({
|
|
|
24837
24901
|
);
|
|
24838
24902
|
const activeTradeKey = import_redis14.redisKeys.runtimeActiveTrade(
|
|
24839
24903
|
userName2,
|
|
24840
|
-
trade.symbol
|
|
24904
|
+
trade.symbol,
|
|
24905
|
+
trade.deploymentId ?? trade.accountId
|
|
24841
24906
|
);
|
|
24842
24907
|
const signalKey = trade.signalId != null ? import_redis14.redisKeys.storeSignal(trade.symbol, trade.signalId) : null;
|
|
24843
24908
|
const evaluationBucketKey = import_redis14.redisKeys.runtimeSignalEvaluationBucket(
|
|
@@ -28353,6 +28418,7 @@ var init_runtimeStrategies = __esm({
|
|
|
28353
28418
|
universe: configUniverse,
|
|
28354
28419
|
accountId: effectiveAccountId,
|
|
28355
28420
|
strategyCreator,
|
|
28421
|
+
sourceStrategyConfig: strategyConfig,
|
|
28356
28422
|
strategyConfig: {
|
|
28357
28423
|
...strategyConfig,
|
|
28358
28424
|
...deploymentStrategy?.config,
|
|
@@ -28652,7 +28718,7 @@ var init_runtimeLineage = __esm({
|
|
|
28652
28718
|
});
|
|
28653
28719
|
|
|
28654
28720
|
// src/lib/signals/evaluations.ts
|
|
28655
|
-
var import_redis19, runtimeLineageScopeCache, runtimeLineageScopeCacheDayKey, buildRuntimeSignalEvaluationId,
|
|
28721
|
+
var import_redis19, runtimeLineageScopeCache, runtimeLineageScopeCacheDayKey, runtimeLineageScopeCacheLoaded, buildRuntimeSignalEvaluationId, buildLineageField, flushRuntimeSignalEvaluations, createRuntimeSignalEvaluationBuffer;
|
|
28656
28722
|
var init_evaluations = __esm({
|
|
28657
28723
|
"src/lib/signals/evaluations.ts"() {
|
|
28658
28724
|
"use strict";
|
|
@@ -28661,79 +28727,140 @@ var init_evaluations = __esm({
|
|
|
28661
28727
|
init_runtimeLineage();
|
|
28662
28728
|
runtimeLineageScopeCache = /* @__PURE__ */ new Map();
|
|
28663
28729
|
runtimeLineageScopeCacheDayKey = "";
|
|
28730
|
+
runtimeLineageScopeCacheLoaded = false;
|
|
28664
28731
|
buildRuntimeSignalEvaluationId = ({
|
|
28665
28732
|
strategyName,
|
|
28666
28733
|
symbol,
|
|
28667
28734
|
timestamp,
|
|
28668
28735
|
runtimeConfigId
|
|
28669
28736
|
}) => runtimeConfigId && runtimeConfigId !== "config" ? [strategyName, runtimeConfigId, symbol, timestamp].join(":") : [strategyName, symbol, timestamp].join(":");
|
|
28670
|
-
|
|
28671
|
-
|
|
28672
|
-
|
|
28673
|
-
|
|
28674
|
-
|
|
28737
|
+
buildLineageField = (scope) => [
|
|
28738
|
+
scope.strategy,
|
|
28739
|
+
scope.runtimeConfigId ?? "config",
|
|
28740
|
+
scope.symbol,
|
|
28741
|
+
runtimeLineageKey(scope.lineage)
|
|
28742
|
+
].join(":");
|
|
28743
|
+
flushRuntimeSignalEvaluations = async (evaluations) => {
|
|
28744
|
+
if (evaluations.length === 0) return;
|
|
28745
|
+
const evaluationsByDay = /* @__PURE__ */ new Map();
|
|
28746
|
+
for (const evaluation of evaluations) {
|
|
28747
|
+
const dayKey = (0, import_time6.getRuntimeStorageDayKey)(evaluation.timestamp);
|
|
28748
|
+
const dayEvaluations = evaluationsByDay.get(dayKey) ?? [];
|
|
28749
|
+
dayEvaluations.push(evaluation);
|
|
28750
|
+
evaluationsByDay.set(dayKey, dayEvaluations);
|
|
28675
28751
|
}
|
|
28676
28752
|
const runtimeSignalRetentionTtl = getRuntimeSignalRetentionTtlSeconds();
|
|
28677
|
-
|
|
28678
|
-
|
|
28679
|
-
|
|
28680
|
-
|
|
28681
|
-
|
|
28682
|
-
|
|
28683
|
-
].join(":");
|
|
28753
|
+
for (const [dayKey, dayEvaluations] of evaluationsByDay) {
|
|
28754
|
+
if (runtimeLineageScopeCacheDayKey !== dayKey) {
|
|
28755
|
+
runtimeLineageScopeCache.clear();
|
|
28756
|
+
runtimeLineageScopeCacheDayKey = dayKey;
|
|
28757
|
+
runtimeLineageScopeCacheLoaded = false;
|
|
28758
|
+
}
|
|
28684
28759
|
const lineageBucket = import_redis19.redisKeys.runtimeLineageScopeBucket(
|
|
28685
|
-
|
|
28760
|
+
dayEvaluations[0].userName,
|
|
28686
28761
|
dayKey
|
|
28687
28762
|
);
|
|
28688
|
-
const
|
|
28689
|
-
|
|
28690
|
-
lineageBucket,
|
|
28691
|
-
lineageField
|
|
28763
|
+
const lineageEvaluations = dayEvaluations.filter(
|
|
28764
|
+
(evaluation) => evaluation.runtimeLineage != null
|
|
28692
28765
|
);
|
|
28693
|
-
|
|
28694
|
-
|
|
28695
|
-
|
|
28696
|
-
|
|
28697
|
-
|
|
28698
|
-
|
|
28699
|
-
|
|
28700
|
-
|
|
28701
|
-
|
|
28702
|
-
|
|
28703
|
-
|
|
28704
|
-
evaluation.
|
|
28705
|
-
|
|
28706
|
-
|
|
28707
|
-
|
|
28708
|
-
|
|
28709
|
-
|
|
28710
|
-
|
|
28711
|
-
|
|
28712
|
-
|
|
28713
|
-
|
|
28714
|
-
|
|
28766
|
+
if (lineageEvaluations.length > 0 && !runtimeLineageScopeCacheLoaded) {
|
|
28767
|
+
const storedScopes = await (0, import_redis19.getHashJsonValues)(lineageBucket);
|
|
28768
|
+
for (const scope of storedScopes) {
|
|
28769
|
+
const lineageField = buildLineageField(scope);
|
|
28770
|
+
runtimeLineageScopeCache.set(`${lineageBucket}:${lineageField}`, scope);
|
|
28771
|
+
}
|
|
28772
|
+
runtimeLineageScopeCacheLoaded = true;
|
|
28773
|
+
}
|
|
28774
|
+
const lineageWrites = /* @__PURE__ */ new Map();
|
|
28775
|
+
for (const evaluation of lineageEvaluations) {
|
|
28776
|
+
const lineageField = buildLineageField({
|
|
28777
|
+
strategy: evaluation.strategy,
|
|
28778
|
+
runtimeConfigId: evaluation.runtimeConfigId,
|
|
28779
|
+
symbol: evaluation.symbol,
|
|
28780
|
+
lineage: evaluation.runtimeLineage
|
|
28781
|
+
});
|
|
28782
|
+
const cacheKey = `${lineageBucket}:${lineageField}`;
|
|
28783
|
+
const existing = runtimeLineageScopeCache.get(cacheKey);
|
|
28784
|
+
const scope = {
|
|
28785
|
+
strategy: evaluation.strategy,
|
|
28786
|
+
symbol: evaluation.symbol,
|
|
28787
|
+
runtimeConfigId: evaluation.runtimeConfigId,
|
|
28788
|
+
lineage: evaluation.runtimeLineage,
|
|
28789
|
+
firstTimestamp: Math.min(
|
|
28790
|
+
existing?.firstTimestamp ?? evaluation.timestamp,
|
|
28791
|
+
evaluation.timestamp
|
|
28792
|
+
),
|
|
28793
|
+
lastTimestamp: Math.max(
|
|
28794
|
+
existing?.lastTimestamp ?? evaluation.timestamp,
|
|
28795
|
+
evaluation.timestamp
|
|
28796
|
+
)
|
|
28797
|
+
};
|
|
28798
|
+
runtimeLineageScopeCache.set(cacheKey, scope);
|
|
28799
|
+
lineageWrites.set(lineageField, scope);
|
|
28800
|
+
}
|
|
28801
|
+
if (lineageWrites.size > 0) {
|
|
28802
|
+
await (0, import_redis19.setHashJsonFields)(
|
|
28803
|
+
lineageBucket,
|
|
28804
|
+
[...lineageWrites].map(([field, data]) => ({ field, data })),
|
|
28805
|
+
{
|
|
28806
|
+
expire: RUNTIME_LINEAGE_SCOPE_RETENTION_TTL_SECONDS
|
|
28807
|
+
}
|
|
28808
|
+
);
|
|
28809
|
+
}
|
|
28810
|
+
const detailedWrites = /* @__PURE__ */ new Map();
|
|
28811
|
+
const statsIncrements = /* @__PURE__ */ new Map();
|
|
28812
|
+
for (const evaluation of dayEvaluations) {
|
|
28813
|
+
if (shouldStoreDetailedRuntimeSignalEvaluation(evaluation)) {
|
|
28814
|
+
const bucket = import_redis19.redisKeys.runtimeSignalEvaluationBucket(
|
|
28815
|
+
evaluation.userName,
|
|
28816
|
+
dayKey,
|
|
28817
|
+
evaluation.strategy
|
|
28818
|
+
);
|
|
28819
|
+
const entries = detailedWrites.get(bucket) ?? [];
|
|
28820
|
+
entries.push({
|
|
28821
|
+
field: evaluation.evaluationId,
|
|
28822
|
+
data: evaluation
|
|
28823
|
+
});
|
|
28824
|
+
detailedWrites.set(bucket, entries);
|
|
28825
|
+
}
|
|
28826
|
+
const statsBucket = import_redis19.redisKeys.runtimeSignalEvaluationStatsBucket(
|
|
28715
28827
|
evaluation.userName,
|
|
28716
28828
|
dayKey,
|
|
28717
28829
|
evaluation.strategy
|
|
28718
|
-
)
|
|
28719
|
-
|
|
28720
|
-
|
|
28721
|
-
|
|
28722
|
-
|
|
28830
|
+
);
|
|
28831
|
+
const increments = statsIncrements.get(statsBucket) ?? {};
|
|
28832
|
+
for (const [field, increment] of Object.entries(
|
|
28833
|
+
buildRuntimeSignalStatsIncrements(evaluation)
|
|
28834
|
+
)) {
|
|
28835
|
+
increments[field] = (increments[field] ?? 0) + increment;
|
|
28723
28836
|
}
|
|
28724
|
-
|
|
28837
|
+
statsIncrements.set(statsBucket, increments);
|
|
28838
|
+
}
|
|
28839
|
+
await Promise.all([
|
|
28840
|
+
...[...detailedWrites].map(
|
|
28841
|
+
([bucket, entries]) => (0, import_redis19.setHashJsonFields)(bucket, entries, {
|
|
28842
|
+
expire: runtimeSignalRetentionTtl
|
|
28843
|
+
})
|
|
28844
|
+
),
|
|
28845
|
+
...[...statsIncrements].map(
|
|
28846
|
+
([bucket, increments]) => (0, import_redis19.incrHashFields)(bucket, increments, {
|
|
28847
|
+
expire: runtimeSignalRetentionTtl
|
|
28848
|
+
})
|
|
28849
|
+
)
|
|
28850
|
+
]);
|
|
28725
28851
|
}
|
|
28726
|
-
|
|
28727
|
-
|
|
28728
|
-
|
|
28729
|
-
|
|
28730
|
-
|
|
28731
|
-
|
|
28732
|
-
|
|
28733
|
-
{
|
|
28734
|
-
|
|
28852
|
+
};
|
|
28853
|
+
createRuntimeSignalEvaluationBuffer = () => {
|
|
28854
|
+
const evaluations = [];
|
|
28855
|
+
return {
|
|
28856
|
+
save: async (evaluation) => {
|
|
28857
|
+
evaluations.push(evaluation);
|
|
28858
|
+
},
|
|
28859
|
+
flush: async () => {
|
|
28860
|
+
const pending = evaluations.splice(0);
|
|
28861
|
+
await flushRuntimeSignalEvaluations(pending);
|
|
28735
28862
|
}
|
|
28736
|
-
|
|
28863
|
+
};
|
|
28737
28864
|
};
|
|
28738
28865
|
}
|
|
28739
28866
|
});
|
|
@@ -28840,8 +28967,8 @@ var init_runtimeLifecycle = __esm({
|
|
|
28840
28967
|
}
|
|
28841
28968
|
try {
|
|
28842
28969
|
const strategy = await create({
|
|
28843
|
-
btcBinanceData:
|
|
28844
|
-
btcCoinbaseData:
|
|
28970
|
+
btcBinanceData: btcBinanceData ?? [],
|
|
28971
|
+
btcCoinbaseData: btcCoinbaseData ?? [],
|
|
28845
28972
|
onRuntimeClose
|
|
28846
28973
|
});
|
|
28847
28974
|
strategy.__tradejsUpdateReferenceData?.({
|
|
@@ -29295,7 +29422,7 @@ var init_signals = __esm({
|
|
|
29295
29422
|
lifecycle
|
|
29296
29423
|
};
|
|
29297
29424
|
};
|
|
29298
|
-
findSignals = async (symbol, connectorName, connector, btcBinanceData, btcCoinbaseData, runtimeStrategies, strategyStats, runtimeCloseNotifications, lifecycle, preloadStart, currentTimestamp, persistStrategyState, universe, interval5, intervalMs2, accountId, deploymentId, instrument, runtimeScopeUniverse) => {
|
|
29425
|
+
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
29426
|
const strategySignals = [];
|
|
29300
29427
|
const loadCached = (cachedSymbol) => connector.kline({
|
|
29301
29428
|
symbol: cachedSymbol,
|
|
@@ -29304,36 +29431,21 @@ var init_signals = __esm({
|
|
|
29304
29431
|
cacheOnly: true,
|
|
29305
29432
|
interval: interval5
|
|
29306
29433
|
});
|
|
29307
|
-
const
|
|
29308
|
-
loadCached(symbol),
|
|
29309
|
-
loadCached("BTCUSDT"),
|
|
29310
|
-
loadCached("ETHUSDT")
|
|
29311
|
-
]) : [await loadCached(symbol), [], []];
|
|
29434
|
+
const cachedData = universe === "crypto" && symbol === "BTCUSDT" ? primaryBtcClosedData : universe === "crypto" && symbol === "ETHUSDT" ? primaryEthClosedData : await loadCached(symbol);
|
|
29312
29435
|
const closedData = getClosedCandlesForInterval(
|
|
29313
29436
|
cachedData,
|
|
29314
29437
|
currentTimestamp,
|
|
29315
29438
|
intervalMs2
|
|
29316
29439
|
);
|
|
29317
|
-
const closedBtcData =
|
|
29318
|
-
|
|
29319
|
-
currentTimestamp,
|
|
29320
|
-
intervalMs2
|
|
29321
|
-
);
|
|
29322
|
-
const closedEthData = getClosedCandlesForInterval(
|
|
29323
|
-
ethCachedData,
|
|
29324
|
-
currentTimestamp,
|
|
29325
|
-
intervalMs2
|
|
29326
|
-
);
|
|
29440
|
+
const closedBtcData = primaryBtcClosedData;
|
|
29441
|
+
const closedEthData = primaryEthClosedData;
|
|
29327
29442
|
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(
|
|
29443
|
+
const alignedEthCandles = alignedCoinCandles.map((candle) => primaryEthByTimestamp.get(candle.timestamp)).filter(
|
|
29332
29444
|
(candle) => Boolean(candle)
|
|
29333
29445
|
);
|
|
29334
29446
|
const lastCandle = alignedCoinCandles.at(-1);
|
|
29335
29447
|
const btcLastCandle = alignedBtcCandles.at(-1);
|
|
29336
|
-
const ethLastCandle = lastCandle == null ? void 0 :
|
|
29448
|
+
const ethLastCandle = lastCandle == null ? void 0 : primaryEthByTimestamp.get(lastCandle.timestamp);
|
|
29337
29449
|
if (!lastCandle || !btcLastCandle) {
|
|
29338
29450
|
return strategySignals;
|
|
29339
29451
|
}
|
|
@@ -29347,6 +29459,7 @@ var init_signals = __esm({
|
|
|
29347
29459
|
strategyName,
|
|
29348
29460
|
configId,
|
|
29349
29461
|
strategyCreator,
|
|
29462
|
+
sourceStrategyConfig,
|
|
29350
29463
|
strategyConfig,
|
|
29351
29464
|
strategyResults
|
|
29352
29465
|
} = runtimeStrategy;
|
|
@@ -29381,46 +29494,61 @@ var init_signals = __esm({
|
|
|
29381
29494
|
configId
|
|
29382
29495
|
});
|
|
29383
29496
|
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
|
-
|
|
29497
|
+
const initialDataLength = previousData.length;
|
|
29498
|
+
const initialBtcDataLength = previousBtcData.length;
|
|
29499
|
+
const initialEthDataLength = previousEthData.length;
|
|
29500
|
+
let evaluation;
|
|
29501
|
+
try {
|
|
29502
|
+
evaluation = await lifecycle.evaluate({
|
|
29503
|
+
key: lifecycleKey,
|
|
29504
|
+
timestamp: lastCandle.timestamp,
|
|
29505
|
+
config: {
|
|
29506
|
+
runtimeConfig,
|
|
29507
|
+
sourceStrategyConfig,
|
|
29508
|
+
symbolResultConfig: strategyResults?.[symbol]?.config ?? null
|
|
29509
|
+
},
|
|
29510
|
+
btcBinanceData,
|
|
29511
|
+
btcCoinbaseData,
|
|
29512
|
+
onRuntimeClose: (event) => {
|
|
29513
|
+
runtimeCloseNotifications.push(event);
|
|
29514
|
+
},
|
|
29515
|
+
create: async ({
|
|
29516
|
+
btcBinanceData: lifecycleBtcBinanceData,
|
|
29517
|
+
btcCoinbaseData: lifecycleBtcCoinbaseData,
|
|
29518
|
+
onRuntimeClose
|
|
29519
|
+
}) => strategyCreator({
|
|
29520
|
+
userName: flags26.user,
|
|
29521
|
+
connectorName,
|
|
29522
|
+
runtimeConfigId: configId,
|
|
29523
|
+
runtimeConfigSnapshot: {
|
|
29524
|
+
userConfig: sourceStrategyConfig,
|
|
29525
|
+
symbolResultConfig: strategyResults?.[symbol]?.config ?? null
|
|
29526
|
+
},
|
|
29527
|
+
connector,
|
|
29528
|
+
symbol,
|
|
29529
|
+
...runtimeScopeUniverse ? {
|
|
29530
|
+
universe,
|
|
29531
|
+
assetClass: instrument?.assetClass,
|
|
29532
|
+
instrument,
|
|
29533
|
+
accountId,
|
|
29534
|
+
deploymentId
|
|
29535
|
+
} : {},
|
|
29536
|
+
data: previousData,
|
|
29537
|
+
btcData: universe === "crypto" ? previousBtcData : [],
|
|
29538
|
+
ethData: universe === "crypto" ? previousEthData : [],
|
|
29539
|
+
btcBinanceData: lifecycleBtcBinanceData,
|
|
29540
|
+
btcCoinbaseData: lifecycleBtcCoinbaseData,
|
|
29541
|
+
config: runtimeConfig,
|
|
29542
|
+
...persistStrategyState ? { sharedStrategyStateKey: lifecycleKey } : {},
|
|
29543
|
+
onRuntimeClose
|
|
29544
|
+
}),
|
|
29545
|
+
run: (strategy) => strategy(lastCandle, btcLastCandle, ethLastCandle)
|
|
29546
|
+
});
|
|
29547
|
+
} finally {
|
|
29548
|
+
previousData.length = initialDataLength;
|
|
29549
|
+
previousBtcData.length = initialBtcDataLength;
|
|
29550
|
+
previousEthData.length = initialEthDataLength;
|
|
29551
|
+
}
|
|
29424
29552
|
if (evaluation.action === "duplicate" || evaluation.action === "stale") {
|
|
29425
29553
|
continue;
|
|
29426
29554
|
}
|
|
@@ -29441,7 +29569,7 @@ var init_signals = __esm({
|
|
|
29441
29569
|
if (typeof signal === "string") {
|
|
29442
29570
|
recordStrategyReason(strategyStats, strategyName, signal, "core");
|
|
29443
29571
|
}
|
|
29444
|
-
await saveRuntimeSignalEvaluation({
|
|
29572
|
+
await saveRuntimeSignalEvaluation?.({
|
|
29445
29573
|
evaluationId: buildRuntimeSignalEvaluationId({
|
|
29446
29574
|
strategyName,
|
|
29447
29575
|
symbol,
|
|
@@ -29507,7 +29635,7 @@ var init_signals = __esm({
|
|
|
29507
29635
|
expire: runtimeSignalRetentionTtl
|
|
29508
29636
|
}
|
|
29509
29637
|
);
|
|
29510
|
-
await saveRuntimeSignalEvaluation({
|
|
29638
|
+
await saveRuntimeSignalEvaluation?.({
|
|
29511
29639
|
evaluationId: buildRuntimeSignalEvaluationId({
|
|
29512
29640
|
strategyName,
|
|
29513
29641
|
symbol,
|
|
@@ -29549,6 +29677,7 @@ var init_signals = __esm({
|
|
|
29549
29677
|
let activeSession;
|
|
29550
29678
|
let projectHooks;
|
|
29551
29679
|
let afterSignalsHookContext = null;
|
|
29680
|
+
const runtimeSignalEvaluations = createRuntimeSignalEvaluationBuffer();
|
|
29552
29681
|
try {
|
|
29553
29682
|
const session = options.session ?? await createSignalsSession(createDefaultSignalsLifecycle());
|
|
29554
29683
|
activeSession = session;
|
|
@@ -29660,7 +29789,12 @@ var init_signals = __esm({
|
|
|
29660
29789
|
if (flags26.updateOnly) {
|
|
29661
29790
|
return;
|
|
29662
29791
|
}
|
|
29663
|
-
const [
|
|
29792
|
+
const [
|
|
29793
|
+
btcBinanceData,
|
|
29794
|
+
btcCoinbaseData,
|
|
29795
|
+
primaryBtcCachedData,
|
|
29796
|
+
primaryEthCachedData
|
|
29797
|
+
] = universe === "crypto" ? await timeOperation3(
|
|
29664
29798
|
"reference candles load",
|
|
29665
29799
|
() => Promise.all([
|
|
29666
29800
|
btcReferences.binance.kline({
|
|
@@ -29676,9 +29810,36 @@ var init_signals = __esm({
|
|
|
29676
29810
|
end: currentTimestamp,
|
|
29677
29811
|
cacheOnly: true,
|
|
29678
29812
|
interval: interval5
|
|
29813
|
+
}),
|
|
29814
|
+
marketConnector.kline({
|
|
29815
|
+
symbol: "BTCUSDT",
|
|
29816
|
+
start: preloadStart,
|
|
29817
|
+
end: currentTimestamp,
|
|
29818
|
+
cacheOnly: true,
|
|
29819
|
+
interval: interval5
|
|
29820
|
+
}),
|
|
29821
|
+
marketConnector.kline({
|
|
29822
|
+
symbol: "ETHUSDT",
|
|
29823
|
+
start: preloadStart,
|
|
29824
|
+
end: currentTimestamp,
|
|
29825
|
+
cacheOnly: true,
|
|
29826
|
+
interval: interval5
|
|
29679
29827
|
})
|
|
29680
29828
|
])
|
|
29681
|
-
) : [[], []];
|
|
29829
|
+
) : [[], [], [], []];
|
|
29830
|
+
const primaryBtcClosedData = getClosedCandlesForInterval(
|
|
29831
|
+
primaryBtcCachedData,
|
|
29832
|
+
currentTimestamp,
|
|
29833
|
+
intervalMs2
|
|
29834
|
+
);
|
|
29835
|
+
const primaryEthClosedData = getClosedCandlesForInterval(
|
|
29836
|
+
primaryEthCachedData,
|
|
29837
|
+
currentTimestamp,
|
|
29838
|
+
intervalMs2
|
|
29839
|
+
);
|
|
29840
|
+
const primaryEthByTimestamp = new Map(
|
|
29841
|
+
primaryEthClosedData.map((candle) => [candle.timestamp, candle])
|
|
29842
|
+
);
|
|
29682
29843
|
const runtimeStrategies = await loadRuntimeStrategies({
|
|
29683
29844
|
userName: flags26.user,
|
|
29684
29845
|
projectRoot: projectRoot12,
|
|
@@ -29762,6 +29923,9 @@ var init_signals = __esm({
|
|
|
29762
29923
|
marketConnector,
|
|
29763
29924
|
btcBinanceData,
|
|
29764
29925
|
btcCoinbaseData,
|
|
29926
|
+
primaryBtcClosedData,
|
|
29927
|
+
primaryEthClosedData,
|
|
29928
|
+
primaryEthByTimestamp,
|
|
29765
29929
|
runtimeStrategies,
|
|
29766
29930
|
strategyStats,
|
|
29767
29931
|
runtimeCloseNotifications,
|
|
@@ -29775,7 +29939,8 @@ var init_signals = __esm({
|
|
|
29775
29939
|
accountId,
|
|
29776
29940
|
deployment?.id,
|
|
29777
29941
|
instrumentsBySymbol.get(symbol),
|
|
29778
|
-
sessionUniverse
|
|
29942
|
+
sessionUniverse,
|
|
29943
|
+
runtimeSignalEvaluations.save
|
|
29779
29944
|
);
|
|
29780
29945
|
if (strategySignals.length > 0) {
|
|
29781
29946
|
signals2.push(...strategySignals);
|
|
@@ -29816,6 +29981,14 @@ var init_signals = __esm({
|
|
|
29816
29981
|
);
|
|
29817
29982
|
throw error;
|
|
29818
29983
|
} finally {
|
|
29984
|
+
try {
|
|
29985
|
+
await runtimeSignalEvaluations.flush();
|
|
29986
|
+
} catch (error) {
|
|
29987
|
+
import_logger10.logger.error(
|
|
29988
|
+
"runtime signal evaluation flush failed: %s",
|
|
29989
|
+
error?.message || String(error)
|
|
29990
|
+
);
|
|
29991
|
+
}
|
|
29819
29992
|
const durationMs = Date.now() - startedAt;
|
|
29820
29993
|
if (activeSession?.deployment) {
|
|
29821
29994
|
await (0, import_tradingAccounts3.saveRuntimeDeploymentHeartbeat)(flags26.user, {
|
|
@@ -33812,7 +33985,7 @@ __export(signalsSummary_exports, {
|
|
|
33812
33985
|
main: () => main36,
|
|
33813
33986
|
signalsSummary: () => signalsSummary
|
|
33814
33987
|
});
|
|
33815
|
-
var import_config11, import_args29, import_logger12, import_connectors18, flags27, projectRoot13, SUMMARY_TIMEZONE2, SUMMARY_TIMEZONE_LABEL2, escapeHtml5, formatMskDateTime3, formatSigned3, formatPnlMoneyText, formatWinRateText, resolveSummaryTitle, normalizeStatus, shouldAttachDebugReport, getSummaryDateParts, formatSummaryIsoDayKey, unescapeHtml, stripTelegramHtml, buildSignalsSummaryAttachment, appendReportAttachmentSummary, resolveSummaryConnectorName, createRuntimeSignalStats, mergeRuntimeSignalStats, buildSummaryPrelude, resolveTradeStatusEmoji, isTimestampInWindow, isRuntimeTradeClosedInWindow, buildSummaryMessages, signalsSummary, main36;
|
|
33988
|
+
var import_config11, import_args29, import_logger12, import_connectors18, import_tradingAccounts4, flags27, projectRoot13, SUMMARY_TIMEZONE2, SUMMARY_TIMEZONE_LABEL2, escapeHtml5, formatMskDateTime3, formatSigned3, formatPnlMoneyText, formatWinRateText, resolveSummaryTitle, normalizeStatus, shouldAttachDebugReport, getSummaryDateParts, formatSummaryIsoDayKey, unescapeHtml, stripTelegramHtml, buildSignalsSummaryAttachment, appendReportAttachmentSummary, resolveSummaryConnectorName, groupRuntimeTradesByConnectorScope, syncRuntimeTradeScopes, createRuntimeSignalStats, mergeRuntimeSignalStats, buildSummaryPrelude, resolveTradeStatusEmoji, isTimestampInWindow, isRuntimeTradeClosedInWindow, buildSummaryMessages, signalsSummary, main36;
|
|
33816
33989
|
var init_signalsSummary = __esm({
|
|
33817
33990
|
"src/scripts/signalsSummary.ts"() {
|
|
33818
33991
|
"use strict";
|
|
@@ -33826,6 +33999,7 @@ var init_signalsSummary = __esm({
|
|
|
33826
33999
|
init_runtimeSignalsLoader();
|
|
33827
34000
|
init_runtimeSignalsStorage();
|
|
33828
34001
|
init_runtimeDebugEvidence();
|
|
34002
|
+
import_tradingAccounts4 = require("@tradejs/infra/tradingAccounts");
|
|
33829
34003
|
import_args29.default.option(["u", "user"], "Use user config", "root");
|
|
33830
34004
|
import_args29.default.option(
|
|
33831
34005
|
"connector",
|
|
@@ -33938,6 +34112,108 @@ var init_signalsSummary = __esm({
|
|
|
33938
34112
|
);
|
|
33939
34113
|
return import_connectors18.DEFAULT_CONNECTOR_NAME;
|
|
33940
34114
|
};
|
|
34115
|
+
groupRuntimeTradesByConnectorScope = ({
|
|
34116
|
+
trades,
|
|
34117
|
+
deployments,
|
|
34118
|
+
fallbackConnectorName
|
|
34119
|
+
}) => {
|
|
34120
|
+
const deploymentById = new Map(
|
|
34121
|
+
deployments.map((deployment) => [deployment.id, deployment])
|
|
34122
|
+
);
|
|
34123
|
+
const scopes = /* @__PURE__ */ new Map();
|
|
34124
|
+
for (const trade of trades) {
|
|
34125
|
+
const deployment = trade.deploymentId ? deploymentById.get(trade.deploymentId) : void 0;
|
|
34126
|
+
const connectorName = deployment?.connectorName ?? fallbackConnectorName;
|
|
34127
|
+
const universe = trade.universe ?? deployment?.universe ?? "crypto";
|
|
34128
|
+
const accountId = trade.accountId ?? deployment?.accountId;
|
|
34129
|
+
const deploymentId = trade.deploymentId;
|
|
34130
|
+
const scopeKey = JSON.stringify([
|
|
34131
|
+
connectorName,
|
|
34132
|
+
universe,
|
|
34133
|
+
accountId ?? null,
|
|
34134
|
+
deploymentId ?? null
|
|
34135
|
+
]);
|
|
34136
|
+
const scope = scopes.get(scopeKey) ?? {
|
|
34137
|
+
connectorName,
|
|
34138
|
+
universe,
|
|
34139
|
+
...accountId ? { accountId } : {},
|
|
34140
|
+
...deploymentId ? { deploymentId } : {},
|
|
34141
|
+
trades: []
|
|
34142
|
+
};
|
|
34143
|
+
scope.trades.push(trade);
|
|
34144
|
+
scopes.set(scopeKey, scope);
|
|
34145
|
+
}
|
|
34146
|
+
return [...scopes.values()];
|
|
34147
|
+
};
|
|
34148
|
+
syncRuntimeTradeScopes = async ({
|
|
34149
|
+
userName: userName2,
|
|
34150
|
+
startTime,
|
|
34151
|
+
endTime,
|
|
34152
|
+
fallbackConnectorName,
|
|
34153
|
+
trades,
|
|
34154
|
+
deployments
|
|
34155
|
+
}) => {
|
|
34156
|
+
const scopes = groupRuntimeTradesByConnectorScope({
|
|
34157
|
+
trades,
|
|
34158
|
+
deployments,
|
|
34159
|
+
fallbackConnectorName
|
|
34160
|
+
});
|
|
34161
|
+
const syncedTrades = [];
|
|
34162
|
+
const connectorNames = /* @__PURE__ */ new Set();
|
|
34163
|
+
for (const scope of scopes) {
|
|
34164
|
+
const connectorName = await resolveSummaryConnectorName(
|
|
34165
|
+
scope.connectorName
|
|
34166
|
+
);
|
|
34167
|
+
const connectorFactory = await (0, import_connectors18.getConnectorCreatorByName)(
|
|
34168
|
+
connectorName,
|
|
34169
|
+
projectRoot13
|
|
34170
|
+
);
|
|
34171
|
+
if (!connectorFactory) {
|
|
34172
|
+
throw new Error(`Connector "${connectorName}" is not registered`);
|
|
34173
|
+
}
|
|
34174
|
+
const connector = await connectorFactory({
|
|
34175
|
+
userName: userName2,
|
|
34176
|
+
universe: scope.universe,
|
|
34177
|
+
accountId: scope.accountId,
|
|
34178
|
+
deploymentId: scope.deploymentId
|
|
34179
|
+
});
|
|
34180
|
+
connectorNames.add(connectorName);
|
|
34181
|
+
syncedTrades.push(
|
|
34182
|
+
...await syncRuntimeTrades({
|
|
34183
|
+
userName: userName2,
|
|
34184
|
+
connector,
|
|
34185
|
+
trades: scope.trades,
|
|
34186
|
+
startTime,
|
|
34187
|
+
endTime,
|
|
34188
|
+
openPositionCallbacks: {
|
|
34189
|
+
onError: (error) => {
|
|
34190
|
+
import_logger12.logger.warn(
|
|
34191
|
+
"signals summary: getOpenPositionPnl failed for scope account=%s deployment=%s: %s",
|
|
34192
|
+
scope.accountId ?? "default",
|
|
34193
|
+
scope.deploymentId ?? "default",
|
|
34194
|
+
formatRuntimeTradeSyncError(error)
|
|
34195
|
+
);
|
|
34196
|
+
}
|
|
34197
|
+
},
|
|
34198
|
+
closedPnlCallbacks: {
|
|
34199
|
+
onError: (error) => {
|
|
34200
|
+
import_logger12.logger.warn(
|
|
34201
|
+
"signals summary: getClosedPnl failed for scope account=%s deployment=%s: %s",
|
|
34202
|
+
scope.accountId ?? "default",
|
|
34203
|
+
scope.deploymentId ?? "default",
|
|
34204
|
+
formatRuntimeTradeSyncError(error)
|
|
34205
|
+
);
|
|
34206
|
+
}
|
|
34207
|
+
}
|
|
34208
|
+
})
|
|
34209
|
+
);
|
|
34210
|
+
}
|
|
34211
|
+
return {
|
|
34212
|
+
trades: syncedTrades,
|
|
34213
|
+
connectorNames: [...connectorNames].sort(),
|
|
34214
|
+
scopesCount: scopes.length
|
|
34215
|
+
};
|
|
34216
|
+
};
|
|
33941
34217
|
createRuntimeSignalStats = () => ({
|
|
33942
34218
|
evaluated: 0,
|
|
33943
34219
|
signals: 0,
|
|
@@ -34247,46 +34523,35 @@ none`
|
|
|
34247
34523
|
);
|
|
34248
34524
|
const endTime = Date.now();
|
|
34249
34525
|
const startTime = endTime - hours * 60 * 60 * 1e3;
|
|
34250
|
-
const
|
|
34251
|
-
|
|
34252
|
-
connectorName,
|
|
34253
|
-
projectRoot13
|
|
34526
|
+
const fallbackConnectorName = await resolveSummaryConnectorName(
|
|
34527
|
+
flags27.connector
|
|
34254
34528
|
);
|
|
34255
|
-
|
|
34256
|
-
|
|
34257
|
-
|
|
34258
|
-
|
|
34259
|
-
|
|
34260
|
-
|
|
34261
|
-
|
|
34529
|
+
const [
|
|
34530
|
+
configuredStrategyNames,
|
|
34531
|
+
signals2,
|
|
34532
|
+
evaluationStatsBuckets,
|
|
34533
|
+
trades,
|
|
34534
|
+
runtimeDeployments
|
|
34535
|
+
] = await Promise.all([
|
|
34262
34536
|
loadRuntimeStrategyNames(flags27.user),
|
|
34263
34537
|
loadRuntimeSignals(flags27.user, { startTime, endTime }),
|
|
34264
34538
|
loadRuntimeSignalEvaluationStatsBuckets(flags27.user),
|
|
34265
|
-
loadRuntimeTrades(flags27.user)
|
|
34539
|
+
loadRuntimeTrades(flags27.user),
|
|
34540
|
+
(0, import_tradingAccounts4.listRuntimeDeployments)(flags27.user)
|
|
34266
34541
|
]);
|
|
34267
|
-
const
|
|
34542
|
+
const {
|
|
34543
|
+
trades: syncedTrades,
|
|
34544
|
+
connectorNames,
|
|
34545
|
+
scopesCount
|
|
34546
|
+
} = await syncRuntimeTradeScopes({
|
|
34268
34547
|
userName: flags27.user,
|
|
34269
|
-
connector,
|
|
34270
|
-
trades,
|
|
34271
34548
|
startTime,
|
|
34272
34549
|
endTime,
|
|
34273
|
-
|
|
34274
|
-
|
|
34275
|
-
|
|
34276
|
-
"signals summary: getOpenPositionPnl failed: %s",
|
|
34277
|
-
formatRuntimeTradeSyncError(error)
|
|
34278
|
-
);
|
|
34279
|
-
}
|
|
34280
|
-
},
|
|
34281
|
-
closedPnlCallbacks: {
|
|
34282
|
-
onError: (error) => {
|
|
34283
|
-
import_logger12.logger.warn(
|
|
34284
|
-
"signals summary: getClosedPnl failed: %s",
|
|
34285
|
-
formatRuntimeTradeSyncError(error)
|
|
34286
|
-
);
|
|
34287
|
-
}
|
|
34288
|
-
}
|
|
34550
|
+
fallbackConnectorName,
|
|
34551
|
+
trades,
|
|
34552
|
+
deployments: runtimeDeployments
|
|
34289
34553
|
});
|
|
34554
|
+
const activeTradeOrderIds = await loadRuntimeActiveTradeOrderIds(flags27.user);
|
|
34290
34555
|
const windowSignals = signals2.filter(
|
|
34291
34556
|
(signal) => signal.timestamp >= startTime && signal.timestamp < endTime
|
|
34292
34557
|
);
|
|
@@ -34304,7 +34569,7 @@ none`
|
|
|
34304
34569
|
(trade) => isRuntimeTradeClosedInWindow(trade, startTime, endTime)
|
|
34305
34570
|
);
|
|
34306
34571
|
const openSnapshotTrades = syncedTrades.filter(
|
|
34307
|
-
(trade) => trade.status === "active" && typeof trade.entryTimestamp === "number" && Number.isFinite(trade.entryTimestamp) && trade.entryTimestamp < endTime
|
|
34572
|
+
(trade) => trade.status === "active" && activeTradeOrderIds.has(trade.orderId) && typeof trade.entryTimestamp === "number" && Number.isFinite(trade.entryTimestamp) && trade.entryTimestamp < endTime
|
|
34308
34573
|
);
|
|
34309
34574
|
const windowTrades = [...windowClosedTrades, ...openSnapshotTrades];
|
|
34310
34575
|
const windowTradeSignalIds = new Set(
|
|
@@ -34327,12 +34592,13 @@ none`
|
|
|
34327
34592
|
0
|
|
34328
34593
|
);
|
|
34329
34594
|
import_logger12.logger.info(
|
|
34330
|
-
"signals summary window=%sh signals=%s evaluations=%s trades=%s
|
|
34595
|
+
"signals summary window=%sh signals=%s evaluations=%s trades=%s connectors=%s scopes=%s user=%s",
|
|
34331
34596
|
hours,
|
|
34332
34597
|
windowSignals.length,
|
|
34333
34598
|
windowEvaluationsCount,
|
|
34334
34599
|
windowClosedTrades.length,
|
|
34335
|
-
|
|
34600
|
+
connectorNames.join(",") || fallbackConnectorName,
|
|
34601
|
+
scopesCount,
|
|
34336
34602
|
flags27.user
|
|
34337
34603
|
);
|
|
34338
34604
|
const debugAttachment = shouldAttachDebugReport(flags27.debugAttachment) ? await buildRuntimeDebugReportAttachment({
|