Estimating Currency Volatility Using GARCH | by Michael Grogan | Towards Data Science

Disclaimer: This article is written on an “as is” basis and without warranty. It was written with the intention of providing an overview of data science concepts, and should not be interpreted as investment advice, or any other sort of professional advice.
Asset prices have a high degree of stochastic trends inherent in the time series. In other words, price fluctuations are subject to a large degree of randomness, and therefore it is very difficult to forecast asset prices using traditional time series models such as ARIMA.
Moreover, with much of the trading done on an algorithmic basis today — prices are constantly adjusting on the basis of such forecasts — making it quite hard to exploit an advantage in the markets.
For instance, suppose I build a time series model to predict rainfall in a city for the next three months. My time series model could have a strong degree of accuracy as the forecasts will not influence rainfall levels in the future. However, if everyone uses an ARIMA model to predict asset price fluctuations for the next three months — then subsequent trading on the basis of those forecasts will directly influence previous forecasts — rendering them invalid in many cases.
As a result, it is common to model projected volatility of an asset price in the financial markets — as opposed to forecasting projected price outright.
Let’s see how this can be accomplished using Python. A GARCH model is used to forecast volatility for the EUR/USD and GBP/USD currency pairs, using data from January 2017 — January 2018.
The data is sourced from FRED using the Quandl library:
eurusd = quandl.get("FRED/DEXUSEU", start_date='2017-01-01', end_date='2018-01-01', api_key='enter_api_key')gbpusd = quandl.get("FRED/DEXUSUK", start_date='2017-01-01', end_date='2018-01-01', api_key='enter_api_key')
The series are converted to logarithmic format to smooth out the time series:
The data is then first-differenced to approximate a Gaussian distribution.
Dickey-Fuller tests show a p-value of 0 for both series — indicating that we reject the null hypothesis that a unit root is present at the 5% level of significance, i.e. stationarity or trend stationarity is indicated as being present in the model.
EUR/USD: Dickey-Fuller Test Results
>>> result = ts.adfuller(data, 1)>>> result(-16.26123019770431, 3.564065405943774e-29, 0, 247, {'1%': -3.457105309726321,  '5%': -2.873313676101283,  '10%': -2.5730443824681606}, -1959.704886024891)
GBP/USD: Dickey-Fuller Test Results
>>> result = ts.adfuller(data, 1)>>> result(-12.380335699861567, 5.045829408723097e-23, 1, 246, {'1%': -3.457215237265747,  '5%': -2.873361841566324,  '10%': -2.5730700760129555}, -1892.8308007824835)
Additionally, a visual screening of QQ plots show that the series now largely follow a normal distribution:
EUR/USD: QQ Plot
GBP/USD: QQ Plot
A GARCH(1,1) model is built to predict the volatility for the last 30 days of trading data for both currency pairs. The previous data is used as the training set for the GARCH model.
# split into train/testn_test = 30train, test = data[:-n_test], data[-n_test:]# define modelmodel = arch_model(train, mean='Zero', vol='GARCH', p=1, q=1)
The predictions are generated as follows:
# fit modelmodel_fit = model.fit()# forecast the test setyhat = model_fit.forecast(horizon=n_test)
Now, let’s compare the predicted variance with the actual 5-day rolling variance across the test set.
Predicted Variance
test.rolling(window=5).var().plot(style='g')pyplot.title("5-day Rolling Variance")
5-day Rolling Variance
pyplot.plot(yhat.variance.values[-1, :])pyplot.title("Predicted Variance")pyplot.show()
We see that the GARCH model predicts a drop in volatility for the last 30 days (as measured by variance) — this is confirmed by a visual inspection of the actual 5-day rolling variance.
Let’s have a look at the comparisons across the GBP/USD.
Predicted Variance
5-day Rolling Variance
We can see that while the scale for the predicted variance is much narrower than the actual 5-day rolling variance — both instances are predicting a decrease in variance across the 30-day test period.
This corresponds with what we actually observe — there was little movement in both the EUR/USD and GBP/USD currency pairs in December 2017 relative to that of other months in the trading year.
This has been an illustration of how GARCH can be used to model time series volatility.
Hope you found the article useful, and any questions or feedback are greatly appreciated.
Machine Learning Mastery: How to Model Volatility with ARCH and GARCH for Time Series Forecasting in Python