Letter #132 — 2026-04-21
Facts
- Session 313 (on-demand wake — Telegram "money market bot stopped trading")
- Current ET: 10:32 AM (April 21, 2026)
- Model: Opus 4.7
- MM LIVE was stuck 40h+ (since ~1:40 PM ET Apr 19) with 4 phantom open orders blocking MAX_OPEN_ORDERS=4 cap
- Bot resumed quoting at 10:32 AM ET after state cleanup
- On-chain USDC: $193.01 (was $200.02 start; real on-chain loss ~$7, vs tracker $95.25 = -$4.75 PNL + $100 buffer)
Session Intent
On-demand + operational. Unstick MM live, reply to Lucas honestly, plan the code fix. Don't expand scope.
Stream
10:26 AM ET — Telegram wake
Lucas: "it seems that the money market bot stopped trading". Service is active (running), but logs showed 40h of SKIP — MAX_OPEN_ORDERS=4 reached every 5 seconds. Something's wrong beyond "stopped."
10:28 AM ET — Root cause
State file has 2 windows from Apr 19 in status=open, 20 shares committed each side, $19.70 reserved from bankroll. Each window = 2 orders → 4 open orders → cap hit.
Tried to resolve them via Gamma API: slug=btc-updown-5m-1776619500 returns empty. Same for 1776620400. Polymarket's Gamma endpoint drops closed markets from slug-indexed results after some time.
The bot's resolver (check_market_resolution) only knows the slug path. No fallback. When Gamma returns None, the window sits "open" forever, and on the next new-window tick the bot loops back to open_orders_now >= MAX_OPEN_ORDERS → SKIP.
Window 1776619800 (entered BETWEEN the two stuck ones) resolved fine same day — suggests a transient Gamma hiccup at 13:26 and 13:40 Apr 19 that broke the first/last queries, while 13:30 made it through. Once dropped, the slug lookup never recovers.
10:30 AM ET — Verified orders expired
Checked all 4 on-chain orders via client.get_order(oid). All four returned status=expired, matched=0/0. So no real capital was ever at risk on these windows — the $19.70 in "reserved" bankroll was a fiction; the capital was already back on-chain.
10:31 AM ET — Unstuck
Stopped service. Backed up state. Called resolve_mm_market(client, state, wid, 'Up') manually for both windows (outcome arg immaterial when fills=0). Bankroll restored: $75.55 → $95.25. Saved. Restarted.
Startup reconcile confirms tracker=$95.25, on_chain=$193.01, drift=$97.76 (= $100 buffer minus $2.25 gas/fees — expected).
10:32 AM ET — First quote after unstick
Window 1776781800: Up $0.68 / Dn $0.31, combined $0.99, margin $0.01, 10 shares. Back in business.
10:32 AM ET — Telegram to Lucas (pending)
Writing reply now.
10:34 AM ET — Code fix deployed
Probed Gamma API by appending &closed=true — returns full resolved market data including outcomePrices: ["1","0"]. Both previously-stuck windows confirm: 1776619500 Up, 1776620400 Down. CLOB /markets/{conditionId} returns empty for these older markets — Gamma's outcomePrices is the durable signal.
Fix in check_market_resolution:
1. If default Gamma slug query returns empty, retry with &closed=true
2. Before falling through to CLOB, check if market.closed and outcomePrices — if so, return winner directly
Verified on all four test windows: 2 previously stuck → correct outcomes; 1 historical → correct; 1 active → None (correct, hasn't resolved). Restarted service. New bankroll $85.35 (1 window's $9.90 reserved).
Principle #116, KB #2699, work log entry recorded.
10:36 AM ET — Lucas follow-up on $100 bankroll cap
Lucas: "what do you mean the $100 bankroll? we put $200 in"
Design note: INITIAL_BANKROLL=$100 in source, on-chain is $200. The bot caps itself at $100 working capital, leaves $100 as buffer. Offered two ways to raise: CLI --bankroll 200 (one-shot) or edit source (permanent). Flagged the tracker-reset caveat (would lose the -$4.75 running record; on-chain reality unchanged). Holding for his answer before touching config.
10:39 AM ET — Second bug: resolve lag past window boundary
After fix #1, bot STILL went back to MAX_OPEN_ORDERS skip with 2 new windows (1776781800, 1776782100) opened but not resolving. Root cause: resolve loop only ran on new-window boundary (once per 5 min). UMA oracle posts can lag past that. Fix #2: added resolve_retry_counter that triggers resolve attempts every 12 poll iterations (~60s) within the same window.
10:41 AM ET — End-to-end verification
Log fired: MM RESOLVED 1776781800: Up, fill=both (up=10.0/10, dn=10.0/10), P&L=$+0.1198, bank=$85.67. Both sides filled, positive P&L, bankroll updated. The stuck-window class of bug is closed end-to-end. On-chain $174.01, tracker $85.67.
10:45 AM ET — Lucas: trade size scaling?
Lucas Telegram: "what size trades are we taking? does the size change based on $100 vs $200 vs $500?"
Checked source: max_cost = min(QUOTE_SIZE=$10, bankroll * 0.25). The 25% rule only bites below ~$40 bankroll. Above that, QUOTE_SIZE=$10 is the hard cap — trade size does NOT scale with bankroll. Raising bankroll = more concurrent windows (but MAX_OPEN_ORDERS=4 caps that at 2 markets). Told Lucas; offered to propose a sizing plan (e.g., QUOTE_SIZE=$25 + bankroll=$200) if he wants bigger bets.
10:46 AM ET — Second resolve cycle clean
Window 1776782100 resolved at 10:46:52, both sides filled 10/10, P&L +$0.3194, bankroll $86.09. First full-cycle validation of the 60s-retry fix: window was entered before restart, resolved in-window (not on boundary), retry caught it. Two clean resolves in a row (1776781800 +$0.12, 1776782100 +$0.32).
10:48 AM ET — Sizing proposal drafted (held)
Lucas offered "yes please propose" path. Pulled LIVE stats to prep: 7 windows resolved, total P&L -$4.31 dominated by one -$5.29 one-sided loss (window 1776619200: Up filled, Dn didn't, market went Down). Ex-outlier +$0.98 across 6 windows. Fill distribution 57/14/29 (both/one/none). Sample too small to trust — recommendation: don't scale up yet, run 100+ windows first. Draft at DRAFT_sizing_proposal.md, ready to send if asked.
What's Next
- Wait on Lucas's response re: $100 vs $200 bankroll cap (guard in place; don't touch config until he answers)
- Evening session can look at stuck-window timeout as belt+suspenders (force-close after N hours if resolve keeps returning None)
Composting
Operational session, no reading.
What's Unfinished
- Lucas pending on bankroll cap question
- btc-multivariant dry run continuing — untouched this session
- Moderate Excel already sent Apr 19; nothing pending on Lucas for that thread