backtest-kit 7.1.0 → 7.3.0

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.mjs CHANGED
@@ -4750,8 +4750,7 @@ const TIMEOUT_SYMBOL = Symbol('timeout');
4750
4750
  * The framework will retry on the next tick.
4751
4751
  */
4752
4752
  const CALL_SIGNAL_SYNC_OPEN_FN = trycatch(async (timestamp, currentPrice, pendingSignal, self) => {
4753
- const publicSignal = TO_PUBLIC_SIGNAL(pendingSignal, currentPrice);
4754
- const pnl = toProfitLossDto(pendingSignal, currentPrice);
4753
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", pendingSignal, currentPrice);
4755
4754
  return await self.params.onSignalSync({
4756
4755
  action: "signal-open",
4757
4756
  symbol: self.params.execution.context.symbol,
@@ -4762,10 +4761,12 @@ const CALL_SIGNAL_SYNC_OPEN_FN = trycatch(async (timestamp, currentPrice, pendin
4762
4761
  signalId: pendingSignal.id,
4763
4762
  timestamp,
4764
4763
  signal: publicSignal,
4764
+ maxDrawdown: publicSignal.maxDrawdown,
4765
+ peakProfit: publicSignal.peakProfit,
4765
4766
  cost: pendingSignal.cost,
4766
4767
  currentPrice,
4767
4768
  position: publicSignal.position,
4768
- pnl,
4769
+ pnl: publicSignal.pnl,
4769
4770
  priceOpen: publicSignal.priceOpen,
4770
4771
  priceTakeProfit: publicSignal.priceTakeProfit,
4771
4772
  priceStopLoss: publicSignal.priceStopLoss,
@@ -4789,8 +4790,7 @@ const CALL_SIGNAL_SYNC_OPEN_FN = trycatch(async (timestamp, currentPrice, pendin
4789
4790
  * strategy state is NOT mutated. The framework will retry on the next tick.
4790
4791
  */
4791
4792
  const CALL_SIGNAL_SYNC_CLOSE_FN = trycatch(async (timestamp, currentPrice, closeReason, signal, self) => {
4792
- const publicSignal = TO_PUBLIC_SIGNAL(signal, currentPrice);
4793
- const pnl = toProfitLossDto(signal, currentPrice);
4793
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", signal, currentPrice);
4794
4794
  return await self.params.onSignalSync({
4795
4795
  action: "signal-close",
4796
4796
  symbol: self.params.execution.context.symbol,
@@ -4801,8 +4801,10 @@ const CALL_SIGNAL_SYNC_CLOSE_FN = trycatch(async (timestamp, currentPrice, close
4801
4801
  signalId: signal.id,
4802
4802
  timestamp,
4803
4803
  signal: publicSignal,
4804
+ maxDrawdown: publicSignal.maxDrawdown,
4805
+ peakProfit: publicSignal.peakProfit,
4804
4806
  currentPrice,
4805
- pnl,
4807
+ pnl: publicSignal.pnl,
4806
4808
  position: publicSignal.position,
4807
4809
  priceOpen: publicSignal.priceOpen,
4808
4810
  priceTakeProfit: publicSignal.priceTakeProfit,
@@ -4863,10 +4865,9 @@ const PROCESS_COMMIT_QUEUE_FN = async (self, currentPrice, timestamp) => {
4863
4865
  if (!self._pendingSignal) {
4864
4866
  return;
4865
4867
  }
4866
- // Get public signal data for commit events (contains effective and original SL/TP)
4867
- const publicSignal = TO_PUBLIC_SIGNAL(self._pendingSignal, currentPrice);
4868
4868
  for (const commit of queue) {
4869
4869
  if (commit.action === "partial-profit") {
4870
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", self._pendingSignal, commit.currentPrice);
4870
4871
  await CALL_COMMIT_FN(self, {
4871
4872
  action: "partial-profit",
4872
4873
  symbol: commit.symbol,
@@ -4876,7 +4877,10 @@ const PROCESS_COMMIT_QUEUE_FN = async (self, currentPrice, timestamp) => {
4876
4877
  backtest: commit.backtest,
4877
4878
  percentToClose: commit.percentToClose,
4878
4879
  currentPrice: commit.currentPrice,
4879
- pnl: toProfitLossDto(self._pendingSignal, commit.currentPrice),
4880
+ pnl: publicSignal.pnl,
4881
+ maxDrawdown: publicSignal.maxDrawdown,
4882
+ peakProfit: publicSignal.peakProfit,
4883
+ signal: publicSignal,
4880
4884
  timestamp,
4881
4885
  totalEntries: publicSignal.totalEntries,
4882
4886
  totalPartials: publicSignal.totalPartials,
@@ -4895,6 +4899,7 @@ const PROCESS_COMMIT_QUEUE_FN = async (self, currentPrice, timestamp) => {
4895
4899
  continue;
4896
4900
  }
4897
4901
  if (commit.action === "partial-loss") {
4902
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", self._pendingSignal, commit.currentPrice);
4898
4903
  await CALL_COMMIT_FN(self, {
4899
4904
  action: "partial-loss",
4900
4905
  symbol: commit.symbol,
@@ -4904,7 +4909,10 @@ const PROCESS_COMMIT_QUEUE_FN = async (self, currentPrice, timestamp) => {
4904
4909
  backtest: commit.backtest,
4905
4910
  percentToClose: commit.percentToClose,
4906
4911
  currentPrice: commit.currentPrice,
4907
- pnl: toProfitLossDto(self._pendingSignal, commit.currentPrice),
4912
+ pnl: publicSignal.pnl,
4913
+ maxDrawdown: publicSignal.maxDrawdown,
4914
+ peakProfit: publicSignal.peakProfit,
4915
+ signal: publicSignal,
4908
4916
  timestamp,
4909
4917
  totalEntries: publicSignal.totalEntries,
4910
4918
  totalPartials: publicSignal.totalPartials,
@@ -4923,6 +4931,7 @@ const PROCESS_COMMIT_QUEUE_FN = async (self, currentPrice, timestamp) => {
4923
4931
  continue;
4924
4932
  }
4925
4933
  if (commit.action === "breakeven") {
4934
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", self._pendingSignal, commit.currentPrice);
4926
4935
  await CALL_COMMIT_FN(self, {
4927
4936
  action: "breakeven",
4928
4937
  symbol: commit.symbol,
@@ -4931,7 +4940,10 @@ const PROCESS_COMMIT_QUEUE_FN = async (self, currentPrice, timestamp) => {
4931
4940
  frameName: self.params.frameName,
4932
4941
  backtest: commit.backtest,
4933
4942
  currentPrice: commit.currentPrice,
4934
- pnl: toProfitLossDto(self._pendingSignal, commit.currentPrice),
4943
+ pnl: publicSignal.pnl,
4944
+ maxDrawdown: publicSignal.maxDrawdown,
4945
+ peakProfit: publicSignal.peakProfit,
4946
+ signal: publicSignal,
4935
4947
  timestamp,
4936
4948
  totalEntries: publicSignal.totalEntries,
4937
4949
  totalPartials: publicSignal.totalPartials,
@@ -4950,6 +4962,7 @@ const PROCESS_COMMIT_QUEUE_FN = async (self, currentPrice, timestamp) => {
4950
4962
  continue;
4951
4963
  }
4952
4964
  if (commit.action === "trailing-stop") {
4965
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", self._pendingSignal, commit.currentPrice);
4953
4966
  await CALL_COMMIT_FN(self, {
4954
4967
  action: "trailing-stop",
4955
4968
  symbol: commit.symbol,
@@ -4959,7 +4972,10 @@ const PROCESS_COMMIT_QUEUE_FN = async (self, currentPrice, timestamp) => {
4959
4972
  backtest: commit.backtest,
4960
4973
  percentShift: commit.percentShift,
4961
4974
  currentPrice: commit.currentPrice,
4962
- pnl: toProfitLossDto(self._pendingSignal, commit.currentPrice),
4975
+ pnl: publicSignal.pnl,
4976
+ maxDrawdown: publicSignal.maxDrawdown,
4977
+ peakProfit: publicSignal.peakProfit,
4978
+ signal: publicSignal,
4963
4979
  timestamp,
4964
4980
  totalEntries: publicSignal.totalEntries,
4965
4981
  totalPartials: publicSignal.totalPartials,
@@ -4978,6 +4994,7 @@ const PROCESS_COMMIT_QUEUE_FN = async (self, currentPrice, timestamp) => {
4978
4994
  continue;
4979
4995
  }
4980
4996
  if (commit.action === "trailing-take") {
4997
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", self._pendingSignal, commit.currentPrice);
4981
4998
  await CALL_COMMIT_FN(self, {
4982
4999
  action: "trailing-take",
4983
5000
  symbol: commit.symbol,
@@ -4987,7 +5004,10 @@ const PROCESS_COMMIT_QUEUE_FN = async (self, currentPrice, timestamp) => {
4987
5004
  backtest: commit.backtest,
4988
5005
  percentShift: commit.percentShift,
4989
5006
  currentPrice: commit.currentPrice,
4990
- pnl: toProfitLossDto(self._pendingSignal, commit.currentPrice),
5007
+ pnl: publicSignal.pnl,
5008
+ maxDrawdown: publicSignal.maxDrawdown,
5009
+ peakProfit: publicSignal.peakProfit,
5010
+ signal: publicSignal,
4991
5011
  timestamp,
4992
5012
  totalEntries: publicSignal.totalEntries,
4993
5013
  totalPartials: publicSignal.totalPartials,
@@ -5006,6 +5026,7 @@ const PROCESS_COMMIT_QUEUE_FN = async (self, currentPrice, timestamp) => {
5006
5026
  continue;
5007
5027
  }
5008
5028
  if (commit.action === "average-buy") {
5029
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", self._pendingSignal, commit.currentPrice);
5009
5030
  const effectivePriceOpen = getEffectivePriceOpen(self._pendingSignal);
5010
5031
  await CALL_COMMIT_FN(self, {
5011
5032
  action: "average-buy",
@@ -5017,7 +5038,10 @@ const PROCESS_COMMIT_QUEUE_FN = async (self, currentPrice, timestamp) => {
5017
5038
  currentPrice: commit.currentPrice,
5018
5039
  cost: commit.cost,
5019
5040
  effectivePriceOpen,
5020
- pnl: toProfitLossDto(self._pendingSignal, commit.currentPrice),
5041
+ pnl: publicSignal.pnl,
5042
+ maxDrawdown: publicSignal.maxDrawdown,
5043
+ peakProfit: publicSignal.peakProfit,
5044
+ signal: publicSignal,
5021
5045
  timestamp,
5022
5046
  totalEntries: publicSignal.totalEntries,
5023
5047
  totalPartials: publicSignal.totalPartials,
@@ -5037,6 +5061,8 @@ const PROCESS_COMMIT_QUEUE_FN = async (self, currentPrice, timestamp) => {
5037
5061
  }
5038
5062
  }
5039
5063
  };
5064
+ /** Zero PNL constant for scheduled signals (which don't have priceOpen or PNL yet) */
5065
+ const ZERO_PNL$1 = { pnlPercentage: 0, priceOpen: 0, priceClose: 0, pnlCost: 0, pnlEntries: 0 };
5040
5066
  /**
5041
5067
  * Converts internal signal to public API format.
5042
5068
  *
@@ -5084,7 +5110,7 @@ const PROCESS_COMMIT_QUEUE_FN = async (self, currentPrice, timestamp) => {
5084
5110
  * // publicSignal._trailingPriceTakeProfit = undefined (hidden from external API)
5085
5111
  * ```
5086
5112
  */
5087
- const TO_PUBLIC_SIGNAL = (signal, currentPrice) => {
5113
+ const TO_PUBLIC_SIGNAL = (type, signal, currentPrice) => {
5088
5114
  const hasTrailingSL = "_trailingPriceStopLoss" in signal && signal._trailingPriceStopLoss !== undefined;
5089
5115
  const hasTrailingTP = "_trailingPriceTakeProfit" in signal && signal._trailingPriceTakeProfit !== undefined;
5090
5116
  const partialExecuted = "_partial" in signal
@@ -5092,11 +5118,14 @@ const TO_PUBLIC_SIGNAL = (signal, currentPrice) => {
5092
5118
  : 0;
5093
5119
  const totalEntries = ("_entry" in signal && Array.isArray(signal._entry))
5094
5120
  ? signal._entry.length
5095
- : 1;
5121
+ : type === "scheduled" ? 0 : 1;
5096
5122
  const totalPartials = ("_partial" in signal && Array.isArray(signal._partial))
5097
5123
  ? signal._partial.length
5098
5124
  : 0;
5099
- const effectivePriceOpen = "_entry" in signal ? getEffectivePriceOpen(signal) : signal.priceOpen;
5125
+ const pnl = type === "scheduled" ? ZERO_PNL$1 : toProfitLossDto(signal, currentPrice);
5126
+ const maxDrawdown = type === "scheduled" ? ZERO_PNL$1 : ("_fall" in signal ? !!signal["_fall"] ? ({ ...signal._fall }) : ZERO_PNL$1 : ZERO_PNL$1);
5127
+ const peakProfit = type === "scheduled" ? ZERO_PNL$1 : ("_peak" in signal ? signal["_peak"] ? ({ ...signal._peak }) : ZERO_PNL$1 : ZERO_PNL$1);
5128
+ const effectivePriceOpen = type === "scheduled" ? signal.priceOpen : "_entry" in signal ? signal["_entry"] ? getEffectivePriceOpen(signal) : signal.priceOpen : signal.priceOpen;
5100
5129
  return {
5101
5130
  ...structuredClone(signal),
5102
5131
  priceOpen: effectivePriceOpen,
@@ -5105,10 +5134,12 @@ const TO_PUBLIC_SIGNAL = (signal, currentPrice) => {
5105
5134
  originalPriceOpen: signal.priceOpen,
5106
5135
  originalPriceStopLoss: signal.priceStopLoss,
5107
5136
  originalPriceTakeProfit: signal.priceTakeProfit,
5137
+ maxDrawdown,
5138
+ peakProfit,
5108
5139
  partialExecuted,
5109
5140
  totalEntries,
5110
5141
  totalPartials,
5111
- pnl: toProfitLossDto(signal, currentPrice),
5142
+ pnl,
5112
5143
  };
5113
5144
  };
5114
5145
  const GET_SIGNAL_FN = trycatch(async (self) => {
@@ -5173,8 +5204,8 @@ const GET_SIGNAL_FN = trycatch(async (self) => {
5173
5204
  timestamp: currentTime,
5174
5205
  _isScheduled: false,
5175
5206
  _entry: [{ price: signal.priceOpen, cost: signal.cost ?? GLOBAL_CONFIG.CC_POSITION_ENTRY_COST, timestamp: currentTime }],
5176
- _peak: { price: signal.priceOpen, timestamp: currentTime, pnlPercentage: 0, pnlCost: 0 },
5177
- _fall: { price: signal.priceOpen, timestamp: currentTime, pnlPercentage: 0, pnlCost: 0 },
5207
+ _peak: { price: signal.priceOpen, timestamp: currentTime, pnlPercentage: 0, pnlCost: 0, priceClose: 0, priceOpen: 0, pnlEntries: 0 },
5208
+ _fall: { price: signal.priceOpen, timestamp: currentTime, pnlPercentage: 0, pnlCost: 0, priceClose: 0, priceOpen: 0, pnlEntries: 0 },
5178
5209
  };
5179
5210
  // Валидируем сигнал перед возвратом
5180
5211
  validatePendingSignal(signalRow, currentPrice);
@@ -5199,8 +5230,8 @@ const GET_SIGNAL_FN = trycatch(async (self) => {
5199
5230
  timestamp: currentTime,
5200
5231
  _isScheduled: true,
5201
5232
  _entry: [{ price: signal.priceOpen, cost: signal.cost ?? GLOBAL_CONFIG.CC_POSITION_ENTRY_COST, timestamp: currentTime }],
5202
- _peak: { price: signal.priceOpen, timestamp: currentTime, pnlPercentage: 0, pnlCost: 0 },
5203
- _fall: { price: signal.priceOpen, timestamp: currentTime, pnlPercentage: 0, pnlCost: 0 },
5233
+ _peak: { price: signal.priceOpen, timestamp: currentTime, pnlPercentage: 0, pnlCost: 0, priceClose: 0, priceOpen: 0, pnlEntries: 0 },
5234
+ _fall: { price: signal.priceOpen, timestamp: currentTime, pnlPercentage: 0, pnlCost: 0, priceClose: 0, priceOpen: 0, pnlEntries: 0 },
5204
5235
  };
5205
5236
  // Валидируем сигнал перед возвратом
5206
5237
  validateScheduledSignal(scheduledSignalRow, currentPrice);
@@ -5222,8 +5253,8 @@ const GET_SIGNAL_FN = trycatch(async (self) => {
5222
5253
  timestamp: currentTime,
5223
5254
  _isScheduled: false,
5224
5255
  _entry: [{ price: currentPrice, cost: signal.cost ?? GLOBAL_CONFIG.CC_POSITION_ENTRY_COST, timestamp: currentTime }],
5225
- _peak: { price: currentPrice, timestamp: currentTime, pnlPercentage: 0, pnlCost: 0 },
5226
- _fall: { price: currentPrice, timestamp: currentTime, pnlPercentage: 0, pnlCost: 0 },
5256
+ _peak: { price: currentPrice, timestamp: currentTime, pnlPercentage: 0, pnlCost: 0, priceClose: 0, priceOpen: 0, pnlEntries: 0 },
5257
+ _fall: { price: currentPrice, timestamp: currentTime, pnlPercentage: 0, pnlCost: 0, priceClose: 0, priceOpen: 0, pnlEntries: 0 },
5227
5258
  };
5228
5259
  // Валидируем сигнал перед возвратом
5229
5260
  validatePendingSignal(signalRow, currentPrice);
@@ -5827,7 +5858,7 @@ const CHECK_SCHEDULED_SIGNAL_TIMEOUT_FN = async (self, scheduled, currentPrice)
5827
5858
  await CALL_CANCEL_CALLBACKS_FN(self, self.params.execution.context.symbol, scheduled, currentPrice, currentTime, self.params.execution.context.backtest);
5828
5859
  const result = {
5829
5860
  action: "cancelled",
5830
- signal: TO_PUBLIC_SIGNAL(scheduled, currentPrice),
5861
+ signal: TO_PUBLIC_SIGNAL("scheduled", scheduled, currentPrice),
5831
5862
  currentPrice: currentPrice,
5832
5863
  closeTimestamp: currentTime,
5833
5864
  strategyName: self.params.method.context.strategyName,
@@ -5883,7 +5914,7 @@ const CANCEL_SCHEDULED_SIGNAL_BY_STOPLOSS_FN = async (self, scheduled, currentPr
5883
5914
  await CALL_CANCEL_CALLBACKS_FN(self, self.params.execution.context.symbol, scheduled, currentPrice, currentTime, self.params.execution.context.backtest);
5884
5915
  const result = {
5885
5916
  action: "cancelled",
5886
- signal: TO_PUBLIC_SIGNAL(scheduled, currentPrice),
5917
+ signal: TO_PUBLIC_SIGNAL("scheduled", scheduled, currentPrice),
5887
5918
  currentPrice: currentPrice,
5888
5919
  closeTimestamp: currentTime,
5889
5920
  strategyName: self.params.method.context.strategyName,
@@ -5934,8 +5965,8 @@ const ACTIVATE_SCHEDULED_SIGNAL_FN = async (self, scheduled, activationTimestamp
5934
5965
  ...scheduled,
5935
5966
  pendingAt: activationTime,
5936
5967
  _isScheduled: false,
5937
- _peak: { price: scheduled.priceOpen, timestamp: activationTime, pnlPercentage: 0, pnlCost: 0 },
5938
- _fall: { price: scheduled.priceOpen, timestamp: activationTime, pnlPercentage: 0, pnlCost: 0 },
5968
+ _peak: { price: scheduled.priceOpen, timestamp: activationTime, pnlPercentage: 0, pnlCost: 0, pnlEntries: 0, priceClose: 0, priceOpen: 0 },
5969
+ _fall: { price: scheduled.priceOpen, timestamp: activationTime, pnlPercentage: 0, pnlCost: 0, pnlEntries: 0, priceClose: 0, priceOpen: 0 },
5939
5970
  };
5940
5971
  // Sync open: if external system rejects — cancel scheduled signal instead of opening
5941
5972
  const syncOpenAllowed = await CALL_SIGNAL_SYNC_OPEN_FN(activationTime, activatedSignal.priceOpen, activatedSignal, self);
@@ -5945,6 +5976,7 @@ const ACTIVATE_SCHEDULED_SIGNAL_FN = async (self, scheduled, activationTimestamp
5945
5976
  signalId: scheduled.id,
5946
5977
  });
5947
5978
  await self.setScheduledSignal(null);
5979
+ const publicSignal = TO_PUBLIC_SIGNAL("scheduled", scheduled, scheduled.priceOpen);
5948
5980
  await CALL_COMMIT_FN(self, {
5949
5981
  action: "cancel-scheduled",
5950
5982
  symbol: self.params.execution.context.symbol,
@@ -5957,7 +5989,10 @@ const ACTIVATE_SCHEDULED_SIGNAL_FN = async (self, scheduled, activationTimestamp
5957
5989
  totalEntries: scheduled._entry?.length ?? 1,
5958
5990
  totalPartials: scheduled._partial?.length ?? 0,
5959
5991
  originalPriceOpen: scheduled.priceOpen,
5960
- pnl: toProfitLossDto(scheduled, scheduled.priceOpen),
5992
+ pnl: publicSignal.pnl,
5993
+ maxDrawdown: publicSignal.maxDrawdown,
5994
+ peakProfit: publicSignal.peakProfit,
5995
+ signal: publicSignal,
5961
5996
  note: scheduled.note,
5962
5997
  });
5963
5998
  return null;
@@ -5968,7 +6003,7 @@ const ACTIVATE_SCHEDULED_SIGNAL_FN = async (self, scheduled, activationTimestamp
5968
6003
  await CALL_OPEN_CALLBACKS_FN(self, self.params.execution.context.symbol, self._pendingSignal, self._pendingSignal.priceOpen, activationTime, self.params.execution.context.backtest);
5969
6004
  const result = {
5970
6005
  action: "opened",
5971
- signal: TO_PUBLIC_SIGNAL(self._pendingSignal, self._pendingSignal.priceOpen),
6006
+ signal: TO_PUBLIC_SIGNAL("pending", self._pendingSignal, self._pendingSignal.priceOpen),
5972
6007
  strategyName: self.params.method.context.strategyName,
5973
6008
  exchangeName: self.params.method.context.exchangeName,
5974
6009
  frameName: self.params.method.context.frameName,
@@ -5982,7 +6017,7 @@ const ACTIVATE_SCHEDULED_SIGNAL_FN = async (self, scheduled, activationTimestamp
5982
6017
  };
5983
6018
  const CALL_SCHEDULE_PING_CALLBACKS_FN = trycatch(beginTime(async (self, symbol, scheduled, timestamp, backtest, currentPrice) => {
5984
6019
  await ExecutionContextService.runInContext(async () => {
5985
- const publicSignal = TO_PUBLIC_SIGNAL(scheduled, currentPrice);
6020
+ const publicSignal = TO_PUBLIC_SIGNAL("scheduled", scheduled, currentPrice);
5986
6021
  // Call system onSchedulePing callback first (emits to pingSubject)
5987
6022
  await self.params.onSchedulePing(self.params.execution.context.symbol, self.params.method.context.strategyName, self.params.method.context.exchangeName, publicSignal, currentPrice, self.params.execution.context.backtest, timestamp);
5988
6023
  // Call user onSchedulePing callback only if signal is still active (not cancelled, not activated)
@@ -6008,7 +6043,7 @@ const CALL_SCHEDULE_PING_CALLBACKS_FN = trycatch(beginTime(async (self, symbol,
6008
6043
  });
6009
6044
  const CALL_ACTIVE_PING_CALLBACKS_FN = trycatch(beginTime(async (self, symbol, pending, timestamp, backtest, currentPrice) => {
6010
6045
  await ExecutionContextService.runInContext(async () => {
6011
- const publicSignal = TO_PUBLIC_SIGNAL(pending, currentPrice);
6046
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", pending, currentPrice);
6012
6047
  // Call system onActivePing callback first (emits to activePingSubject)
6013
6048
  await self.params.onActivePing(self.params.execution.context.symbol, self.params.method.context.strategyName, self.params.method.context.exchangeName, publicSignal, currentPrice, self.params.execution.context.backtest, timestamp);
6014
6049
  // Call user onActivePing callback only if signal is still active (not closed)
@@ -6056,7 +6091,7 @@ const CALL_IDLE_PING_CALLBACKS_FN = trycatch(beginTime(async (self, symbol, time
6056
6091
  const CALL_ACTIVE_CALLBACKS_FN = trycatch(beginTime(async (self, symbol, signal, currentPrice, timestamp, backtest) => {
6057
6092
  await ExecutionContextService.runInContext(async () => {
6058
6093
  if (self.params.callbacks?.onActive) {
6059
- const publicSignal = TO_PUBLIC_SIGNAL(signal, currentPrice);
6094
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", signal, currentPrice);
6060
6095
  await self.params.callbacks.onActive(self.params.execution.context.symbol, publicSignal, currentPrice, self.params.execution.context.backtest);
6061
6096
  }
6062
6097
  }, {
@@ -6079,7 +6114,7 @@ const CALL_ACTIVE_CALLBACKS_FN = trycatch(beginTime(async (self, symbol, signal,
6079
6114
  const CALL_SCHEDULE_CALLBACKS_FN = trycatch(beginTime(async (self, symbol, signal, currentPrice, timestamp, backtest) => {
6080
6115
  await ExecutionContextService.runInContext(async () => {
6081
6116
  if (self.params.callbacks?.onSchedule) {
6082
- const publicSignal = TO_PUBLIC_SIGNAL(signal, currentPrice);
6117
+ const publicSignal = TO_PUBLIC_SIGNAL("scheduled", signal, currentPrice);
6083
6118
  await self.params.callbacks.onSchedule(self.params.execution.context.symbol, publicSignal, currentPrice, self.params.execution.context.backtest);
6084
6119
  }
6085
6120
  }, {
@@ -6102,7 +6137,7 @@ const CALL_SCHEDULE_CALLBACKS_FN = trycatch(beginTime(async (self, symbol, signa
6102
6137
  const CALL_CANCEL_CALLBACKS_FN = trycatch(beginTime(async (self, symbol, signal, currentPrice, timestamp, backtest) => {
6103
6138
  await ExecutionContextService.runInContext(async () => {
6104
6139
  if (self.params.callbacks?.onCancel) {
6105
- const publicSignal = TO_PUBLIC_SIGNAL(signal, currentPrice);
6140
+ const publicSignal = TO_PUBLIC_SIGNAL("scheduled", signal, currentPrice);
6106
6141
  await self.params.callbacks.onCancel(self.params.execution.context.symbol, publicSignal, currentPrice, self.params.execution.context.backtest);
6107
6142
  }
6108
6143
  }, {
@@ -6125,7 +6160,7 @@ const CALL_CANCEL_CALLBACKS_FN = trycatch(beginTime(async (self, symbol, signal,
6125
6160
  const CALL_OPEN_CALLBACKS_FN = trycatch(beginTime(async (self, symbol, signal, priceOpen, timestamp, backtest) => {
6126
6161
  await ExecutionContextService.runInContext(async () => {
6127
6162
  if (self.params.callbacks?.onOpen) {
6128
- const publicSignal = TO_PUBLIC_SIGNAL(signal, priceOpen);
6163
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", signal, priceOpen);
6129
6164
  await self.params.callbacks.onOpen(self.params.execution.context.symbol, publicSignal, priceOpen, self.params.execution.context.backtest);
6130
6165
  }
6131
6166
  }, {
@@ -6148,7 +6183,7 @@ const CALL_OPEN_CALLBACKS_FN = trycatch(beginTime(async (self, symbol, signal, p
6148
6183
  const CALL_CLOSE_CALLBACKS_FN = trycatch(beginTime(async (self, symbol, signal, currentPrice, timestamp, backtest) => {
6149
6184
  await ExecutionContextService.runInContext(async () => {
6150
6185
  if (self.params.callbacks?.onClose) {
6151
- const publicSignal = TO_PUBLIC_SIGNAL(signal, currentPrice);
6186
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", signal, currentPrice);
6152
6187
  await self.params.callbacks.onClose(self.params.execution.context.symbol, publicSignal, currentPrice, self.params.execution.context.backtest);
6153
6188
  }
6154
6189
  }, {
@@ -6271,7 +6306,7 @@ const CALL_RISK_REMOVE_SIGNAL_FN = trycatch(beginTime(async (self, symbol, times
6271
6306
  });
6272
6307
  const CALL_PARTIAL_CLEAR_FN = trycatch(beginTime(async (self, symbol, signal, currentPrice, timestamp, backtest) => {
6273
6308
  await ExecutionContextService.runInContext(async () => {
6274
- const publicSignal = TO_PUBLIC_SIGNAL(signal, currentPrice);
6309
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", signal, currentPrice);
6275
6310
  await self.params.partial.clear(symbol, publicSignal, currentPrice, backtest);
6276
6311
  }, {
6277
6312
  when: new Date(timestamp),
@@ -6293,7 +6328,7 @@ const CALL_PARTIAL_CLEAR_FN = trycatch(beginTime(async (self, symbol, signal, cu
6293
6328
  const CALL_RISK_CHECK_SIGNAL_FN = trycatch(beginTime(async (self, symbol, pendingSignal, currentPrice, timestamp, backtest) => {
6294
6329
  return await ExecutionContextService.runInContext(async () => {
6295
6330
  return await self.params.risk.checkSignal({
6296
- currentSignal: TO_PUBLIC_SIGNAL(pendingSignal, currentPrice),
6331
+ currentSignal: TO_PUBLIC_SIGNAL("scheduled", pendingSignal, currentPrice),
6297
6332
  symbol: symbol,
6298
6333
  strategyName: self.params.method.context.strategyName,
6299
6334
  exchangeName: self.params.method.context.exchangeName,
@@ -6322,7 +6357,7 @@ const CALL_RISK_CHECK_SIGNAL_FN = trycatch(beginTime(async (self, symbol, pendin
6322
6357
  });
6323
6358
  const CALL_PARTIAL_PROFIT_CALLBACKS_FN = trycatch(beginTime(async (self, symbol, signal, currentPrice, percentTp, timestamp, backtest) => {
6324
6359
  await ExecutionContextService.runInContext(async () => {
6325
- const publicSignal = TO_PUBLIC_SIGNAL(signal, currentPrice);
6360
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", signal, currentPrice);
6326
6361
  await self.params.partial.profit(symbol, publicSignal, currentPrice, percentTp, backtest, new Date(timestamp));
6327
6362
  if (self.params.callbacks?.onPartialProfit) {
6328
6363
  await self.params.callbacks.onPartialProfit(symbol, publicSignal, currentPrice, percentTp, backtest);
@@ -6346,7 +6381,7 @@ const CALL_PARTIAL_PROFIT_CALLBACKS_FN = trycatch(beginTime(async (self, symbol,
6346
6381
  });
6347
6382
  const CALL_PARTIAL_LOSS_CALLBACKS_FN = trycatch(beginTime(async (self, symbol, signal, currentPrice, percentSl, timestamp, backtest) => {
6348
6383
  await ExecutionContextService.runInContext(async () => {
6349
- const publicSignal = TO_PUBLIC_SIGNAL(signal, currentPrice);
6384
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", signal, currentPrice);
6350
6385
  await self.params.partial.loss(symbol, publicSignal, currentPrice, percentSl, backtest, new Date(timestamp));
6351
6386
  if (self.params.callbacks?.onPartialLoss) {
6352
6387
  await self.params.callbacks.onPartialLoss(symbol, publicSignal, currentPrice, percentSl, backtest);
@@ -6370,7 +6405,7 @@ const CALL_PARTIAL_LOSS_CALLBACKS_FN = trycatch(beginTime(async (self, symbol, s
6370
6405
  });
6371
6406
  const CALL_BREAKEVEN_CHECK_FN = trycatch(beginTime(async (self, symbol, signal, currentPrice, timestamp, backtest) => {
6372
6407
  await ExecutionContextService.runInContext(async () => {
6373
- const publicSignal = TO_PUBLIC_SIGNAL(signal, currentPrice);
6408
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", signal, currentPrice);
6374
6409
  const isBreakeven = await self.params.breakeven.check(symbol, publicSignal, currentPrice, backtest, new Date(timestamp));
6375
6410
  if (self.params.callbacks?.onBreakeven) {
6376
6411
  isBreakeven && await self.params.callbacks.onBreakeven(symbol, publicSignal, currentPrice, backtest);
@@ -6394,7 +6429,7 @@ const CALL_BREAKEVEN_CHECK_FN = trycatch(beginTime(async (self, symbol, signal,
6394
6429
  });
6395
6430
  const CALL_BREAKEVEN_CLEAR_FN = trycatch(beginTime(async (self, symbol, signal, currentPrice, timestamp, backtest) => {
6396
6431
  await ExecutionContextService.runInContext(async () => {
6397
- const publicSignal = TO_PUBLIC_SIGNAL(signal, currentPrice);
6432
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", signal, currentPrice);
6398
6433
  await self.params.breakeven.clear(symbol, publicSignal, currentPrice, backtest);
6399
6434
  }, {
6400
6435
  when: new Date(timestamp),
@@ -6417,7 +6452,7 @@ const CALL_BACKTEST_SCHEDULE_OPEN_FN = trycatch(beginTime(async (self, symbol, s
6417
6452
  await ExecutionContextService.runInContext(async () => {
6418
6453
  backtestScheduleOpenSubject.next({
6419
6454
  action: "opened",
6420
- signal: TO_PUBLIC_SIGNAL(signal, signal.priceOpen),
6455
+ signal: TO_PUBLIC_SIGNAL("pending", signal, signal.priceOpen),
6421
6456
  strategyName: self.params.method.context.strategyName,
6422
6457
  exchangeName: self.params.method.context.exchangeName,
6423
6458
  frameName: self.params.method.context.frameName,
@@ -6446,10 +6481,10 @@ const CALL_BACKTEST_SCHEDULE_OPEN_FN = trycatch(beginTime(async (self, symbol, s
6446
6481
  const RETURN_SCHEDULED_SIGNAL_ACTIVE_FN = async (self, scheduled, currentPrice) => {
6447
6482
  const currentTime = self.params.execution.context.when.getTime();
6448
6483
  await CALL_SCHEDULE_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, scheduled, currentTime, self.params.execution.context.backtest, currentPrice);
6449
- const pnl = toProfitLossDto(scheduled, currentPrice);
6484
+ const publicSignal = TO_PUBLIC_SIGNAL("scheduled", scheduled, currentPrice);
6450
6485
  const result = {
6451
6486
  action: "waiting",
6452
- signal: TO_PUBLIC_SIGNAL(scheduled, currentPrice),
6487
+ signal: publicSignal,
6453
6488
  currentPrice: currentPrice,
6454
6489
  strategyName: self.params.method.context.strategyName,
6455
6490
  exchangeName: self.params.method.context.exchangeName,
@@ -6457,7 +6492,7 @@ const RETURN_SCHEDULED_SIGNAL_ACTIVE_FN = async (self, scheduled, currentPrice)
6457
6492
  symbol: self.params.execution.context.symbol,
6458
6493
  percentTp: 0,
6459
6494
  percentSl: 0,
6460
- pnl,
6495
+ pnl: publicSignal.pnl,
6461
6496
  backtest: self.params.execution.context.backtest,
6462
6497
  createdAt: currentTime,
6463
6498
  };
@@ -6477,7 +6512,7 @@ const OPEN_NEW_SCHEDULED_SIGNAL_FN = async (self, signal) => {
6477
6512
  await CALL_SCHEDULE_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentPrice, currentTime, self.params.execution.context.backtest);
6478
6513
  const result = {
6479
6514
  action: "scheduled",
6480
- signal: TO_PUBLIC_SIGNAL(signal, currentPrice),
6515
+ signal: TO_PUBLIC_SIGNAL("scheduled", signal, currentPrice),
6481
6516
  strategyName: self.params.method.context.strategyName,
6482
6517
  exchangeName: self.params.method.context.exchangeName,
6483
6518
  frameName: self.params.method.context.frameName,
@@ -6507,7 +6542,7 @@ const OPEN_NEW_PENDING_SIGNAL_FN = async (self, signal) => {
6507
6542
  await CALL_OPEN_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, signal.priceOpen, currentTime, self.params.execution.context.backtest);
6508
6543
  const result = {
6509
6544
  action: "opened",
6510
- signal: TO_PUBLIC_SIGNAL(signal, signal.priceOpen),
6545
+ signal: TO_PUBLIC_SIGNAL("pending", signal, signal.priceOpen),
6511
6546
  strategyName: self.params.method.context.strategyName,
6512
6547
  exchangeName: self.params.method.context.exchangeName,
6513
6548
  frameName: self.params.method.context.frameName,
@@ -6562,13 +6597,13 @@ const CLOSE_PENDING_SIGNAL_FN = async (self, signal, currentPrice, closeReason)
6562
6597
  });
6563
6598
  return null;
6564
6599
  }
6565
- const pnl = toProfitLossDto(signal, currentPrice);
6600
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", signal, currentPrice);
6566
6601
  self.params.logger.info(`ClientStrategy signal ${closeReason}`, {
6567
6602
  symbol: self.params.execution.context.symbol,
6568
6603
  signalId: signal.id,
6569
6604
  closeReason,
6570
6605
  priceClose: currentPrice,
6571
- pnlPercentage: pnl.pnlPercentage,
6606
+ pnlPercentage: publicSignal.pnl.pnlPercentage,
6572
6607
  });
6573
6608
  await CALL_CLOSE_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentPrice, currentTime, self.params.execution.context.backtest);
6574
6609
  // КРИТИЧНО: Очищаем состояние ClientPartial при закрытии позиции
@@ -6579,11 +6614,11 @@ const CLOSE_PENDING_SIGNAL_FN = async (self, signal, currentPrice, closeReason)
6579
6614
  await self.setPendingSignal(null);
6580
6615
  const result = {
6581
6616
  action: "closed",
6582
- signal: TO_PUBLIC_SIGNAL(signal, currentPrice),
6617
+ signal: publicSignal,
6583
6618
  currentPrice: currentPrice,
6584
6619
  closeReason: closeReason,
6585
6620
  closeTimestamp: currentTime,
6586
- pnl: pnl,
6621
+ pnl: publicSignal.pnl,
6587
6622
  strategyName: self.params.method.context.strategyName,
6588
6623
  exchangeName: self.params.method.context.exchangeName,
6589
6624
  frameName: self.params.method.context.frameName,
@@ -6598,17 +6633,12 @@ const RETURN_PENDING_SIGNAL_ACTIVE_FN = async (self, signal, currentPrice, backt
6598
6633
  let percentTp = 0;
6599
6634
  let percentSl = 0;
6600
6635
  const currentTime = self.params.execution.context.when.getTime();
6601
- await CALL_ACTIVE_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentTime, self.params.execution.context.backtest, currentPrice);
6602
6636
  // Calculate percentage of path to TP/SL for partial fill/loss callbacks
6603
6637
  {
6604
6638
  const effectivePriceOpen = getEffectivePriceOpen(signal);
6605
6639
  if (signal.position === "long") {
6606
6640
  // For long: calculate progress towards TP or SL
6607
6641
  const currentDistance = currentPrice - effectivePriceOpen;
6608
- if (currentDistance > 0) {
6609
- // Check if breakeven should be triggered
6610
- await CALL_BREAKEVEN_CHECK_FN(self, self.params.execution.context.symbol, signal, currentPrice, currentTime, self.params.execution.context.backtest);
6611
- }
6612
6642
  if (currentDistance > 0) {
6613
6643
  // Moving towards TP (use trailing TP if set)
6614
6644
  const effectiveTakeProfit = signal._trailingPriceTakeProfit ?? signal.priceTakeProfit;
@@ -6616,14 +6646,17 @@ const RETURN_PENDING_SIGNAL_ACTIVE_FN = async (self, signal, currentPrice, backt
6616
6646
  const progressPercent = (currentDistance / tpDistance) * 100;
6617
6647
  percentTp = Math.min(progressPercent, 100);
6618
6648
  if (currentPrice > signal._peak.price) {
6619
- const { pnl } = TO_PUBLIC_SIGNAL(signal, currentPrice);
6620
- signal._peak = { price: currentPrice, timestamp: currentTime, pnlCost: pnl.pnlCost, pnlPercentage: pnl.pnlPercentage };
6649
+ const { pnl } = TO_PUBLIC_SIGNAL("pending", signal, currentPrice);
6650
+ signal._peak = { price: currentPrice, timestamp: currentTime, pnlCost: pnl.pnlCost, pnlPercentage: pnl.pnlPercentage, pnlEntries: pnl.pnlEntries, priceClose: pnl.priceClose, priceOpen: pnl.priceOpen };
6621
6651
  if (self.params.callbacks?.onWrite) {
6622
6652
  self.params.callbacks.onWrite(signal.symbol, signal, backtest);
6623
6653
  }
6624
6654
  !backtest && await PersistSignalAdapter.writeSignalData(signal, self.params.execution.context.symbol, self.params.strategyName, self.params.exchangeName);
6625
- await self.params.onHighestProfit(TO_PUBLIC_SIGNAL(signal, currentPrice), currentPrice, currentTime);
6655
+ await self.params.onHighestProfit(TO_PUBLIC_SIGNAL("pending", signal, currentPrice), currentPrice, currentTime);
6626
6656
  }
6657
+ await CALL_ACTIVE_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentTime, self.params.execution.context.backtest, currentPrice);
6658
+ // Check if breakeven should be triggered
6659
+ await CALL_BREAKEVEN_CHECK_FN(self, self.params.execution.context.symbol, signal, currentPrice, currentTime, self.params.execution.context.backtest);
6627
6660
  await CALL_PARTIAL_PROFIT_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentPrice, percentTp, currentTime, self.params.execution.context.backtest);
6628
6661
  }
6629
6662
  else if (currentDistance < 0) {
@@ -6633,24 +6666,24 @@ const RETURN_PENDING_SIGNAL_ACTIVE_FN = async (self, signal, currentPrice, backt
6633
6666
  const progressPercent = (Math.abs(currentDistance) / slDistance) * 100;
6634
6667
  percentSl = Math.min(progressPercent, 100);
6635
6668
  if (currentPrice < signal._fall.price) {
6636
- const { pnl } = TO_PUBLIC_SIGNAL(signal, currentPrice);
6637
- signal._fall = { price: currentPrice, timestamp: currentTime, pnlCost: pnl.pnlCost, pnlPercentage: pnl.pnlPercentage };
6669
+ const { pnl } = TO_PUBLIC_SIGNAL("pending", signal, currentPrice);
6670
+ signal._fall = { price: currentPrice, timestamp: currentTime, pnlCost: pnl.pnlCost, pnlPercentage: pnl.pnlPercentage, pnlEntries: pnl.pnlEntries, priceClose: pnl.priceClose, priceOpen: pnl.priceOpen };
6638
6671
  if (self.params.callbacks?.onWrite) {
6639
6672
  self.params.callbacks.onWrite(signal.symbol, signal, backtest);
6640
6673
  }
6641
6674
  !backtest && await PersistSignalAdapter.writeSignalData(signal, self.params.execution.context.symbol, self.params.strategyName, self.params.exchangeName);
6642
- await self.params.onMaxDrawdown(TO_PUBLIC_SIGNAL(signal, currentPrice), currentPrice, currentTime);
6675
+ await self.params.onMaxDrawdown(TO_PUBLIC_SIGNAL("pending", signal, currentPrice), currentPrice, currentTime);
6643
6676
  }
6677
+ await CALL_ACTIVE_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentTime, self.params.execution.context.backtest, currentPrice);
6644
6678
  await CALL_PARTIAL_LOSS_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentPrice, percentSl, currentTime, self.params.execution.context.backtest);
6645
6679
  }
6680
+ else {
6681
+ await CALL_ACTIVE_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentTime, self.params.execution.context.backtest, currentPrice);
6682
+ }
6646
6683
  }
6647
6684
  else if (signal.position === "short") {
6648
6685
  // For short: calculate progress towards TP or SL
6649
6686
  const currentDistance = effectivePriceOpen - currentPrice;
6650
- if (currentDistance > 0) {
6651
- // Check if breakeven should be triggered
6652
- await CALL_BREAKEVEN_CHECK_FN(self, self.params.execution.context.symbol, signal, currentPrice, currentTime, self.params.execution.context.backtest);
6653
- }
6654
6687
  if (currentDistance > 0) {
6655
6688
  // Moving towards TP (use trailing TP if set)
6656
6689
  const effectiveTakeProfit = signal._trailingPriceTakeProfit ?? signal.priceTakeProfit;
@@ -6658,39 +6691,46 @@ const RETURN_PENDING_SIGNAL_ACTIVE_FN = async (self, signal, currentPrice, backt
6658
6691
  const progressPercent = (currentDistance / tpDistance) * 100;
6659
6692
  percentTp = Math.min(progressPercent, 100);
6660
6693
  if (currentPrice < signal._peak.price) {
6661
- const { pnl } = TO_PUBLIC_SIGNAL(signal, currentPrice);
6662
- signal._peak = { price: currentPrice, timestamp: currentTime, pnlCost: pnl.pnlCost, pnlPercentage: pnl.pnlPercentage };
6694
+ const { pnl } = TO_PUBLIC_SIGNAL("pending", signal, currentPrice);
6695
+ signal._peak = { price: currentPrice, timestamp: currentTime, pnlCost: pnl.pnlCost, pnlPercentage: pnl.pnlPercentage, pnlEntries: pnl.pnlEntries, priceClose: pnl.priceClose, priceOpen: pnl.priceOpen };
6663
6696
  if (self.params.callbacks?.onWrite) {
6664
6697
  self.params.callbacks.onWrite(signal.symbol, signal, backtest);
6665
6698
  }
6666
6699
  !backtest && await PersistSignalAdapter.writeSignalData(signal, self.params.execution.context.symbol, self.params.strategyName, self.params.exchangeName);
6667
- await self.params.onHighestProfit(TO_PUBLIC_SIGNAL(signal, currentPrice), currentPrice, currentTime);
6700
+ await self.params.onHighestProfit(TO_PUBLIC_SIGNAL("pending", signal, currentPrice), currentPrice, currentTime);
6668
6701
  }
6702
+ await CALL_ACTIVE_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentTime, self.params.execution.context.backtest, currentPrice);
6703
+ // Check if breakeven should be triggered
6704
+ await CALL_BREAKEVEN_CHECK_FN(self, self.params.execution.context.symbol, signal, currentPrice, currentTime, self.params.execution.context.backtest);
6669
6705
  await CALL_PARTIAL_PROFIT_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentPrice, percentTp, currentTime, self.params.execution.context.backtest);
6670
6706
  }
6671
- if (currentDistance < 0) {
6707
+ else if (currentDistance < 0) {
6672
6708
  // Moving towards SL (use trailing SL if set)
6673
6709
  const effectiveStopLoss = signal._trailingPriceStopLoss ?? signal.priceStopLoss;
6674
6710
  const slDistance = effectiveStopLoss - effectivePriceOpen;
6675
6711
  const progressPercent = (Math.abs(currentDistance) / slDistance) * 100;
6676
6712
  percentSl = Math.min(progressPercent, 100);
6677
6713
  if (currentPrice > signal._fall.price) {
6678
- const { pnl } = TO_PUBLIC_SIGNAL(signal, currentPrice);
6679
- signal._fall = { price: currentPrice, timestamp: currentTime, pnlCost: pnl.pnlCost, pnlPercentage: pnl.pnlPercentage };
6714
+ const { pnl } = TO_PUBLIC_SIGNAL("pending", signal, currentPrice);
6715
+ signal._fall = { price: currentPrice, timestamp: currentTime, pnlCost: pnl.pnlCost, pnlPercentage: pnl.pnlPercentage, pnlEntries: pnl.pnlEntries, priceClose: pnl.priceClose, priceOpen: pnl.priceOpen };
6680
6716
  if (self.params.callbacks?.onWrite) {
6681
6717
  self.params.callbacks.onWrite(signal.symbol, signal, backtest);
6682
6718
  }
6683
6719
  !backtest && await PersistSignalAdapter.writeSignalData(signal, self.params.execution.context.symbol, self.params.strategyName, self.params.exchangeName);
6684
- await self.params.onMaxDrawdown(TO_PUBLIC_SIGNAL(signal, currentPrice), currentPrice, currentTime);
6720
+ await self.params.onMaxDrawdown(TO_PUBLIC_SIGNAL("pending", signal, currentPrice), currentPrice, currentTime);
6685
6721
  }
6722
+ await CALL_ACTIVE_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentTime, self.params.execution.context.backtest, currentPrice);
6686
6723
  await CALL_PARTIAL_LOSS_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentPrice, percentSl, currentTime, self.params.execution.context.backtest);
6687
6724
  }
6725
+ else {
6726
+ await CALL_ACTIVE_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentTime, self.params.execution.context.backtest, currentPrice);
6727
+ }
6688
6728
  }
6689
6729
  }
6690
- const pnl = toProfitLossDto(signal, currentPrice);
6730
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", signal, currentPrice);
6691
6731
  const result = {
6692
6732
  action: "active",
6693
- signal: TO_PUBLIC_SIGNAL(signal, currentPrice),
6733
+ signal: publicSignal,
6694
6734
  currentPrice: currentPrice,
6695
6735
  strategyName: self.params.method.context.strategyName,
6696
6736
  exchangeName: self.params.method.context.exchangeName,
@@ -6698,7 +6738,7 @@ const RETURN_PENDING_SIGNAL_ACTIVE_FN = async (self, signal, currentPrice, backt
6698
6738
  symbol: self.params.execution.context.symbol,
6699
6739
  percentTp,
6700
6740
  percentSl,
6701
- pnl,
6741
+ pnl: publicSignal.pnl,
6702
6742
  backtest: self.params.execution.context.backtest,
6703
6743
  createdAt: currentTime,
6704
6744
  _backtestLastTimestamp: currentTime,
@@ -6734,6 +6774,7 @@ const CANCEL_SCHEDULED_SIGNAL_IN_BACKTEST_FN = async (self, scheduled, averagePr
6734
6774
  reason,
6735
6775
  });
6736
6776
  await self.setScheduledSignal(null);
6777
+ const publicSignal = TO_PUBLIC_SIGNAL("scheduled", scheduled, averagePrice);
6737
6778
  if (reason === "user") {
6738
6779
  await CALL_COMMIT_FN(self, {
6739
6780
  action: "cancel-scheduled",
@@ -6748,14 +6789,17 @@ const CANCEL_SCHEDULED_SIGNAL_IN_BACKTEST_FN = async (self, scheduled, averagePr
6748
6789
  totalEntries: scheduled._entry?.length ?? 1,
6749
6790
  totalPartials: scheduled._partial?.length ?? 0,
6750
6791
  originalPriceOpen: scheduled.priceOpen,
6751
- pnl: toProfitLossDto(scheduled, averagePrice),
6792
+ pnl: publicSignal.pnl,
6793
+ maxDrawdown: publicSignal.maxDrawdown,
6794
+ peakProfit: publicSignal.peakProfit,
6795
+ signal: publicSignal,
6752
6796
  note: cancelNote ?? scheduled.note,
6753
6797
  });
6754
6798
  }
6755
6799
  await CALL_CANCEL_CALLBACKS_FN(self, self.params.execution.context.symbol, scheduled, averagePrice, closeTimestamp, self.params.execution.context.backtest);
6756
6800
  const result = {
6757
6801
  action: "cancelled",
6758
- signal: TO_PUBLIC_SIGNAL(scheduled, averagePrice),
6802
+ signal: publicSignal,
6759
6803
  currentPrice: averagePrice,
6760
6804
  closeTimestamp: closeTimestamp,
6761
6805
  strategyName: self.params.method.context.strategyName,
@@ -6804,8 +6848,8 @@ const ACTIVATE_SCHEDULED_SIGNAL_IN_BACKTEST_FN = async (self, scheduled, activat
6804
6848
  ...scheduled,
6805
6849
  pendingAt: activationTime,
6806
6850
  _isScheduled: false,
6807
- _peak: { price: scheduled.priceOpen, timestamp: activationTime, pnlPercentage: 0, pnlCost: 0 },
6808
- _fall: { price: scheduled.priceOpen, timestamp: activationTime, pnlPercentage: 0, pnlCost: 0 },
6851
+ _peak: { price: scheduled.priceOpen, timestamp: activationTime, pnlPercentage: 0, pnlCost: 0, pnlEntries: 0, priceClose: 0, priceOpen: 0 },
6852
+ _fall: { price: scheduled.priceOpen, timestamp: activationTime, pnlPercentage: 0, pnlCost: 0, pnlEntries: 0, priceClose: 0, priceOpen: 0 },
6809
6853
  };
6810
6854
  // Sync open: if external system rejects — cancel scheduled signal instead of opening
6811
6855
  const syncOpenAllowed = await CALL_SIGNAL_SYNC_OPEN_FN(activationTime, activatedSignal.priceOpen, activatedSignal, self);
@@ -6815,6 +6859,7 @@ const ACTIVATE_SCHEDULED_SIGNAL_IN_BACKTEST_FN = async (self, scheduled, activat
6815
6859
  signalId: scheduled.id,
6816
6860
  });
6817
6861
  await self.setScheduledSignal(null);
6862
+ const publicSignal = TO_PUBLIC_SIGNAL("scheduled", scheduled, scheduled.priceOpen);
6818
6863
  await CALL_COMMIT_FN(self, {
6819
6864
  action: "cancel-scheduled",
6820
6865
  symbol: self.params.execution.context.symbol,
@@ -6827,7 +6872,10 @@ const ACTIVATE_SCHEDULED_SIGNAL_IN_BACKTEST_FN = async (self, scheduled, activat
6827
6872
  totalEntries: scheduled._entry?.length ?? 1,
6828
6873
  totalPartials: scheduled._partial?.length ?? 0,
6829
6874
  originalPriceOpen: scheduled.priceOpen,
6830
- pnl: toProfitLossDto(scheduled, scheduled.priceOpen),
6875
+ pnl: publicSignal.pnl,
6876
+ maxDrawdown: publicSignal.maxDrawdown,
6877
+ peakProfit: publicSignal.peakProfit,
6878
+ signal: publicSignal,
6831
6879
  note: scheduled.note,
6832
6880
  });
6833
6881
  return false;
@@ -6850,20 +6898,20 @@ const CLOSE_PENDING_SIGNAL_IN_BACKTEST_FN = async (self, signal, averagePrice, c
6850
6898
  });
6851
6899
  return null;
6852
6900
  }
6853
- const pnl = toProfitLossDto(signal, averagePrice);
6901
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", signal, averagePrice);
6854
6902
  self.params.logger.debug(`ClientStrategy backtest ${closeReason}`, {
6855
6903
  symbol: self.params.execution.context.symbol,
6856
6904
  signalId: signal.id,
6857
6905
  reason: closeReason,
6858
6906
  priceClose: averagePrice,
6859
6907
  closeTimestamp,
6860
- pnlPercentage: pnl.pnlPercentage,
6908
+ pnlPercentage: publicSignal.pnl.pnlPercentage,
6861
6909
  });
6862
6910
  if (closeReason === "stop_loss") {
6863
- self.params.logger.warn(`ClientStrategy backtest: Signal closed with loss (stop_loss), PNL: ${pnl.pnlPercentage.toFixed(2)}%`);
6911
+ self.params.logger.warn(`ClientStrategy backtest: Signal closed with loss (stop_loss), PNL: ${publicSignal.pnl.pnlPercentage.toFixed(2)}%`);
6864
6912
  }
6865
- if (closeReason === "time_expired" && pnl.pnlPercentage < 0) {
6866
- self.params.logger.warn(`ClientStrategy backtest: Signal closed with loss (time_expired), PNL: ${pnl.pnlPercentage.toFixed(2)}%`);
6913
+ if (closeReason === "time_expired" && publicSignal.pnl.pnlPercentage < 0) {
6914
+ self.params.logger.warn(`ClientStrategy backtest: Signal closed with loss (time_expired), PNL: ${publicSignal.pnl.pnlPercentage.toFixed(2)}%`);
6867
6915
  }
6868
6916
  await CALL_CLOSE_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, averagePrice, closeTimestamp, self.params.execution.context.backtest);
6869
6917
  // КРИТИЧНО: Очищаем состояние ClientPartial при закрытии позиции
@@ -6874,11 +6922,11 @@ const CLOSE_PENDING_SIGNAL_IN_BACKTEST_FN = async (self, signal, averagePrice, c
6874
6922
  await self.setPendingSignal(null);
6875
6923
  const result = {
6876
6924
  action: "closed",
6877
- signal: TO_PUBLIC_SIGNAL(signal, averagePrice),
6925
+ signal: publicSignal,
6878
6926
  currentPrice: averagePrice,
6879
6927
  closeReason: closeReason,
6880
6928
  closeTimestamp: closeTimestamp,
6881
- pnl: pnl,
6929
+ pnl: publicSignal.pnl,
6882
6930
  strategyName: self.params.method.context.strategyName,
6883
6931
  exchangeName: self.params.method.context.exchangeName,
6884
6932
  frameName: self.params.method.context.frameName,
@@ -6902,6 +6950,7 @@ const CLOSE_USER_PENDING_SIGNAL_IN_BACKTEST_FN = async (self, closedSignal, aver
6902
6950
  `Retry backtest() with new candle data.`);
6903
6951
  }
6904
6952
  self._closedSignal = null;
6953
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", closedSignal, averagePrice);
6905
6954
  await CALL_COMMIT_FN(self, {
6906
6955
  action: "close-pending",
6907
6956
  symbol: self.params.execution.context.symbol,
@@ -6915,21 +6964,23 @@ const CLOSE_USER_PENDING_SIGNAL_IN_BACKTEST_FN = async (self, closedSignal, aver
6915
6964
  totalEntries: closedSignal._entry?.length ?? 1,
6916
6965
  totalPartials: closedSignal._partial?.length ?? 0,
6917
6966
  originalPriceOpen: closedSignal.priceOpen,
6918
- pnl: toProfitLossDto(closedSignal, averagePrice),
6967
+ pnl: publicSignal.pnl,
6968
+ maxDrawdown: publicSignal.maxDrawdown,
6969
+ peakProfit: publicSignal.peakProfit,
6970
+ signal: publicSignal,
6919
6971
  note: closedSignal.closeNote ?? closedSignal.note,
6920
6972
  });
6921
6973
  await CALL_CLOSE_CALLBACKS_FN(self, self.params.execution.context.symbol, closedSignal, averagePrice, closeTimestamp, self.params.execution.context.backtest);
6922
6974
  await CALL_PARTIAL_CLEAR_FN(self, self.params.execution.context.symbol, closedSignal, averagePrice, closeTimestamp, self.params.execution.context.backtest);
6923
6975
  await CALL_BREAKEVEN_CLEAR_FN(self, self.params.execution.context.symbol, closedSignal, averagePrice, closeTimestamp, self.params.execution.context.backtest);
6924
6976
  await CALL_RISK_REMOVE_SIGNAL_FN(self, self.params.execution.context.symbol, closeTimestamp, self.params.execution.context.backtest);
6925
- const pnl = toProfitLossDto(closedSignal, averagePrice);
6926
6977
  const result = {
6927
6978
  action: "closed",
6928
- signal: TO_PUBLIC_SIGNAL(closedSignal, averagePrice),
6979
+ signal: publicSignal,
6929
6980
  currentPrice: averagePrice,
6930
6981
  closeReason: "closed",
6931
6982
  closeTimestamp,
6932
- pnl,
6983
+ pnl: publicSignal.pnl,
6933
6984
  strategyName: self.params.method.context.strategyName,
6934
6985
  exchangeName: self.params.method.context.exchangeName,
6935
6986
  frameName: self.params.method.context.frameName,
@@ -6994,8 +7045,8 @@ const PROCESS_SCHEDULED_SIGNAL_CANDLES_FN = async (self, scheduled, candles, fra
6994
7045
  ...activatedSignal,
6995
7046
  pendingAt: candle.timestamp,
6996
7047
  _isScheduled: false,
6997
- _peak: { price: activatedSignal.priceOpen, timestamp: candle.timestamp, pnlPercentage: 0, pnlCost: 0 },
6998
- _fall: { price: activatedSignal.priceOpen, timestamp: candle.timestamp, pnlPercentage: 0, pnlCost: 0 },
7048
+ _peak: { price: activatedSignal.priceOpen, timestamp: candle.timestamp, pnlPercentage: 0, pnlCost: 0, priceClose: 0, priceOpen: 0, pnlEntries: 0 },
7049
+ _fall: { price: activatedSignal.priceOpen, timestamp: candle.timestamp, pnlPercentage: 0, pnlCost: 0, priceClose: 0, priceOpen: 0, pnlEntries: 0 },
6999
7050
  };
7000
7051
  // Sync open: if external system rejects — cancel scheduled signal instead of opening
7001
7052
  const syncOpenAllowed = await CALL_SIGNAL_SYNC_OPEN_FN(candle.timestamp, pendingSignal.priceOpen, pendingSignal, self);
@@ -7005,6 +7056,7 @@ const PROCESS_SCHEDULED_SIGNAL_CANDLES_FN = async (self, scheduled, candles, fra
7005
7056
  signalId: activatedSignal.id,
7006
7057
  });
7007
7058
  await self.setScheduledSignal(null);
7059
+ const publicSignal = TO_PUBLIC_SIGNAL("scheduled", activatedSignal, averagePrice);
7008
7060
  await CALL_COMMIT_FN(self, {
7009
7061
  action: "cancel-scheduled",
7010
7062
  symbol: self.params.execution.context.symbol,
@@ -7017,7 +7069,10 @@ const PROCESS_SCHEDULED_SIGNAL_CANDLES_FN = async (self, scheduled, candles, fra
7017
7069
  totalEntries: activatedSignal._entry?.length ?? 1,
7018
7070
  totalPartials: activatedSignal._partial?.length ?? 0,
7019
7071
  originalPriceOpen: activatedSignal.priceOpen,
7020
- pnl: toProfitLossDto(activatedSignal, averagePrice),
7072
+ pnl: publicSignal.pnl,
7073
+ maxDrawdown: publicSignal.maxDrawdown,
7074
+ peakProfit: publicSignal.peakProfit,
7075
+ signal: publicSignal,
7021
7076
  note: activatedSignal.activateNote ?? activatedSignal.note,
7022
7077
  });
7023
7078
  return { outcome: "pending" };
@@ -7026,7 +7081,7 @@ const PROCESS_SCHEDULED_SIGNAL_CANDLES_FN = async (self, scheduled, candles, fra
7026
7081
  await self.setPendingSignal(pendingSignal);
7027
7082
  await CALL_RISK_ADD_SIGNAL_FN(self, self.params.execution.context.symbol, pendingSignal, candle.timestamp, self.params.execution.context.backtest);
7028
7083
  // Emit commit AFTER successful risk check
7029
- const publicSignalForCommit = TO_PUBLIC_SIGNAL(pendingSignal, averagePrice);
7084
+ const publicSignalForCommit = TO_PUBLIC_SIGNAL("pending", pendingSignal, averagePrice);
7030
7085
  await CALL_COMMIT_FN(self, {
7031
7086
  action: "activate-scheduled",
7032
7087
  symbol: self.params.execution.context.symbol,
@@ -7038,7 +7093,10 @@ const PROCESS_SCHEDULED_SIGNAL_CANDLES_FN = async (self, scheduled, candles, fra
7038
7093
  activateId: activatedSignal.activateId,
7039
7094
  timestamp: candle.timestamp,
7040
7095
  currentPrice: averagePrice,
7041
- pnl: toProfitLossDto(pendingSignal, averagePrice),
7096
+ pnl: publicSignalForCommit.pnl,
7097
+ maxDrawdown: publicSignalForCommit.maxDrawdown,
7098
+ peakProfit: publicSignalForCommit.peakProfit,
7099
+ signal: publicSignalForCommit,
7042
7100
  position: publicSignalForCommit.position,
7043
7101
  priceOpen: publicSignalForCommit.priceOpen,
7044
7102
  priceTakeProfit: publicSignalForCommit.priceTakeProfit,
@@ -7139,7 +7197,6 @@ const PROCESS_PENDING_SIGNAL_CANDLES_FN = async (self, signal, candles, frameEnd
7139
7197
  if (self._closedSignal) {
7140
7198
  return await CLOSE_USER_PENDING_SIGNAL_IN_BACKTEST_FN(self, self._closedSignal, averagePrice, currentCandleTimestamp);
7141
7199
  }
7142
- await CALL_ACTIVE_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentCandleTimestamp, true, averagePrice);
7143
7200
  let shouldClose = false;
7144
7201
  let closeReason;
7145
7202
  // Check time expiration FIRST (КРИТИЧНО!)
@@ -7198,23 +7255,21 @@ const PROCESS_PENDING_SIGNAL_CANDLES_FN = async (self, signal, candles, frameEnd
7198
7255
  if (signal.position === "long") {
7199
7256
  // For long: calculate progress towards TP or SL
7200
7257
  const currentDistance = averagePrice - effectivePriceOpen;
7201
- if (currentDistance > 0) {
7202
- // Check if breakeven should be triggered
7203
- await CALL_BREAKEVEN_CHECK_FN(self, self.params.execution.context.symbol, signal, averagePrice, currentCandleTimestamp, self.params.execution.context.backtest);
7204
- }
7205
7258
  if (currentDistance > 0) {
7206
7259
  // Moving towards TP (use trailing TP if set)
7207
7260
  const effectiveTakeProfit = signal._trailingPriceTakeProfit ?? signal.priceTakeProfit;
7208
7261
  const tpDistance = effectiveTakeProfit - effectivePriceOpen;
7209
7262
  const progressPercent = (currentDistance / tpDistance) * 100;
7210
7263
  if (averagePrice > signal._peak.price) {
7211
- const { pnl } = TO_PUBLIC_SIGNAL(signal, averagePrice);
7212
- signal._peak = { price: averagePrice, timestamp: currentCandleTimestamp, pnlCost: pnl.pnlCost, pnlPercentage: pnl.pnlPercentage };
7264
+ const { pnl } = TO_PUBLIC_SIGNAL("pending", signal, averagePrice);
7265
+ signal._peak = { price: averagePrice, timestamp: currentCandleTimestamp, pnlCost: pnl.pnlCost, pnlPercentage: pnl.pnlPercentage, pnlEntries: pnl.pnlEntries, priceOpen: pnl.priceOpen, priceClose: pnl.priceClose };
7213
7266
  if (self.params.callbacks?.onWrite) {
7214
7267
  self.params.callbacks.onWrite(signal.symbol, signal, true);
7215
7268
  }
7216
- await self.params.onHighestProfit(TO_PUBLIC_SIGNAL(signal, averagePrice), averagePrice, currentCandleTimestamp);
7269
+ await self.params.onHighestProfit(TO_PUBLIC_SIGNAL("pending", signal, averagePrice), averagePrice, currentCandleTimestamp);
7217
7270
  }
7271
+ await CALL_ACTIVE_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentCandleTimestamp, true, averagePrice);
7272
+ await CALL_BREAKEVEN_CHECK_FN(self, self.params.execution.context.symbol, signal, averagePrice, currentCandleTimestamp, self.params.execution.context.backtest);
7218
7273
  await CALL_PARTIAL_PROFIT_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, averagePrice, Math.min(progressPercent, 100), currentCandleTimestamp, self.params.execution.context.backtest);
7219
7274
  }
7220
7275
  else if (currentDistance < 0) {
@@ -7223,53 +7278,59 @@ const PROCESS_PENDING_SIGNAL_CANDLES_FN = async (self, signal, candles, frameEnd
7223
7278
  const slDistance = effectivePriceOpen - effectiveStopLoss;
7224
7279
  const progressPercent = (Math.abs(currentDistance) / slDistance) * 100;
7225
7280
  if (averagePrice < signal._fall.price) {
7226
- const { pnl } = TO_PUBLIC_SIGNAL(signal, averagePrice);
7227
- signal._fall = { price: averagePrice, timestamp: currentCandleTimestamp, pnlCost: pnl.pnlCost, pnlPercentage: pnl.pnlPercentage };
7281
+ const { pnl } = TO_PUBLIC_SIGNAL("pending", signal, averagePrice);
7282
+ signal._fall = { price: averagePrice, timestamp: currentCandleTimestamp, pnlCost: pnl.pnlCost, pnlPercentage: pnl.pnlPercentage, pnlEntries: pnl.pnlEntries, priceOpen: pnl.priceOpen, priceClose: pnl.priceClose };
7228
7283
  if (self.params.callbacks?.onWrite) {
7229
7284
  self.params.callbacks.onWrite(signal.symbol, signal, true);
7230
7285
  }
7231
- await self.params.onMaxDrawdown(TO_PUBLIC_SIGNAL(signal, averagePrice), averagePrice, currentCandleTimestamp);
7286
+ await self.params.onMaxDrawdown(TO_PUBLIC_SIGNAL("pending", signal, averagePrice), averagePrice, currentCandleTimestamp);
7232
7287
  }
7288
+ await CALL_ACTIVE_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentCandleTimestamp, true, averagePrice);
7233
7289
  await CALL_PARTIAL_LOSS_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, averagePrice, Math.min(progressPercent, 100), currentCandleTimestamp, self.params.execution.context.backtest);
7234
7290
  }
7291
+ else {
7292
+ await CALL_ACTIVE_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentCandleTimestamp, true, averagePrice);
7293
+ }
7235
7294
  }
7236
7295
  else if (signal.position === "short") {
7237
7296
  // For short: calculate progress towards TP or SL
7238
7297
  const currentDistance = effectivePriceOpen - averagePrice;
7239
- if (currentDistance > 0) {
7240
- // Check if breakeven should be triggered
7241
- await CALL_BREAKEVEN_CHECK_FN(self, self.params.execution.context.symbol, signal, averagePrice, currentCandleTimestamp, self.params.execution.context.backtest);
7242
- }
7243
7298
  if (currentDistance > 0) {
7244
7299
  // Moving towards TP (use trailing TP if set)
7245
7300
  const effectiveTakeProfit = signal._trailingPriceTakeProfit ?? signal.priceTakeProfit;
7246
7301
  const tpDistance = effectivePriceOpen - effectiveTakeProfit;
7247
7302
  const progressPercent = (currentDistance / tpDistance) * 100;
7248
7303
  if (averagePrice < signal._peak.price) {
7249
- const { pnl } = TO_PUBLIC_SIGNAL(signal, averagePrice);
7250
- signal._peak = { price: averagePrice, timestamp: currentCandleTimestamp, pnlCost: pnl.pnlCost, pnlPercentage: pnl.pnlPercentage };
7304
+ const { pnl } = TO_PUBLIC_SIGNAL("pending", signal, averagePrice);
7305
+ signal._peak = { price: averagePrice, timestamp: currentCandleTimestamp, pnlCost: pnl.pnlCost, pnlPercentage: pnl.pnlPercentage, pnlEntries: pnl.pnlEntries, priceOpen: pnl.priceOpen, priceClose: pnl.priceClose };
7251
7306
  if (self.params.callbacks?.onWrite) {
7252
7307
  self.params.callbacks.onWrite(signal.symbol, signal, true);
7253
7308
  }
7254
- await self.params.onHighestProfit(TO_PUBLIC_SIGNAL(signal, averagePrice), averagePrice, currentCandleTimestamp);
7309
+ await self.params.onHighestProfit(TO_PUBLIC_SIGNAL("pending", signal, averagePrice), averagePrice, currentCandleTimestamp);
7255
7310
  }
7311
+ await CALL_ACTIVE_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentCandleTimestamp, true, averagePrice);
7312
+ await CALL_BREAKEVEN_CHECK_FN(self, self.params.execution.context.symbol, signal, averagePrice, currentCandleTimestamp, self.params.execution.context.backtest);
7256
7313
  await CALL_PARTIAL_PROFIT_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, averagePrice, Math.min(progressPercent, 100), currentCandleTimestamp, self.params.execution.context.backtest);
7257
7314
  }
7258
- if (currentDistance < 0) {
7315
+ else if (currentDistance < 0) {
7259
7316
  // Moving towards SL (use trailing SL if set)
7260
7317
  const effectiveStopLoss = signal._trailingPriceStopLoss ?? signal.priceStopLoss;
7261
7318
  const slDistance = effectiveStopLoss - effectivePriceOpen;
7262
7319
  const progressPercent = (Math.abs(currentDistance) / slDistance) * 100;
7263
7320
  if (averagePrice > signal._fall.price) {
7264
- const { pnl } = TO_PUBLIC_SIGNAL(signal, averagePrice);
7265
- signal._fall = { price: averagePrice, timestamp: currentCandleTimestamp, pnlCost: pnl.pnlCost, pnlPercentage: pnl.pnlPercentage };
7321
+ const { pnl } = TO_PUBLIC_SIGNAL("pending", signal, averagePrice);
7322
+ signal._fall = { price: averagePrice, timestamp: currentCandleTimestamp, pnlCost: pnl.pnlCost, pnlPercentage: pnl.pnlPercentage, pnlEntries: pnl.pnlEntries, priceOpen: pnl.priceOpen, priceClose: pnl.priceClose };
7266
7323
  if (self.params.callbacks?.onWrite) {
7267
7324
  self.params.callbacks.onWrite(signal.symbol, signal, true);
7268
7325
  }
7269
- await self.params.onMaxDrawdown(TO_PUBLIC_SIGNAL(signal, averagePrice), averagePrice, currentCandleTimestamp);
7326
+ await self.params.onMaxDrawdown(TO_PUBLIC_SIGNAL("pending", signal, averagePrice), averagePrice, currentCandleTimestamp);
7270
7327
  }
7328
+ await CALL_ACTIVE_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentCandleTimestamp, true, averagePrice);
7271
7329
  await CALL_PARTIAL_LOSS_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, averagePrice, Math.min(progressPercent, 100), currentCandleTimestamp, self.params.execution.context.backtest);
7272
7330
  }
7331
+ else {
7332
+ await CALL_ACTIVE_PING_CALLBACKS_FN(self, self.params.execution.context.symbol, signal, currentCandleTimestamp, true, averagePrice);
7333
+ }
7273
7334
  }
7274
7335
  }
7275
7336
  // Process queued commit events with candle timestamp
@@ -7280,9 +7341,10 @@ const PROCESS_PENDING_SIGNAL_CANDLES_FN = async (self, signal, candles, frameEnd
7280
7341
  const lastPrice = GET_AVG_PRICE_FN(lastCandles);
7281
7342
  const closeTimestamp = lastCandles[lastCandles.length - 1].timestamp;
7282
7343
  if (signal.minuteEstimatedTime === Infinity) {
7344
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", signal, lastPrice);
7283
7345
  const result = {
7284
7346
  action: "active",
7285
- signal: TO_PUBLIC_SIGNAL(signal, lastPrice),
7347
+ signal: publicSignal,
7286
7348
  currentPrice: lastPrice,
7287
7349
  strategyName: self.params.method.context.strategyName,
7288
7350
  exchangeName: self.params.method.context.exchangeName,
@@ -7290,7 +7352,7 @@ const PROCESS_PENDING_SIGNAL_CANDLES_FN = async (self, signal, candles, frameEnd
7290
7352
  symbol: self.params.execution.context.symbol,
7291
7353
  percentTp: 0,
7292
7354
  percentSl: 0,
7293
- pnl: toProfitLossDto(signal, lastPrice),
7355
+ pnl: publicSignal.pnl,
7294
7356
  backtest: self.params.execution.context.backtest,
7295
7357
  createdAt: closeTimestamp,
7296
7358
  _backtestLastTimestamp: closeTimestamp,
@@ -7473,7 +7535,7 @@ class ClientStrategy {
7473
7535
  this.params.logger.debug("ClientStrategy getPendingSignal", {
7474
7536
  symbol,
7475
7537
  });
7476
- return this._pendingSignal ? TO_PUBLIC_SIGNAL(this._pendingSignal, currentPrice) : null;
7538
+ return this._pendingSignal ? TO_PUBLIC_SIGNAL("pending", this._pendingSignal, currentPrice) : null;
7477
7539
  }
7478
7540
  /**
7479
7541
  * Retrieves the current scheduled signal.
@@ -7484,7 +7546,7 @@ class ClientStrategy {
7484
7546
  this.params.logger.debug("ClientStrategy getScheduledSignal", {
7485
7547
  symbol,
7486
7548
  });
7487
- return this._scheduledSignal ? TO_PUBLIC_SIGNAL(this._scheduledSignal, currentPrice) : null;
7549
+ return this._scheduledSignal ? TO_PUBLIC_SIGNAL("scheduled", this._scheduledSignal, currentPrice) : null;
7488
7550
  }
7489
7551
  /**
7490
7552
  * Checks if breakeven threshold has been reached for the current pending signal.
@@ -8293,6 +8355,7 @@ class ClientStrategy {
8293
8355
  signalId: cancelledSignal.id,
8294
8356
  });
8295
8357
  // Emit commit with correct timestamp from tick context
8358
+ const publicSignal = TO_PUBLIC_SIGNAL("scheduled", cancelledSignal, currentPrice);
8296
8359
  await CALL_COMMIT_FN(this, {
8297
8360
  action: "cancel-scheduled",
8298
8361
  symbol: this.params.execution.context.symbol,
@@ -8306,14 +8369,17 @@ class ClientStrategy {
8306
8369
  totalEntries: cancelledSignal._entry?.length ?? 1,
8307
8370
  totalPartials: cancelledSignal._partial?.length ?? 0,
8308
8371
  originalPriceOpen: cancelledSignal.priceOpen,
8309
- pnl: toProfitLossDto(cancelledSignal, currentPrice),
8372
+ pnl: publicSignal.pnl,
8373
+ maxDrawdown: publicSignal.maxDrawdown,
8374
+ peakProfit: publicSignal.peakProfit,
8375
+ signal: publicSignal,
8310
8376
  note: cancelledSignal.cancelNote ?? cancelledSignal.note,
8311
8377
  });
8312
8378
  // Call onCancel callback
8313
8379
  await CALL_CANCEL_CALLBACKS_FN(this, this.params.execution.context.symbol, cancelledSignal, currentPrice, currentTime, this.params.execution.context.backtest);
8314
8380
  const result = {
8315
8381
  action: "cancelled",
8316
- signal: TO_PUBLIC_SIGNAL(cancelledSignal, currentPrice),
8382
+ signal: publicSignal,
8317
8383
  currentPrice,
8318
8384
  closeTimestamp: currentTime,
8319
8385
  strategyName: this.params.method.context.strategyName,
@@ -8347,6 +8413,7 @@ class ClientStrategy {
8347
8413
  signalId: closedSignal.id,
8348
8414
  });
8349
8415
  // Emit commit with correct timestamp from tick context
8416
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", closedSignal, currentPrice);
8350
8417
  await CALL_COMMIT_FN(this, {
8351
8418
  action: "close-pending",
8352
8419
  symbol: this.params.execution.context.symbol,
@@ -8360,7 +8427,10 @@ class ClientStrategy {
8360
8427
  totalEntries: closedSignal._entry?.length ?? 1,
8361
8428
  totalPartials: closedSignal._partial?.length ?? 0,
8362
8429
  originalPriceOpen: closedSignal.priceOpen,
8363
- pnl: toProfitLossDto(closedSignal, currentPrice),
8430
+ pnl: publicSignal.pnl,
8431
+ maxDrawdown: publicSignal.maxDrawdown,
8432
+ peakProfit: publicSignal.peakProfit,
8433
+ signal: publicSignal,
8364
8434
  note: closedSignal.closeNote ?? closedSignal.note,
8365
8435
  });
8366
8436
  // Call onClose callback
@@ -8370,14 +8440,13 @@ class ClientStrategy {
8370
8440
  // КРИТИЧНО: Очищаем состояние ClientBreakeven при закрытии позиции
8371
8441
  await CALL_BREAKEVEN_CLEAR_FN(this, this.params.execution.context.symbol, closedSignal, currentPrice, currentTime, this.params.execution.context.backtest);
8372
8442
  await CALL_RISK_REMOVE_SIGNAL_FN(this, this.params.execution.context.symbol, currentTime, this.params.execution.context.backtest);
8373
- const pnl = toProfitLossDto(closedSignal, currentPrice);
8374
8443
  const result = {
8375
8444
  action: "closed",
8376
- signal: TO_PUBLIC_SIGNAL(closedSignal, currentPrice),
8445
+ signal: publicSignal,
8377
8446
  currentPrice,
8378
8447
  closeReason: "closed",
8379
8448
  closeTimestamp: currentTime,
8380
- pnl,
8449
+ pnl: publicSignal.pnl,
8381
8450
  strategyName: this.params.method.context.strategyName,
8382
8451
  exchangeName: this.params.method.context.exchangeName,
8383
8452
  frameName: this.params.method.context.frameName,
@@ -8420,8 +8489,8 @@ class ClientStrategy {
8420
8489
  ...activatedSignal,
8421
8490
  pendingAt: currentTime,
8422
8491
  _isScheduled: false,
8423
- _peak: { price: activatedSignal.priceOpen, timestamp: currentTime, pnlPercentage: 0, pnlCost: 0 },
8424
- _fall: { price: activatedSignal.priceOpen, timestamp: currentTime, pnlPercentage: 0, pnlCost: 0 },
8492
+ _peak: { price: activatedSignal.priceOpen, timestamp: currentTime, pnlPercentage: 0, pnlCost: 0, priceClose: 0, pnlEntries: 0, priceOpen: 0 },
8493
+ _fall: { price: activatedSignal.priceOpen, timestamp: currentTime, pnlPercentage: 0, pnlCost: 0, priceClose: 0, pnlEntries: 0, priceOpen: 0 },
8425
8494
  };
8426
8495
  const syncOpenAllowed = await CALL_SIGNAL_SYNC_OPEN_FN(currentTime, currentPrice, pendingSignal, this);
8427
8496
  if (!syncOpenAllowed) {
@@ -8430,6 +8499,7 @@ class ClientStrategy {
8430
8499
  signalId: activatedSignal.id,
8431
8500
  });
8432
8501
  await this.setScheduledSignal(null);
8502
+ const publicSignal = TO_PUBLIC_SIGNAL("scheduled", activatedSignal, currentPrice);
8433
8503
  await CALL_COMMIT_FN(this, {
8434
8504
  action: "cancel-scheduled",
8435
8505
  symbol: this.params.execution.context.symbol,
@@ -8442,7 +8512,10 @@ class ClientStrategy {
8442
8512
  totalEntries: activatedSignal._entry?.length ?? 1,
8443
8513
  totalPartials: activatedSignal._partial?.length ?? 0,
8444
8514
  originalPriceOpen: activatedSignal.priceOpen,
8445
- pnl: toProfitLossDto(activatedSignal, currentPrice),
8515
+ pnl: publicSignal.pnl,
8516
+ maxDrawdown: publicSignal.maxDrawdown,
8517
+ peakProfit: publicSignal.peakProfit,
8518
+ signal: publicSignal,
8446
8519
  note: activatedSignal.activateNote ?? activatedSignal.note,
8447
8520
  });
8448
8521
  return await RETURN_IDLE_FN(this, currentPrice);
@@ -8450,7 +8523,7 @@ class ClientStrategy {
8450
8523
  await this.setPendingSignal(pendingSignal);
8451
8524
  await CALL_RISK_ADD_SIGNAL_FN(this, this.params.execution.context.symbol, pendingSignal, currentTime, this.params.execution.context.backtest);
8452
8525
  // Emit commit AFTER successful risk check
8453
- const publicSignalForCommit = TO_PUBLIC_SIGNAL(pendingSignal, currentPrice);
8526
+ const publicSignalForCommit = TO_PUBLIC_SIGNAL("pending", pendingSignal, currentPrice);
8454
8527
  await CALL_COMMIT_FN(this, {
8455
8528
  action: "activate-scheduled",
8456
8529
  symbol: this.params.execution.context.symbol,
@@ -8462,7 +8535,10 @@ class ClientStrategy {
8462
8535
  activateId: activatedSignal.activateId,
8463
8536
  timestamp: currentTime,
8464
8537
  currentPrice,
8465
- pnl: toProfitLossDto(pendingSignal, currentPrice),
8538
+ pnl: publicSignalForCommit.pnl,
8539
+ maxDrawdown: publicSignalForCommit.maxDrawdown,
8540
+ peakProfit: publicSignalForCommit.peakProfit,
8541
+ signal: publicSignalForCommit,
8466
8542
  position: publicSignalForCommit.position,
8467
8543
  priceOpen: publicSignalForCommit.priceOpen,
8468
8544
  priceTakeProfit: publicSignalForCommit.priceTakeProfit,
@@ -8480,7 +8556,7 @@ class ClientStrategy {
8480
8556
  await CALL_OPEN_CALLBACKS_FN(this, this.params.execution.context.symbol, pendingSignal, currentPrice, currentTime, this.params.execution.context.backtest);
8481
8557
  const result = {
8482
8558
  action: "opened",
8483
- signal: TO_PUBLIC_SIGNAL(pendingSignal, currentPrice),
8559
+ signal: publicSignalForCommit,
8484
8560
  strategyName: this.params.method.context.strategyName,
8485
8561
  exchangeName: this.params.method.context.exchangeName,
8486
8562
  frameName: this.params.method.context.frameName,
@@ -8596,6 +8672,7 @@ class ClientStrategy {
8596
8672
  this._cancelledSignal = null; // Clear after using
8597
8673
  const closeTimestamp = this.params.execution.context.when.getTime();
8598
8674
  // Emit commit with correct timestamp from backtest context
8675
+ const publicSignal = TO_PUBLIC_SIGNAL("scheduled", cancelledSignal, currentPrice);
8599
8676
  await CALL_COMMIT_FN(this, {
8600
8677
  action: "cancel-scheduled",
8601
8678
  symbol: this.params.execution.context.symbol,
@@ -8609,13 +8686,16 @@ class ClientStrategy {
8609
8686
  totalEntries: cancelledSignal._entry?.length ?? 1,
8610
8687
  totalPartials: cancelledSignal._partial?.length ?? 0,
8611
8688
  originalPriceOpen: cancelledSignal.priceOpen,
8612
- pnl: toProfitLossDto(cancelledSignal, currentPrice),
8689
+ pnl: publicSignal.pnl,
8690
+ maxDrawdown: publicSignal.maxDrawdown,
8691
+ peakProfit: publicSignal.peakProfit,
8692
+ signal: publicSignal,
8613
8693
  note: cancelledSignal.cancelNote ?? cancelledSignal.note,
8614
8694
  });
8615
8695
  await CALL_CANCEL_CALLBACKS_FN(this, this.params.execution.context.symbol, cancelledSignal, currentPrice, closeTimestamp, this.params.execution.context.backtest);
8616
8696
  const cancelledResult = {
8617
8697
  action: "cancelled",
8618
- signal: TO_PUBLIC_SIGNAL(cancelledSignal, currentPrice),
8698
+ signal: publicSignal,
8619
8699
  currentPrice,
8620
8700
  closeTimestamp: closeTimestamp,
8621
8701
  strategyName: this.params.method.context.strategyName,
@@ -8651,6 +8731,7 @@ class ClientStrategy {
8651
8731
  }
8652
8732
  this._closedSignal = null; // Clear only after sync confirmed
8653
8733
  // Emit commit with correct timestamp from backtest context
8734
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", closedSignal, currentPrice);
8654
8735
  await CALL_COMMIT_FN(this, {
8655
8736
  action: "close-pending",
8656
8737
  symbol: this.params.execution.context.symbol,
@@ -8664,7 +8745,10 @@ class ClientStrategy {
8664
8745
  totalEntries: closedSignal._entry?.length ?? 1,
8665
8746
  totalPartials: closedSignal._partial?.length ?? 0,
8666
8747
  originalPriceOpen: closedSignal.priceOpen,
8667
- pnl: toProfitLossDto(closedSignal, currentPrice),
8748
+ pnl: publicSignal.pnl,
8749
+ maxDrawdown: publicSignal.maxDrawdown,
8750
+ peakProfit: publicSignal.peakProfit,
8751
+ signal: publicSignal,
8668
8752
  note: closedSignal.closeNote ?? closedSignal.note,
8669
8753
  });
8670
8754
  await CALL_CLOSE_CALLBACKS_FN(this, this.params.execution.context.symbol, closedSignal, currentPrice, closeTimestamp, this.params.execution.context.backtest);
@@ -8673,14 +8757,13 @@ class ClientStrategy {
8673
8757
  // КРИТИЧНО: Очищаем состояние ClientBreakeven при закрытии позиции
8674
8758
  await CALL_BREAKEVEN_CLEAR_FN(this, this.params.execution.context.symbol, closedSignal, currentPrice, closeTimestamp, this.params.execution.context.backtest);
8675
8759
  await CALL_RISK_REMOVE_SIGNAL_FN(this, this.params.execution.context.symbol, closeTimestamp, this.params.execution.context.backtest);
8676
- const pnl = toProfitLossDto(closedSignal, currentPrice);
8677
8760
  const closedResult = {
8678
8761
  action: "closed",
8679
- signal: TO_PUBLIC_SIGNAL(closedSignal, currentPrice),
8762
+ signal: publicSignal,
8680
8763
  currentPrice,
8681
8764
  closeReason: "closed",
8682
8765
  closeTimestamp: closeTimestamp,
8683
- pnl,
8766
+ pnl: publicSignal.pnl,
8684
8767
  strategyName: this.params.method.context.strategyName,
8685
8768
  exchangeName: this.params.method.context.exchangeName,
8686
8769
  frameName: this.params.method.context.frameName,
@@ -9136,7 +9219,7 @@ class ClientStrategy {
9136
9219
  });
9137
9220
  // Call onWrite callback for testing persist storage
9138
9221
  if (this.params.callbacks?.onWrite) {
9139
- this.params.callbacks.onWrite(this.params.execution.context.symbol, TO_PUBLIC_SIGNAL(this._pendingSignal, currentPrice), backtest);
9222
+ this.params.callbacks.onWrite(this.params.execution.context.symbol, TO_PUBLIC_SIGNAL("pending", this._pendingSignal, currentPrice), backtest);
9140
9223
  }
9141
9224
  if (!backtest) {
9142
9225
  await PersistSignalAdapter.writeSignalData(this._pendingSignal, this.params.execution.context.symbol, this.params.strategyName, this.params.exchangeName);
@@ -9319,7 +9402,7 @@ class ClientStrategy {
9319
9402
  });
9320
9403
  // Call onWrite callback for testing persist storage
9321
9404
  if (this.params.callbacks?.onWrite) {
9322
- this.params.callbacks.onWrite(this.params.execution.context.symbol, TO_PUBLIC_SIGNAL(this._pendingSignal, currentPrice), backtest);
9405
+ this.params.callbacks.onWrite(this.params.execution.context.symbol, TO_PUBLIC_SIGNAL("pending", this._pendingSignal, currentPrice), backtest);
9323
9406
  }
9324
9407
  if (!backtest) {
9325
9408
  await PersistSignalAdapter.writeSignalData(this._pendingSignal, this.params.execution.context.symbol, this.params.strategyName, this.params.exchangeName);
@@ -9517,7 +9600,7 @@ class ClientStrategy {
9517
9600
  });
9518
9601
  // Call onWrite callback for testing persist storage
9519
9602
  if (this.params.callbacks?.onWrite) {
9520
- const publicSignal = TO_PUBLIC_SIGNAL(this._pendingSignal, currentPrice);
9603
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", this._pendingSignal, currentPrice);
9521
9604
  this.params.callbacks.onWrite(this.params.execution.context.symbol, publicSignal, backtest);
9522
9605
  }
9523
9606
  if (!backtest) {
@@ -9766,7 +9849,7 @@ class ClientStrategy {
9766
9849
  });
9767
9850
  // Call onWrite callback for testing persist storage
9768
9851
  if (this.params.callbacks?.onWrite) {
9769
- const publicSignal = TO_PUBLIC_SIGNAL(this._pendingSignal, currentPrice);
9852
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", this._pendingSignal, currentPrice);
9770
9853
  this.params.callbacks.onWrite(this.params.execution.context.symbol, publicSignal, backtest);
9771
9854
  }
9772
9855
  if (!backtest) {
@@ -10002,7 +10085,7 @@ class ClientStrategy {
10002
10085
  });
10003
10086
  // Call onWrite callback for testing persist storage
10004
10087
  if (this.params.callbacks?.onWrite) {
10005
- const publicSignal = TO_PUBLIC_SIGNAL(this._pendingSignal, currentPrice);
10088
+ const publicSignal = TO_PUBLIC_SIGNAL("pending", this._pendingSignal, currentPrice);
10006
10089
  this.params.callbacks.onWrite(this.params.execution.context.symbol, publicSignal, backtest);
10007
10090
  }
10008
10091
  if (!backtest) {
@@ -10094,7 +10177,7 @@ class ClientStrategy {
10094
10177
  });
10095
10178
  // Call onWrite callback for testing persist storage
10096
10179
  if (this.params.callbacks?.onWrite) {
10097
- this.params.callbacks.onWrite(this.params.execution.context.symbol, TO_PUBLIC_SIGNAL(this._pendingSignal, currentPrice), backtest);
10180
+ this.params.callbacks.onWrite(this.params.execution.context.symbol, TO_PUBLIC_SIGNAL("pending", this._pendingSignal, currentPrice), backtest);
10098
10181
  }
10099
10182
  if (!backtest) {
10100
10183
  await PersistSignalAdapter.writeSignalData(this._pendingSignal, this.params.execution.context.symbol, this.params.strategyName, this.params.exchangeName);
@@ -12465,12 +12548,15 @@ const alignToInterval = (date, interval) => {
12465
12548
 
12466
12549
  /** Symbol indicating that positions need to be fetched from persistence */
12467
12550
  const POSITION_NEED_FETCH = Symbol("risk-need-fetch");
12551
+ /** Get timestamp from execution context or fallback to aligned current time */
12468
12552
  const GET_CONTEXT_TIMESTAMP_FN = (self) => {
12469
12553
  if (ExecutionContextService.hasContext()) {
12470
12554
  return self.params.execution.context.when.getTime();
12471
12555
  }
12472
12556
  return alignToInterval(new Date(), "1m").getTime();
12473
12557
  };
12558
+ /** Zero PNL constant for scheduled signals (which don't have priceOpen or PNL yet) */
12559
+ const ZERO_PNL = { pnlPercentage: 0, priceOpen: 0, priceClose: 0, pnlCost: 0, pnlEntries: 0 };
12474
12560
  /**
12475
12561
  * Converts signal to risk validation format.
12476
12562
  *
@@ -12513,6 +12599,9 @@ const TO_RISK_SIGNAL = (signal, currentPrice, timestamp) => {
12513
12599
  const partialExecuted = ("_partial" in signal && Array.isArray(signal._partial))
12514
12600
  ? signal._partial.reduce((sum, partial) => sum + partial.percent, 0)
12515
12601
  : 0;
12602
+ const pnl = signal._isScheduled ? ZERO_PNL : toProfitLossDto(signal, currentPrice);
12603
+ const maxDrawdown = signal._isScheduled ? ZERO_PNL : pnl;
12604
+ const peakProfit = signal._isScheduled ? ZERO_PNL : pnl;
12516
12605
  return {
12517
12606
  ...structuredClone(signal),
12518
12607
  cost: signal.cost || GLOBAL_CONFIG.CC_POSITION_ENTRY_COST,
@@ -12526,7 +12615,9 @@ const TO_RISK_SIGNAL = (signal, currentPrice, timestamp) => {
12526
12615
  originalPriceTakeProfit: signal.priceTakeProfit,
12527
12616
  originalPriceOpen: signal.priceOpen ?? currentPrice,
12528
12617
  partialExecuted,
12529
- pnl: toProfitLossDto(signal, currentPrice),
12618
+ pnl,
12619
+ maxDrawdown,
12620
+ peakProfit,
12530
12621
  };
12531
12622
  };
12532
12623
  /** Key generator for active position map */
@@ -18796,7 +18887,9 @@ const backtest_columns = [
18796
18887
  key: "peakPnl",
18797
18888
  label: "Peak PNL",
18798
18889
  format: (data) => {
18799
- const v = data.signal._peak?.pnlPercentage;
18890
+ const v = data.signal.peakProfit?.pnlPercentage;
18891
+ if (v === undefined)
18892
+ return "N/A";
18800
18893
  return `${v > 0 ? "+" : ""}${v.toFixed(2)}%`;
18801
18894
  },
18802
18895
  isVisible: () => true,
@@ -18804,7 +18897,12 @@ const backtest_columns = [
18804
18897
  {
18805
18898
  key: "fallPnl",
18806
18899
  label: "Max DD PNL",
18807
- format: (data) => `${data.signal._fall?.pnlPercentage.toFixed(2)}%`,
18900
+ format: (data) => {
18901
+ const v = data.signal.maxDrawdown?.pnlPercentage;
18902
+ if (v === undefined)
18903
+ return "N/A";
18904
+ return `${v.toFixed(2)}%`;
18905
+ },
18808
18906
  isVisible: () => true,
18809
18907
  },
18810
18908
  ];
@@ -21365,8 +21463,8 @@ let ReportStorage$a = class ReportStorage {
21365
21463
  const tradesPerYear = avgDurationDays > 0 ? 365 / avgDurationDays : 0;
21366
21464
  const expectedYearlyReturns = avgPnl * tradesPerYear;
21367
21465
  // Calculate average peak and fall PNL across all signals
21368
- const avgPeakPnl = this._signalList.reduce((sum, s) => sum + (s.signal._peak?.pnlPercentage ?? 0), 0) / totalSignals;
21369
- const avgFallPnl = this._signalList.reduce((sum, s) => sum + (s.signal._fall?.pnlPercentage ?? 0), 0) / totalSignals;
21466
+ const avgPeakPnl = this._signalList.reduce((sum, s) => sum + (s.signal.peakProfit?.pnlPercentage ?? 0), 0) / totalSignals;
21467
+ const avgFallPnl = this._signalList.reduce((sum, s) => sum + (s.signal.maxDrawdown?.pnlPercentage ?? 0), 0) / totalSignals;
21370
21468
  return {
21371
21469
  signalList: this._signalList,
21372
21470
  totalSignals,
@@ -21895,8 +21993,8 @@ let ReportStorage$9 = class ReportStorage {
21895
21993
  duration: durationMin,
21896
21994
  pendingAt: data.signal.pendingAt,
21897
21995
  scheduledAt: data.signal.scheduledAt,
21898
- peakPnl: data.signal._peak?.pnlPercentage,
21899
- fallPnl: data.signal._fall?.pnlPercentage,
21996
+ peakPnl: data.signal.peakProfit?.pnlPercentage,
21997
+ fallPnl: data.signal.maxDrawdown?.pnlPercentage,
21900
21998
  };
21901
21999
  this._eventList.unshift(newEvent);
21902
22000
  // Trim queue if exceeded GLOBAL_CONFIG.CC_MAX_LIVE_MARKDOWN_ROWS
@@ -24047,8 +24145,8 @@ class HeatmapStorage {
24047
24145
  let avgPeakPnl = null;
24048
24146
  let avgFallPnl = null;
24049
24147
  if (signals.length > 0) {
24050
- avgPeakPnl = signals.reduce((acc, s) => acc + (s.signal._peak?.pnlPercentage ?? 0), 0) / signals.length;
24051
- avgFallPnl = signals.reduce((acc, s) => acc + (s.signal._fall?.pnlPercentage ?? 0), 0) / signals.length;
24148
+ avgPeakPnl = signals.reduce((acc, s) => acc + (s.signal.peakProfit?.pnlPercentage ?? 0), 0) / signals.length;
24149
+ avgFallPnl = signals.reduce((acc, s) => acc + (s.signal.maxDrawdown?.pnlPercentage ?? 0), 0) / signals.length;
24052
24150
  }
24053
24151
  // Apply safe math checks
24054
24152
  if (isUnsafe(winRate))
@@ -28175,8 +28273,16 @@ class BacktestReportService {
28175
28273
  pnlPriceClose: data.pnl.priceClose,
28176
28274
  totalPartials: data.signal?.totalPartials,
28177
28275
  cost: data.signal?.cost,
28178
- peakPnl: data.signal?._peak?.pnlPercentage,
28179
- fallPnl: data.signal?._fall?.pnlPercentage,
28276
+ peakProfitPriceOpen: data.signal?.peakProfit?.priceOpen,
28277
+ peakProfitPriceClose: data.signal?.peakProfit?.priceClose,
28278
+ peakProfitPercentage: data.signal?.peakProfit?.pnlPercentage,
28279
+ peakProfitCost: data.signal?.peakProfit?.pnlCost,
28280
+ peakProfitEntries: data.signal?.peakProfit?.pnlEntries,
28281
+ maxDrawdownPriceOpen: data.signal?.maxDrawdown?.priceOpen,
28282
+ maxDrawdownPriceClose: data.signal?.maxDrawdown?.priceClose,
28283
+ maxDrawdownPercentage: data.signal?.maxDrawdown?.pnlPercentage,
28284
+ maxDrawdownCost: data.signal?.maxDrawdown?.pnlCost,
28285
+ maxDrawdownEntries: data.signal?.maxDrawdown?.pnlEntries,
28180
28286
  }, { ...searchOptions, signalId: data.signal?.id });
28181
28287
  }
28182
28288
  else if (data.action === "closed") {
@@ -28209,8 +28315,16 @@ class BacktestReportService {
28209
28315
  closeReason: data.closeReason,
28210
28316
  closeTime: data.closeTimestamp,
28211
28317
  duration: durationMin,
28212
- peakPnl: data.signal?._peak?.pnlPercentage,
28213
- fallPnl: data.signal?._fall?.pnlPercentage,
28318
+ peakProfitPriceOpen: data.signal?.peakProfit?.priceOpen,
28319
+ peakProfitPriceClose: data.signal?.peakProfit?.priceClose,
28320
+ peakProfitPercentage: data.signal?.peakProfit?.pnlPercentage,
28321
+ peakProfitCost: data.signal?.peakProfit?.pnlCost,
28322
+ peakProfitEntries: data.signal?.peakProfit?.pnlEntries,
28323
+ maxDrawdownPriceOpen: data.signal?.maxDrawdown?.priceOpen,
28324
+ maxDrawdownPriceClose: data.signal?.maxDrawdown?.priceClose,
28325
+ maxDrawdownPercentage: data.signal?.maxDrawdown?.pnlPercentage,
28326
+ maxDrawdownCost: data.signal?.maxDrawdown?.pnlCost,
28327
+ maxDrawdownEntries: data.signal?.maxDrawdown?.pnlEntries,
28214
28328
  }, { ...searchOptions, signalId: data.signal?.id });
28215
28329
  }
28216
28330
  };
@@ -28373,8 +28487,16 @@ class LiveReportService {
28373
28487
  pnlPriceClose: data.pnl.priceClose,
28374
28488
  totalPartials: data.signal?.totalPartials,
28375
28489
  cost: data.signal?.cost,
28376
- peakPnl: data.signal?._peak?.pnlPercentage,
28377
- fallPnl: data.signal?._fall?.pnlPercentage,
28490
+ peakProfitPriceOpen: data.signal?.peakProfit?.priceOpen,
28491
+ peakProfitPriceClose: data.signal?.peakProfit?.priceClose,
28492
+ peakProfitPercentage: data.signal?.peakProfit?.pnlPercentage,
28493
+ peakProfitCost: data.signal?.peakProfit?.pnlCost,
28494
+ peakProfitEntries: data.signal?.peakProfit?.pnlEntries,
28495
+ maxDrawdownPriceOpen: data.signal?.maxDrawdown?.priceOpen,
28496
+ maxDrawdownPriceClose: data.signal?.maxDrawdown?.priceClose,
28497
+ maxDrawdownPercentage: data.signal?.maxDrawdown?.pnlPercentage,
28498
+ maxDrawdownCost: data.signal?.maxDrawdown?.pnlCost,
28499
+ maxDrawdownEntries: data.signal?.maxDrawdown?.pnlEntries,
28378
28500
  }, { ...searchOptions, signalId: data.signal?.id });
28379
28501
  }
28380
28502
  else if (data.action === "opened") {
@@ -28425,8 +28547,16 @@ class LiveReportService {
28425
28547
  pnlPriceClose: data.pnl.priceClose,
28426
28548
  totalPartials: data.signal?.totalPartials,
28427
28549
  cost: data.signal?.cost,
28428
- peakPnl: data.signal?._peak?.pnlPercentage,
28429
- fallPnl: data.signal?._fall?.pnlPercentage,
28550
+ peakProfitPriceOpen: data.signal?.peakProfit?.priceOpen,
28551
+ peakProfitPriceClose: data.signal?.peakProfit?.priceClose,
28552
+ peakProfitPercentage: data.signal?.peakProfit?.pnlPercentage,
28553
+ peakProfitCost: data.signal?.peakProfit?.pnlCost,
28554
+ peakProfitEntries: data.signal?.peakProfit?.pnlEntries,
28555
+ maxDrawdownPriceOpen: data.signal?.maxDrawdown?.priceOpen,
28556
+ maxDrawdownPriceClose: data.signal?.maxDrawdown?.priceClose,
28557
+ maxDrawdownPercentage: data.signal?.maxDrawdown?.pnlPercentage,
28558
+ maxDrawdownCost: data.signal?.maxDrawdown?.pnlCost,
28559
+ maxDrawdownEntries: data.signal?.maxDrawdown?.pnlEntries,
28430
28560
  }, { ...searchOptions, signalId: data.signal?.id });
28431
28561
  }
28432
28562
  else if (data.action === "closed") {
@@ -28459,8 +28589,16 @@ class LiveReportService {
28459
28589
  closeReason: data.closeReason,
28460
28590
  duration: durationMin,
28461
28591
  closeTime: data.closeTimestamp,
28462
- peakPnl: data.signal?._peak?.pnlPercentage,
28463
- fallPnl: data.signal?._fall?.pnlPercentage,
28592
+ peakProfitPriceOpen: data.signal?.peakProfit?.priceOpen,
28593
+ peakProfitPriceClose: data.signal?.peakProfit?.priceClose,
28594
+ peakProfitPercentage: data.signal?.peakProfit?.pnlPercentage,
28595
+ peakProfitCost: data.signal?.peakProfit?.pnlCost,
28596
+ peakProfitEntries: data.signal?.peakProfit?.pnlEntries,
28597
+ maxDrawdownPriceOpen: data.signal?.maxDrawdown?.priceOpen,
28598
+ maxDrawdownPriceClose: data.signal?.maxDrawdown?.priceClose,
28599
+ maxDrawdownPercentage: data.signal?.maxDrawdown?.pnlPercentage,
28600
+ maxDrawdownCost: data.signal?.maxDrawdown?.pnlCost,
28601
+ maxDrawdownEntries: data.signal?.maxDrawdown?.pnlEntries,
28464
28602
  }, { ...searchOptions, signalId: data.signal?.id });
28465
28603
  }
28466
28604
  else if (data.action === "cancelled") {
@@ -29052,8 +29190,16 @@ class HeatReportService {
29052
29190
  openTime: data.signal?.pendingAt,
29053
29191
  scheduledAt: data.signal?.scheduledAt,
29054
29192
  closeTime: data.closeTimestamp,
29055
- peakPnl: data.signal?._peak?.pnlPercentage,
29056
- fallPnl: data.signal?._fall?.pnlPercentage,
29193
+ peakProfitPriceOpen: data.signal?.peakProfit?.priceOpen,
29194
+ peakProfitPriceClose: data.signal?.peakProfit?.priceClose,
29195
+ peakProfitPercentage: data.signal?.peakProfit?.pnlPercentage,
29196
+ peakProfitCost: data.signal?.peakProfit?.pnlCost,
29197
+ peakProfitEntries: data.signal?.peakProfit?.pnlEntries,
29198
+ maxDrawdownPriceOpen: data.signal?.maxDrawdown?.priceOpen,
29199
+ maxDrawdownPriceClose: data.signal?.maxDrawdown?.priceClose,
29200
+ maxDrawdownPercentage: data.signal?.maxDrawdown?.pnlPercentage,
29201
+ maxDrawdownCost: data.signal?.maxDrawdown?.pnlCost,
29202
+ maxDrawdownEntries: data.signal?.maxDrawdown?.pnlEntries,
29057
29203
  }, {
29058
29204
  symbol: data.symbol,
29059
29205
  strategyName: data.strategyName,
@@ -29187,6 +29333,16 @@ class PartialReportService {
29187
29333
  pnlEntries: data.data.pnl.pnlEntries,
29188
29334
  pnlPriceOpen: data.data.pnl.priceOpen,
29189
29335
  pnlPriceClose: data.data.pnl.priceClose,
29336
+ peakProfitPercentage: data.data.peakProfit.pnlPercentage,
29337
+ peakProfitCost: data.data.peakProfit.pnlCost,
29338
+ peakProfitEntries: data.data.peakProfit.pnlEntries,
29339
+ peakProfitPriceOpen: data.data.peakProfit.priceOpen,
29340
+ peakProfitPriceClose: data.data.peakProfit.priceClose,
29341
+ maxDrawdownPercentage: data.data.maxDrawdown.pnlPercentage,
29342
+ maxDrawdownCost: data.data.maxDrawdown.pnlCost,
29343
+ maxDrawdownEntries: data.data.maxDrawdown.pnlEntries,
29344
+ maxDrawdownPriceOpen: data.data.maxDrawdown.priceOpen,
29345
+ maxDrawdownPriceClose: data.data.maxDrawdown.priceClose,
29190
29346
  }, {
29191
29347
  symbol: data.symbol,
29192
29348
  strategyName: data.data.strategyName,
@@ -29237,6 +29393,16 @@ class PartialReportService {
29237
29393
  pnlEntries: data.data.pnl.pnlEntries,
29238
29394
  pnlPriceOpen: data.data.pnl.priceOpen,
29239
29395
  pnlPriceClose: data.data.pnl.priceClose,
29396
+ peakProfitPercentage: data.data.peakProfit.pnlPercentage,
29397
+ peakProfitCost: data.data.peakProfit.pnlCost,
29398
+ peakProfitEntries: data.data.peakProfit.pnlEntries,
29399
+ peakProfitPriceOpen: data.data.peakProfit.priceOpen,
29400
+ peakProfitPriceClose: data.data.peakProfit.priceClose,
29401
+ maxDrawdownPercentage: data.data.maxDrawdown.pnlPercentage,
29402
+ maxDrawdownCost: data.data.maxDrawdown.pnlCost,
29403
+ maxDrawdownEntries: data.data.maxDrawdown.pnlEntries,
29404
+ maxDrawdownPriceOpen: data.data.maxDrawdown.priceOpen,
29405
+ maxDrawdownPriceClose: data.data.maxDrawdown.priceClose,
29240
29406
  }, {
29241
29407
  symbol: data.symbol,
29242
29408
  strategyName: data.data.strategyName,
@@ -29368,6 +29534,16 @@ class BreakevenReportService {
29368
29534
  pnlEntries: data.data.pnl.pnlEntries,
29369
29535
  pnlPriceOpen: data.data.pnl.priceOpen,
29370
29536
  pnlPriceClose: data.data.pnl.priceClose,
29537
+ peakProfitPercentage: data.data.peakProfit.pnlPercentage,
29538
+ peakProfitCost: data.data.peakProfit.pnlCost,
29539
+ peakProfitEntries: data.data.peakProfit.pnlEntries,
29540
+ peakProfitPriceOpen: data.data.peakProfit.priceOpen,
29541
+ peakProfitPriceClose: data.data.peakProfit.priceClose,
29542
+ maxDrawdownPercentage: data.data.maxDrawdown.pnlPercentage,
29543
+ maxDrawdownCost: data.data.maxDrawdown.pnlCost,
29544
+ maxDrawdownEntries: data.data.maxDrawdown.pnlEntries,
29545
+ maxDrawdownPriceOpen: data.data.maxDrawdown.priceOpen,
29546
+ maxDrawdownPriceClose: data.data.maxDrawdown.priceClose,
29371
29547
  }, {
29372
29548
  symbol: data.symbol,
29373
29549
  strategyName: data.data.strategyName,
@@ -29498,6 +29674,16 @@ class RiskReportService {
29498
29674
  pnlEntries: data.currentSignal?.pnl?.pnlEntries,
29499
29675
  pnlPriceOpen: data.currentSignal?.pnl?.priceOpen,
29500
29676
  pnlPriceClose: data.currentSignal?.pnl?.priceClose,
29677
+ peakProfitPercentage: data.currentSignal?.peakProfit?.pnlPercentage,
29678
+ peakProfitCost: data.currentSignal?.peakProfit?.pnlCost,
29679
+ peakProfitEntries: data.currentSignal?.peakProfit?.pnlEntries,
29680
+ peakProfitPriceOpen: data.currentSignal?.peakProfit?.priceOpen,
29681
+ peakProfitPriceClose: data.currentSignal?.peakProfit?.priceClose,
29682
+ maxDrawdownPercentage: data.currentSignal?.maxDrawdown?.pnlPercentage,
29683
+ maxDrawdownCost: data.currentSignal?.maxDrawdown?.pnlCost,
29684
+ maxDrawdownEntries: data.currentSignal?.maxDrawdown?.pnlEntries,
29685
+ maxDrawdownPriceOpen: data.currentSignal?.maxDrawdown?.priceOpen,
29686
+ maxDrawdownPriceClose: data.currentSignal?.maxDrawdown?.priceClose,
29501
29687
  }, {
29502
29688
  symbol: data.symbol,
29503
29689
  strategyName: data.strategyName,
@@ -29577,7 +29763,7 @@ class StrategyReportService {
29577
29763
  /**
29578
29764
  * Logs a cancel-scheduled event when a scheduled signal is cancelled.
29579
29765
  */
29580
- this.cancelScheduled = async (symbol, isBacktest, context, timestamp, signalId, pnl, totalPartials, cancelId, note) => {
29766
+ this.cancelScheduled = async (symbol, isBacktest, context, timestamp, signalId, pnl, peakProfit, maxDrawdown, totalPartials, cancelId, note) => {
29581
29767
  this.loggerService.log("strategyReportService cancelScheduled", {
29582
29768
  symbol,
29583
29769
  isBacktest,
@@ -29599,6 +29785,16 @@ class StrategyReportService {
29599
29785
  pnlEntries: pnl.pnlEntries,
29600
29786
  pnlPriceOpen: pnl.priceOpen,
29601
29787
  pnlPriceClose: pnl.priceClose,
29788
+ peakProfitPercentage: peakProfit.pnlPercentage,
29789
+ peakProfitCost: peakProfit.pnlCost,
29790
+ peakProfitEntries: peakProfit.pnlEntries,
29791
+ peakProfitPriceOpen: peakProfit.priceOpen,
29792
+ peakProfitPriceClose: peakProfit.priceClose,
29793
+ maxDrawdownPercentage: maxDrawdown.pnlPercentage,
29794
+ maxDrawdownCost: maxDrawdown.pnlCost,
29795
+ maxDrawdownEntries: maxDrawdown.pnlEntries,
29796
+ maxDrawdownPriceOpen: maxDrawdown.priceOpen,
29797
+ maxDrawdownPriceClose: maxDrawdown.priceClose,
29602
29798
  totalPartials,
29603
29799
  }, {
29604
29800
  signalId,
@@ -29612,7 +29808,7 @@ class StrategyReportService {
29612
29808
  /**
29613
29809
  * Logs a close-pending event when a pending signal is closed.
29614
29810
  */
29615
- this.closePending = async (symbol, isBacktest, context, timestamp, signalId, pnl, totalPartials, closeId, note) => {
29811
+ this.closePending = async (symbol, isBacktest, context, timestamp, signalId, pnl, peakProfit, maxDrawdown, totalPartials, closeId, note) => {
29616
29812
  this.loggerService.log("strategyReportService closePending", {
29617
29813
  symbol,
29618
29814
  isBacktest,
@@ -29634,6 +29830,16 @@ class StrategyReportService {
29634
29830
  pnlEntries: pnl.pnlEntries,
29635
29831
  pnlPriceOpen: pnl.priceOpen,
29636
29832
  pnlPriceClose: pnl.priceClose,
29833
+ peakProfitPercentage: peakProfit.pnlPercentage,
29834
+ peakProfitCost: peakProfit.pnlCost,
29835
+ peakProfitEntries: peakProfit.pnlEntries,
29836
+ peakProfitPriceOpen: peakProfit.priceOpen,
29837
+ peakProfitPriceClose: peakProfit.priceClose,
29838
+ maxDrawdownPercentage: maxDrawdown.pnlPercentage,
29839
+ maxDrawdownCost: maxDrawdown.pnlCost,
29840
+ maxDrawdownEntries: maxDrawdown.pnlEntries,
29841
+ maxDrawdownPriceOpen: maxDrawdown.priceOpen,
29842
+ maxDrawdownPriceClose: maxDrawdown.priceClose,
29637
29843
  totalPartials,
29638
29844
  }, {
29639
29845
  signalId,
@@ -29647,7 +29853,7 @@ class StrategyReportService {
29647
29853
  /**
29648
29854
  * Logs a partial-profit event when a portion of the position is closed at profit.
29649
29855
  */
29650
- this.partialProfit = async (symbol, percentToClose, currentPrice, isBacktest, context, timestamp, signalId, pnl, totalPartials, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt, totalEntries, originalPriceOpen) => {
29856
+ this.partialProfit = async (symbol, percentToClose, currentPrice, isBacktest, context, timestamp, signalId, pnl, peakProfit, maxDrawdown, totalPartials, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt, totalEntries, originalPriceOpen) => {
29651
29857
  this.loggerService.log("strategyReportService partialProfit", {
29652
29858
  symbol,
29653
29859
  percentToClose,
@@ -29680,6 +29886,16 @@ class StrategyReportService {
29680
29886
  pnlEntries: pnl.pnlEntries,
29681
29887
  pnlPriceOpen: pnl.priceOpen,
29682
29888
  pnlPriceClose: pnl.priceClose,
29889
+ peakProfitPercentage: peakProfit.pnlPercentage,
29890
+ peakProfitCost: peakProfit.pnlCost,
29891
+ peakProfitEntries: peakProfit.pnlEntries,
29892
+ peakProfitPriceOpen: peakProfit.priceOpen,
29893
+ peakProfitPriceClose: peakProfit.priceClose,
29894
+ maxDrawdownPercentage: maxDrawdown.pnlPercentage,
29895
+ maxDrawdownCost: maxDrawdown.pnlCost,
29896
+ maxDrawdownEntries: maxDrawdown.pnlEntries,
29897
+ maxDrawdownPriceOpen: maxDrawdown.priceOpen,
29898
+ maxDrawdownPriceClose: maxDrawdown.priceClose,
29683
29899
  totalPartials,
29684
29900
  }, {
29685
29901
  signalId,
@@ -29693,7 +29909,7 @@ class StrategyReportService {
29693
29909
  /**
29694
29910
  * Logs a partial-loss event when a portion of the position is closed at loss.
29695
29911
  */
29696
- this.partialLoss = async (symbol, percentToClose, currentPrice, isBacktest, context, timestamp, signalId, pnl, totalPartials, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt, totalEntries, originalPriceOpen) => {
29912
+ this.partialLoss = async (symbol, percentToClose, currentPrice, isBacktest, context, timestamp, signalId, pnl, peakProfit, maxDrawdown, totalPartials, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt, totalEntries, originalPriceOpen) => {
29697
29913
  this.loggerService.log("strategyReportService partialLoss", {
29698
29914
  symbol,
29699
29915
  percentToClose,
@@ -29726,6 +29942,16 @@ class StrategyReportService {
29726
29942
  pnlEntries: pnl.pnlEntries,
29727
29943
  pnlPriceOpen: pnl.priceOpen,
29728
29944
  pnlPriceClose: pnl.priceClose,
29945
+ peakProfitPercentage: peakProfit.pnlPercentage,
29946
+ peakProfitCost: peakProfit.pnlCost,
29947
+ peakProfitEntries: peakProfit.pnlEntries,
29948
+ peakProfitPriceOpen: peakProfit.priceOpen,
29949
+ peakProfitPriceClose: peakProfit.priceClose,
29950
+ maxDrawdownPercentage: maxDrawdown.pnlPercentage,
29951
+ maxDrawdownCost: maxDrawdown.pnlCost,
29952
+ maxDrawdownEntries: maxDrawdown.pnlEntries,
29953
+ maxDrawdownPriceOpen: maxDrawdown.priceOpen,
29954
+ maxDrawdownPriceClose: maxDrawdown.priceClose,
29729
29955
  totalPartials,
29730
29956
  }, {
29731
29957
  signalId,
@@ -29739,7 +29965,7 @@ class StrategyReportService {
29739
29965
  /**
29740
29966
  * Logs a trailing-stop event when the stop-loss is adjusted.
29741
29967
  */
29742
- this.trailingStop = async (symbol, percentShift, currentPrice, isBacktest, context, timestamp, signalId, pnl, totalPartials, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt, totalEntries, originalPriceOpen) => {
29968
+ this.trailingStop = async (symbol, percentShift, currentPrice, isBacktest, context, timestamp, signalId, pnl, peakProfit, maxDrawdown, totalPartials, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt, totalEntries, originalPriceOpen) => {
29743
29969
  this.loggerService.log("strategyReportService trailingStop", {
29744
29970
  symbol,
29745
29971
  percentShift,
@@ -29772,6 +29998,16 @@ class StrategyReportService {
29772
29998
  pnlEntries: pnl.pnlEntries,
29773
29999
  pnlPriceOpen: pnl.priceOpen,
29774
30000
  pnlPriceClose: pnl.priceClose,
30001
+ peakProfitPercentage: peakProfit.pnlPercentage,
30002
+ peakProfitCost: peakProfit.pnlCost,
30003
+ peakProfitEntries: peakProfit.pnlEntries,
30004
+ peakProfitPriceOpen: peakProfit.priceOpen,
30005
+ peakProfitPriceClose: peakProfit.priceClose,
30006
+ maxDrawdownPercentage: maxDrawdown.pnlPercentage,
30007
+ maxDrawdownCost: maxDrawdown.pnlCost,
30008
+ maxDrawdownEntries: maxDrawdown.pnlEntries,
30009
+ maxDrawdownPriceOpen: maxDrawdown.priceOpen,
30010
+ maxDrawdownPriceClose: maxDrawdown.priceClose,
29775
30011
  totalPartials,
29776
30012
  }, {
29777
30013
  signalId,
@@ -29785,7 +30021,7 @@ class StrategyReportService {
29785
30021
  /**
29786
30022
  * Logs a trailing-take event when the take-profit is adjusted.
29787
30023
  */
29788
- this.trailingTake = async (symbol, percentShift, currentPrice, isBacktest, context, timestamp, signalId, pnl, totalPartials, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt, totalEntries, originalPriceOpen) => {
30024
+ this.trailingTake = async (symbol, percentShift, currentPrice, isBacktest, context, timestamp, signalId, pnl, peakProfit, maxDrawdown, totalPartials, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt, totalEntries, originalPriceOpen) => {
29789
30025
  this.loggerService.log("strategyReportService trailingTake", {
29790
30026
  symbol,
29791
30027
  percentShift,
@@ -29818,6 +30054,16 @@ class StrategyReportService {
29818
30054
  pnlEntries: pnl.pnlEntries,
29819
30055
  pnlPriceOpen: pnl.priceOpen,
29820
30056
  pnlPriceClose: pnl.priceClose,
30057
+ peakProfitPercentage: peakProfit.pnlPercentage,
30058
+ peakProfitCost: peakProfit.pnlCost,
30059
+ peakProfitEntries: peakProfit.pnlEntries,
30060
+ peakProfitPriceOpen: peakProfit.priceOpen,
30061
+ peakProfitPriceClose: peakProfit.priceClose,
30062
+ maxDrawdownPercentage: maxDrawdown.pnlPercentage,
30063
+ maxDrawdownCost: maxDrawdown.pnlCost,
30064
+ maxDrawdownEntries: maxDrawdown.pnlEntries,
30065
+ maxDrawdownPriceOpen: maxDrawdown.priceOpen,
30066
+ maxDrawdownPriceClose: maxDrawdown.priceClose,
29821
30067
  totalPartials,
29822
30068
  }, {
29823
30069
  signalId,
@@ -29831,7 +30077,7 @@ class StrategyReportService {
29831
30077
  /**
29832
30078
  * Logs a breakeven event when the stop-loss is moved to entry price.
29833
30079
  */
29834
- this.breakeven = async (symbol, currentPrice, isBacktest, context, timestamp, signalId, pnl, totalPartials, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt, totalEntries, originalPriceOpen) => {
30080
+ this.breakeven = async (symbol, currentPrice, isBacktest, context, timestamp, signalId, pnl, peakProfit, maxDrawdown, totalPartials, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt, totalEntries, originalPriceOpen) => {
29835
30081
  this.loggerService.log("strategyReportService breakeven", {
29836
30082
  symbol,
29837
30083
  currentPrice,
@@ -29862,6 +30108,16 @@ class StrategyReportService {
29862
30108
  pnlEntries: pnl.pnlEntries,
29863
30109
  pnlPriceOpen: pnl.priceOpen,
29864
30110
  pnlPriceClose: pnl.priceClose,
30111
+ peakProfitPercentage: peakProfit.pnlPercentage,
30112
+ peakProfitCost: peakProfit.pnlCost,
30113
+ peakProfitEntries: peakProfit.pnlEntries,
30114
+ peakProfitPriceOpen: peakProfit.priceOpen,
30115
+ peakProfitPriceClose: peakProfit.priceClose,
30116
+ maxDrawdownPercentage: maxDrawdown.pnlPercentage,
30117
+ maxDrawdownCost: maxDrawdown.pnlCost,
30118
+ maxDrawdownEntries: maxDrawdown.pnlEntries,
30119
+ maxDrawdownPriceOpen: maxDrawdown.priceOpen,
30120
+ maxDrawdownPriceClose: maxDrawdown.priceClose,
29865
30121
  totalPartials,
29866
30122
  }, {
29867
30123
  signalId,
@@ -29875,7 +30131,7 @@ class StrategyReportService {
29875
30131
  /**
29876
30132
  * Logs an activate-scheduled event when a scheduled signal is activated early.
29877
30133
  */
29878
- this.activateScheduled = async (symbol, currentPrice, isBacktest, context, timestamp, signalId, pnl, totalPartials, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt, totalEntries, originalPriceOpen, activateId, note) => {
30134
+ this.activateScheduled = async (symbol, currentPrice, isBacktest, context, timestamp, signalId, pnl, peakProfit, maxDrawdown, totalPartials, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt, totalEntries, originalPriceOpen, activateId, note) => {
29879
30135
  this.loggerService.log("strategyReportService activateScheduled", {
29880
30136
  symbol,
29881
30137
  currentPrice,
@@ -29909,6 +30165,16 @@ class StrategyReportService {
29909
30165
  pnlEntries: pnl.pnlEntries,
29910
30166
  pnlPriceOpen: pnl.priceOpen,
29911
30167
  pnlPriceClose: pnl.priceClose,
30168
+ peakProfitPercentage: peakProfit.pnlPercentage,
30169
+ peakProfitCost: peakProfit.pnlCost,
30170
+ peakProfitEntries: peakProfit.pnlEntries,
30171
+ peakProfitPriceOpen: peakProfit.priceOpen,
30172
+ peakProfitPriceClose: peakProfit.priceClose,
30173
+ maxDrawdownPercentage: maxDrawdown.pnlPercentage,
30174
+ maxDrawdownCost: maxDrawdown.pnlCost,
30175
+ maxDrawdownEntries: maxDrawdown.pnlEntries,
30176
+ maxDrawdownPriceOpen: maxDrawdown.priceOpen,
30177
+ maxDrawdownPriceClose: maxDrawdown.priceClose,
29912
30178
  totalPartials,
29913
30179
  }, {
29914
30180
  signalId,
@@ -29922,7 +30188,7 @@ class StrategyReportService {
29922
30188
  /**
29923
30189
  * Logs an average-buy (DCA) event when a new averaging entry is added to an open position.
29924
30190
  */
29925
- this.averageBuy = async (symbol, currentPrice, effectivePriceOpen, totalEntries, isBacktest, context, timestamp, signalId, pnl, totalPartials, cost, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt, originalPriceOpen) => {
30191
+ this.averageBuy = async (symbol, currentPrice, effectivePriceOpen, totalEntries, isBacktest, context, timestamp, signalId, pnl, peakProfit, maxDrawdown, totalPartials, cost, position, priceOpen, priceTakeProfit, priceStopLoss, originalPriceTakeProfit, originalPriceStopLoss, scheduledAt, pendingAt, originalPriceOpen) => {
29926
30192
  this.loggerService.log("strategyReportService averageBuy", {
29927
30193
  symbol,
29928
30194
  currentPrice,
@@ -29956,6 +30222,16 @@ class StrategyReportService {
29956
30222
  pnlEntries: pnl.pnlEntries,
29957
30223
  pnlPriceOpen: pnl.priceOpen,
29958
30224
  pnlPriceClose: pnl.priceClose,
30225
+ peakProfitPercentage: peakProfit.pnlPercentage,
30226
+ peakProfitCost: peakProfit.pnlCost,
30227
+ peakProfitEntries: peakProfit.pnlEntries,
30228
+ peakProfitPriceOpen: peakProfit.priceOpen,
30229
+ peakProfitPriceClose: peakProfit.priceClose,
30230
+ maxDrawdownPercentage: maxDrawdown.pnlPercentage,
30231
+ maxDrawdownCost: maxDrawdown.pnlCost,
30232
+ maxDrawdownEntries: maxDrawdown.pnlEntries,
30233
+ maxDrawdownPriceOpen: maxDrawdown.priceOpen,
30234
+ maxDrawdownPriceClose: maxDrawdown.priceClose,
29959
30235
  totalPartials,
29960
30236
  cost,
29961
30237
  }, {
@@ -29983,63 +30259,63 @@ class StrategyReportService {
29983
30259
  exchangeName: event.exchangeName,
29984
30260
  frameName: event.frameName,
29985
30261
  strategyName: event.strategyName,
29986
- }, event.timestamp, event.signalId, event.pnl, event.totalPartials, event.cancelId, event.note));
30262
+ }, event.timestamp, event.signalId, event.pnl, event.peakProfit, event.maxDrawdown, event.totalPartials, event.cancelId, event.note));
29987
30263
  const unClosePending = strategyCommitSubject
29988
30264
  .filter(({ action }) => action === "close-pending")
29989
30265
  .connect(async (event) => await this.closePending(event.symbol, event.backtest, {
29990
30266
  exchangeName: event.exchangeName,
29991
30267
  frameName: event.frameName,
29992
30268
  strategyName: event.strategyName,
29993
- }, event.timestamp, event.signalId, event.pnl, event.totalPartials, event.closeId, event.note));
30269
+ }, event.timestamp, event.signalId, event.pnl, event.peakProfit, event.maxDrawdown, event.totalPartials, event.closeId, event.note));
29994
30270
  const unPartialProfit = strategyCommitSubject
29995
30271
  .filter(({ action }) => action === "partial-profit")
29996
30272
  .connect(async (event) => await this.partialProfit(event.symbol, event.percentToClose, event.currentPrice, event.backtest, {
29997
30273
  exchangeName: event.exchangeName,
29998
30274
  frameName: event.frameName,
29999
30275
  strategyName: event.strategyName,
30000
- }, event.timestamp, event.signalId, event.pnl, event.totalPartials, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt, event.totalEntries, event.originalPriceOpen));
30276
+ }, event.timestamp, event.signalId, event.pnl, event.peakProfit, event.maxDrawdown, event.totalPartials, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt, event.totalEntries, event.originalPriceOpen));
30001
30277
  const unPartialLoss = strategyCommitSubject
30002
30278
  .filter(({ action }) => action === "partial-loss")
30003
30279
  .connect(async (event) => await this.partialLoss(event.symbol, event.percentToClose, event.currentPrice, event.backtest, {
30004
30280
  exchangeName: event.exchangeName,
30005
30281
  frameName: event.frameName,
30006
30282
  strategyName: event.strategyName,
30007
- }, event.timestamp, event.signalId, event.pnl, event.totalPartials, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt, event.totalEntries, event.originalPriceOpen));
30283
+ }, event.timestamp, event.signalId, event.pnl, event.peakProfit, event.maxDrawdown, event.totalPartials, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt, event.totalEntries, event.originalPriceOpen));
30008
30284
  const unTrailingStop = strategyCommitSubject
30009
30285
  .filter(({ action }) => action === "trailing-stop")
30010
30286
  .connect(async (event) => await this.trailingStop(event.symbol, event.percentShift, event.currentPrice, event.backtest, {
30011
30287
  exchangeName: event.exchangeName,
30012
30288
  frameName: event.frameName,
30013
30289
  strategyName: event.strategyName,
30014
- }, event.timestamp, event.signalId, event.pnl, event.totalPartials, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt, event.totalEntries, event.originalPriceOpen));
30290
+ }, event.timestamp, event.signalId, event.pnl, event.peakProfit, event.maxDrawdown, event.totalPartials, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt, event.totalEntries, event.originalPriceOpen));
30015
30291
  const unTrailingTake = strategyCommitSubject
30016
30292
  .filter(({ action }) => action === "trailing-take")
30017
30293
  .connect(async (event) => await this.trailingTake(event.symbol, event.percentShift, event.currentPrice, event.backtest, {
30018
30294
  exchangeName: event.exchangeName,
30019
30295
  frameName: event.frameName,
30020
30296
  strategyName: event.strategyName,
30021
- }, event.timestamp, event.signalId, event.pnl, event.totalPartials, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt, event.totalEntries, event.originalPriceOpen));
30297
+ }, event.timestamp, event.signalId, event.pnl, event.peakProfit, event.maxDrawdown, event.totalPartials, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt, event.totalEntries, event.originalPriceOpen));
30022
30298
  const unBreakeven = strategyCommitSubject
30023
30299
  .filter(({ action }) => action === "breakeven")
30024
30300
  .connect(async (event) => await this.breakeven(event.symbol, event.currentPrice, event.backtest, {
30025
30301
  exchangeName: event.exchangeName,
30026
30302
  frameName: event.frameName,
30027
30303
  strategyName: event.strategyName,
30028
- }, event.timestamp, event.signalId, event.pnl, event.totalPartials, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt, event.totalEntries, event.originalPriceOpen));
30304
+ }, event.timestamp, event.signalId, event.pnl, event.peakProfit, event.maxDrawdown, event.totalPartials, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt, event.totalEntries, event.originalPriceOpen));
30029
30305
  const unActivateScheduled = strategyCommitSubject
30030
30306
  .filter(({ action }) => action === "activate-scheduled")
30031
30307
  .connect(async (event) => await this.activateScheduled(event.symbol, event.currentPrice, event.backtest, {
30032
30308
  exchangeName: event.exchangeName,
30033
30309
  frameName: event.frameName,
30034
30310
  strategyName: event.strategyName,
30035
- }, event.timestamp, event.signalId, event.pnl, event.totalPartials, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt, event.totalEntries, event.originalPriceOpen, event.activateId, event.note));
30311
+ }, event.timestamp, event.signalId, event.pnl, event.peakProfit, event.maxDrawdown, event.totalPartials, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt, event.totalEntries, event.originalPriceOpen, event.activateId, event.note));
30036
30312
  const unAverageBuy = strategyCommitSubject
30037
30313
  .filter(({ action }) => action === "average-buy")
30038
30314
  .connect(async (event) => await this.averageBuy(event.symbol, event.currentPrice, event.effectivePriceOpen, event.totalEntries, event.backtest, {
30039
30315
  exchangeName: event.exchangeName,
30040
30316
  frameName: event.frameName,
30041
30317
  strategyName: event.strategyName,
30042
- }, event.timestamp, event.signalId, event.pnl, event.totalPartials, event.cost, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt, event.originalPriceOpen));
30318
+ }, event.timestamp, event.signalId, event.pnl, event.peakProfit, event.maxDrawdown, event.totalPartials, event.cost, event.position, event.priceOpen, event.priceTakeProfit, event.priceStopLoss, event.originalPriceTakeProfit, event.originalPriceStopLoss, event.scheduledAt, event.pendingAt, event.originalPriceOpen));
30043
30319
  const disposeFn = compose(() => unCancelSchedule(), () => unClosePending(), () => unPartialProfit(), () => unPartialLoss(), () => unTrailingStop(), () => unTrailingTake(), () => unBreakeven(), () => unActivateScheduled(), () => unAverageBuy());
30044
30320
  return () => {
30045
30321
  disposeFn();
@@ -30138,6 +30414,16 @@ class SyncReportService {
30138
30414
  pnlEntries: data.pnl.pnlEntries,
30139
30415
  pnlPriceOpen: data.pnl.priceOpen,
30140
30416
  pnlPriceClose: data.pnl.priceClose,
30417
+ peakProfitPercentage: data.peakProfit.pnlPercentage,
30418
+ peakProfitCost: data.peakProfit.pnlCost,
30419
+ peakProfitEntries: data.peakProfit.pnlEntries,
30420
+ peakProfitPriceOpen: data.peakProfit.priceOpen,
30421
+ peakProfitPriceClose: data.peakProfit.priceClose,
30422
+ maxDrawdownPercentage: data.maxDrawdown.pnlPercentage,
30423
+ maxDrawdownCost: data.maxDrawdown.pnlCost,
30424
+ maxDrawdownEntries: data.maxDrawdown.pnlEntries,
30425
+ maxDrawdownPriceOpen: data.maxDrawdown.priceOpen,
30426
+ maxDrawdownPriceClose: data.maxDrawdown.priceClose,
30141
30427
  currentPrice: data.currentPrice,
30142
30428
  };
30143
30429
  const searchOptions = {
@@ -30248,6 +30534,16 @@ class HighestProfitReportService {
30248
30534
  priceOpen: data.signal.priceOpen,
30249
30535
  priceTakeProfit: data.signal.priceTakeProfit,
30250
30536
  priceStopLoss: data.signal.priceStopLoss,
30537
+ peakProfitPercentage: data.signal.peakProfit.pnlPercentage,
30538
+ peakProfitCost: data.signal.peakProfit.pnlCost,
30539
+ peakProfitEntries: data.signal.peakProfit.pnlEntries,
30540
+ peakProfitPriceOpen: data.signal.peakProfit.priceOpen,
30541
+ peakProfitPriceClose: data.signal.peakProfit.priceClose,
30542
+ maxDrawdownPercentage: data.signal.maxDrawdown.pnlPercentage,
30543
+ maxDrawdownCost: data.signal.maxDrawdown.pnlCost,
30544
+ maxDrawdownEntries: data.signal.maxDrawdown.pnlEntries,
30545
+ maxDrawdownPriceOpen: data.signal.maxDrawdown.priceOpen,
30546
+ maxDrawdownPriceClose: data.signal.maxDrawdown.priceClose,
30251
30547
  }, {
30252
30548
  symbol: data.symbol,
30253
30549
  strategyName: data.signal.strategyName,
@@ -31525,7 +31821,9 @@ class SyncMarkdownService {
31525
31821
  pendingAt: data.pendingAt,
31526
31822
  totalEntries: data.totalEntries,
31527
31823
  totalPartials: data.totalPartials,
31528
- pnl: data.pnl,
31824
+ pnl: data.signal.pnl,
31825
+ maxDrawdown: data.signal.maxDrawdown,
31826
+ peakProfit: data.signal.peakProfit,
31529
31827
  closeReason: data.action === "signal-close" ? data.closeReason : undefined,
31530
31828
  backtest: data.backtest,
31531
31829
  createdAt,
@@ -31700,6 +31998,8 @@ let ReportStorage$1 = class ReportStorage {
31700
31998
  signalId: data.id,
31701
31999
  position: data.position,
31702
32000
  pnl: data.pnl,
32001
+ maxDrawdown: data.maxDrawdown,
32002
+ peakProfit: data.peakProfit,
31703
32003
  currentPrice,
31704
32004
  priceOpen: data.priceOpen,
31705
32005
  priceTakeProfit: data.priceTakeProfit,
@@ -32311,6 +32611,16 @@ class MaxDrawdownReportService {
32311
32611
  priceOpen: data.signal.priceOpen,
32312
32612
  priceTakeProfit: data.signal.priceTakeProfit,
32313
32613
  priceStopLoss: data.signal.priceStopLoss,
32614
+ peakProfitPercentage: data.signal.peakProfit.pnlPercentage,
32615
+ peakProfitCost: data.signal.peakProfit.pnlCost,
32616
+ peakProfitEntries: data.signal.peakProfit.pnlEntries,
32617
+ peakProfitPriceOpen: data.signal.peakProfit.priceOpen,
32618
+ peakProfitPriceClose: data.signal.peakProfit.priceClose,
32619
+ maxDrawdownPercentage: data.signal.maxDrawdown.pnlPercentage,
32620
+ maxDrawdownCost: data.signal.maxDrawdown.pnlCost,
32621
+ maxDrawdownEntries: data.signal.maxDrawdown.pnlEntries,
32622
+ maxDrawdownPriceOpen: data.signal.maxDrawdown.priceOpen,
32623
+ maxDrawdownPriceClose: data.signal.maxDrawdown.priceClose,
32314
32624
  }, {
32315
32625
  symbol: data.symbol,
32316
32626
  strategyName: data.signal.strategyName,
@@ -32403,6 +32713,8 @@ class ReportStorage {
32403
32713
  signalId: data.id,
32404
32714
  position: data.position,
32405
32715
  pnl: data.pnl,
32716
+ maxDrawdown: data.maxDrawdown,
32717
+ peakProfit: data.peakProfit,
32406
32718
  currentPrice,
32407
32719
  priceOpen: data.priceOpen,
32408
32720
  priceTakeProfit: data.priceTakeProfit,
@@ -35354,6 +35666,9 @@ class BrokerAdapter {
35354
35666
  priceTakeProfit: event.signal.priceTakeProfit,
35355
35667
  priceStopLoss: event.signal.priceStopLoss,
35356
35668
  priceOpen: event.signal.priceOpen,
35669
+ pnl: event.signal.pnl,
35670
+ peakProfit: event.signal.peakProfit,
35671
+ maxDrawdown: event.signal.maxDrawdown,
35357
35672
  context: {
35358
35673
  strategyName: event.strategyName,
35359
35674
  exchangeName: event.exchangeName,
@@ -35371,7 +35686,10 @@ class BrokerAdapter {
35371
35686
  currentPrice: event.currentPrice,
35372
35687
  cost: event.signal.cost,
35373
35688
  symbol: event.symbol,
35374
- pnl: event.pnl,
35689
+ pnl: event.signal.pnl,
35690
+ priceOpen: event.signal.priceOpen,
35691
+ peakProfit: event.signal.peakProfit,
35692
+ maxDrawdown: event.signal.maxDrawdown,
35375
35693
  totalEntries: event.totalEntries,
35376
35694
  totalPartials: event.totalPartials,
35377
35695
  priceStopLoss: event.signal.priceStopLoss,
@@ -54413,11 +54731,23 @@ const CREATE_SIGNAL_NOTIFICATION_FN = (data) => {
54413
54731
  totalPartials: data.signal.totalPartials,
54414
54732
  cost: data.signal.cost,
54415
54733
  pnl: data.signal.pnl,
54734
+ maxDrawdown: data.signal.maxDrawdown,
54735
+ peakProfit: data.signal.peakProfit,
54416
54736
  pnlPercentage: data.signal.pnl.pnlPercentage,
54417
54737
  pnlPriceOpen: data.signal.pnl.priceOpen,
54418
54738
  pnlPriceClose: data.signal.pnl.priceClose,
54419
54739
  pnlCost: data.signal.pnl.pnlCost,
54420
54740
  pnlEntries: data.signal.pnl.pnlEntries,
54741
+ peakProfitPriceOpen: data.signal.peakProfit.priceOpen,
54742
+ peakProfitPriceClose: data.signal.peakProfit.priceClose,
54743
+ peakProfitPercentage: data.signal.peakProfit.pnlPercentage,
54744
+ peakProfitCost: data.signal.peakProfit.pnlCost,
54745
+ peakProfitEntries: data.signal.peakProfit.pnlEntries,
54746
+ maxDrawdownPriceOpen: data.signal.maxDrawdown.priceOpen,
54747
+ maxDrawdownPriceClose: data.signal.maxDrawdown.priceClose,
54748
+ maxDrawdownPercentage: data.signal.maxDrawdown.pnlPercentage,
54749
+ maxDrawdownCost: data.signal.maxDrawdown.pnlCost,
54750
+ maxDrawdownEntries: data.signal.maxDrawdown.pnlEntries,
54421
54751
  note: data.signal.note,
54422
54752
  scheduledAt: data.signal.scheduledAt,
54423
54753
  pendingAt: data.signal.pendingAt,
@@ -54447,11 +54777,23 @@ const CREATE_SIGNAL_NOTIFICATION_FN = (data) => {
54447
54777
  totalEntries: data.signal.totalEntries,
54448
54778
  totalPartials: data.signal.totalPartials,
54449
54779
  pnlPercentage: data.pnl.pnlPercentage,
54450
- pnl: data.pnl,
54780
+ pnl: data.signal.pnl,
54781
+ maxDrawdown: data.signal.maxDrawdown,
54782
+ peakProfit: data.signal.peakProfit,
54451
54783
  pnlPriceOpen: data.pnl.priceOpen,
54452
54784
  pnlPriceClose: data.pnl.priceClose,
54453
54785
  pnlCost: data.pnl.pnlCost,
54454
54786
  pnlEntries: data.pnl.pnlEntries,
54787
+ peakProfitPriceOpen: data.signal.peakProfit.priceOpen,
54788
+ peakProfitPriceClose: data.signal.peakProfit.priceClose,
54789
+ peakProfitPercentage: data.signal.peakProfit.pnlPercentage,
54790
+ peakProfitCost: data.signal.peakProfit.pnlCost,
54791
+ peakProfitEntries: data.signal.peakProfit.pnlEntries,
54792
+ maxDrawdownPriceOpen: data.signal.maxDrawdown.priceOpen,
54793
+ maxDrawdownPriceClose: data.signal.maxDrawdown.priceClose,
54794
+ maxDrawdownPercentage: data.signal.maxDrawdown.pnlPercentage,
54795
+ maxDrawdownCost: data.signal.maxDrawdown.pnlCost,
54796
+ maxDrawdownEntries: data.signal.maxDrawdown.pnlEntries,
54455
54797
  closeReason: data.closeReason,
54456
54798
  duration: durationMin,
54457
54799
  note: data.signal.note,
@@ -54481,11 +54823,23 @@ const CREATE_SIGNAL_NOTIFICATION_FN = (data) => {
54481
54823
  totalPartials: data.signal.totalPartials,
54482
54824
  cost: data.signal.cost,
54483
54825
  pnl: data.signal.pnl,
54826
+ maxDrawdown: data.signal.maxDrawdown,
54827
+ peakProfit: data.signal.peakProfit,
54484
54828
  pnlPercentage: data.signal.pnl.pnlPercentage,
54485
54829
  pnlPriceOpen: data.signal.pnl.priceOpen,
54486
54830
  pnlPriceClose: data.signal.pnl.priceClose,
54487
54831
  pnlCost: data.signal.pnl.pnlCost,
54488
54832
  pnlEntries: data.signal.pnl.pnlEntries,
54833
+ peakProfitPriceOpen: data.signal.peakProfit.priceOpen,
54834
+ peakProfitPriceClose: data.signal.peakProfit.priceClose,
54835
+ peakProfitPercentage: data.signal.peakProfit.pnlPercentage,
54836
+ peakProfitCost: data.signal.peakProfit.pnlCost,
54837
+ peakProfitEntries: data.signal.peakProfit.pnlEntries,
54838
+ maxDrawdownPriceOpen: data.signal.maxDrawdown.priceOpen,
54839
+ maxDrawdownPriceClose: data.signal.maxDrawdown.priceClose,
54840
+ maxDrawdownPercentage: data.signal.maxDrawdown.pnlPercentage,
54841
+ maxDrawdownCost: data.signal.maxDrawdown.pnlCost,
54842
+ maxDrawdownEntries: data.signal.maxDrawdown.pnlEntries,
54489
54843
  scheduledAt: data.signal.scheduledAt,
54490
54844
  currentPrice: data.currentPrice,
54491
54845
  note: data.signal.note,
@@ -54550,11 +54904,23 @@ const CREATE_PARTIAL_PROFIT_NOTIFICATION_FN = (data) => ({
54550
54904
  totalEntries: data.data.totalEntries,
54551
54905
  totalPartials: data.data.totalPartials,
54552
54906
  pnl: data.data.pnl,
54907
+ maxDrawdown: data.data.maxDrawdown,
54908
+ peakProfit: data.data.peakProfit,
54553
54909
  pnlPercentage: data.data.pnl.pnlPercentage,
54554
54910
  pnlPriceOpen: data.data.pnl.priceOpen,
54555
54911
  pnlPriceClose: data.data.pnl.priceClose,
54556
54912
  pnlCost: data.data.pnl.pnlCost,
54557
54913
  pnlEntries: data.data.pnl.pnlEntries,
54914
+ peakProfitPriceOpen: data.data.peakProfit.priceOpen,
54915
+ peakProfitPriceClose: data.data.peakProfit.priceClose,
54916
+ peakProfitPercentage: data.data.peakProfit.pnlPercentage,
54917
+ peakProfitCost: data.data.peakProfit.pnlCost,
54918
+ peakProfitEntries: data.data.peakProfit.pnlEntries,
54919
+ maxDrawdownPriceOpen: data.data.maxDrawdown.priceOpen,
54920
+ maxDrawdownPriceClose: data.data.maxDrawdown.priceClose,
54921
+ maxDrawdownPercentage: data.data.maxDrawdown.pnlPercentage,
54922
+ maxDrawdownCost: data.data.maxDrawdown.pnlCost,
54923
+ maxDrawdownEntries: data.data.maxDrawdown.pnlEntries,
54558
54924
  note: data.data.note,
54559
54925
  scheduledAt: data.data.scheduledAt,
54560
54926
  pendingAt: data.data.pendingAt,
@@ -54586,11 +54952,23 @@ const CREATE_PARTIAL_LOSS_NOTIFICATION_FN = (data) => ({
54586
54952
  totalEntries: data.data.totalEntries,
54587
54953
  totalPartials: data.data.totalPartials,
54588
54954
  pnl: data.data.pnl,
54955
+ maxDrawdown: data.data.maxDrawdown,
54956
+ peakProfit: data.data.peakProfit,
54589
54957
  pnlPercentage: data.data.pnl.pnlPercentage,
54590
54958
  pnlPriceOpen: data.data.pnl.priceOpen,
54591
54959
  pnlPriceClose: data.data.pnl.priceClose,
54592
54960
  pnlCost: data.data.pnl.pnlCost,
54593
54961
  pnlEntries: data.data.pnl.pnlEntries,
54962
+ peakProfitPriceOpen: data.data.peakProfit.priceOpen,
54963
+ peakProfitPriceClose: data.data.peakProfit.priceClose,
54964
+ peakProfitPercentage: data.data.peakProfit.pnlPercentage,
54965
+ peakProfitCost: data.data.peakProfit.pnlCost,
54966
+ peakProfitEntries: data.data.peakProfit.pnlEntries,
54967
+ maxDrawdownPriceOpen: data.data.maxDrawdown.priceOpen,
54968
+ maxDrawdownPriceClose: data.data.maxDrawdown.priceClose,
54969
+ maxDrawdownPercentage: data.data.maxDrawdown.pnlPercentage,
54970
+ maxDrawdownCost: data.data.maxDrawdown.pnlCost,
54971
+ maxDrawdownEntries: data.data.maxDrawdown.pnlEntries,
54594
54972
  note: data.data.note,
54595
54973
  scheduledAt: data.data.scheduledAt,
54596
54974
  pendingAt: data.data.pendingAt,
@@ -54621,11 +54999,23 @@ const CREATE_BREAKEVEN_NOTIFICATION_FN = (data) => ({
54621
54999
  totalEntries: data.data.totalEntries,
54622
55000
  totalPartials: data.data.totalPartials,
54623
55001
  pnl: data.data.pnl,
55002
+ maxDrawdown: data.data.maxDrawdown,
55003
+ peakProfit: data.data.peakProfit,
54624
55004
  pnlPercentage: data.data.pnl.pnlPercentage,
54625
55005
  pnlPriceOpen: data.data.pnl.priceOpen,
54626
55006
  pnlPriceClose: data.data.pnl.priceClose,
54627
55007
  pnlCost: data.data.pnl.pnlCost,
54628
55008
  pnlEntries: data.data.pnl.pnlEntries,
55009
+ peakProfitPriceOpen: data.data.peakProfit.priceOpen,
55010
+ peakProfitPriceClose: data.data.peakProfit.priceClose,
55011
+ peakProfitPercentage: data.data.peakProfit.pnlPercentage,
55012
+ peakProfitCost: data.data.peakProfit.pnlCost,
55013
+ peakProfitEntries: data.data.peakProfit.pnlEntries,
55014
+ maxDrawdownPriceOpen: data.data.maxDrawdown.priceOpen,
55015
+ maxDrawdownPriceClose: data.data.maxDrawdown.priceClose,
55016
+ maxDrawdownPercentage: data.data.maxDrawdown.pnlPercentage,
55017
+ maxDrawdownCost: data.data.maxDrawdown.pnlCost,
55018
+ maxDrawdownEntries: data.data.maxDrawdown.pnlEntries,
54629
55019
  note: data.data.note,
54630
55020
  scheduledAt: data.data.scheduledAt,
54631
55021
  pendingAt: data.data.pendingAt,
@@ -54660,12 +55050,24 @@ const CREATE_STRATEGY_COMMIT_NOTIFICATION_FN = (data) => {
54660
55050
  originalPriceOpen: data.originalPriceOpen,
54661
55051
  totalEntries: data.totalEntries,
54662
55052
  totalPartials: data.totalPartials,
54663
- pnl: data.pnl,
55053
+ pnl: data.signal.pnl,
55054
+ maxDrawdown: data.signal.maxDrawdown,
55055
+ peakProfit: data.signal.peakProfit,
54664
55056
  pnlPercentage: data.pnl.pnlPercentage,
54665
55057
  pnlPriceOpen: data.pnl.priceOpen,
54666
55058
  pnlPriceClose: data.pnl.priceClose,
54667
55059
  pnlCost: data.pnl.pnlCost,
54668
55060
  pnlEntries: data.pnl.pnlEntries,
55061
+ peakProfitPriceOpen: data.signal.peakProfit.priceOpen,
55062
+ peakProfitPriceClose: data.signal.peakProfit.priceClose,
55063
+ peakProfitPercentage: data.signal.peakProfit.pnlPercentage,
55064
+ peakProfitCost: data.signal.peakProfit.pnlCost,
55065
+ peakProfitEntries: data.signal.peakProfit.pnlEntries,
55066
+ maxDrawdownPriceOpen: data.signal.maxDrawdown.priceOpen,
55067
+ maxDrawdownPriceClose: data.signal.maxDrawdown.priceClose,
55068
+ maxDrawdownPercentage: data.signal.maxDrawdown.pnlPercentage,
55069
+ maxDrawdownCost: data.signal.maxDrawdown.pnlCost,
55070
+ maxDrawdownEntries: data.signal.maxDrawdown.pnlEntries,
54669
55071
  scheduledAt: data.scheduledAt,
54670
55072
  pendingAt: data.pendingAt,
54671
55073
  note: data.note,
@@ -54693,12 +55095,24 @@ const CREATE_STRATEGY_COMMIT_NOTIFICATION_FN = (data) => {
54693
55095
  originalPriceOpen: data.originalPriceOpen,
54694
55096
  totalEntries: data.totalEntries,
54695
55097
  totalPartials: data.totalPartials,
54696
- pnl: data.pnl,
55098
+ pnl: data.signal.pnl,
55099
+ maxDrawdown: data.signal.maxDrawdown,
55100
+ peakProfit: data.signal.peakProfit,
54697
55101
  pnlPercentage: data.pnl.pnlPercentage,
54698
55102
  pnlPriceOpen: data.pnl.priceOpen,
54699
55103
  pnlPriceClose: data.pnl.priceClose,
54700
55104
  pnlCost: data.pnl.pnlCost,
54701
55105
  pnlEntries: data.pnl.pnlEntries,
55106
+ peakProfitPriceOpen: data.signal.peakProfit.priceOpen,
55107
+ peakProfitPriceClose: data.signal.peakProfit.priceClose,
55108
+ peakProfitPercentage: data.signal.peakProfit.pnlPercentage,
55109
+ peakProfitCost: data.signal.peakProfit.pnlCost,
55110
+ peakProfitEntries: data.signal.peakProfit.pnlEntries,
55111
+ maxDrawdownPriceOpen: data.signal.maxDrawdown.priceOpen,
55112
+ maxDrawdownPriceClose: data.signal.maxDrawdown.priceClose,
55113
+ maxDrawdownPercentage: data.signal.maxDrawdown.pnlPercentage,
55114
+ maxDrawdownCost: data.signal.maxDrawdown.pnlCost,
55115
+ maxDrawdownEntries: data.signal.maxDrawdown.pnlEntries,
54702
55116
  scheduledAt: data.scheduledAt,
54703
55117
  pendingAt: data.pendingAt,
54704
55118
  note: data.note,
@@ -54725,12 +55139,24 @@ const CREATE_STRATEGY_COMMIT_NOTIFICATION_FN = (data) => {
54725
55139
  originalPriceOpen: data.originalPriceOpen,
54726
55140
  totalEntries: data.totalEntries,
54727
55141
  totalPartials: data.totalPartials,
54728
- pnl: data.pnl,
55142
+ pnl: data.signal.pnl,
55143
+ maxDrawdown: data.signal.maxDrawdown,
55144
+ peakProfit: data.signal.peakProfit,
54729
55145
  pnlPercentage: data.pnl.pnlPercentage,
54730
55146
  pnlPriceOpen: data.pnl.priceOpen,
54731
55147
  pnlPriceClose: data.pnl.priceClose,
54732
55148
  pnlCost: data.pnl.pnlCost,
54733
55149
  pnlEntries: data.pnl.pnlEntries,
55150
+ peakProfitPriceOpen: data.signal.peakProfit.priceOpen,
55151
+ peakProfitPriceClose: data.signal.peakProfit.priceClose,
55152
+ peakProfitPercentage: data.signal.peakProfit.pnlPercentage,
55153
+ peakProfitCost: data.signal.peakProfit.pnlCost,
55154
+ peakProfitEntries: data.signal.peakProfit.pnlEntries,
55155
+ maxDrawdownPriceOpen: data.signal.maxDrawdown.priceOpen,
55156
+ maxDrawdownPriceClose: data.signal.maxDrawdown.priceClose,
55157
+ maxDrawdownPercentage: data.signal.maxDrawdown.pnlPercentage,
55158
+ maxDrawdownCost: data.signal.maxDrawdown.pnlCost,
55159
+ maxDrawdownEntries: data.signal.maxDrawdown.pnlEntries,
54734
55160
  scheduledAt: data.scheduledAt,
54735
55161
  pendingAt: data.pendingAt,
54736
55162
  note: data.note,
@@ -54758,12 +55184,24 @@ const CREATE_STRATEGY_COMMIT_NOTIFICATION_FN = (data) => {
54758
55184
  originalPriceOpen: data.originalPriceOpen,
54759
55185
  totalEntries: data.totalEntries,
54760
55186
  totalPartials: data.totalPartials,
54761
- pnl: data.pnl,
55187
+ pnl: data.signal.pnl,
55188
+ maxDrawdown: data.signal.maxDrawdown,
55189
+ peakProfit: data.signal.peakProfit,
54762
55190
  pnlPercentage: data.pnl.pnlPercentage,
54763
55191
  pnlPriceOpen: data.pnl.priceOpen,
54764
55192
  pnlPriceClose: data.pnl.priceClose,
54765
55193
  pnlCost: data.pnl.pnlCost,
54766
55194
  pnlEntries: data.pnl.pnlEntries,
55195
+ peakProfitPriceOpen: data.signal.peakProfit.priceOpen,
55196
+ peakProfitPriceClose: data.signal.peakProfit.priceClose,
55197
+ peakProfitPercentage: data.signal.peakProfit.pnlPercentage,
55198
+ peakProfitCost: data.signal.peakProfit.pnlCost,
55199
+ peakProfitEntries: data.signal.peakProfit.pnlEntries,
55200
+ maxDrawdownPriceOpen: data.signal.maxDrawdown.priceOpen,
55201
+ maxDrawdownPriceClose: data.signal.maxDrawdown.priceClose,
55202
+ maxDrawdownPercentage: data.signal.maxDrawdown.pnlPercentage,
55203
+ maxDrawdownCost: data.signal.maxDrawdown.pnlCost,
55204
+ maxDrawdownEntries: data.signal.maxDrawdown.pnlEntries,
54767
55205
  scheduledAt: data.scheduledAt,
54768
55206
  pendingAt: data.pendingAt,
54769
55207
  note: data.note,
@@ -54791,12 +55229,24 @@ const CREATE_STRATEGY_COMMIT_NOTIFICATION_FN = (data) => {
54791
55229
  originalPriceOpen: data.originalPriceOpen,
54792
55230
  totalEntries: data.totalEntries,
54793
55231
  totalPartials: data.totalPartials,
54794
- pnl: data.pnl,
55232
+ pnl: data.signal.pnl,
55233
+ maxDrawdown: data.signal.maxDrawdown,
55234
+ peakProfit: data.signal.peakProfit,
54795
55235
  pnlPercentage: data.pnl.pnlPercentage,
54796
55236
  pnlPriceOpen: data.pnl.priceOpen,
54797
55237
  pnlPriceClose: data.pnl.priceClose,
54798
55238
  pnlCost: data.pnl.pnlCost,
54799
55239
  pnlEntries: data.pnl.pnlEntries,
55240
+ peakProfitPriceOpen: data.signal.peakProfit.priceOpen,
55241
+ peakProfitPriceClose: data.signal.peakProfit.priceClose,
55242
+ peakProfitPercentage: data.signal.peakProfit.pnlPercentage,
55243
+ peakProfitCost: data.signal.peakProfit.pnlCost,
55244
+ peakProfitEntries: data.signal.peakProfit.pnlEntries,
55245
+ maxDrawdownPriceOpen: data.signal.maxDrawdown.priceOpen,
55246
+ maxDrawdownPriceClose: data.signal.maxDrawdown.priceClose,
55247
+ maxDrawdownPercentage: data.signal.maxDrawdown.pnlPercentage,
55248
+ maxDrawdownCost: data.signal.maxDrawdown.pnlCost,
55249
+ maxDrawdownEntries: data.signal.maxDrawdown.pnlEntries,
54800
55250
  scheduledAt: data.scheduledAt,
54801
55251
  pendingAt: data.pendingAt,
54802
55252
  note: data.note,
@@ -54824,12 +55274,24 @@ const CREATE_STRATEGY_COMMIT_NOTIFICATION_FN = (data) => {
54824
55274
  originalPriceOpen: data.originalPriceOpen,
54825
55275
  totalEntries: data.totalEntries,
54826
55276
  totalPartials: data.totalPartials,
54827
- pnl: data.pnl,
55277
+ pnl: data.signal.pnl,
55278
+ maxDrawdown: data.signal.maxDrawdown,
55279
+ peakProfit: data.signal.peakProfit,
54828
55280
  pnlPercentage: data.pnl.pnlPercentage,
54829
55281
  pnlPriceOpen: data.pnl.priceOpen,
54830
55282
  pnlPriceClose: data.pnl.priceClose,
54831
55283
  pnlCost: data.pnl.pnlCost,
54832
55284
  pnlEntries: data.pnl.pnlEntries,
55285
+ peakProfitPriceOpen: data.signal.peakProfit.priceOpen,
55286
+ peakProfitPriceClose: data.signal.peakProfit.priceClose,
55287
+ peakProfitPercentage: data.signal.peakProfit.pnlPercentage,
55288
+ peakProfitCost: data.signal.peakProfit.pnlCost,
55289
+ peakProfitEntries: data.signal.peakProfit.pnlEntries,
55290
+ maxDrawdownPriceOpen: data.signal.maxDrawdown.priceOpen,
55291
+ maxDrawdownPriceClose: data.signal.maxDrawdown.priceClose,
55292
+ maxDrawdownPercentage: data.signal.maxDrawdown.pnlPercentage,
55293
+ maxDrawdownCost: data.signal.maxDrawdown.pnlCost,
55294
+ maxDrawdownEntries: data.signal.maxDrawdown.pnlEntries,
54833
55295
  scheduledAt: data.scheduledAt,
54834
55296
  pendingAt: data.pendingAt,
54835
55297
  note: data.note,
@@ -54858,12 +55320,24 @@ const CREATE_STRATEGY_COMMIT_NOTIFICATION_FN = (data) => {
54858
55320
  originalPriceTakeProfit: data.originalPriceTakeProfit,
54859
55321
  originalPriceStopLoss: data.originalPriceStopLoss,
54860
55322
  originalPriceOpen: data.originalPriceOpen,
54861
- pnl: data.pnl,
55323
+ pnl: data.signal.pnl,
55324
+ maxDrawdown: data.signal.maxDrawdown,
55325
+ peakProfit: data.signal.peakProfit,
54862
55326
  pnlPercentage: data.pnl.pnlPercentage,
54863
55327
  pnlPriceOpen: data.pnl.priceOpen,
54864
55328
  pnlPriceClose: data.pnl.priceClose,
54865
55329
  pnlCost: data.pnl.pnlCost,
54866
55330
  pnlEntries: data.pnl.pnlEntries,
55331
+ peakProfitPriceOpen: data.signal.peakProfit.priceOpen,
55332
+ peakProfitPriceClose: data.signal.peakProfit.priceClose,
55333
+ peakProfitPercentage: data.signal.peakProfit.pnlPercentage,
55334
+ peakProfitCost: data.signal.peakProfit.pnlCost,
55335
+ peakProfitEntries: data.signal.peakProfit.pnlEntries,
55336
+ maxDrawdownPriceOpen: data.signal.maxDrawdown.priceOpen,
55337
+ maxDrawdownPriceClose: data.signal.maxDrawdown.priceClose,
55338
+ maxDrawdownPercentage: data.signal.maxDrawdown.pnlPercentage,
55339
+ maxDrawdownCost: data.signal.maxDrawdown.pnlCost,
55340
+ maxDrawdownEntries: data.signal.maxDrawdown.pnlEntries,
54867
55341
  scheduledAt: data.scheduledAt,
54868
55342
  pendingAt: data.pendingAt,
54869
55343
  note: data.note,
@@ -54884,12 +55358,24 @@ const CREATE_STRATEGY_COMMIT_NOTIFICATION_FN = (data) => {
54884
55358
  totalEntries: data.totalEntries,
54885
55359
  totalPartials: data.totalPartials,
54886
55360
  originalPriceOpen: data.originalPriceOpen,
54887
- pnl: data.pnl,
55361
+ pnl: data.signal.pnl,
55362
+ maxDrawdown: data.signal.maxDrawdown,
55363
+ peakProfit: data.signal.peakProfit,
54888
55364
  pnlPercentage: data.pnl.pnlPercentage,
54889
55365
  pnlPriceOpen: data.pnl.priceOpen,
54890
55366
  pnlPriceClose: data.pnl.priceClose,
54891
55367
  pnlCost: data.pnl.pnlCost,
54892
55368
  pnlEntries: data.pnl.pnlEntries,
55369
+ peakProfitPriceOpen: data.signal.peakProfit.priceOpen,
55370
+ peakProfitPriceClose: data.signal.peakProfit.priceClose,
55371
+ peakProfitPercentage: data.signal.peakProfit.pnlPercentage,
55372
+ peakProfitCost: data.signal.peakProfit.pnlCost,
55373
+ peakProfitEntries: data.signal.peakProfit.pnlEntries,
55374
+ maxDrawdownPriceOpen: data.signal.maxDrawdown.priceOpen,
55375
+ maxDrawdownPriceClose: data.signal.maxDrawdown.priceClose,
55376
+ maxDrawdownPercentage: data.signal.maxDrawdown.pnlPercentage,
55377
+ maxDrawdownCost: data.signal.maxDrawdown.pnlCost,
55378
+ maxDrawdownEntries: data.signal.maxDrawdown.pnlEntries,
54893
55379
  note: data.note,
54894
55380
  createdAt: data.timestamp,
54895
55381
  };
@@ -54908,12 +55394,24 @@ const CREATE_STRATEGY_COMMIT_NOTIFICATION_FN = (data) => {
54908
55394
  totalEntries: data.totalEntries,
54909
55395
  totalPartials: data.totalPartials,
54910
55396
  originalPriceOpen: data.originalPriceOpen,
54911
- pnl: data.pnl,
55397
+ pnl: data.signal.pnl,
55398
+ maxDrawdown: data.signal.maxDrawdown,
55399
+ peakProfit: data.signal.peakProfit,
54912
55400
  pnlPercentage: data.pnl.pnlPercentage,
54913
55401
  pnlPriceOpen: data.pnl.priceOpen,
54914
55402
  pnlPriceClose: data.pnl.priceClose,
54915
55403
  pnlCost: data.pnl.pnlCost,
54916
55404
  pnlEntries: data.pnl.pnlEntries,
55405
+ peakProfitPriceOpen: data.signal.peakProfit.priceOpen,
55406
+ peakProfitPriceClose: data.signal.peakProfit.priceClose,
55407
+ peakProfitPercentage: data.signal.peakProfit.pnlPercentage,
55408
+ peakProfitCost: data.signal.peakProfit.pnlCost,
55409
+ peakProfitEntries: data.signal.peakProfit.pnlEntries,
55410
+ maxDrawdownPriceOpen: data.signal.maxDrawdown.priceOpen,
55411
+ maxDrawdownPriceClose: data.signal.maxDrawdown.priceClose,
55412
+ maxDrawdownPercentage: data.signal.maxDrawdown.pnlPercentage,
55413
+ maxDrawdownCost: data.signal.maxDrawdown.pnlCost,
55414
+ maxDrawdownEntries: data.signal.maxDrawdown.pnlEntries,
54917
55415
  note: data.note,
54918
55416
  createdAt: data.timestamp,
54919
55417
  };
@@ -54938,12 +55436,24 @@ const CREATE_SIGNAL_SYNC_NOTIFICATION_FN = (data) => {
54938
55436
  exchangeName: data.exchangeName,
54939
55437
  signalId: data.signalId,
54940
55438
  currentPrice: data.currentPrice,
54941
- pnl: data.pnl,
55439
+ pnl: data.signal.pnl,
55440
+ maxDrawdown: data.signal.maxDrawdown,
55441
+ peakProfit: data.signal.peakProfit,
54942
55442
  pnlPercentage: data.pnl.pnlPercentage,
54943
55443
  pnlPriceOpen: data.pnl.priceOpen,
54944
55444
  pnlPriceClose: data.pnl.priceClose,
54945
55445
  pnlCost: data.pnl.pnlCost,
54946
55446
  pnlEntries: data.pnl.pnlEntries,
55447
+ peakProfitPriceOpen: data.signal.peakProfit.priceOpen,
55448
+ peakProfitPriceClose: data.signal.peakProfit.priceClose,
55449
+ peakProfitPercentage: data.signal.peakProfit.pnlPercentage,
55450
+ peakProfitCost: data.signal.peakProfit.pnlCost,
55451
+ peakProfitEntries: data.signal.peakProfit.pnlEntries,
55452
+ maxDrawdownPriceOpen: data.signal.maxDrawdown.priceOpen,
55453
+ maxDrawdownPriceClose: data.signal.maxDrawdown.priceClose,
55454
+ maxDrawdownPercentage: data.signal.maxDrawdown.pnlPercentage,
55455
+ maxDrawdownCost: data.signal.maxDrawdown.pnlCost,
55456
+ maxDrawdownEntries: data.signal.maxDrawdown.pnlEntries,
54947
55457
  cost: data.cost,
54948
55458
  position: data.position,
54949
55459
  priceOpen: data.priceOpen,
@@ -54971,12 +55481,24 @@ const CREATE_SIGNAL_SYNC_NOTIFICATION_FN = (data) => {
54971
55481
  exchangeName: data.exchangeName,
54972
55482
  signalId: data.signalId,
54973
55483
  currentPrice: data.currentPrice,
54974
- pnl: data.pnl,
55484
+ pnl: data.signal.pnl,
55485
+ maxDrawdown: data.signal.maxDrawdown,
55486
+ peakProfit: data.signal.peakProfit,
54975
55487
  pnlPercentage: data.pnl.pnlPercentage,
54976
55488
  pnlPriceOpen: data.pnl.priceOpen,
54977
55489
  pnlPriceClose: data.pnl.priceClose,
54978
55490
  pnlCost: data.pnl.pnlCost,
54979
55491
  pnlEntries: data.pnl.pnlEntries,
55492
+ peakProfitPriceOpen: data.signal.peakProfit.priceOpen,
55493
+ peakProfitPriceClose: data.signal.peakProfit.priceClose,
55494
+ peakProfitPercentage: data.signal.peakProfit.pnlPercentage,
55495
+ peakProfitCost: data.signal.peakProfit.pnlCost,
55496
+ peakProfitEntries: data.signal.peakProfit.pnlEntries,
55497
+ maxDrawdownPriceOpen: data.signal.maxDrawdown.priceOpen,
55498
+ maxDrawdownPriceClose: data.signal.maxDrawdown.priceClose,
55499
+ maxDrawdownPercentage: data.signal.maxDrawdown.pnlPercentage,
55500
+ maxDrawdownCost: data.signal.maxDrawdown.pnlCost,
55501
+ maxDrawdownEntries: data.signal.maxDrawdown.pnlEntries,
54980
55502
  position: data.position,
54981
55503
  priceOpen: data.priceOpen,
54982
55504
  priceTakeProfit: data.priceTakeProfit,
@@ -55082,11 +55604,23 @@ const CREATE_SIGNAL_INFO_NOTIFICATION_FN = (data) => ({
55082
55604
  totalEntries: data.data.totalEntries,
55083
55605
  totalPartials: data.data.totalPartials,
55084
55606
  pnl: data.data.pnl,
55607
+ maxDrawdown: data.data.maxDrawdown,
55608
+ peakProfit: data.data.peakProfit,
55085
55609
  pnlPercentage: data.data.pnl.pnlPercentage,
55086
55610
  pnlPriceOpen: data.data.pnl.priceOpen,
55087
55611
  pnlPriceClose: data.data.pnl.priceClose,
55088
55612
  pnlCost: data.data.pnl.pnlCost,
55089
55613
  pnlEntries: data.data.pnl.pnlEntries,
55614
+ peakProfitPriceOpen: data.data.peakProfit.priceOpen,
55615
+ peakProfitPriceClose: data.data.peakProfit.priceClose,
55616
+ peakProfitPercentage: data.data.peakProfit.pnlPercentage,
55617
+ peakProfitCost: data.data.peakProfit.pnlCost,
55618
+ peakProfitEntries: data.data.peakProfit.pnlEntries,
55619
+ maxDrawdownPriceOpen: data.data.maxDrawdown.priceOpen,
55620
+ maxDrawdownPriceClose: data.data.maxDrawdown.priceClose,
55621
+ maxDrawdownPercentage: data.data.maxDrawdown.pnlPercentage,
55622
+ maxDrawdownCost: data.data.maxDrawdown.pnlCost,
55623
+ maxDrawdownEntries: data.data.maxDrawdown.pnlEntries,
55090
55624
  note: data.note,
55091
55625
  notificationId: data.notificationId,
55092
55626
  scheduledAt: data.data.scheduledAt,