This article is some sort of continuation from this one.
Our previous model for stock simulations did not take in account the following idea:
when a stock (or the market) is going up, then it should be (intuitively) at least, more likely that it will continue to go up. Or at the very least, as it is the case for a football game, it does not feel right to believe that the probability of either of the two possible outcomes is exactly 50%.
The idea behind Markov chains is really versatile, we can apply it also to the markets.
With a “bit” of study (I’m being sarcastic here), you can come up with something pretty complicated like this, however, the model I’m going to show here is much more naive and easier.
Suppose a Markov chain with two states, market up and market down. Once you found the probabilities of each state, you can easily simulate a random walk (based on a Markov chain of course).
Here is the code for this model:
import numpy as np | |
from matplotlib import pyplot as plt | |
path = "C:\\" | |
#data is stored in a .txt file in format DOHLCV | |
def readData(stock): | |
file = open(path+stock+'.txt',"r") | |
data = file.read() | |
file.close() | |
return data | |
#We read data and get a list with each line in string format | |
data = readData('stock').split('\n') | |
#This function returns a list with float mean values | |
#from two columns (1st and 4th in this case) | |
def getColumn(list1): | |
dataAr = [] | |
for i in range(len(list1)-1): | |
dataToGet = (float(list1[i].split(',')[1]) + float(list1[i].split(',')[4]))/2 | |
dataAr.append(dataToGet) | |
return dataAr | |
#Here is our data (type(data[1]) = float) | |
data = getColumn(data) | |
#Calculate percentage change | |
def getPercentageChange(v1,v2): | |
pc = (v2-v1)/abs(v1) | |
return pc | |
#Given an array of numbers, this function returns an array | |
#with percentage changes between each pair of values | |
def getPcArray(list1): | |
pcArray = [] | |
for i in range(len(list1)-2): | |
pcArray.append(getPercentageChange(list1[i],list1[i+1])) | |
return pcArray | |
dataPerc = getPcArray(data) | |
#Now we need to calculate conditional probabilities | |
negativesP = 0 | |
negativesN = 0 | |
for i in range(1,len(dataPerc)): | |
if dataPerc[i-1] <= 0 and dataPerc[i] > 0: | |
negativesP += 1 | |
elif dataPerc[i-1] <= 0 and dataPerc[i] < 0: | |
negativesN += 1 | |
positivesP = 0 | |
positivesN = 0 | |
for i in range(1,len(dataPerc)): | |
if dataPerc[i-1] > 0 and dataPerc[i] > 0: | |
positivesP += 1 | |
elif dataPerc[i-1] > 0 and dataPerc[i] < 0: | |
positivesN += 1 | |
#pUp_givenUp = probability of going up, given that | |
#the previous step was upwards | |
pUp_givenUp = positivesP/(positivesP+positivesN) | |
pDown_givenUp = positivesN/(positivesP+positivesN) | |
pUp_givenDown = negativesP/(negativesP+negativesN) | |
pDown_givenDown = negativesN/(negativesP+negativesN) | |
#Transition matrices for our model | |
stateUp = [pUp_givenUp,pDown_givenUp] | |
stateDown = [pUp_givenDown,pDown_givenDown] | |
#This function simulates n random walks according | |
#to the parameters specified and the Markov model. | |
def simulate(n): | |
k = 0 | |
for i in range(n): | |
#Initial value | |
initial = 100 | |
#Possible percentage change [up,down] | |
variat = [0.02,-0.02] | |
#Initial percentage change | |
invar = np.random.choice(variat,replace=True) | |
#List of simulated data | |
simulatedData = [] | |
#Simulation process | |
for i in range(255): | |
if invar >= 0: | |
invar = np.random.choice(variat,replace=True,p=stateUp) | |
else: | |
invar = np.random.choice(variat,replace=True,p=stateDown) | |
initial = initial*(1+invar) | |
simulatedData.append(initial) | |
#x axis | |
index = list(range(len(simulatedData))) | |
#Plot the data | |
print(k) | |
k += 1 | |
plt.plot(index,simulatedData) | |
plt.title(str(n)+" simulated random walks") | |
#Let's simulate 2 random processes | |
simulate(2) | |
plt.show() | |
# Output (conditional probabilities) | |
# | |
# pUp_givenUp pDown_givenUp pUp_givenDown pDown_givenDown | |
# 0.60360 0.39639 0.44806 0.55193 |
The graphs below represent respectively, 2, 200 and 500 random paths.
200 random walks
500 random walks
Hope this was interesting.
Disclaimer
This article is for educational purpose only. The numbers are invented. The author is not responsible for any consequence or loss due to inappropriate use. It may contain mistakes and errors. You should never use this article for purposes different from the educational one.