Predicting Stock Prices with quantmod and prophet
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 Xstr_replace_all(): to replace the periods with dashesas.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.
Sources
Forecasting Bitcoin Prices Using Prophet in R
Future Post Ideas
Comparing Stocks
Analyzing Financial Statements