Spaces:
Runtime error
Runtime error
| from __future__ import annotations | |
| import math | |
| import pandas as pd | |
| def max_drawdown(equity: pd.Series) -> float: | |
| if equity.empty: | |
| return 0.0 | |
| running_max = equity.cummax() | |
| drawdown = equity / running_max - 1 | |
| return float(drawdown.min()) | |
| def backtest_realized_vol_signal( | |
| prices: pd.Series, | |
| short_window: int = 10, | |
| long_window: int = 30, | |
| holding_days: int = 5, | |
| signal: str = "long_vol", | |
| ) -> dict: | |
| close = prices.dropna().astype(float) | |
| returns = close.pct_change().dropna() | |
| short_rv = returns.rolling(short_window).std() * math.sqrt(252) | |
| long_rv = returns.rolling(long_window).std() * math.sqrt(252) | |
| trades = [] | |
| equity = [1.0] | |
| index = 0 | |
| dates = list(returns.index) | |
| while index + holding_days < len(returns): | |
| current_date = dates[index] | |
| if pd.isna(short_rv.iloc[index]) or pd.isna(long_rv.iloc[index]): | |
| index += 1 | |
| equity.append(equity[-1]) | |
| continue | |
| vol_expanding = short_rv.iloc[index] > long_rv.iloc[index] | |
| enter = vol_expanding if signal == "long_vol" else not vol_expanding | |
| if not enter: | |
| index += 1 | |
| equity.append(equity[-1]) | |
| continue | |
| period_returns = returns.iloc[index + 1:index + 1 + holding_days] | |
| realized_move = float(period_returns.abs().sum()) | |
| signed_pnl = realized_move if signal == "long_vol" else -realized_move | |
| equity.append(equity[-1] * (1 + signed_pnl)) | |
| trades.append( | |
| { | |
| "entry_date": str(current_date), | |
| "exit_date": str(dates[index + holding_days]), | |
| "short_rv": float(short_rv.iloc[index]), | |
| "long_rv": float(long_rv.iloc[index]), | |
| "realized_abs_move": realized_move, | |
| "pnl_proxy": signed_pnl, | |
| } | |
| ) | |
| index += holding_days | |
| equity_series = pd.Series(equity) | |
| wins = [trade for trade in trades if trade["pnl_proxy"] > 0] | |
| return { | |
| "signal": signal, | |
| "short_window": short_window, | |
| "long_window": long_window, | |
| "holding_days": holding_days, | |
| "trade_count": len(trades), | |
| "win_rate": len(wins) / len(trades) if trades else 0.0, | |
| "total_return_proxy": float(equity_series.iloc[-1] - 1) if not equity_series.empty else 0.0, | |
| "max_drawdown_proxy": max_drawdown(equity_series), | |
| "avg_trade_pnl_proxy": ( | |
| sum(trade["pnl_proxy"] for trade in trades) / len(trades) | |
| if trades | |
| else 0.0 | |
| ), | |
| "trades": trades[:100], | |
| "limitations": [ | |
| "This is an underlying-price realized-volatility signal backtest, not a true option PnL backtest.", | |
| "It does not use historical option-chain prices, bid/ask spreads, margin, assignment, or delta hedging costs.", | |
| ], | |
| } | |