I am trying to apply PCA to portfolio of securities. My understanding is that the first principal component can be used to evaluate weights for portfolio of maximum variance and each next principal portfolio would have lower variance of returns. I implemented the following Python code:
import pandas_datareader as web import sklearn.decomposition import pandas as pd import numpy as np start="1/1/2016" end="1/1/2020" engine = 'stooq' MSFT = web.DataReader('MSFT.US',engine,start=start,end=end)[::-1] AAPL = web.DataReader('AAPL.US',engine,start=start,end=end)[::-1] AMZN = web.DataReader('AMZN.US',engine,start=start,end=end)[::-1] GOOG = web.DataReader('QQQ.US',engine,start=start,end=end)[::-1] stocks = [MSFT,AAPL,AMZN,GOOG] snames = ['MSFT','AAPL','AMZN','QQQ'] # build returns for sname, stock in zip(snames, stocks): stock['ret']=stock.Close/stock.Close.shift(1)-1 stock.dropna(inplace=True) ret = pd.DataFrame() ret = pd.concat([stock.iloc[:,-1] for stock in stocks],axis=1) ret.columns = snames # PCA decomposition sklearn_pca = sklearn.decomposition.PCA() sklearn_pca.fit_transform(ret) eVec = pd.DataFrame(sklearn_pca.components_) for i in range(eVec.shape): eVec.iloc[i,:] /= eVec.iloc[i,:].sum() # Print print("Eigenvectors: ") print (eVec) print portfolio_ret = np.dot(ret,eVec.T) print("Explained variance: ",sklearn_pca.explained_variance_) print("std dev comparison:") for i in range(eVec.shape): print("std in principal portfolio: "+str(i)+" ",portfolio_ret[:,i].std())
I get the following output from my code:
Eigenvectors: 0 1 2 3 0 0.261228 0.257406 0.268283 0.213082 1 1.498299 12.356333 -15.088625 2.233993 2 34.957326 -23.782872 -15.253020 5.078566 3 -2.170364 -1.577372 -0.700586 5.448321 Explained variance: [9.10267304e-04 1.57918603e-04 8.46751096e-05 1.54724748e-05] std dev comparison: std in principal portfolio: 0 0.015135846955727339 std in principal portfolio: 1 0.24730052498285351 std in principal portfolio: 2 0.41607045895649003 std in principal portfolio: 3 0.024037508433806268
From the above output
Explained variance indicates that eigenvectors are listed in descending order of variance. The PCA analysis seems to be correct.
Above I calculated returns for principal portfolios corresponding to eigenvectors. What I don't understand is why standard deviations of returns are the lowest for the principal portfolio corresponding to the first (0th in Python's convention) eigenvector (
I would expect it to be the highest as this should be portfolio maximizing the std, variance and thus the risk.
EDIT: It was suggested in comments that the PCA part could be split into atomic operations for better understanding. Here is the equivalent code for evaluation of eigenvalues and eigenvectors before scaling:
ret_dm = ret - ret.mean(axis=0) # de-mean cov = np.cov(ret_dm.T) # compute the covariance matrix eVal, eVec = np.linalg.eig(cov) # sort vectors and values by descending eigenvalue indices = eVal.argsort()[::-1] # sort args descending eVal, eVec = eVal[indices], eVec[:,indices] # transform to row eigenvectors eVec = eVec.T