我正试图对未来某个时间(例如90天)的股票波动做出预测。看来GARCH是为此使用的传统模型。
我已经在下面使用Python的arch
库实现了这一点。我所做的一切都在注释中进行了解释,运行代码唯一需要更改的是提供您自己的每日价格,而不是从我自己的API检索价格的地方。
import utils
import numpy as np
import pandas as pd
import arch
import matplotlib.pyplot as plt
ticker = 'AAPL' # Ticker to retrieve data for
forecast_horizon = 90 # Number of days to forecast
# Retrive prices from IEX API
prices = utils.dw.get(filename=ticker, source='iex', iex_range='5y')
df = prices[['date', 'close']]
df['daily_returns'] = np.log(df['close']).diff() # Daily log returns
df['monthly_std'] = df['daily_returns'].rolling(21).std() # Standard deviation across trading month
df['annual_vol'] = df['monthly_std'] * np.sqrt(252) # Annualize monthly standard devation
df = df.dropna().reset_index(drop=True)
# Convert decimal returns to %
returns = df['daily_returns'] * 100
# Fit GARCH model
am = arch.arch_model(returns[:-forecast_horizon])
res = am.fit(disp='off')
# Calculate fitted variance values from model parameters
# Convert variance to standard deviation (volatility)
# Revert previous multiplication by 100
fitted = 0.1 * np.sqrt(
res.params['omega'] +
res.params['alpha[1]'] *
res.resid**2 +
res.conditional_volatility**2 *
res.params['beta[1]']
)
# Make forecast
# Convert variance to standard deviation (volatility)
# Revert previous multiplication by 100
forecast = 0.1 * np.sqrt(res.forecast(horizon=forecast_horizon).variance.values[-1])
# Store actual, fitted, and forecasted results
vol = pd.DataFrame({
'actual': df['annual_vol'],
'model': np.append(fitted, forecast)
})
# Plot Actual vs Fitted/Forecasted
plt.plot(vol['actual'][:-forecast_horizon], label='Train')
plt.plot(vol['actual'][-forecast_horizon - 1:], label='Test')
plt.plot(vol['model'][:-forecast_horizon], label='Fitted')
plt.plot(vol['model'][-forecast_horizon - 1:], label='Forecast')
plt.legend()
plt.show()
对于Apple,这将产生以下情节:
很明显,拟合值一直远远低于实际值,这也导致该预测也被大大低估了(鉴于苹果在此测试期间的波动性异常高,因此这是一个不佳的例子,我尝试过的公司,该模型总是低估了拟合值。
我所做的一切都正确吗,GARCH模型不是很强大,还是很难建模?还是我犯了一些错误?