@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 connectorName = await resolveSummaryConnectorName(flags27.connector);
34414
- const connectorFactory = await (0, import_connectors18.getConnectorCreatorByName)(
34415
- connectorName,
34416
- projectRoot13
34526
+ const fallbackConnectorName = await resolveSummaryConnectorName(
34527
+ flags27.connector
34417
34528
  );
34418
- if (!connectorFactory) {
34419
- throw new Error(`Connector "${connectorName}" is not registered`);
34420
- }
34421
- const connector = await connectorFactory({
34422
- userName: flags27.user
34423
- });
34424
- const [configuredStrategyNames, signals2, evaluationStatsBuckets, trades] = await Promise.all([
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 syncedTrades = await syncRuntimeTrades({
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
- openPositionCallbacks: {
34437
- onError: (error) => {
34438
- import_logger12.logger.warn(
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 connector=%s user=%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
- connectorName,
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(
@@ -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 connectorName = await resolveSummaryConnectorName(flags.connector);
1196
- const connectorFactory = await (0, import_connectors.getConnectorCreatorByName)(
1197
- connectorName,
1198
- projectRoot
1308
+ const fallbackConnectorName = await resolveSummaryConnectorName(
1309
+ flags.connector
1199
1310
  );
1200
- if (!connectorFactory) {
1201
- throw new Error(`Connector "${connectorName}" is not registered`);
1202
- }
1203
- const connector = await connectorFactory({
1204
- userName: flags.user
1205
- });
1206
- const [configuredStrategyNames, signals, evaluationStatsBuckets, trades] = await Promise.all([
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 syncedTrades = await syncRuntimeTrades({
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
- openPositionCallbacks: {
1219
- onError: (error) => {
1220
- import_logger.logger.warn(
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 connector=%s user=%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
- connectorName,
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.9",
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.9",
33
- "@tradejs/connectors": "^2.0.9",
34
- "@tradejs/core": "^2.0.9",
35
- "@tradejs/indicators": "^2.0.9",
36
- "@tradejs/infra": "^2.0.9",
37
- "@tradejs/node": "^2.0.9",
38
- "@tradejs/strategies": "^2.0.9",
39
- "@tradejs/types": "^2.0.9",
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",