Predicting Stock Prices with quantmod and prophet

20/3/2022 5-minute read

Background

Last summer I took a business finance class, and learned a little about stocks. Most of my projects centered around a company called MicroVision which is a research and development company creating the newest Lidar technology for autonomous vehicles.

Set Up

# Global Options 
knitr::opts_chunk$set(error=FALSE,
                      message= FALSE,
                      warning=FALSE)

For this project you only need three packages:

  • quantmod: to get the data from yahoo finance

  • tidyverse: to clean the data

  • prophet: to make predictions

(Links to Github Repositories Below)

# Load Libraries 
library(quantmod)
library(tidyverse)  
library(prophet) 

Load Data

There are a few places that quantmod can pull data from, but the default we will be using is Yahoo Finace, you can also specify this with src="yahoo". Use ?getSymbols for more information on it’s parameters.

getSymbols("MVIS")
## [1] "MVIS"

Right away we can use quantmod functions like chartSeries() to look at various plots of MicroVision stocks. Below are a few examples showing various subsets of data from 2019 - 2022. As well as different types such as bar, line, candlesticks, and auto. The last graph also includes addBBands(), addMomentum() and addROC(). Use ? with any of these functions to find out more details on their parameters.

chartSeries(MVIS, type = "candlesticks", subset = '2019-09-01::2019-12-31', theme= chartTheme('white'))

chartSeries(MVIS, type = "bar", subset = '2020', theme= chartTheme('white'))

chartSeries(MVIS, type = "line", subset = '2021', theme= chartTheme('white'))

chartSeries(MVIS, type = "auto", subset = '2022', theme= chartTheme('white'))

chartSeries(MVIS, type = "auto", subset = '2022-03', theme= chartTheme('white'))

addBBands(n=20,sd=2)

addMomentum(n=1)

addROC(n=7)

Tidy Data

head(MVIS)
##            MVIS.Open MVIS.High MVIS.Low MVIS.Close MVIS.Volume MVIS.Adjusted
## 2007-01-03     25.68     26.40    24.16      24.56      106750         24.56
## 2007-01-04     25.76     30.48    25.44      29.92      703538         29.92
## 2007-01-05     30.00     31.44    28.16      29.60      333425         29.60
## 2007-01-08     31.92     32.64    30.24      31.44      341050         31.44
## 2007-01-09     30.96     31.20    29.20      29.36      242725         29.36
## 2007-01-10     29.68     30.80    27.76      29.68      169038         29.68

You might notice that the date column doesn’t have a column name, and that is because it is being read as the names of the rows. To change this we will first need to change the data into a data frame, and then change the row names into a column with the function rownames_to_column(). It is then important to assign the date series column the name ds. That is how the prophet package will recognize it, so this will save us the step of renaming this later on.

MVIS <- data.frame(MVIS)
MVIS <- rownames_to_column(MVIS, "ds")
head(MVIS)
##           ds MVIS.Open MVIS.High MVIS.Low MVIS.Close MVIS.Volume MVIS.Adjusted
## 1 2007-01-03     25.68     26.40    24.16      24.56      106750         24.56
## 2 2007-01-04     25.76     30.48    25.44      29.92      703538         29.92
## 3 2007-01-05     30.00     31.44    28.16      29.60      333425         29.60
## 4 2007-01-08     31.92     32.64    30.24      31.44      341050         31.44
## 5 2007-01-09     30.96     31.20    29.20      29.36      242725         29.36
## 6 2007-01-10     29.68     30.80    27.76      29.68      169038         29.68

For some reason these changes have altered the data slightly. This is where the tidyverse and the mutate() function will come in handy. Within the mutate() function I am using three other functions:

  • str_remove(): to remove the X

  • str_replace_all(): to replace the periods with dashes

  • as.Date(): to change the ds column from a charater value to a date value

# Tidy 
MVIS <- MVIS %>%
  mutate(ds = str_remove(ds, "X"),
         ds = str_replace_all(ds, "[.]","-"),
         ds = as.Date(ds))
head(MVIS)
##           ds MVIS.Open MVIS.High MVIS.Low MVIS.Close MVIS.Volume MVIS.Adjusted
## 1 2007-01-03     25.68     26.40    24.16      24.56      106750         24.56
## 2 2007-01-04     25.76     30.48    25.44      29.92      703538         29.92
## 3 2007-01-05     30.00     31.44    28.16      29.60      333425         29.60
## 4 2007-01-08     31.92     32.64    30.24      31.44      341050         31.44
## 5 2007-01-09     30.96     31.20    29.20      29.36      242725         29.36
## 6 2007-01-10     29.68     30.80    27.76      29.68      169038         29.68

Lastly to create a data frame of only the closing costs and the time series. For the prophet package it is important the the closing costs column be renamed y.

# CLosing Data 
MVIS_close <- data.frame(ds = MVIS$ds, y = MVIS$MVIS.Close)
head(MVIS_close)
##           ds     y
## 1 2007-01-03 24.56
## 2 2007-01-04 29.92
## 3 2007-01-05 29.60
## 4 2007-01-08 31.44
## 5 2007-01-09 29.36
## 6 2007-01-10 29.68

Prophet Function

Now that our data is ready, lets create our model using the prophet() function. As well as our predicted model using the function make_future_dataframe(). I made the period about 3 years (which is a lot), but you can change this to whatever you like.

# call prophet function to fit the model 
Model1 <- prophet(MVIS_close, daily.seasonality=TRUE)
Future1 <- make_future_dataframe(Model1, periods = 365*3)
tail(Future1)
##              ds
## 4923 2025-03-17
## 4924 2025-03-18
## 4925 2025-03-19
## 4926 2025-03-20
## 4927 2025-03-21
## 4928 2025-03-22

Predict Function

The predict function uses various model fitting functions to predict future results.

# Forecast Proper 
Forecast1 <- predict(Model1, Future1)
# Forecast Values 
predict_date <- Forecast1$ds[length(Forecast1$ds)]
predict_value <- Forecast1$yhat[length(Forecast1$yhat)]
predict_lower <- Forecast1$yhat_lower[length(Forecast1$yhat_lower)]
predict_upper <- Forecast1$yhat_upper[length(Forecast1$yhat_upper)]

This model predicts that on 2025-03-22, the value of MicroVision stock will be about 19.7897189. This value is in a range between -5.2078987 and 46.3215886. Note that this range is so large because of the long time period on which it is making the prediction.

Plot Model

This is an interactive plot that shows the actual values in black, and the predicted values in blue. The grey graph underneath the main graph can be adjusted to look at specific time windows.

dyplot.prophet(Model1, Forecast1)

Plot Componets

Lastly we can use the function prophet_plot_componets() to see a plot of yearly, weekly, seasonally, and daily trends of this stock.

prophet_plot_components(Model1, Forecast1)

Looking at daily trends it appears that MicroVision was on the decline after 2010 for some time, but has been trading up since about 2019.

Looking at the weekly trends, it obvious MicroVision is popular during the Monday - Friday trading week, however looking at the time trends the stock is most popular at the beginning and end of the day.

The third graph shows us that MicroVision does not seem to preform well in the first quarter of the year, but picks up around May until it starts to drop off again around November.

Package Repositories

quantmod

prophet

tidyverse

Future Post Ideas

  • Comparing Stocks

  • Analyzing Financial Statements