Markov Chain Model

Markov chains are usually used in modeling many practical problems. They are also effective in modeling time series.

The Markov Process provides a credible approach for successfully analyzing and predicting time series data which reflect

Markov dependency.: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4247363/.

Price volatilities make stock investments risky, leaving investors in critical position when uncertain decision is made. To improve investor evaluation confidence on exchange markets, while not using time series methodology, we specify equity price change as a stochastic process assumed to possess Markov dependency with respective state transition probabilities matrices following the identified state pace (i.e. decrease, stable or increase).

For more details on Markov Chain Model Application on Share Price Movement in Stock Market: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.866.8019&rep=rep1&type=pdf.

another one: https://web.wpi.edu/Pubs/E-project/Available/E-project-031411-153131/unrestricted/MQP_HS1_3699.pdf.

library(quantmod) 
## Warning: package 'quantmod' was built under R version 3.4.3
## Loading required package: xts
## Warning: package 'xts' was built under R version 3.4.3
## Loading required package: zoo
## Warning: package 'zoo' was built under R version 3.4.3
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
## Loading required package: TTR
## Warning: package 'TTR' was built under R version 3.4.3
## Version 0.4-0 included new data defaults. See ?getSymbols.
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 3.4.3
library(markovchain)
## Warning: package 'markovchain' was built under R version 3.4.3
## Package:  markovchain
## Version:  0.6.9.8-1
## Date:     2017-08-15
## BugReport: http://github.com/spedygiorgio/markovchain/issues
library(diagram)
## Loading required package: shape
library(expm)
## Warning: package 'expm' was built under R version 3.4.3
## Loading required package: Matrix
## Warning: package 'Matrix' was built under R version 3.4.3
## 
## Attaching package: 'expm'
## The following object is masked from 'package:Matrix':
## 
##     expm
library(pracma)
## 
## Attaching package: 'pracma'
## The following objects are masked from 'package:expm':
## 
##     expm, logm, sqrtm
## The following objects are masked from 'package:Matrix':
## 
##     expm, lu, tril, triu
getSymbols("QQQ", from = "2017-01-01", to = "2017-11-01")
## 'getSymbols' currently uses auto.assign=TRUE by default, but will
## use auto.assign=FALSE in 0.5-0. You will still be able to use
## 'loadSymbols' to automatically load data. getOption("getSymbols.env")
## and getOption("getSymbols.auto.assign") will still be checked for
## alternate defaults.
## 
## This message is shown once per session and may be disabled by setting 
## options("getSymbols.warning4.0"=FALSE). See ?getSymbols for details.
## 
## WARNING: There have been significant changes to Yahoo Finance data.
## Please see the Warning section of '?getSymbols.yahoo' for details.
## 
## This message is shown once per session and may be disabled by setting
## options("getSymbols.yahoo.warning"=FALSE).
## [1] "QQQ"
chart_Series(QQQ)

chartSeries(QQQ,TA='addBBands();addBBands(draw="p"); addVo();addMACD()', subset='2017',theme="white") 

Calculate Daily Return

QQQ_log_returns <- dailyReturn(QQQ,type = 'log')

df = data.frame(date = index(QQQ_log_returns), QQQ_log_returns, row.names=NULL)

ggplot(df, aes(df$date, df$daily.returns)) + geom_line() + scale_x_date('Month/2017')  + ylab("QQQ Log Daily Return") +
  xlab("") + labs(title = "QQQ Daily Return (Log)")

Is Daily Return a normal distribution?

x <- df$daily.returns
h=hist(df$daily.returns,breaks= 20,col="blue",main="Histogram with Normal Curve")
xfit<-seq(min(x),max(x),length=40) 
yfit<-dnorm(xfit,mean=mean(x),sd=sd(x)) 
yfit <- yfit*diff(h$mids[1:2])*length(x) 
lines(xfit, yfit, col="red", lwd=3)

Estimate Daily Return

probs <- c(.005, .025, .25, .5, .75, .975, .995)
dist_log_returns <- quantile(QQQ_log_returns,probs = probs, na.rm = TRUE)
dist_log_returns
##         0.5%         2.5%          25%          50%          75% 
## -0.025159010 -0.017008157 -0.001540675  0.001661796  0.003921491 
##        97.5%        99.5% 
##  0.011952463  0.016517317
mean_log_returns <- mean(QQQ_log_returns, na.rm = TRUE)
sd_log_returns <- sd(QQQ_log_returns, na.rm = TRUE)
mean_log_returns  
## [1] 0.001159414
sd_log_returns 
## [1] 0.006610009
mean_returns = exp(mean_log_returns)
mean_returns
## [1] 1.00116

On average, the mean daily return is 0.00116% more than the previous day’s price.

mysequence<-df$daily.returns
U=length(mysequence[mysequence = 0])
D=length(mysequence[mysequence < 0])
I=length(mysequence[mysequence > 0])

df$trend = cut(df$daily.returns, c(-1, 0, 1))
mysequence<-df$trend
createSequenceMatrix(mysequence)
##        (-1,0] (0,1]
## (-1,0]     25    52
## (0,1]      52    80
myFit<-markovchainFit(data=mysequence,confidencelevel = .9,method = "mle")
myFit
## $estimate
## MLE Fit 
##  A  2 - dimensional discrete Markov Chain defined by the following states: 
##  (-1,0], (0,1] 
##  The transition matrix  (by rows)  is defined as follows: 
##           (-1,0]     (0,1]
## (-1,0] 0.3246753 0.6753247
## (0,1]  0.3939394 0.6060606
## 
## 
## $standardError
##            (-1,0]      (0,1]
## (-1,0] 0.06493506 0.09365068
## (0,1]  0.05462956 0.06775964
## 
## $confidenceLevel
## [1] 0.9
## 
## $lowerEndpointMatrix
##           (-1,0]     (0,1]
## (-1,0] 0.2414577 0.5553065
## (0,1]  0.3239288 0.5192231
## 
## $upperEndpointMatrix
##          (-1,0]     (0,1]
## (-1,0] 0.407893 0.7953429
## (0,1]  0.463950 0.6928981
## 
## $logLikelihood
## [1] -137.0395
mF<-myFit$estimate
mF
## MLE Fit 
##  A  2 - dimensional discrete Markov Chain defined by the following states: 
##  (-1,0], (0,1] 
##  The transition matrix  (by rows)  is defined as follows: 
##           (-1,0]     (0,1]
## (-1,0] 0.3246753 0.6753247
## (0,1]  0.3939394 0.6060606
a11=mF[1,1]
a12=mF[1,2]
a21=mF[2,1]
a22=mF[2,2]

## Hard code the transition matrix
stateNames <- c("Down","Up")
DU <- matrix(c(a11,a12,a21,a22),nrow=2, byrow=TRUE)


dtmcA <- new("markovchain",transitionMatrix=DU, states=c("Down","Up"), name="MarkovChain A") 

dtmcA
## MarkovChain A 
##  A  2 - dimensional discrete Markov Chain defined by the following states: 
##  Down, Up 
##  The transition matrix  (by rows)  is defined as follows: 
##           Down        Up
## Down 0.3246753 0.6753247
## Up   0.3939394 0.6060606
plot(dtmcA)

## Using plotmat from diagram package
stateNames <- c("Down","Up")
row.names(DU) <- stateNames; colnames(DU) <- stateNames
DU=round(DU,3)
plotmat(DU,pos = c(1,1), 
        lwd = 2, box.lwd = 2, 
        cex.txt = 0.8, 
        box.size = 0.12, 
        box.type = "circle", 
        box.prop = 0.7,
        box.col = "light blue",
        arr.length=.4,
        arr.width=.2,
        self.cex = .6,
        self.shifty = -.01,
        self.shiftx = .17,
        main = "Markov Chain Transition Matrix on QQQ")

Define current state

Today QQQ is Up, that means starting vector (0,1)

x1 <- matrix(c(0,1),nrow=1, byrow=TRUE)

Forecast the state of tomorrow

Predict what will happen tomorrow (in one day)

x1 %*% DU
##       Down    Up
## [1,] 0.394 0.606

That means we will have 66% chance will have No Rain tomorrow, 23% chance will have Light Rain, and 11% chance to have Heavy Rain.

Forecast the states for the next 7 days

DU2 <- DU %^% 2
DU3 <- DU %^% 3
DU4 <- DU %^% 4
DU5 <- DU %^% 5
DU6 <- DU %^% 6
DU7 <- DU %^% 7
cat("Day 1 Forecast")
## Day 1 Forecast
round(x1%*%DU,3)
##       Down    Up
## [1,] 0.394 0.606
cat("Day 2 Forecast")
## Day 2 Forecast
round(x1%*%DU2,3)
##       Down    Up
## [1,] 0.367 0.633
cat("Day 3 Forecast")
## Day 3 Forecast
round(x1%*%DU3,3)
##       Down    Up
## [1,] 0.369 0.631
cat("Day 4 Forecast")
## Day 4 Forecast
round(x1%*%DU4,3)
##       Down    Up
## [1,] 0.369 0.631
cat("Day 5 Forecast")
## Day 5 Forecast
round(x1%*%DU5,3)
##       Down    Up
## [1,] 0.369 0.631
cat("Day 6 Forecast")
## Day 6 Forecast
round(x1%*%DU6,3)
##       Down    Up
## [1,] 0.369 0.631
cat("Day 7 Forecast")
## Day 7 Forecast
round(x1%*%DU7,3)
##       Down    Up
## [1,] 0.369 0.631
DU7 = round(DU7,3)

plotmat(DU7,pos = c(1,1), 
        lwd = 2, box.lwd = 2, 
        cex.txt = 0.8, 
        box.size = 0.12, 
        box.type = "circle", 
        box.prop = 0.7,
        box.col = "light blue",
        arr.length=.4,
        arr.width=.2,
        self.cex = .6,
        self.shifty = -.01,
        self.shiftx = .17,
        main = "Markov Chain Transition Matrix on QQQ")