@tradejs/cli 2.0.9 → 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
CHANGED
|
@@ -11160,7 +11160,7 @@ var init_timeWindow = __esm({
|
|
|
11160
11160
|
});
|
|
11161
11161
|
|
|
11162
11162
|
// src/lib/runtimeRedis.ts
|
|
11163
|
-
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;
|
|
11164
11164
|
var init_runtimeRedis = __esm({
|
|
11165
11165
|
"src/lib/runtimeRedis.ts"() {
|
|
11166
11166
|
"use strict";
|
|
@@ -11264,6 +11264,15 @@ var init_runtimeRedis = __esm({
|
|
|
11264
11264
|
const trades = await Promise.all(keys.map((key) => (0, import_redis4.getData)(key, null)));
|
|
11265
11265
|
return trades.filter(isRuntimeTradeRecord).filter(filterByWindow).sort((left, right) => left.entryTimestamp - right.entryTimestamp);
|
|
11266
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
|
+
};
|
|
11267
11276
|
loadStrategyResultSymbols = async ({
|
|
11268
11277
|
userName: userName2,
|
|
11269
11278
|
strategy
|
|
@@ -24892,7 +24901,8 @@ var init_runtimeDebugEvidence = __esm({
|
|
|
24892
24901
|
);
|
|
24893
24902
|
const activeTradeKey = import_redis14.redisKeys.runtimeActiveTrade(
|
|
24894
24903
|
userName2,
|
|
24895
|
-
trade.symbol
|
|
24904
|
+
trade.symbol,
|
|
24905
|
+
trade.deploymentId ?? trade.accountId
|
|
24896
24906
|
);
|
|
24897
24907
|
const signalKey = trade.signalId != null ? import_redis14.redisKeys.storeSignal(trade.symbol, trade.signalId) : null;
|
|
24898
24908
|
const evaluationBucketKey = import_redis14.redisKeys.runtimeSignalEvaluationBucket(
|
|
@@ -33975,7 +33985,7 @@ __export(signalsSummary_exports, {
|
|
|
33975
33985
|
main: () => main36,
|
|
33976
33986
|
signalsSummary: () => signalsSummary
|
|
33977
33987
|
});
|
|
33978
|
-
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;
|
|
33979
33989
|
var init_signalsSummary = __esm({
|
|
33980
33990
|
"src/scripts/signalsSummary.ts"() {
|
|
33981
33991
|
"use strict";
|
|
@@ -33989,6 +33999,7 @@ var init_signalsSummary = __esm({
|
|
|
33989
33999
|
init_runtimeSignalsLoader();
|
|
33990
34000
|
init_runtimeSignalsStorage();
|
|
33991
34001
|
init_runtimeDebugEvidence();
|
|
34002
|
+
import_tradingAccounts4 = require("@tradejs/infra/tradingAccounts");
|
|
33992
34003
|
import_args29.default.option(["u", "user"], "Use user config", "root");
|
|
33993
34004
|
import_args29.default.option(
|
|
33994
34005
|
"connector",
|
|
@@ -34101,6 +34112,108 @@ var init_signalsSummary = __esm({
|
|
|
34101
34112
|
);
|
|
34102
34113
|
return import_connectors18.DEFAULT_CONNECTOR_NAME;
|
|
34103
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
|
+
};
|
|
34104
34217
|
createRuntimeSignalStats = () => ({
|
|
34105
34218
|
evaluated: 0,
|
|
34106
34219
|
signals: 0,
|
|
@@ -34410,46 +34523,35 @@ none`
|
|
|
34410
34523
|
);
|
|
34411
34524
|
const endTime = Date.now();
|
|
34412
34525
|
const startTime = endTime - hours * 60 * 60 * 1e3;
|
|
34413
|
-
const
|
|
34414
|
-
|
|
34415
|
-
connectorName,
|
|
34416
|
-
projectRoot13
|
|
34526
|
+
const fallbackConnectorName = await resolveSummaryConnectorName(
|
|
34527
|
+
flags27.connector
|
|
34417
34528
|
);
|
|
34418
|
-
|
|
34419
|
-
|
|
34420
|
-
|
|
34421
|
-
|
|
34422
|
-
|
|
34423
|
-
|
|
34424
|
-
|
|
34529
|
+
const [
|
|
34530
|
+
configuredStrategyNames,
|
|
34531
|
+
signals2,
|
|
34532
|
+
evaluationStatsBuckets,
|
|
34533
|
+
trades,
|
|
34534
|
+
runtimeDeployments
|
|
34535
|
+
] = await Promise.all([
|
|
34425
34536
|
loadRuntimeStrategyNames(flags27.user),
|
|
34426
34537
|
loadRuntimeSignals(flags27.user, { startTime, endTime }),
|
|
34427
34538
|
loadRuntimeSignalEvaluationStatsBuckets(flags27.user),
|
|
34428
|
-
loadRuntimeTrades(flags27.user)
|
|
34539
|
+
loadRuntimeTrades(flags27.user),
|
|
34540
|
+
(0, import_tradingAccounts4.listRuntimeDeployments)(flags27.user)
|
|
34429
34541
|
]);
|
|
34430
|
-
const
|
|
34542
|
+
const {
|
|
34543
|
+
trades: syncedTrades,
|
|
34544
|
+
connectorNames,
|
|
34545
|
+
scopesCount
|
|
34546
|
+
} = await syncRuntimeTradeScopes({
|
|
34431
34547
|
userName: flags27.user,
|
|
34432
|
-
connector,
|
|
34433
|
-
trades,
|
|
34434
34548
|
startTime,
|
|
34435
34549
|
endTime,
|
|
34436
|
-
|
|
34437
|
-
|
|
34438
|
-
|
|
34439
|
-
"signals summary: getOpenPositionPnl failed: %s",
|
|
34440
|
-
formatRuntimeTradeSyncError(error)
|
|
34441
|
-
);
|
|
34442
|
-
}
|
|
34443
|
-
},
|
|
34444
|
-
closedPnlCallbacks: {
|
|
34445
|
-
onError: (error) => {
|
|
34446
|
-
import_logger12.logger.warn(
|
|
34447
|
-
"signals summary: getClosedPnl failed: %s",
|
|
34448
|
-
formatRuntimeTradeSyncError(error)
|
|
34449
|
-
);
|
|
34450
|
-
}
|
|
34451
|
-
}
|
|
34550
|
+
fallbackConnectorName,
|
|
34551
|
+
trades,
|
|
34552
|
+
deployments: runtimeDeployments
|
|
34452
34553
|
});
|
|
34554
|
+
const activeTradeOrderIds = await loadRuntimeActiveTradeOrderIds(flags27.user);
|
|
34453
34555
|
const windowSignals = signals2.filter(
|
|
34454
34556
|
(signal) => signal.timestamp >= startTime && signal.timestamp < endTime
|
|
34455
34557
|
);
|
|
@@ -34467,7 +34569,7 @@ none`
|
|
|
34467
34569
|
(trade) => isRuntimeTradeClosedInWindow(trade, startTime, endTime)
|
|
34468
34570
|
);
|
|
34469
34571
|
const openSnapshotTrades = syncedTrades.filter(
|
|
34470
|
-
(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
|
|
34471
34573
|
);
|
|
34472
34574
|
const windowTrades = [...windowClosedTrades, ...openSnapshotTrades];
|
|
34473
34575
|
const windowTradeSignalIds = new Set(
|
|
@@ -34490,12 +34592,13 @@ none`
|
|
|
34490
34592
|
0
|
|
34491
34593
|
);
|
|
34492
34594
|
import_logger12.logger.info(
|
|
34493
|
-
"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",
|
|
34494
34596
|
hours,
|
|
34495
34597
|
windowSignals.length,
|
|
34496
34598
|
windowEvaluationsCount,
|
|
34497
34599
|
windowClosedTrades.length,
|
|
34498
|
-
|
|
34600
|
+
connectorNames.join(",") || fallbackConnectorName,
|
|
34601
|
+
scopesCount,
|
|
34499
34602
|
flags27.user
|
|
34500
34603
|
);
|
|
34501
34604
|
const debugAttachment = shouldAttachDebugReport(flags27.debugAttachment) ? await buildRuntimeDebugReportAttachment({
|
|
@@ -382,7 +382,8 @@ var buildRuntimeDebugReportPayload = async ({
|
|
|
382
382
|
);
|
|
383
383
|
const activeTradeKey = import_redis3.redisKeys.runtimeActiveTrade(
|
|
384
384
|
userName,
|
|
385
|
-
trade.symbol
|
|
385
|
+
trade.symbol,
|
|
386
|
+
trade.deploymentId ?? trade.accountId
|
|
386
387
|
);
|
|
387
388
|
const signalKey = trade.signalId != null ? import_redis3.redisKeys.storeSignal(trade.symbol, trade.signalId) : null;
|
|
388
389
|
const evaluationBucketKey = import_redis3.redisKeys.runtimeSignalEvaluationBucket(
|
package/dist/lib/runtimeRedis.js
CHANGED
|
@@ -23,6 +23,7 @@ __export(runtimeRedis_exports, {
|
|
|
23
23
|
getRuntimeStrategyConfigKeys: () => getRuntimeStrategyConfigKeys,
|
|
24
24
|
isRuntimeStrategyEnabled: () => isRuntimeStrategyEnabled,
|
|
25
25
|
isRuntimeTradeRecord: () => isRuntimeTradeRecord,
|
|
26
|
+
loadRuntimeActiveTradeOrderIds: () => loadRuntimeActiveTradeOrderIds,
|
|
26
27
|
loadRuntimeStrategyConfigs: () => loadRuntimeStrategyConfigs,
|
|
27
28
|
loadRuntimeStrategyNames: () => loadRuntimeStrategyNames,
|
|
28
29
|
loadRuntimeTrades: () => loadRuntimeTrades,
|
|
@@ -131,6 +132,15 @@ var loadRuntimeTrades = async (userName, {
|
|
|
131
132
|
const trades = await Promise.all(keys.map((key) => (0, import_redis.getData)(key, null)));
|
|
132
133
|
return trades.filter(isRuntimeTradeRecord).filter(filterByWindow).sort((left, right) => left.entryTimestamp - right.entryTimestamp);
|
|
133
134
|
};
|
|
135
|
+
var loadRuntimeActiveTradeOrderIds = async (userName) => {
|
|
136
|
+
const keys = await (0, import_redis.getKeys)(import_redis.redisKeys.runtimeActiveTrades(userName));
|
|
137
|
+
const refs = await Promise.all(keys.map((key) => (0, import_redis.getData)(key, null)));
|
|
138
|
+
return new Set(
|
|
139
|
+
refs.map(
|
|
140
|
+
(ref) => ref && typeof ref === "object" && "orderId" in ref && typeof ref.orderId === "string" && ref.orderId.trim() ? ref.orderId.trim() : null
|
|
141
|
+
).filter((orderId) => orderId != null)
|
|
142
|
+
);
|
|
143
|
+
};
|
|
134
144
|
var loadStrategyResultSymbols = async ({
|
|
135
145
|
userName,
|
|
136
146
|
strategy
|
|
@@ -148,6 +158,7 @@ var loadStrategyResultSymbols = async ({
|
|
|
148
158
|
getRuntimeStrategyConfigKeys,
|
|
149
159
|
isRuntimeStrategyEnabled,
|
|
150
160
|
isRuntimeTradeRecord,
|
|
161
|
+
loadRuntimeActiveTradeOrderIds,
|
|
151
162
|
loadRuntimeStrategyConfigs,
|
|
152
163
|
loadRuntimeStrategyNames,
|
|
153
164
|
loadRuntimeTrades,
|
|
@@ -382,7 +382,8 @@ var buildRuntimeDebugReportPayload = async ({
|
|
|
382
382
|
);
|
|
383
383
|
const activeTradeKey = import_redis3.redisKeys.runtimeActiveTrade(
|
|
384
384
|
userName,
|
|
385
|
-
trade.symbol
|
|
385
|
+
trade.symbol,
|
|
386
|
+
trade.deploymentId ?? trade.accountId
|
|
386
387
|
);
|
|
387
388
|
const signalKey = trade.signalId != null ? import_redis3.redisKeys.storeSignal(trade.symbol, trade.signalId) : null;
|
|
388
389
|
const evaluationBucketKey = import_redis3.redisKeys.runtimeSignalEvaluationBucket(
|
|
@@ -381,7 +381,8 @@ var buildRuntimeDebugReportPayload = async ({
|
|
|
381
381
|
);
|
|
382
382
|
const activeTradeKey = import_redis3.redisKeys.runtimeActiveTrade(
|
|
383
383
|
userName,
|
|
384
|
-
trade.symbol
|
|
384
|
+
trade.symbol,
|
|
385
|
+
trade.deploymentId ?? trade.accountId
|
|
385
386
|
);
|
|
386
387
|
const signalKey = trade.signalId != null ? import_redis3.redisKeys.storeSignal(trade.symbol, trade.signalId) : null;
|
|
387
388
|
const evaluationBucketKey = import_redis3.redisKeys.runtimeSignalEvaluationBucket(
|
|
@@ -107,6 +107,15 @@ var loadRuntimeTrades = async (userName, {
|
|
|
107
107
|
const trades = await Promise.all(keys.map((key) => (0, import_redis.getData)(key, null)));
|
|
108
108
|
return trades.filter(isRuntimeTradeRecord).filter(filterByWindow).sort((left, right) => left.entryTimestamp - right.entryTimestamp);
|
|
109
109
|
};
|
|
110
|
+
var loadRuntimeActiveTradeOrderIds = async (userName) => {
|
|
111
|
+
const keys = await (0, import_redis.getKeys)(import_redis.redisKeys.runtimeActiveTrades(userName));
|
|
112
|
+
const refs = await Promise.all(keys.map((key) => (0, import_redis.getData)(key, null)));
|
|
113
|
+
return new Set(
|
|
114
|
+
refs.map(
|
|
115
|
+
(ref) => ref && typeof ref === "object" && "orderId" in ref && typeof ref.orderId === "string" && ref.orderId.trim() ? ref.orderId.trim() : null
|
|
116
|
+
).filter((orderId) => orderId != null)
|
|
117
|
+
);
|
|
118
|
+
};
|
|
110
119
|
|
|
111
120
|
// src/lib/runtimeTradeSync.ts
|
|
112
121
|
var import_constants = require("@tradejs/core/constants");
|
|
@@ -636,7 +645,8 @@ var buildRuntimeDebugReportPayload = async ({
|
|
|
636
645
|
);
|
|
637
646
|
const activeTradeKey = import_redis4.redisKeys.runtimeActiveTrade(
|
|
638
647
|
userName,
|
|
639
|
-
trade.symbol
|
|
648
|
+
trade.symbol,
|
|
649
|
+
trade.deploymentId ?? trade.accountId
|
|
640
650
|
);
|
|
641
651
|
const signalKey = trade.signalId != null ? import_redis4.redisKeys.storeSignal(trade.symbol, trade.signalId) : null;
|
|
642
652
|
const evaluationBucketKey = import_redis4.redisKeys.runtimeSignalEvaluationBucket(
|
|
@@ -771,6 +781,7 @@ var buildRuntimeDebugReportAttachment = async (params) => {
|
|
|
771
781
|
};
|
|
772
782
|
|
|
773
783
|
// src/scripts/signalsSummary.ts
|
|
784
|
+
var import_tradingAccounts = require("@tradejs/infra/tradingAccounts");
|
|
774
785
|
import_args.default.option(["u", "user"], "Use user config", "root");
|
|
775
786
|
import_args.default.option(
|
|
776
787
|
"connector",
|
|
@@ -883,6 +894,108 @@ var resolveSummaryConnectorName = async (value) => {
|
|
|
883
894
|
);
|
|
884
895
|
return import_connectors.DEFAULT_CONNECTOR_NAME;
|
|
885
896
|
};
|
|
897
|
+
var groupRuntimeTradesByConnectorScope = ({
|
|
898
|
+
trades,
|
|
899
|
+
deployments,
|
|
900
|
+
fallbackConnectorName
|
|
901
|
+
}) => {
|
|
902
|
+
const deploymentById = new Map(
|
|
903
|
+
deployments.map((deployment) => [deployment.id, deployment])
|
|
904
|
+
);
|
|
905
|
+
const scopes = /* @__PURE__ */ new Map();
|
|
906
|
+
for (const trade of trades) {
|
|
907
|
+
const deployment = trade.deploymentId ? deploymentById.get(trade.deploymentId) : void 0;
|
|
908
|
+
const connectorName = deployment?.connectorName ?? fallbackConnectorName;
|
|
909
|
+
const universe = trade.universe ?? deployment?.universe ?? "crypto";
|
|
910
|
+
const accountId = trade.accountId ?? deployment?.accountId;
|
|
911
|
+
const deploymentId = trade.deploymentId;
|
|
912
|
+
const scopeKey = JSON.stringify([
|
|
913
|
+
connectorName,
|
|
914
|
+
universe,
|
|
915
|
+
accountId ?? null,
|
|
916
|
+
deploymentId ?? null
|
|
917
|
+
]);
|
|
918
|
+
const scope = scopes.get(scopeKey) ?? {
|
|
919
|
+
connectorName,
|
|
920
|
+
universe,
|
|
921
|
+
...accountId ? { accountId } : {},
|
|
922
|
+
...deploymentId ? { deploymentId } : {},
|
|
923
|
+
trades: []
|
|
924
|
+
};
|
|
925
|
+
scope.trades.push(trade);
|
|
926
|
+
scopes.set(scopeKey, scope);
|
|
927
|
+
}
|
|
928
|
+
return [...scopes.values()];
|
|
929
|
+
};
|
|
930
|
+
var syncRuntimeTradeScopes = async ({
|
|
931
|
+
userName,
|
|
932
|
+
startTime,
|
|
933
|
+
endTime,
|
|
934
|
+
fallbackConnectorName,
|
|
935
|
+
trades,
|
|
936
|
+
deployments
|
|
937
|
+
}) => {
|
|
938
|
+
const scopes = groupRuntimeTradesByConnectorScope({
|
|
939
|
+
trades,
|
|
940
|
+
deployments,
|
|
941
|
+
fallbackConnectorName
|
|
942
|
+
});
|
|
943
|
+
const syncedTrades = [];
|
|
944
|
+
const connectorNames = /* @__PURE__ */ new Set();
|
|
945
|
+
for (const scope of scopes) {
|
|
946
|
+
const connectorName = await resolveSummaryConnectorName(
|
|
947
|
+
scope.connectorName
|
|
948
|
+
);
|
|
949
|
+
const connectorFactory = await (0, import_connectors.getConnectorCreatorByName)(
|
|
950
|
+
connectorName,
|
|
951
|
+
projectRoot
|
|
952
|
+
);
|
|
953
|
+
if (!connectorFactory) {
|
|
954
|
+
throw new Error(`Connector "${connectorName}" is not registered`);
|
|
955
|
+
}
|
|
956
|
+
const connector = await connectorFactory({
|
|
957
|
+
userName,
|
|
958
|
+
universe: scope.universe,
|
|
959
|
+
accountId: scope.accountId,
|
|
960
|
+
deploymentId: scope.deploymentId
|
|
961
|
+
});
|
|
962
|
+
connectorNames.add(connectorName);
|
|
963
|
+
syncedTrades.push(
|
|
964
|
+
...await syncRuntimeTrades({
|
|
965
|
+
userName,
|
|
966
|
+
connector,
|
|
967
|
+
trades: scope.trades,
|
|
968
|
+
startTime,
|
|
969
|
+
endTime,
|
|
970
|
+
openPositionCallbacks: {
|
|
971
|
+
onError: (error) => {
|
|
972
|
+
import_logger.logger.warn(
|
|
973
|
+
"signals summary: getOpenPositionPnl failed for scope account=%s deployment=%s: %s",
|
|
974
|
+
scope.accountId ?? "default",
|
|
975
|
+
scope.deploymentId ?? "default",
|
|
976
|
+
formatRuntimeTradeSyncError(error)
|
|
977
|
+
);
|
|
978
|
+
}
|
|
979
|
+
},
|
|
980
|
+
closedPnlCallbacks: {
|
|
981
|
+
onError: (error) => {
|
|
982
|
+
import_logger.logger.warn(
|
|
983
|
+
"signals summary: getClosedPnl failed for scope account=%s deployment=%s: %s",
|
|
984
|
+
scope.accountId ?? "default",
|
|
985
|
+
scope.deploymentId ?? "default",
|
|
986
|
+
formatRuntimeTradeSyncError(error)
|
|
987
|
+
);
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
})
|
|
991
|
+
);
|
|
992
|
+
}
|
|
993
|
+
return {
|
|
994
|
+
trades: syncedTrades,
|
|
995
|
+
connectorNames: [...connectorNames].sort(),
|
|
996
|
+
scopesCount: scopes.length
|
|
997
|
+
};
|
|
998
|
+
};
|
|
886
999
|
var createRuntimeSignalStats = () => ({
|
|
887
1000
|
evaluated: 0,
|
|
888
1001
|
signals: 0,
|
|
@@ -1192,46 +1305,35 @@ var signalsSummary = async () => {
|
|
|
1192
1305
|
);
|
|
1193
1306
|
const endTime = Date.now();
|
|
1194
1307
|
const startTime = endTime - hours * 60 * 60 * 1e3;
|
|
1195
|
-
const
|
|
1196
|
-
|
|
1197
|
-
connectorName,
|
|
1198
|
-
projectRoot
|
|
1308
|
+
const fallbackConnectorName = await resolveSummaryConnectorName(
|
|
1309
|
+
flags.connector
|
|
1199
1310
|
);
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1311
|
+
const [
|
|
1312
|
+
configuredStrategyNames,
|
|
1313
|
+
signals,
|
|
1314
|
+
evaluationStatsBuckets,
|
|
1315
|
+
trades,
|
|
1316
|
+
runtimeDeployments
|
|
1317
|
+
] = await Promise.all([
|
|
1207
1318
|
loadRuntimeStrategyNames(flags.user),
|
|
1208
1319
|
loadRuntimeSignals(flags.user, { startTime, endTime }),
|
|
1209
1320
|
loadRuntimeSignalEvaluationStatsBuckets(flags.user),
|
|
1210
|
-
loadRuntimeTrades(flags.user)
|
|
1321
|
+
loadRuntimeTrades(flags.user),
|
|
1322
|
+
(0, import_tradingAccounts.listRuntimeDeployments)(flags.user)
|
|
1211
1323
|
]);
|
|
1212
|
-
const
|
|
1324
|
+
const {
|
|
1325
|
+
trades: syncedTrades,
|
|
1326
|
+
connectorNames,
|
|
1327
|
+
scopesCount
|
|
1328
|
+
} = await syncRuntimeTradeScopes({
|
|
1213
1329
|
userName: flags.user,
|
|
1214
|
-
connector,
|
|
1215
|
-
trades,
|
|
1216
1330
|
startTime,
|
|
1217
1331
|
endTime,
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
"signals summary: getOpenPositionPnl failed: %s",
|
|
1222
|
-
formatRuntimeTradeSyncError(error)
|
|
1223
|
-
);
|
|
1224
|
-
}
|
|
1225
|
-
},
|
|
1226
|
-
closedPnlCallbacks: {
|
|
1227
|
-
onError: (error) => {
|
|
1228
|
-
import_logger.logger.warn(
|
|
1229
|
-
"signals summary: getClosedPnl failed: %s",
|
|
1230
|
-
formatRuntimeTradeSyncError(error)
|
|
1231
|
-
);
|
|
1232
|
-
}
|
|
1233
|
-
}
|
|
1332
|
+
fallbackConnectorName,
|
|
1333
|
+
trades,
|
|
1334
|
+
deployments: runtimeDeployments
|
|
1234
1335
|
});
|
|
1336
|
+
const activeTradeOrderIds = await loadRuntimeActiveTradeOrderIds(flags.user);
|
|
1235
1337
|
const windowSignals = signals.filter(
|
|
1236
1338
|
(signal) => signal.timestamp >= startTime && signal.timestamp < endTime
|
|
1237
1339
|
);
|
|
@@ -1249,7 +1351,7 @@ var signalsSummary = async () => {
|
|
|
1249
1351
|
(trade) => isRuntimeTradeClosedInWindow(trade, startTime, endTime)
|
|
1250
1352
|
);
|
|
1251
1353
|
const openSnapshotTrades = syncedTrades.filter(
|
|
1252
|
-
(trade) => trade.status === "active" && typeof trade.entryTimestamp === "number" && Number.isFinite(trade.entryTimestamp) && trade.entryTimestamp < endTime
|
|
1354
|
+
(trade) => trade.status === "active" && activeTradeOrderIds.has(trade.orderId) && typeof trade.entryTimestamp === "number" && Number.isFinite(trade.entryTimestamp) && trade.entryTimestamp < endTime
|
|
1253
1355
|
);
|
|
1254
1356
|
const windowTrades = [...windowClosedTrades, ...openSnapshotTrades];
|
|
1255
1357
|
const windowTradeSignalIds = new Set(
|
|
@@ -1272,12 +1374,13 @@ var signalsSummary = async () => {
|
|
|
1272
1374
|
0
|
|
1273
1375
|
);
|
|
1274
1376
|
import_logger.logger.info(
|
|
1275
|
-
"signals summary window=%sh signals=%s evaluations=%s trades=%s
|
|
1377
|
+
"signals summary window=%sh signals=%s evaluations=%s trades=%s connectors=%s scopes=%s user=%s",
|
|
1276
1378
|
hours,
|
|
1277
1379
|
windowSignals.length,
|
|
1278
1380
|
windowEvaluationsCount,
|
|
1279
1381
|
windowClosedTrades.length,
|
|
1280
|
-
|
|
1382
|
+
connectorNames.join(",") || fallbackConnectorName,
|
|
1383
|
+
scopesCount,
|
|
1281
1384
|
flags.user
|
|
1282
1385
|
);
|
|
1283
1386
|
const debugAttachment = shouldAttachDebugReport(flags.debugAttachment) ? await buildRuntimeDebugReportAttachment({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradejs/cli",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.10",
|
|
4
4
|
"description": "Official CLI for the TradeJS TypeScript framework: infra setup, backtests, signals, bots, and ML workflows.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tradejs",
|
|
@@ -29,14 +29,14 @@
|
|
|
29
29
|
"tradejs": "dist/cli.js"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@tradejs/base": "^2.0.
|
|
33
|
-
"@tradejs/connectors": "^2.0.
|
|
34
|
-
"@tradejs/core": "^2.0.
|
|
35
|
-
"@tradejs/indicators": "^2.0.
|
|
36
|
-
"@tradejs/infra": "^2.0.
|
|
37
|
-
"@tradejs/node": "^2.0.
|
|
38
|
-
"@tradejs/strategies": "^2.0.
|
|
39
|
-
"@tradejs/types": "^2.0.
|
|
32
|
+
"@tradejs/base": "^2.0.10",
|
|
33
|
+
"@tradejs/connectors": "^2.0.10",
|
|
34
|
+
"@tradejs/core": "^2.0.10",
|
|
35
|
+
"@tradejs/indicators": "^2.0.10",
|
|
36
|
+
"@tradejs/infra": "^2.0.10",
|
|
37
|
+
"@tradejs/node": "^2.0.10",
|
|
38
|
+
"@tradejs/strategies": "^2.0.10",
|
|
39
|
+
"@tradejs/types": "^2.0.10",
|
|
40
40
|
"args": "^5.0.3",
|
|
41
41
|
"bcryptjs": "^2.4.3",
|
|
42
42
|
"chalk": "4.1.2",
|