Mar-15-2021, 03:35 PM
Hello Guys!
I am fairly new to Python and I am seeking for help.
I am trying to do the parametric portfolio optimization by Brandt. (2009)
with the dataset of Kenneth French´s 3 Factor Model (Dataset can be found here: https://mba.tuck.dartmouth.edu/pages/fac...brary.html
My code so far is:
It may have to do with the Dimensions, but
I cant seem to find an answer for it.
I would be really grateful for any ideas and suggestions.
Best regards,
Steffen
I am fairly new to Python and I am seeking for help.
I am trying to do the parametric portfolio optimization by Brandt. (2009)
with the dataset of Kenneth French´s 3 Factor Model (Dataset can be found here: https://mba.tuck.dartmouth.edu/pages/fac...brary.html
My code so far is:
import pandas as pd import numpy as np import matplotlib.pyplot as plt import scipy.stats as st import sympy as sp import scipy as sp # The Code for the Optimization and the Scaling is taken from: https://github.com/Seaaann/Parametric-Portfolio-Policy #MIT License #Copyright © 2020 SySean #Permission is hereby granted, free of charge, to any person obtaining a copy #of this software and associated documentation files (the "Software"), to deal #in the Software without restriction, including without limitation the rights #to use, copy, modify, merge, publish, distribute, sublicense, and/or sell #copies of the Software, and to permit persons to whom the Software is #furnished to do so, subject to the following conditions: #The above copyright notice and this permission notice shall be included in all #copies or substantial portions of the Software. #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE #SOFTWARE. # importing data ff_factors = pd.read_csv('F-F_Research_Data_Factors.csv', skiprows = 3,index_col=0, nrows = 1135) del ff_factors["RF"] ff_factors.index = pd.to_datetime(ff_factors.index, format= '%Y%m') ff_factors.index = ff_factors.index + pd.offsets.MonthEnd() ff_factors = ff_factors.apply(lambda x: x/ 100) # creating different fama french factors returns= ff_factors excess = ff_factors["Mkt-RF"] size = ff_factors["SMB"] value = ff_factors["HML"] # creating means and std for scaling returns_mean = returns.mean(axis=1) excess_mean = excess.mean() size_mean = size.mean() value_mean = value.mean() returns_std = returns.std(axis=1) excess_std = excess.std() size_std = size.std() value_std = value.std() ## scaling the factors def Scale(y,c=True, sc=True): x = y.copy() if c: x -= x.mean() if sc and c: x /= x.std() elif sc: x /= np.sqrt(x.pow(2).sum().div(x.count() - 1)) return x scaled_excess = pd.DataFrame(Scale(excess.T)) scaled_size = pd.DataFrame(Scale(size.T)) scaled_value= pd.DataFrame(Scale(value.T)) Returns = returns.reset_index(drop=True) ## Parametric Portfolio Policies function def PPS(x, wb, nt, excess, size, value, rr): w1= wb + nt * (x[0] * excess) w2= wb + nt * (x[1]* size) w3= wb + nt * (x[2]* value) wret = (w1*excess + w2*size + w3*value).sum() ut = ((1 + wret) ** (1 - rr)) / (1 - rr) u = -(ut.mean()) return u Scaled_excess = scaled_excess.reset_index(drop = True) Scaled_size = scaled_size.reset_index(drop=True) Scaled_value = scaled_value.reset_index(drop=True) nt = wb = 1/ np.shape(returns)[1] rr = 5 res_save = [] weights = [] x0 = np.array([0,0,0]) for i in range(0, 60): opt = sp.optimize.minimize( PPS, x0, method="BFGS", args=( wb, nt, Scaled_excess.iloc[0:1075+i], Scaled_size.iloc[0:1075+i], Scaled_value.iloc[0:1075 + i], rr, ), ) print("The {} window".format(i + 1)) print("The value:", opt["x"]) res_save.append(opt["x"]) w = wb + nt * ( opt["x"][0] * Scaled_excess.iloc[i + 1075, :] + opt["x"][1] * Scaled_size.iloc[i + 1075, :] + opt["x"][2] * Scaled_value.iloc[i+ 1075, :] ) print(w) weights.append(w) index = returns.index[1075:1135] char_df = pd.DataFrame(res_save, index=index, columns=["Excess","Value","Size"])The main problem I have right now is that the optimal weights are optimized as NaN:
Output:The 60 window
The value: [0. 0. 0.]
HML NaN
Mkt-RF NaN
SMB NaN
Name: 1134, dtype: float64
Instead of the decimals of the optimal weights. It may have to do with the Dimensions, but
I cant seem to find an answer for it.
I would be really grateful for any ideas and suggestions.
Best regards,
Steffen