EfficientFrontier
Documentation for EfficientFrontier.
EfficientFrontier.EfficientFrontier
EfficientFrontier.Event
EfficientFrontier.Problem
EfficientFrontier.Settings
EfficientFrontier.Status
EfficientFrontier.sCL
EfficientFrontier.sEF
LightenQP.OOQP
EfficientFrontier.ECL
EfficientFrontier.ECL!
EfficientFrontier.EVdata
EfficientFrontier.L2mu
EfficientFrontier.LightenCL!
EfficientFrontier.SettingsLP
EfficientFrontier.SettingsQP
EfficientFrontier.SimplexCL!
EfficientFrontier.cbCL!
EfficientFrontier.computeCL!
EfficientFrontier.eFrontier
EfficientFrontier.ePortfolio
EfficientFrontier.mu2L
LightenQP.fPortfolio
EfficientFrontier.EfficientFrontier
— ModuleEntire Efficient Frontier by Status-Segment Method
EfficientFrontier.Event
— Type struct Event{T<:AbstractFloat}
Events that assets go IN/OUT(DN or UP), or inequalities go binded (EO, as equality) or not (OE, original ineq), with fields:
From::Status
To::Status
id::Int #asset ID
L::T #L
EfficientFrontier.Problem
— Type Problem(E::T, V; u, d, G, g, A, b, equilibrate) where T
Problem(E::T, V, u; equilibrate) where T
Problem(E::T, V, u, d; equilibrate) where T
Problem(E::T, V, u, d, G, g; equilibrate) where T
Problem(E::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 s.t. z′E = μ Az = b ∈ R^{M} Gz ≤ g ∈ R^{J} d ≤ z ≤ u ∈ R^{N}\]
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(aEF, mu) #weight of the efficient portfolio given mu
See Documentation for EfficientFrontier.jl
See also EfficientFrontier.ECL
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 #general scalar
tolNorm::T #for norms
tolS::T #for identifying S
tolL::T #for L
tolG::T #for Greeks (beta and gamma)
muShft::T #shift the mu to (1 +/- muShft)*mu
EfficientFrontier.Status
— Type @enum Status
Status: assets go IN/OUT(DN or UP), or inequalities go binded (EO, as equality) or not (OE, original ineq), with fields:
IN #within the lower and upper bound
DN #down, lower bound
UP #upper bound
OE #original <= not binded
EO #edge, <= as =
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::Integer #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{Int64} #id of related critical line
LightenQP.OOQP
— MethodEfficientFrontier.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::Integer #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.LightenCL!
— Method LightenCL!(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
settings : for LightenQP solver, chance for a QP solver needed is <=0.1% (when the corner portfolio is degenerated, or infinite many solutions to SimplexLP encounted)
settingsLP : `SimplexLP.Settings`, for SimplexLP solver, we always first try the SimplexLP, and a chance of >=99.9% we find the critical line
See also cbCL!
, Problem
, Settings
, SettingsQP
EfficientFrontier.SettingsLP
— MethodSettingsLP(P::Problem; kwargs...)
Settings for SimplexLP
's numerical solver Settings
See also EfficientFrontier.Simplex.Settings
EfficientFrontier.SettingsQP
— MethodSettingsQP(P::Problem; kwargs...)
Settings for LightenQP
's numerical solver Settings
See also LightenQP.Settings
EfficientFrontier.SimplexCL!
— Method SimplexCL!(aCL::Vector{sCL{T}}, PS::Problem{T}; nS=Settings(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 : `SimplexLP.Settings`, for SimplexLP solver, we always first try the SimplexLP, and a chance of >=99.9% we find the critical line
when the remaining <=0.1% 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{Int64} #id of related critical line
end
See also EfficientFrontier.ECL
, ePortfolio
, Problem
, Settings
EfficientFrontier.ePortfolio
— Method z = ePortfolio(aEF::sEF, mu)
z = ePortfolio(P::Problem, mu; nS=Settings(P)) #one-step, given mu
z = ePortfolio(aCL::Vector{sCL}, P::Problem, L)
z = ePortfolio(P::Problem; nS=Settings(P), settings, settingsLP, L::T=0.0) #one-step, given L
ePortfolio(aEF, mu)
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(P, mu; nS=Settings(P))
compute the efficient portfolio for P
given mu, returns portfolio weights z (Nx1 vector of NaN if mu is out of range) If mu is a vector, z is a matrix, its row k is the portfolio weights for mu[k]. Here you can not set init::Function
ePortfolio(aCL, P, L)
compute the efficient portfolio for P
with known Critical Lines aCL
, given L
ePortfolio(P::Problem; nS=Settings(P), settings, settingsLP, L::T=0.0)
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
LightenQP.fPortfolio
— Method x = fPortfolio(P::Problem; settingsLP=settingsLP, L=0) # active-set numerical solver
x, status = fPortfolio(P::Problem, mu; settings=SettingsQP, check=true) # `LightenQP`'s numerical solver
compute frontier portfolio at given L
or mu
.
L=-Inf :FP(L=-Inf), LMFP (Lowest Mean Frontier Portfolio)
L=+Inf :FP(L=+Inf), HMFP (Highest Mean Frontier Portfolio) == HVEP (Highest Variance Efficient Portfolio) == HMEP (Highest Mean Efficient Portfolio)
L=L0 :FP(L=L0), the frontier (minimum variance) portfolio at L=L0. L=0, LVEP (Lowest Variance Efficient Portfolio, also called GMVP, Global Minimum Variance Portfolio)
mu=-Inf :FP(L=-Inf), LMFP (Lowest Mean Frontier Portfolio)
mu=+Inf :FP(L=+Inf), HMFP (Highest Mean Frontier Portfolio) == HVEP (Highest Variance Efficient Portfolio) == HMEP (Highest Mean Efficient Portfolio)
mu=mu0 :FP(mu=mu0), the frontier (minimum variance) portfolio at mu=mu0
if check=false
, we do not check if mu is feasible or not (between lowest and highest mean)
See also ePortfolio
, Problem
, SettingsQP
, LightenQP.fPortfolio