live: commit the TrendRider V9/V10 registrations the monitor already runs
trader.py registers trend_rider_v9 (+ vt24/vt32/vt36) and trend_rider_v10 (+ vt32/vt36) from strategies/trend_rider_v9.py, and bridge.py labels them. These were left uncommitted by the 2026-10-07 research session while the monitor ran them from the working tree (state files data/trader_us_trend_rider_v9*/v10*). research/tr9_*.py is the research trail CLAUDE.md cites. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
69
research/tr9_audit.py
Normal file
69
research/tr9_audit.py
Normal file
@@ -0,0 +1,69 @@
|
||||
"""Full-window audit: every registered US strategy vs TrendRider V9.
|
||||
|
||||
Runs the official engine path (run_market, same params as precompute) over
|
||||
the current 10y common window and writes the comparison table plus the
|
||||
head-to-head verdict (does V9 beat every other strategy on BOTH CAGR and
|
||||
Sharpe?) to data/research/results/tr9_full_comparison.json.
|
||||
|
||||
PYTHONPATH=. uv run python -m research.tr9_audit
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
|
||||
import pandas as pd
|
||||
|
||||
from trader import (AGENT_REVIEW_STRATEGIES, STRATEGY_REGISTRY,
|
||||
strategy_supports_market)
|
||||
|
||||
import research.tr9_lab as lab
|
||||
|
||||
OUT = os.path.join("data", "research", "results", "tr9_full_comparison.json")
|
||||
V9_NAMES = ["trend_rider_v9", "trend_rider_v9_vt24", "trend_rider_v9_vt32", "trend_rider_v9_vt36",
|
||||
"trend_rider_v10", "trend_rider_v10_vt32", "trend_rider_v10_vt36"]
|
||||
NEW_NAMES = [n for n in V9_NAMES if "v10" in n]
|
||||
|
||||
|
||||
def main() -> None:
|
||||
us_names = [n for n in STRATEGY_REGISTRY
|
||||
if strategy_supports_market(n, "us") and n not in AGENT_REVIEW_STRATEGIES
|
||||
and not n.startswith("sim_")]
|
||||
end = "2026-10-07"
|
||||
print(f"auditing {len(us_names)} US strategies (window ...{end})")
|
||||
curves = lab.run(us_names, start="2017-12-26", end=end)
|
||||
rows = []
|
||||
for name, eq in curves.items():
|
||||
m = lab.metrics(eq)
|
||||
rows.append({"name": name, **m})
|
||||
df = pd.DataFrame(rows).sort_values("cagr", ascending=False)
|
||||
pd.set_option("display.width", 200)
|
||||
print(f"{'name':44s} {'CAGR':>8s} {'vol':>7s} {'Sharpe':>7s} {'MDD':>7s}")
|
||||
for _, r in df.iterrows():
|
||||
print(f"{r['name']:44s} {r['cagr']*100:7.1f}% {r['vol']*100:6.1f}% "
|
||||
f"{r['sharpe']:7.2f} {r['mdd']*100:6.1f}%")
|
||||
|
||||
others = df[~df["name"].isin(NEW_NAMES)]
|
||||
best_cagr = others.loc[others["cagr"].idxmax()]
|
||||
best_sharpe = others.loc[others["sharpe"].idxmax()]
|
||||
print(f"\nexisting best CAGR : {best_cagr['name']} {best_cagr['cagr']*100:.1f}%")
|
||||
print(f"existing best Sharpe : {best_sharpe['name']} {best_sharpe['sharpe']:.2f}")
|
||||
verdict = {}
|
||||
for v9 in NEW_NAMES:
|
||||
row = df[df["name"] == v9].iloc[0]
|
||||
beat_cagr = bool((others["cagr"] < row["cagr"]).all())
|
||||
beat_sharpe = bool((others["sharpe"] < row["sharpe"]).all())
|
||||
verdict[v9] = {"cagr": float(row["cagr"]), "sharpe": float(row["sharpe"]),
|
||||
"mdd": float(row["mdd"]),
|
||||
"beats_all_cagr": beat_cagr, "beats_all_sharpe": beat_sharpe,
|
||||
"beats_all_both": beat_cagr and beat_sharpe}
|
||||
print(f"{v9}: CAGR {row['cagr']*100:.1f}% (beats all: {beat_cagr}), "
|
||||
f"Sharpe {row['sharpe']:.2f} (beats all: {beat_sharpe})")
|
||||
with open(OUT, "w") as fh:
|
||||
json.dump({"window": {"start": "2017-12-26", "end": end},
|
||||
"rows": rows, "verdict": verdict}, fh, indent=1)
|
||||
print("wrote", OUT)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user