| """Performance metrics for backtest results.""" | |
| from __future__ import annotations | |
| import numpy as np | |
| import pandas as pd | |
| def annualized_return(daily_returns: pd.Series) -> float: | |
| return float((1 + daily_returns).prod() ** (252 / max(len(daily_returns), 1)) - 1) | |
| def sharpe_ratio(daily_returns: pd.Series, rf: float = 0.0) -> float: | |
| excess = daily_returns - rf / 252 | |
| return float(excess.mean() / (excess.std() + 1e-8) * np.sqrt(252)) | |
| def max_drawdown(equity_curve: pd.Series) -> float: | |
| peak = equity_curve.cummax() | |
| dd = equity_curve / peak - 1 | |
| return float(dd.min()) | |
| def summarize_returns(daily_returns: pd.Series) -> dict: | |
| equity = (1 + daily_returns).cumprod() | |
| return { | |
| "ann_return": annualized_return(daily_returns), | |
| "sharpe": sharpe_ratio(daily_returns), | |
| "max_drawdown": max_drawdown(equity), | |
| "total_return": float(equity.iloc[-1] - 1) if len(equity) else np.nan, | |
| } | |