backtest-kit 1.5.15 → 1.5.16

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/build/index.cjs CHANGED
@@ -6487,7 +6487,7 @@ const columns$3 = [
6487
6487
  },
6488
6488
  ];
6489
6489
  /** Maximum number of events to store in live trading reports */
6490
- const MAX_EVENTS$3 = 250;
6490
+ const MAX_EVENTS$4 = 250;
6491
6491
  /**
6492
6492
  * Storage class for accumulating all tick events per strategy.
6493
6493
  * Maintains a chronological list of all events (idle, opened, active, closed).
@@ -6520,7 +6520,7 @@ let ReportStorage$3 = class ReportStorage {
6520
6520
  }
6521
6521
  {
6522
6522
  this._eventList.push(newEvent);
6523
- if (this._eventList.length > MAX_EVENTS$3) {
6523
+ if (this._eventList.length > MAX_EVENTS$4) {
6524
6524
  this._eventList.shift();
6525
6525
  }
6526
6526
  }
@@ -6544,7 +6544,7 @@ let ReportStorage$3 = class ReportStorage {
6544
6544
  stopLoss: data.signal.priceStopLoss,
6545
6545
  });
6546
6546
  // Trim queue if exceeded MAX_EVENTS
6547
- if (this._eventList.length > MAX_EVENTS$3) {
6547
+ if (this._eventList.length > MAX_EVENTS$4) {
6548
6548
  this._eventList.shift();
6549
6549
  }
6550
6550
  }
@@ -6570,7 +6570,7 @@ let ReportStorage$3 = class ReportStorage {
6570
6570
  };
6571
6571
  this._eventList.push(newEvent);
6572
6572
  // Trim queue if exceeded MAX_EVENTS
6573
- if (this._eventList.length > MAX_EVENTS$3) {
6573
+ if (this._eventList.length > MAX_EVENTS$4) {
6574
6574
  this._eventList.shift();
6575
6575
  }
6576
6576
  }
@@ -6599,7 +6599,7 @@ let ReportStorage$3 = class ReportStorage {
6599
6599
  };
6600
6600
  this._eventList.push(newEvent);
6601
6601
  // Trim queue if exceeded MAX_EVENTS
6602
- if (this._eventList.length > MAX_EVENTS$3) {
6602
+ if (this._eventList.length > MAX_EVENTS$4) {
6603
6603
  this._eventList.shift();
6604
6604
  }
6605
6605
  }
@@ -7001,7 +7001,7 @@ const columns$2 = [
7001
7001
  },
7002
7002
  ];
7003
7003
  /** Maximum number of events to store in schedule reports */
7004
- const MAX_EVENTS$2 = 250;
7004
+ const MAX_EVENTS$3 = 250;
7005
7005
  /**
7006
7006
  * Storage class for accumulating scheduled signal events per strategy.
7007
7007
  * Maintains a chronological list of scheduled and cancelled events.
@@ -7030,7 +7030,34 @@ let ReportStorage$2 = class ReportStorage {
7030
7030
  stopLoss: data.signal.priceStopLoss,
7031
7031
  });
7032
7032
  // Trim queue if exceeded MAX_EVENTS
7033
- if (this._eventList.length > MAX_EVENTS$2) {
7033
+ if (this._eventList.length > MAX_EVENTS$3) {
7034
+ this._eventList.shift();
7035
+ }
7036
+ }
7037
+ /**
7038
+ * Adds an opened event to the storage.
7039
+ *
7040
+ * @param data - Opened tick result
7041
+ */
7042
+ addOpenedEvent(data) {
7043
+ const durationMs = data.signal.pendingAt - data.signal.scheduledAt;
7044
+ const durationMin = Math.round(durationMs / 60000);
7045
+ const newEvent = {
7046
+ timestamp: data.signal.pendingAt,
7047
+ action: "opened",
7048
+ symbol: data.signal.symbol,
7049
+ signalId: data.signal.id,
7050
+ position: data.signal.position,
7051
+ note: data.signal.note,
7052
+ currentPrice: data.currentPrice,
7053
+ priceOpen: data.signal.priceOpen,
7054
+ takeProfit: data.signal.priceTakeProfit,
7055
+ stopLoss: data.signal.priceStopLoss,
7056
+ duration: durationMin,
7057
+ };
7058
+ this._eventList.push(newEvent);
7059
+ // Trim queue if exceeded MAX_EVENTS
7060
+ if (this._eventList.length > MAX_EVENTS$3) {
7034
7061
  this._eventList.shift();
7035
7062
  }
7036
7063
  }
@@ -7058,7 +7085,7 @@ let ReportStorage$2 = class ReportStorage {
7058
7085
  };
7059
7086
  this._eventList.push(newEvent);
7060
7087
  // Trim queue if exceeded MAX_EVENTS
7061
- if (this._eventList.length > MAX_EVENTS$2) {
7088
+ if (this._eventList.length > MAX_EVENTS$3) {
7062
7089
  this._eventList.shift();
7063
7090
  }
7064
7091
  }
@@ -7073,29 +7100,44 @@ let ReportStorage$2 = class ReportStorage {
7073
7100
  eventList: [],
7074
7101
  totalEvents: 0,
7075
7102
  totalScheduled: 0,
7103
+ totalOpened: 0,
7076
7104
  totalCancelled: 0,
7077
7105
  cancellationRate: null,
7106
+ activationRate: null,
7078
7107
  avgWaitTime: null,
7108
+ avgActivationTime: null,
7079
7109
  };
7080
7110
  }
7081
7111
  const scheduledEvents = this._eventList.filter((e) => e.action === "scheduled");
7112
+ const openedEvents = this._eventList.filter((e) => e.action === "opened");
7082
7113
  const cancelledEvents = this._eventList.filter((e) => e.action === "cancelled");
7083
7114
  const totalScheduled = scheduledEvents.length;
7115
+ const totalOpened = openedEvents.length;
7084
7116
  const totalCancelled = cancelledEvents.length;
7085
7117
  // Calculate cancellation rate
7086
7118
  const cancellationRate = totalScheduled > 0 ? (totalCancelled / totalScheduled) * 100 : null;
7119
+ // Calculate activation rate
7120
+ const activationRate = totalScheduled > 0 ? (totalOpened / totalScheduled) * 100 : null;
7087
7121
  // Calculate average wait time for cancelled signals
7088
7122
  const avgWaitTime = totalCancelled > 0
7089
7123
  ? cancelledEvents.reduce((sum, e) => sum + (e.duration || 0), 0) /
7090
7124
  totalCancelled
7091
7125
  : null;
7126
+ // Calculate average activation time for opened signals
7127
+ const avgActivationTime = totalOpened > 0
7128
+ ? openedEvents.reduce((sum, e) => sum + (e.duration || 0), 0) /
7129
+ totalOpened
7130
+ : null;
7092
7131
  return {
7093
7132
  eventList: this._eventList,
7094
7133
  totalEvents: this._eventList.length,
7095
7134
  totalScheduled,
7135
+ totalOpened,
7096
7136
  totalCancelled,
7097
7137
  cancellationRate,
7138
+ activationRate,
7098
7139
  avgWaitTime,
7140
+ avgActivationTime,
7099
7141
  };
7100
7142
  }
7101
7143
  /**
@@ -7125,8 +7167,11 @@ let ReportStorage$2 = class ReportStorage {
7125
7167
  "",
7126
7168
  `**Total events:** ${stats.totalEvents}`,
7127
7169
  `**Scheduled signals:** ${stats.totalScheduled}`,
7170
+ `**Opened signals:** ${stats.totalOpened}`,
7128
7171
  `**Cancelled signals:** ${stats.totalCancelled}`,
7172
+ `**Activation rate:** ${stats.activationRate === null ? "N/A" : `${stats.activationRate.toFixed(2)}% (higher is better)`}`,
7129
7173
  `**Cancellation rate:** ${stats.cancellationRate === null ? "N/A" : `${stats.cancellationRate.toFixed(2)}% (lower is better)`}`,
7174
+ `**Average activation time:** ${stats.avgActivationTime === null ? "N/A" : `${stats.avgActivationTime.toFixed(2)} minutes`}`,
7130
7175
  `**Average wait time (cancelled):** ${stats.avgWaitTime === null ? "N/A" : `${stats.avgWaitTime.toFixed(2)} minutes`}`
7131
7176
  ].join("\n");
7132
7177
  }
@@ -7182,10 +7227,10 @@ class ScheduleMarkdownService {
7182
7227
  */
7183
7228
  this.getStorage = functoolsKit.memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, () => new ReportStorage$2());
7184
7229
  /**
7185
- * Processes tick events and accumulates scheduled/cancelled events.
7186
- * Should be called from signalLiveEmitter subscription.
7230
+ * Processes tick events and accumulates scheduled/opened/cancelled events.
7231
+ * Should be called from signalEmitter subscription.
7187
7232
  *
7188
- * Processes only scheduled and cancelled event types.
7233
+ * Processes only scheduled, opened and cancelled event types.
7189
7234
  *
7190
7235
  * @param data - Tick result from strategy execution
7191
7236
  *
@@ -7203,6 +7248,13 @@ class ScheduleMarkdownService {
7203
7248
  if (data.action === "scheduled") {
7204
7249
  storage.addScheduledEvent(data);
7205
7250
  }
7251
+ else if (data.action === "opened") {
7252
+ // Check if this opened signal was previously scheduled
7253
+ // by checking if signal has scheduledAt != pendingAt
7254
+ if (data.signal.scheduledAt !== data.signal.pendingAt) {
7255
+ storage.addOpenedEvent(data);
7256
+ }
7257
+ }
7206
7258
  else if (data.action === "cancelled") {
7207
7259
  storage.addCancelledEvent(data);
7208
7260
  }
@@ -7340,7 +7392,7 @@ function percentile(sortedArray, p) {
7340
7392
  return sortedArray[Math.max(0, index)];
7341
7393
  }
7342
7394
  /** Maximum number of performance events to store per strategy */
7343
- const MAX_EVENTS$1 = 10000;
7395
+ const MAX_EVENTS$2 = 10000;
7344
7396
  /**
7345
7397
  * Storage class for accumulating performance metrics per strategy.
7346
7398
  * Maintains a list of all performance events and provides aggregated statistics.
@@ -7358,7 +7410,7 @@ class PerformanceStorage {
7358
7410
  addEvent(event) {
7359
7411
  this._events.push(event);
7360
7412
  // Trim queue if exceeded MAX_EVENTS (keep most recent)
7361
- if (this._events.length > MAX_EVENTS$1) {
7413
+ if (this._events.length > MAX_EVENTS$2) {
7362
7414
  this._events.shift();
7363
7415
  }
7364
7416
  }
@@ -8270,6 +8322,8 @@ const columns$1 = [
8270
8322
  format: (data) => data.totalTrades.toString(),
8271
8323
  },
8272
8324
  ];
8325
+ /** Maximum number of signals to store per symbol in heatmap reports */
8326
+ const MAX_EVENTS$1 = 250;
8273
8327
  /**
8274
8328
  * Storage class for accumulating closed signals per strategy and generating heatmap.
8275
8329
  * Maintains symbol-level statistics and provides portfolio-wide metrics.
@@ -8289,7 +8343,12 @@ class HeatmapStorage {
8289
8343
  if (!this.symbolData.has(symbol)) {
8290
8344
  this.symbolData.set(symbol, []);
8291
8345
  }
8292
- this.symbolData.get(symbol).push(data);
8346
+ const signals = this.symbolData.get(symbol);
8347
+ signals.push(data);
8348
+ // Trim queue if exceeded MAX_EVENTS per symbol
8349
+ if (signals.length > MAX_EVENTS$1) {
8350
+ signals.shift();
8351
+ }
8293
8352
  }
8294
8353
  /**
8295
8354
  * Calculates statistics for a single symbol.
package/build/index.mjs CHANGED
@@ -6485,7 +6485,7 @@ const columns$3 = [
6485
6485
  },
6486
6486
  ];
6487
6487
  /** Maximum number of events to store in live trading reports */
6488
- const MAX_EVENTS$3 = 250;
6488
+ const MAX_EVENTS$4 = 250;
6489
6489
  /**
6490
6490
  * Storage class for accumulating all tick events per strategy.
6491
6491
  * Maintains a chronological list of all events (idle, opened, active, closed).
@@ -6518,7 +6518,7 @@ let ReportStorage$3 = class ReportStorage {
6518
6518
  }
6519
6519
  {
6520
6520
  this._eventList.push(newEvent);
6521
- if (this._eventList.length > MAX_EVENTS$3) {
6521
+ if (this._eventList.length > MAX_EVENTS$4) {
6522
6522
  this._eventList.shift();
6523
6523
  }
6524
6524
  }
@@ -6542,7 +6542,7 @@ let ReportStorage$3 = class ReportStorage {
6542
6542
  stopLoss: data.signal.priceStopLoss,
6543
6543
  });
6544
6544
  // Trim queue if exceeded MAX_EVENTS
6545
- if (this._eventList.length > MAX_EVENTS$3) {
6545
+ if (this._eventList.length > MAX_EVENTS$4) {
6546
6546
  this._eventList.shift();
6547
6547
  }
6548
6548
  }
@@ -6568,7 +6568,7 @@ let ReportStorage$3 = class ReportStorage {
6568
6568
  };
6569
6569
  this._eventList.push(newEvent);
6570
6570
  // Trim queue if exceeded MAX_EVENTS
6571
- if (this._eventList.length > MAX_EVENTS$3) {
6571
+ if (this._eventList.length > MAX_EVENTS$4) {
6572
6572
  this._eventList.shift();
6573
6573
  }
6574
6574
  }
@@ -6597,7 +6597,7 @@ let ReportStorage$3 = class ReportStorage {
6597
6597
  };
6598
6598
  this._eventList.push(newEvent);
6599
6599
  // Trim queue if exceeded MAX_EVENTS
6600
- if (this._eventList.length > MAX_EVENTS$3) {
6600
+ if (this._eventList.length > MAX_EVENTS$4) {
6601
6601
  this._eventList.shift();
6602
6602
  }
6603
6603
  }
@@ -6999,7 +6999,7 @@ const columns$2 = [
6999
6999
  },
7000
7000
  ];
7001
7001
  /** Maximum number of events to store in schedule reports */
7002
- const MAX_EVENTS$2 = 250;
7002
+ const MAX_EVENTS$3 = 250;
7003
7003
  /**
7004
7004
  * Storage class for accumulating scheduled signal events per strategy.
7005
7005
  * Maintains a chronological list of scheduled and cancelled events.
@@ -7028,7 +7028,34 @@ let ReportStorage$2 = class ReportStorage {
7028
7028
  stopLoss: data.signal.priceStopLoss,
7029
7029
  });
7030
7030
  // Trim queue if exceeded MAX_EVENTS
7031
- if (this._eventList.length > MAX_EVENTS$2) {
7031
+ if (this._eventList.length > MAX_EVENTS$3) {
7032
+ this._eventList.shift();
7033
+ }
7034
+ }
7035
+ /**
7036
+ * Adds an opened event to the storage.
7037
+ *
7038
+ * @param data - Opened tick result
7039
+ */
7040
+ addOpenedEvent(data) {
7041
+ const durationMs = data.signal.pendingAt - data.signal.scheduledAt;
7042
+ const durationMin = Math.round(durationMs / 60000);
7043
+ const newEvent = {
7044
+ timestamp: data.signal.pendingAt,
7045
+ action: "opened",
7046
+ symbol: data.signal.symbol,
7047
+ signalId: data.signal.id,
7048
+ position: data.signal.position,
7049
+ note: data.signal.note,
7050
+ currentPrice: data.currentPrice,
7051
+ priceOpen: data.signal.priceOpen,
7052
+ takeProfit: data.signal.priceTakeProfit,
7053
+ stopLoss: data.signal.priceStopLoss,
7054
+ duration: durationMin,
7055
+ };
7056
+ this._eventList.push(newEvent);
7057
+ // Trim queue if exceeded MAX_EVENTS
7058
+ if (this._eventList.length > MAX_EVENTS$3) {
7032
7059
  this._eventList.shift();
7033
7060
  }
7034
7061
  }
@@ -7056,7 +7083,7 @@ let ReportStorage$2 = class ReportStorage {
7056
7083
  };
7057
7084
  this._eventList.push(newEvent);
7058
7085
  // Trim queue if exceeded MAX_EVENTS
7059
- if (this._eventList.length > MAX_EVENTS$2) {
7086
+ if (this._eventList.length > MAX_EVENTS$3) {
7060
7087
  this._eventList.shift();
7061
7088
  }
7062
7089
  }
@@ -7071,29 +7098,44 @@ let ReportStorage$2 = class ReportStorage {
7071
7098
  eventList: [],
7072
7099
  totalEvents: 0,
7073
7100
  totalScheduled: 0,
7101
+ totalOpened: 0,
7074
7102
  totalCancelled: 0,
7075
7103
  cancellationRate: null,
7104
+ activationRate: null,
7076
7105
  avgWaitTime: null,
7106
+ avgActivationTime: null,
7077
7107
  };
7078
7108
  }
7079
7109
  const scheduledEvents = this._eventList.filter((e) => e.action === "scheduled");
7110
+ const openedEvents = this._eventList.filter((e) => e.action === "opened");
7080
7111
  const cancelledEvents = this._eventList.filter((e) => e.action === "cancelled");
7081
7112
  const totalScheduled = scheduledEvents.length;
7113
+ const totalOpened = openedEvents.length;
7082
7114
  const totalCancelled = cancelledEvents.length;
7083
7115
  // Calculate cancellation rate
7084
7116
  const cancellationRate = totalScheduled > 0 ? (totalCancelled / totalScheduled) * 100 : null;
7117
+ // Calculate activation rate
7118
+ const activationRate = totalScheduled > 0 ? (totalOpened / totalScheduled) * 100 : null;
7085
7119
  // Calculate average wait time for cancelled signals
7086
7120
  const avgWaitTime = totalCancelled > 0
7087
7121
  ? cancelledEvents.reduce((sum, e) => sum + (e.duration || 0), 0) /
7088
7122
  totalCancelled
7089
7123
  : null;
7124
+ // Calculate average activation time for opened signals
7125
+ const avgActivationTime = totalOpened > 0
7126
+ ? openedEvents.reduce((sum, e) => sum + (e.duration || 0), 0) /
7127
+ totalOpened
7128
+ : null;
7090
7129
  return {
7091
7130
  eventList: this._eventList,
7092
7131
  totalEvents: this._eventList.length,
7093
7132
  totalScheduled,
7133
+ totalOpened,
7094
7134
  totalCancelled,
7095
7135
  cancellationRate,
7136
+ activationRate,
7096
7137
  avgWaitTime,
7138
+ avgActivationTime,
7097
7139
  };
7098
7140
  }
7099
7141
  /**
@@ -7123,8 +7165,11 @@ let ReportStorage$2 = class ReportStorage {
7123
7165
  "",
7124
7166
  `**Total events:** ${stats.totalEvents}`,
7125
7167
  `**Scheduled signals:** ${stats.totalScheduled}`,
7168
+ `**Opened signals:** ${stats.totalOpened}`,
7126
7169
  `**Cancelled signals:** ${stats.totalCancelled}`,
7170
+ `**Activation rate:** ${stats.activationRate === null ? "N/A" : `${stats.activationRate.toFixed(2)}% (higher is better)`}`,
7127
7171
  `**Cancellation rate:** ${stats.cancellationRate === null ? "N/A" : `${stats.cancellationRate.toFixed(2)}% (lower is better)`}`,
7172
+ `**Average activation time:** ${stats.avgActivationTime === null ? "N/A" : `${stats.avgActivationTime.toFixed(2)} minutes`}`,
7128
7173
  `**Average wait time (cancelled):** ${stats.avgWaitTime === null ? "N/A" : `${stats.avgWaitTime.toFixed(2)} minutes`}`
7129
7174
  ].join("\n");
7130
7175
  }
@@ -7180,10 +7225,10 @@ class ScheduleMarkdownService {
7180
7225
  */
7181
7226
  this.getStorage = memoize(([symbol, strategyName]) => `${symbol}:${strategyName}`, () => new ReportStorage$2());
7182
7227
  /**
7183
- * Processes tick events and accumulates scheduled/cancelled events.
7184
- * Should be called from signalLiveEmitter subscription.
7228
+ * Processes tick events and accumulates scheduled/opened/cancelled events.
7229
+ * Should be called from signalEmitter subscription.
7185
7230
  *
7186
- * Processes only scheduled and cancelled event types.
7231
+ * Processes only scheduled, opened and cancelled event types.
7187
7232
  *
7188
7233
  * @param data - Tick result from strategy execution
7189
7234
  *
@@ -7201,6 +7246,13 @@ class ScheduleMarkdownService {
7201
7246
  if (data.action === "scheduled") {
7202
7247
  storage.addScheduledEvent(data);
7203
7248
  }
7249
+ else if (data.action === "opened") {
7250
+ // Check if this opened signal was previously scheduled
7251
+ // by checking if signal has scheduledAt != pendingAt
7252
+ if (data.signal.scheduledAt !== data.signal.pendingAt) {
7253
+ storage.addOpenedEvent(data);
7254
+ }
7255
+ }
7204
7256
  else if (data.action === "cancelled") {
7205
7257
  storage.addCancelledEvent(data);
7206
7258
  }
@@ -7338,7 +7390,7 @@ function percentile(sortedArray, p) {
7338
7390
  return sortedArray[Math.max(0, index)];
7339
7391
  }
7340
7392
  /** Maximum number of performance events to store per strategy */
7341
- const MAX_EVENTS$1 = 10000;
7393
+ const MAX_EVENTS$2 = 10000;
7342
7394
  /**
7343
7395
  * Storage class for accumulating performance metrics per strategy.
7344
7396
  * Maintains a list of all performance events and provides aggregated statistics.
@@ -7356,7 +7408,7 @@ class PerformanceStorage {
7356
7408
  addEvent(event) {
7357
7409
  this._events.push(event);
7358
7410
  // Trim queue if exceeded MAX_EVENTS (keep most recent)
7359
- if (this._events.length > MAX_EVENTS$1) {
7411
+ if (this._events.length > MAX_EVENTS$2) {
7360
7412
  this._events.shift();
7361
7413
  }
7362
7414
  }
@@ -8268,6 +8320,8 @@ const columns$1 = [
8268
8320
  format: (data) => data.totalTrades.toString(),
8269
8321
  },
8270
8322
  ];
8323
+ /** Maximum number of signals to store per symbol in heatmap reports */
8324
+ const MAX_EVENTS$1 = 250;
8271
8325
  /**
8272
8326
  * Storage class for accumulating closed signals per strategy and generating heatmap.
8273
8327
  * Maintains symbol-level statistics and provides portfolio-wide metrics.
@@ -8287,7 +8341,12 @@ class HeatmapStorage {
8287
8341
  if (!this.symbolData.has(symbol)) {
8288
8342
  this.symbolData.set(symbol, []);
8289
8343
  }
8290
- this.symbolData.get(symbol).push(data);
8344
+ const signals = this.symbolData.get(symbol);
8345
+ signals.push(data);
8346
+ // Trim queue if exceeded MAX_EVENTS per symbol
8347
+ if (signals.length > MAX_EVENTS$1) {
8348
+ signals.shift();
8349
+ }
8291
8350
  }
8292
8351
  /**
8293
8352
  * Calculates statistics for a single symbol.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backtest-kit",
3
- "version": "1.5.15",
3
+ "version": "1.5.16",
4
4
  "description": "A TypeScript library for trading system backtest",
5
5
  "author": {
6
6
  "name": "Petr Tripolsky",
package/types.d.ts CHANGED
@@ -4079,13 +4079,13 @@ declare class LiveMarkdownService {
4079
4079
 
4080
4080
  /**
4081
4081
  * Unified scheduled signal event data for report generation.
4082
- * Contains all information about scheduled and cancelled events.
4082
+ * Contains all information about scheduled, opened and cancelled events.
4083
4083
  */
4084
4084
  interface ScheduledEvent {
4085
4085
  /** Event timestamp in milliseconds (scheduledAt for scheduled/cancelled events) */
4086
4086
  timestamp: number;
4087
4087
  /** Event action type */
4088
- action: "scheduled" | "cancelled";
4088
+ action: "scheduled" | "opened" | "cancelled";
4089
4089
  /** Trading pair symbol */
4090
4090
  symbol: string;
4091
4091
  /** Signal ID */
@@ -4104,13 +4104,13 @@ interface ScheduledEvent {
4104
4104
  stopLoss: number;
4105
4105
  /** Close timestamp (only for cancelled) */
4106
4106
  closeTimestamp?: number;
4107
- /** Duration in minutes (only for cancelled) */
4107
+ /** Duration in minutes (only for cancelled/opened) */
4108
4108
  duration?: number;
4109
4109
  }
4110
4110
  /**
4111
4111
  * Statistical data calculated from scheduled signals.
4112
4112
  *
4113
- * Provides metrics for scheduled signal tracking and cancellation analysis.
4113
+ * Provides metrics for scheduled signal tracking, activation and cancellation analysis.
4114
4114
  *
4115
4115
  * @example
4116
4116
  * ```typescript
@@ -4118,10 +4118,11 @@ interface ScheduledEvent {
4118
4118
  *
4119
4119
  * console.log(`Total events: ${stats.totalEvents}`);
4120
4120
  * console.log(`Scheduled signals: ${stats.totalScheduled}`);
4121
+ * console.log(`Opened signals: ${stats.totalOpened}`);
4121
4122
  * console.log(`Cancelled signals: ${stats.totalCancelled}`);
4122
4123
  * console.log(`Cancellation rate: ${stats.cancellationRate}%`);
4123
4124
  *
4124
- * // Access raw event data (includes scheduled, cancelled)
4125
+ * // Access raw event data (includes scheduled, opened, cancelled)
4125
4126
  * stats.eventList.forEach(event => {
4126
4127
  * if (event.action === "cancelled") {
4127
4128
  * console.log(`Cancelled signal: ${event.signalId}`);
@@ -4130,18 +4131,24 @@ interface ScheduledEvent {
4130
4131
  * ```
4131
4132
  */
4132
4133
  interface ScheduleStatistics {
4133
- /** Array of all scheduled/cancelled events with full details */
4134
+ /** Array of all scheduled/opened/cancelled events with full details */
4134
4135
  eventList: ScheduledEvent[];
4135
- /** Total number of all events (includes scheduled, cancelled) */
4136
+ /** Total number of all events (includes scheduled, opened, cancelled) */
4136
4137
  totalEvents: number;
4137
4138
  /** Total number of scheduled signals */
4138
4139
  totalScheduled: number;
4140
+ /** Total number of opened signals (activated from scheduled) */
4141
+ totalOpened: number;
4139
4142
  /** Total number of cancelled signals */
4140
4143
  totalCancelled: number;
4141
4144
  /** Cancellation rate as percentage (0-100), null if no scheduled signals. Lower is better. */
4142
4145
  cancellationRate: number | null;
4146
+ /** Activation rate as percentage (0-100), null if no scheduled signals. Higher is better. */
4147
+ activationRate: number | null;
4143
4148
  /** Average waiting time for cancelled signals in minutes, null if no cancelled signals */
4144
4149
  avgWaitTime: number | null;
4150
+ /** Average waiting time for opened signals in minutes, null if no opened signals */
4151
+ avgActivationTime: number | null;
4145
4152
  }
4146
4153
  /**
4147
4154
  * Service for generating and saving scheduled signals markdown reports.
@@ -4173,10 +4180,10 @@ declare class ScheduleMarkdownService {
4173
4180
  */
4174
4181
  private getStorage;
4175
4182
  /**
4176
- * Processes tick events and accumulates scheduled/cancelled events.
4177
- * Should be called from signalLiveEmitter subscription.
4183
+ * Processes tick events and accumulates scheduled/opened/cancelled events.
4184
+ * Should be called from signalEmitter subscription.
4178
4185
  *
4179
- * Processes only scheduled and cancelled event types.
4186
+ * Processes only scheduled, opened and cancelled event types.
4180
4187
  *
4181
4188
  * @param data - Tick result from strategy execution
4182
4189
  *