31 min read

> "In a market with many outcomes, the edge is not in predicting the winner --- it is in understanding the relationships between all the losers." --- Attributed to a professional sports bettor

Chapter 15: Multi-Outcome and Scalar Market Strategies

"In a market with many outcomes, the edge is not in predicting the winner --- it is in understanding the relationships between all the losers." --- Attributed to a professional sports bettor

Most of our discussion so far has focused on binary markets --- contracts that resolve to Yes or No. But many of the most interesting prediction markets have three, five, ten, or even hundreds of possible outcomes. Who will win the presidential nomination? Which team will win the championship? What range will GDP growth fall into? These multi-outcome markets and scalar markets present unique challenges and, crucially, unique opportunities that do not exist in simple binary settings.

This chapter builds on the foundational contract structures introduced in Chapter 4 and the trading frameworks developed in Chapters 13 and 14. We will develop a rigorous toolkit for extracting true probabilities from overround-laden prices, detecting arbitrage, constructing optimal portfolios across mutually exclusive outcomes, trading scalar distributions, and managing risk in these complex environments.


15.1 Multi-Outcome Markets: Structure and Opportunities

15.1.1 Review of Multi-Outcome Contract Structures

Recall from Chapter 4 that a multi-outcome market (also called a categorical market or winner-take-all market) consists of $n$ mutually exclusive and exhaustive contracts. Exactly one contract resolves to 1 (paying out), and all others resolve to 0. Examples include:

  • Election markets: "Who will win the 2028 presidential election?" with contracts for each candidate.
  • Sports futures: "Who will win the Super Bowl?" with a contract for each team.
  • Award markets: "Who will win Best Picture?" with a contract for each nominee.

If we denote the prices of the $n$ contracts as $p_1, p_2, \ldots, p_n$, the complete market constraint requires:

$$\sum_{i=1}^{n} p_i = 1$$

In a perfectly efficient market with no transaction costs, the prices would sum to exactly 1 and could be directly interpreted as probabilities. In practice, this almost never happens.

15.1.2 The Overround Problem

In real markets, prices typically sum to more than 1:

$$\sum_{i=1}^{n} p_i = 1 + \omega$$

where $\omega > 0$ is the overround (also called vig, juice, or margin). The overround represents the market operator's built-in profit margin. For example, in a three-horse race, you might see:

Horse Price Implied Probability
A 0.45 45%
B 0.35 35%
C 0.28 28%
Total 1.08 108%

Here the overround is $\omega = 0.08$ or 8%. Buying all three contracts guarantees spending $1.08 to win $1.00 --- a guaranteed loss of $0.08. This overround makes the raw prices unreliable as probability estimates and creates the first challenge we must address.

15.1.3 Why Multi-Outcome Markets Create Unique Opportunities

Multi-outcome markets offer several structural advantages over binary markets:

  1. More dimensions for mispricing: With $n$ outcomes, there are $n$ prices that must be internally consistent. The more outcomes, the more ways the market can be wrong.

  2. Relative value opportunities: Even if you cannot determine the absolute probability of any outcome, you may be able to identify that one outcome is overpriced relative to another.

  3. Constraint exploitation: The requirement that probabilities sum to 1 creates mathematical relationships that can be exploited when violated.

  4. Behavioral biases amplified: Longshot bias, favorite-longshot bias, and other behavioral effects are more pronounced when there are many outcomes.

  5. Liquidity fragmentation: With many outcomes, liquidity is spread thin, creating wider spreads and more frequent mispricings.

15.1.4 Identifying Mispricing Across Outcomes

The simplest form of mispricing detection in a multi-outcome market compares your estimated probabilities to the market's implied probabilities. Let $q_i$ be your estimated probability for outcome $i$ and $\hat{p}_i$ be the market's implied probability (after removing overround). The edge on outcome $i$ is:

$$\text{edge}_i = q_i - \hat{p}_i$$

But in multi-outcome markets, we must think more carefully. Since all probabilities must sum to 1, overestimating one outcome's probability necessarily means underestimating others. This interdependence is what makes multi-outcome markets simultaneously more complex and more rewarding.

A useful metric is the relative edge:

$$\text{relative\_edge}_i = \frac{q_i - \hat{p}_i}{\hat{p}_i}$$

This normalizes the edge by the baseline probability, making it easier to compare opportunities across outcomes with very different probabilities.


15.2 Extracting True Probabilities from Overround Markets

Before we can identify mispricings, we need to convert raw market prices (which include overround) into genuine probability estimates. This section covers four methods, each with different assumptions and properties.

15.2.1 Overround Calculation

Given prices $p_1, p_2, \ldots, p_n$, the overround is:

$$\omega = \sum_{i=1}^{n} p_i - 1$$

The overround percentage is often quoted as $\omega \times 100\%$. In practice:

  • Prediction markets (Polymarket, Kalshi): 1--5% typical overround
  • Sports betting markets: 2--15% depending on sport and market
  • Horse racing: 15--25% common in parimutuel pools

15.2.2 Method 1: Multiplicative (Proportional) Removal

The simplest approach divides each price by the sum of all prices:

$$\hat{p}_i^{\text{mult}} = \frac{p_i}{\sum_{j=1}^{n} p_j}$$

Assumption: The overround is distributed proportionally to each outcome's probability. A 50% chance outcome bears 5 times the absolute overround of a 10% chance outcome.

Pros: Simple, intuitive, always produces valid probabilities.

Cons: Tends to underestimate favorites and overestimate longshots if the overround is not truly proportional (which it usually is not).

15.2.3 Method 2: Additive (Equal) Removal

Subtract an equal amount from each price:

$$\hat{p}_i^{\text{add}} = p_i - \frac{\omega}{n}$$

Assumption: The overround is distributed equally across all outcomes.

Pros: Simple to compute.

Cons: Can produce negative probabilities for low-probability outcomes. If outcome $j$ has $p_j < \omega/n$, then $\hat{p}_j^{\text{add}} < 0$, which is nonsensical. This method is only appropriate when all outcomes have similar probabilities.

15.2.4 Method 3: Shin's Method

Shin (1991, 1993) developed a model that accounts for the presence of informed traders in the market. Shin's method assumes the bookmaker sets prices optimally given the existence of insider information. The key parameter $z$ represents the proportion of informed traders.

The Shin probabilities satisfy:

$$\hat{p}_i^{\text{Shin}} = \frac{\sqrt{z^2 + 4(1-z) \cdot \frac{p_i}{S} \cdot (S - p_i)} - z}{2(1-z)}$$

where $S = \sum_{j=1}^{n} p_j$ and $z$ is found by solving:

$$\sum_{i=1}^{n} \hat{p}_i^{\text{Shin}} = 1$$

In practice, $z$ is found numerically (e.g., via bisection or Newton's method).

Assumption: Overround is distributed more heavily on longshots because the bookmaker needs greater protection against informed traders on obscure outcomes.

Pros: Theoretically motivated, handles the favorite-longshot bias naturally, widely used in academic research.

Cons: More complex to implement, assumes a specific model of market microstructure.

15.2.5 Method 4: Power Method

The power method finds an exponent $k$ such that:

$$\sum_{i=1}^{n} p_i^k = 1$$

Then the true probabilities are:

$$\hat{p}_i^{\text{power}} = p_i^k$$

Since $\sum p_i > 1$, we need $k > 1$ to shrink the probabilities. The exponent $k$ is found numerically.

Assumption: The relationship between raw prices and true probabilities follows a power law. This distributes the overround in a non-linear way that removes more from extreme probabilities.

Pros: Flexible, empirically performs well, produces valid probabilities.

Cons: Less theoretical justification than Shin's method.

15.2.6 Comparison of Methods

The methods differ most dramatically for extreme probabilities:

Method Effect on Favorites Effect on Longshots
Multiplicative Slight underestimate Slight overestimate
Additive Moderate underestimate Strong overestimate or invalid
Shin Most accurate for favorites Reduces longshots significantly
Power Moderate adjustment Moderate adjustment

For serious quantitative work, Shin's method and the power method are generally preferred. The multiplicative method is a reasonable default when simplicity is needed.

15.2.7 Python Implementation

import numpy as np
from scipy.optimize import brentq

def overround(prices):
    """Calculate the overround from a set of prices."""
    return sum(prices) - 1.0

def multiplicative_removal(prices):
    """Remove overround proportionally."""
    total = sum(prices)
    return [p / total for p in prices]

def additive_removal(prices):
    """Remove overround equally from each outcome."""
    n = len(prices)
    omega = overround(prices)
    result = [p - omega / n for p in prices]
    # Check for negative values
    if any(r < 0 for r in result):
        print("Warning: Negative probabilities produced. "
              "Additive method inappropriate for this market.")
    return result

def shin_removal(prices):
    """Remove overround using Shin's method."""
    S = sum(prices)
    n = len(prices)

    def shin_prob(p_i, z, S):
        discriminant = z**2 + 4*(1-z) * (p_i/S) * (S - p_i)
        return (np.sqrt(discriminant) - z) / (2*(1-z))

    def objective(z):
        probs = [shin_prob(p, z, S) for p in prices]
        return sum(probs) - 1.0

    # z must be in (0, 1); search for root
    z_opt = brentq(objective, 1e-10, 0.999)
    probs = [shin_prob(p, z_opt, S) for p in prices]
    return probs, z_opt

def power_removal(prices):
    """Remove overround using the power method."""
    def objective(k):
        return sum(p**k for p in prices) - 1.0

    k_opt = brentq(objective, 1.0, 10.0)
    probs = [p**k_opt for p in prices]
    return probs, k_opt

# Example usage
prices = [0.45, 0.35, 0.28]
print(f"Overround: {overround(prices):.2%}")
print(f"Multiplicative: {multiplicative_removal(prices)}")
print(f"Additive: {additive_removal(prices)}")

shin_probs, z = shin_removal(prices)
print(f"Shin (z={z:.4f}): {[f'{p:.4f}' for p in shin_probs]}")

power_probs, k = power_removal(prices)
print(f"Power (k={k:.4f}): {[f'{p:.4f}' for p in power_probs]}")

The full implementation with visualization is in code/example-01-overround-removal.py.


15.3 Dutch Book Arguments and Arbitrage Detection

15.3.1 What Is a Dutch Book?

A Dutch book is a set of bets that guarantees a profit regardless of the outcome. The term originates from the gambling world, where "booking" refers to accepting bets and "Dutch" historically referred to a particular style of auction or negative connotation.

In the context of prediction markets, a Dutch book exists when the market prices are inconsistent --- specifically, when you can construct a portfolio that has a positive payoff in every possible state of the world.

Type 1 Dutch Book (Buyer's Dutch Book): If prices sum to less than 1:

$$\sum_{i=1}^{n} p_i < 1$$

Buy one unit of every outcome. You pay $\sum p_i < 1$ and receive exactly $1$ regardless of which outcome occurs. Profit = $1 - \sum p_i > 0$.

Type 2 Dutch Book (Seller's Dutch Book): If prices sum to more than 1:

$$\sum_{i=1}^{n} p_i > 1$$

Sell (short) one unit of every outcome. You receive $\sum p_i > 1$ and pay out exactly $1$. Profit = $\sum p_i - 1 > 0$.

15.3.2 Beyond Simple Sum Violations

In practice, simple sum-to-1 violations are rare in well-functioning markets. More interesting Dutch book opportunities arise from:

  1. Cross-market inconsistencies: The same event traded on different platforms with different prices.

  2. Bid-ask spread exploitation: Using the best bid on some outcomes and the best ask on others.

  3. Conditional market inconsistencies: When conditional and unconditional markets are inconsistent (covered more in Chapter 30).

  4. Stale prices: Some outcomes in a multi-outcome market update faster than others after news.

15.3.3 Detecting Dutch Book Opportunities

For a market with $n$ outcomes and prices $p_1, \ldots, p_n$:

Check 1 --- Sum Test: - If $\sum p_i^{\text{ask}} < 1$: Buyer's Dutch book exists (buy all at ask). - If $\sum p_i^{\text{bid}} > 1$: Seller's Dutch book exists (sell all at bid).

Check 2 --- Mixed Strategy: For each outcome $i$, you can choose to buy, sell, or ignore. The optimal Dutch book solves:

$$\max_{x_1, \ldots, x_n} \min_{j \in \{1,\ldots,n\}} \text{payoff if outcome } j \text{ occurs}$$

where $x_i > 0$ means buying $x_i$ units of contract $i$, $x_i < 0$ means selling $|x_i|$ units, and $x_i = 0$ means no position.

If outcome $j$ occurs, the payoff is:

$$\pi_j = -\sum_{i=1}^{n} x_i \cdot p_i^{(\text{direction})} + x_j$$

where $p_i^{(\text{direction})}$ is the ask price if $x_i > 0$ (buying) and the bid price if $x_i < 0$ (selling).

A Dutch book exists if and only if $\max \min_j \pi_j > 0$. This can be solved as a linear program.

15.3.4 The Linear Programming Formulation

We can formulate Dutch book detection as a linear program. Introduce variables $x_i^+$ (units bought) and $x_i^-$ (units sold) for each outcome $i$, and a variable $g$ representing the guaranteed profit:

$$\max \; g$$

subject to:

$$\forall j: \; x_j^+ - x_j^- - \sum_{i=1}^{n} (x_i^+ \cdot a_i - x_i^- \cdot b_i) \geq g$$

$$x_i^+, x_i^- \geq 0 \quad \forall i$$

where $a_i$ is the ask price and $b_i$ is the bid price for outcome $i$.

If the optimal $g > 0$, a Dutch book exists, and the optimal $x_i^+, x_i^-$ tell you exactly how to construct it.

15.3.5 Python Dutch Book Detector

import numpy as np
from scipy.optimize import linprog

def detect_dutch_book(asks, bids):
    """
    Detect Dutch book opportunities in a multi-outcome market.

    Parameters:
        asks: list of ask prices for each outcome
        bids: list of bid prices for each outcome

    Returns:
        dict with 'exists', 'profit', and 'positions'
    """
    n = len(asks)

    # Variables: [x1+, x1-, x2+, x2-, ..., xn+, xn-, g]
    # We maximize g, so minimize -g
    c = np.zeros(2*n + 1)
    c[-1] = -1  # minimize -g => maximize g

    # Constraints: for each outcome j
    # x_j+ - x_j- - sum_i(x_i+ * a_i - x_i- * b_i) >= g
    # Rearranged: -x_j+ + x_j- + sum_i(x_i+ * a_i - x_i- * b_i) + g <= 0
    A_ub = np.zeros((n, 2*n + 1))
    b_ub = np.zeros(n)

    for j in range(n):
        for i in range(n):
            A_ub[j, 2*i] = asks[i]      # coefficient of x_i+
            A_ub[j, 2*i+1] = -bids[i]   # coefficient of x_i-
        A_ub[j, 2*j] -= 1        # subtract x_j+ (the payout)
        A_ub[j, 2*j+1] += 1      # add x_j- (the payout obligation)
        A_ub[j, -1] = 1          # g

    # Bounds: x_i+, x_i- >= 0, g unrestricted
    bounds = [(0, None)] * (2*n) + [(None, None)]

    result = linprog(c, A_ub=A_ub, b_ub=b_ub, bounds=bounds, method='highs')

    if result.success and -result.fun > 1e-8:
        positions = {}
        for i in range(n):
            buy = result.x[2*i]
            sell = result.x[2*i+1]
            net = buy - sell
            if abs(net) > 1e-8:
                positions[i] = {'buy': buy, 'sell': sell, 'net': net}
        return {
            'exists': True,
            'profit': -result.fun,
            'positions': positions
        }
    else:
        return {
            'exists': False,
            'profit': 0,
            'positions': {}
        }

15.3.6 Practical Considerations

Dutch books in real markets are rare and fleeting because:

  1. Transaction costs: Fees, spreads, and slippage consume the arbitrage profit.
  2. Execution risk: By the time you execute all legs, prices may have moved.
  3. Capital requirements: Multi-leg positions tie up margin.
  4. Platform risk: Cross-platform arbitrage requires accounts and capital on multiple platforms.

The practical threshold is: a Dutch book is exploitable only if the guaranteed profit exceeds the total transaction costs of establishing all positions. In prediction markets with 2-5% fees per trade, you need significant price dislocations to profit.


15.4 Portfolio Optimization Across Outcomes

15.4.1 The Multi-Outcome Portfolio Problem

When you have identified mispricings across multiple outcomes in a market, you face a portfolio allocation problem: how much of your bankroll should you allocate to each mispriced outcome?

This is more subtle than the binary case because the outcomes are mutually exclusive. If you bet on outcome A and outcome B, at most one can win. This negative correlation is built into the structure and must be accounted for.

15.4.2 Return Structure

Consider a multi-outcome market with prices $p_1, \ldots, p_n$ and your estimated true probabilities $q_1, \ldots, q_n$. If you buy $f_i$ fraction of your bankroll on outcome $i$, your return if outcome $j$ wins is:

$$R_j = \frac{f_j}{p_j} - \sum_{i=1}^{n} f_i$$

The first term is the payout from the winning bet (you invested $f_j$ at price $p_j$, receiving $f_j / p_j$). The second term is the total amount invested across all outcomes.

Simplifying:

$$R_j = f_j \left(\frac{1}{p_j} - 1\right) - \sum_{i \neq j} f_i$$

15.4.3 Expected Return and Variance

The expected return is:

$$E[R] = \sum_{j=1}^{n} q_j R_j = \sum_{j=1}^{n} q_j \left[\frac{f_j}{p_j} - \sum_{i=1}^{n} f_i\right]$$

$$= \sum_{j=1}^{n} \frac{q_j f_j}{p_j} - \sum_{i=1}^{n} f_i$$

$$= \sum_{j=1}^{n} f_j \left(\frac{q_j}{p_j} - 1\right)$$

This is intuitive: each bet contributes proportionally to its edge $q_j/p_j - 1$.

The variance is more complex due to the mutual exclusivity:

$$\text{Var}(R) = \sum_{j=1}^{n} q_j R_j^2 - \left(\sum_{j=1}^{n} q_j R_j\right)^2$$

15.4.4 Kelly Criterion for Multiple Mutually Exclusive Outcomes

The Kelly criterion for a single binary bet extends to the multi-outcome case. We want to maximize the expected logarithm of wealth:

$$\max_{f_1, \ldots, f_n} \sum_{j=1}^{n} q_j \ln\left(1 + R_j\right)$$

subject to:

$$\sum_{i=1}^{n} f_i \leq B \quad \text{(budget constraint)}$$ $$f_i \geq 0 \quad \forall i \quad \text{(no short selling)}$$

where $B$ is the maximum fraction of bankroll to risk.

Substituting:

$$\max_{f_1, \ldots, f_n} \sum_{j=1}^{n} q_j \ln\left(1 + f_j \left(\frac{1}{p_j} - 1\right) - \sum_{i \neq j} f_i\right)$$

This is a concave optimization problem (the log of a linear function is concave, and a weighted sum of concave functions is concave) and can be solved numerically.

15.4.5 Simultaneous Kelly: The Analytic Insight

For the special case where we bet on all outcomes (which may be optimal when all are mispriced), there is an elegant characterization. Let $F = \sum f_i$ be the total fraction wagered. If outcome $j$ wins, the wealth ratio is:

$$W_j = 1 - F + \frac{f_j}{p_j}$$

The Kelly objective becomes:

$$\max \sum_{j=1}^{n} q_j \ln\left(1 - F + \frac{f_j}{p_j}\right)$$

Taking derivatives and setting to zero:

$$\frac{q_j}{p_j \left(1 - F + f_j/p_j\right)} = \lambda \quad \forall j \text{ where } f_j > 0$$

This yields:

$$1 - F + \frac{f_j}{p_j} = \frac{q_j}{\lambda p_j}$$

Summing over all outcomes:

$$n(1 - F) + F \cdot \frac{\sum p_i^{-1} p_i}{\cdots}$$

The algebra becomes intricate, but the key insight is that the optimal Kelly bet on outcome $j$ is:

$$f_j^* = p_j \left(\frac{q_j}{\lambda^* p_j} - 1 + F^*\right)$$

where $\lambda^*$ and $F^*$ are determined by the constraints. In practice, numerical optimization is the standard approach.

15.4.6 Python Multi-Kelly Optimizer

import numpy as np
from scipy.optimize import minimize

def multi_kelly(true_probs, market_prices, max_bet_fraction=0.5):
    """
    Compute Kelly-optimal allocation across mutually exclusive outcomes.

    Parameters:
        true_probs: your estimated probabilities (must sum to 1)
        market_prices: market prices (may sum to != 1)
        max_bet_fraction: maximum total fraction of bankroll to wager

    Returns:
        dict with optimal fractions and expected growth rate
    """
    n = len(true_probs)
    q = np.array(true_probs)
    p = np.array(market_prices)

    def neg_expected_log_growth(f):
        total_bet = np.sum(f)
        growth = 0.0
        for j in range(n):
            wealth_if_j = 1.0 - total_bet + f[j] / p[j]
            if wealth_if_j <= 0:
                return 1e10  # penalty for bankruptcy
            growth += q[j] * np.log(wealth_if_j)
        return -growth

    # Initial guess: proportional to edge
    edges = q / p - 1
    f0 = np.maximum(edges, 0) * 0.01
    f0 = f0 / max(np.sum(f0), 1) * max_bet_fraction * 0.5

    # Constraints
    constraints = [
        {'type': 'ineq', 'fun': lambda f: max_bet_fraction - np.sum(f)}
    ]

    # Bounds: each f_i >= 0
    bounds = [(0, max_bet_fraction) for _ in range(n)]

    result = minimize(neg_expected_log_growth, f0, method='SLSQP',
                     bounds=bounds, constraints=constraints)

    if result.success:
        optimal_f = result.x
        expected_growth = -result.fun
        return {
            'fractions': optimal_f,
            'total_wagered': np.sum(optimal_f),
            'expected_log_growth': expected_growth,
            'expected_growth_pct': (np.exp(expected_growth) - 1) * 100
        }
    else:
        raise ValueError(f"Optimization failed: {result.message}")

15.4.7 Fractional Kelly in Multi-Outcome Markets

Just as in binary markets, full Kelly can be aggressive. Fractional Kelly (betting a fraction $\alpha$ of the full Kelly amount) reduces variance at the cost of expected growth rate:

$$f_i^{\alpha\text{-Kelly}} = \alpha \cdot f_i^{\text{Kelly}}$$

For multi-outcome markets, $\alpha = 0.25$ to $0.50$ is commonly recommended because:

  1. Probability estimates across many outcomes are less reliable than for binary events.
  2. The mutual exclusivity constraint means a loss on one outcome is guaranteed, increasing the importance of survival.
  3. Model risk is higher when estimating a full probability distribution versus a single probability.

15.4.8 Mean-Variance Optimization

An alternative to Kelly is mean-variance optimization, adapted for the discrete structure of multi-outcome markets.

The covariance matrix for mutually exclusive outcomes has a special structure. Let $X_i$ be the indicator for outcome $i$ (1 if $i$ wins, 0 otherwise). Then:

$$\text{Cov}(X_i, X_j) = \begin{cases} q_i(1 - q_i) & \text{if } i = j \\ -q_i q_j & \text{if } i \neq j \end{cases}$$

The return on a portfolio with fractions $f_1, \ldots, f_n$ has:

$$E[R] = \sum_j f_j \left(\frac{q_j}{p_j} - 1\right)$$

$$\text{Var}(R) = \sum_j q_j \left(\frac{f_j}{p_j} - F\right)^2 - \left(\sum_j q_j \left(\frac{f_j}{p_j} - F\right)\right)^2$$

where $F = \sum f_i$. The mean-variance frontier can be traced by solving:

$$\min_f \text{Var}(R) \quad \text{s.t.} \quad E[R] = \mu, \; f_i \geq 0, \; \sum f_i \leq B$$

for varying target returns $\mu$.


15.5 Rank-Order and Relative Value Strategies

15.5.1 The Relative Value Philosophy

A powerful approach in multi-outcome markets is to focus on relative rather than absolute probabilities. Instead of asking "What is the probability that Candidate A wins?", you ask "Is Candidate A overpriced relative to Candidate B?"

This is powerful because:

  1. Relative assessments are easier: You may not know the absolute win probability, but you might know that two candidates are roughly equally likely.
  2. Reduces model risk: You do not need a complete probability model, just comparative judgments.
  3. Natural hedging: Relative value trades have built-in hedging properties.

15.5.2 Pair Trades in Multi-Outcome Markets

A pair trade in a multi-outcome market involves going long one outcome and short another. If you believe Candidate A (priced at 0.15) is underpriced relative to Candidate B (priced at 0.20), you can:

  • Buy $x$ contracts of A at 0.15
  • Sell $x$ contracts of B at 0.20

Your cost is $0.15x - 0.20x = -0.05x$ (you actually receive net $0.05x$ upfront).

Payoffs: - If A wins: Receive $x$ from A, pay $0$ on B. Net = $x - 0.15x + 0.20x = x + 0.05x$. - If B wins: Receive $0$ from A, pay $x$ on B. Net = $-0.15x + 0.20x - x = -0.95x$. - If neither wins: Receive $0$ from A, pay $0$ on B. Net = $-0.15x + 0.20x = 0.05x$.

This trade profits if A wins or if neither wins, and loses only if B wins. The key insight: you profit in $n - 1$ of $n$ outcomes if A wins, and also profit in $n - 2$ outcomes if neither wins. You only lose if B specifically wins.

15.5.3 Optimal Relative Value Sizing

For a pair trade (long outcome $i$, short outcome $j$), define the odds ratio:

$$\text{OR}_{ij} = \frac{q_i / q_j}{p_i / p_j}$$

If $\text{OR}_{ij} > 1$, outcome $i$ is underpriced relative to $j$. The magnitude tells you the degree of relative mispricing.

Kelly sizing for a pair trade must account for the three-state payoff structure. The optimal size can be found numerically using the same log-wealth maximization framework, but restricted to positions on outcomes $i$ and $j$ only.

15.5.4 Rank-Order Strategies

A broader approach examines the rank ordering of outcomes. Your model might predict:

$$q_1 > q_2 > q_3 > \cdots > q_n$$

The market might imply:

$$p_2 > p_1 > p_3 > \cdots > p_n$$

Where the rank orderings disagree, there are trading opportunities. You can construct portfolios that profit if your rank ordering is correct, even if your absolute probabilities are wrong.

Rank-Order Portfolio Construction:

  1. For each pair $(i, j)$ where your ranking disagrees with the market, compute the odds ratio $\text{OR}_{ij}$.
  2. Weight each pair trade by its odds ratio (stronger conviction gets more weight).
  3. Combine into a single portfolio.
  4. Check that the combined portfolio has acceptable risk properties.

15.5.5 Python Relative Value Analyzer

import numpy as np
from itertools import combinations

def find_relative_value_opportunities(true_probs, market_prices, names=None):
    """
    Identify relative value opportunities in a multi-outcome market.

    Parameters:
        true_probs: estimated true probabilities
        market_prices: market prices
        names: optional names for outcomes

    Returns:
        list of opportunities sorted by odds ratio
    """
    n = len(true_probs)
    if names is None:
        names = [f"Outcome {i+1}" for i in range(n)]

    opportunities = []
    for i, j in combinations(range(n), 2):
        if market_prices[i] > 0 and market_prices[j] > 0:
            if true_probs[i] > 0 and true_probs[j] > 0:
                market_ratio = market_prices[i] / market_prices[j]
                true_ratio = true_probs[i] / true_probs[j]
                odds_ratio = true_ratio / market_ratio

                if abs(odds_ratio - 1.0) > 0.05:  # threshold
                    if odds_ratio > 1:
                        long_idx, short_idx = i, j
                    else:
                        long_idx, short_idx = j, i
                        odds_ratio = 1.0 / odds_ratio

                    opportunities.append({
                        'long': names[long_idx],
                        'short': names[short_idx],
                        'long_idx': long_idx,
                        'short_idx': short_idx,
                        'odds_ratio': odds_ratio,
                        'long_price': market_prices[long_idx],
                        'short_price': market_prices[short_idx],
                        'long_true_prob': true_probs[long_idx],
                        'short_true_prob': true_probs[short_idx],
                    })

    return sorted(opportunities, key=lambda x: x['odds_ratio'], reverse=True)

def simulate_pair_trade(long_price, short_price, long_true_prob,
                       short_true_prob, size=100):
    """Simulate outcomes of a pair trade."""
    neither_prob = 1 - long_true_prob - short_true_prob
    cost = (long_price - short_price) * size

    # Payoffs
    if_long_wins = size - cost
    if_short_wins = -size - cost
    if_neither_wins = -cost

    expected_pnl = (long_true_prob * if_long_wins +
                    short_true_prob * if_short_wins +
                    neither_prob * if_neither_wins)

    return {
        'cost': cost,
        'if_long_wins': if_long_wins,
        'if_short_wins': if_short_wins,
        'if_neither_wins': if_neither_wins,
        'expected_pnl': expected_pnl,
        'prob_profit': long_true_prob + neither_prob,
    }

15.6 Scalar Market Strategies

15.6.1 What Are Scalar Markets?

A scalar market (also called a range market or bracket market) resolves to a value on a continuous scale, typically discretized into brackets. Instead of asking "Who will win?", scalar markets ask "What will the value be?"

Examples: - "What will US GDP growth be in 2026?" with brackets: <0%, 0-1%, 1-2%, 2-3%, 3-4%, >4% - "How many electoral votes will the winning candidate receive?" with brackets: 270-299, 300-329, 330-359, 360-399, 400+ - "What will the Fed funds rate be at the end of 2026?" with brackets at each 25bp increment

15.6.2 Implied Distribution Extraction

The bracket prices in a scalar market define a discrete probability distribution over the outcome space. But we can go further and extract an implied continuous distribution.

If the brackets are $[a_0, a_1), [a_1, a_2), \ldots, [a_{n-1}, a_n]$ with prices $p_1, \ldots, p_n$, then after removing overround to get probabilities $q_1, \ldots, q_n$, we know:

$$P(a_{k-1} \leq X < a_k) = q_k$$

The cumulative distribution function (CDF) at the bracket boundaries is:

$$F(a_k) = \sum_{i=1}^{k} q_i$$

To get a continuous distribution, we can:

  1. Linear interpolation: Assume the density is uniform within each bracket.
  2. Parametric fitting: Fit a known distribution (normal, log-normal, etc.) to the bracket probabilities.
  3. Spline interpolation: Fit a smooth CDF through the boundary points.

15.6.3 Parametric Distribution Fitting

For many economic and financial variables, a normal or log-normal distribution is a reasonable model. We can fit the distribution by minimizing the discrepancy between the model's bracket probabilities and the market's implied bracket probabilities.

Given a parametric family $F(x; \theta)$, we find:

$$\hat{\theta} = \arg\min_\theta \sum_{k=1}^{n} \left(q_k - [F(a_k; \theta) - F(a_{k-1}; \theta)]\right)^2$$

Or using maximum likelihood:

$$\hat{\theta} = \arg\max_\theta \sum_{k=1}^{n} q_k \cdot \ln[F(a_k; \theta) - F(a_{k-1}; \theta)]$$

The latter is equivalent to treating the bracket probabilities as a multinomial distribution and finding the parametric distribution that best explains them.

15.6.4 Identifying Bracket Mispricings

The power of distribution fitting is that it imposes smoothness constraints on the probability distribution. If the market implies:

Bracket Market Prob Normal Fit Prob Difference
< 0% 0.05 0.04 +0.01
0-1% 0.12 0.13 -0.01
1-2% 0.30 0.28 +0.02
2-3% 0.35 0.33 +0.02
3-4% 0.15 0.18 -0.03
> 4% 0.03 0.04 -0.01

The 3-4% bracket appears underpriced relative to what a smooth normal distribution would suggest. This could indicate a trading opportunity.

Of course, the market may have good reason to deviate from a normal distribution. The edge comes from combining the statistical analysis with domain knowledge about why certain brackets might be systematically mispriced.

15.6.5 Trading Strategies for Scalar Markets

Strategy 1: Bracket Arbitrage

If the implied distribution has "bumps" or "holes" that violate smoothness, trade to smooth them: - Sell overpriced brackets (those above the fitted distribution) - Buy underpriced brackets (those below the fitted distribution)

Strategy 2: Distribution Shift

If your model predicts a different mean or variance than the market implies: - Higher mean: Buy upper brackets, sell lower brackets - Lower variance: Sell tail brackets, buy center brackets - Higher variance: Buy tail brackets, sell center brackets

Strategy 3: Tail Trading

Markets systematically underprice or overprice tail events. If you believe tails are underpriced: - Buy the extreme brackets - Fund by selling the middle brackets

Strategy 4: Conditional Bracket Optimization

If you have a model that predicts the probability of each bracket conditional on other information (e.g., current economic data), you can compare your conditional model to the market's unconditional pricing.

15.6.6 The Implied Moments Approach

From the bracket probabilities, you can compute the implied moments of the distribution:

Implied Mean (using bracket midpoints $m_k$):

$$\hat{\mu} = \sum_{k=1}^{n} q_k \cdot m_k$$

Implied Variance:

$$\hat{\sigma}^2 = \sum_{k=1}^{n} q_k \cdot (m_k - \hat{\mu})^2$$

Implied Skewness:

$$\hat{\gamma} = \frac{\sum_{k=1}^{n} q_k \cdot (m_k - \hat{\mu})^3}{\hat{\sigma}^3}$$

These implied moments can be compared to your model's predicted moments. Discrepancies suggest trading opportunities focused on the specific moments that differ.

15.6.7 Python Scalar Market Analyzer

import numpy as np
from scipy.stats import norm
from scipy.optimize import minimize

class ScalarMarketAnalyzer:
    def __init__(self, bracket_edges, prices):
        """
        Parameters:
            bracket_edges: list of n+1 boundary values
                           [lower, b1, b2, ..., upper]
            prices: list of n bracket prices
        """
        self.edges = np.array(bracket_edges, dtype=float)
        self.prices = np.array(prices, dtype=float)
        self.n_brackets = len(prices)
        self.midpoints = (self.edges[:-1] + self.edges[1:]) / 2

        # Remove overround
        total = np.sum(self.prices)
        self.overround = total - 1.0
        self.probs = self.prices / total  # multiplicative removal

    def implied_moments(self):
        """Compute implied mean, variance, skewness."""
        mean = np.sum(self.probs * self.midpoints)
        var = np.sum(self.probs * (self.midpoints - mean)**2)
        std = np.sqrt(var)
        skew = np.sum(self.probs * ((self.midpoints - mean)/std)**3)
        return {'mean': mean, 'std': std, 'variance': var, 'skewness': skew}

    def fit_normal(self):
        """Fit a normal distribution to bracket probabilities."""
        def neg_log_likelihood(params):
            mu, sigma = params
            if sigma <= 0:
                return 1e10
            ll = 0
            for k in range(self.n_brackets):
                model_prob = (norm.cdf(self.edges[k+1], mu, sigma) -
                             norm.cdf(self.edges[k], mu, sigma))
                model_prob = max(model_prob, 1e-10)
                ll += self.probs[k] * np.log(model_prob)
            return -ll

        moments = self.implied_moments()
        result = minimize(neg_log_likelihood,
                         [moments['mean'], moments['std']],
                         method='Nelder-Mead')
        mu_fit, sigma_fit = result.x
        return {'mu': mu_fit, 'sigma': abs(sigma_fit)}

    def bracket_mispricings(self, fitted_dist):
        """Compare market probabilities to fitted distribution."""
        mu, sigma = fitted_dist['mu'], fitted_dist['sigma']
        mispricings = []
        for k in range(self.n_brackets):
            model_prob = (norm.cdf(self.edges[k+1], mu, sigma) -
                         norm.cdf(self.edges[k], mu, sigma))
            diff = self.probs[k] - model_prob
            mispricings.append({
                'bracket': f"[{self.edges[k]}, {self.edges[k+1]})",
                'market_prob': self.probs[k],
                'model_prob': model_prob,
                'difference': diff,
                'direction': 'SELL' if diff > 0.01 else
                            ('BUY' if diff < -0.01 else 'HOLD')
            })
        return mispricings

The complete implementation is in code/example-03-scalar-analysis.py.


15.7 Hedging and Risk Management in Multi-Outcome Markets

15.7.1 Why Hedging Matters More in Multi-Outcome Markets

In a binary market, your risk is simple: you are either right or wrong. In a multi-outcome market with $n$ outcomes, there are $n$ possible states of the world, and your portfolio might have vastly different values in each state. Hedging becomes essential for managing this complexity.

15.7.2 Full vs. Partial Hedging

Full Hedging: Locking in a guaranteed profit. This is essentially the Dutch book from Section 15.3 --- if you have a profitable position, you can trade to guarantee your profit regardless of outcome. However, full hedging reduces your expected value.

Partial Hedging: Reducing your worst-case loss while preserving most of your expected value. This is more common in practice.

15.7.3 The Hedging Decision Framework

Consider a portfolio with positions $x_1, \ldots, x_n$ in a multi-outcome market. The payoff in state $j$ is:

$$\pi_j = x_j - \text{cost}$$

where cost is the total amount spent on all positions.

A hedge trade modifies the portfolio to reduce the range of payoffs. The hedging decision involves:

  1. Identify your worst state: Which outcome gives you the largest loss?
  2. Compute the hedging cost: How much expected value must you sacrifice to reduce the worst-case loss?
  3. Choose the hedge ratio: How much of the worst-case loss do you want to eliminate?

15.7.4 Cross-Outcome Hedging

A natural hedge in multi-outcome markets exploits the mutual exclusivity structure. If you have a large long position on Outcome A, you can partially hedge by:

  1. Buying the "field": Buy small positions in every other outcome. This guarantees some recovery if A loses.

  2. Selling A partially: Reduce your position in A at current prices.

  3. Structured hedging: Buy specific outcomes that are most likely to win if A does not, based on your model of conditional probabilities.

15.7.5 Dynamic Hedging Over Time

As time passes and new information arrives, the optimal hedge changes. Dynamic hedging involves:

  1. Rebalancing: Periodically adjusting your hedge positions as prices move.
  2. Event-driven hedging: Adding hedges before known events (debates, data releases) that could cause large price moves.
  3. Time decay hedging: As the market approaches resolution, adjust positions to account for reduced uncertainty.

15.7.6 Python Hedging Calculator

import numpy as np
from scipy.optimize import minimize

def calculate_hedge(positions, prices, true_probs, max_hedge_cost=0.1):
    """
    Calculate optimal partial hedge for a multi-outcome portfolio.

    Parameters:
        positions: current position sizes (positive = long)
        prices: current market prices
        true_probs: estimated true probabilities
        max_hedge_cost: maximum expected value sacrifice for hedging

    Returns:
        dict with hedge trades and resulting portfolio metrics
    """
    n = len(positions)
    pos = np.array(positions, dtype=float)
    p = np.array(prices, dtype=float)
    q = np.array(true_probs, dtype=float)

    # Current payoffs in each state
    cost = np.sum(np.maximum(pos, 0) * p)
    current_payoffs = np.array([
        pos[j] * (1 / p[j]) if pos[j] > 0 else -pos[j] * (1 / p[j])
        for j in range(n)
    ])

    # Simplified: payoff if outcome j wins
    payoffs = np.zeros(n)
    for j in range(n):
        payoffs[j] = -np.sum(np.abs(pos) * p)  # cost
        for i in range(n):
            if i == j and pos[i] > 0:
                payoffs[j] += pos[i]  # winning payout
            elif i == j and pos[i] < 0:
                payoffs[j] -= abs(pos[i])  # short payout obligation

    current_ev = np.sum(q * payoffs)
    current_worst = np.min(payoffs)

    # Optimize hedge: find additional trades to minimize worst case
    # subject to not sacrificing too much EV
    def objective(hedge):
        new_payoffs = payoffs.copy()
        hedge_cost = 0
        for i in range(n):
            if hedge[i] > 0:
                hedge_cost += hedge[i] * p[i]
                new_payoffs[i] += hedge[i]
            elif hedge[i] < 0:
                hedge_cost -= hedge[i] * p[i]
                for j in range(n):
                    if j != i:
                        new_payoffs[j] += abs(hedge[i]) * p[i]
        for j in range(n):
            new_payoffs[j] -= hedge_cost
        return -np.min(new_payoffs)  # minimize negative of worst case

    bounds = [(-100, 100) for _ in range(n)]
    constraints = [{
        'type': 'ineq',
        'fun': lambda h: max_hedge_cost - abs(np.sum(h * p))
    }]

    result = minimize(objective, np.zeros(n), method='SLSQP',
                     bounds=bounds, constraints=constraints)

    hedge_trades = result.x
    return {
        'hedge_trades': hedge_trades,
        'original_worst_case': current_worst,
        'hedged_worst_case': -result.fun,
        'original_ev': current_ev,
        'hedge_cost': np.sum(np.abs(hedge_trades) * p),
    }

15.7.7 Risk Metrics for Multi-Outcome Portfolios

Several risk metrics are useful for multi-outcome portfolios:

Maximum Loss: The worst payoff across all states:

$$\text{MaxLoss} = \min_{j} \pi_j$$

Expected Shortfall: The expected payoff in the worst $\alpha$% of outcomes:

$$\text{ES}_\alpha = \text{average of worst } \lceil \alpha n \rceil \text{ payoffs, weighted by probability}$$

Payoff Range: The difference between best and worst payoffs:

$$\text{Range} = \max_j \pi_j - \min_j \pi_j$$

Probability of Loss: The probability of a negative payoff:

$$P(\text{loss}) = \sum_{j: \pi_j < 0} q_j$$

A well-hedged portfolio should have a small range relative to its expected value, a bounded maximum loss, and a low probability of loss.


15.8 Market-Making Multi-Outcome Markets

15.8.1 The Multi-Outcome Market Maker's Problem

Market making in multi-outcome markets is fundamentally different from binary markets because the market maker must simultaneously quote bid and ask prices on $n$ contracts while managing inventory across all of them.

The core challenge: inventory risk is multidimensional. In a binary market, the market maker's risk is one-dimensional (net long or net short). In an $n$-outcome market, the market maker has an $n$-dimensional risk profile.

15.8.2 Inventory Management

The market maker's inventory at time $t$ is a vector $\mathbf{I}_t = (I_{t,1}, \ldots, I_{t,n})$ where $I_{t,i}$ is the net position in contract $i$. The market maker wants to keep this vector close to zero.

Inventory cost if outcome $j$ occurs:

$$C_j = I_{t,j} - \sum_{i=1}^{n} I_{t,i} \cdot p_i^{\text{mid}}$$

The first term is the payout on the winning contract; the second is the approximate value of the entire inventory at midpoint prices.

15.8.3 Dynamic Pricing with Inventory

A common approach adjusts the midpoint based on inventory:

$$\text{mid}_{i,t} = \hat{p}_i + \delta \cdot I_{t,i}$$

where $\hat{p}_i$ is the fair value estimate and $\delta$ is an inventory adjustment parameter. When the market maker is long outcome $i$ ($I_{t,i} > 0$), the midpoint increases, making it more likely they will sell and reduce inventory.

The bid-ask spread for outcome $i$:

$$\text{bid}_i = \text{mid}_i - s_i/2, \quad \text{ask}_i = \text{mid}_i + s_i/2$$

where $s_i$ is the spread, which may vary by outcome (wider spreads for less liquid outcomes).

15.8.4 The Automated Market Maker (AMM) Approach

In decentralized prediction markets, automated market makers like the Logarithmic Market Scoring Rule (LMSR) are commonly used. The LMSR, introduced by Robin Hanson, defines prices as:

$$p_i = \frac{e^{q_i / b}}{\sum_{j=1}^{n} e^{q_j / b}}$$

where $q_i$ is the total quantity of contract $i$ purchased and $b$ is a liquidity parameter. This is essentially a softmax function that automatically adjusts prices as trades occur.

Key properties of LMSR: - Prices always sum to 1 (no overround). - Prices are always between 0 and 1. - Buying contract $i$ increases $p_i$ and decreases all others. - The parameter $b$ controls liquidity: larger $b$ means more liquidity (smaller price impact per trade) but more potential loss for the market maker.

The maximum loss for the LMSR market maker is bounded by $b \cdot \ln(n)$, making the risk calculable.

15.8.5 Python Multi-Outcome Market Maker Simulation

import numpy as np

class MultiOutcomeMarketMaker:
    def __init__(self, n_outcomes, initial_probs, spread=0.02,
                 inventory_adj=0.001, max_inventory=1000):
        self.n = n_outcomes
        self.fair_values = np.array(initial_probs, dtype=float)
        self.spread = spread
        self.inventory_adj = inventory_adj
        self.max_inventory = max_inventory
        self.inventory = np.zeros(n_outcomes)
        self.pnl = 0.0
        self.trade_history = []

    def get_quotes(self):
        """Get current bid/ask quotes for all outcomes."""
        adj = self.fair_values + self.inventory_adj * self.inventory
        adj = np.clip(adj, 0.01, 0.99)
        bids = adj - self.spread / 2
        asks = adj + self.spread / 2
        return {
            'bids': np.clip(bids, 0.01, 0.99),
            'asks': np.clip(asks, 0.01, 0.99)
        }

    def execute_trade(self, outcome_idx, side, quantity):
        """
        Execute a trade.

        Parameters:
            outcome_idx: which outcome (0 to n-1)
            side: 'buy' or 'sell'
            quantity: number of contracts
        """
        quotes = self.get_quotes()

        if side == 'buy':
            price = quotes['asks'][outcome_idx]
            self.inventory[outcome_idx] -= quantity  # MM sells
            self.pnl += price * quantity
        else:
            price = quotes['bids'][outcome_idx]
            self.inventory[outcome_idx] += quantity  # MM buys
            self.pnl -= price * quantity

        self.trade_history.append({
            'outcome': outcome_idx,
            'side': side,
            'quantity': quantity,
            'price': price,
        })

        return price

    def resolve(self, winning_outcome):
        """Resolve the market and compute final PnL."""
        # Settlement: inventory in winning outcome pays out
        settlement = self.inventory[winning_outcome]
        self.pnl -= settlement  # pay out winning contracts held
        # Actually: positive inventory means MM is long, receives payout
        # negative inventory means MM is short, must pay out
        # Net: pnl += inventory[winning] * 1 - cost_of_inventory
        final_pnl = self.pnl + self.inventory[winning_outcome]
        return {
            'final_pnl': final_pnl,
            'inventory_at_settlement': self.inventory.copy(),
            'n_trades': len(self.trade_history),
        }

    def update_fair_values(self, new_probs):
        """Update fair value estimates (e.g., based on new information)."""
        self.fair_values = np.array(new_probs, dtype=float)

15.8.6 Market Making Risks and Mitigations

Adverse selection: Informed traders will systematically trade against the market maker on the outcome they know will win. Mitigations: - Wider spreads on outcomes with higher adverse selection risk - Faster fair value updates - Position limits per outcome

Inventory concentration: If the market maker accumulates a large position in one outcome, they face catastrophic risk if that outcome loses. Mitigations: - Inventory-dependent pricing (as above) - Hard inventory limits - Cross-outcome hedging

Correlation risk: In multi-outcome markets, a trade in one outcome provides information about all others. A sophisticated market maker updates all prices after every trade.


15.9 Real-World Examples

15.9.1 Election Markets with Multiple Candidates

Scenario: A primary election market lists 8 candidates. The market prices are:

Candidate Price Implied Prob (mult.)
A 0.32 28.8%
B 0.28 25.2%
C 0.18 16.2%
D 0.12 10.8%
E 0.08 7.2%
F 0.05 4.5%
G 0.04 3.6%
H 0.04 3.6%
Total 1.11 100%

The overround is 11%, which is typical for a multi-candidate market. Key observations:

  1. Favorite-longshot bias: The top candidates (A, B) are likely slightly overpriced and the long shots (G, H) slightly overpriced due to the well-documented favorite-longshot bias, though this works in different directions depending on the mechanism.

  2. Clustering opportunity: Candidates C and D are priced quite close to each other. If your analysis suggests one is significantly more likely than the other, this relative value trade has good risk/reward.

  3. Field pricing: The sum of prices for candidates E through H is 0.21. If you believe the probability that "someone outside the top 4" wins is different from 0.21, you can trade the "field."

Professional traders in these markets typically: - Build polling-based models to generate independent probability estimates. - Focus on relative mispricings rather than absolute probabilities. - Use fractional Kelly (0.25--0.33) given the high uncertainty. - Dynamically hedge as the race evolves.

15.9.2 Sports Futures Markets

Scenario: NFL Super Bowl futures market with 32 teams. Key characteristics:

  1. High overround: Futures markets often have 20--40% overround.
  2. Longshot clustering: Most teams are priced between 0.01 and 0.05.
  3. Seasonal dynamics: Prices change dramatically during the season.
  4. Information advantage: Local beat reporters may have informational edges on specific teams.

Strategy: A quantitative approach might: 1. Build an Elo-based or simulation-based model to produce win probabilities. 2. Use Shin's method to extract true probabilities from market prices. 3. Identify the teams with the largest positive edge. 4. Size positions using fractional Kelly (0.20 is common for sports futures). 5. Rebalance after each game week.

15.9.3 Economic Indicator Brackets

Scenario: A Kalshi-style market on quarterly GDP growth with brackets:

Bracket Price
< 0.0% 0.05
0.0--1.0% 0.12
1.0--2.0% 0.28
2.0--3.0% 0.33
3.0--4.0% 0.18
> 4.0% 0.08
Total 1.04

Professional approach:

  1. Extract implied distribution: Use the methods from Section 15.6.
  2. Compare to econometric model: The Federal Reserve's GDPNow model, the Blue Chip consensus, or your own VAR model provides an alternative distribution.
  3. Identify moment mismatch: Perhaps the market implies a mean of 2.1% with a standard deviation of 1.3%, while your model suggests mean 2.5% with standard deviation 1.0%.
  4. Trade the difference: Buy the 2--3% and 3--4% brackets (higher mean), sell the tails (lower variance).
  5. Size conservatively: Economic data is noisy; use 0.15--0.25 Kelly.

15.9.4 Award Prediction Markets

Markets for awards (Oscars, Nobel Prize, etc.) have unique features: - Very few informed traders: Unlike elections or sports, there are relatively few people with genuine inside information. - Strong behavioral biases: Narrative-driven pricing, recency bias, and herd behavior are pronounced. - Thin liquidity: These markets attract less volume, creating wider mispricings. - Time-varying information: For Oscars, guild voting results, critic reviews, and other precursors provide incremental information.


15.10 Advanced: Combinatorial Strategies

15.10.1 Preview of Combinatorial Markets

Chapter 30 will cover combinatorial prediction markets in depth, but we introduce the basic concepts here because they build directly on multi-outcome market strategies.

A combinatorial market allows trading on combinations of outcomes across multiple events. For example:

  • Event 1: "Who will win the presidency?" (Candidates A, B, C)
  • Event 2: "Which party will control the Senate?" (Democrat, Republican)

A combinatorial market would allow trading on all $3 \times 2 = 6$ joint outcomes: - A wins presidency AND Democrats control Senate - A wins presidency AND Republicans control Senate - B wins presidency AND Democrats control Senate - etc.

15.10.2 Basic Combinatorial Thinking

Even without formal combinatorial markets, you can apply combinatorial thinking to multi-outcome markets:

Conditional probability exploitation: If you know that Candidate A winning makes economic outcome X more likely, you can construct a portfolio that profits from this conditional relationship.

Cross-market consistency: If two separate markets (e.g., "Who will win?" and "Will the margin be > 5%?") are inconsistent with each other, you can exploit the inconsistency.

Scenario analysis: Build a complete scenario matrix and identify positions that are profitable across the most likely scenarios.

15.10.3 Joint Probability Estimation

Given $n$ outcomes in market 1 and $m$ outcomes in market 2, the joint probability matrix has $n \times m$ entries. But we often only observe the marginal probabilities:

$$P(A_i) = \sum_j P(A_i, B_j), \quad P(B_j) = \sum_i P(A_i, B_j)$$

Without knowing the correlation structure, there are many possible joint distributions consistent with the marginals. The strategy is to:

  1. Estimate the correlation from external data.
  2. Construct the most plausible joint distribution.
  3. Compare it to what the market implies (if combinatorial contracts exist).
  4. Trade any discrepancies.

15.10.4 Copula Approaches

A copula separates the marginal distributions from the dependence structure. For prediction market applications:

  1. Use the marginal probabilities from each market.
  2. Choose a copula (Gaussian, Clayton, Frank) to model the dependence.
  3. Estimate the copula parameter from historical data or domain knowledge.
  4. Generate the joint distribution.
  5. Price conditional and joint contracts.

This is a preview; Chapter 30 develops these ideas fully.


15.11 Chapter Summary

This chapter has developed a comprehensive toolkit for trading multi-outcome and scalar prediction markets. The key takeaways are:

On extracting true probabilities: - Raw market prices include overround and cannot be directly used as probabilities. - Shin's method and the power method provide the most reliable probability extraction. - The choice of method matters most for extreme (very high or very low) probabilities.

On arbitrage and Dutch books: - Dutch books are guaranteed-profit portfolios that exploit price inconsistencies. - Simple sum violations are rare; more interesting opportunities come from cross-market inconsistencies. - Linear programming provides a systematic way to detect and construct Dutch books. - Transaction costs eliminate most theoretical Dutch book opportunities.

On portfolio optimization: - The Kelly criterion extends to multi-outcome markets but must account for mutual exclusivity. - Numerical optimization is typically required; closed-form solutions exist only in special cases. - Fractional Kelly (0.25--0.50 of full Kelly) is strongly recommended due to higher model risk. - Mean-variance optimization provides an alternative framework with different risk properties.

On relative value strategies: - Relative assessments (outcome A vs. outcome B) are often more reliable than absolute probability estimates. - Pair trades in multi-outcome markets have natural hedging properties. - Odds ratios quantify relative mispricing and guide trade sizing.

On scalar markets: - Bracket prices define an implied probability distribution. - Distribution fitting (parametric or non-parametric) reveals bracket-level mispricings. - Moment-based analysis (mean, variance, skewness) provides a higher-level view of market expectations. - Trading strategies include bracket arbitrage, distribution shift, and tail trading.

On risk management: - Multi-outcome portfolios have multidimensional risk profiles. - Partial hedging preserves expected value while bounding worst-case losses. - Dynamic hedging adjusts positions as new information arrives. - Risk metrics include maximum loss, expected shortfall, and probability of loss.

On market making: - Multi-outcome market makers face multidimensional inventory risk. - Inventory-dependent pricing is essential for managing risk. - The LMSR provides an automated approach with bounded loss.


What's Next

Chapter 16 explores live market analysis and trade execution, bringing together the theoretical frameworks from Chapters 13--15 into a practical workflow. We will build a real-time analysis pipeline that extracts true probabilities, identifies mispricings, constructs optimal portfolios, and executes trades --- including multi-outcome and scalar markets. We will also address the practical challenges of order routing, partial fills, and execution timing that determine whether theoretical edge translates into actual profit.


Key Equations Summary

Concept Equation
Overround $\omega = \sum_{i=1}^{n} p_i - 1$
Multiplicative removal $\hat{p}_i = p_i / \sum p_j$
Power method $\hat{p}_i = p_i^k$ where $\sum p_i^k = 1$
Kelly return (outcome $j$ wins) $R_j = f_j/p_j - \sum f_i$
Expected portfolio return $E[R] = \sum f_j(q_j/p_j - 1)$
Relative edge (odds ratio) $\text{OR}_{ij} = (q_i/q_j) / (p_i/p_j)$
Implied mean (scalar) $\hat{\mu} = \sum q_k m_k$
LMSR pricing $p_i = e^{q_i/b} / \sum e^{q_j/b}$
LMSR max loss $b \cdot \ln(n)$

Glossary

  • Bracket market: A scalar market divided into discrete ranges.
  • Categorical market: A market with multiple mutually exclusive outcomes where exactly one wins.
  • Dutch book: A set of bets guaranteeing profit regardless of outcome.
  • LMSR: Logarithmic Market Scoring Rule, an automated market maker for multi-outcome markets.
  • Odds ratio: The ratio of true probability ratios to market price ratios for two outcomes.
  • Overround: The amount by which market prices exceed 1 in a multi-outcome market.
  • Pair trade: A simultaneous long and short position in two outcomes of the same market.
  • Power method: An overround removal technique using power-law transformation.
  • Scalar market: A market resolving to a continuous numerical value.
  • Shin's method: An overround removal technique based on a model of informed trading.