"""Adversarial dissection of the SELECTION-FREE relative-value basket vs TP01.""" from __future__ import annotations import importlib.util, sys from pathlib import Path import numpy as np import pandas as pd HERE = Path(__file__).resolve().parent sys.path.insert(0, str(HERE)) sys.path.insert(0, "/opt/docker/PythagorasGoal/scripts/research/alt") import ortholib as ol import altlib as al AGENTS = HERE / "agents" def _book(path: Path): spec = importlib.util.spec_from_file_location(path.stem, path) mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) return mod.book def _sh(s) -> float: r = np.asarray(pd.Series(s).dropna().values, float) return float(np.mean(r) / np.std(r) * np.sqrt(365.25)) if len(r) > 2 and np.std(r) > 0 else 0.0 def _dd(s) -> float: eq = (1.0 + pd.Series(s).dropna()).cumprod() return float((eq / eq.cummax() - 1.0).min()) def uplift_at(cand: pd.Series, B: pd.Series, lo=None, hi=None, w=0.25) -> float: J = pd.concat({"B": B, "C": cand}, axis=1, join="inner").dropna() if lo is not None: J = J[J.index >= pd.Timestamp(lo, tz="UTC")] if hi is not None: J = J[J.index < pd.Timestamp(hi, tz="UTC")] if len(J) < 30: return float("nan") return _sh((1 - w) * J["B"] + w * J["C"]) - _sh(J["B"]) def main(): B = al.tp01_baseline_daily() # ---- collect ALL books, classify ---- rows = {} meta = {} for p in sorted(AGENTS.glob("agent_*.py")): try: ev = ol.eval_book(_book(p)) except Exception as e: print(f"skip {p.stem}: {e}"); continue d = ev["daily"] if d.std() == 0: print(f"skip degenerate {p.stem}"); continue rows[p.stem.replace("agent_", "")] = d meta[p.stem.replace("agent_", "")] = ev names = list(rows) M = pd.concat(rows, axis=1, join="inner").dropna() print(f"\nBooks loaded: {len(names)} common-date matrix: {M.shape[0]} days " f"[{M.index.min().date()} .. {M.index.max().date()}]") # selection-free: ALL non-degenerate, market-neutral. exclude only the OBVIOUS # degenerate DILUTE (rebalance_harvest, sharpe<0 standalone & negative every metric). excl = ["12_rebalance_harvest"] keep = [n for n in names if n not in excl] print(f"Basket = equal-weight of {len(keep)} books (excluded only {excl})") basket = M[keep].mean(axis=1) basket_all = M.mean(axis=1) # truly ALL incl rebalance_harvest for label, bk in [("BASKET(excl harvest)", basket), ("BASKET(all 18)", basket_all)]: print(f"\n===== {label} =====") Bal = pd.concat({"B": B, "C": bk}, axis=1, join="inner").dropna() corr = Bal["B"].corr(Bal["C"]) print(f" standalone Sharpe {_sh(bk):.3f} maxDD {_dd(bk):.3f} corr->TP01 {corr:.3f} " f"n={len(bk)}") # full + per-cut uplift (forward windows from cut) print(f" uplift (w=0.25, window = [cut, end)):") for cut in ["2018-01-01", "2021-01-01", "2022-01-01", "2023-01-01", "2024-01-01", "2025-01-01"]: u = uplift_at(bk, B, lo=cut) print(f" from {cut[:4]}+ : {u:+.3f}") # PRE-2025 ONLY (exclude suspect window) u_pre = uplift_at(bk, B, hi="2025-01-01") u_2025 = uplift_at(bk, B, lo="2025-01-01") print(f" uplift 2019-2024 ONLY (exclude suspect window): {u_pre:+.3f}") print(f" uplift 2025+ ONLY : {u_2025:+.3f}") # per-year standalone returns & per-year uplift print(f" per-year: standalone ret | blend-uplift(w0.25, that year only)") for y in sorted(set(bk.index.year)): sub = bk[bk.index.year == y] ret = float((1 + sub).prod() - 1) uy = uplift_at(bk, B, lo=f"{y}-01-01", hi=f"{y+1}-01-01") print(f" {y}: ret {ret:+7.2%} uplift {uy:+.3f}") # ---- decompose full-sample uplift: pre vs post 2025 ---- print("\n===== UPLIFT DECOMPOSITION (basket excl harvest, w=0.25) =====") full = uplift_at(basket, B, lo="2018-01-01") print(f" full-sample uplift {full:+.3f}") print(f" pre-2025 (2019-2024) {uplift_at(basket,B,hi='2025-01-01'):+.3f}") print(f" 2025+ only {uplift_at(basket,B,lo='2025-01-01'):+.3f}") # ---- fee sensitivity: rebuild basket at higher fees ---- print("\n===== FEE SENSITIVITY (rebuild every book's daily net at higher RT fee) =====") for fee_side in [0.0005, 0.0010, 0.0015]: dd = {} for p in sorted(AGENTS.glob("agent_*.py")): nm = p.stem.replace("agent_", "") if nm in excl: continue try: ev = ol.eval_book(_book(p), fee_side=fee_side) if ev["daily"].std() > 0: dd[nm] = ev["daily"] except Exception: pass Mf = pd.concat(dd, axis=1, join="inner").dropna() bk = Mf.mean(axis=1) u_full = uplift_at(bk, B, lo="2018-01-01") u_pre = uplift_at(bk, B, hi="2025-01-01") u_25 = uplift_at(bk, B, lo="2025-01-01") print(f" RT={2*fee_side*100:.2f}% standalone Sh {_sh(bk):+.3f} " f"uplift full {u_full:+.3f} | pre25 {u_pre:+.3f} | 25+ {u_25:+.3f}") # ---- turnover / executability of the basket ---- print("\n===== EXECUTION REALISM (per-book at $600, basket-averaged legs) =====") tns = [meta[n]["turnover_per_year"] for n in keep] print(f" per-book turnover/yr: min {min(tns):.1f} med {np.median(tns):.1f} max {max(tns):.1f}") print(f" Basket = mean of {len(keep)} books; each leg capped 0.5. Averaged turnover lower.") # build averaged book legs to measure REAL basket turnover & notional btc, eth = ol.aligned() wbs, wes = [], [] for n in keep: wb, we = _book(AGENTS / f"agent_{n}.py")(btc, eth) wbs.append(np.nan_to_num(np.asarray(wb, float))) wes.append(np.nan_to_num(np.asarray(we, float))) wb = np.clip(np.mean(wbs, axis=0), -0.5, 0.5) we = np.clip(np.mean(wes, axis=0), -0.5, 0.5) pb = np.zeros(len(wb)); pb[1:] = wb[:-1] pe = np.zeros(len(we)); pe[1:] = we[:-1] turn = np.abs(np.diff(pb, prepend=0.0)) + np.abs(np.diff(pe, prepend=0.0)) turn_yr = turn.sum() / (len(turn) / 365.25) max_leg = float(np.max(np.maximum(np.abs(pb), np.abs(pe)))) print(f" AVERAGED-BASKET book: turnover/yr {turn_yr:.1f} max-leg-frac {max_leg:.3f} " f"max per-leg notional @$600 = ${max_leg*600:.0f}") print(f" typical daily notional traded @$600 satellite (say 20% slot=$120): " f"${turn_yr/365.25*120:.2f}/day both legs") if __name__ == "__main__": main()