Finance

Contents

Finance#

Portfolio projection lives on the mixture itself (project()); there is no separate finance-layer wrapper.

Risk Measures#

Coherent risk measures for univariate normal-mixture portfolio returns.

The current implementation provides Conditional Value at Risk (CVaR), with value, first derivatives, and second derivatives in both the projected parameter space \((\tilde\mu, \tilde\gamma, \tilde\sigma)\) and the portfolio-weight space \(w \in \mathbb{R}^d\). Formulas follow docs/theory/cvar_derivatives.md.

CVaR integrates the conditional normal analytically over a positive scenario measure of \(Y\). The default is deterministic quadrature; an array supplies equal-weight Monte Carlo draws. Deterministic VaR uses the Univariate* PINV ppf().

class normix.finance.risk.RiskMeasure[source]#

Bases: Module

Abstract base for portfolio risk measures.

abstractmethod value(univariate, scenarios=None)[source]#

Risk of the univariate normal mixture represented by univariate.

Parameters:
Return type:

Array

abstractmethod value_reduced(mu, gamma, sigma, scenarios)[source]#

Risk from raw scalar parameters \((\tilde\mu, \tilde\gamma, \tilde\sigma)\).

The univariate normal mixture is \(\tilde\mu + \tilde\gamma Y + \tilde\sigma\sqrt{Y}Z\). Unlike value(), this signature takes plain scalars (no distribution object) and must be Bessel-/PINV-free so it can be jax.vmap()-ed across an efficient-surface grid that shares the scenario measure scenarios.

Parameters:
Return type:

Array

value_grad_hess_w(model, w, scenarios=None)[source]#

Fused \((r(w), \nabla_w r, H_r(w))\) under one shared scenario measure.

Consumed by transaction_costs and diversification. Concrete measures override with an analytically fused implementation (CVaR shares one conditional VaR solve); the base raises — a value-only measure cannot participate in the derivative-consuming layers.

Parameters:
Return type:

tuple[Array, Array, Array]

class normix.finance.risk.CVaR(alpha)[source]#

Bases: RiskMeasure

Conditional Value at Risk at tail probability \(\alpha \in (0, 1)\).

For a univariate normal mixture \(X = \tilde\mu + \tilde\gamma Y + \tilde\sigma \sqrt{Y} Z\), the value is computed in closed form conditional on \(Y\):

\[\operatorname{CVaR}_\alpha(X) = \frac{1}{\alpha} E_Y\!\left[ \tilde\sigma \sqrt{Y} \, \varphi(z_Y) - (\tilde\mu + \tilde\gamma Y) \Phi(z_Y) \right],\]

where \(z_Y = (x_\alpha - \tilde\mu - \tilde\gamma Y) / (\tilde\sigma \sqrt{Y})\) and \(x_\alpha = -\operatorname{VaR}_\alpha\) is found by transformed bisection on the conditional CDF under the same measure as the integral. scenarios=None uses subordinator quadrature. See Quadrature scenarios for mixture CVaR for accuracy and moment domains.

Notes

At zero skew with divergent CVaR, derivatives represent limits under tail truncation, not classical derivatives of an infinite-valued function. The scalar scale derivative is \(+\infty\); its second derivative is zero because each truncated risk is linear in scale. Portfolio chain-rule terms preserve exact zero coefficients and otherwise retain the sign of the product with an infinite derivative.

Parameters:

alpha (float)

alpha: float#
var(univariate)[source]#

\(\operatorname{VaR}_\alpha\) via deterministic PINV ppf().

Parameters:

univariate (_UnivariateNormalMixtureMixin)

Return type:

Array

value(univariate, scenarios=None)[source]#

Risk of the univariate normal mixture represented by univariate.

Parameters:
Return type:

Array

value_reduced(mu, gamma, sigma, scenarios)[source]#

CVaR from raw scalar parameters, vectorizable over a surface grid.

Inverts the conditional CDF for \(x_\alpha\) by bisection on the component-quantile bracket \([\min_i q_i, \max_i q_i]\), \(q_i = \tilde\mu + \tilde\gamma Y_i + \tilde\sigma\sqrt{Y_i}\, \Phi^{-1}(\alpha)\). The bracket contains the root for every positive scenario measure. No PINV table and no Bessel evaluation; the CVaR integral is _cvar_from_quantile.

Raises:

equinox.EquinoxRuntimeError – If the result is NaN, also under jit and vmap. Divergent moments return infinity.

Parameters:
Return type:

Array

gradient_scalar(univariate, scenarios=None)[source]#

Return \((\partial r / \partial \tilde\mu, \partial r / \partial \tilde\gamma, \partial r / \partial \tilde\sigma)\).

Parameters:
Return type:

Array

hessian_scalar(univariate, scenarios=None)[source]#

Return the \(3 \times 3\) Hessian in \((\tilde\mu, \tilde\gamma, \tilde\sigma)\).

\(\partial^2/\partial \tilde\mu \, \cdot = 0\) exactly; the other non-trivial blocks follow docs/theory/cvar_derivatives.md (4).

Parameters:
Return type:

Array

value_w(model, w, scenarios=None)[source]#
Parameters:
Return type:

Array

gradient_w(model, w, scenarios=None)[source]#

Gradient \(\nabla_w r_{\operatorname{CVaR}_\alpha}(w)\).

Parameters:
Return type:

Array

hessian_w(model, w, scenarios=None)[source]#

Hessian \(H_{r_{\operatorname{CVaR}_\alpha}}(w)\).

Parameters:
Return type:

Array

value_grad_hess_w(model, w, scenarios=None)[source]#

Fused \((r, \nabla_w r, H_r)\) with one conditional VaR solve.

Equivalent to calling value_w(), gradient_w(), and hessian_w() separately, but projects once and bisects the conditional CDF once.

Parameters:
Return type:

tuple[Array, Array, Array]

step_resolution(univariate, scenarios=None)[source]#

Transition width divided by local node spacing in \(\log Y\).

Reports \(R=1/(\rho_{loc}\,h)\) at the conditional-CDF step. A small value suggests increasing the node count; this is a heuristic, not an error bound. Returns infinity when there is no positive step, and zero when the step lies outside the node range. Duplicate and zero-mass nodes do not improve resolution.

Parameters:
Return type:

Array

Mean-Risk Optimization#

Mean-risk portfolio optimization for normal-mixture models.

For a multivariate normal mixture \(X \stackrel{d}{=} \mu + \gamma Y + \sqrt{Y} Z\) with \(Z \sim \mathcal{N}(0, \Sigma)\), the mean-risk problem

\[\min_w \rho(w^\top X) \quad \text{s.t.} \quad w^\top e = 1, \quad E[w^\top X] \ge m\]

reduces — for any coherent risk measure \(\rho\) — to a two-dimensional problem in the reduced coordinates \(\tilde\mu = w^\top\mu\) and \(\tilde\gamma = w^\top\gamma\). The minimum-dispersion weights that realise a given \((\tilde\mu, \tilde\gamma)\) are

\[w^*(\tilde\mu, \tilde\gamma) = \Sigma^{-1}[\mu\;\gamma\;e]\,A^{-1} [\tilde\mu\;\tilde\gamma\;1]^\top, \qquad A = [\mu\;\gamma\;e]^\top \Sigma^{-1} [\mu\;\gamma\;e],\]

and the realised dispersion is \(g(\tilde\mu, \tilde\gamma) = [\tilde\mu\;\tilde\gamma\;1] A^{-1} [\tilde\mu\;\tilde\gamma\;1]^\top\). The map \((\tilde\mu, \tilde\gamma) \mapsto \rho\) is the efficient surface; its lower envelope under the return constraint is the efficient frontier.

The inverse formulae hold when \(A\) is nonsingular, that is when \(r = \operatorname{rank}[\mu\;\gamma\;e] = 3\). If \(r < 3\), the attainable pairs form an affine set \(\mathcal{S}\) of dimension \(r-1\). On \(\mathcal{S}\) the same formulae hold with the pseudoinverse \(A^{+}\) in place of \(A^{-1}\). A target outside \(\mathcal{S}\) is not a portfolio.

See Mean-Risk Optimization for Normal Mixture Distributions for the derivation.

class normix.finance.optimization.EfficientSurface(mu_tilde, gamma_tilde, risk, expected_return)[source]#

Bases: Module

Efficient surface \((\tilde\mu, \tilde\gamma) \mapsto \rho\) on a grid.

risk[i, j] is the risk of the minimum-dispersion portfolio with reduced coordinates (mu_tilde[i], gamma_tilde[j]); expected_return[i, j] = mu_tilde[i] + gamma_tilde[j] * E[Y].

Parameters:
mu_tilde: Array#
gamma_tilde: Array#
risk: Array#
expected_return: Array#
class normix.finance.optimization.EfficientFrontier(expected_return, risk, mu_tilde, gamma_tilde, weights)[source]#

Bases: Module

Mean-risk efficient frontier: minimum risk per target expected return.

Each entry is the solution of the reduced problem on the constraint line \(\tilde\mu + \tilde\gamma E[Y] = m\), including the realised portfolio weights of shape (K, d).

Parameters:
expected_return: Array#
risk: Array#
mu_tilde: Array#
gamma_tilde: Array#
weights: Array#
class normix.finance.optimization.MeanRiskProblem(model, risk, scenarios=None)[source]#

Bases: Module

Mean-risk optimization in reduced \((\tilde\mu, \tilde\gamma)\) coordinates.

Bundles a fitted NormalMixture and a RiskMeasure. All heavy evaluations share a fixed probability measure of the subordinator. scenarios=None builds quadrature once at construction. Supply an array for equal-weight Monte Carlo, or a DiscreteMeasure for weighted scenarios. Per-call overrides share one measure across the whole grid or frontier. Expected returns continue to use the model law’s mean.

The whitened factorisation of \(M = [\mu\;\gamma\;e]\) is computed once at construction. The Gram matrix \(A = M^\top\Sigma^{-1}M\) is stored for the minimum-dispersion anchor; it is positive semidefinite and need not be invertible. Weights use the truncated pseudoinverse of the whitened factor and are returned only for attainable targets.

Parameters:
model: NormalMixture#
risk: RiskMeasure#
A: Array#
S: Array#
Vh: Array#
LT_U: Array#
rank: int#
scenarios: DiscreteMeasure#
E_Y()[source]#

\(E[Y]\) — subordinator mean.

Return type:

Array

weights(mu_tilde, gamma_tilde)[source]#

Minimum-dispersion weights realising \((\tilde\mu, \tilde\gamma)\).

Raises:

ValueError – If \((\tilde\mu, \tilde\gamma)\) is outside the reachable set. The message names each coordinate of \(M^\top w - c\) whose absolute residual exceeds MEAN_RISK_REACH_ATOL.

Parameters:
Return type:

Array

dispersion(mu_tilde, gamma_tilde)[source]#

Realised dispersion \(g(\tilde\mu, \tilde\gamma) = w^{*\top}\Sigma w^*\).

Raises:

ValueError – If \((\tilde\mu, \tilde\gamma)\) is outside the reachable set.

Parameters:
Return type:

Array

expected_return(mu_tilde, gamma_tilde)[source]#

\(m = \tilde\mu + \tilde\gamma\,E[Y]\).

Parameters:
Return type:

Array

min_dispersion_point()[source]#

Reduced coordinates \((\tilde\mu, \tilde\gamma)\) of the global minimum-dispersion portfolio \(w = \Sigma^{-1}e / (e^\top\Sigma^{-1}e)\).

The objective is \(w^\top\Sigma w\) subject to \(w^\top e = 1\), not \(w^\top\mathrm{Cov}(X)w\). A convenient anchor for choosing efficient-surface grid ranges.

Return type:

tuple[Array, Array]

projection_at(mu_tilde, gamma_tilde)[source]#

Univariate portfolio return at \((\tilde\mu, \tilde\gamma)\).

Projects the minimum-dispersion weights(); the result is a Univariate* instance with location \(\tilde\mu\), skewness \(\tilde\gamma\), variance \(g(\tilde\mu, \tilde\gamma)\).

Parameters:
Return type:

NormalMixture

risk_at(mu_tilde, gamma_tilde, scenarios=None)[source]#

Efficient-surface risk at a single \((\tilde\mu, \tilde\gamma)\).

Parameters:
Return type:

Array

efficient_surface(mu_tilde, gamma_tilde, scenarios=None)[source]#

Evaluate the efficient surface over the grid mu_tilde × gamma_tilde.

mu_tilde and gamma_tilde are 1-D arrays; the returned risk has shape (len(mu_tilde), len(gamma_tilde)). Memory scales as len(mu_tilde) * len(gamma_tilde) * len(scenarios.Y). Every grid node must lie in the reachable set.

Raises:

ValueError – If any node lies outside the reachable set.

Parameters:
Return type:

EfficientSurface

efficient_frontier(returns, scenarios=None, *, gamma_bounds, n_iter=48)[source]#

Minimum risk for each target expected return in returns.

For every target \(m\), minimises the risk along the part of \(\tilde\mu + \tilde\gamma E[Y] = m\) that lies in the reachable set and in gamma_bounds. When the reachable set is a plane this is golden-section search in \(\tilde\gamma\). When it is a line, the return constraint selects one point of the line, or the whole line if the return is constant there. A constant return that misses the line, and any target off the reachable set, is infeasible. When the reachable set is a point, that portfolio is returned for its own expected return and every other return is infeasible.

Raises:

ValueError – If a target return is not attainable on the reachable set, or the feasible \(\tilde\gamma\) lies outside gamma_bounds.

Parameters:
Return type:

EfficientFrontier

Transaction Costs#

Local-quadratic transaction-cost portfolio rebalancing.

The mean-risk problem with an \(\ell_1\) turnover penalty

\[\max_w \; w^\top m - c_1\, r(w) - c_2 \|w - w_0\|_1 \quad\text{s.t.}\quad w^\top e = 1,\; A w \le b\]

cannot use the two-dimensional efficient-surface reduction, because the turnover term breaks translation invariance in the reduced coordinates. When costs keep the solution near the current portfolio \(w_0\), a second-order Taylor expansion of the convex risk \(r\) yields a convex quadratic program in buy/sell variables \(v = (v^+; v^-)\) with \(w = w_0 + v^+ - v^-\) (see Portfolio Optimization with Transaction Costs).

This module builds the QP matrices from any RiskMeasure that supplies gradient_w() / hessian_w(). Solving is optional and uses scipy.optimize (already a core dependency); heavier QP backends can consume the same matrices later.

class normix.finance.transaction_costs.QuadraticApproximation(w0, value, gradient, hessian)[source]#

Bases: Module

Local Taylor model of \(r\) at the current portfolio \(w_0\).

\[r(w) \approx r(w_0) + (w - w_0)^\top \nabla r(w_0) + \tfrac12 (w - w_0)^\top H_r(w_0)\,(w - w_0).\]
Parameters:
w0: Array#
value: Array#
gradient: Array#
hessian: Array#
class normix.finance.transaction_costs.TransactionCostQP(m_tilde, H_tilde, e_tilde, A_tilde, b_tilde, w0, c1, c2, approx, m)[source]#

Bases: Module

Buy/sell quadratic program for the local transaction-cost problem.

Maximises \(v^\top \tilde m - (c_1/2)\, v^\top \tilde H\, v\) over \(v \ge 0\) subject to \(v^\top \tilde e = 0\) and optional \(\tilde A v \le \tilde b\). Reconstruct \(w^* = w_0 + (I\;-I)\,v^*\).

Parameters:
m_tilde#

Linear term \(\tilde m \in \mathbb{R}^{2d}\).

Type:

jax.Array

H_tilde#

Block Hessian \(\tilde H\) (optionally Tikhonov-regularised).

Type:

jax.Array

e_tilde#

Budget dual vector \((e; -e)\).

Type:

jax.Array

A_tilde, b_tilde

Optional inequality block; None when only the budget constraint is active.

w0, c1, c2

Anchor portfolio and objective coefficients.

approx#

Underlying risk Taylor model (for objective bookkeeping).

Type:

normix.finance.transaction_costs.QuadraticApproximation

m#

Expected-return vector used to build \(\tilde m\).

Type:

jax.Array

A_tilde: Array | None#
b_tilde: Array | None#
w0: Array#
c1: Array#
c2: Array#
property d: int#
weights_from_v(v)[source]#

Map buy/sell variables to portfolio weights \(w_0 + v^+ - v^-\).

Parameters:

v (Array)

Return type:

Array

approx_objective(w)[source]#

Local quadratic objective (constants retained) at weights w.

Parameters:

w (Array)

Return type:

Array

hold_objective()[source]#

Objective of holding \(w_0\) (zero turnover).

Return type:

Array

class normix.finance.transaction_costs.TransactionCostResult(weights, v, turnover, approx_objective, hold_objective, improved, qp)[source]#

Bases: Module

Solution of the local transaction-cost QP.

improved is True when the approximate objective at weights exceeds the hold objective; otherwise the theory recommends keeping \(w_0\) (see the note in Portfolio Optimization with Transaction Costs).

Parameters:
weights: Array#
v: Array#
turnover: Array#
approx_objective: Array#
hold_objective: Array#
improved: Array#
qp: TransactionCostQP#
normix.finance.transaction_costs.build_quadratic_approximation(risk, model, w0, scenarios=None)[source]#

Evaluate \(r(w_0)\), \(\nabla r(w_0)\), and \(H_r(w_0)\).

Uses value_grad_hess_w() so the conditional VaR bisection runs once rather than three times.

Parameters:
Return type:

QuadraticApproximation

normix.finance.transaction_costs.build_transaction_cost_qp(approx, m, c1, c2, A=None, b=None, hess_reg=1e-06)[source]#

Assemble the buy/sell QP matrices from a risk Taylor model.

Parameters:
  • approx (QuadraticApproximation) – Local approximation of \(r\) at \(w_0\).

  • m (Array) – Expected-return vector (\(E[X]\) for a normal mixture).

  • c1 (float | Array) – Risk and turnover coefficients.

  • c2 (float | Array) – Risk and turnover coefficients.

  • A (Array | None) – Optional inequality \(A w \le b\) (same \(w_0\) must be feasible). Pass None for the budget-only problem.

  • b (Array | None) – Optional inequality \(A w \le b\) (same \(w_0\) must be feasible). Pass None for the budget-only problem.

  • hess_reg (float) – Absolute Tikhonov ridge on \(\tilde H\) so the QP is strictly convex (\(\tilde H\) has a nontrivial nullspace along \(v^+ = v^-\)). Unlike Newton, this is not scaled by \(\mathrm{tr}(\tilde H)\).

Return type:

TransactionCostQP

normix.finance.transaction_costs.solve_transaction_cost_qp(qp, *, x0=None, options=None)[source]#

Solve the local QP with scipy.optimize.minimize (SLSQP).

Minimises \((c_1/2)\, v^\top \tilde H\, v - \tilde m^\top v\) subject to \(v \ge 0\), \(\tilde e^\top v = 0\), and optional \(\tilde A v \le \tilde b\). If the approximate objective does not beat holding \(w_0\), returns the hold portfolio.

Parameters:
Return type:

TransactionCostResult

class normix.finance.transaction_costs.TransactionCostProblem(model, risk, c1, c2)[source]#

Bases: Module

Local-quadratic transaction-cost rebalancing for a normal mixture.

Bundles a fitted NormalMixture and a RiskMeasure with coefficients \((c_1, c_2)\). The risk object is reused unchanged — only its weight-space gradient and Hessian at \(w_0\) enter the QP.

Parameters:
model: NormalMixture#
risk: RiskMeasure#
c1: float#
c2: float#
expected_return_vector()[source]#

Asset expected returns \(m = E[X] = \mu + \gamma\, E[Y]\).

Return type:

Array

approximate(w0, scenarios=None)[source]#

Local Taylor model of risk at w0 under subordinator scenarios.

Parameters:
Return type:

QuadraticApproximation

build_qp(w0, scenarios=None, *, m=None, A=None, b=None, hess_reg=1e-06)[source]#

Build the buy/sell QP at w0.

m defaults to expected_return_vector(). Optional A, b encode \(A w \le b\) (e.g. long-only via A = -I, b = 0).

Parameters:
Return type:

TransactionCostQP

solve(w0, scenarios=None, *, m=None, A=None, b=None, hess_reg=1e-06, options=None)[source]#

Build and solve the local QP; see solve_transaction_cost_qp().

Parameters:
Return type:

TransactionCostResult

true_objective_at(w, w0, scenarios=None, m=None)[source]#

Exact objective \(w^\top m - c_1 r(w) - c_2 \|w - w_0\|_1\).

Parameters:
Return type:

Array

Weight Functional#

Risk measures as JIT-able functions of portfolio weights.

WeightFunctional bundles a RiskMeasure, a multivariate normal-mixture model, and a fixed subordinator measure into a callable w -> ℝ with gradient and Hessian companions for optimisation.

class normix.finance.functional.WeightFunctional(risk, model, scenarios=None)[source]#

Bases: Module

Risk measure as a function of weights, with frozen model and scenarios.

Bundles a RiskMeasure, a NormalMixture model, and a probability measure of the subordinator into JIT-able callables intended for mean-risk optimisation (Phase E).

Parameters:
risk: RiskMeasure#
model: NormalMixture#
scenarios: DiscreteMeasure#
grad(w)[source]#
Parameters:

w (Array)

Return type:

Array

hess(w)[source]#
Parameters:

w (Array)

Return type:

Array

Diversification#

Diversification analytics: effective number of bets under a torsion.

Variance ENB diagonalizes the return covariance \(\mathrm{Cov}[X] = E[Y]\Sigma + \mathrm{Var}[Y]\,\gamma\gamma^\top\) (Effective Number of Bets and Minimum Torsion); generalized ENB diagonalizes the Hessian of the squared coherent risk \(H_{r^2} = 2\nabla r\,\nabla r^\top + 2 r H_r\) (Generalized Effective Number of Bets). Both reduce to one core: normalize \(d_k v_k^2\) over a torsion \(T H T^\top = \operatorname{diag}(d)\), \(v = (T^\top)^{-1} w\), and exponentiate the entropy.

Minimum torsion is a diagonalization strategy, not a diversification measure.

class normix.finance.diversification.TorsionDecomposition(T, T_inv_T, d, eigenvalues, valid)[source]#

Bases: Module

Diagonalization \(T H T^\top = \operatorname{diag}(d)\) of a PSD matrix.

T_inv_T is \((T^\top)^{-1}\), the map from portfolio weights \(w\) to torsion-adjusted weights \(v\). Both concrete torsions supply it in closed form (no solve at evaluation time). eigenvalues is the pre-clamp spectrum used for validity checks. valid is False when a material negative eigenvalue was present.

Parameters:
T: Array#
T_inv_T: Array#
d: Array#
eigenvalues: Array#
valid: Array#
class normix.finance.diversification.Torsion[source]#

Bases: Module

Strategy: how to diagonalize a PSD matrix into uncorrelated bets.

abstractmethod decompose(H)[source]#

Return \((T, (T^\top)^{-1}, d)\) with \(THT^\top = \operatorname{diag}(d)\).

Roundoff-scale negative eigenvalues are projected to zero; material indefiniteness sets valid=False (callers NaN the ENB).

Parameters:

H (Array)

Return type:

TorsionDecomposition

class normix.finance.diversification.MinimumTorsion[source]#

Bases: Torsion

Constrained minimum torsion (Meucci 2014): \(T = C^{-1/2}\operatorname{diag}(s)^{-1}\).

Closed form at \(D = I\). The iterative algorithm (unconstrained \(D\)) is deferred; it would land as a sibling IterativeMinimumTorsion without touching callers.

decompose(H)[source]#

Return \((T, (T^\top)^{-1}, d)\) with \(THT^\top = \operatorname{diag}(d)\).

Roundoff-scale negative eigenvalues are projected to zero; material indefiniteness sets valid=False (callers NaN the ENB).

Parameters:

H (Array)

Return type:

TorsionDecomposition

class normix.finance.diversification.PCATorsion[source]#

Bases: Torsion

Principal-components torsion (Meucci 2010): \(T = E^\top\), \(d = \Lambda\).

Rows ordered by descending eigenvalue. Eigenvector sign/order is unstable under near-ties — documented; MinimumTorsion is the default.

decompose(H)[source]#

Return \((T, (T^\top)^{-1}, d)\) with \(THT^\top = \operatorname{diag}(d)\).

Roundoff-scale negative eigenvalues are projected to zero; material indefiniteness sets valid=False (callers NaN the ENB).

Parameters:

H (Array)

Return type:

TorsionDecomposition

class normix.finance.diversification.ENBResult(enb, p, risk, v, d, T, eigenvalues)[source]#

Bases: Module

Effective number of bets and its decomposition at one portfolio.

p is normalized by \(\sum_k d_k v_k^2\) (a simplex up to floating point). risk is the 1-homogeneous risk whose square was diagonalized: portfolio volatility \(\sqrt{w^\top\Sigma_X w}\) for VarianceENB, \(\rho(w^\top X)\) for GeneralizedENB. enb is NaN when the local matrix is materially indefinite, the portfolio risk is non-positive, or the total contribution vanishes.

Parameters:
enb: Array#
p: Array#
risk: Array#
v: Array#
d: Array#
T: Array#
eigenvalues: Array#
class normix.finance.diversification.VarianceENB(torsion=MinimumTorsion())[source]#

Bases: Module

Variance-based effective number of bets (Effective Number of Bets and Minimum Torsion).

Diagonalizes the return covariance model.cov() \(= E[Y]\Sigma + \mathrm{Var}[Y]\,\gamma\gamma^\top\) — not the dispersion \(\Sigma\). Deterministic: no subordinator sample. Requires a finite Var[Y] (same moment caveat as skewness()).

Parameters:

torsion (Torsion)

torsion: Torsion = MinimumTorsion()#
evaluate(model, w)[source]#

ENB of \(w^\top X\) under the fitted model. Y-free by design.

vmap-able over a weight grid: jax.vmap(enb.evaluate, in_axes=(None, 0)).

Parameters:
Return type:

ENBResult

evaluate_covariance(Sigma_X, w)[source]#

ENB from an explicit covariance (empirical, factor-model, stress).

Precondition: Sigma_X PSD with nonzero diagonal, w != 0.

Parameters:
Return type:

ENBResult

class normix.finance.diversification.GeneralizedENB(risk, torsion=MinimumTorsion())[source]#

Bases: Module

ENB of a squared coherent risk measure (Generalized Effective Number of Bets).

For 1-homogeneous \(\rho\), diagonalizes \(H_{r^2}(w) = 2\nabla r\,\nabla r^\top + 2 r H_r\) where \((r, \nabla r, H_r)\) come from one call to risk.value_grad_hess_w(model, w, scenarios). Meaningful only for \(r(w) > 0\) (else \(r^2\) is not convex at w and enb is NaN).

Parameters:
risk: RiskMeasure#
torsion: Torsion = MinimumTorsion()#
evaluate(model, w, scenarios=None)[source]#

ENB at w under a fixed subordinator measure.

Defaults to subordinator quadrature. Pass a shared measure or sample to reuse it across evaluations. Supports vmap over weights.

Parameters:
Return type:

ENBResult

Scenario measures#

Discrete probability measures for conditional expectations.

See Quadrature scenarios for mixture CVaR for the quadrature construction and the finance identities preserved by positive weights.

class normix.utils.quadrature.DiscreteMeasure(Y, log_p, tail_index=inf)[source]#

Bases: Module

Probability measure \(Q=\sum_j p_j\delta_{Y_j}\) on positive nodes.

Parameters:
  • Y (Array) – Nonempty, finite, positive one-dimensional nodes.

  • log_p (Array) – Log weights with the same shape as Y. Normalized at construction; \(-\infty\) denotes a zero weight. At least one must be finite.

  • tail_index (Array) – Positive-moment threshold of the source law. Defaults to infinity for empirical measures. Quadrature retains the source threshold so truncation cannot hide a divergent risk or derivative.

property p: Array#

Normalized, nonnegative probabilities.

mean()[source]#

Finite discrete mean \(E_Q[Y]\), irrespective of the source law.

Return type:

Array

classmethod from_sample(Y)[source]#

Assign equal probabilities to a sample, preserving its order.

Parameters:

Y (Array)

Return type:

DiscreteMeasure

classmethod from_weights(Y, w)[source]#

Normalize finite nonnegative weights with positive total mass.

Parameters:
Return type:

DiscreteMeasure

classmethod coerce(scenarios, subordinator=None)[source]#

Use a measure, assign sample weights, or build subordinator quadrature.

None requires a subordinator. Explicit measures retain their source law metadata and are returned unchanged.

Parameters:
Return type:

DiscreteMeasure