Springboard Foundation OF Data Science:
Time Series Analysis of
the EUR/GBP currency pair

Application of the ARIMA model for forecasting of daily closing exchange rates

Audrey Ekuban

Types Of Analysis Used In Forex

Forex analysis : determine whether to buy or sell a currency pair

Fundamental Analysis

Fundamental analysis : monitoring of factors, such as interest rates, unemployment rates, gross domestic product (GDP) and many other economic releases that come out of the countries in question.

Technical Analysis

Technical analysis : evaluation by analysing statistics generated by market activity, such as past prices and volume.

Based on three assumptions:

  1. The market discounts everything.
  2. Price moves in trends.
  3. History tends to repeat itself.

Time Series Analysis

Two main goals: Identifying the nature of a sequence of observations and predicting future values using historical observations (forecasting).

Generally, two general components of Time series patterns: Trend and Seasonality. The trend is a linear or non-linear component and it does not repeat within the time range. The Seasonality repeats itself in systematic intervals over time.

A stationary time series: one whose statistical properties such as mean, variance, autocorrelation, etc. are all constant over time. The stationarized series can be prediced as the properties will be the same in the future as they have been in the past.

Autoregressive Integrated Moving Average (ARIMA): A statistical analysis model that uses time series data to predict future trends. It is a form of regression analysis that seeks to predict future movements along the seemingly random walk taken by stocks and the financial market by examining the differences between values in the series instead of using the actual data values. Lags of the differenced series are referred to as “autoregressive” and lags within forecasted data are referred to as “moving average. (Investopdia)”

Data Preparation

The data was downloaded using R script from www.forexite.com.The website provides intraday data going back to 2001

As the downloaded files contained a number of currency pairs an R script was used to extract the EUR/GBP currency pairs into a single file

Data consists of Open, High, Low and Close prices; Close prices were extracte from the file

The data is a weakly regular time series i.e. there was some missing data which was due to the FOREX market being closed.

Converting the data to a Time Series object in R created a strictly regular time series and this is what was used in the analysis

R Packages used: ggfortify, xts, forecast, tseries, ggplot2, zoo, timeDate

The Training set contained 3000 data points and the test set contained 1789 data points

Data Plot

The data shows that during the 2007/2008 Financial crisis GBP was at is weakest point against EUR.

Closing Price Plot using Time Index

# Focus on closing prices
EURGBP.price = EURGBP.ts.daily[,'Close']

autoplot(as.zoo(EURGBP.price), ts.colour = 'blue') +
  ggtitle('EURGBP Closing Prices') + xlab('Time Index') + ylab('price')

Time Series Identification

# Split the time series into Training and Testing
EURGBP.training = window(EURGBP.price, 1, 3000)
EURGBP.test = window(EURGBP.price, 3000)

autoplot(as.zoo(EURGBP.training), ts.colour = 'blue') +
  ggtitle('Training Data') + xlab('Time Index') + ylab('Closing Price')

Acf(EURGBP.training)

tseries::kpss.test(EURGBP.training)
## 
##  KPSS Test for Level Stationarity
## 
## data:  EURGBP.training
## KPSS Level = 16.974, Truncation lag parameter = 12, p-value = 0.01

Transform the data and examine

lambda = forecast::BoxCox.lambda(EURGBP.training,lower=-2)
transformedPrices = forecast::BoxCox(EURGBP.training, lambda)

autoplot(as.zoo(transformedPrices), ts.colour = 'blue') +
  ggtitle('Training Data') + xlab('Time Index') + ylab('transformed Closing Price')

Acf(transformedPrices)

tseries::kpss.test(transformedPrices)
## 
##  KPSS Test for Level Stationarity
## 
## data:  transformedPrices
## KPSS Level = 17.857, Truncation lag parameter = 12, p-value = 0.01

Take 1st differences of the transformed data

diffPrices = diff(transformedPrices)
autoplot(as.zoo(diffPrices), ts.colour = 'blue') +
  ggtitle('First Difference Training Data') + xlab('Time Index') + ylab('transformed Closing Price')

Acf(diffPrices)

tseries::kpss.test(diffPrices)
## 
##  KPSS Test for Level Stationarity
## 
## data:  diffPrices
## KPSS Level = 0.056454, Truncation lag parameter = 12, p-value =
## 0.1

Model Identification and Estimation

auto.arima(transformedPrices)
## Series: transformedPrices 
## ARIMA(2,1,2)                    
## 
## Coefficients:
##          ar1      ar2      ma1     ma2
##       1.3409  -0.9536  -1.3392  0.9350
## s.e.  0.0170   0.0284   0.0206  0.0315
## 
## sigma^2 estimated as 5.744e-05:  log likelihood=10388.7
## AIC=-20767.4   AICc=-20767.38   BIC=-20737.37
pacf(diffPrices)

# Use acf rather tha Acf
acf(diffPrices)

Increase lags in differenced data

diffPrices = diff(transformedPrices, lag = 2, diff = 1)

pacf(diffPrices)

# Use acf rather tha Acf
acf(diffPrices)

auto.arima(transformedPrices, approximation=FALSE, stepwise=FALSE, max.order=15)
## Series: transformedPrices 
## ARIMA(3,1,2)                    
## 
## Coefficients:
##          ar1      ar2     ar3      ma1     ma2
##       1.3705  -1.0046  0.0196  -1.3488  0.9618
## s.e.  0.0249   0.0306  0.0189   0.0168  0.0203
## 
## sigma^2 estimated as 5.742e-05:  log likelihood=10389.91
## AIC=-20767.83   AICc=-20767.8   BIC=-20731.79
AIC(Arima(transformedPrices, c(3,1,2)),
    Arima(transformedPrices, c(4,1,3)),
    Arima(transformedPrices, c(5,1,4)))
##                                      df       AIC
## Arima(transformedPrices, c(3, 1, 2))  6 -20767.83
## Arima(transformedPrices, c(4, 1, 3))  8 -20756.21
## Arima(transformedPrices, c(5, 1, 4)) 10 -20769.68

Forecasting

testTransformedPrices = forecast::BoxCox(EURGBP.test, lambda)

transformedPrices.fit <- Arima(transformedPrices, c(3,1,2))
ggtsdiag(transformedPrices.fit)

Apply model to Testing Data

testTransformedPrices.fit = Arima(testTransformedPrices, model=transformedPrices.fit)
ggtsdiag(testTransformedPrices.fit)

Transformed Predicted and Testing Data

accuracy(fitted(testTransformedPrices.fit), testTransformedPrices)
##                     ME        RMSE         MAE         MPE     MAPE
## Test set -3.920594e-05 0.006561965 0.004697599 -0.02400249 1.988625
##                 ACF1 Theil's U
## Test set 0.003043687  1.002799

Untransformed Predicted and Testing Data

fittedPrices = forecast::InvBoxCox(fitted(testTransformedPrices.fit), lambda)