Tracking risk measure

PortfolioOptimisers.RiskTrackingErrorType
struct RiskTrackingError{__T_tr, __T_r, __T_err, __T_alg} <: AbstractTracking

Constrains how far a portfolio's risk may stand from a benchmark portfolio's risk.

This is the constraint twin of RiskTrackingRiskMeasure: the same quantity in the same two modes, bounded here rather than minimised. Give it to a JuMPOptimiser's tr slot, and the solution satisfies the bound; give the matching measure to expected_risk afterwards, and you read the value it bound. The distance is a risk distance rather than a norm of the return difference, which is what separates it from TrackingError.

Mathematical definition

alg chooses which of two quantities err bounds.

Independent (IndependentVariableTracking) bounds the risk of the weight difference:

\[\begin{align} \rho(\boldsymbol{w} - \boldsymbol{w}_b) &\leq \varepsilon\,. \end{align}\]

Dependent (DependentVariableTracking) bounds the difference of the two risks:

\[\begin{align} \lvert \rho(\boldsymbol{w}) - \rho(\boldsymbol{w}_b) \rvert &\leq \varepsilon\,. \end{align}\]

Where:

  • $\boldsymbol{w}$: Portfolio weights vector $N \times 1$.
  • $\boldsymbol{w}_b$: Benchmark portfolio weights vector $N \times 1$, the w of tr.
  • $\rho$: The risk measure in r.
  • $\varepsilon$: The tolerance in err.

Both bind at err, and the realised value can be read back through the matching RiskTrackingRiskMeasure.

Warning

The default err = 0.0 admits only portfolios whose tracked risk is exactly the benchmark's. For a positive-definite measure in independent mode that pins $\boldsymbol{w}$ to $\boldsymbol{w}_b$. State an err unless that is what you want.

The bound reads tr.w and never tr.fees, so it holds no Fees object to amortise and fee amortisation cannot reach it.

Fields

  • tr: Benchmark tracking specification.
  • r: Risk measure instance.
  • err: Tracking error tolerance.
  • alg: Tracking formulation algorithm.

Constructors

RiskTrackingError(;    tr::WeightsTracking,    r::AbstractBaseRiskMeasure = StandardDeviation(),    err::Number = 0.0,    alg::VariableTracking = IndependentVariableTracking()) -> RiskTrackingError

Keywords correspond to the struct's fields.

The constructor rewrites r through no_bounds_no_risk_expr_risk_measure, so the inner measure's own settings.ub and settings.rke are dropped. The measure is being used to measure the distance, not to bound the portfolio or to contribute to the objective, and both of those belong to the enclosing optimisation. err is this constraint's only bound.

Validation

Examples

julia> RiskTrackingError(; tr = WeightsTracking(; w = [0.5, 0.5]), err = 0.05)RiskTrackingError   tr ┼ WeightsTracking      │    fees ┼ nothing      │       w ┼ Vector{Float64}: [0.5, 0.5]      │   fixed ┴ Bool: false    r ┼ StandardDeviation      │   settings ┼ RiskMeasureSettings      │            │   scale ┼ Int64: 1      │            │      ub ┼ nothing      │            │     rke ┴ Bool: false      │      sigma ┼ nothing      │       chol ┴ nothing  err ┼ Float64: 0.05  alg ┴ IndependentVariableTracking()

Related

References

  • [94] D. P. Palomar. Portfolio Optimization: Theory and Application (Cambridge University Press, 2025).
  • [5] D. Cajas. Advanced Portfolio Optimization: A Cutting-edge Quantitative Approach (Springer Nature Switzerland, 2025). Section 9.2.
source
PortfolioOptimisers.TrackingRiskMeasureType
struct TrackingRiskMeasure{__T_settings, __T_tr, __T_alg} <: RiskMeasure

Represents the Tracking Error risk measure.

TrackingRiskMeasure penalises portfolio deviation from a benchmark by computing a norm of the difference between portfolio returns and a benchmark return series or benchmark weights. The tracking error is defined using returns-based or weights-based benchmarks, and the norm is configurable.

Mathematical definition

Let $\boldsymbol{x}$ be the portfolio returns series, $\boldsymbol{b}$ the benchmark returns, and $N_T$ the number of observations. With the default L2Norm, the tracking error is:

\[\begin{align} \mathrm{TE}(\boldsymbol{w}) &= \frac{\lVert \boldsymbol{x} - \boldsymbol{b} \rVert_2}{\sqrt{N_T - \nu}}\,. \end{align}\]

Where:

  • $\mathrm{TE}(\boldsymbol{w})$: $L^2$ tracking error of the portfolio.
  • $\boldsymbol{w}$: Portfolio weights vector $N \times 1$.
  • $\boldsymbol{x}$: Portfolio returns series $N_T \times 1$.
  • $\boldsymbol{b}$: Benchmark returns series $N_T \times 1$.
  • $N_T$: Number of observations.
  • $\nu$: Delta degrees of freedom, the ddof field of the norm. It is 1 by default, so the denominator is the sample one.

The alg field selects the norm. It sets both the norm of the deviation vector and the divisor that scales it — see norm_error and norm_factor.

Fields

  • settings: Risk measure settings.
  • tr: Benchmark tracking specification.
  • alg: Tracking formulation algorithm.

Constructors

TrackingRiskMeasure(;    settings::RiskMeasureSettings = RiskMeasureSettings(),    tr::AbstractTrackingAlgorithm,    alg::NormError = L2Norm()) -> TrackingRiskMeasure

Keywords correspond to the struct's fields.

View parameters

When port_opt_view is called on this type, the following @vprop-tagged fields are automatically subset to the selected indices:

Functor

(r::TrackingRiskMeasure)(w::VecNum, X::MatNum, fees = nothing)

Computes the Tracking Error of a portfolio weight vector w.

Arguments

  • w::VecNum: Portfolio weights vector.
  • X::MatNum: Asset returns matrix ($T \times N$).
  • fees: Optional fee structure.

The benchmark's fee and the portfolio's fee are charged at the same site, over the same X, and neither is divided by a fold. fees reaches calc_net_returns and r.tr.fees reaches tracking_benchmark. A bare AmortisedFees on either one charges in full, so both halves of the norm read one clock. State a horizon on both to divide both.

Precomputed portfolio returns

(r::TrackingRiskMeasure{<:Any, <:ReturnsTracking})(x::VecNum)

Computes the Tracking Error of an already-reduced portfolio returns series x ($T \times 1$). Only a ReturnsTracking measure supports this, because its benchmark is itself a returns series. A WeightsTracking measure rebuilds its benchmark from the asset returns, so it needs the portfolio weights and throws an ArgumentError instead. See supports_precomputed_returns.

Examples

julia> TrackingRiskMeasure(; tr = ReturnsTracking(; w = [0.1, -0.2, 0.3]))TrackingRiskMeasure  settings ┼ RiskMeasureSettings           │   scale ┼ Float64: 1.0           │      ub ┼ nothing           │     rke ┴ Bool: true        tr ┼ ReturnsTracking           │   w ┴ Vector{Float64}: [0.1, -0.2, 0.3]       alg ┼ L2Norm           │   ddof ┴ Int64: 1

Related

References

  • [94] D. P. Palomar. Portfolio Optimization: Theory and Application (Cambridge University Press, 2025).
  • [5] D. Cajas. Advanced Portfolio Optimization: A Cutting-edge Quantitative Approach (Springer Nature Switzerland, 2025). Section 9.2.
source
PortfolioOptimisers.RiskTrackingRiskMeasureType
struct RiskTrackingRiskMeasure{__T_settings, __T_tr, __T_r, __T_alg} <: RiskMeasure

Represents the Risk Tracking risk measure.

RiskTrackingRiskMeasure computes the deviation of portfolio risk from a benchmark portfolio risk, using any base risk measure. Two modes are supported:

  • Independent (IndependentVariableTracking): computes the risk of the weight difference $\boldsymbol{w} - \boldsymbol{w}_b$.
  • Dependent (DependentVariableTracking): computes the absolute difference between the portfolio risk and the benchmark risk.

Mathematical definition

Independent mode:

\[\begin{align} \mathrm{RkTrack}_{\mathrm{indep}}(\boldsymbol{w}) &= \rho(\boldsymbol{w} - \boldsymbol{w}_b)\,. \end{align}\]

Where:

  • $\mathrm{RkTrack}_{\mathrm{indep}}(\boldsymbol{w})$: Risk of the weight difference between portfolio and benchmark.
  • $\boldsymbol{w}$: Portfolio weights vector $N \times 1$.
  • $\boldsymbol{w}_b$: Benchmark portfolio weights vector $N \times 1$.
  • $\rho$: Chosen base risk measure.

Dependent mode:

\[\begin{align} \mathrm{RkTrack}_{\mathrm{dep}}(\boldsymbol{w}) &= |\rho(\boldsymbol{w}) - \rho(\boldsymbol{w}_b)|\,. \end{align}\]

Where:

  • $\mathrm{RkTrack}_{\mathrm{dep}}(\boldsymbol{w})$: Absolute difference between portfolio risk and benchmark risk.
  • $\boldsymbol{w}$: Portfolio weights vector $N \times 1$.
  • $\boldsymbol{w}_b$: Benchmark portfolio weights vector $N \times 1$.
  • $\rho$: Chosen base risk measure.

Neither this measure nor its constraint twin reads tr.fees: the computation reads tr.w alone. There is no Fees object on this path, so fee amortisation cannot reach it, and the distance is re-evaluated fresh every fold.

Fields

  • settings: Risk measure settings.
  • tr: Benchmark tracking specification.
  • r: Risk measure instance.
  • alg: Tracking formulation algorithm.

Constructors

RiskTrackingRiskMeasure(;    settings::RiskMeasureSettings = RiskMeasureSettings(),    tr::WeightsTracking,    r::AbstractBaseRiskMeasure = Variance(),    alg::VariableTracking = IndependentVariableTracking()) -> RiskTrackingRiskMeasure

Keywords correspond to the struct's fields.

Functor

(r::RiskTrackingRiskMeasure)(w::VecNum, X::MatNum, fees = nothing)

Computes the Risk Tracking deviation of a portfolio weight vector w.

Arguments

  • w::VecNum: Portfolio weights vector.
  • X::MatNum: Asset returns matrix ($T \times N$).
  • fees: Optional fee structure.

Examples

julia> RiskTrackingRiskMeasure(; tr = WeightsTracking(; w = [0.5, 0.5]))RiskTrackingRiskMeasure  settings ┼ RiskMeasureSettings           │   scale ┼ Float64: 1.0           │      ub ┼ nothing           │     rke ┴ Bool: true        tr ┼ WeightsTracking           │    fees ┼ nothing           │       w ┼ Vector{Float64}: [0.5, 0.5]           │   fixed ┴ Bool: false         r ┼ Variance           │   settings ┼ RiskMeasureSettings           │            │   scale ┼ Int64: 1           │            │      ub ┼ nothing           │            │     rke ┴ Bool: false           │      sigma ┼ nothing           │       chol ┼ nothing           │         rc ┼ nothing           │        alg ┴ SquaredSOCRiskExpr()       alg ┴ IndependentVariableTracking()

Related

References

  • [94] D. P. Palomar. Portfolio Optimization: Theory and Application (Cambridge University Press, 2025).
  • [5] D. Cajas. Advanced Portfolio Optimization: A Cutting-edge Quantitative Approach (Springer Nature Switzerland, 2025). Section 9.2.
source
PortfolioOptimisers.port_opt_viewMethod
port_opt_view(::Nothing, ::Any; kwargs...) -> nothing
port_opt_view(::Nothing, ::Any, args...; kwargs...) -> nothing

Canonical absent-value fallback for port_opt_view: an index view of a missing (nothing) estimator, algorithm, result, or constraint is itself nothing.

These methods serve every propagation family. Because many optional fields are typed Option{T} = Union{Nothing, T}, the ::Nothing-specific methods are also what disambiguate a nothing argument from the family-specific Option{T} passthroughs and from the universal leaf fallback. Both carry a fixed second positional so they dominate the universal port_opt_view(x, i, args...) method.

Algorithm

  1. Return nothing. Neither method reads its index, its tail or its keywords.

The two methods differ only in whether they accept a tail, and both are needed: a call site that threads no tail resolves on the first, and one that threads a returns matrix resolves on the second.

Examples

julia> PortfolioOptimisers.port_opt_view(nothing, 1)
source
PortfolioOptimisers.port_opt_viewMethod
port_opt_view(
    tr::RiskTrackingError,
    i,
    X::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    args...
) -> RiskTrackingError{WeightsTracking{__T_fees, __T_w, __T_fixed}, _A, <:Number, <:VariableTracking} where {__T_fees, __T_w, __T_fixed, _A}

Return a view of RiskTrackingError tr sliced to asset indices i.

Slices both the inner tracking benchmark and the risk measure for cluster-based optimisation.

Related

source
PortfolioOptimisers.factoryFunction
factory(
    tr::RiskTrackingError,
    pr::AbstractPriorResult,
    slv,
    ucs;
    ...
) -> RiskTrackingError{WeightsTracking{__T_fees, __T_w, __T_fixed}, _A, <:Number, <:VariableTracking} where {__T_fees, __T_w, __T_fixed, _A}
factory(
    tr::RiskTrackingError,
    pr::AbstractPriorResult,
    slv,
    ucs,
    w::Union{Nothing, AbstractVector{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}}},
    args...;
    kwargs...
) -> RiskTrackingError{WeightsTracking{__T_fees, __T_w, __T_fixed}, _A, <:Number, <:VariableTracking} where {__T_fees, __T_w, __T_fixed, _A}

Create an instance of RiskTrackingError updating the inner benchmark and risk measure from the prior result and solver context.

Related

source
PortfolioOptimisers.factoryMethod
factory(
    r::TrackingRiskMeasure,
    ,
    ,
    ,
    w::AbstractVector{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    args...;
    kwargs...
) -> TrackingRiskMeasure{RiskMeasureSettings{__T_scale, __T_ub, __T_rke}, <:AbstractTrackingAlgorithm, <:NormError} where {__T_scale, __T_ub, __T_rke}

Create an instance of TrackingRiskMeasure from a full optimisation context, forwarding w to factory(r, w).

Ignores prior result, solver, and uncertainty set arguments.

Related

source
PortfolioOptimisers.port_opt_viewMethod
port_opt_view(
    r::RiskTrackingRiskMeasure,
    i,
    X::AbstractMatrix{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}},
    args...
) -> RiskTrackingRiskMeasure{RiskMeasureSettings{__T_scale, __T_ub, __T_rke}, WeightsTracking{__T_fees, __T_w, __T_fixed}, _A, <:VariableTracking} where {__T_scale, __T_ub, __T_rke, __T_fees, __T_w, __T_fixed, _A}

Return a view of RiskTrackingRiskMeasure r sliced to asset indices i.

Slices both the inner tracking benchmark and the risk measure for cluster-based optimisation.

Related

source
PortfolioOptimisers.factoryMethod
factory(
    r::RiskTrackingRiskMeasure,
    w::AbstractVector{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}}
) -> RiskTrackingRiskMeasure{RiskMeasureSettings{__T_scale, __T_ub, __T_rke}, WeightsTracking{__T_fees, __T_w, __T_fixed}, _A, <:VariableTracking} where {__T_scale, __T_ub, __T_rke, __T_fees, __T_w, __T_fixed, _A}

Create an instance of RiskTrackingRiskMeasure updating the inner benchmark and risk measure from new portfolio weights w.

Related

source
PortfolioOptimisers.factoryMethod
factory(
    r::RiskTrackingRiskMeasure,
    pr::AbstractPriorResult,
    args...;
    kwargs...
) -> RiskTrackingRiskMeasure{RiskMeasureSettings{__T_scale, __T_ub, __T_rke}, WeightsTracking{__T_fees, __T_w, __T_fixed}, _A, <:VariableTracking} where {__T_scale, __T_ub, __T_rke, __T_fees, __T_w, __T_fixed, _A}

Create an instance of RiskTrackingRiskMeasure updating the inner risk measure from the prior result.

The inner tracking benchmark is preserved; the risk measure is updated via factory.

Related

source

References

[5]
D. Cajas. Advanced Portfolio Optimization: A Cutting-edge Quantitative Approach (Springer Nature Switzerland, 2025).
[94]
D. P. Palomar. Portfolio Optimization: Theory and Application (Cambridge University Press, 2025).