Polymarket markets aren't isolated. "Will X win the primary" and "will X win the general" aren't independent events - they're logically linked. When linked markets are priced inconsistently with each other, that inconsistency is arbitrage, and it's detectable with the same graph technique used for decades in currency exchange arbitrage.
The core idea
In FX arbitrage, you build a graph where currencies are nodes and exchange rates are edges, then look for a cycle where multiplying the rates around the loop gives you more money than you started with. A negative cycle in log-space (via Bellman-Ford) finds it.
Prediction markets map onto the same structure:
- Nodes = specific outcomes ("X wins primary," "X wins general," "Y wins general")
- Edges = the implied relationship between two outcomes' probabilities - logical implication, mutual exclusivity, or a statistically estimated conditional link
- Edge weight = -log(implied conditional probability), same transform used in FX arbitrage graphs
A negative cycle means the market's combined pricing is internally inconsistent - the equivalent of an arbitrage loop in currency markets.
Building the graph
import networkx as nx
G = nx.DiGraph()
# Each edge: implied conditional probability between two market outcomes
# weight = -log(p), so a negative cycle = mispricing
G.add_edge("X_wins_primary", "X_wins_general", weight=-math.log(p_implied))
G.add_edge("X_wins_general", "X_wins_primary", weight=-math.log(1/p_implied))
# Bellman-Ford naturally detects negative cycles
try:
nx.find_negative_cycle(G, source="X_wins_primary")
# cycle found → mispricing exists
except nx.NetworkXError:
pass # no arbitrage detected
The interesting engineering isn't the algorithm - Bellman-Ford is 70 years old. It's everything around it:
The actual hard parts
- Edge construction. Logical implication edges (mutually exclusive outcomes, "wins primary → can win general") are easy. Statistically-estimated edges (correlation between two only loosely related markets) are where false positives live - a "negative cycle" built on a shaky correlation isn't real arbitrage, it's noise.
- Real-time graph maintenance. Prices move continuously; the graph needs edge weights updated on every relevant tick, not rebuilt from scratch - otherwise you're always finding yesterday's arbitrage.
- Execution risk between legs. Finding a negative cycle tells you a snapshot was inconsistent. Actually capturing it means executing multiple legs before the market corrects - the gap between detection and fill is where backtested arbitrage dies in live trading.
- Correlation ≠ causation edges. The riskiest part of this whole approach is including an edge that looks statistically justified but isn't logically guaranteed - that turns "arbitrage" into "correlated bet," which is a very different risk profile.
Where this actually helps
Even without fully automating execution, this graph gives you something simpler and still valuable: a live map of which markets are pricing inconsistently relative to each other, which is useful signal on its own a mispricing worth investigating manually, even before you trust it enough to automate.
Top comments (0)