Self-tuning loop: per-setup report + nightly re-sweep + live learned-params
(a) learn_params.per_setup_report: permanent per-setup P&L/earliness breakdown
in the harness (forces all-setups so the ORB-vs-rest comparison is visible).
(b) nightly_tune.py + nightly_tune.sh: backfill latest bars, sweep ORB params
over accumulated gapper sessions, write the best PROFITABLE config to
data/learned_params.json. run_live_paper reads it on boot and applies the
tuned ready_score / min_bars (explicit env still wins); won't overwrite with
a losing or thin-sample config. Cron-scheduled after the close.
Verified: 75/75 tests; boot logs the learned params and applies them.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
92985938e1
commit
c7bfb3512a
4 files changed
+175
-1
No files matched your search
+23
-1
@@ -25,6 +25,7 @@ still work against whatever data already exists.
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
@@ -72,6 +73,16 @@ def _now_session_date():
|
||||
return session_date
|
||||
|
||||
|
||||
def _load_learned() -> dict:
|
||||
"""Nightly-tuned params from data/learned_params.json (empty if absent)."""
|
||||
path = os.path.join(os.environ.get("DATA_DIR", "./data"), "learned_params.json")
|
||||
try:
|
||||
with open(path) as fh:
|
||||
return json.load(fh)
|
||||
except Exception: # noqa: BLE001
|
||||
return {}
|
||||
|
||||
|
||||
def _db_target_desc() -> str:
|
||||
"""Human-readable Postgres target for the boot log (password masked)."""
|
||||
url = os.environ.get("DATABASE_URL")
|
||||
@@ -169,6 +180,13 @@ def build_runtime(args: argparse.Namespace) -> dict:
|
||||
)
|
||||
)
|
||||
|
||||
_learned = _load_learned()
|
||||
if _learned:
|
||||
print(f"[boot] learned params: ready_score={_learned.get('ready_score_pct')} "
|
||||
f"min_bars={_learned.get('min_bars')} setups={_learned.get('setups')} "
|
||||
f"(tuned {str(_learned.get('as_of', ''))[:10]} over {_learned.get('sessions')} "
|
||||
f"sessions; backtest pnl {_learned.get('pnl')}, entry@{_learned.get('entry_min')}min)")
|
||||
|
||||
watcher = Watcher(
|
||||
store,
|
||||
ResearchWatchlistProvider(
|
||||
@@ -179,7 +197,11 @@ def build_runtime(args: argparse.Namespace) -> dict:
|
||||
session_id=session_id,
|
||||
mode=EventMode.PAPER,
|
||||
max_symbols=int(os.environ.get("WATCHER_MAX_SYMBOLS", "25")),
|
||||
min_bars=int(os.environ.get("WATCHER_MIN_BARS", "10")),
|
||||
# Defaults come from the nightly self-tuner (learned_params.json);
|
||||
# an explicit env var still wins.
|
||||
min_bars=int(os.environ.get("WATCHER_MIN_BARS", str(_learned.get("min_bars", 10)))),
|
||||
ready_score_pct=float(os.environ.get(
|
||||
"WATCHER_READY_SCORE", str(_learned.get("ready_score_pct", 60.0)))),
|
||||
min_quality=float(os.environ.get("WATCHER_MIN_QUALITY", "0.30")),
|
||||
),
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user