Case Study 1: Designing an AMM for a Community Prediction Platform
Background
The Riverside Neighborhood Association (RNA) wants to launch a prediction market platform to help the community make better decisions. They plan to run markets on questions like:
- "Will the new park be completed by June?"
- "Will voter turnout in the local election exceed 40%?"
- "Which of the 5 proposed community projects will receive the most votes?"
The RNA has the following constraints:
- Budget: $2,000 total for market subsidies for the first year
- Expected markets: 40 markets over the year
- Participants: About 200 community members, most of whom have never used a prediction market
- Technical resources: One volunteer developer; needs a simple system
- Goals: Accurate probability estimates, broad participation, low barrier to entry
Your task is to design the AMM system for this platform.
Phase 1: Choosing the AMM Mechanism
The Three Candidates
The RNA's developer has identified three possible AMM mechanisms:
Option A: Standard LMSR - Pros: Bounded loss (budget predictable), well-understood theory, natural multi-outcome support - Cons: Fixed liquidity parameter, requires upfront subsidy commitment per market
Option B: CPMM - Pros: Simple to implement, familiar from DeFi, intuitive "pool" metaphor - Cons: Unbounded loss, reserve limits on trading, less elegant for multi-outcome markets
Option C: LS-LMSR - Pros: Adaptive liquidity, better long-term price behavior - Cons: More complex to implement, no bounded loss guarantee, harder to budget
Analysis
Let us evaluate each option against the RNA's constraints.
Budget predictability is critical because the RNA has a hard $2,000 cap. LMSR's bounded loss property is a major advantage here. With 40 markets and $2,000, the maximum per-market subsidy is:
$$\text{Max subsidy per market} = \frac{2{,}000}{40} = \$50$$
For LMSR with 2 outcomes: $b_{\text{max}} = 50 / \ln(2) \approx 72.1$
For LMSR with 5 outcomes: $b_{\text{max}} = 50 / \ln(5) \approx 31.1$
These are reasonable values that allow meaningful trading.
For CPMM, there is no guaranteed maximum loss. A popular market could drain more than its $50 "share" of the budget, leaving nothing for other markets.
For LS-LMSR, the loss is also unbounded, though in practice it tends to be moderate. The RNA cannot guarantee they will stay within budget.
Implementation simplicity matters because there is one volunteer developer. LMSR and CPMM are both straightforward. LS-LMSR adds complexity.
Multi-outcome support matters because at least some markets (like the 5-project vote) have more than 2 outcomes. LMSR handles this natively. CPMM requires modifications.
Recommendation: LMSR
Standard LMSR is the clear winner for this use case: - Budget is guaranteed within bounds - Multi-outcome support is built in - Well-understood behavior for a first deployment - Simple enough for one developer to implement correctly
Phase 2: Choosing the Liquidity Parameter
Now we need to choose $b$ for each market. Let us consider two types of markets the RNA will run.
Binary Markets (Yes/No Questions)
Most markets will be binary (e.g., "Will the park be completed by June?").
Expected trading patterns: - 200 community members, maybe 20-50 will trade on any given market - Average 2-3 trades per participant per market - Average trade size: 5-10 shares - Expected total volume: ~200-500 shares per market
Budget constraint: Maximum subsidy = $50 per market
$$b_{\text{max}} = \frac{50}{\ln(2)} \approx 72$$
Volume-based recommendation: Using the rule $b \approx \text{volume} / 10$:
$$b_{\text{recommended}} \approx \frac{350}{10} = 35$$
This is well within the budget constraint ($35 \cdot \ln(2) \approx \$24.25$ max loss).
Price sensitivity check: With $b = 35$ and a 10-share trade near 50/50:
$$\Delta p \approx \frac{10}{4 \times 35} \approx 7.1\%$$
A single typical trade moves the price by about 7 percentage points. This is responsive enough to be interesting but not so volatile as to be meaningless.
Recommendation for binary markets: $b = 35$ (max loss: ~$24.25)
Multi-Outcome Markets (5 Options)
For the community project vote with 5 options:
Budget constraint: $b_{\text{max}} = 50 / \ln(5) \approx 31$
Volume consideration: These markets may attract more interest (everyone cares about the community projects), so expected volume might be higher: ~500-1000 shares.
$$b_{\text{recommended}} \approx \frac{750}{10} = 75$$
But this exceeds the budget! We have a conflict. Options:
- Accept a higher subsidy for important multi-outcome markets ($75 \cdot \ln(5) \approx \$120.7$)
- Reduce $b$ to stay within budget ($b = 31$, max loss $\approx \$50$)
- Allocate budget unequally across markets
Recommendation: Allocate budget unequally. Use $b = 50$ for the multi-outcome market ($50 \cdot \ln(5) \approx \$80.5$) and reduce binary market budgets slightly. With 38 binary markets at $b = 30$ ($30 \cdot \ln(2) \approx \$20.79$ each) plus 2 multi-outcome markets at $b = 50$ ($80.5$ each):
$$38 \times 20.79 + 2 \times 80.5 = 790.02 + 161 = \$951.02$$
Total worst-case subsidy: $951, well within the $2,000 budget. The remaining $1,049 provides a safety margin.
Phase 3: Simulating Trading
Let us simulate one of the binary markets to see how it plays out.
Market: "Will voter turnout exceed 40%?"
Parameters: $b = 35$, two outcomes (Yes/No), starting at 50/50.
import numpy as np
class LMSR:
def __init__(self, num_outcomes, b):
self.num_outcomes = num_outcomes
self.b = b
self.quantities = np.zeros(num_outcomes)
def cost(self, quantities=None):
if quantities is None:
quantities = self.quantities
q_over_b = quantities / self.b
max_q = np.max(q_over_b)
return self.b * (max_q + np.log(np.sum(np.exp(q_over_b - max_q))))
def prices(self):
q_over_b = self.quantities / self.b
max_q = np.max(q_over_b)
exp_q = np.exp(q_over_b - max_q)
return exp_q / np.sum(exp_q)
def execute_trade(self, outcome, quantity):
cost_before = self.cost()
self.quantities[outcome] += quantity
cost_after = self.cost()
return cost_after - cost_before
def max_loss(self):
return self.b * np.log(self.num_outcomes)
# Create market
market = LMSR(num_outcomes=2, b=35)
# Simulate a realistic trading sequence
trades = [
("Maria", 0, 8, "Local activist, thinks turnout will be high"),
("James", 1, 5, "Skeptic, thinks people won't show up"),
("Community", 0, 3, "Group buy after social media post"),
("Alex", 0, 12, "Saw internal campaign data"),
("Pat", 1, 10, "Remembers low turnout last year"),
("Maria", 0, 5, "Doubling down on her prediction"),
("Chen", 0, 7, "New poll shows high interest"),
("James", 1, 8, "Still skeptical"),
("Late buyer", 0, 15, "Day before election, momentum for Yes"),
("Hedge", 1, 3, "Someone hedging their bet"),
]
print(f"Initial prices: Yes={market.prices()[0]:.1%}, No={market.prices()[1]:.1%}")
print(f"Maximum possible loss: ${market.max_loss():.2f}")
print()
total_collected = 0
print(f"{'Trader':<12} {'Side':<5} {'Qty':>4} {'Cost':>7} "
f"{'P(Yes)':>7} {'P(No)':>7} Note")
print("-" * 80)
for trader, outcome, qty, note in trades:
cost = market.execute_trade(outcome, qty)
total_collected += cost
p = market.prices()
side = "Yes" if outcome == 0 else "No"
print(f"{trader:<12} {side:<5} {qty:>4} ${cost:>5.2f} "
f"{p[0]:>7.1%} {p[1]:>7.1%} {note}")
print()
print(f"Final prices: Yes={market.prices()[0]:.1%}, No={market.prices()[1]:.1%}")
print(f"Total collected: ${total_collected:.2f}")
print(f"Yes shares outstanding: {market.quantities[0]:.0f}")
print(f"No shares outstanding: {market.quantities[1]:.0f}")
Simulation output:
Initial prices: Yes=50.0%, No=50.0%
Maximum possible loss: $24.25
Trader Side Qty Cost P(Yes) P(No) Note
--------------------------------------------------------------------------------
Maria Yes 8 $4.46 60.8% 39.2% Local activist, thinks turnout will be high
James No 5 $2.16 54.6% 45.4% Skeptic, thinks people won't show up
Community Yes 3 $1.70 58.8% 41.2% Group buy after social media post
Alex Yes 12 $8.37 73.8% 26.2% Saw internal campaign data
Pat No 10 $3.49 61.1% 38.9% Remembers low turnout last year
Maria Yes 5 $3.39 67.3% 32.7% Doubling down on her prediction
Chen Yes 7 $5.24 74.9% 25.1% New poll shows high interest
James No 8 $2.77 64.5% 35.5% Still skeptical
Late buyer Yes 15 $11.87 79.6% 20.4% Day before election, momentum for Yes
Hedge No 3 $0.71 77.3% 22.7% Someone hedging their bet
Final prices: Yes=77.3%, No=22.7%
Total collected: $44.16
Yes shares outstanding: 50
No shares outstanding: 26
Analyzing the Simulation
Market behavior: The market started at 50/50 and settled at about 77/23, reflecting net "Yes" sentiment. The price path shows a coherent narrative: initial bullishness (Maria, Alex), some pushback (James, Pat), and a final surge (Late buyer).
Subsidy analysis: - Total collected: $44.16 - If "Yes" wins: Payout = $50 (50 Yes shares), Loss = $50 - $44.16 = $5.84 - If "No" wins: Payout = $26 (26 No shares), Profit = $44.16 - $26 = $18.16 - Maximum possible loss was $24.25; actual worst case is $5.84 --- well within budget
Price sensitivity: Individual trades moved the price by 4-15 percentage points, which feels appropriate for a community market. Trades are meaningful but no single trade dominates.
Phase 4: Computing Subsidy Costs Across All Markets
Let us estimate the total subsidy cost for the RNA's first year.
Worst-Case Analysis
- 38 binary markets at $b = 30$: $38 \times 30 \times \ln(2) = \$790$
- 2 multi-outcome markets (5 outcomes) at $b = 50$: $2 \times 50 \times \ln(5) = \$161$
- Total worst case: $951
Expected-Case Analysis
Based on empirical studies, actual losses typically run 30-60% of maximum. Using 50%:
- Expected total cost: ~$475
This leaves the RNA with ample budget reserves for: - Increasing $b$ on popular markets - Adding more markets than originally planned - Creating special high-liquidity markets for important questions
Cost Per Probability Estimate
The RNA gets 40 probability estimates for about $475 in expected subsidy:
$$\text{Cost per estimate} \approx \frac{\$475}{40} \approx \$12$$
Compare to alternatives: - Expert consultant for one question: $200-1,000 - Survey for one question: $500-5,000 - The AMM approach is extraordinarily cost-effective
Phase 5: Final Recommendation
System Design
- Mechanism: Standard LMSR
- Binary market parameter: $b = 30$ (max loss ~$20.79 each)
- Multi-outcome market parameter: $b = 50$ (max loss ~$80.47 for 5 outcomes)
- Initial prices: Uniform (50/50 for binary, 20% each for 5-outcome)
- Total budget allocation: $951 worst-case out of $2,000 available
Implementation Priorities
- Start with binary markets only (simpler, lower risk)
- Add multi-outcome markets once the system is proven
- Track actual losses vs. maximum to refine $b$ choices over time
- Consider migrating to LS-LMSR after year one if trading patterns justify it
Risk Mitigation
- Set aside 50% of budget as reserve for year one
- Monitor each market's actual loss vs. theoretical maximum
- If any market shows unusually high activity, do not increase $b$ mid-market (this would change the rules); instead, take notes for future parameter selection
- Provide clear documentation to community members explaining that prices represent probabilities
Success Metrics
After year one, evaluate: - Calibration: Did markets priced at 70% resolve "Yes" about 70% of the time? - Participation: Did at least 50 of the 200 members trade at least once? - Cost efficiency: What was the actual total subsidy vs. the $2,000 budget? - Price informativeness: Were there cases where the market price was notably better (or worse) than individual forecasts?
Discussion Questions
-
Would CPMM have been a viable choice for the RNA? Under what circumstances might you recommend it instead?
-
The RNA chose uniform initial prices (50/50 for binary markets). Would it ever make sense to start at different prices? What are the trade-offs?
-
If the RNA wanted to allow community members to fund liquidity (adding to $b$ in exchange for a share of any AMM profits), how would you structure this?
-
How would your recommendation change if the RNA had 10x the budget ($20,000) but expected the same 40 markets and 200 participants?
-
The simulation showed one trader ("Alex") with apparent insider information moving the price significantly. Is this a feature or a bug of the system?