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.SettingsLP
EfficientFrontier.SettingsQP
EfficientFrontier.SimplexCL!
EfficientFrontier.cbCL!
EfficientFrontier.computeCL!
EfficientFrontier.eFrontier
EfficientFrontier.ePortfolio
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
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), 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 degenarated, 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.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))
ePortfolio(aEF::sEF, 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::Problem, 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
See also EfficientFrontier.ECL
, eFrontier
, Problem
, Settings
LightenQP.fPortfolio
— Method x, status = fPortfolio(P::Problem; settings=SettingsQP, L=0)
x, status = fPortfolio(P::Problem, mu; settings=SettingsQP, check=true)
compute frontier portfolio at given L or mu, using LightenQP
's numerical solver fPortfolio
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)
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)
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