EfficientFrontier

Documentation for EfficientFrontier.

EfficientFrontier.EventType
    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.ProblemType
    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.SettingsType
    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.StatusType
    @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.sCLType
    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.sEFType
    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
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.ECLMethod
    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

See Documentation for EfficientFrontier.jl

See also Problem, Settings

EfficientFrontier.EVdataFunction
    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.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.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.eFrontierMethod
    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.ePortfolioMethod
    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

LightenQP.fPortfolioMethod
    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