Source code for finance_calcs.portfolio
"""Portfolio-level exposure and concentration metrics.
All inputs are expressions over a column of position weights or
notional dollar exposures, evaluated within the appropriate group
(typically a ``group_by("date")``). Weights need not sum to one — the
expressions operate on whatever is supplied.
"""
from __future__ import annotations
import polars as pl
__all__ = [
"gross_leverage",
"gross_exposure",
"net_exposure",
"long_exposure",
"short_exposure",
"concentration",
"top_n_concentration",
"active_share",
]
[docs]
def gross_leverage(weights: pl.Expr) -> pl.Expr:
"""Sum of absolute weights — total notional / equity.
Args:
weights: Position weight expression.
Returns:
Scalar gross-leverage expression.
"""
return weights.abs().sum()
[docs]
def gross_exposure(weights: pl.Expr) -> pl.Expr:
"""Alias for ``gross_leverage`` — long + short notional.
Args:
weights: Position weight expression.
Returns:
Scalar gross-exposure expression.
"""
return weights.abs().sum()
[docs]
def net_exposure(weights: pl.Expr) -> pl.Expr:
"""Long minus short notional — signed sum of weights.
Args:
weights: Position weight expression.
Returns:
Scalar net-exposure expression.
"""
return weights.sum()
[docs]
def long_exposure(weights: pl.Expr) -> pl.Expr:
"""Sum of positive weights.
Args:
weights: Position weight expression.
Returns:
Scalar long-exposure expression.
"""
return pl.when(weights > 0).then(weights).otherwise(0.0).sum()
[docs]
def short_exposure(weights: pl.Expr) -> pl.Expr:
"""Sum of negative weights (returned as a negative number).
Args:
weights: Position weight expression.
Returns:
Scalar short-exposure expression.
"""
return pl.when(weights < 0).then(weights).otherwise(0.0).sum()
[docs]
def concentration(weights: pl.Expr) -> pl.Expr:
"""Herfindahl-Hirschman index of normalised absolute weights.
Computed on absolute weights normalised to sum to 1 — yields
``1/N`` for an equal-weight portfolio of ``N`` names and ``1.0``
for a single-name portfolio.
Args:
weights: Position weight expression.
Returns:
Scalar HHI expression in ``(0, 1]``.
"""
abs_w = weights.abs()
norm = abs_w / abs_w.sum()
return norm.pow(2).sum()
[docs]
def top_n_concentration(weights: pl.Expr, n: int = 10) -> pl.Expr:
"""Fraction of gross exposure held by the top ``n`` absolute weights.
Args:
weights: Position weight expression.
n: Number of top positions.
Returns:
Scalar expression in ``[0, 1]``.
"""
abs_w = weights.abs()
return abs_w.top_k(n).sum() / abs_w.sum()
[docs]
def active_share(weights: pl.Expr, benchmark_weights: pl.Expr) -> pl.Expr:
"""Active share — ``0.5 * sum(|w - b|)``.
Args:
weights: Portfolio weight expression.
benchmark_weights: Benchmark weight expression aligned to ``weights``.
Returns:
Scalar active-share expression in ``[0, 1]``.
"""
return 0.5 * (weights - benchmark_weights).abs().sum()