I am trying to create a minimum variance portfolio based on 1 year of data. I then want to rebalance the portfolio every month recomputing thus the covariance matrix. (my dataset starts in 1992 and finishes in 2017).
I did the following code which works when it is not in a loop. But when put in the loop the inverse of the covariance matrix is Singular. I don't understand why this problem arises since I reset every variable at the end of the loop.
### Importing the necessary libraries ###
import pandas as pd
import numpy as np
from numpy.linalg import inv
### Importing the dataset ###
df = pd.read_csv("UK_Returns.csv", sep = ";")
df.set_index('Date', inplace = True)
### Define varibales ###
stocks = df.shape[1]
returns = []
vol = []
weights_p =[]
### for loop to compute portfolio and rebalance every 30 days ###
for i in range (0,288):
a = i*30
b = i*30 + 252
portfolio = df[a:b]
mean_ret = ((1+portfolio.mean())**252)-1
var_cov = portfolio.cov()*252
inv_var_cov = inv(var_cov)
doit = 0
weights = np.dot(np.ones((1,stocks)),inv_var_cov)/(np.dot(np.ones((1,stocks)),np.dot(inv_var_cov,np.ones((stocks,1)))))
ret = np.dot(weights, mean_ret)
std = np.sqrt(np.dot(weights, np.dot(var_cov, weights.T)))
returns.append(ret)
vol.append(std)
weights_p.append(weights)
weights = []
var_cov = np.zeros((stocks,stocks))
inv_var_cov = np.zeros((stocks,stocks))
i+=1
Does anyone has an idea to solve this issue?
The error it yields is the following:
---------------------------------------------------------------------------
LinAlgError Traceback (most recent call last)
<ipython-input-17-979efdd1f5b2> in <module>()
21 mean_ret = ((1+portfolio.mean())**252)-1
22 var_cov = portfolio.cov()*252
---> 23 inv_var_cov = inv(var_cov)
24 doit = 0
25 weights = np.dot(np.ones((1,stocks)),inv_var_cov)/(np.dot(np.ones((1,stocks)),np.dot(inv_var_cov,np.ones((stocks,1)))))
<__array_function__ internals> in inv(*args, **kwargs)
1 frames
/usr/local/lib/python3.6/dist-packages/numpy/linalg/linalg.py in _raise_linalgerror_singular(err, flag)
95
96 def _raise_linalgerror_singular(err, flag):
---> 97 raise LinAlgError("Singular matrix")
98
99 def _raise_linalgerror_nonposdef(err, flag):
LinAlgError: Singular matrix
Thank you so much for any help you can provide me with!
The data is shared in the following google drive: https://drive.google.com/file/d/1-Bw7cowZKCNU4JgNCitmblHVw73ORFKR/view?usp=sharing
It would be better to identify what is causing the singularity of the matrix but there are means of living with singular matrices.
Try to use pseudoinverse by np.linalg.pinv()
. It is guaranteed to always exist.
See pinv
Other way around it is avoid computing inverse matrix at all. Just find Least Squares solution of the system. See lstsq
Just replace np.dot(X,inv_var_cov)
with
np.linalg.lstsq(var_conv, X, rcond=None)[0]