From ec308346b2b9f8fedb589919a7acdcd1ae9fa22f Mon Sep 17 00:00:00 2001 From: jgrusewski Date: Sat, 6 Jun 2026 16:55:42 +0200 Subject: [PATCH] fix(surfer): cwd-independent PoC + fixed-phase weekly rebalance (cron-ready) - Rebalance keyed on FIXED calendar phase (epoch-day%7==0 -> Thursdays) instead of drifting days[0]%K, so backtest and live agree on rebalance timing. - STATE path absolute (relative to script) -> paper mode runs from any cwd (cron-safe). - Backtest unchanged (net +0.40@$20M, CPCV-med +0.47). Installed system crontab (daily 12:07): marks paper PnL daily, rebalances Thursdays, logs to data/surfer/paper_runs.log. Forward-test seeded inception 2026-06-06. Co-Authored-By: Claude Opus 4.8 (1M context) --- scripts/surfer/surfer_poc.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/scripts/surfer/surfer_poc.py b/scripts/surfer/surfer_poc.py index a54d6a2e6..d773d9590 100644 --- a/scripts/surfer/surfer_poc.py +++ b/scripts/surfer/surfer_poc.py @@ -31,7 +31,8 @@ import torch # noqa: E402 DEV = "cuda" if torch.cuda.is_available() else "cpu" DAY_MS = 86_400_000 -STATE = "data/surfer/poc_state.json" +_REPO = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) # cwd-independent (cron-safe) +STATE = os.path.join(_REPO, "data/surfer/poc_state.json") CFG = dict( lookback=20, # XS momentum horizon (days) @@ -81,11 +82,11 @@ def compute_weights(close, qvol, days, cfg): sig = trailing(lc, cfg["lookback"]).copy(); sig[~univ] = np.nan wt = xs_weights(sig) # daily target (market-neutral, unit gross) wt = ewma_rows(wt, cfg["smooth_span"]) # smooth - held = wt.copy() # weekly rebalance on calendar day % K - K = cfg["rebal_k"] + held = wt.copy() # weekly rebalance on FIXED calendar phase (day%K==0) + K = cfg["rebal_k"] # epoch day0=Thu → rebalances every Thursday, live-consistent last = 0 for t in range(T): - if days[t] % K == days[0] % K: + if days[t] % K == 0: last = t held[t] = wt[last] return held, univ @@ -234,7 +235,7 @@ def paper(cfg): st["equity"] *= (1.0 + ret) st["log"].append({"day": today, "mark_ret": round(ret, 6), "equity": round(st["equity"], 5)}) # 2) REBALANCE on the weekly boundary - rebal = (st["last_mark_day"] is None) or (today % cfg["rebal_k"] == days[0] % cfg["rebal_k"]) + rebal = (st["last_mark_day"] is None) or (today % cfg["rebal_k"] == 0) # fixed weekly phase (Thursdays) trades = [] if rebal: cur = st["positions"]