EfficientFrontier.EfficientFrontier
— ModuleEntire Efficient Frontier by Status-Segment Method
EfficientFrontier.Problem
— Type Problem(E::Vector{T}, V; u, d, G, g, A, b, equilibrate) where T
Problem(E::Vector{T}, V, u; equilibrate) where T
Problem(E::Vector{T}, V, u, d; equilibrate) where T
Problem(E::Vector{T}, V, u, d, G, g; equilibrate) where T
Problem(E::Vector{T}, V, u, d, G, g, A, b; equilibrate) where T
Setup a Portfolio Selection model: for mean vector E and variance matrix V
\[ min (1/2)z′Vz - L⋅z′E s.t. Az = b ∈ R^{M} Gz ≤ g ∈ R^{J} d ≤ z ≤ u ∈ R^{N}\]
From L=+∞ to L=0. Default values: u = +∞, d = 0, G = [], g = [], A = ones(1,N), b = [1], and equilibrate = false
Example
using EfficientFrontier
V = [1/100 1/80 1/100
1/80 1/16 1/40
1/100 1/40 1/25] #variance matrix
E = [109 / 100; 23 / 20; 119 / 100] #mean vector
P = Problem(E, V) #Default models, non-shortsale
aCL = EfficientFrontier.ECL(P) #compute all Critical Lines
aEF = eFrontier(aCL, P) #compute the Efficient Frontier
mu = (aEF.mu[1]+aEF.mu[end])/2 #mu at the middle of Efficient Frontier
z = ePortfolio(mu, aEF) #weight of the efficient portfolio given mu
See Documentation for EfficientFrontier.jl
See also EfficientFrontier.ECL
, eFrontier
, ePortfolio
EfficientFrontier.Settings
— Type Settings(P::Problem; kwargs...) The default Settings to given Problem
Settings(; kwargs...) The default Settings is set by Float64 type
Settings{T<:AbstractFloat}(; kwargs...)
kwargs are from the fields of Settings{T<:AbstractFloat} for Float64 and BigFloat
tol::T #2^-26 ≈ 1.5e-8 general scalar
tolN::T #2^-26 ≈ 1.5e-8 for norms
tolS::T #2^-26 ≈ 1.5e-8 for identifying S
tolL::T #2^-26 ≈ 1.5e-8 for L
tolG::T #2^-27 ≈ 7.5e-9 for Greeks (beta and gamma)
muShft::T #2^-18 ≈ 3.8e-6 shift the mu to (1 +/- muShft)*mu
EfficientFrontier.sCL
— Type sCL(P::Problem) define an empty Vector of struct sCL for Problem P
struct sCL{T<:AbstractFloat}
Critical Line segment, with fields: default T = Float64
S::Vector{Status} # (N+J)x1
K::Int #number of IN assets
L1::T #higher lambda
I1::Vector{Event{T}} #go in/out events at L1
L0::T #lower lambda
I0::Vector{Event{T}} #go in/out events at L0
alpha::Vector{T} # K x 1
beta::Vector{T} # K x 1
EfficientFrontier.sEF
— Type struct sEF
Efficient Frontier, with fields:
Ap::Matrix{Float64} # v=a₂μ²+a₁μ+a₀, each row [a₂ a₁ a₀]
mu::Vector{Float64} #higher mean
sgm::Vector{Float64} #higher sigma
Z::Matrix{Float64} #weights, each corner portfolio in one row
ic::Vector{Int} #id of related critical line
EfficientFrontier.ECL!
— Method ECL!(aCL::Vector{sCL{T}}, PS::Problem{T}; numSettings = Settings(PS), incL=false, settings=SettingsQP(PS), settingsLP=SettingsLP(PS)) where T
compute all the Critical Line Segments as L decreasing to 0 (increasing to +Inf if incL=true), given the first one in aCL[end]. The settings
is the LightenQP.Settings
setting from LightenQP Return value: true if done
EfficientFrontier.ECL
— Method aCL = ECL(PS::Problem; init::Function=SimplexCL!; numSettings = Settings(PS), settings=SettingsQP(PS), settingsLP=SettingsLP(PS))
compute all the Critical Line Segments. Init the CL by Simplex Method (combinatorial search init=cbCL!
)
the return aCL has the follwing structure
struct sCL{T<:AbstractFloat} #critical line segment
S::Vector{Status} # (N+J)x1
K::Int #number of IN assets
L1::T #higher lambda
I1::Vector{Event{T}} #go in/out events at L1
L0::T #lower lambda
I0::Vector{Event{T}} #go in/out events at L0
alpha::Vector{T} # K x 1
beta::Vector{T} # K x 1
end
EfficientFrontier.EVdata
— Function EVdata(ds::Symbol, verbose=true)
extract some data sets
:Abad Abad's equilibrum data
:Markowitz Markowitz and Todd (2000), chapter 13, pp.337
:Ungil from https://github.com/ungil/Markowitz.jl/blob/master/examples/frontier.jl
:SP500 Hints to download the SP500 data set
EfficientFrontier.L2mu
— Method L2mu(aEF::sEF, aCL::Vector{sCL{T}}, mu::T) where T
compute mu from L
EfficientFrontier.SettingsLP
— MethodSettingsLP(P::Problem; kwargs...)
Settings for SimplexLP
's numerical solver Settings
See also StatusSwitchingQP.Settings
EfficientFrontier.SettingsQP
— MethodSettingsQP(P::Problem; kwargs...)
Settings for SSQP
's Status Switching solver Settings
See also StatusSwitchingQP.Settings
EfficientFrontier.SimplexCL!
— Method SimplexCL!(aCL::Vector{sCL{T}}, PS::Problem{T}; nS=Settings(PS), settings=SettingsQP(PS), settingsLP=SettingsLP(PS)) where T
compute the Critical Line Segments by Simplex method, for the highest expected return. Save the CL to aCL if done
settingsLP : for SimplexLP solver, we always first try the SimplexLP, and a chance of >=99.99% we find the critical line
when the remaining <=0.01% happens (when the corner portfolio is degenerated, or infinite many solutions to SimplexLP encounted),
we use ASQP, which use LP to obtain an initial point, so no SettingsQP needed
See also cbCL!
, Problem
, Settings
, SettingsQP
EfficientFrontier.cbCL!
— Method cbCL!(aCL::Vector{sCL{T}}, PS::Problem{T}; nS=Settings(PS), oneCL=true, K=PS.M+PS.J+1, kwargs...) where T
compute one or all (oneCL=false, K=PS.M) the Critical Line Segments by enumerating (combinations of Status). Save the CL(s) to aCL if done
See also SimplexCL!
, Problem
, Settings
EfficientFrontier.computeCL!
— Method computeCL!(aCL::Vector{sCL{T}}, S::Vector{Status}, PS::Problem{T}, nS::Settings{T}) where T
compute the Critical Line Segment for S::Vector{Status}, save to aCL[end]. Return value: true if done.
EfficientFrontier.eFrontier
— Method aEF = eFrontier(aCL::Vector{sCL{T}}, PS::Problem{T}; nS=Settings(PS)) where T
compute the Full Efficient Frontier by Status-Segment Method
the return aEF has the follwing structure
struct sEF #Efficient Frontier Float64 is OK
Ap::Matrix{Float64} # v=a₂μ²+a₁μ+a₀, each row [a₂ a₁ a₀]
mu::Vector{Float64} #higher mean
sgm::Vector{Float64} #higher sigma
Z::Matrix{Float64} #weights, each corner portfolio in one row
ic::Vector{Int} #id of related critical line
end
See also EfficientFrontier.ECL
, ePortfolio
, Problem
, Settings
EfficientFrontier.ePortfolio
— Method z = ePortfolio(mu, aEF::sEF)
z = ePortfolio(mu, P::Problem; nS=Settings(P), settings, settingsLP) #one-step, given mu
z = ePortfolio(P::Problem, L, aCL::Vector{sCL})
z = ePortfolio(P::Problem, L::T=0.0; nS=Settings(P), settings, settingsLP) #one-step, given L
ePortfolio(mu::Float64, aEF)
compute the efficient portfolio given mu when Efficient Frontier is known, returns portfolio weights z (Nx1 vector of NaN if mu is out of range)
ePortfolio(mu, P; nS=Settings(P))
compute the efficient portfolio for P
given mu::Float64, returns portfolio weights z (Nx1 vector of NaN if mu is out of range) If mu is a ::Vector{Float64}, z is a matrix, its row k is the portfolio weights for mu[k]. Here you can not set init::Function
ePortfolio(P, L::T, aCL)
compute the efficient portfolio for P
with known Critical Lines aCL
, given L::T
(Float64, BigFloat)
ePortfolio(P::Problem, L::T=0.0; nS=Settings(P), settings, settingsLP)
compute the efficient portfolio for P
given L
See also EfficientFrontier.ECL
, eFrontier
, Problem
, Settings
EfficientFrontier.mu2L
— Method mu2L(aEF::sEF, aCL::Vector{sCL{T}}, mu::T) where T
compute L from mu
StatusSwitchingQP.Simplex.SimplexLP
— Method SimplexLP(PS::Problem; settings=Simplex.Settings(PS), min=true)
find the Status
for assets by simplex method. If min=false
, we maximize the objective function
See also StatusSwitchingQP.Status
, Problem
, StatusSwitchingQP.Settings
, StatusSwitchingQP.Simplex.cDantzigLP
, StatusSwitchingQP.Simplex.maxImprvLP