"""Winsorize the per-symbol DAILY-CLOSE carry return so a single absurd basis/funding print cannot dominate
the cross-sectional carry sleeve — the 2025-02-02 xsfunding artifact (+179.7% sleeve / +44.69% book in one
day, ~15x the next-largest ever +8% day) was a bad spot/perp print in the daily-close basis term
`(spot_ret − perp_ret)`, NOT a capturable edge. The cap is applied IN `carry_return_by_symbol` (the SSOT
both the backtest baseline and the live book read), so it is retroactive AND prospective.

The deliberate intraday `worst_basis` liquidation charge (capped at −100%) is a SEPARATE, already-bounded
override and must NOT be winsorized — that regression is asserted here too (and covered by
test_carry_worst_basis_charge.py)."""
from fxhnt.application.paper_book import (
    _CARRY_RET_DAILY_CAP,
    carry_return_by_symbol,
    sleeve_daily_carry,
)
from fxhnt.domain.paper import Position


def _pos(sym, qty, entry):
    return Position("xsfunding", sym, qty, entry, "2026-01-01")


def test_absurd_positive_carry_ret_is_capped():
    # The 2025-02-02 artifact shape: a lone +179.7% (basis) print. Capped to +cap, not silently dropped.
    cr = carry_return_by_symbol({"A": 0.0}, {"A": 1.797})
    assert cr["A"] == _CARRY_RET_DAILY_CAP


def test_absurd_negative_carry_ret_is_capped():
    cr = carry_return_by_symbol({"A": 0.0}, {"A": -1.80})
    assert cr["A"] == -_CARRY_RET_DAILY_CAP


def test_normal_returns_pass_through_unchanged():
    # ±5% daily basis+funding is a real, capturable move — untouched by the cap.
    cr = carry_return_by_symbol({"A": 0.01, "B": -0.02}, {"A": 0.04, "B": -0.03})
    assert abs(cr["A"] - 0.05) < 1e-12
    assert abs(cr["B"] - (-0.05)) < 1e-12


def test_cap_applies_to_combined_funding_plus_basis():
    # An artifact can arrive via either leg; the cap is on the COMBINED carry return.
    cr = carry_return_by_symbol({"A": 0.30}, {"A": 0.30})   # combined +0.60 > cap
    assert cr["A"] == _CARRY_RET_DAILY_CAP


def test_default_cap_is_documented_bound():
    assert _CARRY_RET_DAILY_CAP == 0.25


def test_book_sleeve_return_bounded_by_cap():
    # A unit-weight long on the glitch symbol would have booked +179.7% for the day; capped to +cap.
    prev = [_pos("A", 0.1, 10.0)]              # w = qty*entry = +1, gross = 1
    cr = carry_return_by_symbol({"A": 0.0}, {"A": 1.797})
    assert abs(sleeve_daily_carry(prev, cr) - _CARRY_RET_DAILY_CAP) < 1e-12


def test_book_skew_drops_when_outlier_capped():
    # A book long the glitch symbol AND a normal symbol: the day return is dominated-then-bounded by the cap,
    # far below the uncapped ~ (1.797 + 0.02)/2 ≈ +0.91 it would otherwise book.
    prev = [_pos("A", 0.1, 10.0), _pos("B", 0.1, 10.0)]     # equal +1 weights, gross = 2
    cr = carry_return_by_symbol({"A": 0.0, "B": 0.0}, {"A": 1.797, "B": 0.02})
    day = sleeve_daily_carry(prev, cr)                      # (cap + 0.02)/2
    assert abs(day - (_CARRY_RET_DAILY_CAP + 0.02) / 2.0) < 1e-12
    assert day < 0.20                                       # nowhere near the uncapped +0.91


def test_worst_basis_liquidation_charge_is_not_winsorized():
    # REGRESSION: the deliberate intraday worst_basis override (−100% cap) is a separate, already-bounded
    # charge and must survive UNwinsorized — a −1.0 leg-loss must not be clipped up to −cap.
    cr = carry_return_by_symbol({"A": 0.0}, {"A": -0.007}, worst_basis_by_symbol={"A": -1.63})
    assert cr["A"] == -1.0                                  # not -_CARRY_RET_DAILY_CAP
    # a mild worst_basis beyond the daily cap also survives (it is the real intraday excursion).
    cr2 = carry_return_by_symbol({"A": 0.0}, {"A": 0.0}, worst_basis_by_symbol={"A": -0.40})
    assert abs(cr2["A"] - (-0.40)) < 1e-12
