LMSR / Market Scoring Rules (Connection to Verex) TODO
Concept
A market scoring rule turns a proper scoring rule into an automated market maker, where participants update the current distribution toward their own beliefs and are rewarded for the improvement they contribute. LMSR is derived from the logarithmic scoring rule: for each outcome it defines a cost function over the vector q of quantities sold so far, in log-sum-exp form. The cost of a trade is the difference between the cost function's value after the trade and before it, so path independence holds — the total cost to reach the same final state is the same regardless of the path taken. The instantaneous price is the partial derivative of the cost function, which takes the softmax form of quantities divided by the liquidity parameter, so prices always sum to 1 and can be read as probabilities. A larger liquidity parameter reduces price movement for the same trade size, but it also raises the upper bound on the market maker's maximum possible loss — and that bound is always finite.
Because LMSR always quotes a price even without a counter order, it's used for bootstrapping initial liquidity, and choosing the liquidity parameter is a direct trade-off between slippage and the operating loss budget.
Code & Formula
# LMSR/마켓 스코어링(Verex 연결) — 로그-합-지수 비용함수와 경로독립적 가격
# C(q) = b*ln(sum(exp(q_i/b))), price_i = exp(q_i/b) / sum(exp(q_j/b)) (softmax)
import math
def cost(q, b):
m = max(q) # 오버플로 방지를 위한 log-sum-exp 안정화 트릭
return b * (m / b + math.log(sum(math.exp((qi - m) / b) for qi in q)))
def prices(q, b):
m = max(q)
exps = [math.exp((qi - m) / b) for qi in q]
s = sum(exps)
return [e / s for e in exps]
b = 100.0 # 유동성 파라미터: 클수록 가격 변동은 완만해지고 손실 상한은 커진다
q = [0.0, 0.0] # 두 결과(YES/NO) 초기 보유 수량, 시작 가격은 각각 0.5
print("초기 가격:", [round(p, 4) for p in prices(q, b)])
def buy(q, b, outcome, shares):
before = cost(q, b)
q2 = list(q)
q2[outcome] += shares
after = cost(q2, b)
return q2, after - before # 지불해야 할 비용
# YES에 20주 매수
q, paid = buy(q, b, 0, 20)
print(f"YES 20주 매수 비용 = {paid:.4f}, 매수 후 가격 = {[round(p,4) for p in prices(q, b)]}")
# 같은 거래를 유동성이 작은 마켓(b=20)에서 하면 가격이 훨씬 크게 움직인다
q_small, paid_small = buy([0.0, 0.0], 20.0, 0, 20)
print(f"[b=20] 같은 20주 매수 비용 = {paid_small:.4f}, 가격 = {[round(p,4) for p in prices(q_small, 20.0)]}")
# 마켓 메이커의 최대 손실 상한은 b*ln(결과 수)로 유한하다
worst_case_loss = b * math.log(len(q))
print(f"b={b}일 때 마켓 메이커 최대 손실 상한 = {worst_case_loss:.4f}")
Exercise
Implement the LMSR cost function and price function in code for a two-outcome market, vary the liquidity parameter, and simulate the average fill price and cumulative maximum loss for buying the same quantity — tabulate the results.
Practical Connection
Since Verex uses LMSR alongside a CLOB, the real implementation questions are: at what point does the market maker's price diverge from the order book's best quote, and how do you compute log-sum-exp safely in fixed-point arithmetic so that rounding error doesn't accumulate systematically against the market maker.
Where it lands in Jayverse
- Verex: bound LMSR divergence from the CLOB with an explicit threshold. Compare the LMSR quoted price against the CLOB best quote at varying liquidity parameter b, and trigger a maker-parameter review when divergence crosses a set number rather than drifting silently.
- Verex: put the liquidity parameter's max-loss bound into the market-maker config. LMSR's finite max-possible-loss is a direct function of b; that number belongs alongside slippage tuning as an operating loss budget, not just a code comment.
- Auditor: test the fixed-point log-sum-exp for accumulated rounding error. The same "was this computed under the invariant" question from the Liquid issuance case applies here — add a numerical-stability test over a long trade sequence, not just a single-call unit test.
Key expressions
| Expression | 뜻 · 쓰이는 자리 |
|---|---|
| path independence | 경로 독립성 · 어떤 경로로 거래해도 최종 비용이 같아지는 성질을 가리킬 때. "path independence holds" |
| bootstrapping | 초기값 없이 스스로 시작하기·마중물 역할 · 유동성이 전혀 없어도 가격을 제시할 수 있는 기능. "used for bootstrapping initial liquidity" |
| trade-off | 상충 관계·맞바꿈 · 한쪽을 얻으면 다른 쪽을 포기해야 하는 관계. "a direct trade-off between slippage and the operating loss budget" |
| diverge from | ~에서 벗어나다·어긋나다 · 두 가격이 서로 달라지기 시작하는 지점을 물을 때. "the market maker's price diverge from the order book's best quote" |
| upper bound | 상한·최댓값 · 손실이 아무리 커도 넘지 못하는 한계선을 말할 때. "raises the upper bound on the market maker's maximum possible loss" |
| accumulate against | ~에 불리하게 누적되다 · 반올림 오차 등이 한쪽에만 계속 쌓이는 것을 말할 때. "doesn't accumulate systematically against the market maker" |
| LMSR | 로그마켓스코어링룰(Logarithmic Market Scoring Rule) · 로그 스코어링 규칙에서 유도된 자동화 마켓메이커 비용함수. "LMSR is derived from the logarithmic scoring rule" |
| CLOB | 중앙집중형 지정가 주문장(Central Limit Order Book) · Verex가 LMSR과 함께 쓰는 전통적 호가창 거래 메커니즘. "Since Verex uses LMSR alongside a CLOB" |
If you study this on a given day, add a note link and a ✅ to this line in the source curriculum (docs/knowledge/math-50-curriculum.md) and this spot will lead straight to the note body. You can also write directly on this page — but regenerating overwrites it, so it's safer to keep anything you want to save as markdown under docs/algorithms/.