Python Forum
Parametric portfolio optimization by Brandt 2009
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Parametric portfolio optimization by Brandt 2009
#1
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:
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
Reply


Messages In This Thread
Parametric portfolio optimization by Brandt 2009 - by schnellinga - Mar-15-2021, 03:35 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  Stock clustering and portfolio diversification. Suitable features. timurkanaz 1 392 Mar-27-2024, 09:54 AM
Last Post: Larz60+
  How implement parametric ODE equation in python meesmaeili 1 2,279 Oct-16-2018, 01:39 AM
Last Post: scidam

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020