mirror of
https://github.com/NicolasBohn/NexQuant.git
synced 2026-07-27 15:37:44 +00:00
cbe1c52e00
Rename all source files, scripts, tests, documentation, and configuration from Predix/predix to NexQuant/nexquant across the entire codebase.
76 lines
2.7 KiB
Python
76 lines
2.7 KiB
Python
#!/usr/bin/env python
|
|
"""Parent orchestrator: calls nexquant_rebacktest_one.py for each strategy."""
|
|
import json, subprocess, sys
|
|
from pathlib import Path
|
|
from datetime import datetime
|
|
|
|
STRAT_DIR = Path("results/strategies_new")
|
|
|
|
# Build work list
|
|
work = []
|
|
for f in sorted(STRAT_DIR.glob("*.json")):
|
|
if "verified_v2" in f.read_text():
|
|
continue
|
|
try:
|
|
d = json.loads(f.read_text())
|
|
except Exception:
|
|
continue
|
|
if d.get("factor_names") and d.get("code"):
|
|
work.append(f)
|
|
|
|
print(f"{len(work)} strategies to re-backtest", flush=True)
|
|
|
|
ok = skip = fail = 0
|
|
start = datetime.now()
|
|
|
|
for i, f in enumerate(work):
|
|
name = f.stem[:45]
|
|
print(f"[{i+1}/{len(work)}] {name} ...", end=" ", flush=True)
|
|
try:
|
|
r = subprocess.run(
|
|
["timeout", "-s", "KILL", "90", "python", "scripts/nexquant_rebacktest_one.py", str(f)],
|
|
capture_output=True, text=True, timeout=120,
|
|
stdin=subprocess.DEVNULL,
|
|
)
|
|
result = json.loads(r.stdout.strip() or "{}")
|
|
except subprocess.TimeoutExpired:
|
|
print("TIMEOUT", flush=True)
|
|
fail += 1
|
|
continue
|
|
except Exception as e:
|
|
print(f"ERROR: {e}", flush=True)
|
|
fail += 1
|
|
continue
|
|
|
|
if result.get("status") == "ok":
|
|
data = json.loads(f.read_text())
|
|
data["reevaluation_status"] = "verified_v2"
|
|
data["sharpe_ratio"] = result.get("sharpe")
|
|
data["max_drawdown"] = result.get("max_drawdown")
|
|
data["win_rate"] = result.get("win_rate")
|
|
data["total_return"] = result.get("total_return")
|
|
data["summary"] = {
|
|
**data.get("summary", {}),
|
|
"sharpe": result.get("sharpe"),
|
|
"max_drawdown": result.get("max_drawdown"),
|
|
"win_rate": result.get("win_rate"),
|
|
"monthly_return_pct": result.get("monthly_return_pct"),
|
|
"real_n_trades": result.get("n_trades"),
|
|
"total_return": result.get("total_return"),
|
|
"annualized_return": result.get("annualized_return"),
|
|
"engine": "verified_v2",
|
|
"txn_cost_bps": 2.14,
|
|
}
|
|
f.write_text(json.dumps(data, indent=2, ensure_ascii=False))
|
|
ok += 1
|
|
print(f"S={result['sharpe']:.1f} DD={result['max_drawdown']:.2%} WR={result['win_rate']:.1%} T={result['n_trades']}", flush=True)
|
|
elif result.get("status") == "skipped":
|
|
skip += 1
|
|
print(f"SKIP: {result.get('reason', '?')}", flush=True)
|
|
else:
|
|
fail += 1
|
|
print(f"FAIL: {result.get('stderr', result.get('error', '?'))[:100]}", flush=True)
|
|
|
|
elapsed = (datetime.now() - start).total_seconds()
|
|
print(f"\nDONE: ok={ok} skip={skip} fail={fail} in {elapsed:.0f}s", flush=True)
|