Introduction
The purpose of this assignment is to apply additive and multiplicative decomposition techniques to predict the next month’s worth of a stock’s prices using two years of historic data from Yahoo Finance. The first step is to download two years’ worth of data using the quantmod
package. Then we’ll use functions from the forecast
package to make one month’s worth of predictions.
library(quantmod)
library(forecast)
library(lubridate)
getSymbols('YOU.L', src = 'yahoo',
from = Sys.Date() - years(2), to = Sys.Date())
yougov <- ts(YOU.L, frequency = 7)
Share prices are generally trending upwards. There are some ups and downs of various sizes. For example, there was a large dip in share prices following the Brexit vote, which was largely viewed as a failure by British market research firms. That said, there doesn’t seem to be any type of seasonality.
library(dplyr)
library(yaztheme)
y = yougov[,'YOU.L.Adjusted']
close_price_line <- autoplot(y)+
labs(x = 'Time', y = 'Adjusted Closing Price',
title = 'YouGov PLC (YOU.L) Adjusted Closing Price over Time')+
theme_yaz()+
scale_x_continuous(breaks = c(0, 52), labels = c('2 Years Ago','1 Year Ago'))
close_price_hist <- ggplot(YOU.L, aes(x = YOU.L.Adjusted))+
geom_histogram(fill = yaz_cols[1])+
theme_yaz()+
labs(title = ' ', y = 'Frequency',
x = element_blank())+
coord_flip()
library(gridExtra)
grid.arrange(
close_price_line, close_price_hist,
nrow = 1, widths = c(3,1)
)

Decomposition
Decomposition methods seek to break up a time series to isolate overall trends, seasonality, and some remainder component (Hyndman Ch 6).
Multiplicative and additive decomposition methods produce very similar outputs. Visually, both methods appear to perform similarly from a visual inspection of the relevant plots below.
fit.mult <- decompose(y, type="multiplicative")
mult.plot <- autoplot(fit.mult) + xlab("Day") +
ggtitle("Multiplicative Decomposition")+
theme_yaz()
fit.add <- decompose(y, type="additive")
add.plot <- autoplot(fit.add) + xlab("Day") +
ggtitle("Additive Decomposition")+
theme_yaz()
grid.arrange(
mult.plot, add.plot, nrow = 1
)

A more formal evaluation of the methods indicates that the multiplicative model is better, which makes sense due to the lack of consistent seasonal trends.
eval_stats <- function(fit, ts.obj){
error<-as.vector(
na.omit(
fit$random
) #generate residuals without NA
)
datavector<-ts.obj[4:502]
abserror<-abs(error)
sqerror<-error^2
pererror<-(abserror/datavector)*100
me <- round(mean(error),2)
mae <- round(mean(abserror),2)
mse <- round(mean(sqerror),2)
rmse <- round(sqrt(mse),2)
mape <- round(mean(pererror),2)
return(data.frame(
values = c(me, mae, mse, rmse, mape),
metrics = c('Mean Error','Mean Absolute Error','Mean Squared Error',
'Root Mean Squared Error','Mean Absolute Percent Error')
)
)
}
inner_join(
eval_stats(fit.add, yougov)%>%dplyr::select(Additive = values, metrics),
eval_stats(fit.mult, yougov)%>%dplyr::select(Multiplicative = values, metrics)
)%>%
dplyr::select(Metric = metrics, Additive, Multiplicative)%>%
knitr::kable()
Joining, by = "metrics"
Mean Error |
0.00 |
1.00 |
Mean Absolute Error |
1.83 |
1.00 |
Mean Squared Error |
7.97 |
1.00 |
Root Mean Squared Error |
2.82 |
1.00 |
Mean Absolute Percent Error |
0.86 |
0.51 |
LS0tDQp0aXRsZTogIllvdUdvdiBTdG9jayBQcmljZXM6IEFkZGl0aXZlIGFuZCBNdWx0aXBsaWNhdGl2ZSBEZWNvbXBvc2l0aW9uIg0KYXV0aG9yOiAnSm9zaCBZYXptYW4nDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIyBJbnRyb2R1Y3Rpb24NClRoZSBwdXJwb3NlIG9mIHRoaXMgYXNzaWdubWVudCBpcyB0byBhcHBseSBhZGRpdGl2ZSBhbmQgbXVsdGlwbGljYXRpdmUgZGVjb21wb3NpdGlvbiB0ZWNobmlxdWVzIHRvIHByZWRpY3QgdGhlIG5leHQgbW9udGgncyB3b3J0aCBvZiBhIHN0b2NrJ3MgcHJpY2VzIHVzaW5nIHR3byB5ZWFycyBvZiBoaXN0b3JpYyBkYXRhIGZyb20gWWFob28gRmluYW5jZS4gVGhlIGZpcnN0IHN0ZXAgaXMgdG8gZG93bmxvYWQgdHdvIHllYXJzJyB3b3J0aCBvZiBkYXRhIHVzaW5nIHRoZSBbYHF1YW50bW9kYF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3F1YW50bW9kL3F1YW50bW9kLnBkZikgcGFja2FnZS4gVGhlbiB3ZSdsbCB1c2UgZnVuY3Rpb25zIGZyb20gdGhlIFtgZm9yZWNhc3RgXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvZm9yZWNhc3QvZm9yZWNhc3QucGRmKSBwYWNrYWdlIHRvIG1ha2Ugb25lIG1vbnRoJ3Mgd29ydGggb2YgcHJlZGljdGlvbnMuIA0KDQpgYGB7ciwgZWNobyA9IFRSVUUsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9IEZBTFNFfQ0KbGlicmFyeShxdWFudG1vZCkNCmxpYnJhcnkoZm9yZWNhc3QpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmdldFN5bWJvbHMoJ1lPVS5MJywgc3JjID0gJ3lhaG9vJywgDQogICAgICAgICAgIGZyb20gPSBTeXMuRGF0ZSgpIC0geWVhcnMoMiksIHRvID0gU3lzLkRhdGUoKSkNCg0KeW91Z292IDwtIHRzKFlPVS5MLCBmcmVxdWVuY3kgPSA3KQ0KYGBgDQoNClNoYXJlIHByaWNlcyBhcmUgZ2VuZXJhbGx5IHRyZW5kaW5nIHVwd2FyZHMuIFRoZXJlIGFyZSBzb21lIHVwcyBhbmQgZG93bnMgb2YgdmFyaW91cyBzaXplcy4gRm9yIGV4YW1wbGUsIHRoZXJlIHdhcyBhIGxhcmdlIGRpcCBpbiBzaGFyZSBwcmljZXMgZm9sbG93aW5nIHRoZSBCcmV4aXQgdm90ZSwgd2hpY2ggd2FzIGxhcmdlbHkgdmlld2VkIGFzIGEgZmFpbHVyZSBieSBCcml0aXNoIG1hcmtldCByZXNlYXJjaCBmaXJtcy4gVGhhdCBzYWlkLCB0aGVyZSBkb2Vzbid0IHNlZW0gdG8gYmUgYW55IHR5cGUgb2Ygc2Vhc29uYWxpdHkuIA0KYGBge3IsIGVjaG8gPSBUUlVFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0ID0gNH0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHlhenRoZW1lKQ0KeSA9IHlvdWdvdlssJ1lPVS5MLkFkanVzdGVkJ10NCmNsb3NlX3ByaWNlX2xpbmUgPC0gYXV0b3Bsb3QoeSkrDQogIGxhYnMoeCA9ICdUaW1lJywgeSA9ICdBZGp1c3RlZCBDbG9zaW5nIFByaWNlJywNCiAgICAgICB0aXRsZSA9ICdZb3VHb3YgUExDIChZT1UuTCkgQWRqdXN0ZWQgQ2xvc2luZyBQcmljZSBvdmVyIFRpbWUnKSsNCiAgdGhlbWVfeWF6KCkrDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKDAsIDUyKSwgbGFiZWxzID0gYygnMiBZZWFycyBBZ28nLCcxIFllYXIgQWdvJykpDQpjbG9zZV9wcmljZV9oaXN0IDwtIGdncGxvdChZT1UuTCwgYWVzKHggPSBZT1UuTC5BZGp1c3RlZCkpKw0KICBnZW9tX2hpc3RvZ3JhbShmaWxsID0geWF6X2NvbHNbMV0pKw0KICB0aGVtZV95YXooKSsNCiAgbGFicyh0aXRsZSA9ICcgJywgeSA9ICdGcmVxdWVuY3knLA0KICAgICAgIHggPSBlbGVtZW50X2JsYW5rKCkpKw0KICBjb29yZF9mbGlwKCkNCg0KbGlicmFyeShncmlkRXh0cmEpDQpncmlkLmFycmFuZ2UoDQogIGNsb3NlX3ByaWNlX2xpbmUsIGNsb3NlX3ByaWNlX2hpc3QsDQogIG5yb3cgPSAxLCB3aWR0aHMgPSBjKDMsMSkNCikNCmBgYA0KDQojIyBEZWNvbXBvc2l0aW9uDQpEZWNvbXBvc2l0aW9uIG1ldGhvZHMgc2VlayB0byBicmVhayB1cCBhIHRpbWUgc2VyaWVzIHRvIGlzb2xhdGUgb3ZlcmFsbCB0cmVuZHMsIHNlYXNvbmFsaXR5LCBhbmQgc29tZSByZW1haW5kZXIgY29tcG9uZW50IChbSHluZG1hbiBDaCA2XShodHRwOi8vb3RleHRzLm9yZy9mcHAyL2NoLWRlY29tcG9zaXRpb24uaHRtbCkpLiANCg0KTXVsdGlwbGljYXRpdmUgYW5kIGFkZGl0aXZlIGRlY29tcG9zaXRpb24gbWV0aG9kcyBwcm9kdWNlIHZlcnkgc2ltaWxhciBvdXRwdXRzLiBWaXN1YWxseSwgYm90aCBtZXRob2RzIGFwcGVhciB0byBwZXJmb3JtIHNpbWlsYXJseSBmcm9tIGEgdmlzdWFsIGluc3BlY3Rpb24gb2YgdGhlIHJlbGV2YW50IHBsb3RzIGJlbG93Lg0KDQpgYGB7ciwgZmlnLndpZHRoPTExLCBmaWcuaGVpZ2h0PTV9DQpmaXQubXVsdCA8LSBkZWNvbXBvc2UoeSwgdHlwZT0ibXVsdGlwbGljYXRpdmUiKQ0KbXVsdC5wbG90IDwtIGF1dG9wbG90KGZpdC5tdWx0KSArIHhsYWIoIkRheSIpICsNCiAgZ2d0aXRsZSgiTXVsdGlwbGljYXRpdmUgRGVjb21wb3NpdGlvbiIpKw0KICB0aGVtZV95YXooKQ0KDQpmaXQuYWRkIDwtIGRlY29tcG9zZSh5LCB0eXBlPSJhZGRpdGl2ZSIpDQphZGQucGxvdCA8LSBhdXRvcGxvdChmaXQuYWRkKSArIHhsYWIoIkRheSIpICsNCiAgZ2d0aXRsZSgiQWRkaXRpdmUgRGVjb21wb3NpdGlvbiIpKw0KICB0aGVtZV95YXooKQ0KDQpncmlkLmFycmFuZ2UoDQogIG11bHQucGxvdCwgYWRkLnBsb3QsIG5yb3cgPSAxDQopDQpgYGANCg0KQSBtb3JlIGZvcm1hbCBldmFsdWF0aW9uIG9mIHRoZSBtZXRob2RzIGluZGljYXRlcyB0aGF0IHRoZSBtdWx0aXBsaWNhdGl2ZSBtb2RlbCBpcyBiZXR0ZXIsIHdoaWNoIG1ha2VzIHNlbnNlIGR1ZSB0byB0aGUgbGFjayBvZiBjb25zaXN0ZW50IHNlYXNvbmFsIHRyZW5kcy4NCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXRob2QgPSBGQUxTRX0NCmV2YWxfc3RhdHMgPC0gZnVuY3Rpb24oZml0LCB0cy5vYmopew0KICBlcnJvcjwtYXMudmVjdG9yKA0KICAgIG5hLm9taXQoDQogICAgICBmaXQkcmFuZG9tDQogICAgICApICAjZ2VuZXJhdGUgcmVzaWR1YWxzIHdpdGhvdXQgTkENCiAgICApDQogIGRhdGF2ZWN0b3I8LXRzLm9ials0OjUwMl0NCiAgYWJzZXJyb3I8LWFicyhlcnJvcikNCiAgc3FlcnJvcjwtZXJyb3JeMg0KICBwZXJlcnJvcjwtKGFic2Vycm9yL2RhdGF2ZWN0b3IpKjEwMA0KICBtZSA8LSByb3VuZChtZWFuKGVycm9yKSwyKQ0KICBtYWUgPC0gcm91bmQobWVhbihhYnNlcnJvciksMikNCiAgbXNlIDwtIHJvdW5kKG1lYW4oc3FlcnJvciksMikNCiAgcm1zZSA8LSByb3VuZChzcXJ0KG1zZSksMikNCiAgbWFwZSA8LSByb3VuZChtZWFuKHBlcmVycm9yKSwyKQ0KICByZXR1cm4oZGF0YS5mcmFtZSgNCiAgICB2YWx1ZXMgPSBjKG1lLCBtYWUsIG1zZSwgcm1zZSwgbWFwZSksDQogICAgbWV0cmljcyA9IGMoJ01lYW4gRXJyb3InLCdNZWFuIEFic29sdXRlIEVycm9yJywnTWVhbiBTcXVhcmVkIEVycm9yJywNCiAgICAgICAgICAgICAgICAnUm9vdCBNZWFuIFNxdWFyZWQgRXJyb3InLCdNZWFuIEFic29sdXRlIFBlcmNlbnQgRXJyb3InKQ0KICAgICkNCiAgKQ0KfQ0KDQppbm5lcl9qb2luKA0KICBldmFsX3N0YXRzKGZpdC5hZGQsIHlvdWdvdiklPiVkcGx5cjo6c2VsZWN0KEFkZGl0aXZlID0gdmFsdWVzLCBtZXRyaWNzKSwNCiAgZXZhbF9zdGF0cyhmaXQubXVsdCwgeW91Z292KSU+JWRwbHlyOjpzZWxlY3QoTXVsdGlwbGljYXRpdmUgPSB2YWx1ZXMsIG1ldHJpY3MpDQogICklPiUNCiAgZHBseXI6OnNlbGVjdChNZXRyaWMgPSBtZXRyaWNzLCBBZGRpdGl2ZSwgTXVsdGlwbGljYXRpdmUpJT4lDQogIGtuaXRyOjprYWJsZSgpDQpgYGANCg0K