feat(pairs): attiva ETH/BTC 15m flat-skip in PORT06 (BLEND, mezza size)
Origine: gioco "Blind Traders" (100 agenti ciechi su BTC/ETH anonimizzati) -> vincitore = spread ETH/BTC reversion a 15m. Testato sul serio col gate PORT06: non duplicato (corr 1h vs 15m = 0.37), robusto (16/16 celle Sharpe>1), edge NON artefatto delle candele flat ETH 15m (filtrandole resta l'83% dello Sharpe). Percorso live costruito e validato: - pairs_research.pairs_sim_flat: engine generalizzato con exit LIVE-REALIZABLE (arma exit_ready, esce alla 1a barra pulita); regression-lock a pairs_sim. - PairsWorker: flat_skip + exit_ready + rilevamento flat da OHLC (1h byte-exact). - runner: fetch diretto dei timeframe sub-orari + override position_size per-sleeve. - validate_worker_pairs: replay worker == backtest a 15m (8452 vs 8453 trade). - _defs/build_everything: sleeve PR_ETHBTC_15M (mezza size, pos 0.10) -> PORT06 FULL 6.43->7.20, OOS 8.58->9.66, DD giu'. Rischio bilanciato col 1h. - smoke live: Cerbero serve candele 15m fresche; worker ticca. Diari docs/diary/2026-06-09-*. Caveat slippage: mezza size = blend-tilt prudente. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
"""
|
||||
run_game — carica le 100 strategie proposte dagli agenti ciechi (file in
|
||||
data/games/specs/agent_*.json), lancia il torneo (epoche + cull) e stampa la
|
||||
classifica finale, poi RIVELA cosa erano X e Y.
|
||||
|
||||
Se mancano agenti (file assenti o malformati) riempie con spec casuali, cosi'
|
||||
il gioco gira sempre a 100 concorrenti.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import random
|
||||
from pathlib import Path
|
||||
|
||||
from scripts.games import engine
|
||||
from scripts.games.arena import random_spec, run_tournament, leaderboard, _normalize
|
||||
|
||||
SPECS_DIR = Path("data/games/specs")
|
||||
N = 100
|
||||
|
||||
|
||||
def load_specs():
|
||||
rng = random.Random(123)
|
||||
specs, briefs, sources = [], [], []
|
||||
for i in range(N):
|
||||
f = SPECS_DIR / f"agent_{i}.json"
|
||||
spec = None
|
||||
if f.exists():
|
||||
try:
|
||||
raw = json.loads(f.read_text())
|
||||
fam = raw.get("family")
|
||||
params = dict(raw.get("params", {}))
|
||||
if "direction" in raw and "direction" not in params:
|
||||
params["direction"] = raw["direction"]
|
||||
spec = {"family": fam, "series": raw.get("series", "A"),
|
||||
"tf": raw.get("tf", "1h"), "params": params}
|
||||
# X->A, Y->B mapping (gli agenti vedono X/Y)
|
||||
s = spec["series"]
|
||||
spec["series"] = {"X": "A", "Y": "B", "AB": "AB",
|
||||
"A": "A", "B": "B"}.get(s, "A")
|
||||
spec = _normalize(spec)
|
||||
briefs.append(str(raw.get("hypothesis", ""))[:300])
|
||||
sources.append("agent")
|
||||
except Exception as e:
|
||||
spec = None
|
||||
if spec is None:
|
||||
spec = random_spec(rng)
|
||||
briefs.append("(spec mancante -> sostituto casuale)")
|
||||
sources.append("random")
|
||||
specs.append(spec)
|
||||
n_agent = sources.count("agent")
|
||||
print(f"caricati {n_agent}/{N} spec da agenti reali, "
|
||||
f"{N - n_agent} sostituiti casuali")
|
||||
return specs, briefs
|
||||
|
||||
|
||||
def main():
|
||||
slip = float(os.environ.get("GAME_SLIP", "0.0"))
|
||||
engine.set_slippage(slip)
|
||||
if slip > 0:
|
||||
print(f"SLIPPAGE attivo: {slip*100:.3f}%/lato "
|
||||
f"(single-leg {2*slip*100:.2f}% RT extra, pairs {4*slip*100:.2f}% extra)")
|
||||
specs, briefs = load_specs()
|
||||
payload = run_tournament(specs, briefs=briefs, seed=2026,
|
||||
epochs=90, cull_every=10, cull_n=10)
|
||||
leaderboard(payload, top=10)
|
||||
rev = payload["reveal"]
|
||||
print(f"\n>>> RIVELAZIONE: Serie X = {rev['A']}, Serie Y = {rev['B']} "
|
||||
f"(timeframe base {rev['tf']}). Gli agenti non lo sapevano. <<<")
|
||||
# vincitore
|
||||
w = payload["results"][0]
|
||||
sp = w["spec"]
|
||||
print(f"\nVINCITORE: agente #{w['agent']} su {w['tf']} | {sp['family']} "
|
||||
f"{sp['series']} {sp['params'].get('direction','')}")
|
||||
print(f" ipotesi dell'agente: {w['brief']}")
|
||||
print(f" TEST(OOS): PnL {w['test']['pnl_pct']:.0f}% | win "
|
||||
f"{w['test']['win_rate']*100:.0f}% | {w['test']['tpm']:.1f} trade/mese "
|
||||
f"| Sharpe {w['test']['sharpe']:.1f}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user