Resolution Timing Arbitrage: Exploiting Cross-Platform Settlement Asynchronicity
Resolution Timing Arbitrage: Exploiting Cross-Platform Settlement Asynchronicity
Executive Summary
When the same event trades on multiple prediction market platforms, the resolution timing is rarely synchronized. One venue may settle hours, days, or even weeks before another—creating a window where an informed trader knows the outcome while positions remain open elsewhere. This is resolution timing arbitrage, and it represents one of the most persistent yet underappreciated edges in prediction market microstructure.
This article provides a quantitative framework for:
- Identifying timing arbitrage opportunities across Polymarket, Kalshi, and other venues
- Modeling the expected value of cross-platform latency exploitation
- Building monitoring systems to detect resolution announcements in real-time
- Managing the counterparty and operational risks inherent in settlement delays
By the end, you'll have working code for timing arbitrage detection and a decision matrix for when to exploit—or avoid—these edges.
Core Concept
The Settlement Latency Window
Prediction markets resolve through diverse mechanisms with varying speeds:
| Platform | Typical Resolution Time | Settlement Mechanism | Notification Latency | |----------|------------------------|---------------------|---------------------| | Polymarket | 2-48 hours post-event | UMA Optimistic Oracle | 1-5 minutes (Discord/Twitter) | | Kalshi | 1-7 days post-event | Internal + CFTC oversight | 5-30 minutes (Email/API) | | Axiom | 1-24 hours post-event | UMA-based | 1-10 minutes (On-chain events) | | Betfair | Immediate to 24 hours | Exchange matching engine | Real-time (Streaming API) | | Crypto sportsbooks | Immediate to 48 hours | Automated oracle feeds | 1-15 minutes |
The settlement latency window (SLW) is the time between:
- The first authoritative resolution (outcome becomes knowable)
- The final platform settlement (all positions closed)
During this window, traders with faster information pipelines can:
- Exit winning positions at pre-resolution prices
- Enter contrarian positions on lagging platforms
- Hedge cross-platform exposure with near-certain outcomes
The Arbitrage Value Equation
The expected value of a timing arbitrage opportunity can be modeled as:
EV = (P × S × D) - (C × T) - R
Where:
- P = Probability of successful information edge (0.0-1.0)
- S = Size of position that can be executed
- D = Price delta between platforms (normalized to 0.0-1.0)
- C = Capital cost per unit time (including opportunity cost and funding)
- T = Expected time to full settlement
- R = Risk-adjusted cost of adverse selection or platform intervention
A simplified Timing Arbitrage Score (TAS) for rapid assessment:
TAS = (D × √S) / (T × σ)
Where σ represents the volatility of the underlying event (higher volatility = more noise, harder to exploit).
Information Asymmetry Sources
Timing edges emerge from several structural factors:
- Oracle Diversity: Platforms using different resolution sources (primary vs. secondary reporting)
- Dispute Windows: UMA-based markets have 48-96 hour dispute periods before finalization
- Manual Review: Human oversight for edge cases creates unpredictable delays
- Time Zone Effects: Operational teams in different geographic regions
- Technical Latency: API polling intervals, webhook delivery, and database propagation
Worked Example
Scenario: The 2024 Election Resolution Cascade
Consider the 2024 U.S. Presidential election results as a canonical timing arbitrage case:
Event Timeline:
- Nov 5, 11:47 PM ET: Major networks call Pennsylvania for Candidate A
- Nov 5, 11:52 PM ET: Mathematical elimination—Candidate B cannot reach 270 electoral votes
- Nov 6, 12:15 AM ET: Polymarket resolution proposal submitted (UMA oracle)
- Nov 6, 12:47 AM ET: Kalshi trading suspended pending resolution review
- Nov 6, 2:30 AM ET: UMA dispute window expires, Polymarket settles
- Nov 6, 9:00 AM ET: Kalshi official resolution and settlement
Arbitrage Opportunity Window:
| Time | Platform | Action | Price | Implied Edge | |------|----------|--------|-------|-------------| | 11:52 PM | Polymarket | Buy YES | $0.94 | 6% | | 12:15 AM | Axiom | Buy YES | $0.96 | 4% | | 2:30 AM | Kalshi | Still trading | $0.97 | 3% | | 9:00 AM | All platforms | Settled at $1.00 | — | — |
Quantitative Analysis:
A trader with $500,000 capital and 15-minute information latency could have:
Position Size: $500,000
Average Entry: $0.955
Settlement Price: $1.00
Gross Profit: $500,000 × (1.00 - 0.955) = $22,500
Capital Cost (9.25 hours @ 8% APR): $500,000 × 0.08 × (9.25/8760) = $42
Expected Value: $22,500 - $42 - $500 (risk buffer) = $21,958
ROI: 4.4% in <24 hours
Annualized ROI: ~1,600% (if repeatable)
This represents a TAS of 7.2 (highly favorable) assuming σ=0.05.
Implementation Notes
Real-Time Resolution Detection Pipeline
Building a timing arbitrage system requires sub-minute detection of resolution events. Here's a production-ready monitoring architecture:
#!/usr/bin/env python3
"""
Resolution Timing Arbitrage Detector
Monitors multiple platforms for settlement events and cross-references prices
"""
import asyncio
import json
import os
from dataclasses import dataclass
from datetime import datetime, timedelta
from typing import Dict, List, Optional
import aiohttp
import websockets
@dataclass
class MarketPosition:
platform: str
market_id: str
yes_price: float
no_price: float
liquidity: float
last_updated: datetime
@dataclass
class ResolutionEvent:
platform: str
market_id: str
outcome: str
confidence: float
detected_at: datetime
source: str # 'websocket', 'polling', 'manual'
class TimingArbitrageDetector:
def __init__(self):
self.positions: Dict[str, List[MarketPosition]] = {}
self.resolution_cache: Dict[str, ResolutionEvent] = {}
self.arbitrage_threshold = 0.03 # 3% minimum edge
async def poll_polymarket(self) -> List[MarketPosition]:
"""Poll Polymarket API for market data"""
async with aiohttp.ClientSession() as session:
async with session.get(
"https://gamma-api.polymarket.com/markets",
params={"active": "true", "closed": "false"}
) as resp:
data = await resp.json()
return [
MarketPosition(
platform="polymarket",
market_id=m["conditionId"],
yes_price=float(m.get("outcomePrices", [0, 1])[1]),
no_price=float(m.get("outcomePrices", [1, 0])[0]),
liquidity=float(m.get("volume", 0)),
last_updated=datetime.utcnow()
)
for m in data
]
async def poll_kalshi(self) -> List[MarketPosition]:
"""Poll Kalshi API for market data (requires auth)"""
api_key = os.environ.get("KALSHI_API_KEY")
async with aiohttp.ClientSession() as session:
async with session.get(
"https://trading-api.kalshi.com/v1/markets",
headers={"Authorization": f"Bearer {api_key}"}
) as resp:
data = await resp.json()
return [
MarketPosition(
platform="kalshi",
market_id=m["ticker"],
yes_price=m.get("yes_ask", 0) / 100,
no_price=m.get("no_ask", 0) / 100,
liquidity=m.get("volume", 0),
last_updated=datetime.utcnow()
)
for m in data.get("markets", [])
]
async def monitor_twitter_resolution(self, keywords: List[str]):
"""Monitor Twitter/X for resolution announcements"""
# Note: Requires Twitter API v2 access
# This is a simplified implementation
pass
def calculate_arbitrage_opportunity(
self,
market_pair: List[MarketPosition],
resolved_outcome: str
) -> Optional[Dict]:
"""
Calculate if a timing arbitrage exists
Returns opportunity details if edge > threshold
"""
if len(market_pair) < 2:
return None
resolved_platform = None
unresolved_platforms = []
for pos in market_pair:
market_key = f"{pos.platform}:{pos.market_id}"
if market_key in self.resolution_cache:
resolved_platform = pos
else:
unresolved_platforms.append(pos)
if not resolved_platform or not unresolved_platforms:
return None
opportunities = []
for unresolved in unresolved_platforms:
# Calculate price delta
if resolved_outcome == "yes":
delta = 1.0 - unresolved.yes_price
action = "buy_yes"
entry = unresolved.yes_price
else:
delta = 1.0 - unresolved.no_price
action = "buy_no"
entry = unresolved.no_price
if delta > self.arbitrage_threshold:
ev = self._calculate_ev(
position_size=min(10000, unresolved.liquidity * 0.1),
entry_price=entry,
delta=delta
)
opportunities.append({
"action": action,
"target_platform": unresolved.platform,
"resolved_platform": resolved_platform.platform,
"entry_price": entry,
"expected_exit": 1.0,
"delta": delta,
"position_size": min(10000, unresolved.liquidity * 0.1),
"expected_value": ev,
"timestamp": datetime.utcnow().isoformat()
})
return opportunities[0] if opportunities else None
def _calculate_ev(
self,
position_size: float,
entry_price: float,
delta: float,
time_to_settlement: float = 24, # hours
capital_cost_annual: float = 0.08
) -> float:
"""Calculate expected value of timing arbitrage"""
gross_profit = position_size * delta
capital_cost = position_size * capital_cost_annual * (time_to_settlement / 8760)
risk_buffer = position_size * 0.001 # 10bps risk adjustment
return gross_profit - capital_cost - risk_buffer
async def run_monitoring_loop(self):
"""Main monitoring loop"""
while True:
try:
# Poll all platforms
polymarket_data = await self.poll_polymarket()
# kalshi_data = await self.poll_kalshi() # Uncomment with valid API key
# Group by market correlation (simplified—would use semantic matching)
# For demonstration, assume markets are pre-mapped
print(f"[UTC {datetime.utcnow()}] Polled {len(polymarket_data)} markets")
await asyncio.sleep(30) # 30-second polling interval
except Exception as e:
print(f"Error in monitoring loop: {e}")
await asyncio.sleep(60)
if __name__ == "__main__":
detector = TimingArbitrageDetector()
asyncio.run(detector.run_monitoring_loop())
Cross-Platform Market Mapping
The most challenging aspect of timing arbitrage is market correlation detection—determining when two markets on different platforms represent the same underlying event. Approaches include:
- Semantic Matching: NLP-based comparison of market titles and descriptions
- Keyword Clustering: Shared entities (candidates, teams, companies, countries)
- Resolution Source Alignment: Markets referencing the same oracle source
- Manual Curation: Maintaining a mapping database for high-volume events
Execution Considerations
Once an opportunity is detected, execution speed becomes critical:
| Factor | Impact | Mitigation | |--------|--------|------------| | API latency | 100-500ms | WebSocket feeds, colocation | | Rate limiting | Throttling | Exponential backoff, multiple keys | | Position limits | Reduced size | Multiple sub-accounts | | Withdrawal delays | Capital trapped | Pre-funded accounts on all platforms |
Failure Modes / Common Mistakes
1. False Resolution Signals
Not all early announcements are authoritative. Common traps:
- Projected results: News organizations calling races before 100% counted
- Conditional resolutions: "Assuming no recount" settlements that get disputed
- Test environments: Staging systems leaking false signals
Mitigation: Require multiple independent confirmations before acting.
2. Dispute Window Risk (UMA Markets)
UMA-based markets have a 48-96 hour dispute window. A "resolved" market can revert:
Case Study: Market resolved YES at 2:00 AM
Trader buys NO at $0.02 on lagging platform
Dispute raised at 10:00 AM (legitimate ambiguity found)
Market reverts to unresolved
Final resolution: YES (original outcome stood)
Result: 100% loss on NO position
Mitigation: Only exploit timing edges after the dispute window closes, or size positions to account for revert probability.
3. Platform Intervention
Platforms may void trades or suspend markets when timing arbitrage is detected:
- Kalshi: CFTC-regulated, can cancel "clearly erroneous" trades
- Polymarket: UMA governance can modify resolutions
- Crypto sportsbooks: Often reserve right to void suspicious activity
Mitigation: Diversify across platforms; never exceed 5% of daily volume on any single venue.
4. Adverse Selection in Fast Markets
When you're buying at $0.94 after a resolution signal, you may be trading against:
- Insiders with better information
- Automated systems with faster feeds
- Platform operators themselves
Mitigation: Analyze order book depth; if your entry moves the market significantly, the edge may already be gone.
Checklist
Before executing a timing arbitrage strategy:
- [ ] Confirmed resolution source is authoritative (not projection/estimate)
- [ ] Verified dispute window has closed (for UMA markets)
- [ ] Checked position limits won't restrict intended size
- [ ] Confirmed withdrawal capability on target platform
- [ ] Analyzed order book depth for slippage estimation
- [ ] Calculated TAS > 2.0 (favorable edge threshold)
- [ ] Set up automated position sizing (don't exceed 10% of liquidity)
- [ ] Tested API endpoints within last 24 hours
- [ ] Verified capital is pre-funded on all target platforms
- [ ] Set stop-loss for case of resolution reversal
Sources + Further Reading
Platform Documentation
- UMA Optimistic Oracle Technical Specification
- Polymarket API Documentation
- Kalshi Trading API Reference
Academic Research
- "The Market Microstructure of Prediction Markets" — Wolfers & Zitzewitz (2004)
- "Arbitrage and Efficiency in Event Markets" — Crosetto & Filippin (2016)
- "Information Aggregation in Prediction Markets" — Chen et al. (2021)
Industry Analysis
- Bloomberg: "The $100 Million Race to Predict the Future" (2024)
- FT Alphaville: "Prediction Markets and the Wisdom of Crowds" (2023)
- Kalshi Blog: "How We Settle Markets" (2024)
Related SettleRisk Resources
- Oracle Governance Risk Framework
- Resolution Infrastructure Deep Dive
- UMA Whale Concentration Analysis
This article is for educational purposes only. Timing arbitrage carries significant risk of loss, and past performance does not guarantee future results. Always conduct your own research and never trade with capital you cannot afford to lose.
Get weekly risk analysis in your inbox
Market risk scores, emerging dispute patterns, and settlement delay trends — delivered every Monday.