Forecasting Exchange Rates
Time Series data is vastly used across various domains for forecasting. Forecasting the future can be beneficial for the analysts and management in making better calculated decisions to maximise returns and minimise risks.
In this article,we will be demonstrating how we can forecast exchange rates. If you are new to finance and want to understand what exchange rates are then please go through: How do exchange rates work?
It provides a basic overview of market data. Exchange rates are dependent on a range of factors such as supply and demand, government policies, country’s growth rates etc.
Forecasting Exchange Rates
Recently, a number of technological advancements have been introduced that can forecast future time points quickly, efficiently and accurately. To get a detailed understanding on how Time Series Analysis and forecasting is done, please go through this article: Time Series Forecasting
After completing this tutorial, you will know:
- How to scrape the exchange rates from xe.com
- What is fbProphet, and how to use it
- How to build your own forecasting model using fbProphet.
Scraping Data from the web
Importing the libraries:
import pandas as pd
import datetime
from datetime import timedelta, date
Method for yielding date range:
def daterange(start_date, end_date): for n in range(int ((end_date - start_date).days)): yield start_date + timedelta(n)
Setting the start date & end date:
Here, we are setting the start date as 1st September, 2019 and end date as today's date, so that we can fetch the entire data within this range.start_date = date(2019, 9, 1) end_date = datetime.date.today()
Defining Pandas Dataframe and fetching all the data for Hong Kong Dollars to Any other currency:
I was concerned about Hong Kong Dollars to Indian Rupee conversion rates, hence I have used "HKD", you can use whatever you feel like
df = pd.DataFrame() for single_date in daterange(start_date, end_date): dfs = pd.read_html(f'https://www.xe.com/currencytables/?from=HKD&date={single_date.strftime("%Y-%m-%d")}')[0] dfs['Date'] = single_date.strftime("%Y-%m-%d") df = df.append(dfs)
Defining the Dataframe columns:
df.columns = ['Currency code', 'Currency name', 'Units per HKD', 'HKD per Unit', 'Date'] df.head()
Let say, we are trying to forecast the conversion rate of Hong Kong Dollars to Indian Rupee, then from the extracted data, we use a filter based on the Currency Code as "INR", so that just Indian Rupee data is extracted.
inr_df = df[df['Currency code'] == 'INR']
Check the data:
inr_df.head()
Plotting the graph:
inr_df.plot(x='Date', y='Units per HKD', figsize=(12, 8)
That's how the graph looks like for almost 13 months ranging from 1/09/2018 to 11/10/2019, accordingly the start date and end dates can be changed to fetch the entire data.
What is fbProphet?
You can read about Facebook Prophet here: Click here
Installation:pip install pystan pip install fbprophet
If the above steps, doesn't work, then try the below code in Anaconda Prompt:
conda install -c conda-forge fbprophet
Forecasting - Facebook Prophet
Prophet follows the sklearn model API. We create an instance of the Prophet class and then call it's fit and predict methods.
You can read about the Prophet API's here: Click HereFirst we'll import the data
import pandas as pd from fbprophet import Prophet import plotly.graph_objs as go import plotly.offline as py import numpy as np df= inr_df.drop(['Unnamed: 0', 'Currency code', 'Currency name', 'HKD per Unit'], axis=1) df = df.rename(columns={'Units per HKD': 'y', 'Date': 'ds'}) df['ds'] = pd.to_datetime(df['ds'], format='%d/%m/%Y') df.head(5)
Now, we perform a log transformation, just to make the time series stationary, and after forecasting is done, we can do the inverse transformation.
# to save a copy of the original data..you'll see why shortly. df['y_orig'] = df['y'] # log-transform of y df['y'] = np.log(df['y'])
We fit the model by instantiating a new
Prophet
object. Any settings to the forecasting procedure are passed into the constructor. Then you call itsfit
method and pass in the historical dataframe. Fitting should take 1-5 seconds.#instantiate Prophet model = Prophet() model.fit(df)
Predictions are then made on a dataframe with a column
ds
containing the dates for which a prediction is to be made. You can get a suitable dataframe that extends into the future a specified number of days using the helper methodProphet.make_future_dataframe
. By default it will also include the dates from the history, so we will see the model fit as well.future_data = model.make_future_dataframe(periods=30, freq = 'D') future_data.tail()
The
predict
method will assign each row infuture
a predicted value which it namesyhat
. If you pass in historical dates, it will provide an in-sample fit. Theforecast
object here is a new dataframe that includes a columnyhat
with the forecast, as well as columns for components and uncertainty intervals.forecast_data = model.predict(future_data) forecast_data[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail(5)
# make sure we save the original forecast data forecast_data_orig = forecast_data forecast_data_orig['yhat'] = np.exp(forecast_data_orig['yhat']) forecast_data_orig['yhat_lower'] = np.exp(forecast_data_orig['yhat_lower']) forecast_data_orig['yhat_upper'] = np.exp(forecast_data_orig['yhat_upper']) fig = model.plot(forecast_data_orig)
fig2 = model.plot_components(forecast_data_orig)
From the time series component graph, it's clear that there's an increasing trend, which means the value of HKD is somehow increasing linearly. Apart from that, it's quite visible that the seasonality is high during Tuesday's & Wednesday's (I Hope you figured out that these are the best days in the week for a money transfer - cheers!!)
Copy the log-transformed data to another column
df['y_log']=df['y'] df['y']=df['y_orig']
An interactive figure of the forecast can be created with plotly. You will need to install plotly separately, as it will not by default be installed with fbprophet
# Python from fbprophet.plot import plot_plotly import plotly.offline as py py.init_notebook_mode() fig = plot_plotly(model, forecast_data_orig) # This returns a plotly Figure py.iplot(fig)
If you want an offline graph, plotly provives an API named "offline", which we have already imported in the beginning of the tutorial, and we can use that feature to plot it in an interactive offline graph and can analyse deeply. The offline graph would open in a separate tab in your browser and would look like the below graph:
final_df = pd.DataFrame(forecast_data_orig) actual_chart = go.Scatter(y=df["y_orig"], name= 'Actual') predict_chart = go.Scatter(y=final_df["yhat"], name= 'Predicted') predict_chart_upper = go.Scatter(y=final_df["yhat_upper"], name= 'Predicted Upper') predict_chart_lower = go.Scatter(y=final_df["yhat_lower"], name= 'Predicted Lower') py.plot([actual_chart, predict_chart, predict_chart_upper, predict_chart_lower])
The beauty of Facebook Prophet is that, it predicts a range i.e. Predicted upper & Predicted lower, and as you can see from the graph, the Actual data lies between the upper & lower range almost throughout the data, that's the accuracy of using this algorithm. Irrespective of the minor spikes, the prediction range carries the Actual data throughout the graph.
Adding to this, the above model is just the basic code of it, we can definitely fine tune by inserting holidays, understanding and changing the daily/weekly/monthly/yearly seasonality and various other factors.
I hope this document provides you the basic idea on Foreign exchange rate data scraping from xe.com, along with the time series forecasting of the same data (Hong Kong Dollars to Indian Rupee rates), keep exploring our other posts, cheers!!
Disclaimer: The scraping from xe.com data shown above is against XE Currency’s Terms of Use. Use the codes just for self learning & practice and not for business.
- Zep Analytics
- Mar, 05 2022