"""Pure capacity caps: a target weight may not imply a notional above per_symbol_cap×NLV, nor above
participation_rate×ADV for that symbol (don't be a disproportionate share of a thin market)."""
from __future__ import annotations

import math


def cap_weights(weights: dict[str, float], *, nlv: float, adv_usd: dict[str, float],
                per_symbol_cap: float, participation_rate: float) -> dict[str, float]:
    # I1: NaN/inf NLV means capital is unknown — zero all weights rather than allow max exposure.
    if not math.isfinite(nlv) or nlv <= 0:
        return {s: 0.0 for s in weights}
    out: dict[str, float] = {}
    for s, w in weights.items():
        # I2: a non-finite weight has no safe interpretation — zero that symbol.
        if not math.isfinite(w):
            out[s] = 0.0
            continue
        max_w = per_symbol_cap
        adv = adv_usd.get(s)
        # I2: a non-finite ADV must not weaken the cap; only apply ADV cap when ADV is finite and positive.
        if adv is not None and math.isfinite(adv) and adv > 0:
            max_w = min(max_w, participation_rate * adv / nlv)
        out[s] = max(-max_w, min(max_w, w))
    return out
