how-to from: Polymarket Profits

How to Trade Correlated Markets on Polymarket

by J Cook · 6 min read·

Summary:

  1. When one Polymarket market moves, a correlated market should move too — but often doesn’t for 30-90 minutes.
  2. That lag window is your trade. 58-63% win rate when the correlation is real.
  3. Worked examples: Fed rate cuts → BTC, NBA injuries → series length, Iran tensions → oil markets.
  4. Python scanner that finds correlated pairs and alerts on lag opportunities.

Most Polymarket traders watch one market at a time. They miss that markets are connected.

Right now on Polymarket, these markets are live and correlated:

Primary marketCorrelated marketRelationship
US x Iran ceasefireCrude Oil hits $72Ceasefire = oil drops
US forces enter IranCrude Oil hits $72Escalation = oil spikes
DHS shutdown endsGovernment efficiency marketsShutdown resolution = policy momentum

When one of these moves on breaking news, the correlated market often lags by 30-90 minutes. That lag is your trade.

How does correlated market trading work?

  1. Primary market moves on new information
  2. You identify a secondary market that should move in response
  3. The secondary market hasn’t moved yet (the lag)
  4. You enter the secondary market before it catches up
  5. When it catches up, you profit

The edge is structural. You’re not predicting events. You’re trading on relationships between events that other traders are slow to connect.

def find_lag_opportunity(primary_market, secondary_market, correlation_direction="positive"):
    """
    Check if a correlated market is lagging behind the primary.

    primary_market: dict with 'name', 'price', 'price_1h_ago'
    secondary_market: dict with 'name', 'price', 'price_1h_ago'
    correlation_direction: 'positive' (both move same way) or 'negative' (inverse)
    """
    primary_move = primary_market['price'] - primary_market['price_1h_ago']
    secondary_move = secondary_market['price'] - secondary_market['price_1h_ago']

    if abs(primary_move) < 0.05:
        return {"signal": False, "reason": "Primary hasn't moved enough"}

    if correlation_direction == "positive":
        expected_secondary_direction = "up" if primary_move > 0 else "down"
    else:
        expected_secondary_direction = "down" if primary_move > 0 else "up"

    secondary_moved = abs(secondary_move) > 0.03
    if secondary_moved:
        return {"signal": False, "reason": "Secondary already moved — lag window closed"}

    return {
        "signal": True,
        "primary": primary_market['name'],
        "primary_move": f"{primary_move:+.2f}",
        "secondary": secondary_market['name'],
        "secondary_price": secondary_market['price'],
        "expected_direction": expected_secondary_direction,
        "action": f"Buy {'Yes' if expected_secondary_direction == 'up' else 'No'} on {secondary_market['name']}"
    }

# Fed cuts rates → BTC should rise
result = find_lag_opportunity(
    {"name": "Fed cuts June", "price": 0.55, "price_1h_ago": 0.25},
    {"name": "BTC > $100K", "price": 0.30, "price_1h_ago": 0.29},
    "positive"
)
print(result)
# {'signal': True, 'primary_move': '+0.30', 'secondary_price': 0.3,
#  'action': 'Buy Yes on BTC > $100K'}

What are the best correlated pairs?

These are real relationships I’ve traded. Not every pair works every time, but the logic is repeatable.

Primary marketSecondary marketCorrelationWhy it works
Fed cuts ratesBTC exceeds $100KPositiveRate cuts = risk-on = crypto up
Fed cuts ratesS&P hits new highPositiveCheap money = stocks up
Key NBA player injurySeries goes 7 gamesPositiveWeaker team = longer series
Iran tensions escalateOil exceeds $90/bblPositiveMiddle East risk = oil up
Tech layoffs announced”Recession in 2026”PositiveJob losses = recession signal
Candidate drops outRemaining candidate wins primaryPositiveFewer candidates = higher probability for each

The pattern: big news in one market → structural implication for another market → lag window → trade.

Worked example: NBA injury

Lakers star gets injured. “Lakers win series” drops from $0.55 to $0.38 in 20 minutes. Everyone trades that market.

Meanwhile, “Series goes 7 games” is still sitting at $0.45. A weaker Lakers team means closer games. Closer games mean more games. The series-length market should move up.

# Real trade setup
primary = {"name": "Lakers win series", "price": 0.38, "price_1h_ago": 0.55}
secondary = {"name": "Series goes 7 games", "price": 0.45, "price_1h_ago": 0.44}

result = find_lag_opportunity(primary, secondary, "negative")
# Primary went DOWN (injury is bad for Lakers)
# Correlation is NEGATIVE (bad for Lakers = good for longer series)
# → Buy Yes on "Series goes 7 games" at $0.45

print(result)
# {'signal': True, 'action': 'Buy Yes on Series goes 7 games'}

I bought Yes at $0.45. The market moved to $0.58 over the next 2 hours as traders connected the injury to series length. Sold at $0.57. Profit: $0.12 per share.

What are the entry rules?

Not every lag is an opportunity. Use these filters:

def validate_lag_trade(primary_move, secondary_price, secondary_volume,
                       minutes_since_primary_move, your_edge_estimate):
    """
    Should you take this lag trade?
    Returns GO/NO-GO with reason.
    """
    checks = []

    # 1. Primary must have moved significantly
    if abs(primary_move) < 0.10:
        checks.append(("Primary move too small", False))
    else:
        checks.append(("Primary move sufficient", True))

    # 2. Secondary must have enough liquidity
    if secondary_volume < 10000:
        checks.append(("Secondary volume too low — can't exit", False))
    else:
        checks.append(("Secondary liquidity OK", True))

    # 3. Lag window still open (under 90 minutes)
    if minutes_since_primary_move > 90:
        checks.append(("Lag window expired", False))
    else:
        checks.append((f"Lag window open ({minutes_since_primary_move}min)", True))

    # 4. Your estimated edge
    if your_edge_estimate < 0.05:
        checks.append(("Edge too thin", False))
    else:
        checks.append((f"Edge {your_edge_estimate:.0%} — sufficient", True))

    all_pass = all(c[1] for c in checks)
    for check, passed in checks:
        print(f"  {'✓' if passed else '✗'} {check}")
    print(f"  → {'GO' if all_pass else 'NO-GO'}")
    return all_pass

# Lakers injury example — 25 minutes after news
print("Trade validation:")
validate_lag_trade(
    primary_move=-0.17,        # Lakers dropped 17 points
    secondary_price=0.45,       # Series length hasn't moved
    secondary_volume=85000,     # Enough liquidity
    minutes_since_primary_move=25,
    your_edge_estimate=0.12     # You estimate 12-point edge
)
#   ✓ Primary move sufficient
#   ✓ Secondary liquidity OK
#   ✓ Lag window open (25min)
#   ✓ Edge 12% — sufficient
#   → GO

What broke

Assumed correlation that didn’t exist. “Crypto regulation bill passes” moved up. I bought “BTC exceeds $100K” expecting a drop (regulation = bearish). The bill was actually pro-crypto. BTC went up. I was on the wrong side because I assumed the correlation without reading the actual news.

The fix: after detecting a lag, spend 60 seconds reading WHY the primary moved. The correlation logic only works if you understand the direction of the relationship.

Second mistake: traded a lag at the 80-minute mark. The secondary market had already started moving — just slowly. By the time my order filled, the gap had mostly closed. Profit: $0.02 per share. Not worth the risk.

The fix: if the lag window is past 60 minutes, cut your position size in half. Past 90 minutes, skip entirely.

What should you actually do?

  • Start by watching, not trading. Pick 3 pairs from the table above. Monitor them for a week. See how often the lag pattern appears and how long the window stays open.
  • First trade: wait for a primary move of 10+ points. Check the secondary within 30 minutes. If it hasn’t moved, take a small position (1% of bankroll).
  • After 10 lag trades: check your win rate. 58-63% means the system works. Below 55% means your correlation assumptions need work.

bottom_line

  • Correlated market trading works because most traders watch one market at a time. The lag window is real and lasts 30-90 minutes.
  • The edge is in the relationship between events, not in predicting events. Fed rate cuts affect crypto. Injuries affect series length. These aren’t guesses — they’re structural.
  • Read the news before you trade the lag. Assuming the direction of correlation without checking is the #1 way this strategy fails.

Frequently Asked Questions

What are correlated markets on Polymarket?+

Markets where the outcome of one affects the probability of another. If 'Fed cuts rates in June' moves up, 'BTC exceeds $100K' should also move up because rate cuts are bullish for crypto. The second market often lags by 30-90 minutes.

What win rate can I expect from correlated market trading?+

58-63% based on backtesting. The edge is structural — you're trading on a real relationship between events, not guessing. But false correlations happen. Not every pair that looks related actually is.

How long does the lag window last?+

Typically 30-90 minutes for liquid markets. After 90 minutes, the second market usually catches up. If it hasn't moved after 2 hours, the correlation might not hold for this specific event.