Volatility Measure using GARCH & Monte-Carlo Simulations | by Sarit Maitra | Towards Data Science

Risk measures are major factors in portfolio & fund management. Volatility and risks are interlinked. Highly volatile investments are prone to high risk and thus detrimental to short-term risk. Traditionally volatility plays an important role in measuring risk, however, volatility don’t follows the market variations. To estimate volatility, it is necessary to develop a model considering the movements of the volatility in the time-series e.g. asymmetric Garch models, like Tarch and Egarch model.
Here, we will explore as how to use GARCH, EGARCH, and GJR-GARCH models combined with Monte-Carlo simulations to built an VaR model. The leptokurtosis, clustering volatility and leverage effects characteristics of financial time-series justifies the GARCH modeling approach. The non-linear characteristic of the time-series will be used to check the Brownian motion and investigate into the temporal evolutionary patterns.
So, prior to GARCH modeling approach, we will employ Data-Modelling techniques involving Fractal Dimension (FD), Rescaled Range and Recurrence Quantification Analysis (RQA) to summarize the non-linear dynamics behavior of data and accomplish the study objective.
Hurst coefficient (H) is a characteristic of long-range dependence and is related to FD (FD + H = 2). Re-scaled (R/S) analysis is the central tool of fractal data modelling. Empirical studies (*1) showed that R/S brings superior results when compared with other methods in this category e.g. the analysis of auto-correlations, variance ratios, and spectral decomposition. It is the measure characterizing the divergence of time series defined as the range of the mean-centered values for a given duration (T) divided by the standard deviation for that duration [R/S = k * T(H)]; k is a constant that depends on the time series. H measures the long-term memory of a time series, characterizing it as either mean-reverting, trending or a random walk.
H < 0.5 indicating mean reversion
H > 0.5 indicating a trending time series and
H = 0.5 indicating a random walk.
The Recurrence quantification analysis (RQA) will be used to extract valuable insights from data through the quantification of dynamical systems by computing the measures like REC, DET, TT, and LAM.
We will explore how a GARCH model for risk evaluation can be used.
A crucial limitation of a GARCH model is the non-negativity constraints on its parameters are imposed to ensure the positivity of the conditional variance. Such constraints can create difficulties in estimating GARCH models. Therefore, Asymmetric GARCH model, popularly known as GJR-GARCH model can be used to deal with the limitation of Symmetric GARCH models. More so, exponential GARCH (EGARCH) will be introduced present potential improvements over the conventional GARCH models (4).
Let’s see what is stored in the data.
Crude oil prices in the past decades showing large fluctuations especially around the year 2008. It can be seen that, with multiple cliff-like increases and decrease, the price remained at a relative low level. A clear evidence of significant serial auto-correlation in the original data can be seen from auto-correlation plot. The shape of the QQ and Probability plots indicate that the process is close to normality but with heavy tails.
The frequently used form of simple returns is: r(t) = {p(t) — p(t-1)}/p(t-1) and log returns = ln(pt/p(t-1), pt the daily Crude price, r(t) is the daily return.
log return is considered here as daily return. The visual display of the original price and log return clearly justifies the use of log return with nearly constant mean.
The return series plot shows periods of high and low variability. A process of random and centered about zero can be seen in the plot. Both positive and negative returns with large amplitude fluctuation increase the difficulty of risk investment and management. The mean of daily oil returns is substantially around the zero-level horizon with apparent volatility clustering, indicating the presence of heteroscedasticity. The ACF is small, serially uncorrelated, but highly dependent. The shape of the QQ and Probability plots show no significant changes. Both positive and negative returns with large amplitude fluctuation increase the difficulty of risk investment and management.
sns.distplot(df.returns, color=’blue’) #density plotplt.title(“2000–2019 Crude Oil return frequency”)plt.xlabel(‘Possible range of data values’)# Pull up summary statisticsprint(df.returns.describe())
The skewness of returns (-0.119) and rightward deviation shows that the positive returns are more intensive than the negative returns, the kurtosis (7.042) reflecting and large range of oil volatility.
Skewness and kurtosis of the standard normal distribution are 0 and 3 respectively.
The value of Jarque-Bera test shows that the traditional normal distribution assumption is not suitable for the real distribution of Crude Oil returns.
ADF = ADF(df.returns)print(ADF.summary().as_text())kpss = KPSS(df.returns)print(kpss.summary().as_text())dfgls = DFGLS(df.returns)print(dfgls.summary().as_text())pp = PhillipsPerron(df.returns)print(pp.summary().as_text())za = ZivotAndrews(df.returns)print(za.summary().as_text())vr = VarianceRatio(df.returns, 12)print(vr.summary().as_text())
VR tests was performed to test whether the return series is a pure random walk versus having some predictability. We have compared here 1-month to 12-months returns. Rejection of the null with a negative test statistic VA(-11.07) indicates the presence of serial correlation in the time series. The tests of unit roots and stationarity with ADF, KPSS, DFGLS, PP and ZA statistics are all shown to be significant, indicating the application of the GARCH-type model to fit the return series is appropriate.
Ever since Mandelbrot had published his works on the application of R/S analysis to long-memory dependencies in time series (Mandelbrot, Wallis, 1969; Mandelbrot, 1972) and since Peters had presented his Fractal Market Hypothesis (Peters, 1991) as an alternative to commonly acknowledged Efficient Market Hypothesis, this approach is being examined with regard to financial time series.
We will now extended the investigation on stationarity using H. The H provides a way to measure the amount by which a financial time series deviates from a random walk.
closes_recent = df.Price[-2000:]plot(closes_recent); show()# calculate Hurst of recent priceslag1 = 2lags = range(lag1, 20)tau = [sqrt(std(subtract(closes_recent[lag:], closes_recent[:-lag]))) for lag in lags]plot(log(lags), log(tau)); show()m = polyfit(log(lags), log(tau), 1)hurst = m[0]*2print (‘hurst = ‘,hurst)
H(0.531) indicates of a random movement time series with long run dependence. The long memory in log returns justifies the GARCH models for the given series in this study.
time_series = TimeSeries(df.Price, embedding_dimension=2, time_delay=2)settings = Settings(time_series, computing_type=ComputingType.Classic, neighbourhood=FixedRadius(0.65), similarity_measure=EuclideanMetric,theiler_corrector=1)computation = RQAComputation.create(settings, verbose=True)result = computation.run()result.min_diagonal_line_length = 2result.min_vertical_line_length = 2result.min_white_vertical_line_lelngth = 2print(result)
Here, the low RR indicates a lower degree of periodicity and random behavior; moreover, low DET value indicating less deterministic nature. LAM value indicates laminarity in the process which is the alternation of phases of apparently periodic and chaotic dynamics. Though the findings from RQA also justified the implications of fractal modelling, however, by showing the auto regressing behavior, the non-linear dynamics rejected the Efficient Market Hypothesis justifying the usage of GARCH approach too.
It is always a good idea to scale the return by 100 before estimating GARCH-type models. This helps the optimizer converse since the scale of the volatility intercept is much closer to the scale of the other parameters in the model.
X = 100* df.returns
Let’s fit an ARCH model and plot the squared residual to examine the auto correlation.
gam = arch_model(Model.resid, p=2, o=0, q=2, dist=’StudentsT’)gres = gam.fit(update_freq=5, disp=’off’)print(gres.summary())tsplot(gres.resid**2, lags=30)
We can see a clear evidence of auto-correlation in squared residuals. Let’s fit a GARCH model and see how it performs. We will apply the procedure as follows:
Iterate through combinations of ARIMA(p, d, q) models to best fit the time series.
Pick the GARCH model orders according to the ARIMA model with lowest AIC.
Fit the GARCH(p, q) model to the time series.
Examine the model residuals and squared residuals for auto-correlation
def _get_best_model(TS): best_aic = np.inf  best_order = None best_mdl = None pq_rng = range(5) # [0,1,2,3,4,5] d_rng = range(2) # [0,1] for i in pq_rng: for d in d_rng: for j in pq_rng: try: tmp_mdl = smt.ARIMA(TS, order=(i,d,j)).fit( method=’mle’, trend=’nc’ ) tmp_aic = tmp_mdl.aic if tmp_aic < best_aic: best_aic = tmp_aic best_order = (i, d, j) best_mdl = tmp_mdl except: continue print(‘aic: {:6.2f} | order: {}’.format(best_aic, best_order))  return best_aic, best_order, best_mdl TS = Xres_tup = _get_best_model(TS)
#aic: 22462.01 | order: (2, 0, 2)
So, we find here that, the best model is ARIMA(2,0,2). Now we plot the residuals to decide if they possess evidence of conditional heteroskedastic behavior.
am = arch_model(X, p=2, q=2, o=1,power=2.0, vol=’Garch’, dist=’StudentsT’)res = am.fit(update_freq=5)print(res.summary())
am = arch_model(X, p=2, q=2, o=1,power=2.0, vol=’Garch’, dist=’StudentsT’)res = am.fit(update_freq=5)print(res.summary())eam = arch_model(X, p=2,q=2, o=1, power=2.0, vol=’EGARCH’, dist=’StudentsT’)eres = eam.fit(update_freq=5)print(res.summary())gjam = arch_model(X, p=2, o=1, q=2, power=2.0, dist=’StudentsT’)gjres = gjam.fit(update_freq=5, disp=’off’)print(gjres.summary())
The output from all 3 GARCH models are displayed in table format. Omega (ω) is white noise, alpha and beta are parameters of the model. Also, α [1] + β [1] < 1 indicates a stable model. The EGARCH model appeared to be the best of the three here, however, the difference is minor between GARCH and EGARCH.
Though I have experimented with all the available data; however, it would a good idea to split the data in train/test and obtain MSE/MAE/RMSE results to compare the best model fit.
The standardized residuals are calculated by dividing the residuals by the conditional volatility.
std_resid = res_normal.resid / res_normal.conditional_volatilityunit_var_resid = res_normal.resid / res_normal.resid.std()
The standardized residuals and the conditional volatility plot showing some errors however, not large in magnitude.
plt.xlim(-2, 2)sns.kdeplot(squared_resid, shade=True)sns.kdeplot(std_resid, shade=True)sns.kdeplot(unit_var_resid, shade=True)plt.legend([‘Squared Residual’, “Unit variance residual”, “Std Residual”], loc=’best’)plt.show()
The standardized residuals are also plotted along with the non- standardized, but scaled residuals. The squared residuals are more peaked in the center indicating that the distribution is somewhat heavier tailed than that of the standardized residuals. Let’s check the ACF plot.
plot_acf(std_resid)plt.title(‘Standardized residuals’)pyplot.show()
Looks like some of the spikes are out of the shaded confidence zone. Let’s view the squared residuals.
plot_acf(squared_resid)plt.title(‘Squared residuals’)pyplot.show()
Squared residuals displays the data points are within the blue shaded confidence zone (95%) indicating model fitment.
am = arch_model(X,mean=’HAR’,lags=[1,5,22],vol=’Constant’) sim_data = am.simulate([0.1,0.4,0.3,0.2,1.0], 250)sim_data.index = pd.date_range(‘2019–01–01’,periods=250) am = arch_model(sim_data[‘data’],mean=’HAR’,lags=[1,5,22], vol=’Constant’) res = am.fit()fig = res.hedgehog_plot(type=’mean’)
The hedgehog plot showing the forecasting methods across the year 2019. The orange lines indicating the forecasts at different time intervals.
Simulation-based method was used to obtain the confidence intervals for forecasted volatility from EGARCH is simulated here. This process was repeated many times to obtain an ensemble of volatility forecasts. The point of forecast was computed by averaging over the simulations, and a 95% confidence interval was computed using the 2.5% and 97.5% quantiles of the simulation distribution, respectively. Considering the mean return input (mu) is 0.0292 and the annual volatility input (vol) is (26.48) * sqrt 252 = 37.37%.
vol = df.returns.std()*sqrt(252)print (“Annual Volatility =”, str(round(vol,4)*100)+”%”)#Define VariablesS = df.Price[-1] #starting stock price (i.e. last available real stock price)T = 252 #Number of trading daysmu = 0.0622 #Returnvol = 0.3737 #Volatilitydaily_returns=np.random.normal((1+mu)**(1/T),vol/sqrt(T),T)price_list = [S] price_list.append(price_list[-1]*x)#Generate Plots — price series and histogram of daily returnsplt.plot(price_list)plt.show()plt.hist(daily_returns-1, 100) plt.show()
Above top most Fig displays a single simulation of potential price series evolution over a trading year (252 days), based upon a draw of random daily returns that follow a normal distribution. The second plot is a histogram of those random daily returns over the year period. However, the real insight can be gained from running tens of thousands of simulations, with each run producing a different series of potential price evolution based upon the same stock characteristics (mu and vol).
#set up empty list to hold our ending values for each simulated price seriesresult = []S = df.Price[-1] #starting stock price (i.e. last available real stock price)T = 252 #Number of trading daysmu = 0.0622 #Returnvol = 0.3737 #Volatility#choose number of runs to simulate — I have chosen 10,000for i in range(10000): #create list of daily returns using random normal distribution daily_returns= np.random.normal((1+mu)**(1/T),vol/sqrt(T),T)  #set starting price and create price series generated by above random daily returns price_list = [S]  for x in daily_returns: price_list.append(price_list[-1]*x)#append the ending value of each simulated run to the empty list we created at the beginning result.append(price_list[-1])plt.figure(figsize=(10,6))plt.hist(result,bins= 100)plt.axvline(np.percentile(result,5), color=’r’, linestyle=’dashed’, linewidth=2)plt.axvline(np.percentile(result,95), color=’r’, linestyle=’dashed’, linewidth=2)plt.figtext(0.6,0.8,s=”Start price: $%.2f” %S)plt.figtext(0.6,0.7,”Mean final price: $58.44")plt.figtext(0.6,0.6,”5% quantile: $29.72")plt.figtext(0.15,0.6, “95% quantile: $101.75”)plt.title(u”Final price distribution for Crude stock”, weight=’bold’, fontsize=12)plt.show()
The results here would be slightly different due to the fact that these are simulations of random daily return draws. Because of the paths included in each simulation, the more the mean value tend towards the mean return used in “mu” input. The below histogram displays a couple of quantiles of the potential price distribution, to get an idea of the likelihood of very high or very low returns.
It is quite clear that, there is 5% chance that the Crude stock price will end up below around $ 29.72 and 5% chance it will finish above $ 101.75.
Here, we have investigated and presented a hybrid time-varying long memory GARCH and simulations based volatility model. Empirical evidences suggest that Crude data with Brownian motion tend to show some degree of predictability in their temporal dynamics.
Though VaR can be measured suing analytical approach, as-well-as simulations; we have used Monte-Carlo simulations to check the robustness of the results. The output from Monte Carlo simulations show that even after controlling for extraneous factors the results remain robust. So, the findings have provided an excellent hybrid EGARCH and Monte-Carlo simulations based model considering the volatility features such as volatility clustering and asymmetry, time-varying risk and heavy tail distribution to measure the crude oil price.
I can be reached here .
References:
(1)Mandelbrot, B. B., & Wallis, J. R. (1969). Computer experiments with fractional Gaussian noises: Part 2, rescaled ranges and spectra. Water resources research, 5(1), 242–259
(2) Dutta, A. (2014). Modelling volatility: symmetric or asymmetric garch models. Journal of Statistics: Advances in Theory and Applications, 12(2), 99–108.
(3) Glosten, L., Jagannathan, R. and Runkle, D. (1993) On the relation between expected return on stocks, Journal of Finance, 48, 1779–801.
(4) Nelson, D. (1991) Conditional heteroskedasticity in asset returns: a new approach, Econometrica, 59, 349–70.
(5) Peters, E. E. (1991), Chaos and Order in the Capital Markets: a New View of Cycles, Prices, and Market Volatility, Wiley, New York.