"""TEMPLATE for a blind-signal agent. COPY this, rename, implement `signal`. You are given two anonymized, overlaid price curves ("A" and "B"), rebased to 100. You do NOT know what they are. Find a way to ANTICIPATE the next move. Rules (enforced automatically — break them and you are disqualified): * `signal(df)` returns float array len(df). position[i] in [-1,+1] = how much of equity to hold during the NEXT bar (sign=long/short, 0=flat). The evaluator shifts it -> you trade bar i+1 with a decision made at close[i]. * CAUSAL/ONLINE only: position[i] uses ONLY rows 0..i. No .shift(-k), no centered windows, no fitting a model on the whole df then predicting the whole df. If you train a model, use an EXPANDING/WALK-FORWARD scheme (refit using only past rows) or fit once on an EARLY fixed warmup and freeze. * Tune ONLY on split='train'. The held-out tail is scored by the orchestrator. Score it: uv run python scripts/research/blind/blind_eval.py --module --split train Make sure the output has "causality": {"ok": true, ...}. """ import numpy as np import blindlib as bl def signal(df): c = df["close"].values.astype(float) # --- EXAMPLE: vol-targeted dual-timescale momentum (replace with your idea) --- fast = c / bl.sma(c, 20) - 1.0 slow = c / bl.sma(c, 100) - 1.0 raw = np.sign(fast) * 0.5 + np.sign(slow) * 0.5 # -1..1 direction pos = bl.vol_target(raw, df, target_vol=0.20, vol_win_days=30, leverage_cap=1.0) return np.clip(pos, -1.0, 1.0)