Median Absolute Deviation Risk

PortfolioOptimisers.MedianAbsoluteDeviationType
struct MedianAbsoluteDeviation{__T_settings, __T_w, __T_mu, __T_flag} <: HierarchicalRiskMeasure

Represents the Median Absolute Deviation (MAD) risk measure for hierarchical portfolio optimisation.

MedianAbsoluteDeviation computes the median (or mean) absolute deviation of portfolio returns about a specified centre, providing a robust alternative to variance for measuring dispersion.

Mathematical definition

Let $\mu$ be the chosen centre (median or mean of returns, or a user-supplied value). Define the deviations $\delta_t = x_t - \mu$. The MAD is:

\[\begin{align} \mathrm{MAD}(\boldsymbol{x}) &= \mathrm{median}_{1 \leq t \leq T}(|\delta_t|)\,. \end{align}\]

Where:

  • $\mathrm{MAD}(\boldsymbol{x})$: Median absolute deviation of portfolio returns.
  • $\boldsymbol{x}$: Portfolio returns vector $T \times 1$.
  • $T$: Number of observations.
  • $\mu$: Chosen centre (median, mean, or user-supplied value).
  • $\delta_t = x_t - \mu$: Deviation of return at period $t$ from the centre.

When flag = true (default), the result is scaled by a consistency factor $(\Phi^{-1}(3/4))^{-1} \approx 1.4826$ so that the MAD is a consistent estimator of the standard deviation under normality.

Fields

  • settings: Risk measure settings.
  • w: Optional observation weights vector observations × 1, or a concrete subtype of DynamicAbstractWeights. If nothing, the computation is unweighted.
  • mu: Centre the absolute deviation is taken about. It is a MedianCenteringFunction that centres the portfolio series at the point of use, a scalar or a vector assets × 1, or a Deferred Quantity — an expected returns estimator or a prior estimator that computes the centre against the optimisation's own prior, at factory time (see MedAbsDevMu and resolve_deferred_quantities). There is no nothing state; the default is MedianCentering.
  • flag: Algorithm selection flag.

Constructors

MedianAbsoluteDeviation(;    settings::HierarchicalRiskMeasureSettings = HierarchicalRiskMeasureSettings(),    w::Option{<:ObsWeights} = nothing,    mu::MedAbsDevMu = MedianCentering(),    flag::Bool = true) -> MedianAbsoluteDeviation

Keywords correspond to the struct's fields.

Validation

  • If mu is a VecNum: !isempty(mu) and all(isfinite, mu).
  • If mu is a Number: isfinite(mu).
  • If w is not nothing, !isempty(w).
Warning

A stated mu is pinned: it crosses a Cross-Validation fold or a subset view as the whole universe's answer, so it does not follow the refit the optimisation runs on. A caller who wants it to follow the fit names a Deferred Quantity in mu, or keeps a MedianCenteringFunction, which recomputes the centre from the portfolio series at every call.

Functor

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

Computes the MAD of the portfolio returns series.

Arguments

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

View parameters

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

  • mu: A stated value is sliced to the selected indices via port_opt_view. A Deferred Quantity passes through unsliced, and then fits on the subset.

Examples

julia> MedianAbsoluteDeviation()MedianAbsoluteDeviation  settings ┼ HierarchicalRiskMeasureSettings           │   scale ┴ Float64: 1.0         w ┼ nothing        mu ┼ MedianCentering()      flag ┴ Bool: true

Related

References

  • [117] P. J. Rousseeuw and C. Croux. Alternatives to the median absolute deviation. Journal of the American Statistical Association 88, 1273–1283 (1993).
source
PortfolioOptimisers.port_opt_viewMethod
port_opt_view(x, i, args...; kwargs...) -> nothing_scalar_array_view(x, i)

Sub-select an estimator, result, or algorithm to the asset/observation index i.

port_opt_view is the index-selection counterpart of factory: where factory threads runtime values down a composed struct tree, port_opt_view threads an index selection — restricting every data-bearing field and composed child to the subset i. It is the mechanism that makes meta-optimisers (NestedClustered, SubsetResampling) and cross-validation variants operate on subproblems with identical struct shapes.

Callers do not normally call port_opt_view directly; it is driven by meta-optimisers and cross-validation internals. It is public (not exported) because extension authors who implement a new composed estimator may need to define a method. Use @vprop on data-bearing fields to have the method generated automatically.

This universal fallback handles leaf values: arrays are sliced via nothing_scalar_array_view; scalars, nothing, estimators without data fields, and algorithms pass through unchanged. Composed structs that recurse into children define their own (more specific) method — emitted by @vprop or hand-written.

The threaded tail args... (typically the returns matrix X for the JuMP families) and any kwargs are accepted and dropped here, so a macro-threaded port_opt_view(child, i, X) never MethodErrors on a leaf field.

Algorithm

  1. Drop args... and kwargs.... This method is the leaf of the recursion, so it threads nothing further.
  2. Return nothing_scalar_array_view of x at i, whose own algorithm names the rule for each leaf type.

Related

source

References

[117]
P. J. Rousseeuw and C. Croux. Alternatives to the median absolute deviation. Journal of the American Statistical Association 88, 1273–1283 (1993).