"""THE agent-editable file of the autoresearch loop (see program.md).

Contract — keep this exact interface:
    scores(close, volume) -> pd.Series indexed by ticker
close/volume are daily panels (rows = dates, cols = tickers), already truncated
so close.index[-1] IS the as-of date. Higher score = buy; NaN = skip the ticker.
Must be deterministic, pandas/numpy only, no I/O or network.

Seed: vectorized port of the Simons lens (screener/strategies/simons.py).
"""
import numpy as np
import pandas as pd


def scores(close: pd.DataFrame, volume: pd.DataFrame) -> pd.Series:
    last = close.iloc[-1]

    w10 = close.tail(10)
    z = (last - w10.mean()) / w10.std()          # z-score vs 10d MA

    d = close.tail(15).diff()
    gain, loss = d.clip(lower=0).mean(), (-d.clip(upper=0)).mean()
    rsi = 100 - 100 / (1 + gain / loss)          # RSI-14

    mom = close.iloc[-21] / close.iloc[-126] - 1  # 6-1 momentum

    r = close.tail(127).pct_change()
    sh = np.sqrt(252) * r.mean() / r.std()       # 126d Sharpe

    subs = pd.DataFrame({
        "mr_z":   (1 - (z + 2.5) / 3.5).clip(0, 1),   # lower_better(z, -2.5, 1.0)
        "mr_rsi": (1 - (rsi - 30) / 40).clip(0, 1),   # lower_better(rsi, 30, 70)
        "mom":    ((mom + 0.2) / 0.6).clip(0, 1),     # higher_better(mom, -0.2, 0.4)
        "sharpe": ((sh + 0.5) / 2.5).clip(0, 1),      # higher_better(sh, -0.5, 2.0)
    })
    w = pd.Series({"mr_z": 0.40, "mr_rsi": 0.05, "mom": 0.15, "sharpe": 0.40})
    return subs.mul(w).sum(axis=1, min_count=1) / subs.notna().mul(w).sum(axis=1)


if __name__ == "__main__":
    import prepare
    print(f"METRIC {prepare.evaluate(scores):.4f}")
