Skip to content
18

Mean Risk

PortfolioOptimisers.MeanRiskResult Type
julia
struct MeanRiskResult{__T_jr, __T_fb} <: RiskJuMPOptimisationResult

Result type for Mean-Risk portfolio optimisation.

Fields

Property access delegates to the embedded JuMPOptimisationResult: the virtual :w property and unknown properties resolve through jr.

Constructors

julia
MeanRiskResult(; jr::JuMPOptimisationResult, fb::Option{<:OptE_Opt}) -> MeanRiskResult

Keywords correspond to the struct's fields.

Related

source
PortfolioOptimisers.mean_risk_td_defaults Function
julia
mean_risk_td_defaults(

) -> @NamedTuple{r::Variance{RiskMeasureSettings{Float64, Nothing, Bool}, Nothing, Nothing, Nothing, SquaredSOCRiskExpr}, obj::MinimumRisk}

Return the static defaults of the MeanRisk fields that may hold a TimeDependent.

Shared by the constructor's test-substitution pass and time_dependent_field_defaults, so the fold-less value of a field is declared once. Fields whose static default is nothing are omitted.

Related

source
PortfolioOptimisers.factory Method
julia
factory(a::Union{Nothing, <:AbstractEstimator, <:AbstractAlgorithm,
                 <:AbstractResult}, args...; kwargs...) -> a

No-op factory function for constructing objects with a uniform interface.

Defining methods which dispatch on the first argument allows for a consistent factory interface across different types.

factory and port_opt_view are the two propagation mechanisms in this library. They are duals: factory threads runtime values (prior moments, observation weights, previous portfolio weights) down through a composed struct tree; port_opt_view threads an index selection (a subset of assets or observations) down through the same tree.

Arguments

  • a: Indicates no object should be constructed.

  • args...: Arbitrary positional arguments (ignored).

  • kwargs...: Arbitrary keyword arguments (ignored).

Returns

  • a: The input unchanged.

Examples

julia
julia> factory(nothing, 1, 2; x = 3)

julia> factory(MeanValue())
MeanValue
  w ┴ nothing

Related

source
julia
factory(res::NonFiniteAllocationOptimisationResult, fb::Option{<:OptE_Opt})

Rebuild a continuous optimisation result with an updated fallback optimiser fb.

Every optimisation result carries fb as its last field, so the generic rebuild copies all fields unchanged except the trailing fb. Concrete result types may override this method when rebuilding requires more than swapping fb.

Related

source
julia
factory(
    opt::Union{NonFiniteAllocationOptimisationEstimator, NonFiniteAllocationOptimisationResult},
    _
) -> SubsetResamplingResult

Return opt unchanged.

Default pass-through factory for optimisation estimators and results. Overridden for estimators that carry parameters requiring update at each optimisation step.

Related

source
Base.getproperty Method
julia
getproperty(
    r::RiskJuMPOptimisationResult,
    sym::Symbol
) -> Any

Default property access for RiskJuMPOptimisationResult: unique fields resolve directly; everything else delegates to the embedded JuMPOptimisationResult jr.

source
PortfolioOptimisers.MeanRisk Type
julia
struct MeanRisk{__T_opt, __T_r, __T_obj, __T_wi, __T_fb} <: RiskJuMPOptimisationEstimator

Mean-Risk portfolio optimiser.

MeanRisk formulates and solves a mean-risk portfolio optimisation problem using JuMP. It can optimise a wide variety of objective functions (minimum risk, maximum return, maximum Sharpe ratio, maximum utility) subject to risk, weight, cardinality, and custom constraints.

Fields

  • opt: JuMP optimiser configuration.

  • r: Risk measure or vector of risk measures.

  • obj: Portfolio objective function.

  • wi: Initial portfolio weights for warm-starting the solver.

  • fb: Fallback result or estimator.

Constructors

julia
MeanRisk(;
    opt::JuMPOptimiser,
    r::TD{<:RM_VecRM} = Variance(),
    obj::TD{<:ObjectiveFunction} = MinimumRisk(),
    wi::TD_Option{<:VecNum} = nothing,
    fb::TDO_Option{<:OptE_Opt} = nothing
) -> MeanRisk

Keywords correspond to the struct's fields. Fields typed TD, TD_Option or TDO_Option may hold a TimeDependent per-fold schedule instead of a static value: the risk measure, objective, warm start and fallback are problem definition, so a cross-validation fold loop resolves them per fold, and a fold-less optimise runs with each at its static default (nothing for wi and fb, so a scheduled fallback is disabled outside fold loops unless the schedule carries a default).

Validation

  • If r is a vector: !isempty(r).

  • If wi is provided: !isempty(wi).

  • fb schedules: bind !== :nearest.

Propagated parameters

When factory is called on this type, the following @fprop-tagged fields are automatically propagated:

  • opt: Recursively updated via factory.

  • r: Recursively updated via factory.

  • fb: Recursively updated via factory.

Examples

julia
julia> MeanRisk(; opt = JuMPOptimiser(; slv = Solver(; solver = nothing)))
MeanRisk
  opt ┼ JuMPOptimiser
      │        pe ┼ EmpiricalPrior
      │           │        ce ┼ PortfolioOptimisersCovariance
      │           │           │   ce ┼ Covariance
      │           │           │      │    me ┼ SimpleExpectedReturns
      │           │           │      │       │   w ┴ nothing
      │           │           │      │    ce ┼ GeneralCovariance
      │           │           │      │       │   ce ┼ StatsBase.SimpleCovariance: StatsBase.SimpleCovariance(true)
      │           │           │      │       │    w ┴ nothing
      │           │           │      │   alg ┴ FullMoment()
      │           │           │   mp ┼ MatrixProcessing
      │           │           │      │     pdm ┼ Posdef
      │           │           │      │         │      alg ┼ UnionAll: NearestCorrelationMatrix.Newton
      │           │           │      │         │   kwargs ┴ @NamedTuple{}: NamedTuple()
      │           │           │      │      dn ┼ nothing
      │           │           │      │      dt ┼ nothing
      │           │           │      │     alg ┼ nothing
      │           │           │      │   order ┴ NTuple{4, Symbol}: (:pdm, :dn, :dt, :alg)
      │           │        me ┼ SimpleExpectedReturns
      │           │           │   w ┴ nothing
      │           │   horizon ┴ nothing
      │       slv ┼ Solver
      │           │          name ┼ String: ""
      │           │        solver ┼ nothing
      │           │      settings ┼ nothing
      │           │     check_sol ┼ @NamedTuple{}: NamedTuple()
      │           │   add_bridges ┴ Bool: true
      │        wb ┼ WeightBounds
      │           │   lb ┼ Float64: 0.0
      │           │   ub ┴ Float64: 1.0
      │       bgt ┼ Float64: 1.0
      │      sbgt ┼ nothing
      │        lt ┼ nothing
      │        st ┼ nothing
      │      lcse ┼ nothing
      │       cte ┼ nothing
      │    gcarde ┼ nothing
      │   sgcarde ┼ nothing
      │      smtx ┼ nothing
      │     sgmtx ┼ nothing
      │       slt ┼ nothing
      │       sst ┼ nothing
      │      sglt ┼ nothing
      │      sgst ┼ nothing
      │        tn ┼ nothing
      │      fees ┼ nothing
      │      sets ┼ nothing
      │        tr ┼ nothing
      │       ple ┼ nothing
      │       ret ┼ ArithmeticReturn
      │           │   ucs ┼ nothing
      │           │    lb ┼ nothing
      │           │    mu ┴ nothing
      │       sca ┼ SumScalariser()
      │      ccnt ┼ nothing
      │      cobj ┼ nothing
      │        sc ┼ Int64: 1
      │        so ┼ Int64: 1
      │        ss ┼ nothing
      │      card ┼ nothing
      │     scard ┼ nothing
      │       wn2 ┼ nothing
      │       wnp ┼ nothing
      │     wninf ┼ nothing
      │        l1 ┼ nothing
      │        l2 ┼ nothing
      │      linf ┼ nothing
      │        lp ┼ nothing
      │       brt ┼ Bool: false
      │    cle_pr ┼ Bool: true
      │    strict ┴ Bool: false
    r ┼ Variance
      │   settings ┼ RiskMeasureSettings
      │            │   scale ┼ Float64: 1.0
      │            │      ub ┼ nothing
      │            │     rke ┴ Bool: true
      │      sigma ┼ nothing
      │       chol ┼ nothing
      │         rc ┼ nothing
      │        alg ┴ SquaredSOCRiskExpr()
  obj ┼ MinimumRisk()
   wi ┼ nothing
   fb ┴ nothing

Mathematical definition

The general mean-risk optimisation problem is:

minwf(w)s.t.wW.

Objective f depends on ObjectiveFunction:

Where:

  • w: Portfolio weight vector.

  • W: Feasible weight set defined by portfolio constraints.

  • f(w): Objective function (depends on ObjectiveFunction).

  • ρ(w): Portfolio risk measure.

  • μ^: Estimated expected return vector.

  • λ: Risk aversion parameter.

  • rf: Risk-free rate.

Related

source
PortfolioOptimisers.needs_previous_weights Method
julia
needs_previous_weights(opt::MeanRisk) -> Any

Return true if any sub-estimator of opt requires previous portfolio weights (JuMP optimiser, risk measure, or fallback).

source
PortfolioOptimisers.factory Method
julia
factory(a::Union{Nothing, <:AbstractEstimator, <:AbstractAlgorithm,
                 <:AbstractResult}, args...; kwargs...) -> a

No-op factory function for constructing objects with a uniform interface.

Defining methods which dispatch on the first argument allows for a consistent factory interface across different types.

factory and port_opt_view are the two propagation mechanisms in this library. They are duals: factory threads runtime values (prior moments, observation weights, previous portfolio weights) down through a composed struct tree; port_opt_view threads an index selection (a subset of assets or observations) down through the same tree.

Arguments

  • a: Indicates no object should be constructed.

  • args...: Arbitrary positional arguments (ignored).

  • kwargs...: Arbitrary keyword arguments (ignored).

Returns

  • a: The input unchanged.

Examples

julia
julia> factory(nothing, 1, 2; x = 3)

julia> factory(MeanValue())
MeanValue
  w ┴ nothing

Related

source
julia
factory(
    opt::Union{NonFiniteAllocationOptimisationEstimator, NonFiniteAllocationOptimisationResult},
    _
) -> SubsetResamplingResult

Return opt unchanged.

Default pass-through factory for optimisation estimators and results. Overridden for estimators that carry parameters requiring update at each optimisation step.

Related

source
PortfolioOptimisers.port_opt_view Method
julia
port_opt_view(
    mr::MeanRisk,
    i,
    X::AbstractMatrix{<:Union{var"#s29", var"#s28"} where {var"#s29"<:Number, var"#s28"<:AbstractJuMPScalar}},
    args...
) -> MeanRisk{JuMPOptimiser{__T_pe, __T_slv, __T_wb, __T_bgt, __T_sbgt, __T_lt, __T_st, __T_lcse, __T_cte, __T_gcarde, __T_sgcarde, __T_smtx, __T_sgmtx, __T_slt, __T_sst, __T_sglt, __T_sgst, __T_tn, __T_fees, __T_sets, __T_tr, __T_ple, __T_ret, __T_sca, __T_ccnt, __T_cobj, __T_sc, __T_so, __T_ss, __T_card, __T_scard, __T_wn2, __T_wnp, __T_wninf, __T_l1, __T_l2, __T_linf, __T_lp, __T_brt, __T_cle_pr, __T_strict}} where {__T_pe, __T_slv, __T_wb, __T_bgt, __T_sbgt, __T_lt, __T_st, __T_lcse, __T_cte, __T_gcarde, __T_sgcarde, __T_smtx, __T_sgmtx, __T_slt, __T_sst, __T_sglt, __T_sgst, __T_tn, __T_fees, __T_sets, __T_tr, __T_ple, __T_ret, __T_sca, __T_ccnt, __T_cobj, __T_sc, __T_so, __T_ss, __T_card, __T_scard, __T_wn2, __T_wnp, __T_wninf, __T_l1, __T_l2, __T_linf, __T_lp, __T_brt, __T_cle_pr, __T_strict}

Return a cluster-sliced copy of MeanRisk for asset index set i and returns matrix X.

source
PortfolioOptimisers.solve_mean_risk! Function
julia
solve_mean_risk!(model, mr, ret, pr, ::Val{false}, ::Val{false}, args...)
solve_mean_risk!(model, mr, ret, pr, ::Val{true}, ::Val{false}, fees)
solve_mean_risk!(model, mr, ret, pr, ::Val{false}, ::Val{true}, fees)
solve_mean_risk!(model, mr, ret, pr, ::Val{true}, ::Val{true}, fees)

Solve the Mean-Risk optimisation problem.

Dispatches based on whether a return frontier and/or risk frontier sweep is requested (controlled by Val arguments). Single-point, return-frontier, risk-frontier, and combined sweeps are all handled.

Arguments

  • model::JuMP.Model: JuMP optimisation model.

  • mr::MeanRisk: MeanRisk estimator configuration.

  • ret::JuMPReturnsEstimator: Returns estimator.

  • pr::AbstractPriorResult: Prior result with asset moments.

  • ::Val{bool}: Whether to do a return frontier sweep.

  • ::Val{bool}: Whether to do a risk frontier sweep.

  • fees: Optional fees configuration.

Returns

  • (retcode, sol) or (retcodes, sols) depending on the sweep mode.

Related

source
PortfolioOptimisers.compute_ret_lbs Function
julia
compute_ret_lbs(lbs, args...)

Compute the return lower bounds for the efficient frontier sweep.

Dispatches based on the type of lbs: if a pre-computed vector of lower bounds is provided, returns it directly. If a Frontier specification is given, solves the minimum and maximum return sub-problems and constructs a range of bounds.

Arguments

  • lbs: Pre-computed return bounds vector (VecNum) or Frontier configuration.

  • args...: Additional arguments (model, optimiser, prior, etc.) needed when lbs is a Frontier.

Returns

  • Vector or range of return lower bounds for frontier sweep.

Related

source
julia
compute_ret_lbs(lbs::Frontier, model::JuMP.Model, mr::MeanRisk, ret::JuMPReturnsEstimator, pr::AbstractPriorResult, fees::Option{<:Fees})

Compute return lower bounds for a MeanRisk efficient frontier sweep by solving minimum and maximum return sub-problems.

Solves the minimum-risk and maximum-return portfolios, then constructs a uniformly spaced range of lbs.N return targets spanning the two extremes.

Arguments

  • lbs::Frontier: Frontier configuration specifying the number of points.

  • model::JuMP.Model: JuMP optimisation model.

  • mr::MeanRisk: MeanRisk estimator configuration.

  • ret::JuMPReturnsEstimator: Returns estimator.

  • pr::AbstractPriorResult: Prior result with asset moments.

  • fees::Option{<:Fees}: Optional fees configuration.

Returns

  • Range of return lower bounds for the frontier sweep.

Related

source
julia
compute_ret_lbs(lbs::Frontier, rt_min::Number, rt_max::Number)

Compute return lower bounds for a NearOptimalCentering frontier sweep from pre-computed minimum and maximum return values.

Constructs a uniformly spaced range of lbs.N return targets between rt_min and rt_max.

Arguments

  • lbs::Frontier: Frontier configuration specifying the number of points.

  • rt_min::Number: Minimum portfolio return (from the minimum-risk portfolio).

  • rt_max::Number: Maximum portfolio return (from the maximum-return portfolio).

Returns

  • Range of lbs.N equally spaced return lower bounds.

Related

source
PortfolioOptimisers._rebuild_risk_frontier Function
julia
_rebuild_risk_frontier(pr, fees, ...)

Internal helper to rebuild the risk frontier from a prior result.

Recomputes the risk range used for the efficient frontier given updated prior information and fee structures.

Arguments

  • pr: Prior result with asset moments.

  • fees: Optional fees configuration.

  • Additional parameters.

Returns

  • Tuple of risk bound values for the frontier.

Related

source
PortfolioOptimisers.rebuild_risk_frontier Function
julia
rebuild_risk_frontier(model, mr, ...)

Rebuild the efficient frontier risk bounds from a solved JuMP model.

Extracts and recomputes risk bound values from the optimised model for use in subsequent frontier sweeps.

Arguments

  • model: Solved JuMP model.

  • mr: MeanRisk optimiser configuration.

  • Additional parameters.

Returns

  • Updated risk bounds for the frontier.

Related

source
PortfolioOptimisers.compute_risk_ubs Function
julia
compute_risk_ubs(model, opt, ...)

Compute or rebuild risk upper bounds for the efficient frontier sweep.

Extracts the risk frontier from the model and rebuilds any frontier bounds that have not yet been computed as numeric vectors.

Arguments

  • model::JuMP.Model: JuMP optimisation model containing the risk frontier.

  • opt: Optimiser configuration.

  • Additional arguments (prior, fees, weights, etc.).

Returns

  • Updated risk frontier vector of pairs.

Related

source
julia
compute_risk_ubs(model::JuMP.Model, noc::NearOptimalCentering{<:Any, <:Any, <:Any, <:Any, <:Any, <:Any, <:Any, <:Any, <:Any, <:Any, <:Any, <:ConstrainedNearOptimalCentering}, pr::AbstractPriorResult, fees::Option{<:Fees}, w_min::VecNum, w_max::VecNum)

Compute risk upper bounds for a constrained NearOptimalCentering frontier sweep.

Identifies risk frontier entries that are not yet resolved (i.e. not concrete weight vectors) and rebuilds them using the minimum and maximum portfolio weights.

Arguments

  • model::JuMP.Model: JuMP optimisation model containing risk_frontier.

  • noc::NearOptimalCentering{..., <:ConstrainedNearOptimalCentering}: Constrained Near Optimal Centering optimiser.

  • pr::AbstractPriorResult: Prior result with asset moments.

  • fees::Option{<:Fees}: Optional fees configuration.

  • w_min::VecNum: Minimum-risk portfolio weights.

  • w_max::VecNum: Maximum-risk (maximum-return) portfolio weights.

Returns

  • Updated risk frontier vector of (keys, vals) pairs.

Related

source
PortfolioOptimisers.optimise Function
julia
optimise(mr::MeanRisk{<:Any, <:Any, <:Any, <:Any, Nothing},
         rd::ReturnsResult = ReturnsResult(); dims::Int = 1,
         str_names::Bool = false, save::Bool = true, kwargs...) -> MeanRiskResult

Run the Mean-Risk portfolio optimisation.

Arguments

  • mr: The mean risk optimiser to use.

  • rd: The returns result to use. If isa(mr.opt.pe, AbstractPriorResult), rd is not necessary if doing a standalone optimisation, but may be required/desired by fallbacks and/or clusterisation.

  • dims: The dimension along which observations advance in time.

  • str_names: Whether to use string names for the assets in the optimisation.

  • save: Whether to save the JuMP model in the optimisation result.

  • kwargs: Additional keyword arguments passed to the optimisation function.

Related

source