Skip to content

Sortino Ratio

Downside-deviation-adjusted Sharpe variant. It only penalizes negative returns (returns below target_return), using the same zero-volatility guard as Sharpe. Edge-first; wired to more than one Price Factor it fans out to per-ticker by_symbol results.

What (One-liner)

A Layer-1 transform: consume a returns series, emit a risk-adjusted return that penalizes only downside (sub-target) volatility — the asymmetric correction of Sharpe. Zero downside clamps to 0.0, not inf.

Inputs

  • returns (array, required) — return series.
  • target_return (number, optional) — minimum acceptable return, default 0.
  • annualization_factor (number, optional) — default 252.

Outputs

  • sortino_ratio — annualized Sortino.
  • by_symbol — per-ticker map when fed by multiple Price Factors.

How to use

  1. Provide a returns array.
  2. Optionally set target_return (default 0) and annualization_factor.

Core formulas

excess = returns - rf
downside = [min(x - target, 0) for x in excess]
sortino = mean(excess) / std(downside, ddof=0) × √annualization_factor

Zero downside → 0.0.

Assumptions & applicability

Assumptions: annualization_factor matches input frequency (252 daily) + MAR = target_return (default 0) + downside std right-truncated + zero downside → 0.0.

Applicability: fat-tailed / skewed / hedge-fund-style strategies, n ≥ 30.

Out of scope: intraday, all-positive return sequences, short series n<30.

Known limitations

  1. Undefined / unstable when there are very few sub-target observations.
  2. target_return choice materially shifts the result.
  3. Zero downside clamped to 0.0 (BUG-GOLDEN-001 fix approach).
  4. Shares annualization assumptions with Sharpe.

References

Sortino & Price (1994) + Rollinger-Hoffman (2013) calculation pitfalls guide.

Golden Test

tests/golden/fixtures/tier1/sortino_ratio/, 1e-12 tolerance, passing as of 2026-05-25. Reference: independent numpy 2.2.6 reimplementation of Sortino-Price (1994).

Changelog

  • 1.1.0 (2026-05-25) — Promoted to Active as Layer-1 transform; merged rich governance fields from the superseded Layer-0 sortino_ratio card.
  • 1.0.0 (2026-05-23) — Initial edge-first Layer-1 Draft card.

Verifiable intelligence for the decisions that demand scrutiny.