"""Candidate edge #4: causal pump/anomaly detection. A per-coin, same-day-observable turnover z-spike ->
a short-the-pump target weight. Must be run through honest_sleeve_returns to see if it survives the real
pump-day slippage (the killer). Pure; NO look-ahead (the z-score uses strictly PAST turnover only)."""
from __future__ import annotations

import statistics as st

from fxhnt.application.honest_gates import book_returns, risk_parity_weights, sharpe_of
from fxhnt.application.honest_reference import honest_sleeve_returns

_WINDOW = 20


def pump_signal(turnover_panel: dict[str, dict[int, float]], *, z: float = 3.0) -> dict[int, dict[str, float]]:
    """{day: {symbol: -1.0}} — a short-the-pump target on each coin-day whose turnover z-score vs its
    trailing _WINDOW days (strictly PAST) exceeds `z`. Causal: needs >= _WINDOW prior days and nonzero
    trailing stdev, else no signal."""
    out: dict[int, dict[str, float]] = {}
    for sym, series in turnover_panel.items():
        days = sorted(series)
        for i, d in enumerate(days):
            hist = [series[days[j]] for j in range(max(0, i - _WINDOW), i)]   # strictly past
            if len(hist) < _WINDOW:
                continue
            mu, sd = st.mean(hist), st.pstdev(hist)
            if sd > 0.0 and (series[d] - mu) / sd > z:
                out.setdefault(d, {})[sym] = -1.0
    return out


def evaluate_pump_edge(weights_by_day, turnover_panel, spread_bps, *, aum, impact_k,
                       positioning_series=None):
    """Run the pump weights through the honest-cost pipeline and return the 3-gate verdict:
    - sharpe: honest net Sharpe of the pump series (after capacity + slippage);
    - survives_execution (G-execution, the killer): net Sharpe > 0 after real pump-day slippage;
    - marginal_vs_positioning (G-marginal): risk-parity(pos, pump) book Sharpe - positioning-alone Sharpe,
      or None if no positioning_series supplied."""
    net = honest_sleeve_returns(weights_by_day, turnover_panel, spread_bps, aum=aum, impact_k=impact_k)
    sh = sharpe_of(net)
    marginal = None
    if positioning_series is not None:
        rbs = {"pos": positioning_series, "pump": net}
        book = book_returns(rbs, risk_parity_weights(rbs))
        marginal = sharpe_of(book) - sharpe_of(positioning_series)
    return {"sharpe": sh, "survives_execution": sh > 0.0, "marginal_vs_positioning": marginal}
