Add improved vol calculation.

This commit is contained in:
sam
2024-11-15 01:22:16 -08:00
parent 588c4a8fa4
commit 36eda3eb3e
+37 -7
View File
@@ -133,11 +133,37 @@ def analyze_trends(df):
return position_returns
def calculate_volatility(df, short_window=30, medium_window=90, long_window=180):
"""
Calculate volatility using multiple timeframes and exponential weighting.
Returns a more nuanced estimate of current market volatility.
"""
df = df.copy()
# Calculate log returns if not already present
if "Log_Return" not in df.columns:
df["Log_Price"] = np.log(df["Close"])
df["Log_Return"] = df["Log_Price"].diff()
# Calculate exponentially weighted volatilities for different timeframes
short_vol = df["Log_Return"].ewm(span=short_window).std().iloc[-1]
medium_vol = df["Log_Return"].ewm(span=medium_window).std().iloc[-1]
long_vol = df["Log_Return"].ewm(span=long_window).std().iloc[-1]
# Blend the estimates with more weight on recent data
base_vol = 0.5 * short_vol + 0.3 * medium_vol + 0.2 * long_vol
# Scale up volatility to target ~68% coverage
volatility_scale = 1.2
return base_vol * volatility_scale
def project_prices(
df, days_forward=365, simulations=1000, confidence_levels=[0.95, 0.68]
):
"""
Project future Bitcoin prices using Monte Carlo simulation.
Now with enhanced volatility calculation.
"""
# Calculate log returns for volatility estimation
df = df.copy()
@@ -170,19 +196,23 @@ def project_prices(
[cycle_trends.get(day, cycle_trends.mean()) for day in future_cycle_days]
)
# Calculate volatility using recent data
recent_volatility = df["Log_Return"].tail(90).std()
# Calculate enhanced volatility
volatility = calculate_volatility(df)
# Run Monte Carlo simulation
np.random.seed(42) # For reproducibility
# Run Monte Carlo simulation with enhanced volatility
np.random.seed(42)
simulated_paths = np.zeros((days_forward, simulations))
for sim in range(simulations):
# Generate random returns using cycle-aware expected returns
# Generate random returns with slight skew based on expected returns
skew = np.sign(expected_returns) * 0.1 # Small skew in direction of trend
returns = np.random.normal(
loc=expected_returns, scale=recent_volatility, size=days_forward
loc=expected_returns + skew * volatility,
scale=volatility,
size=days_forward,
)
# Since we're using log returns, we can simply sum them
# Calculate price path
cumulative_returns = np.cumsum(returns)
price_path = last_price * np.exp(cumulative_returns)
simulated_paths[:, sim] = price_path