24 — Performance & Attribution

Risk-Adjusted Performance#

RatiosStatistical1 min read
◆ The PatternSharpe, Sortino, Calmar — normalize returns by the risk taken

Raw returns are misleading without context. Risk-adjusted ratios level the playing field:

RatioFormulaRisk measure
Sharpe(Rp−Rf)/σTotal volatility
Sortino(Rp−Rf)/σdownDownside deviation
CalmarCAGR / Max DDMax drawdown
Treynor(Rp−Rf)/βMarket beta
Informationα / TETracking error

Sharpe > 1 is good, > 2 is excellent, > 3 is suspicious (likely overfitting or illiquidity premium). Sortino is preferred for asymmetric return distributions since it penalizes only downside.

// Risk-adjusted performance ratios
Pattern bridge: Standard deviation and downside deviation connect to The Toolkit — Sharpe Ratio.
Worked example

Twelve monthly returns and a 3% risk-free rate. The Sharpe ratio is 0.78; the Sortino ratio, which only counts downside, is 1.31, because most of the volatility here was upside. The maximum drawdown was only 2.5%, so the Calmar ratio is 3.1. Three ratios, three impressions, from the same twelve numbers.

Where it misleads
  • Sharpe ratios from short samples are very noisy, and monthly returns that are autocorrelated (smoothed, illiquid assets) inflate them (Lo 2002).
  • Trying many strategies and reporting the best inflates the Sharpe ratio; the deflated Sharpe ratio corrects for that (Bailey & López de Prado 2014).
  • Calmar is normally measured over 36 months; one year’s drawdown is too short to say much.
In code
r = np.array([2.1, -1.0, 3.2, 0.5, -2.5, 1.8, 0.9, -0.4, 2.6, -1.6, 1.4, 0.7]) / 100   # 12 months, made up
rf = 0.03 / 12
ex = r - rf
sharpe = ex.mean() / ex.std(ddof=1) * np.sqrt(12)
downside = np.sqrt((np.minimum(ex, 0) ** 2).mean()) * np.sqrt(12)
sortino = ex.mean() * 12 / downside
wealth = np.cumprod(1 + r)
mdd = (1 - wealth / np.maximum.accumulate(wealth)).max()
calmar = (wealth[-1] - 1) / mdd                            # one year, so the total return is the annual one
Python, in your browser — edit the code and run it again

Assumes import numpy as np and import pandas as pd. Each snippet carries its own example numbers; the comments say which are made up or simulated.

Sources
  • W. F. Sharpe, “Mutual Fund Performance”, Journal of Business 39(1), 1966
  • W. F. Sharpe, “The Sharpe Ratio”, Journal of Portfolio Management 21(1), 1994
  • F. A. Sortino & L. N. Price, “Performance Measurement in a Downside Risk Framework”, Journal of Investing 3(3), 1994
  • A. W. Lo, “The Statistics of Sharpe Ratios”, Financial Analysts Journal 58(4), 2002
  • D. H. Bailey & M. López de Prado, “The Deflated Sharpe Ratio: Correcting for Selection Bias, Backtest Overfitting, and Non-Normality”, Journal of Portfolio Management 40(5), 2014

Last reviewed October 2026 · How this site checks its content · Report a mistake

Linked from 2
← Previous
Alpha Generation
Open in the full reader, with the topic sidebar