API Documentation
Portfolio analytics
Modules
OnlinePortfolioAnalytics.OnlinePortfolioAnalytics — ModuleOnlinePortfolioAnalytics provides streaming portfolio analytics using online algorithms that process data incrementally without storing the full history.
Features
- Return Calculations:
SimpleAssetReturn,LogAssetReturn,CumulativeReturn,AnnualizedReturn - Mean Returns:
ArithmeticMeanReturn,GeometricMeanReturn - Volatility:
StdDev,DownsideDeviation,UpsideDeviation - Drawdown Analysis:
DrawDowns,ArithmeticDrawDowns,MaxDrawDown,MaxArithmeticDrawDown - Risk-Adjusted Returns:
Sharpe,Sortino,Calmar,Omega - CAPM Metrics:
Beta,ExpectedReturn,Treynor,JensenAlpha - Relative Performance:
TrackingError,InformationRatio - Risk Metrics:
VaR,ExpectedShortfall - Statistical Moments:
AssetReturnMoments
Usage
All types implement the OnlineStatsBase interface:
using OnlinePortfolioAnalytics
# Create a statistic
stat = Sharpe{Float64}()
# Feed observations one at a time
for return_value in returns
fit!(stat, return_value)
end
# Get current value
result = value(stat)For metrics requiring paired asset/benchmark data, use AssetBenchmarkReturn:
stat = Beta{Float64}()
fit!(stat, AssetBenchmarkReturn(0.05, 0.03)) # Asset +5%, Market +3%
value(stat)MIT License
Copyright (c) 2024 FemtoTrader <femto.trader@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Functions
OnlineStats.fit! Base.empty!
Asset return
OnlinePortfolioAnalytics.SimpleAssetReturn — Typemutable struct SimpleAssetReturn{T} <: OnlinePortfolioAnalytics.AssetReturn{T}SimpleAssetReturn{T}(; period::Int = 1)Calculate simple (arithmetic) returns from a stream of price observations.
Simple returns measure the percentage change in price between two periods using the formula (Pt - P{t-k}) / P_{t-k}, where k is the period.
Mathematical Definition
$R_t = \frac{P_t - P_{t-k}}{P_{t-k}}$
Where:
- $P_t$ = price at time t
- $P_{t-k}$ = price k periods ago
- $k$ = period (default: 1)
Parameters
period: Number of periods for return calculation (default: 1)
Edge Cases
- Returns
missinguntilperiod + 1observations have been received - Returns
missingif price at t-k is zero (division by zero avoided)
Fields
value::Union{Missing,T}: Current return valuen::Int: Number of observationsperiod::Int: Return calculation period
Example
stat = SimpleAssetReturn{Float64}()
fit!(stat, 100.0) # First price observation
fit!(stat, 110.0) # Second price observation
value(stat) # Returns 0.1 (10% return)See also: LogAssetReturn, CumulativeReturn
OnlinePortfolioAnalytics.LogAssetReturn — Typemutable struct LogAssetReturn{T} <: OnlinePortfolioAnalytics.AssetReturn{T}LogAssetReturn{T}(; period::Int = 1)Calculate logarithmic (continuously compounded) returns from a stream of price observations.
Log returns are additive across time periods and are commonly used in financial modeling because they have better statistical properties than simple returns.
Mathematical Definition
$R_t = \ln\left(\frac{P_t}{P_{t-k}}\right)$
Where:
- $P_t$ = price at time t
- $P_{t-k}$ = price k periods ago
- $k$ = period (default: 1)
- $\ln$ = natural logarithm
Parameters
period: Number of periods for return calculation (default: 1)
Edge Cases
- Returns
missinguntilperiod + 1observations have been received - Undefined behavior if price at t-k is zero or negative
Fields
value::Union{Missing,T}: Current return valuen::Int: Number of observationsperiod::Int: Return calculation period
Example
stat = LogAssetReturn{Float64}()
fit!(stat, 100.0) # First price observation
fit!(stat, 110.0) # Second price observation
value(stat) # Returns ~0.0953 (log return)See also: SimpleAssetReturn, CumulativeReturn
Mean return
OnlinePortfolioAnalytics.ArithmeticMeanReturn — Typemutable struct ArithmeticMeanReturn{T} <: OnlinePortfolioAnalytics.AbstractMeanReturn{T}ArithmeticMeanReturn{T}()Calculate the arithmetic mean of returns from a stream of observations.
The arithmetic mean is the simple average of all returns. It is commonly used for short-term performance analysis but can overestimate long-term growth.
Mathematical Definition
$\bar{R} = \frac{1}{n}\sum_{i=1}^{n} R_i$
Where:
- $R_i$ = return for period i
- $n$ = number of observations
Edge Cases
- Returns
0.0when no observations (n=0)
Fields
value::T: Current mean returnn::Int: Number of observationssum::Sum: Internal sum tracker
Example
stat = ArithmeticMeanReturn{Float64}()
fit!(stat, 0.05) # 5% return
fit!(stat, -0.02) # -2% return
fit!(stat, 0.03) # 3% return
value(stat) # Returns 0.02 (2% average)See also: GeometricMeanReturn, StdDev
OnlinePortfolioAnalytics.GeometricMeanReturn — Typemutable struct GeometricMeanReturn{T} <: OnlinePortfolioAnalytics.AbstractMeanReturn{T}GeometricMeanReturn{T}()Calculate the geometric mean of returns from a stream of observations.
The geometric mean accounts for compounding and provides a better measure of long-term average return than arithmetic mean. It represents the constant return rate that would produce the same final value.
Mathematical Definition
$G = \left(\prod_{i=1}^{n}(1+R_i)\right)^{1/n} - 1$
Where:
- $R_i$ = return for period i
- $n$ = number of observations
Edge Cases
- Returns
0.0when no observations (n=0) - Returns
-1.0if cumulative product becomes zero
Fields
value::T: Current geometric mean returnn::Int: Number of observationsprod::Prod: Internal product tracker
Example
stat = GeometricMeanReturn{Float64}()
fit!(stat, 0.10) # 10% return
fit!(stat, -0.05) # -5% return
fit!(stat, 0.08) # 8% return
value(stat) # Geometric mean returnSee also: ArithmeticMeanReturn, CumulativeReturn
Cumulative return
OnlinePortfolioAnalytics.CumulativeReturn — Typemutable struct CumulativeReturn{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{T}CumulativeReturn{T}()Calculate the cumulative (total) return from a stream of periodic returns.
Cumulative return represents the total growth factor of an investment over the entire observation period using geometric compounding.
Mathematical Definition
$C = \prod_{i=1}^{n}(1+R_i)$
Where:
- $R_i$ = return for period i
- $n$ = number of observations
Note: The value represents the growth factor, not the percentage return. Subtract 1 to get the percentage cumulative return.
Edge Cases
- Returns
0.0when no observations (n=0) - Returns the running product as observations are added
Fields
value::T: Current cumulative growth factorn::Int: Number of observationsprod::Prod: Internal product tracker
Example
stat = CumulativeReturn{Float64}()
fit!(stat, 0.10) # 10% return
fit!(stat, -0.05) # -5% return
fit!(stat, 0.03) # 3% return
value(stat) # Cumulative growth factor (e.g., 1.0785)
# Percentage return: value(stat) - 1 = 0.0785 (7.85%)See also: AnnualizedReturn, DrawDowns, GeometricMeanReturn
Standard deviation
OnlinePortfolioAnalytics.StdDev — Typemutable struct StdDev{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{T}StdDev{T}()Calculate the sample standard deviation of returns from a stream of observations.
Standard deviation measures the volatility or dispersion of returns around the mean. It is a fundamental risk measure in portfolio analysis.
Mathematical Definition
$\sigma = \sqrt{\frac{1}{n-1}\sum_{i=1}^{n}(R_i - \bar{R})^2}$
Where:
- $R_i$ = return for period i
- $\bar{R}$ = mean return
- $n$ = number of observations
Edge Cases
- Returns
1.0when no observations (initial value) - Returns
0.0when only one observation (no variance)
Fields
value::T: Current standard deviationn::Int: Number of observationsvariance::Variance: Internal variance tracker
Example
stat = StdDev{Float64}()
fit!(stat, 0.05) # 5% return
fit!(stat, -0.02) # -2% return
fit!(stat, 0.03) # 3% return
value(stat) # Standard deviation of returnsSee also: ArithmeticMeanReturn, Sharpe
Drawdowns
OnlinePortfolioAnalytics.DrawDowns — Typemutable struct DrawDowns{T} <: OnlinePortfolioAnalytics.AbstractDrawDowns{T}DrawDowns{T}()Calculate the current drawdown from a stream of returns using the geometric method.
Drawdown measures the percentage decline from the peak cumulative return to the current cumulative return. This implementation uses geometric compounding where cumulative returns are computed as the product of (1 + return).
Mathematical Definition
For a sequence of returns r₁, r₂, ..., rₙ:
- Cumulative return at time t: $C_t = \prod_{i=1}^{t}(1+R_i)$
- Running peak at time t: $P_t = \max(C_1, C_2, ..., C_t)$
- Drawdown at time t: $D_t = \frac{C_t}{P_t} - 1$
Edge Cases
- Returns
0.0when no observations (n=0) - Returns
0.0at new peaks (no drawdown) - Returns negative values during drawdown periods
Fields
value::T: Current drawdown value (negative or zero)n::Int: Number of observationsprod::Prod: Internal cumulative return trackerextrema::Extrema: Internal peak tracker
Example
stat = DrawDowns{Float64}()
fit!(stat, 0.10) # 10% gain - new peak
fit!(stat, -0.05) # 5% loss - in drawdown
fit!(stat, -0.03) # 3% loss - deeper drawdown
value(stat) # Current drawdown (negative value)See also: ArithmeticDrawDowns, MaxDrawDown
OnlinePortfolioAnalytics.ArithmeticDrawDowns — Typemutable struct ArithmeticDrawDowns{T} <: OnlinePortfolioAnalytics.AbstractDrawDowns{T}ArithmeticDrawDowns{T}()Calculate the current drawdown from a stream of returns using the arithmetic method.
Drawdown measures the percentage decline from the peak cumulative return to the current cumulative return. This implementation uses arithmetic compounding where cumulative returns are computed as the sum of returns.
Mathematical Definition
For a sequence of returns r₁, r₂, ..., rₙ:
- Cumulative return at time t: $C_t = 1 + \sum_{i=1}^{t} R_i$
- Running peak at time t: $P_t = \max(C_1, C_2, ..., C_t)$
- Drawdown at time t: $D_t = \frac{C_t}{P_t} - 1$
Edge Cases
- Returns
0.0when no observations (n=0) - Returns
0.0at new peaks (no drawdown) - Returns negative values during drawdown periods
Fields
value::T: Current drawdown value (negative or zero)n::Int: Number of observationssum::Sum: Internal cumulative return trackerextrema::Extrema: Internal peak tracker
Example
stat = ArithmeticDrawDowns{Float64}()
fit!(stat, 0.10) # 10% gain - new peak
fit!(stat, -0.05) # 5% loss - in drawdown
fit!(stat, -0.03) # 3% loss - deeper drawdown
value(stat) # Current drawdown (negative value)See also: DrawDowns, MaxArithmeticDrawDown
Maximum Drawdown
OnlinePortfolioAnalytics.AbstractMaxDrawDown — TypeAbstract supertype for maximum drawdown statistics. Subtypes: MaxDrawDown (geometric), MaxArithmeticDrawDown (arithmetic)
OnlinePortfolioAnalytics.MaxDrawDown — Typemutable struct MaxDrawDown{T} <: OnlinePortfolioAnalytics.AbstractMaxDrawDown{T}MaxDrawDown{T}()Track the maximum (worst) peak-to-trough decline using geometric return compounding.
Maximum drawdown is the largest percentage decline from a cumulative return peak to a subsequent trough. This implementation uses the geometric method where cumulative returns are computed as the product of (1 + return).
The value returns the most negative drawdown observed, following industry convention where "maximum drawdown" refers to the largest decline magnitude.
Mathematical Definition
For a sequence of returns r₁, r₂, ..., rₙ:
- Cumulative return at time t: Cₜ = ∏ᵢ₌₁ᵗ (1 + rᵢ)
- Running peak at time t: Pₜ = max(C₁, C₂, ..., Cₜ)
- Drawdown at time t: Dₜ = Cₜ / Pₜ - 1
- Maximum drawdown: min(D₁, D₂, ..., Dₙ)
Example
stat = MaxDrawDown{Float64}()
fit!(stat, 0.10) # 10% gain
fit!(stat, -0.05) # 5% loss
fit!(stat, -0.15) # 15% loss
value(stat) # Returns most negative drawdown observed (e.g., -0.19)References
- empyrical (Python): max_drawdown() returns negative value
- PerformanceAnalytics (R): maxDrawdown() returns positive magnitude
See also: MaxArithmeticDrawDown, DrawDowns
OnlinePortfolioAnalytics.MaxArithmeticDrawDown — Typemutable struct MaxArithmeticDrawDown{T} <: OnlinePortfolioAnalytics.AbstractMaxDrawDown{T}MaxArithmeticDrawDown{T}()Track the maximum (worst) peak-to-trough decline using arithmetic return compounding.
This implementation uses the arithmetic method where cumulative returns are computed as the sum of returns, suitable for simple (non-compounding) returns.
The value returns the most negative drawdown observed, following industry convention where "maximum drawdown" refers to the largest decline magnitude.
Mathematical Definition
For a sequence of returns r₁, r₂, ..., rₙ:
- Cumulative return at time t: Cₜ = 1 + Σᵢ₌₁ᵗ rᵢ
- Running peak at time t: Pₜ = max(C₁, C₂, ..., Cₜ)
- Drawdown at time t: Dₜ = Cₜ / Pₜ - 1
- Maximum drawdown: min(D₁, D₂, ..., Dₙ)
Example
stat = MaxArithmeticDrawDown{Float64}()
fit!(stat, 0.10) # 10% gain
fit!(stat, -0.05) # 5% loss
value(stat) # Returns most negative drawdown observedSee also: MaxDrawDown, ArithmeticDrawDowns
Statistical moments
OnlinePortfolioAnalytics.AssetReturnMoments — Typemutable struct AssetReturnMoments{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsMultiOutput{T}AssetReturnMoments{T}()Calculate the first four statistical moments of returns from a stream of observations.
This type computes mean, standard deviation, skewness, and kurtosis simultaneously, providing a complete statistical profile of the return distribution. The output is a NamedTuple with fields :mean, :std, :skewness, and :kurtosis.
Mathematical Definition
- Mean: $\bar{R} = \frac{1}{n}\sum_{i=1}^{n} R_i$
- Standard deviation: $\sigma = \sqrt{\frac{1}{n-1}\sum_{i=1}^{n}(R_i - \bar{R})^2}$
- Skewness: $\gamma_1 = \frac{\frac{1}{n}\sum_{i=1}^{n}(R_i - \bar{R})^3}{\sigma^3}$
- Kurtosis: $\gamma_2 = \frac{\frac{1}{n}\sum_{i=1}^{n}(R_i - \bar{R})^4}{\sigma^4} - 3$ (excess kurtosis)
Edge Cases
- Returns
(mean=0.0, std=0.0, skewness=0.0, kurtosis=0.0)when no observations - Skewness and kurtosis require at least 3-4 observations for meaningful values
Fields
value::NamedTuple: Current moments as (mean, std, skewness, kurtosis)n::Int: Number of observationsmoments::Moments: Internal moments tracker
Example
stat = AssetReturnMoments{Float64}()
fit!(stat, 0.05)
fit!(stat, -0.02)
fit!(stat, 0.03)
fit!(stat, -0.01)
m = value(stat)
m.mean # Mean return
m.std # Standard deviation
m.skewness # Skewness
m.kurtosis # Excess kurtosisSee also: ArithmeticMeanReturn, StdDev
Sharpe ratio
OnlinePortfolioAnalytics.Sharpe — Typemutable struct Sharpe{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{T}Sharpe{T}(; period=252, risk_free=0)Calculate the Sharpe ratio from a stream of periodic returns.
The Sharpe ratio measures risk-adjusted performance by dividing excess return (above risk-free rate) by volatility. Higher values indicate better risk-adjusted returns.
Mathematical Definition
$S = \sqrt{T} \times \frac{E[R] - r_f}{\sigma}$
Where:
- $E[R]$ = expected (mean) return
- $r_f$ = risk-free rate
- $\sigma$ = standard deviation of returns
- $T$ = annualization period
Parameters
period: Annualization factor (default: 252)- Daily: 252 (trading days per year)
- Weekly: 52
- Monthly: 12
- Hourly: 252 × 6.5
risk_free: Risk-free rate per period (default: 0)
Edge Cases
- Returns
NaNwhen standard deviation is zero (all returns identical) - Returns
0.0when no observations
Fields
value::T: Current Sharpe ration::Int: Number of observationsmean::Mean: Internal mean trackerstddev::StdDev: Internal standard deviation trackerperiod::Int: Annualization factorrisk_free::T: Risk-free rate
Example
stat = Sharpe{Float64}(period=252, risk_free=0.0)
fit!(stat, 0.02) # 2% return
fit!(stat, -0.01) # -1% return
fit!(stat, 0.03) # 3% return
value(stat) # Annualized Sharpe ratioSortino ratio
OnlinePortfolioAnalytics.Sortino — Typemutable struct Sortino{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{T}Sortino{T}(; period=252, risk_free=0)Calculate the Sortino ratio from a stream of periodic returns.
The Sortino ratio is similar to the Sharpe ratio but uses only downside deviation (volatility of negative returns) in the denominator, making it more appropriate for asymmetric return distributions.
Mathematical Definition
$So = \sqrt{T} \times \frac{E[R] - r_f}{\sigma_{down}}$
Where:
- $E[R]$ = expected (mean) return
- $r_f$ = risk-free rate
- $\sigma_{down}$ = standard deviation of negative returns only
- $T$ = annualization period
Parameters
period: Annualization factor (default: 252)- Daily: 252 (trading days per year)
- Weekly: 52
- Monthly: 12
- Hourly: 252 × 6.5
risk_free: Risk-free rate per period (default: 0)
Edge Cases
- Returns
NaNorInfwhen downside deviation is zero (no negative returns) - Returns
0.0when no observations
Fields
value::T: Current Sortino ration::Int: Number of observationsmean_ret::Mean: Internal mean return trackerstddev_neg_ret::StdDev: Internal downside deviation trackerperiod::Int: Annualization factorrisk_free::T: Risk-free rate
Example
stat = Sortino{Float64}(period=252, risk_free=0.0)
fit!(stat, 0.02) # 2% return (positive, not included in downside)
fit!(stat, -0.01) # -1% return (negative, included in downside)
fit!(stat, 0.03) # 3% return
value(stat) # Annualized Sortino ratioSee also: Sharpe, DownsideDeviation, Calmar
Annualized return
OnlinePortfolioAnalytics.AnnualizedReturn — Typemutable struct AnnualizedReturn{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{T}AnnualizedReturn{T}(; period=252)Calculate annualized return (CAGR - Compound Annual Growth Rate) from a stream of periodic returns using geometric compounding.
Mathematical Definition
For a sequence of returns r₁, r₂, ..., rₙ:
- Cumulative return: C = ∏ᵢ₌₁ⁿ (1 + rᵢ)
- Annualized return: (C)^(period/n) - 1
This is equivalent to the CAGR (Compound Annual Growth Rate) formula.
Parameters
period: Annualization factor (default 252 for daily returns)- Daily: 252 (trading days per year)
- Weekly: 52
- Monthly: 12
- Hourly: 252 × 6.5
Fields
value::T: Current annualized returnn::Int: Number of observationsprod::Prod{T}: Internal product tracker for cumulative returnperiod::Int: Annualization factor
Example
stat = AnnualizedReturn()
fit!(stat, 0.01) # 1% daily return
fit!(stat, 0.02) # 2% daily return
fit!(stat, -0.01) # -1% daily return
value(stat) # Annualized returnSee also: Calmar, CumulativeReturn
Calmar ratio
OnlinePortfolioAnalytics.Calmar — Typemutable struct Calmar{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{T}Calmar{T}(; period=252)Calculate the Calmar ratio from a stream of periodic returns.
The Calmar ratio measures risk-adjusted performance by dividing the annualized return by the absolute value of the maximum drawdown.
Mathematical Definition
$\text{Calmar} = \frac{\text{AnnualizedReturn}}{|\text{MaxDrawDown}|}$
Where:
- AnnualizedReturn is the CAGR (Compound Annual Growth Rate)
- MaxDrawDown is the worst peak-to-trough decline (negative value)
Parameters
period: Annualization factor (default 252 for daily returns)- Daily: 252 (trading days per year)
- Weekly: 52
- Monthly: 12
Fields
value::T: Current Calmar ration::Int: Number of observationsannualized_return::AnnualizedReturn{T}: Internal annualized return trackermax_drawdown::MaxDrawDown{T}: Internal max drawdown trackerperiod::Int: Annualization factor
Edge Cases
- Returns
Infwhen max drawdown is zero (all positive returns) - Returns
0.0when no observations have been made
Example
stat = Calmar()
fit!(stat, 0.05) # 5% gain
fit!(stat, -0.03) # 3% loss
fit!(stat, 0.02) # 2% gain
value(stat) # Calmar ratioSee also: AnnualizedReturn, MaxDrawDown, Sharpe
Beta
OnlinePortfolioAnalytics.Beta — Typemutable struct Beta{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{AssetBenchmarkReturn{T}}Beta{T}()Calculate the beta coefficient (systematic risk) from paired asset/market returns.
Beta measures how an asset moves relative to a market benchmark. A beta of 1.0 means the asset moves with the market; beta > 1 means more volatile than market; beta < 1 means less volatile; negative beta means inverse correlation.
Mathematical Definition
$\beta = \frac{\text{Cov}(R_a, R_m)}{\text{Var}(R_m)}$
Where:
- $R_a$ = asset returns
- $R_m$ = market returns
- Cov = covariance
- Var = variance
Input Type
Accepts AssetBenchmarkReturn observations via fit!.
Edge Cases
- Returns
0.0when fewer than 2 observations (insufficient data) - Returns
0.0when market variance is zero (avoid division by zero)
Fields
value::T: Current beta valuen::Int: Number of observationscov_matrix::CovMatrix: Internal 2x2 covariance matrix tracker
Example
stat = Beta()
fit!(stat, AssetBenchmarkReturn(0.05, 0.03)) # Asset +5%, Market +3%
fit!(stat, AssetBenchmarkReturn(0.02, 0.01)) # Asset +2%, Market +1%
fit!(stat, AssetBenchmarkReturn(-0.01, -0.02)) # Asset -1%, Market -2%
value(stat) # Beta coefficientSee also: AssetBenchmarkReturn, ExpectedReturn
Expected return (CAPM)
OnlinePortfolioAnalytics.ExpectedReturn — Typemutable struct ExpectedReturn{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{AssetBenchmarkReturn{T}}ExpectedReturn{T}(; risk_free=0.0)Calculate the CAPM (Capital Asset Pricing Model) expected return from paired asset/market returns.
The expected return represents the theoretical return an asset should earn based on its systematic risk (beta) relative to the market.
Mathematical Definition
$E[R_a] = r_f + \beta \times (E[R_m] - r_f)$
Where:
- $E[R_a]$ = expected return of the asset
- $r_f$ = risk-free rate
- $\beta$ = beta coefficient (systematic risk)
- $E[R_m]$ = expected market return (mean)
Parameters
risk_free: Risk-free rate of return (default 0.0)
Input Type
Accepts AssetBenchmarkReturn observations via fit!.
Edge Cases
- Returns
risk_freewhen fewer than 2 observations (insufficient data for beta)
Fields
value::T: Current expected returnn::Int: Number of observationsbeta::Beta{T}: Internal beta trackerrisk_free::T: Risk-free rate
Example
stat = ExpectedReturn(risk_free=0.02) # 2% risk-free rate
fit!(stat, AssetBenchmarkReturn(0.05, 0.03)) # Asset +5%, Market +3%
fit!(stat, AssetBenchmarkReturn(0.02, 0.01)) # Asset +2%, Market +1%
value(stat) # CAPM expected returnSee also: AssetBenchmarkReturn, Beta
Value at Risk (VaR)
OnlinePortfolioAnalytics.VaR — Typemutable struct VaR{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{T}VaR{T}(; confidence=0.95, b=500)Calculate Value at Risk (VaR) from a stream of returns using online quantile estimation.
VaR measures the potential loss at a given confidence level. For example, a 95% VaR of -0.05 means there is a 5% chance of losing more than 5% of the portfolio value.
Mathematical Definition
$\text{VaR}_\alpha = \text{Quantile}_{1-\alpha}(R)$
Where:
- $\alpha$ = confidence level (e.g., 0.95 for 95% VaR)
- $R$ = return distribution
- The result is the $(1-\alpha)$ percentile of returns
Parameters
confidence: Confidence level (default 0.95 for 95% VaR)b: Number of histogram bins for quantile estimation (default 500)
Input Type
Accepts single return values (Number) via fit!.
Edge Cases
- Returns
0.0when no observations (n=0)
Fields
value::T: Current VaR valuen::Int: Number of observationsquantile::Quantile: Internal quantile trackerconfidence::Float64: Confidence level
Example
stat = VaR(confidence=0.95)
for ret in returns
fit!(stat, ret)
end
var_95 = value(stat) # 5th percentile lossSee also: ExpectedShortfall
Expected Shortfall (CVaR)
OnlinePortfolioAnalytics.ExpectedShortfall — Typemutable struct ExpectedShortfall{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{T}ExpectedShortfall{T}(; confidence=0.95)Calculate Expected Shortfall (CVaR/ES) from a stream of returns.
Expected Shortfall measures the average loss in the tail beyond the VaR threshold. Also known as Conditional VaR (CVaR) or Average Value at Risk (AVaR). It is considered a more coherent risk measure than VaR.
Mathematical Definition
$\text{ES}_\alpha = E[R | R \leq \text{VaR}_\alpha]$
Where:
- $\alpha$ = confidence level (e.g., 0.95 for 95% ES)
- $R$ = return distribution
- ES is the conditional expectation of returns below VaR
Parameters
confidence: Confidence level (default 0.95 for 95% ES)
Input Type
Accepts single return values (Number) via fit!.
Edge Cases
- Returns
0.0when no observations (n=0) - Returns VaR value when no observations below threshold
Fields
value::T: Current ES valuen::Int: Number of observationssum_below::T: Sum of returns at or below VaR thresholdcount_below::Int: Count of returns at or below VaRvar_threshold::T: Current VaR estimate used as thresholdconfidence::Float64: Confidence level
Example
stat = ExpectedShortfall(confidence=0.95)
for ret in returns
fit!(stat, ret)
end
es_95 = value(stat) # Average of worst 5% returnsSee also: VaR
Treynor ratio
OnlinePortfolioAnalytics.Treynor — Typemutable struct Treynor{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{AssetBenchmarkReturn{T}}Treynor{T}(; risk_free=0.0)Calculate Treynor Ratio from paired asset/market returns.
Treynor Ratio measures the excess return per unit of systematic risk (beta). Unlike Sharpe Ratio which uses total risk, Treynor uses only market-related risk.
Mathematical Definition
$\text{Treynor} = \frac{E[R_a] - r_f}{\beta}$
Where:
- $R_a$ = asset returns
- $r_f$ = risk-free rate
- $\beta$ = systematic risk (from CAPM)
Parameters
risk_free: Risk-free rate (default 0.0)
Input Type
Accepts AssetBenchmarkReturn observations via fit!.
Edge Cases
- Returns
0.0when fewer than 2 observations (insufficient for beta) - Returns
Infor-Infwhen beta is zero (division by zero)
Fields
value::T: Current Treynor ration::Int: Number of observationsbeta::Beta{T}: Internal beta trackerasset_mean::Mean: Mean asset return trackerrisk_free::T: Risk-free rate
Example
stat = Treynor(risk_free=0.02)
fit!(stat, AssetBenchmarkReturn(0.05, 0.03)) # Asset +5%, Market +3%
fit!(stat, AssetBenchmarkReturn(0.02, 0.01)) # Asset +2%, Market +1%
value(stat) # (mean_return - rf) / betaSee also: AssetBenchmarkReturn, Beta, Sharpe
Information ratio
OnlinePortfolioAnalytics.InformationRatio — Typemutable struct InformationRatio{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{AssetBenchmarkReturn{T}}InformationRatio{T}()Calculate Information Ratio from paired asset/benchmark returns.
Information Ratio measures the excess return of an asset relative to its benchmark, adjusted for the tracking error. It is a key metric for evaluating active management skill.
Mathematical Definition
$\text{IR} = \frac{E[R_a - R_b]}{\sigma(R_a - R_b)} = \frac{\text{Mean Excess Return}}{\text{Tracking Error}}$
Where:
- $R_a$ = asset/portfolio returns
- $R_b$ = benchmark returns
- $E[.]$ = expected value (mean)
- $\sigma$ = standard deviation
Input Type
Accepts AssetBenchmarkReturn observations via fit!.
Edge Cases
- Returns
0.0when fewer than 2 observations (insufficient for TE) - Returns
0.0when tracking error is zero (perfect tracking)
Fields
value::T: Current IR valuen::Int: Number of observationsexcess_mean::Mean: Tracker for mean excess returntracking_error::TrackingError{T}: Tracker for tracking error
Example
stat = InformationRatio()
fit!(stat, AssetBenchmarkReturn(0.05, 0.04)) # Asset +5%, Benchmark +4%
fit!(stat, AssetBenchmarkReturn(0.02, 0.03)) # Asset +2%, Benchmark +3%
fit!(stat, AssetBenchmarkReturn(-0.01, -0.02)) # Asset -1%, Benchmark -2%
value(stat) # Mean(excess) / TrackingErrorSee also: AssetBenchmarkReturn, TrackingError
Tracking error
OnlinePortfolioAnalytics.TrackingError — Typemutable struct TrackingError{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{AssetBenchmarkReturn{T}}TrackingError{T}()Calculate Tracking Error from paired asset/benchmark returns.
Tracking Error measures how closely a portfolio follows its benchmark by computing the standard deviation of the difference between asset and benchmark returns.
Mathematical Definition
$\text{TE} = \sigma(R_a - R_b)$
Where:
- $R_a$ = asset/portfolio returns
- $R_b$ = benchmark returns
- $\sigma$ = standard deviation
Input Type
Accepts AssetBenchmarkReturn observations via fit!.
Edge Cases
- Returns
0.0when fewer than 2 observations (insufficient for std dev) - Returns
0.0for perfect tracking (identical returns)
Fields
value::T: Current tracking error valuen::Int: Number of observationsdiff_variance::Variance: Internal variance tracker for return differences
Example
stat = TrackingError()
fit!(stat, AssetBenchmarkReturn(0.05, 0.04)) # Asset +5%, Benchmark +4%
fit!(stat, AssetBenchmarkReturn(0.02, 0.03)) # Asset +2%, Benchmark +3%
fit!(stat, AssetBenchmarkReturn(-0.01, -0.02)) # Asset -1%, Benchmark -2%
value(stat) # Standard deviation of differencesSee also: AssetBenchmarkReturn, InformationRatio
Downside deviation
OnlinePortfolioAnalytics.DownsideDeviation — Typemutable struct DownsideDeviation{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{T}DownsideDeviation{T}(; threshold=0.0)Calculate Downside Deviation (semi-standard deviation) from a stream of returns.
Downside Deviation measures the volatility of returns below a threshold (typically 0 or MAR). It captures only negative volatility, providing a more intuitive measure of risk than symmetric standard deviation.
Mathematical Definition
$\text{DD} = \sqrt{\frac{1}{n} \sum_{i=1}^{n} \min(R_i - \tau, 0)^2}$
Where:
- $R_i$ = return for period i
- $\tau$ = threshold (Minimum Acceptable Return)
- $n$ = total number of observations (consistent with Sortino definition)
Parameters
threshold: Minimum Acceptable Return (default 0.0)
Input Type
Accepts single return values (Number) via fit!.
Edge Cases
- Returns
0.0when no observations (n=0) - Returns
0.0when all returns are above threshold
Fields
value::T: Current downside deviationn::Int: Total observation countn_below::Int: Count of observations below thresholdsum_sq_below::T: Sum of squared deviations below thresholdthreshold::T: MAR threshold
Example
stat = DownsideDeviation(threshold=0.0)
for ret in returns
fit!(stat, ret)
end
dd = value(stat) # Semi-std of returns below 0See also: UpsideDeviation, Sortino
Upside deviation
OnlinePortfolioAnalytics.UpsideDeviation — Typemutable struct UpsideDeviation{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{T}UpsideDeviation{T}(; threshold=0.0)Calculate Upside Deviation (semi-standard deviation) from a stream of returns.
Upside Deviation measures the volatility of returns above a threshold. It captures only positive volatility, complementing Downside Deviation.
Mathematical Definition
$\text{UD} = \sqrt{\frac{1}{n} \sum_{i=1}^{n} \max(R_i - \tau, 0)^2}$
Where:
- $R_i$ = return for period i
- $\tau$ = threshold (Minimum Acceptable Return)
- $n$ = total number of observations
Parameters
threshold: Minimum Acceptable Return (default 0.0)
Input Type
Accepts single return values (Number) via fit!.
Edge Cases
- Returns
0.0when no observations (n=0) - Returns
0.0when all returns are below threshold
Fields
value::T: Current upside deviationn::Int: Total observation countn_above::Int: Count of observations above thresholdsum_sq_above::T: Sum of squared deviations above thresholdthreshold::T: MAR threshold
Example
stat = UpsideDeviation(threshold=0.0)
for ret in returns
fit!(stat, ret)
end
ud = value(stat) # Semi-std of returns above 0See also: DownsideDeviation
Omega ratio
OnlinePortfolioAnalytics.Omega — Typemutable struct Omega{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{T}Omega{T}(; threshold=0.0)Calculate Omega Ratio from a stream of returns.
Omega Ratio measures the probability-weighted ratio of gains to losses above/below a threshold. It considers the entire return distribution, not just mean and variance.
Mathematical Definition
$\Omega(\tau) = \frac{\sum_{R_i > \tau} (R_i - \tau)}{\sum_{R_i < \tau} (\tau - R_i)}$
Where:
- $R_i$ = return for period i
- $\tau$ = threshold (typically 0)
Parameters
threshold: Reference threshold (default 0.0)
Input Type
Accepts single return values (Number) via fit!.
Edge Cases
- Returns
0.0when no observations (n=0) - Returns
Infwhen no losses (all returns above threshold) - Returns
0.0when no gains (all returns below threshold)
Fields
value::T: Current Omega ration::Int: Observation countsum_gains::T: Sum of returns above thresholdsum_losses::T: Sum of absolute shortfall below thresholdthreshold::T: Reference threshold
Example
stat = Omega(threshold=0.0)
for ret in returns
fit!(stat, ret)
end
omega = value(stat) # sum(gains) / sum(losses)Jensen's Alpha
OnlinePortfolioAnalytics.JensenAlpha — Typemutable struct JensenAlpha{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{AssetBenchmarkReturn{T}}JensenAlpha{T}(; risk_free=0.0)Calculate Jensen's Alpha from paired asset/market returns.
Jensen's Alpha measures the excess return of a portfolio above what the CAPM (Capital Asset Pricing Model) would predict, given its beta. Positive alpha indicates outperformance, negative alpha indicates underperformance.
Mathematical Definition
$\alpha = E[R_a] - (r_f + \beta \times (E[R_m] - r_f))$
Where:
- $R_a$ = asset returns
- $R_m$ = market returns
- $r_f$ = risk-free rate
- $\beta$ = systematic risk coefficient
Parameters
risk_free: Risk-free rate (default 0.0)
Input Type
Accepts AssetBenchmarkReturn observations via fit!.
Edge Cases
- Returns
0.0when fewer than 2 observations (insufficient for beta)
Fields
value::T: Current Jensen's alphan::Int: Number of observationsasset_mean::Mean: Mean asset return trackermarket_mean::Mean: Mean market return trackerbeta::Beta{T}: Beta coefficient trackerrisk_free::T: Risk-free rate
Example
stat = JensenAlpha(risk_free=0.02)
fit!(stat, AssetBenchmarkReturn(0.05, 0.03)) # Asset +5%, Market +3%
fit!(stat, AssetBenchmarkReturn(0.02, 0.01)) # Asset +2%, Market +1%
value(stat) # Actual return - CAPM expected returnSee also: AssetBenchmarkReturn, Beta, ExpectedReturn
Market Capture Ratios
OnlinePortfolioAnalytics.UpCapture — Typemutable struct UpCapture{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{AssetBenchmarkReturn{T}}UpCapture{T}()Calculate up-market capture ratio from paired asset/benchmark returns.
Up capture measures how much of the benchmark's gains the portfolio captures during positive market periods. A ratio > 1.0 means the portfolio outperforms in up markets.
Mathematical Definition
$\text{UpCapture} = \frac{\left(\prod_{R_b > 0}(1 + R_a)\right)^{1/n_{up}} - 1}{\left(\prod_{R_b > 0}(1 + R_b)\right)^{1/n_{up}} - 1}$
Where:
- $R_a$ = asset return when benchmark is positive
- $R_b$ = benchmark return (> 0)
- $n_{up}$ = count of positive benchmark periods
This is the ratio of annualized geometric mean returns in up markets.
Input Type
Accepts AssetBenchmarkReturn observations via fit!. Only observations where benchmark return > 0 are included.
Edge Cases
- Returns
NaNwhen no positive benchmark periods observed - Returns
NaNwith no observations
Interpretation
- Ratio > 1.0: Portfolio outperforms benchmark in up markets
- Ratio = 1.0: Portfolio matches benchmark in up markets
- Ratio < 1.0: Portfolio underperforms benchmark in up markets
Fields
value: Current up capture ratio valuen: Total number of observationsn_up: Count of up-market observations (benchmark > 0)asset_prod: Product of (1 + R_asset) for up periodsbenchmark_prod: Product of (1 + R_benchmark) for up periods
Example
stat = UpCapture()
fit!(stat, AssetBenchmarkReturn(0.05, 0.03)) # Up market: +5% vs +3%
fit!(stat, AssetBenchmarkReturn(-0.02, -0.04)) # Down market (ignored)
fit!(stat, AssetBenchmarkReturn(0.02, 0.01)) # Up market: +2% vs +1%
value(stat) # Up capture ratio (> 1.0 in this case)See also: DownCapture, UpDownCaptureRatio, AssetBenchmarkReturn
OnlinePortfolioAnalytics.DownCapture — Typemutable struct DownCapture{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{AssetBenchmarkReturn{T}}DownCapture{T}()Calculate down-market capture ratio from paired asset/benchmark returns.
Down capture measures how much of the benchmark's losses the portfolio captures during negative market periods. A ratio < 1.0 means the portfolio falls less than the benchmark in down markets, which is desirable.
Mathematical Definition
$\text{DownCapture} = \frac{\left(\prod_{R_b < 0}(1 + R_a)\right)^{1/n_{down}} - 1}{\left(\prod_{R_b < 0}(1 + R_b)\right)^{1/n_{down}} - 1}$
Where:
- $R_a$ = asset return when benchmark is negative
- $R_b$ = benchmark return (< 0)
- $n_{down}$ = count of negative benchmark periods
This is the ratio of annualized geometric mean returns in down markets.
Input Type
Accepts AssetBenchmarkReturn observations via fit!. Only observations where benchmark return < 0 are included.
Edge Cases
- Returns
NaNwhen no negative benchmark periods observed - Returns
NaNwith no observations
Interpretation
- Ratio < 1.0: Portfolio falls less than benchmark in down markets (desirable)
- Ratio = 1.0: Portfolio matches benchmark in down markets
- Ratio > 1.0: Portfolio falls more than benchmark in down markets (unfavorable)
Fields
value: Current down capture ratio valuen: Total number of observationsn_down: Count of down-market observations (benchmark < 0)asset_prod: Product of (1 + R_asset) for down periodsbenchmark_prod: Product of (1 + R_benchmark) for down periods
Example
stat = DownCapture()
fit!(stat, AssetBenchmarkReturn(-0.02, -0.05)) # Down market: -2% vs -5%
fit!(stat, AssetBenchmarkReturn(0.03, 0.04)) # Up market (ignored)
fit!(stat, AssetBenchmarkReturn(-0.01, -0.03)) # Down market: -1% vs -3%
value(stat) # Down capture ratio (< 1.0 in this case - good!)See also: UpCapture, UpDownCaptureRatio, AssetBenchmarkReturn
OnlinePortfolioAnalytics.UpDownCaptureRatio — Typemutable struct UpDownCaptureRatio{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{AssetBenchmarkReturn{T}}UpDownCaptureRatio{T}()Calculate the up/down capture ratio from paired asset/benchmark returns.
The up/down capture ratio measures the asymmetry of portfolio performance relative to the benchmark across market conditions. A ratio > 1.0 indicates favorable asymmetry (captures more upside, less downside).
Mathematical Definition
$\text{UpDownCaptureRatio} = \frac{\text{UpCapture}}{\text{DownCapture}}$
Where:
UpCapture= geometric mean ratio of returns in up marketsDownCapture= geometric mean ratio of returns in down markets
Input Type
Accepts AssetBenchmarkReturn observations via fit!.
Edge Cases
- Returns
NaNwhen either up capture or down capture isNaN - Returns
Infif down capture is zero (undefined in practice) - Returns
NaNwith no observations
Interpretation
- Ratio > 1.0: Favorable asymmetry (desirable)
- Portfolio captures more upside and/or less downside
- Ratio = 1.0: Symmetric performance
- Ratio < 1.0: Unfavorable asymmetry
- Portfolio captures less upside and/or more downside
Fields
value: Current up/down capture ratio valuen: Total number of observationsup_capture: Internal up capture trackerdown_capture: Internal down capture tracker
Example
stat = UpDownCaptureRatio()
fit!(stat, AssetBenchmarkReturn(0.06, 0.04)) # Up market
fit!(stat, AssetBenchmarkReturn(-0.01, -0.03)) # Down market
fit!(stat, AssetBenchmarkReturn(0.03, 0.02)) # Up market
fit!(stat, AssetBenchmarkReturn(-0.02, -0.04)) # Down market
value(stat) # Up/Down ratio (> 1.0 means favorable asymmetry)See also: UpCapture, DownCapture, AssetBenchmarkReturn
Extended Risk-Adjusted Ratios
OnlinePortfolioAnalytics.UlcerIndex — Typemutable struct UlcerIndex{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{T}UlcerIndex{T}()Calculate the Ulcer Index from a stream of returns.
The Ulcer Index measures the depth and duration of drawdowns by computing the root-mean-square (RMS) of all drawdown values. It penalizes both the magnitude and frequency of drawdowns, capturing the "pain" of holding an investment through volatile periods.
Mathematical Definition
$\text{UlcerIndex} = \sqrt{\frac{1}{n} \sum_{i=1}^{n} D_i^2}$
Where:
- $D_i$ = drawdown at time i (from DrawDowns tracker, always ≤ 0)
Edge Cases
- Returns
0.0when no observations - Returns
0.0when no drawdown (always at peak)
Interpretation
- Lower values indicate smoother returns with shallower drawdowns
- Higher values indicate more volatile returns with deeper/longer drawdowns
- Always non-negative (RMS of non-positive values)
Fields
drawdowns: Internal drawdown trackerrms: RMS of drawdown values
Example
stat = UlcerIndex()
fit!(stat, 0.10) # +10% gain - new peak
fit!(stat, -0.05) # -5% loss - in drawdown
fit!(stat, -0.03) # -3% loss - deeper drawdown
value(stat) # RMS of drawdown valuesSee also: PainIndex, DrawDowns, MaxDrawDown
OnlinePortfolioAnalytics.PainIndex — Typemutable struct PainIndex{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{T}PainIndex{T}()Calculate the Pain Index from a stream of returns.
The Pain Index measures the average depth of drawdowns by computing the mean of absolute drawdown values. It provides a linear measure of "pain" compared to the quadratic penalty of the Ulcer Index.
Mathematical Definition
$\text{PainIndex} = \frac{1}{n} \sum_{i=1}^{n} |D_i|$
Where:
- $D_i$ = drawdown at time i (from DrawDowns tracker, always ≤ 0)
- $|D_i|$ = absolute value of drawdown
Edge Cases
- Returns
0.0when no observations - Returns
0.0when no drawdown (always at peak)
Interpretation
- Lower values indicate smoother returns with shallower drawdowns
- Higher values indicate more volatile returns with deeper drawdowns
- Always non-negative
Fields
value: Current Pain Index valuen: Number of observationsdrawdowns: Internal drawdown trackersum_abs_dd: Sum of absolute drawdowns
Example
stat = PainIndex()
fit!(stat, 0.10) # +10% gain - new peak
fit!(stat, -0.05) # -5% loss - in drawdown
fit!(stat, -0.03) # -3% loss - deeper drawdown
value(stat) # Mean of absolute drawdown valuesSee also: UlcerIndex, PainRatio, DrawDowns
OnlinePortfolioAnalytics.SterlingRatio — Typemutable struct SterlingRatio{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{T}SterlingRatio{T}(; period=252, threshold=0.10)Calculate the Sterling Ratio from a stream of returns.
The Sterling Ratio measures risk-adjusted performance by dividing annualized return by the adjusted maximum drawdown. The threshold (default 10%) accounts for "normal" expected drawdown, making the ratio more stable for portfolios with small drawdowns.
Mathematical Definition
$\text{SterlingRatio} = \frac{\text{AnnualizedReturn}}{|\text{MaxDrawDown}| - \text{threshold}}$
Where:
- AnnualizedReturn = geometric mean return annualized
- MaxDrawDown = worst peak-to-trough decline (negative value)
- threshold = drawdown adjustment (default 0.10)
Parameters
period: Annualization factor (default: 252 for daily returns)threshold: Drawdown adjustment (default: 0.10 = 10%)
Edge Cases
- Returns
Infwhen |MaxDD| ≤ threshold (adjusted denominator is ≤ 0) - Returns
0.0when no observations
Interpretation
- Higher values indicate better risk-adjusted returns
- Accounts for expected "normal" drawdown via threshold
Fields
value: Current Sterling Ratio valuen: Number of observationsannualized_return: Internal annualized return trackermax_drawdown: Internal max drawdown trackerthreshold: Drawdown threshold adjustmentperiod: Annualization period
Example
stat = SterlingRatio(period=252, threshold=0.10)
for r in returns
fit!(stat, r)
end
value(stat) # Annualized return / (|MaxDD| - 10%)See also: Calmar, MaxDrawDown, AnnualizedReturn
OnlinePortfolioAnalytics.BurkeRatio — Typemutable struct BurkeRatio{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{T}BurkeRatio{T}(; period=252, risk_free=0)Calculate the Burke Ratio from a stream of returns.
The Burke Ratio measures risk-adjusted performance by dividing excess return by the root-mean-square of drawdown values. Unlike Sterling (which uses only max drawdown), Burke penalizes both the magnitude and frequency of all drawdowns.
Mathematical Definition
$\text{BurkeRatio} = \frac{\text{AnnualizedReturn} - R_f}{\sqrt{\frac{1}{n}\sum_{i=1}^{n} D_i^2}}$
Where:
- AnnualizedReturn = geometric mean return annualized
- $R_f$ = risk-free rate
- $D_i$ = drawdown at time i
The denominator is equivalent to the Ulcer Index.
Parameters
period: Annualization factor (default: 252 for daily returns)risk_free: Risk-free rate per period (default: 0)
Edge Cases
- Returns
Infwhen sum of squared drawdowns is zero (no drawdowns) - Returns
0.0when no observations
Interpretation
- Higher values indicate better risk-adjusted returns
- Penalizes both depth and frequency of drawdowns
Fields
value: Current Burke Ratio valuen: Number of observationsannualized_return: Internal annualized return trackerdrawdowns: Internal drawdown trackersum_dd_squared: Sum of squared drawdownsrisk_free: Risk-free rateperiod: Annualization period
Example
stat = BurkeRatio(period=252, risk_free=0.0)
for r in returns
fit!(stat, r)
end
value(stat) # Excess return / sqrt(mean(DD^2))See also: SterlingRatio, UlcerIndex, MaxDrawDown
OnlinePortfolioAnalytics.PainRatio — Typemutable struct PainRatio{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{T}PainRatio{T}(; period=252, risk_free=0)Calculate the Pain Ratio from a stream of returns.
The Pain Ratio measures risk-adjusted performance by dividing excess return by the Pain Index (mean absolute drawdown). It provides a linear penalty for drawdowns compared to the quadratic penalty of the Burke Ratio.
Mathematical Definition
$\text{PainRatio} = \frac{\text{AnnualizedReturn} - R_f}{\text{PainIndex}}$
Where:
- AnnualizedReturn = geometric mean return annualized
- $R_f$ = risk-free rate
- PainIndex = mean of absolute drawdown values
Parameters
period: Annualization factor (default: 252 for daily returns)risk_free: Risk-free rate per period (default: 0)
Edge Cases
- Returns
Infwhen Pain Index is zero (no drawdowns) - Returns
0.0when no observations
Interpretation
- Higher values indicate better risk-adjusted returns
- Uses linear (not quadratic) penalty for drawdowns
Fields
value: Current Pain Ratio valuen: Number of observationsannualized_return: Internal annualized return trackerpain_index: Internal Pain Index trackerrisk_free: Risk-free rateperiod: Annualization period
Example
stat = PainRatio(period=252, risk_free=0.0)
for r in returns
fit!(stat, r)
end
value(stat) # Excess return / PainIndexSee also: PainIndex, BurkeRatio, SterlingRatio
Volatility & Stability Metrics
OnlinePortfolioAnalytics.AnnualVolatility — Typemutable struct AnnualVolatility{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{T}AnnualVolatility{T}(; period=252)Calculate annualized volatility from a stream of periodic returns.
Annualized volatility is the standard deviation of returns scaled by the square root of the annualization period. It represents the expected annual dispersion of returns.
Mathematical Definition
$\text{Annual Volatility} = \sigma \times \sqrt{\text{period}}$
Where:
- $\sigma$ = sample standard deviation of periodic returns
- period = annualization factor (252 for daily, 52 for weekly, 12 for monthly)
Parameters
period: Annualization factor (default 252 for daily returns)- Daily: 252 (trading days per year)
- Weekly: 52
- Monthly: 12
Fields
value: Current annualized volatility valuen: Number of observationsvariance: Internal variance trackerperiod: Annualization period
Example
stat = AnnualVolatility()
fit!(stat, 0.01) # 1% daily return
fit!(stat, 0.02) # 2% daily return
fit!(stat, -0.01) # -1% daily return
value(stat) # Annualized volatilityOnlinePortfolioAnalytics.Stability — Typemutable struct Stability{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{T}Stability{T}()Calculate stability as the R-squared of a linear regression of cumulative log returns.
Stability measures how consistently returns grow over time. A stability of 1.0 indicates perfectly linear growth (constant returns), while lower values indicate more erratic growth.
Mathematical Definition
Stability is the coefficient of determination (R²) from regressing cumulative log returns on the observation index:
$R^2 = 1 - \frac{SS_{res}}{SS_{tot}}$
Where we track cumulative log returns: $y_i = \sum_{j=1}^{i} \log(1 + r_j)$
And regress against time index $x_i = i$.
Edge Cases
- Returns
0.0when fewer than 2 observations (cannot compute regression) - Returns values in [0, 1] for valid regressions
Fields
value: Current R-squared valuen: Number of observationssum_x: Sum of x (time indices)sum_x2: Sum of x squaredsum_y: Sum of y (cumulative log returns)sum_y2: Sum of y squaredsum_xy: Sum of x*ycum_log_return: Current cumulative log return
Example
stat = Stability()
for _ in 1:20
fit!(stat, 0.01) # Consistent 1% return
end
value(stat) # Should be close to 1.0 (highly stable)See also: AnnualizedReturn
OnlinePortfolioAnalytics.TailRatio — Typemutable struct TailRatio{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{T}TailRatio{T}(; b=500)Calculate the tail ratio as the ratio of the 95th percentile to the absolute value of the 5th percentile of returns.
Tail ratio measures the symmetry of return distribution tails:
- Ratio > 1.0: Fatter right tail (larger gains than losses at extremes)
- Ratio ≈ 1.0: Symmetric tails
- Ratio < 1.0: Fatter left tail (larger losses than gains at extremes)
Mathematical Definition
$\text{Tail Ratio} = \frac{\text{Percentile}_{95}(R)}{|\text{Percentile}_{5}(R)|}$
Where:
- $\text{Percentile}_{95}(R)$ = 95th percentile of returns
- $\text{Percentile}_{5}(R)$ = 5th percentile of returns
Parameters
b: Number of histogram bins for quantile estimation (default 500)
Edge Cases
- Returns
Infif 5th percentile is zero - May return
NaNwith insufficient data
Fields
value: Current tail ratio valuen: Number of observationsquantile: Internal quantile tracker for 5th and 95th percentiles
Example
stat = TailRatio()
for r in returns
fit!(stat, r)
end
ratio = value(stat) # > 1.0 means fatter right tailSee also: VaR, ExpectedShortfall
Modigliani Measures
OnlinePortfolioAnalytics.M2 — Typemutable struct M2{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{AssetBenchmarkReturn{T}}M2{T}(; risk_free=0.0)Calculate the M2 (Modigliani-Modigliani) risk-adjusted performance measure from a stream of paired portfolio and benchmark returns.
M2 adjusts the portfolio return to have the same volatility as the benchmark, making performance comparison between portfolios with different risk levels more meaningful.
Mathematical Definition
$M^2 = R_f + (\bar{R}_{port} - R_f) \times \frac{\sigma_{bench}}{\sigma_{port}}$
Where:
- $R_f$ = risk-free rate
- $\bar{R}_{port}$ = mean portfolio return
- $\sigma_{port}$ = portfolio standard deviation
- $\sigma_{bench}$ = benchmark standard deviation
Interpretation
- M2 represents what the portfolio return would have been if it had the same risk as the benchmark
- Higher M2 indicates better risk-adjusted performance
- M2 is directly comparable to benchmark return (same scale and units)
Parameters
risk_free: Risk-free rate (default 0.0)
Edge Cases
- Returns
0.0when portfolio volatility is zero (undefined) - Returns
0.0when fewer than 2 observations (insufficient data)
Fields
value: Current M2 valuen: Number of observationsport_mean: Portfolio mean trackerport_variance: Portfolio variance trackerbench_variance: Benchmark variance trackerrisk_free: Risk-free rate
Example
stat = M2(risk_free=0.02)
fit!(stat, AssetBenchmarkReturn(0.10, 0.08)) # Portfolio +10%, Benchmark +8%
fit!(stat, AssetBenchmarkReturn(0.05, 0.04)) # Portfolio +5%, Benchmark +4%
value(stat) # Risk-adjusted portfolio returnSee also: MSquaredExcess, Sharpe, InformationRatio
OnlinePortfolioAnalytics.MSquaredExcess — Typemutable struct MSquaredExcess{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{AssetBenchmarkReturn{T}}MSquaredExcess{T}(; risk_free=0.0)Calculate the M-Squared Excess (M2 minus benchmark mean return) from a stream of paired portfolio and benchmark returns.
M-Squared Excess represents the risk-adjusted excess return of the portfolio relative to the benchmark. It shows how much the portfolio would have outperformed (or underperformed) the benchmark if both had the same volatility.
Mathematical Definition
$M^2_{excess} = M^2 - \bar{R}_{bench}$
Where:
- $M^2 = R_f + (\bar{R}_{port} - R_f) \times \frac{\sigma_{bench}}{\sigma_{port}}$
- $\bar{R}_{bench}$ = mean benchmark return
Interpretation
- Positive value: Portfolio outperforms on a risk-adjusted basis
- Negative value: Portfolio underperforms on a risk-adjusted basis
- Zero: Portfolio performs exactly as expected for its risk level
Parameters
risk_free: Risk-free rate (default 0.0)
Edge Cases
- Returns
0.0when fewer than 2 observations (insufficient data)
Fields
value: Current M-Squared Excess valuen: Number of observationsm2: Internal M2 trackerbench_mean: Benchmark mean trackerrisk_free: Risk-free rate
Example
stat = MSquaredExcess(risk_free=0.02)
fit!(stat, AssetBenchmarkReturn(0.10, 0.08))
fit!(stat, AssetBenchmarkReturn(0.05, 0.04))
value(stat) # Risk-adjusted excess return vs benchmarkSee also: M2, InformationRatio, ActivePremium
OnlinePortfolioAnalytics.ActivePremium — Typemutable struct ActivePremium{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{AssetBenchmarkReturn{T}}ActivePremium{T}(; period=252)Calculate the Active Premium (annualized portfolio return minus annualized benchmark return) from a stream of paired portfolio and benchmark returns.
Active Premium measures the raw excess return of the portfolio over the benchmark on an annualized basis, without adjusting for risk.
Mathematical Definition
$\text{Active Premium} = \text{AnnualizedReturn}_{port} - \text{AnnualizedReturn}_{bench}$
Where AnnualizedReturn is the CAGR (Compound Annual Growth Rate): $\text{AnnualizedReturn} = (\prod_{i=1}^{n}(1 + r_i))^{period/n} - 1$
Interpretation
- Positive value: Portfolio outperforms benchmark
- Negative value: Portfolio underperforms benchmark
- Zero: Portfolio matches benchmark exactly
Parameters
period: Annualization factor (default 252 for daily returns)- Daily: 252 (trading days per year)
- Weekly: 52
- Monthly: 12
Fields
value: Current Active Premium valuen: Number of observationsport_ann_return: Portfolio annualized return trackerbench_ann_return: Benchmark annualized return trackerperiod: Annualization period
Example
stat = ActivePremium(period=252)
fit!(stat, AssetBenchmarkReturn(0.01, 0.008)) # Daily returns
fit!(stat, AssetBenchmarkReturn(0.02, 0.015))
value(stat) # Annualized excess returnSee also: AnnualizedReturn, InformationRatio, MSquaredExcess
Upside Potential Ratio
OnlinePortfolioAnalytics.UpsidePotentialRatio — Typemutable struct UpsidePotentialRatio{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{T}UpsidePotentialRatio{T}(; mar=0.0)Calculate the Upside Potential Ratio from a stream of returns.
The Upside Potential Ratio measures the ratio of expected positive deviation above a Minimum Acceptable Return (MAR) to the downside deviation below that threshold. It captures the asymmetry between upside gains and downside losses.
Mathematical Definition
$\text{UPR} = \frac{E[\max(R - MAR, 0)]}{\text{DownsideDeviation}}$
Where:
- $R$ = return
- $MAR$ = Minimum Acceptable Return (threshold)
- Upside Potential = $\frac{1}{n} \sum_{i=1}^{n} \max(R_i - MAR, 0)$
- Downside Deviation = $\sqrt{\frac{1}{n} \sum_{i=1}^{n} \min(R_i - MAR, 0)^2}$
Interpretation
- UPR > 1: Upside potential exceeds downside risk (favorable)
- UPR = 1: Upside potential equals downside risk
- UPR < 1: Downside risk exceeds upside potential (unfavorable)
- UPR = Inf: No downside (all returns above MAR)
- UPR = 0: No upside (all returns below MAR)
Parameters
mar: Minimum Acceptable Return threshold (default 0.0)
Fields
value: Current Upside Potential Ratio valuen: Number of observationssum_upside: Sum of positive deviations from MARdownside_deviation: Internal downside deviation trackermar: Minimum Acceptable Return threshold
Example
stat = UpsidePotentialRatio(mar=0.0)
fit!(stat, 0.10) # +10% return
fit!(stat, -0.03) # -3% return
fit!(stat, 0.05) # +5% return
value(stat) # Upside potential / downside deviationSee also: DownsideDeviation, UpsideDeviation, Sortino
Rolling Window Framework
OnlinePortfolioAnalytics.Rolling — Typemutable struct Rolling{T, S<:OnlineStatsBase.OnlineStat} <: OnlineStatsBase.OnlineStat{T}Rolling(stat; window)Wrap any OnlineStat to compute rolling window statistics.
The Rolling wrapper maintains a circular buffer of observations and recomputes the wrapped statistic over only the most recent window observations. This enables streaming computation of rolling metrics like rolling Sharpe ratio or rolling drawdown.
Parameters
stat: Any OnlineStat to wrap (e.g.,Sharpe{Float64}(),MaxDrawDown{Float64}())window: Size of the rolling window (must be > 0)
Implementation Details
When a new observation arrives:
- Add it to the circular buffer
- If buffer exceeds window size, the oldest observation is automatically removed
- Reset the wrapped stat and refit with all buffer contents
Edge Cases
- Before window is full: Computes on available observations (partial window)
- After window is full: Computes on exactly
windowmost recent observations
Fields
stat: The wrapped OnlineStatbuffer: Circular buffer storing observations (OnlineStatsBase.CircBuff)window: Rolling window sizen: Total observations seen
Example
# Rolling 60-period Sharpe ratio
rolling_sharpe = Rolling(Sharpe{Float64}(), window=60)
for ret in daily_returns
fit!(rolling_sharpe, ret)
println("60-day rolling Sharpe: ", value(rolling_sharpe))
end
# Rolling 30-period max drawdown
rolling_dd = Rolling(MaxDrawDown{Float64}(), window=30)
for ret in returns
fit!(rolling_dd, ret)
endSee also: Sharpe, MaxDrawDown, Calmar
Input types
Asset/Benchmark return pair
OnlinePortfolioAnalytics.AssetBenchmarkReturn — Typestruct AssetBenchmarkReturn{T<:Real}AssetBenchmarkReturn{T<:Real}(asset, benchmark)Wrapper type for paired (asset, benchmark) return observations.
Used as input for relative performance metrics (e.g., TrackingError, InformationRatio) and CAPM-based metrics (e.g., Beta, ExpectedReturn, Treynor, JensenAlpha).
The benchmark can be any reference portfolio or market index depending on the analysis context.
Fields
asset::T: Asset/portfolio return for this observationbenchmark::T: Benchmark/market return for this observation
Example
obs = AssetBenchmarkReturn(0.05, 0.03) # 5% asset return, 3% benchmark return
fit!(beta_stat, obs)
fit!(tracking_error_stat, obs)See also: Beta, ExpectedReturn, Treynor, JensenAlpha, TrackingError, InformationRatio
Other
OnlinePortfolioAnalytics.Prod — Typemutable struct Prod{T} <: OnlineStatsBase.OnlineStat{Number}Prod(T::Type = Float64)Streaming product accumulator that computes the running product of observations.
Mathematical Definition
$P = \prod_{i=1}^{n} x_i$
Where:
- $x_i$ = observation for period i
- $n$ = number of observations
For weighted observations with weight $w$: $P = P \cdot x^w$
This represents "fitting x with multiplicity w" - equivalent to fitting x exactly w times.
Fields
prod::T: Current accumulated product valuen::Int: Number of observations (or total accumulated weight)
Initial State
prod = one(T)(multiplicative identity)n = 0
Edge Cases
- Empty stat:
value(stat) == one(T),nobs(stat) == 0 - Zero input: Product becomes and stays zero
- For
T<:Integer: inputs are rounded before multiplication
Example
stat = Prod(Float64)
fit!(stat, 2.0)
fit!(stat, 3.0)
fit!(stat, 4.0)
value(stat) # => 24.0
nobs(stat) # => 3
# Weighted fit (x^w semantics)
stat2 = Prod(Float64)
fit!(stat2, 2.0, 3) # 2^3 = 8
value(stat2) # => 8.0See also: LogProd, CumulativeReturn, GeometricMeanReturn
OnlinePortfolioAnalytics.LogProd — Typemutable struct LogProd{T} <: OnlineStatsBase.OnlineStat{Number}LogProd(T::Type = Float64)Numerically stable streaming product accumulator that operates in log-space.
For products of many values (>100), standard multiplication can overflow (Inf) or underflow (0.0). LogProd avoids this by accumulating log(x) values and returning exp(sum_of_logs).
Mathematical Definition
$P = \prod_{i=1}^{n} x_i = \exp\left(\sum_{i=1}^{n} \log(x_i)\right)$
For weighted observations: $P = P \cdot x^w = \exp(\text{log\_sum} + w \cdot \log(x))$
Fields
log_sum::T: Sum of logarithms of observed valuesn::Int: Number of observations (or total accumulated weight)
Initial State
log_sum = zero(T)n = 0value(stat) == 1.0(sinceexp(0) = 1)
Edge Cases
- Empty stat:
value(stat) == 1.0,nobs(stat) == 0 - Zero input (
x = 0):log(0) = -Inf, sovalue(stat) == 0.0 - Negative input (
x < 0):log(x)returnsNaN(undefined in real domain) - For very large products: stays finite when
Prodwould overflow
Example
# Standard Prod overflows
prod_stat = Prod(Float64)
for _ in 1:10000
fit!(prod_stat, 1.001)
end
value(prod_stat) # => Inf (overflow!)
# LogProd stays stable
log_stat = LogProd(Float64)
for _ in 1:10000
fit!(log_stat, 1.001)
end
value(log_stat) # => 21916.68... (finite and correct)See also: Prod
OnlinePortfolioAnalytics.RMS — Typemutable struct RMS{T} <: OnlinePortfolioAnalytics.PortfolioAnalyticsSingleOutput{T}RMS{T}()Calculate the Root Mean Square (RMS) from a stream of numeric values.
RMS is a fundamental statistical measure that computes the square root of the mean of squared values. It is commonly used in signal processing, physics, and finance to measure the magnitude of varying quantities.
Mathematical Definition
$\text{RMS} = \sqrt{\frac{1}{n} \sum_{i=1}^{n} x_i^2}$
Where:
- $x_i$ = observation at time i
- $n$ = total number of observations
Edge Cases
- Returns
0.0when no observations (n=0) - Handles negative values correctly (squared, so sign doesn't matter)
- RMS of all zeros returns
0.0
Fields
value: Current RMS valuen: Number of observationssum_sq: Sum of squared values
Example
stat = RMS()
fit!(stat, 3.0)
fit!(stat, 4.0)
value(stat) # sqrt((9+16)/2) ≈ 3.536Usage in Portfolio Analytics
RMS is used internally by UlcerIndex to compute the root-mean-square of drawdown values, measuring the "pain" of holding an investment through volatile periods.
See also: UlcerIndex, DownsideDeviation, StdDev