Mar-15-2021, 03:35 PM
(This post was last modified: Mar-15-2021, 05:43 PM by schnellinga.)
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: float64Instead 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
