Put-Call Pararity and Box Spread Arbitrage

Put-call parity is the no-arbitrage relationship linking a call, a put, the underlying, and the risk-free rate at a single strike and expiry. Violations imply conversion or reversal arbitrage; combinations across strikes create box spreads — synthetic risk-free loans embedded in the options chain. These are among the cleanest arbitrages in quantitative finance, but they are fought over by professional market makers with microsecond latency. This article states the math precisely, shows how box spreads work, and explains when retail or slow quant capital can still harvest dislocations.

Put-call parity

For European options on a non-dividend-paying underlying:

C - P = S - K × exp(-rT)
SymbolMeaning
CCall price
PPut price
SSpot price
KStrike
rRisk-free rate
TTime to expiry

Conversion: buy stock, buy put, sell call → locks in K at expiry. If the package costs less than K×e^{-rT}, arbitrage profit.

Reversal: sell stock (short), buy call, sell put → synthetic short stock. If the package credits more than K×e^{-rT}, arbitrage profit.

American options and dividends modify the bounds (early exercise premium on calls, dividend adjustments). See Black-Scholes for the continuous-time derivation and Greeks for how parity failures show up as delta-neutral packages with non-zero carry.

import numpy as np

def parity_violation_bps(call, put, spot, strike, rate, ttm_years):
    """Positive = call rich (sell call, buy put, buy stock)."""
    synthetic_fwd = call - put + strike * np.exp(-rate * ttm_years)
    return (synthetic_fwd - spot) / spot * 10_000

# violation_bps > +transaction_cost → reversal arb
# violation_bps < -transaction_cost → conversion arb

The box spread

A box is long a call spread and long a put spread at the same strikes:

Box(K1, K2) = Long Call(K1) + Short Call(K2) + Long Put(K2) + Short Put(K1)

Payoff at expiry is always K2 - K1 regardless of spot. By put-call parity, the box price should equal (K2 - K1) × exp(-rT). If the market box trades cheap, you buy a synthetic bond; if expensive, you sell one.

box_price ≈ (K2 - K1) × exp(-rT)
implied_rate = -ln(box_price / (K2 - K1)) / T

Box spreads are used by:

  • Arbitrage desks — to earn implied repo rates when box implied rate ≠ funding rate
  • Borrowers/lenders — synthetic financing without touching the stock loan market
  • Market makers — to hedge pin risk around strikes into expiry

Where dislocations come from

Parity should hold exactly in theory. In practice, violations arise from:

SourceEffectTypical size
Bid-ask on four legsApparent violation within spread5-50 bps
Hard-to-borrow stockPuts rich, calls cheap on reversals10-500+ bps
Dividend uncertaintyForward price mis-estimatedVariable
Early exercise (American)Call floor above parityPennies to dollars
Stale quotesPhantom arb in backtestsMeaningless
Pin risk into expiryBox prices distort near strikesLast few days
Regulatory capitalSome legs capital-intensiveStructural

The actionable arb is when violation exceeds four-leg transaction costs + borrow fee + margin cost and persists for long enough to execute. On liquid index options (SPX, SPY), violations inside the spread are noise. On single names with high borrow, reversals can persist for days.

Execution: why paper arb dies live

A four-leg options arb requires:

  1. Simultaneous fill on all legs — legging risk is the main killer
  2. Margin — short options and stock borrow tie up capital; ROE may be 2-5% annualized

on a "risk-free" trade

  1. Assignment risk — American exercise on short calls around ex-dividend dates
  2. Stock borrow — reversal requires short stock; hard-to-borrow names have fees that

eat the edge (see short selling mechanics)

Professional desks use combo orders (exchange-defined spreads) to guarantee all-or-nothing fills. Retail without combo access faces legging risk on every attempt.

Box spread as financing

In 2019-2021, retail traders famously used SPX box spreads via IBKR as synthetic high-yield loans when box implied rates exceeded T-bills. The trade:

  • Buy box below par → receive K2-K1 at expiry, pay less now → implied borrowing
  • ROE depends on margin treatment (portfolio margin vs Reg T)

Risks that ended some participants:

  • Assignment on short calls before expiry
  • Margin calls if SPX moves and short legs are margined incorrectly
  • Broker policy changes — brokers can restrict box spread strategies
  • Tax treatment — may differ from simple interest income

This is classical arbitrage in structure but operational risk in practice.

Monitoring parity in a quant stack

A systematic monitor scans the options chain for parity violations:

def scan_parity(chain: list[dict], spot: float, rate: float, ttm: float,
                min_bps: float = 15) -> list[dict]:
  """chain: list of {strike, call_bid, call_ask, put_bid, put_ask}"""
    opps = []
    for row in chain:
        K = row['strike']
        # Conservative: use ask for long legs, bid for short
        rev_profit = (row['call_bid'] - row['put_ask']
                      + K * np.exp(-rate * ttm) - spot)
        conv_profit = (spot - row['call_ask'] + row['put_bid']
                       - K * np.exp(-rate * ttm))
        for side, p in [('reversal', rev_profit), ('conversion', conv_profit)]:
            bps = p / spot * 10_000
            if bps > min_bps:
                opps.append({'strike': K, 'side': side, 'bps': bps})
    return opps

Filter for conservative fill prices (bid/ask, not mid). Require persistence — snapshot violations that disappear in 100ms are not tradable. Log borrow fees for reversals.

Connection to volatility trading

Put-call parity links the volatility surface to forward prices. If calls and puts at the same strike imply different implied vols (vol skew), parity still holds on prices — but the skew tells you about tail demand. Volatility arbitrage desks use parity-consistent packages (straddles, risk reversals) rather than naked directional options.

A risk reversal (long call, short put, delta-hedged) is effectively a synthetic forward; its mispricing vs the stock forward is a parity-relative trade, not a vol bet.

Key takeaways

  • Put-call parity: C - P = S - K×e^{-rT}; violations imply conversion/reversal arb
  • Box spreads synthesize risk-free payoff K2-K1; price implies a financing rate
  • Real arb requires four-leg execution, borrow availability, and margin ROE analysis
  • Bid-ask noise creates phantom violations — use conservative prices and persistence filters
  • Box spread financing trades carry assignment, margin, and broker-policy risks
#put-call parity #box spread #options arbitrage #conversion reversal #synthetic positions