Skip to content

Commit 5da9019

Browse files
committed
Fix iso format check
1 parent 7f3af1e commit 5da9019

File tree

1 file changed

+25
-27
lines changed

1 file changed

+25
-27
lines changed

investing_algorithm_framework/domain/backtesting/backtest_metrics.py

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -206,14 +206,21 @@ def __post_init__(self):
206206
def to_dict(self) -> dict:
207207
"""
208208
Convert the BacktestMetrics instance to a dictionary.
209+
Ensures all datetime values are serialized to ISO format, but
210+
leaves strings unchanged.
209211
210212
Returns:
211213
dict: A dictionary representation of the BacktestMetrics instance.
212214
"""
215+
216+
def ensure_iso(value):
217+
return value.isoformat() \
218+
if hasattr(value, "isoformat") else value
219+
213220
return {
214-
"backtest_start_date": self.backtest_start_date.isoformat(),
215-
"backtest_end_date": self.backtest_end_date.isoformat(),
216-
"equity_curve": [(value, date.isoformat())
221+
"backtest_start_date": ensure_iso(self.backtest_start_date),
222+
"backtest_end_date": ensure_iso(self.backtest_end_date),
223+
"equity_curve": [(value, ensure_iso(date))
217224
for value, date in self.equity_curve],
218225
"final_value": self.final_value,
219226
"total_net_gain": self.total_net_gain,
@@ -223,24 +230,23 @@ def to_dict(self) -> dict:
223230
"total_loss": self.total_loss,
224231
"total_loss_percentage": self.total_loss_percentage,
225232
"cumulative_return": self.cumulative_return,
226-
"cumulative_return_series": [(value, date.isoformat())
233+
"cumulative_return_series": [(value, ensure_iso(date))
227234
for value, date in
228235
self.cumulative_return_series],
229236
"cagr": self.cagr,
230237
"sharpe_ratio": self.sharpe_ratio,
231-
"rolling_sharpe_ratio": [
232-
(value, date.isoformat())
233-
for value, date in self.rolling_sharpe_ratio
234-
],
238+
"rolling_sharpe_ratio": [(value, ensure_iso(date))
239+
for value, date in
240+
self.rolling_sharpe_ratio],
235241
"sortino_ratio": self.sortino_ratio,
236242
"calmar_ratio": self.calmar_ratio,
237243
"profit_factor": self.profit_factor,
238244
"annual_volatility": self.annual_volatility,
239-
"monthly_returns": [(value, date.isoformat())
245+
"monthly_returns": [(value, ensure_iso(date))
240246
for value, date in self.monthly_returns],
241-
"yearly_returns": [(value, date.isoformat())
247+
"yearly_returns": [(value, ensure_iso(date))
242248
for value, date in self.yearly_returns],
243-
"drawdown_series": [(value, date.isoformat())
249+
"drawdown_series": [(value, ensure_iso(date))
244250
for value, date in self.drawdown_series],
245251
"max_drawdown": self.max_drawdown,
246252
"max_drawdown_absolute": self.max_drawdown_absolute,
@@ -251,25 +257,19 @@ def to_dict(self) -> dict:
251257
"exposure_ratio": self.exposure_ratio,
252258
"cumulative_exposure": self.cumulative_exposure,
253259
"average_trade_gain": self.average_trade_gain,
254-
"average_trade_gain_percentage":
255-
self.average_trade_gain_percentage,
260+
"average_trade_gain_percentage": self.average_trade_gain_percentage,
256261
"average_trade_loss": self.average_trade_loss,
257-
"average_trade_loss_percentage":
258-
self.average_trade_loss_percentage,
262+
"average_trade_loss_percentage": self.average_trade_loss_percentage,
259263
"average_trade_return": self.average_trade_return,
260-
"average_trade_return_percentage":
261-
self.average_trade_return_percentage,
264+
"average_trade_return_percentage": self.average_trade_return_percentage,
262265
"median_trade_return": self.median_trade_return,
263-
"median_trade_return_percentage":
264-
self.median_trade_return_percentage,
266+
"median_trade_return_percentage": self.median_trade_return_percentage,
265267
"number_of_positive_trades": self.number_of_positive_trades,
266268
"percentage_positive_trades": self.percentage_positive_trades,
267269
"number_of_negative_trades": self.number_of_negative_trades,
268270
"percentage_negative_trades": self.percentage_negative_trades,
269-
"best_trade": self.best_trade.to_dict()
270-
if self.best_trade else None,
271-
"worst_trade": self.worst_trade.to_dict()
272-
if self.worst_trade else None,
271+
"best_trade": self.best_trade.to_dict() if self.best_trade else None,
272+
"worst_trade": self.worst_trade.to_dict() if self.worst_trade else None,
273273
"average_trade_duration": self.average_trade_duration,
274274
"average_trade_size": self.average_trade_size,
275275
"number_of_trades": self.number_of_trades,
@@ -278,10 +278,8 @@ def to_dict(self) -> dict:
278278
"percentage_winning_months": self.percentage_winning_months,
279279
"percentage_winning_years": self.percentage_winning_years,
280280
"average_monthly_return": self.average_monthly_return,
281-
"average_monthly_return_losing_months":
282-
self.average_monthly_return_losing_months,
283-
"average_monthly_return_winning_months":
284-
self.average_monthly_return_winning_months,
281+
"average_monthly_return_losing_months": self.average_monthly_return_losing_months,
282+
"average_monthly_return_winning_months": self.average_monthly_return_winning_months,
285283
"best_month": self.best_month,
286284
"best_year": self.best_year,
287285
"worst_month": self.worst_month,

0 commit comments

Comments
 (0)