From 2c9faf85849bae2d5ff62e8f0e5548a578b70b02 Mon Sep 17 00:00:00 2001 From: jaxperro Date: Thu, 23 Jul 2026 15:43:39 -0400 Subject: [PATCH] copybot: expected-resolution ETA on open bets (display metadata only) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Feed builder enriches open bet records with end_ts via the cached _market lookup — one fetch per position lifetime, <=8 per publish pass, fetched-but-unknown marked to prevent refetch loops. No execution-path change; both dashboards render it under the LIVE pill with the in-play-resolves-earlier tooltip. Co-Authored-By: Claude Fable 5 --- copybot.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/copybot.py b/copybot.py index 0d4f70a5..7c74ee10 100644 --- a/copybot.py +++ b/copybot.py @@ -341,6 +341,17 @@ def market_neg_risk(cond): return bool(m.get("neg_risk")) if m else False +def _iso_end(s): + """CLOB end_date_iso -> epoch (None on parse trouble). Display metadata + only — in-play markets usually resolve well before the scheduled end.""" + try: + import calendar + return calendar.timegm(time.strptime( + s.replace("+00:00", "Z")[:20], "%Y-%m-%dT%H:%M:%SZ")) + except Exception: + return None + + def resolution_price(token_id, cond, outcome=None): """Settled price of our held token — 1.0 won, 0.0 lost, 0.5 refunded (50/50 resolution: walkovers/abandonments), None if not resolved yet. @@ -1612,6 +1623,21 @@ class Copybot: for m in missed: w = (m.get("wallet") or "").lower() m["name"] = self.names.get(w) or addr_names.get(w) or w[:10] + # expected-resolution ETA (2026-07-23, display metadata only): one + # cached market fetch per open bet lifetime, <=8 per publish pass; + # "end_ts" in the record marks fetched-even-if-unknown (no refetch + # loops on metadata-less markets) + fetched = 0 + for tok, b in bets.items(): + if b.get("status") != "open" or "end_ts" in b or fetched >= 8: + continue + cond = (mp.get(tok) or {}).get("cond") + if not cond: + b["end_ts"] = None + continue + m = _market(cond) or {} + b["end_ts"] = _iso_end(m.get("end_date_iso") or "") + fetched += 1 feed = { "mode": "live" if self.engine.ex.live else "paper", "bankroll": bank, "stake": round(self.engine.stake_usd(), 2),