diff --git a/freqtrade/data/metrics.py b/freqtrade/data/metrics.py index 5538b72e5..b766f461d 100644 --- a/freqtrade/data/metrics.py +++ b/freqtrade/data/metrics.py @@ -352,6 +352,30 @@ def _calculate_annualized_ratio( # Define high (negative) ratio to be clear that this is NOT optimal. return -100.0 + +def _calculate_daily_returns_from_balance( + balance_history: pd.DataFrame, + date_col: str, + balance_col: str, +) -> pd.Series: + if ( + len(balance_history) == 0 + or date_col not in balance_history + or balance_col not in balance_history + ): + return pd.Series(dtype=float) + + wallet = balance_history.loc[:, [date_col, balance_col]].copy() + wallet = wallet.dropna(subset=[date_col, balance_col]).sort_values(date_col) + + if len(wallet) < 2: + return pd.Series(dtype=float) + + # Sample balance to daily end-of-day values to normalize variable snapshot frequency. + daily_balance = wallet.set_index(date_col)[balance_col].resample("1D").last().dropna() + return daily_balance.pct_change().dropna() + + def calculate_sortino( trades: pd.DataFrame, min_date: datetime | None, @@ -412,23 +436,7 @@ def calculate_sharpe_from_balance( :param balance_col: Column containing historical balance values :return: sharpe """ - if ( - len(balance_history) == 0 - or date_col not in balance_history - or balance_col not in balance_history - ): - return 0.0 - - wallet = balance_history.loc[:, [date_col, balance_col]].copy() - wallet[date_col] = pd.to_datetime(wallet[date_col], utc=True, errors="coerce") - wallet = wallet.dropna(subset=[date_col, balance_col]).sort_values(date_col) - - if len(wallet) < 2: - return 0.0 - - # Sample balance to daily end-of-day values to normalize variable snapshot frequency. - daily_balance = wallet.set_index(date_col)[balance_col].resample("1D").last().dropna() - daily_returns = daily_balance.pct_change().dropna() + daily_returns = _calculate_daily_returns_from_balance(balance_history, date_col, balance_col) if len(daily_returns) == 0: return 0.0