Cov shrink matrix with average correlation

Hello World!

I have a my covariance matrix with let's say 500 assets and I need to replace my "initial" Covmatrix with shrinked one by changing all the correlations inside by their average. On the diagonal I would have the variances and others are covariances but with correlation_mean×sd1×sd2 ... No idea so far for me. Please help me someone :frowning:

Welcome to the community!

Can you please describe more elaborately, preferably with an example, what do you mean by this?

It'll be best if you create a small dataset, say 10 observations 5 variables (set a seed for reproducibility, for example 42045), calculate usual covariance matrix, and show us your desired result (possibly defining manually). We'll also appreciate if you please share all these in form of a REPRoducible EXample (reprex in short).

If you're unfamiliar with reprex, please take a look at this FAQ.

X=read.delim(file.choose(),sep=";",header=FALSE) # Loading the data
X=diff(as.matrix(log(X)),1) # computing returns
mu=apply(X,2,mean) # Estimating expectation
sigma=cov(X) # Estimating covariance
sigma_inv=solve(sigma) # Inverting covariance
gamma=3 # Setting the risk aversion parameter
w=1/gammasigma_inv%%mu # Computing the optimal weights
w=w/sum(w) # rescaling the parameters to be make sure portfolio weight sum to 1
RP=X%*%w
P=cumprod(1+RP)
plot(log(P),type="l",ylim=c(0,25),xlab="Time",ylab="log performance")

Splitting the sample in two

index=nrow(X)/2 # defining the size of the sample used to estimated the moments
mu=apply(X[1:index,],2,mean)
sigma=cov(X[1:index,])
sigma_inv=solve(sigma)
gamma=3
w=1/gammasigma_inv%%mu
w=w/sum(w)
RP=X%*%w
P=cumprod(1+RP)
lines(log(P),type="l",col="red")
legend("topleft",c("Full sample","Half sample"),col=c(1,2),lty=1)

w_total=c()
w_sigma=c()
w_mu=c()
count=0
for (i in 1:1000)
{
u=round(runif(1,1000,nrow(X)),0)
sample=X[(u-499):(u),]
check=try(solve(var(sample)),silent=TRUE)
if (is.character(check))
{
count=count+1
}else{
mu_temp=apply(sample,2,mean)
sigma_inv_temp=solve(cov(sample))
temp=1/gammasigma_inv_temp%%mu

w_sigma=rbind(w_sigma,t(temp))
temp=1/gamma*sigma_inv%*%mu_temp

w_mu=rbind(mu_temp,t(temp))
temp=1/gamma*sigma_inv_temp%*%mu_temp
w_total=rbind(w_total,t(temp))

}
print(c(i,count/500))
}

X[mu(mu+500),]

par(mfrow=c(1,3))
boxplot((w_total[,1:20]), main="MU AND SIGMA UPDATED")
boxplot((w_mu[,1:20]), main="MU UPDATED")
boxplot((w_sigma[,1:20]), main= "SIGMA UPDATED")

F= I , lambda = 0.2, minimizing parameter

par(mfrow=c(1,1))
lambda=0.2
sigmashrinked=0.8sigma+0.2diag(452) # the identity matrix has to be length of 452 to correspond to the size
sigmashrinked

boxplot(sigmashrinked, xlim=c(0,20), ylim=c(-10,10))

####################2-2

corelation_matrix= cor(sigma) - diag(452)

ro_tot=sum(corelation_matrix)
sqr= 451*452 # divided by two means
cons_corr=ro_tot/(sqr)

ro_sig=cons_corr*sigma

mat1= (matrix(1,452,452)-diag(452))cons_corr + diag(452)
verdict=mat1%
%sigma
verdict

debut=sigma*cons_corr

diagmat=diag(452)*debut
milieu=debut-diagmat
diasig=diag(452)*sigma
fin=milieu+diasig

sigmashrinked_second=0.8sigma+0.2fin
boxplot(sigmashrinked_second, xlim=c(0,20), ylim=c(-10,10))

This is certainly not what I meant. This is certainly copy-paste friendly, but neither reproducible (as there is no data), nor illustrative of your problem.

Please go through the guide I shared earlier, and provide only the code necessary for you to illustrate what you have and what you want to have. I think if you follow the outline I suggested in my earlier post, that'll be sufficient in this case.

1 Like

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.