In [1]:
using Dates, DelimitedFiles, Statistics
include("jlFiles/printmat.jl")
include("jlFiles/printTable.jl")
Out[1]:
In [2]:
using Plots
#pyplot(size=(600,400)) #pyplot or gr
gr(size=(480,320))
default(fmt = :svg)
In [3]:
(x,header) = readdlm("Data/Fin1PerfEvalEmp.csv",',',header=true)
(IndNames,FundNames) = (header[2:9],header[10:11]) #names of variables
dN = Date.(x[:,1],"yyyy-mm-dd") #convert to Date
(Rb,RFunds,Rf) = (convert.(Float64,x[:,2:9]),convert.(Float64,x[:,10:11]),
convert.(Float64,x[:,12])); #convert to Float64
In [4]:
Re = RFunds .- Rf #excess returns of the funds
Rme = Rb[:,1] - Rf #excess returns of the market (S&P 500)
μᵉp = mean(Re,dims=1) #average excess returns of funds, 1xn
σp = std(Re,dims=1) #std, 1xn
μᵉm = mean(Rme) #average excess returns of market
σm = std(Rme)
SRp = (μᵉp./σp)*sqrt(52) #Sharpe ratio
SRm = (μᵉm/σm)*sqrt(52)
M2p = (SRp.-SRm)*σm*sqrt(52)*100
M2m = 0 #(SRm.-SRm)*σm=0
xut = hcat([μᵉm;μᵉp']*52*100,[SRm;SRp'],[M2m;M2p'])
printTable(xut,["ERe","SR","MM"],["Market";FundNames])
In [5]:
T = size(Re,1)
x = [ones(T) Rme]
b = x\Re #2xn, OLS Re = α + β*Rme + ϵ, n = number of funds
ϵ = Re - x*b #Txn, residuals
σϵ = std(ϵ,dims=1) #1xn
ARp = (b[1:1,:]*52*100)./(σϵ*sqrt(52)*100) #b[1:1,:] is 1xn
ARm = 0
xut = [ARm;ARp']
printTable(xut,["AR"],["Market";FundNames])
In [6]:
TRp = 52*100*μᵉp./b[2:2,:]
TRm = 52*100*μᵉm/1 #market has β=1
T2p = TRp .- μᵉm*52*100
T2m = 0 #TRm - μᵉm*52*100
xut = hcat([TRm;TRp'],[T2m;T2p'])
printTable(xut,["TR","T2"],["Market";FundNames])
using the JuMP and Ipopt packages.
Notice:
(a) The regression is $Y = b_1 X_1 + ...+ b_K X_K + u$,
where $0 <= b_j$ and $\sum_{i=1}^{K}b_i = 1$.
(b) Write the sum of squared residuals of the regression as
$(Y-Xb)'(Y-Xb) = Y'Y - 2Y'Xb + b'X'Xb$.
Only the two last terms matter for the choice of $b$.
(c) To minimize $- 2Y'Xb + b'X'Xb$, we use the JuMP package. To speed up the iteration we calculate $Y'X$ and $X'X$ only once.
Notice, we could equally well minimize $(Y-Xb)'(Y-Xb)$, but that is slower since we have re-evaluate the whole expression (including $Y'Y$ and $X'X$) in each iteration.
In [7]:
using JuMP, Ipopt
function StyleAnalysisPs(Y,X)
(T,K) = (size(X,1),size(X,2))
XX = X'X #calculate XX and YX once
YX = Y'X
b_ls = X\Y #LS estimate of weights, no restrictions
model = Model(optimizer_with_attributes(Ipopt.Optimizer,"print_level" => 1))
@variable(model,b[i=1:K] >= 0.0) #no short sales
@objective(model,Min,-2*YX*b + b'*XX*b) #min (Y-X*b)'*(Y-X*b) also works
@constraint(model,sum(b) == 1.0) #sums to 1
optimize!(model)
if has_values(model)
b_sa = value.(b)
else
b_sa = NaN
end
return b_sa,b_ls
end
Out[7]:
The next cell makes a "style analysis regression" based on the entire sample. The dependent variable is the first mutual fund in RFunds (see data loading) and all indices (again, see data loading) are used as regressors.
In [8]:
(b,b_ls) = StyleAnalysisPs(RFunds[:,1],Rb)
printblue("OLS and style analysis coeffs")
colNames = ["OLS" "Restricted LS"]
xut = [b_ls b;sum([b_ls b],dims=1)]
printTable(xut,colNames,[IndNames;"Sum"],width=15)
In [9]:
(T,K) = size(Rb)
WinSize = 104
b = fill(NaN,(T,K))
for t = (WinSize+1):T
#local vv #only needed in REPL/script
vv = (t-WinSize):t
b[t,:] = StyleAnalysisPs(RFunds[vv,1],Rb[vv,:])[1]
end
In [10]:
xTicksLoc = Dates.value.([Date(2000);Date(2005);Date(2010);Date(2015)])
xTicksLab = ["2000";"2005";"2010";"2015"]
p1 = plot( dN,b,
layout = (3,3),
legend = false,
size = (800,600),
linecolor = :blue,
xticks = (xTicksLoc,xTicksLab),
ylims = (0,0.6),
title = [permutedims(IndNames) ""],
titlefont =font(10) )
#modify subplot [3,3] to be blank
plot!(p1[3,3],legend=false,grid=false,foreground_color_subplot=:white)
Out[10]:
In [ ]: