Add improved vol calculation.
This commit is contained in:
@@ -133,11 +133,37 @@ def analyze_trends(df):
|
|||||||
return position_returns
|
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(
|
def project_prices(
|
||||||
df, days_forward=365, simulations=1000, confidence_levels=[0.95, 0.68]
|
df, days_forward=365, simulations=1000, confidence_levels=[0.95, 0.68]
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Project future Bitcoin prices using Monte Carlo simulation.
|
Project future Bitcoin prices using Monte Carlo simulation.
|
||||||
|
Now with enhanced volatility calculation.
|
||||||
"""
|
"""
|
||||||
# Calculate log returns for volatility estimation
|
# Calculate log returns for volatility estimation
|
||||||
df = df.copy()
|
df = df.copy()
|
||||||
@@ -170,19 +196,23 @@ def project_prices(
|
|||||||
[cycle_trends.get(day, cycle_trends.mean()) for day in future_cycle_days]
|
[cycle_trends.get(day, cycle_trends.mean()) for day in future_cycle_days]
|
||||||
)
|
)
|
||||||
|
|
||||||
# Calculate volatility using recent data
|
# Calculate enhanced volatility
|
||||||
recent_volatility = df["Log_Return"].tail(90).std()
|
volatility = calculate_volatility(df)
|
||||||
|
|
||||||
# Run Monte Carlo simulation
|
# Run Monte Carlo simulation with enhanced volatility
|
||||||
np.random.seed(42) # For reproducibility
|
np.random.seed(42)
|
||||||
simulated_paths = np.zeros((days_forward, simulations))
|
simulated_paths = np.zeros((days_forward, simulations))
|
||||||
|
|
||||||
for sim in range(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(
|
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)
|
cumulative_returns = np.cumsum(returns)
|
||||||
price_path = last_price * np.exp(cumulative_returns)
|
price_path = last_price * np.exp(cumulative_returns)
|
||||||
simulated_paths[:, sim] = price_path
|
simulated_paths[:, sim] = price_path
|
||||||
|
|||||||
Reference in New Issue
Block a user