Norm error

PortfolioOptimisers.NormErrorType
abstract type NormError <: AbstractEstimator

Abstract supertype for all norm-based error algorithms.

All concrete and/or abstract types representing norm-based error algorithms (such as second-order cone or norm-one error) should be subtypes of NormError.

Interfaces

In order to implement a new norm-based error algorithm which will work seamlessly with the library, subtype NormError with all necessary parameters struct, and implement the following method:

  • norm_factor(f::NormError, T::Number) -> Number: Returns the divisor that scales the norm. The T === nothing case is already covered by a generic method that returns 1.

The functor side is norm_error, and the model side is set_risk_constraints! for TrackingRiskMeasure and set_tracking_error_constraints! for TrackingError. All three must agree.

Related

source
PortfolioOptimisers.L2NormType
struct L2Norm{__T_ddof} <: NormError

Second-order cone (SOC) norm-based error formulation.

L2Norm implements a norm-based error formulation using the Euclidean (L2) norm, scaled by the square root of the number of assets minus the degrees of freedom (ddof). This is commonly used for error constraints and objectives in portfolio optimisation.

Mathematical definition

\[\begin{align} \mathrm{TE}_{L_2}(\boldsymbol{a},\boldsymbol{b}) &= \frac{\lVert \boldsymbol{a} - \boldsymbol{b} \rVert_2}{\sqrt{T - d}}\,. \end{align}\]

Where:

  • $\mathrm{TE}_{L_2}(\boldsymbol{a},\boldsymbol{b})$: L2-norm error.
  • $\boldsymbol{a}$: Portfolio weight or return vector $T \times 1$.
  • $\boldsymbol{b}$: Benchmark vector $T \times 1$.
  • $T$: Number of observations.
  • $d$: Degrees of freedom, ddof. When $T$ is not provided the denominator is 1.

The source states the denominator as $\sqrt{T}$. The default ddof = 1 gives the sample denominator $\sqrt{T-1}$. Set ddof = 0 to recover the source.

Fields

  • ddof: Degrees-of-freedom correction.

Constructors

L2Norm(;    ddof::Integer = 1) -> L2Norm

Keywords correspond to the struct's fields.

Validation

  • 0 <= ddof.

Examples

julia> L2Norm()L2Norm  ddof ┴ Int64: 1

Related

References

  • [5] D. Cajas. Advanced Portfolio Optimization: A Cutting-edge Quantitative Approach (Springer Nature Switzerland, 2025). Section 9.2, Equation 9.16.
source
PortfolioOptimisers.SquaredL2NormType
struct SquaredL2Norm{__T_ddof} <: NormError

Second-order cone (SOC) squared norm-based error formulation.

SquaredL2Norm implements a norm-based error formulation using the squared Euclidean (L2) norm, scaled by the number of assets minus the degrees of freedom (ddof). This is commonly used for norm error constraints and objectives in portfolio optimisation where squared error is preferred.

The value is the square of the L2Norm error, so a settings.ub on a TrackingRiskMeasure carries squared units. The JuMP model converts the bound with a square root, so the two encodings accept the same bound.

Mathematical definition

\[\begin{align} \mathrm{TE}_{L_2^2}(\boldsymbol{a},\boldsymbol{b}) &= \frac{\lVert \boldsymbol{a} - \boldsymbol{b} \rVert_2^2}{T - d}\,. \end{align}\]

Where:

  • $\mathrm{TE}_{L_2^2}(\boldsymbol{a},\boldsymbol{b})$: Squared L2-norm error.
  • $\boldsymbol{a}$: Portfolio weight or return vector $T \times 1$.
  • $\boldsymbol{b}$: Benchmark vector $T \times 1$.
  • $T$: Number of observations.
  • $d$: Degrees of freedom, ddof. When $T$ is not provided the denominator is 1.

Fields

  • ddof: Degrees-of-freedom correction.

Constructors

SquaredL2Norm(;    ddof::Integer = 1,) -> SquaredL2Norm

Keywords correspond to the struct's fields.

Validation

  • 0 <= ddof.

Examples

julia> SquaredL2Norm()SquaredL2Norm  ddof ┴ Int64: 1

Related

References

  • [5] D. Cajas. Advanced Portfolio Optimization: A Cutting-edge Quantitative Approach (Springer Nature Switzerland, 2025). Section 9.2, Equation 9.16.
source
PortfolioOptimisers.L1NormType
struct L1Norm <: NormError

Norm-one (NOC) error formulation.

L1Norm implements a norm-based error formulation using the L1 (norm-one) distance between portfolio and benchmark weights. This is commonly used for error constraints and objectives in portfolio optimisation where sparsity or absolute deviations are preferred.

Mathematical definition

\[\begin{align} \mathrm{TE}_{L_1}(\boldsymbol{a},\boldsymbol{b}) &= \frac{\lVert \boldsymbol{a} - \boldsymbol{b} \rVert_1}{T}\,. \end{align}\]

Where:

  • $\mathrm{TE}_{L_1}(\boldsymbol{a},\boldsymbol{b})$: L1-norm error.
  • $\boldsymbol{a}$: Portfolio weight or return vector $T \times 1$.
  • $\boldsymbol{b}$: Benchmark vector $T \times 1$.
  • $T$: Number of observations. When $T$ is not provided the denominator is 1.

Constructors

L1Norm() -> L1Norm

Examples

julia> L1Norm()L1Norm()

Related

References

  • [5] D. Cajas. Advanced Portfolio Optimization: A Cutting-edge Quantitative Approach (Springer Nature Switzerland, 2025). Section 9.2, Equation 9.17.
source
PortfolioOptimisers.LpNormType
struct LpNorm{__T_p, __T_ddof} <: NormError

L-p norm error estimator.

LpNorm takes the Lp-norm of the difference between the portfolio and the benchmark returns, and divides it by $(T - d)^{1/p}$. It generalises L1Norm and L2Norm to a free norm order.

Mathematical definition

\[\begin{align} \mathrm{TE}_{L_p}(\boldsymbol{a},\boldsymbol{b}) &= \frac{\lVert \boldsymbol{a} - \boldsymbol{b} \rVert_p}{(T - d)^{1/p}}\,. \end{align}\]

Where:

  • $\mathrm{TE}_{L_p}(\boldsymbol{a},\boldsymbol{b})$: Lp-norm error.
  • $\boldsymbol{a}$: Portfolio weight or return vector $T \times 1$.
  • $\boldsymbol{b}$: Benchmark vector $T \times 1$.
  • $T$: Number of observations.
  • $d$: Degrees of freedom, ddof. When $T$ is not provided the denominator is 1.
  • $p$: Norm order.

Fields

  • p: Power or order parameter.
  • ddof: Degrees-of-freedom correction.

Constructors

LpNorm(; p::Number = 3, ddof::Integer = 0) -> LpNorm

Keywords correspond to the struct's fields.

Validation

  • 0 <= ddof. The constructor does not bound p. The JuMP model does: both set_risk_constraints! and set_tracking_error_constraints! need 1 < p for the power cone, and raise a DomainError otherwise. The functor accepts any p that LinearAlgebra.norm accepts.

Examples

julia> LpNorm()LpNorm     p ┼ Int64: 3  ddof ┴ Int64: 0

Related

source
PortfolioOptimisers.LInfNormType
struct LInfNorm{__T_ddof} <: NormError

L-infinity norm (maximum absolute deviation) error estimator.

LInfNorm takes the largest absolute deviation between the portfolio and the benchmark returns, and divides it by $T - d$.

Mathematical definition

\[\begin{align} \mathrm{TE}_{L_\infty}(\boldsymbol{a},\boldsymbol{b}) &= \frac{\lVert \boldsymbol{a} - \boldsymbol{b} \rVert_\infty}{T - d}\,. \end{align}\]

Where:

  • $\mathrm{TE}_{L_\infty}(\boldsymbol{a},\boldsymbol{b})$: L∞-norm error, the largest absolute deviation.
  • $\boldsymbol{a}$: Portfolio weight or return vector $T \times 1$.
  • $\boldsymbol{b}$: Benchmark vector $T \times 1$.
  • $T$: Number of observations.
  • $d$: Degrees of freedom, ddof. When $T$ is not provided the denominator is 1.

Fields

  • ddof: Degrees-of-freedom correction.

Constructors

LInfNorm(; ddof::Integer = 0) -> LInfNorm

Keywords correspond to the struct's fields.

Validation

  • 0 <= ddof.

Examples

julia> LInfNorm()LInfNorm  ddof ┴ Int64: 0

Related

source
PortfolioOptimisers.norm_factorFunction
norm_factor(f::Union{Nothing, <:NormError}, T::Option{<:Number})

Compute the denominator that scales a norm in norm_error.

The factor is the single place where the optional observation count T is turned into a divisor. Each NormError declares its own factor, and the T === nothing case is a method, not a branch inside one. A branch is what let ifelse evaluate T - f.ddof on the nothing path.

Algorithm

The method Julia selects on the types of f and T is the algorithm. A T of nothing selects the method that returns 1, so the nothing case is a method and never a branch inside one.

  1. f === nothing gives sqrt(T), the unweighted L2 factor.
  2. L2Norm gives sqrt(T - f.ddof).
  3. SquaredL2Norm gives T - f.ddof.
  4. L1Norm gives T, because that norm carries no degrees of freedom.
  5. LpNorm gives (T - f.ddof)^(1/f.p), taken with cbrt when f.p is 3, the default.
  6. LInfNorm gives T - f.ddof.

Arguments

  • f: Norm-based error algorithm, a NormError subtype. nothing means an unweighted L2 norm.
  • T: Optional number of observations.

Returns

  • factor::Number: Divisor for the norm. It is 1 when T is nothing.

Examples

julia> PortfolioOptimisers.norm_factor(L2Norm(), 4)1.7320508075688772julia> PortfolioOptimisers.norm_factor(LInfNorm(), nothing)1

Related

source

References

[5]
D. Cajas. Advanced Portfolio Optimization: A Cutting-edge Quantitative Approach (Springer Nature Switzerland, 2025).