Sortino

Also written Sortino ratio, sortino_ratio, target downside deviation

Average return in excess of a target, divided by the downside deviation below that same target: the square root of the mean squared shortfall, where every period at or above the target counts as a zero. Unlike the Sharpe ratio, gains do not enlarge the denominator. The target, the return frequency, how the mean is taken and what the squared shortfalls are divided by are all choices, and tools make them differently.

How it works

The ratio is the Sharpe ratio with the denominator replaced. Instead of the standard deviation of all returns around their mean, it divides by a deviation measured only below a target, so a large gain no longer counts as risk.

The definition in the Red Rock Capital paper — the one QuantStats names as its basis in its own docstring — is two lines. The numerator is the average period return minus the target return T. The denominator is the target downside deviation: for every period take min(0, Xi − T), square it, average the squares over all N periods, and take the square root. T is what Sortino's early work called the minimum acceptable return, or MAR.

Two details are where implementations part company.

The zeros stay in. A period above the target contributes a zero, and that zero is still counted in N. The paper's own complaint is that software more often than not does something else — most commonly throwing the positive returns away and taking the standard deviation of the negative ones. On its worked example (annual returns of 17, 15, 23, −5, 12, 9, 13 and −4 per cent, target zero) the defined calculation gives 4.417. Dividing the squared shortfalls by the two losing years instead of all eight gives half that; the standard deviation of the two losses alone gives about fourteen. Same eight numbers, three ratios.

The target is a parameter, not a constant. Zero, the risk-free rate and a mandate's required return are all legitimate, and each gives a different deviation, not just a different numerator.

What the tools in this catalogue actually compute

Read from their source and documentation:

  • empyrical-reloaded — sortino_ratio takes a per-period required_return, zero by default. The numerator is the arithmetic mean of returns less that target, scaled by the annualisation factor; downside_risk is the root mean square of the clipped shortfalls over every observation, scaled by its square root.
  • QuantStats — subtracts the risk-free rate (zero by default) from the returns, then divides the sum of squared negative returns by the count of all returns and multiplies the result by the square root of 252. It also ships adjusted_sortino, the same figure divided by the square root of two — a scaling the docstring attributes to Jack Schwager, meant to make it comparable with a Sharpe ratio — and a "smart" variant with an autocorrelation penalty.
  • ffn — uses excess returns over its rf, so the target is the risk-free rate, with the root mean square over all periods; it reports daily, monthly and yearly Sortino separately, annualising each by the square root of 252, 12 or 1, with the daily factor inferred from the data when it can be.
  • Backtesting.py — the numerator is its geometric annualised return minus the risk-free rate, while the downside deviation is of returns clipped at zero, not at the risk-free rate. A comment in the code says outright that its Sortino does not match empyrical's because empyrical uses the arithmetic mean.
  • Portfolio Visualizer — monthly returns, the risk-free rate as the default MAR (three-month Treasury bills from FRED), the mean squared shortfall over all n, annualised by the square root of 12. Its separately printed downside deviation is defined against zero, so it is not the denominator of the Sortino on the same page.
  • testfolio — daily excess returns over the reporting currency's risk-free proxy, the arithmetic mean, then annualised.

PortfoliosLab and Snowball Analytics print the ratio too; neither card records the formula behind it, so treat those figures as unknown on all four questions below until the vendor's help page answers them.

Why it matters here

A Sortino next to a strategy is only comparable with a Sortino computed the same way, and the cards in analysis libraries and backtesting frameworks do not compute it the same way. Before setting one tool's figure beside another's, the four questions are: what target, which return frequency, arithmetic or geometric numerator, and divided by every period or only the losing ones. A daily-annualised ratio against a monthly-annualised one, or a zero target against a T-bill target in a year when bills paid five per cent, is a difference in method, not in the strategy.

The ratio is also mechanically unstable on a short history: when only a handful of periods fall below the target, the denominator is built from those few squares, and one more bad month moves it a long way. That is a property of the arithmetic, and a reason to compute it yourself from the returns series — every library above takes one — rather than lift it from a tearsheet. The Sharpe ratio page covers the same choices for the numerator and the annualisation factor, and maximum drawdown is the other downside figure most of these tools print beside it.

Where you will meet this

The cards where this changes a decision, then the rest that use the word.

Sources

  1. Sortino: A 'Sharper' Ratio — Red Rock Capital (Thomas N. Rollinger and Scott T. Hoffman), read
  2. Portfolio Visualizer Documentation — Portfolio Visualizer, read
  3. Help, Methodology, and Tool Guides — testfolio, read
  4. quantstats/stats.py, sortino() and adjusted_sortino() — QuantStats (GitHub), read
  5. empyrical/stats.py, sortino_ratio() and downside_risk() — empyrical-reloaded (GitHub), read
  6. ffn/core.py, calc_sortino_ratio() and PerformanceStats — ffn (GitHub), read
  7. backtesting/_stats.py, compute_stats() — Backtesting.py (GitHub), read

FAQ

Why does dividing by the number of losing periods change the answer so much?

Because the periods above the target are supposed to stay in the average as zeros. On the Red Rock worked example of eight annual returns with two losses, dividing the squared shortfalls by all eight gives a downside deviation of 2.264% and a ratio of 4.417; dividing by the two losses alone doubles the deviation and halves the ratio. The gap is the square root of total periods over losing periods, so it grows as losses get rarer.

Is the Sortino a tool prints daily, monthly or annual?

Usually a per-period ratio multiplied by the square root of periods per year, but the period differs. Portfolio Visualizer computes it on monthly returns and multiplies by the square root of 12; testfolio, QuantStats, empyrical and Backtesting.py work from daily returns. ffn prints a daily, a monthly and a yearly Sortino side by side, and on the same history they are three different numbers.

Updated