u/CommercialPurple3490

How I model fair value for Polymarket BTC binary options — Black-Scholes on a 15-min horizon, conviction scoring, and what the backtest actually taught me

Following up on my auto-tuner post. Several people asked about the core signal logic, so here's a deeper dive into how the bot actually decides to enter a trade.

The market

Polymarket runs BTC (and ETH) Up/Down markets on 15-minute windows. You buy YES or NO shares at a price between 0 and 1. If BTC closes above the opening price at slot expiry, YES resolves to 1.00. Taker fee is ~1.8% at p=0.5, drops to zero at the extremes.

The signal model

I use a Black-Scholes digital option formula to compute a fair value probability:

p_up = N( drift / (sigma * sqrt(T)) )

Where:

  • drift = (spot_now − slot_open) / slot_open
  • sigma = rolling 15m realized volatility (per-minute)
  • T = seconds remaining in slot / 900

Edge = |fair_value − market_ask|. Only enter if edge ≥ 0.26 (taker fee at p=0.5 is 1.8%, so you need meaningful edge to have a real business).

What I learned the hard way

Edge bucket 0.22–0.25 was consistently negative in live data. The fee eats it. I was entering trades that looked like edge but weren't, once fees were accounted for. Raising the minimum edge from 0.22 to 0.26 cut roughly 40% of entries but turned the PnL positive.

Re-entries after SL: disabled. 37 re-entries in the first day generated −$16.71. The model was still "convinced" but the market had already told me I was wrong.

Conviction scoring

Not all edge-positive entries are equal. I score each potential entry 0–1:

score = 0.30×edge_norm + 0.25×upside_norm + 0.20×drift_norm + 0.15×time_norm + 0.10
  • edge_norm: edge / min_edge (capped at 1)
  • upside_norm: (1 − ask_px) / 0.40 — how much room to TP
  • drift_norm: confirmed momentum from slot open
  • time_norm: seconds remaining (longer window = more time for price to move)

Below 0.62 conviction: skip. Position sizing is tiered: $25 / $40 / $60 by tier (0.62–0.70 / 0.70–0.85 / ≥0.85).

Entry filters beyond edge

  • Min drift: 0.12% from slot open. Don't enter a market that hasn't moved — the model overestimates probability when BTC is flat.
  • Min price: 0.35 — very cheap shares have high variance and the SL fires frequently at noise levels.
  • Min seconds left: 60 — at <60s the TP at 0.97 is unreachable for most entries.
  • Max seconds left: 270 — don't enter in the first 10 minutes of the slot (slot_too_fresh).
  • Late-entry penalty: for entries with <400s left, required edge scales up proportionally.

Position management — the stack

Evaluated in this order every 3 seconds:

  1. TP at 0.97 — exit immediately
  2. Time-stop — if age > 240s and price hasn't moved ≥3% from entry, close. Dead positions waste slot time.
  3. Break-even — if HWM ≥ entry × 1.05, move SL to entry. A trade that reached +5% should never close negative.
  4. Lock-profit — if HWM ≥ entry × 1.10, floor SL at entry × 1.03. Minimum 3% locked.
  5. SL — dynamic by price: 15% for mid-range entries, 10% for expensive (0.60–0.85), 8% for high-prob (≥0.85).
  6. Trailing — 8% from HWM, activates after ≥8% gain. Protects the peak without cutting winners early.

Directional block and circuit breaker

After any SL in a (slot, direction) pair: block re-entry in that direction for the rest of the slot. This is cross-market too — BTC and ETH on the same 15m timestamp are highly correlated. A Down SL on BTC blocks Down entries on ETH for that slot.

Circuit breaker: ≥2 SLs in the same direction within 45 minutes → block that direction for 30 minutes.

Backtest reality

The Polymarket API returns limited historical data (~18–22 closed slots). With current parameters (MIN_EDGE=0.26, MIN_CONVICTION=0.62, MIN_DRIFT=0.12%) the main rejection reason is drift_too_low — BTC/ETH are sideways most of the time. The bot is very selective.

3 trades from 18 slots in the last backtest: 100% win rate, +$78 total. Small sample — meaningless for win rate estimation, but useful to confirm the plumbing works and sizing makes sense.

What I'd want feedback on

The conviction formula is hand-tuned. I used bucket analysis on ~200 live trades to weight the components, but there's no guarantee the weights generalize. Has anyone used Bayesian optimization or simple grid search to calibrate something like this without overfitting?

Also curious if anyone else is running models on these markets — the Black-Scholes assumption of constant intra-slot volatility is obviously wrong (news events, liquidations), but it's a useful baseline.

reddit.com
u/CommercialPurple3490 — 8 days ago

Built an AI auto-tuner for my Polymarket bot that reads live BTC market regime before adjusting parameters — sharing the approach

Following up on my previous post about the bot itself. This week I built something on top of it that I found interesting enough to share.

The problem

The bot has ~12 tunable parameters (min edge, trailing stop activation, conviction threshold, etc.). I was adjusting them manually after reviewing trade history. That works, but it's reactive — you're optimizing for what already happened, not what the market is doing right now.

What I built

An auto-tuner that runs on a daily cron (06:00 UTC) and does this:

  1. Pulls the last 48h of closed trades from SQLite and computes performance buckets (PnL by edge range, by exit reason, by hour)
  2. Fetches live BTC candles from Binance (50×1h + 32×15m) and computes:
    • ATR as % of price (1h and 15m)
    • Volatility regime: LOW / MEDIUM / HIGH
    • Momentum over 4h and 24h
    • Volume ratio (recent 4h avg vs 24h baseline)
    • Trend classification: BULLISH / BEARISH / RECOVERING / FADING / NEUTRAL
  3. Sends both the historical metrics AND the live market context to Claude (Haiku) with a prompt that includes forward-looking rules — e.g. "in LOW volatility, raise MIN_EDGE to filter noise; in HIGH volatility, tighten trailing"
  4. Validates the suggested values against hard bounds, applies them to .env, restarts the service
  5. Sends an email with the full reasoning, what changed, and the market regime snapshot

Example output from today

BTC was at ~$81k, ATR-15m at 0.22%, regime LOW, trend BEARISH (-1.9% in 24h).

Claude's suggestions (all applied in dry-run):

  • POLY_MIN_EDGE: 0.22 → 0.36 (filter out noise entries in tight markets)
  • POLY_MAX_SECONDS_LEFT: 240 → 220 (avoid late entries in compressed windows)
  • POLY_TRAILING_ACTIVATION_PCT: 0.08 → 0.12 (TP at 0.97 is the realistic exit anyway)
  • POLY_MIN_CONVICTION: 0.55 → 0.60 (skip marginal setups in choppy conditions)

The reasoning it generated was actually coherent — it tied each change back to a specific regime characteristic, not just the historical bucket.

What I'd like feedback on

  • Is this kind of "regime-aware parameter switching" a known pattern in algo trading? Curious if there's literature or common approaches I should be looking at.
  • The market context is currently just price/ATR/momentum/volume. What else would you add? Funding rate? OI? Implied vol proxy?
  • Daily cadence feels right for now, but wondering if intraday regime shifts (e.g. pre/post US session) would justify more frequent runs — or if that's just overfitting noise.

Happy to discuss the technical side. The prompt engineering for the parameter suggestions is the part I'm least confident about — it works, but it feels fragile.

reddit.com
u/CommercialPurple3490 — 16 days ago

Built an automated trading bot for Polymarket BTC/ETH 15min markets — sharing my journey &amp; looking for feedback

Hey everyone,

I've been building a trading bot for Polymarket's BTC and ETH 15-minute up/down markets. Here's the honest recap.

How it evolved:

  • Started with no filters, almost no logic — results were rough
  • Built a backtester and kept it in sync with the live engine on every change
  • Added fair value estimation, entry filters, conviction scoring for position sizing, and adaptive exits (trailing stop, time-based stall exits)
  • Every change goes through backtest before touching real funds

Test numbers so far:

  • 130 total trades
  • 50% win rate
  • ~+$18.88 net P&L

Still in testing mode, but the logic is holding up.

What I'd love input on:

  1. ETH vs BTC 15min — Is ETH liquidity/spread comparable to BTC, or noticeably worse in your experience?
  2. Correlation risk — BTC and ETH slots move together a lot. How do you think about that exposure when trading both simultaneously?
  3. Market hours — Any times of day where 15min markets feel more predictable (or more random)?

Happy to discuss the technical side. Strategy stays private, but the engineering is fair game. AMA.

reddit.com
u/CommercialPurple3490 — 18 days ago