Skip to content

A Quick Example

PharosAbad edited this page Apr 26, 2023 · 10 revisions

Non-short-sale model

Given the no short-sale problem:

$$ \begin{array} [c]{cl} \min & \frac{1}{2}\mathbf{z}^{\prime}\mathbf{Vz}-L\mathbf{z}^{\prime }\boldsymbol{\mu}\\ s.t. & \mathbf{z}^{\prime}\mathbf{1}=1\\ & \mathbf{z}\geq 0\in\mathbb{R}^{N} \end{array} $$

with the data

using EfficientFrontier

V = [1/100 1/80 1/100
     1/80 1/16 1/40
     1/100 1/40 1/25]
E = [109 / 100; 23 / 20; 119 / 100]

Test it out: The Entire Efficient Frontier

We first define the no short-sale model by

P = Problem(E, V)

the model is stored in the Problem structure

Problem{Float64}([1.09, 1.15, 1.19], [0.01 0.0125 0.01; 0.0125 0.0625 0.025; 0.01 0.025 0.04], [Inf, Inf, Inf], [0.0, 0.0, 0.0], Matrix{Float64}(undef, 0, 3), Float64[], [1.0 1.0 1.0], [1.0], 3, 1, 0, false, 1.0, 1.0)

Now, we are ready to compute the ENTIRE frontier

aCL = EfficientFrontier.ECL(P)
4-element Vector{sCL{Float64}}:
 sCL{Float64}(Status[DN, DN, IN], 1, Inf, Event{Float64}[], 0.37499999999999967, Event{Float64}[Event{Float64}(DN, IN, 2, 0.37499999999999967)], [1.0000000000000002], [-8.455458555545192e-15])
 sCL{Float64}(Status[DN, IN, IN], 2, 0.3749999999999996, Event{Float64}[Event{Float64}(DN, IN, 2, 0.3749999999999996)], 0.2884615384615385, Event{Float64}[Event{Float64}(DN, IN, 1, 0.2884615384615385)], [0.28571428571428575, 0.7142857142857143], [-0.7619047619047628, 0.7619047619047592])
 sCL{Float64}(Status[IN, IN, IN], 3, 0.28846153846154, Event{Float64}[Event{Float64}(DN, IN, 1, 0.28846153846154)], 0.13636363636363846, Event{Float64}[Event{Float64}(IN, DN, 2, 0.13636363636363846)], [1.0344827586206895, -0.05911330049261083, 0.02463054187192118], [-3.5862068965517047, 0.43349753694580606, 3.1527093596059146])
 sCL{Float64}(Status[IN, DN, IN], 2, 0.13636363636363644, Event{Float64}[Event{Float64}(IN, DN, 2, 0.13636363636363644)], 0.0, Event{Float64}[Event{Float64}(IN, DN, 3, 0.0)], [1.0, 0.0], [-3.3333333333333286, 3.3333333333333286])

Corner Portfolios

From the efficient frontier aCL, we can compute the corner portfolios

aEF = eFrontier(aCL, P)
sEF([32.81250000000447 -77.34375000001053 45.61328125000621; 2.9301385681291876 -6.381351039260658 3.4842306581984444; 3.0000000000000067 -6.540000000000015 3.574300000000008; 3.0000000000000067 -6.540000000000015 3.574300000000008], [1.1899999999999984, 1.1873626373626427, 1.1354545454545455, 1.09], [0.19999999999999973, 0.1955766124237118, 0.12727272727272723, 0.1], [0.0 0.0 0.9999999999999987; 0.0 0.06593406593406467 0.9340659340659397; 0.5454545454545459 0.0 0.45454545454545414; 1.0 0.0 0.0], [2, 3, 4, 4])

The corner portfolio: $\mu$ and $\sigma$

julia> [aEF.mu aEF.sgm]
4×2 Matrix{Float64}:
 1.19     0.2
 1.18736  0.195577
 1.13545  0.127273
 1.09     0.1

The corner portfolio: weights

julia> aEF.Z
4×3 Matrix{Float64}:
 0.0       0.0        1.0
 0.0       0.0659341  0.934066
 0.545455  0.0        0.454545
 1.0       0.0        0.0

Remark: it is a pity that the Julia's Computer Algebra System (CAS) is still clumsy. Using CAS, you will find the analytical result is

 0.0    0.0      1.0
 0.0    6/91     85/96
 6/11   0.0      5/11
 1.0    0.0      0.0

Parabola Segments (Frontiers)

The corner portfolio: parabola segments $v=a_{2}\mu^{2}+a_{1}\mu+a_{0}$ in the $\mu-v$ plane

julia> aEF.Ap
4×3 Matrix{Float64}:
 32.8125   -77.3438   45.6133
  2.93014   -6.38135   3.48423
  3.0       -6.54      3.5743
  3.0       -6.54      3.5743

Find an efficient portfolio at given expected rate of return

mu = (aEF.mu[1]+aEF.mu[end])/2
z = ePortfolio(mu, aEF)  #ePortfolio(aEF, mu)
3-element Vector{Float64}:
 0.4976905311778428
 0.005773672055425533
 0.4965357967667321

Tangent Point of Adjacent Frontier

The 2nd corner portfolio is the tangent point of the 1st and 2nd segments of frontier on E-V plane

# a₀+a₁x+a₂x²=b₀+b₁x+b₂x² ==> c₂x²+c₁x+c₀=0, c_{i}=a_{i}-b_{i}
c2 = aEF.Ap[1,1] - aEF.Ap[2,1]
c1 = aEF.Ap[1,2] - aEF.Ap[2,2]
c0 = aEF.Ap[1,3] - aEF.Ap[2,3]
#Δ=c₁²-4c₀c₂ == 0
delta = c1^2 -4*c2*c0    #-1.8189894035458565e-12

Find the corner portfolio, say, the join point from adjacent parabolas

mu = -c1/(2*c2)
mu - aEF.mu[2]    #-7.327471962526033e-15

tangency checking

#((dv)/(dx))=a₁+2a₂x
aEF.Ap[1,2] + 2*aEF.Ap[1,1]*mu -(aEF.Ap[2,2] + 2*aEF.Ap[2,1]*mu)  #-1.509903313490213e-14

Scripts

    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

One-step: Find an Efficient Portfolio

To find a single efficient frontier portfolio (using EfficientFrontier as an analytical solver for quadratic program)

    P = Problem(E, V)
    mu = (E[2]+E[3])/2
    z = ePortfolio(mu, P)

compute the efficient portfolio given expected return at mu=1.17

3-element Vector{Float64}:
 0.1824480369515394
 0.043879907621241665
 0.7736720554272218

the z = ePortfolio(mu, P::Problem) is equivalent to

    aCL = EfficientFrontier.ECL(P)
    aEF = eFrontier(aCL, P)
    z = ePortfolio(mu, aEF)
    #display(ePortfolio(mu, P)- ePortfolio(mu, aEF)) #0