Introduction to forecasting Philippine stock prices using Facebook’s Prophet
By: Lorenzo Ampil
Tags: Stock Market, Forecasting, Data Science, Simulation

Introduction to forecasting Philippine stock prices using Facebook’s Prophet

A basic python workflow for predicting the stock price of the Philippine company, Jollibee Food Corp (JFC)

I’ve been into stock trading in the Philippines since I was in college and was immediately convinced that this is a field where forecasting models would be very useful. Why? Because your ability to make money in the stock market is dependent on your ability to predict what the price is going to be in the future.

In this post, I will demonstrate a quick way to forecast the daily closing price of a Philippine stock, Jollibee Foods Corporation (JFC), using the powerful Prophet package on python. Prophet is an open source forecasting tool made by Facebook that speeds up the standard forecasting workflow from something that typically takes days or weeks to something that takes as little as a few minutes (assuming you already have data in the correct format).

All relevant data and code can be found in the time-series directory of this repo.

We will follow the workflow below:

Install and import the necessary packages Get the data Plot the time series Train the Prophet model Predict the future! Assess accuracy

Let’s get started!

1. Install and import the necessary packages

Just Prophet + the basics.

# Run these on your terminal

pip install pandas

pip install datetime

pip install fbprophet

pip install numpy

pip install matplotlib # Alternatively, you can run these from jupyter this way

!pip install pandas

!pip install datetime

!pip install fbprophet

!pip install numpy

!pip install matplotlib

2. Get the data

All we need is a file that we can read into python as a pandas DataFrame which contains 2 columns corresponding to the stock’s closing price and date.

For this introduction, I’ve saved a copy of JFC’s closing prices from 2013–09–01 to 2019–04–26 (along with the rest of the code here) in the time-series directory of this repo. We can access the data by cloning this repo and navigating to the time-series directory.



git clone

cd data-science-demos/time-series # Run these on your terminalgit clone https://github.com/enzoampil/data-science-demos.git cd data-science-demos/time-series

!git clone

!cd data-science-demos/time-series # Alternatively, you can run these from jupyter this way!git clone https://github.com/enzoampil/data-science-demos.git !cd data-science-demos/time-series

jfc = pd.read_csv(" # Read the JFC data (csv) as a pandas DataFramejfc = pd.read_csv(" jfc_20130901_to_20190426.csv ") # Convert the date column to datetime format

jfc['CHART_DATE'] = pd.to_datetime(jfc.CHART_DATE)

3. Plot the time series

For this, we can use the basic plotting functionality accessible straight from the pandas DataFrame.

# Plot the time series

# 'CHART_DATE' is the date and 'CLOSE' is the closing price

jfc.set_index('CHART_DATE').CLOSE.plot(figsize=(15, 10))

plt.title('Jollibee Daily Closing Price', fontsize=25)

You will notice that JFC’s closing price moves in cycles of upward and downward movements, but the overall trend is still going up. One of the strengths of Prophet is that it can automatically account for the seasonality found in trends when making its forecasts.

4. Train the Prophet model

Now, we can train the Prophet model! To do this, we have to first filter the DataFrame to have only two columns: the date, “CHART_DATE” and the closing price, “CLOSE”. Then, we change their names to “ds” and “y”, respectively, since Prophet automatically reads the “ds” column as the date and the “y” column as the variable being forecasted. Finally, we train the model on the training data, which refers to the data before the beginning of a specified holdout period. In this case, “HOLDOUT_START” is the date corresponding to the beginning of the holdout period (set at 2019–03–01).

Note that the data for the holdout period will be treated as our validation set and will be used in assessing the performance of the trained Prophet model.

# Set holdout (validation) set start

HOLDOUT_START = '2019-03-01' # Import the Prophet package

from fbprophet import Prophet # Filter to only the date and closing price columns

ts = jfc[['CHART_DATE', 'CLOSE']] # Rename the date and closing price columns to 'ds', and 'y', respectively

# We do this since prophet automatically reads the 'ds' column as the date and the 'y' column as the variable that we are forecasting

ts.columns = ['ds', 'y'] # Fit the Prophet model to the training data (before the start of the holdout set)

# We set daily_seasonality and yearly_seasonality to True to account for daily and yearly seasonality, respectively

m = Prophet(daily_seasonality=True, yearly_seasonality=True).fit(ts[ts.ds < HOLDOUT_START])

5. Predict the future!

In Prophet, we do this by first creating a future dataframe, where we specify how far into the future we want to forecast; in this case, we set it to 336 days. Next, we call the predict method found inside the trained prophet model (using the future dataframe as an argument) and this returns the predictions.

# Set the forecast period, "periods", in the specified unit, "freq"

# In this case, we're predicting 336 days into the future

future = m.make_future_dataframe(periods=7*4*12, freq='D') # Make the actual predictions

pred = m.predict(future) # Visualise the predictions using Prophet's plotting method

from matplotlib import pyplot as plt

fig1 = m.plot(pred)

plt.title('Jollibee: Forecasted Daily Closing Price', fontsize=25)

The forecasts along with historical closing prices are shown above. The blue line corresponds to the forecasted closing prices, while the black dots correspond to the historical closing prices from the training set. The forecasted closing prices for the holdout period indicate that prices will go down for that period (2019–03–01 to 2019–04–26).

The shaded blue region corresponds to the forecasted 95% confidence intervals. You will notice that forecasts that are further away, also have wider forecasted confidence intervals.

6. Assess accuracy

To assess the accuracy of our trained Prophet model, we will compute the root mean squared error (RMSE) of our predictions on the holdout set from 2019–03–01 to 2019–04–26. To visualise performance in more detail, we also plot the predicted JFC closing price vs the actual JFC closing price for the 57 day holdout period.

# Concatenate holdout (validation) set predictions and targets into one dataframe for easy comparison

pred_holdout = pred[(pred.ds >= HOLDOUT_START)&(pred.ds <= ts.ds.max())].set_index('ds').yhat

target_holdout = ts[ts.ds >= HOLDOUT_START].set_index('ds')

comb = pd.concat([pred_holdout, target_holdout], axis=1).dropna() # Calculate root mean squared error (RMSE)

import numpy as np

rmse_holdout = np.sqrt(comb.yhat.subtract(comb.y).pow(2).mean()) # Plot predicted vs target while displaying accuracy based on rmse

comb.columns = ['Predicted', 'Actual']

comb.plot(figsize=(15, 10))

plt.title('Predicted (yhat) vs Actual (y) JFC Closing Price

Validation Set RMSE: {}'.format(rmse_holdout), fontsize=25)

As stated earlier, the forecasted prices (blue) for the holdout set indicate that prices would go down overall for the duration of the holdout set. Interestingly, the actual prices (orange) also showed an overall decrease in JFC’s closing price, although sharper than the one predicted.

In addition, the short term movements also appear to be reflected by the forecasts. The actual trend shows an initial increase up to April 8, and then a drop leading to April 26. Again, the forecasts show similar movements, although not as sharp.

The calculated root mean squared error (RMSE) of 5.56 tells us that on average (with increased weight on large errors) the Prophet model’s JFC closing price predictions are wrong by PHP 5.56 for the holdout set from 2019–03–01 to 2019–04–26. Is this error small enough for us to trust the predictions? That will depend on our willingness to take on risk, but a conservative rule of thumb is to only make trades on forecasts that indicate a profit opportunity even at the expected downward deviation from the forecasted price.

What’s next?

Congratulations! You now know how to execute a basic forecasting workflow using the powerful Prophet package. This involved the following steps: 1) installing and importing the necessary packages, 2) getting the data, 3) plotting the time series, 4) training the Prophet model, 5) predicting the future using the model, and finally, 6) assessing accuracy. This same workflow can be applied using other forecasting models and for use cases other than predicting stock prices.

It’s important to note that there are still many ways to improve our current forecasting workflow:

Use exogenous variables and derived indicators for prediction. We can explicitly account for information other than the stock’s past closing prices (exogenous variables). Examples of these are a stock’s traded volume, the price and volume of other stocks, interest rates, inflation, success of a recent ad launched, and other derived metrics like moving volatility, RSI, short-term & long-term moving average, etc. Identify events that can catalyse price movement. Examples are company related announcements (often disclosed on twitter) such as those about performance, mergers & acquisitions, new laws, etc. We can model these specifically in order to estimate their impact on the price. Experiment with other powerful models. I often use Prophet as a baseline but still end up using other models that beat the base model’s performance. Examples of these are gradient boosting machines (e.g. LightGBM), deep learning models (e.g. LSTM RNNs), and other cutting edge time series models (e.g. TBATS, SARIMAX). Improve accuracy of forecasted model uncertainty. Aside from the performance of point forecasts, arguably more important is the accuracy of forecasted uncertainty, which can guide us in knowing when to trust the model’s predictions more. This has been a focus of recent research and some have successfully created models that accurately predict 95% confidence intervals that actually cover 95% of targets. Visualise estimated impact via simulation engines. By creating models that can account for external factors and events, we can turn these models into simulation engines that can visualise how prices will change across different scenarios (i.e. scenario analysis). For example, how would the price look given a recession next year, paired with a 2% hike in interest rates?

Above are only some of the many ways to improve our current forecasting workflow and I plan to discuss these in more detail in future blog posts. If you have any suggestions on which ones to start with, feel free to comment or email me at lorenzo.ampil@gmail.com. Stay tuned!

Note from Towards Data Science’s editors: While we allow independent authors to publish articles in accordance with our rules and guidelines, we do not endorse each author’s contribution. You should not rely on an author’s works without seeking professional advice. See our Reader Terms for details.