Skip to content

Neutrality

A dollar-neutral book can still carry a market bet when its names have different betas. The toolkit removes each exposure separately:

import pandas as pd
from aether_quant import neutrality

raw = {"AAA": 0.3, "BBB": 0.3, "CCC": -0.3, "DDD": -0.3}
book, steps = neutrality.apply_book_neutrality(
    raw, sector_by_symbol={"AAA": "tech", "BBB": "energy", "CCC": "tech", "DDD": "energy"},
    dollar_neutral=True, sector_neutral=True, gross_exposure_cap=1.0, max_weight_per_name=0.2, sector_max_net_weight=0.05,
)
betas = {"AAA": 1.4, "BBB": 0.8, "CCC": 1.0, "DDD": 0.9}
hedged = neutrality.beta_neutralize(book, betas)                 # the smallest change that zeroes net beta
print(steps["steps_applied"], round(neutrality.net_beta(hedged, betas), 12))

exposures = pd.DataFrame({"size": [1.0, -0.5, 0.2, 0.3], "value": [0.1, 0.4, -0.2, -0.3]}, index=list(raw))
pure = neutrality.factor_neutralize(pd.Series(raw), exposures)   # zero exposure to every listed factor
Function Removes
apply_book_neutrality dollar and sector exposure, per-name and sector caps, gross cap (proved shrink-only and sign-preserving in Lean 4)
beta_neutralize(weights, betas, hedge=None) net beta, by projection or through a hedge instrument
factor_neutralize(weights, exposures) every column of exposures, by least squares
estimate_betas(returns, market) OLS betas over a trailing window, NaN when too short
sector_relative_scores, residualise_signal sector or factor effects from the scores, before weights exist