How I automated value discovery in binary oil markets using Python, Yahoo Finance, and the Polymarket API
Why Prediction Markets?
Polymarket lets you trade on the probability of real‑world events. There are often inefficiencies—especially when fear or greed distorts prices. But manually checking dozens of contracts and calculating fair probabilities is tedious.
Yesterday, I noticed a juicy set of markets: What price will WTI Crude Oil hit in May 2026?
Dozens of binary options—touching $70, $80, $100, $115—each with a YES and NO price. The question was clear: where’s the value?
The Idea
Build a Python script that:
- Fetches live WTI spot price and OVX (oil volatility index) from Yahoo Finance,
- Pulls real‑time Polymarket odds directly from their API (no manual scraping!),
- Applies a touch‑barrier probability model (Brownian motion with zero drift) for the remaining days of the month,
- Compares model probabilities to market prices, and
- Recommends the best trades using the Kelly criterion for position sizing.
The result: every run reveals which contracts are overpriced or underpriced relative to a volatility‑based fair value.
The Model (in Plain English)
For a stock (or oil) that follows a random walk, the probability of hitting a lower barrier (K) within time (T) at volatility (\sigma) is:
[
P_{\text{hit}} = 2 \cdot \Phi\left( \frac{\ln(K/S_0)}{\sigma \sqrt{T}} \right)
]
- (S_0) = current price
- (\sigma) = annualised volatility (from OVX)
- (T) = time left (26 days → ~0.071 years)
For upside barriers we simply flip the ratio. This is a textbook “reflection principle” result. No drift assumption keeps it simple—and over a few weeks, drift is usually negligible compared to vol.
Why OVX?
OVX reflects the market’s expectation of 30‑day oil volatility. It’s the perfect input for a 26‑day touch probability.
Connecting to Polymarket (without pulling your hair out)
Polymarket’s Gamma API was a bit tricky: some endpoints return outcomePrices as a JSON string rather than an array. My first attempts threw “Invalid price format” errors.
The fix: check if the price field is a string, and if so, json.loads() it. After that, mapping questions like “Will WTI hit (LOW) $95?” to my labels (↓$95) was just a regex job:
pattern = r'hit\s*\(?(HIGH|LOW)\)?\s*\$(\d+)'
match = re.search(pattern, question, re.IGNORECASE)
From there, building a dictionary of live YES/NO prices is straightforward.
The Script Output (Real Example)
Running on May 5, 2026 with WTI at $104.08 and OVX at 78.6%, I got:
| Contract | P_model | P_market | Edge | Kelly Y | Kelly N | Signal |
|---|---|---|---|---|---|---|
| ↓$70 | 5.7% | 5.5% | +0.2% | 0.000 | 0.002 | fair value |
| ↓$80 | 21.1% | 23.5% | -2.4% | 0.000 | 0.031 | BUY NO (f*=0.031) |
| ↓$85 | 34.0% | 41.0% | -7.0% | 0.000 | 0.119 | BUY NO (f*=0.119) |
| ↓$90 | 49.9% | 57.5% | -7.6% | 0.000 | 0.151 | BUY NO (f*=0.151) |
| ↓$95 | 67.5% | 75.0% | -7.5% | 0.000 | 0.300 | BUY NO (f*=0.300) |
| ↓$100 | 85.2% | 90.5% | -5.3% | 0.000 | 0.357 | BUY NO (f*=0.357) |
| ↑$110 | 79.0% | 78.5% | +0.5% | 0.023 | 0.000 | BUY YES (f*=0.023) |
| ↑$115 | 63.4% | 60.5% | +2.9% | 0.074 | 0.000 | BUY YES (f*=0.074) |
What jumps out:
- The market overprices downside touch probabilities compared to even a high‑vol model. Contracts like ↓$95 and ↓$100 show a solid edge for buying NO.
- The upside contracts are slightly underpricing a rally — ↑$115 gives a small but positive edge.
- The Kelly fractions (f*) indicate that selling these overpriced insurance contracts could be a high‑conviction bet.
Why This Matters
- Automated edge detection – Run the script, see the mispricings instantly.
- Position sizing – The Kelly output keeps you from overbetting; you can scale down to half‑Kelly for safety.
- Live data – No more copying prices by hand or guessing vol.
- Extensible – Swap in different models, add more barriers, or integrate liquidity checks.
Try It Yourself
The full code is about 170 lines of Python (using yfinance, requests, scipy). I haven’t open‑sourced the repo yet, but I’m happy to share the script if you reach out.
Platforms I use:
- Preddy – great for discovering and tracking prediction market opportunities.
- Polymarket – the core prediction market where I trade these contracts.
(Full disclosure: these are referral links, but I use both platforms daily for my own trading.)
Let’s Discuss
Have you traded on Polymarket? How do you quantify edge?
I’d love to hear about your approaches—and whether you’re also seeing systematic overpricing of downside barriers.
Drop a comment below.
Happy (probabilistic) hunting! 🛢️
Top comments (1)
If this post gets 100 meaningful comments, I'll make the repo public. Let's use the thread to discuss edge in prediction markets — what's your favorite metric or model?