# Find the Equilibrium Matrix in Markov Chain using Python in Indian Stock Market

## Find the Equilibrium Matrix in Markov Chain using Python in Stock Market

Before We discuss further, Please read make sure You have read the previous articles in this following order –

## Recap on Getting Transition Matrix in Markov Chain Using Python

Let’s follow the path shown in Markov Chains in Stock Market Using Python – Getting Transition Matrix, Here is the sum of the whole python code so far to get Transition Matrix –

```				```
symbol = "NIFTY 50"
days = 1000
end_date = datetime.datetime.now().strftime("%d-%b-%Y")
end_date = str(end_date)

start_date = (datetime.datetime.now()- datetime.timedelta(days=days)).strftime("%d-%b-%Y")
start_date = str(start_date)

df=index_history("NIFTY 50",start_date,end_date)

df["state"]=df["CLOSE"].astype(float).pct_change()
df['state']=df['state'].apply(lambda x: 'Upside' if (x > 0.001) else ('Downside' if (x<=0.001) else 'Consolidation'))

df['priorstate']=df['state'].shift(1)

states = df [['priorstate','state']].dropna()
states_matrix = states.groupby(['priorstate','state']).size().unstack().fillna(0)

transition_matrix= states_matrix.apply(lambda x: x/float(x.sum()),axis=1)
print(transition_matrix)
```
```

Output –

```				```
state          Downside    Upside
priorstate
Consolidation  0.000000  1.000000
Downside       0.638821  0.361179
Upside         0.554307  0.445693
```
```

## Forecasting Futures Probabilities of States using Python

Now, We will walk the sections discussed in Markov Chain and Linear Algebra – Calculation of Stationary Distribution using Python again but this time using Python. Remember this diagram?

Let’s consider time as `t`. Now, We will see observe other probability matrices.

In case You are confused with the terms of “Transition Matrix” and “Probability Matrix” again. “Transition Matrix” is the probability matrix at `t=0`. It shows the probability at `t=0`, right?

So, Let’s build the Markov Chain by multiplying this transition matrix by itself to obtain the probability matrix in `t=1` which would allow us to make one-day forecasts.

```				```
t_0 = transition_matrix.copy()
t_1 = round(t_0.dot(t_0),4)
t_1
```
```

Output –

```				```
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-11-4c583b2519ce> in <module>
1 t_0 = transition_matrix.copy()
----> 2 t_1 = round(t_0.dot(t_0),4)
3 t_1

\python39\lib\site-packages\pandas\core\frame.py in dot(self, other)
1242             common = self.columns.union(other.index)
1243             if len(common) > len(self.columns) or len(common) > len(other.index):
-> 1244                 raise ValueError("matrices are not aligned")
1245
1246             left = self.reindex(columns=common, copy=False)

ValueError: matrices are not aligned
```
```

The dot function only works if the Matrix is `2x2` or `3x3`. As The “consolidation” state’s column in the last is filled with 0,0,0. Our `3x3` matrix becomes `3x2`. So, Let’s just remove the consolidation state as it has so low outcome.

```				```
symbol = "NIFTY 50"
days = 1000
end_date = datetime.datetime.now().strftime("%d-%b-%Y")
end_date = str(end_date)

start_date = (datetime.datetime.now()- datetime.timedelta(days=days)).strftime("%d-%b-%Y")
start_date = str(start_date)

df=index_history("NIFTY 50",start_date,end_date)

df["state"]=df["CLOSE"].astype(float).pct_change()
df['state']=df['state'].apply(lambda x: 'Upside' if (x > 0) else 'Downside' )

df['priorstate']=df['state'].shift(1)

states = df [['priorstate','state']].dropna()
states_matrix = states.groupby(['priorstate','state']).size().unstack().fillna(0)

transition_matrix= states_matrix.apply(lambda x: x/float(x.sum()),axis=1)
print(transition_matrix)
```
```

Output –

```				```
state       Downside    Upside
priorstate
Downside    0.595238  0.404762
Upside      0.515152  0.484848
```
```
So, Let’s find the transition matrix at t=1 again.
```				```
t_0 = transition_matrix.copy()
t_1 =t_0.dot(t_0)
t_1
```
```

Output –

```				```
state   	Downside	Upside
priorstate
Downside	0.562822	0.437178
Upside  	0.556408	0.443592
```
```

The Initial Transition Matrix

Just putting the image of Transition Matrix to help to visualize!

## Construction of the Markov Chain Using Python

`Just syncing with the last chapter where we discussed this in Linear Algebra section, `Here the `π_0 = t_0 = A`.

Now, We need to extend the Markov Chain similarly. You can refer the below diagram if it helps to recall.

So,  `π_1.A =`

Similarly,  `π_2.A =`

If we continue multiplying the transition matrix that we have obtained in `t=1` by the original transition matrix in t0, we obtain the probabilities in time `t=2`. Let’s find the transition matrix at `t=2` and `t=3` and so on in a similar manner.

```				```
t_2 = t_0.dot(t_1)
t_2
```
```

Output –

```				```
state   	Downside	    Upside
priorstate
Downside	0.560226	0.439774
Upside  	0.559712    0.440288
```
```
```				```
t_3 = t_0.dot(t_2)
t_3
```
```

Output –

```				```
state	    Downside	Upside
priorstate
Downside	0.560018	0.439982
Upside	    0.559977	0.440023
```
```

Let’s Normalize –

```				```
import numpy as np
pd.DataFrame(np.linalg.matrix_power(t_0,4))
```
```

Output –

```				```
#
0	        1
0	0.560018	0.439982
1	0.559977	0.440023
```
```

This `numpy` trick gives us identical results. If You know the rules of Linear Algebra it will make sense as our `π_0 = t_0 = A`. So, We are raising the initial transition matrix to `n` days to obtain the same result. So –

```				```
t_n = pd.DataFrame(np.linalg.matrix_power(t_0,n+1))
```
```

## Finding Equilibrium Matrix using Python

To find out the equilibrium matrix we can iterate the process up to the probabilities don’t change more.

Input –

```				```
t_0 = transition_matrix.copy()

t_m = t_0.copy()
t_n = t_0.dot(t_0)

i = 1
while(not(t_m.equals(t_n))):
i += 1
t_m = t_n.copy()
t_n = t_n.dot(t_0)

print("Equilibrium Matrix Number: " + str(i))
print(t_n)
```
```

Output –

```				```
Equilibrium Matrix Number: 16
state       Downside  Upside
priorstate
Downside        0.56    0.44
Upside          0.56    0.44
```
```

So, t = 16, We get our equilibrium matrix.

## What is the meaning of Equilibrium Matrix?

The equilibrium Matrix is a stationary state. So, As per the theory of the Markov Chain, This figure will stay the same for foreseeable data points (hence, future) right? Let’s test it on ∞ days like We did while doing our random walk.

Input –

```				```
symbol = "NIFTY 50"
days = 9209
end_date = datetime.datetime.now().strftime("%d-%b-%Y")
end_date = str(end_date)

start_date = (datetime.datetime.now()- datetime.timedelta(days=days)).strftime("%d-%b-%Y")
start_date = str(start_date)

df=index_history("NIFTY 50",start_date,end_date)

df["state"]=df["CLOSE"].astype(float).pct_change()
df['state']=df['state'].apply(lambda x: 'Upside' if (x > 0) else 'Downside' )

df['priorstate']=df['state'].shift(1)

states = df [['priorstate','state']].dropna()
states_matrix = states.groupby(['priorstate','state']).size().unstack().fillna(0)

transition_matrix= states_matrix.apply(lambda x: x/float(x.sum()),axis=1)
t_0 = transition_matrix.copy()

t_m = t_0.copy()
t_n = t_0.dot(t_0)

i = 1
while(not(t_m.equals(t_n))):
i += 1
t_m = t_n.copy()
t_n = t_n.dot(t_0)

print("Equilibrium Matrix Number: " + str(i))
print(t_n)
```
```

Output –

```				```
Equilibrium Matrix Number: 15
state       Downside    Upside
priorstate
Downside    0.536083  0.463917
Upside      0.536083  0.463917
```
```

So, t = 15, We get our equilibrium matrix.

Anyways, the number of the matrix where we get the equilibrium does not matter much. What matters is the values. You can see the values are really close!

Interpreting,

`P(priorstate="Downside"/state="Downside)` i.e. If We had a Downside day today, Tomorrow there is 53.6083% probability of having a Downside day.

Similarly,

If We had a Downside day today, Tomorrow there is 46.3917% probability of having an Upside day.

×Close