def calculate_rolling_statistics(returns: pd.Series,
window: int = 60) -> pd.DataFrame:
"""
Calcule les statistiques rolling
Args:
returns: Serie de returns
window: Fenetre (default: 60 jours)
Returns:
DataFrame avec rolling stats
"""
df = pd.DataFrame(index=returns.index)
# Rolling Sharpe (annualise)
rolling_mean = returns.rolling(window).mean() * 252
rolling_std = returns.rolling(window).std() * np.sqrt(252)
df['rolling_sharpe'] = (rolling_mean - 0.02) / rolling_std # Rf = 2%
# Rolling Volatility
df['rolling_volatility'] = rolling_std
# Rolling Return (annualise)
df['rolling_return'] = rolling_mean
# Rolling Win Rate
df['rolling_winrate'] = (returns > 0).rolling(window).mean()
return df
# Calculer rolling stats
rolling_df = calculate_rolling_statistics(backtest_df['strategy_returns'], window=60)
# Visualisation
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# Rolling Sharpe
ax1 = axes[0, 0]
ax1.plot(rolling_df.index, rolling_df['rolling_sharpe'], linewidth=2, color='navy')
ax1.axhline(y=0, color='red', linestyle='--', linewidth=1)
ax1.axhline(y=1, color='green', linestyle='--', linewidth=1, alpha=0.5)
ax1.fill_between(rolling_df.index, rolling_df['rolling_sharpe'], 0,
where=rolling_df['rolling_sharpe'] > 0, color='green', alpha=0.2)
ax1.fill_between(rolling_df.index, rolling_df['rolling_sharpe'], 0,
where=rolling_df['rolling_sharpe'] < 0, color='red', alpha=0.2)
ax1.set_ylabel('Sharpe Ratio', fontsize=12)
ax1.set_title('Rolling Sharpe Ratio (60j)', fontsize=14, fontweight='bold')
ax1.grid(True, alpha=0.3)
# Rolling Volatility
ax2 = axes[0, 1]
ax2.plot(rolling_df.index, rolling_df['rolling_volatility'] * 100,
linewidth=2, color='darkorange')
ax2.axhline(y=rolling_df['rolling_volatility'].mean() * 100, color='red',
linestyle='--', label=f"Mean: {rolling_df['rolling_volatility'].mean():.2%}")
ax2.set_ylabel('Volatilite (%)', fontsize=12)
ax2.set_title('Rolling Volatility (60j)', fontsize=14, fontweight='bold')
ax2.legend()
ax2.grid(True, alpha=0.3)
# Rolling Return
ax3 = axes[1, 0]
ax3.plot(rolling_df.index, rolling_df['rolling_return'] * 100,
linewidth=2, color='darkgreen')
ax3.axhline(y=0, color='red', linestyle='--', linewidth=1)
ax3.fill_between(rolling_df.index, rolling_df['rolling_return'] * 100, 0,
where=rolling_df['rolling_return'] > 0, color='green', alpha=0.2)
ax3.fill_between(rolling_df.index, rolling_df['rolling_return'] * 100, 0,
where=rolling_df['rolling_return'] < 0, color='red', alpha=0.2)
ax3.set_ylabel('Return Annualise (%)', fontsize=12)
ax3.set_title('Rolling Return (60j)', fontsize=14, fontweight='bold')
ax3.grid(True, alpha=0.3)
# Rolling Win Rate
ax4 = axes[1, 1]
ax4.plot(rolling_df.index, rolling_df['rolling_winrate'] * 100,
linewidth=2, color='purple')
ax4.axhline(y=50, color='red', linestyle='--', linewidth=1, label='50%')
ax4.set_ylabel('Win Rate (%)', fontsize=12)
ax4.set_title('Rolling Win Rate (60j)', fontsize=14, fontweight='bold')
ax4.legend()
ax4.grid(True, alpha=0.3)
for ax in axes.flat:
ax.set_xlabel('Date', fontsize=12)
plt.tight_layout()
plt.show()