데모

LMSR과 하이브리드 AMM

첫 유동성을 돈으로 사는 방법과, 그 값이 왜 미리 아는 숫자인가 — 그리고 이 설계에 유효기간이 있다는 것.

공식

LMSR(로그 시장 스코어링 규칙)은 미결제 주식 벡터 q에 대해 하나의 비용 함수를 정의합니다:

C(q) = b · ln( Σᵢ e^(qᵢ / b) )

pᵢ(q) = e^(qᵢ/b) / Σⱼ e^(qⱼ/b)      →  Σ pᵢ = 1  (항상)

최악 손실 = b · ln(n)      →  b=250, n=2  ⇒  ≈ 173 USDC

여기서 중요한 건 세 번째 줄입니다. b·ln(n)은 리스크 추정치가 아니라 최댓값입니다 — 예산 항목에 적을 수 있는 숫자죠. b는 깊이와 슬리피지를 맞바꾸는 손잡이입니다: b가 크면 호가가 두꺼워지고 가격이 덜 밀리지만, 그만큼 최대 보조금도 커집니다.

스프레드는 누가 정하고, 누가 지불하는가

"스프레드가 넓다"는 사실 하나에 서로 다른 질문 셋이 섞여 있습니다. 나누면 혼란이 풀립니다.

질문
스프레드는 왜 넓은가?정보 거래자가 존재하기 때문 — 그 위험을 가격에 반영한 것
왜 경쟁이 좁히지 않는가?그 마켓에서 경쟁하는 메이커가 적기 때문
그런데 왜 누군가는 그 값을 내는가?무지한 거래자가 존재하기 때문

스프레드는 정보 거래자 때문에 설정되고, 무지한 거래자에 의해 지불된다.

두 사실이 같은 숫자 안에 함께 삽니다. 2센트에서 8센트로 벌리는 건 동시에 두 가지를 말합니다 — "여러분 중 의미 있는 비율이 뭔가를 안다고 본다", 그리고 "모르는 사람이 충분히 많아서 이 값을 여전히 받을 수 있다".

정보 비율을 올리면 — 시장이 사라진다

정보  5%  →  2센트 스프레드로 가능
정보 15%  →  8센트 스프레드로 가능
정보 40%  →  어떤 스프레드로도 불가능

어느 지점부터는 정보 흐름을 견딜 만큼 넓은 스프레드가 너무 넓어서 무지한 거래자 누구도 지불하지 않습니다. 메이커의 유일한 합리적 선택은 호가를 접는 것입니다. 이것이 고전적인 시장 붕괴(market breakdown) 결과이고, 실제 시장에서 형편없는 호가 대신 아예 호가가 없는 상태를 보게 되는 이유이기도 합니다. 호가가 없는 시장은 고장난 시장이 아니라 올바르게 가격이 매겨진 시장입니다.

그래서 "스프레드가 넓으니 정보 거래자가 적다"는 아니고, 한 단계 강한 다음 문장이 맞습니다:

시장이 존재한다는 것 자체가 — 스프레드가 얼마든 — 그것을 지탱할 무지한 흐름이 충분하다는 증거다.

넓은 스프레드의 두 가지 해석

위와 무관한 두 번째 이유가 있습니다 — 경쟁. 열 명의 메이커가 한 마켓을 호가하면 서로 깎아 진짜 정보비용까지 내려갑니다. 한 명뿐이면 그 위로 받고 차액을 챙길 수 있습니다. 밖에서는 둘을 구별하기 어렵습니다.

해석신호
정직실제로 위험한 마켓, 올바르게 가격 매겨짐넓은데 거래량이 많음
지대(rent)경쟁 없는 메이커 하나가 마음대로 받는 값넓은데 거래량이 얇음

그럼 Polymarket은 왜 안 쓰는가

먼저 프레임부터 바로잡아야 합니다: 하이브리드 AMM은 더 발전된 설계가 아닙니다. 정말 우월하다면 Polymarket이 안 쓴다는 사실 자체가 문제의 증거일 겁니다. 더 발전된 게 아니라 트레이드오프 위의 다른 지점이고, 그 거래는 특정 단계에서만 말이 됩니다.

  1. 그들에겐 그 문제가 없다. LMSR 호가는 콜드 스타트를 해결합니다. Polymarket은 유동성 있는 모든 마켓에 전문 마켓메이커가 경쟁합니다. 거기에 보조금 사다리를 얹는 건 이미 공짜로 얻는 유동성과 경쟁하려고 돈을 쓰는 일 — 이미 다른 방법으로 나은 병에 대한 치료제입니다.
  2. 보조금은 상장 수에 비례한다. b=250 이진 마켓 하나당 최악 ≈173 USDC. 10개면 괜찮고, 수천 개면 구조적 비용 센터입니다. 게다가 돌아오는 수수료가 아니라 손실입니다. 그들의 경제 구조는 수수료·리워드 기반이고 이건 보조금 기반이라, 규모가 커지면 잘 섞이지 않습니다.
  3. 역선택 — 실제로 물어뜯는 문제. LMSR에는 견해가 없습니다. 뉴스가 터져도 공식대로 계속 호가합니다. 사람 메이커는 정보 냄새를 맡으면 벌리거나 취소하지만, 사다리는 그냥 앉아서 털립니다. b·ln(n)이 총손실 상한이긴 하나 — 가장 크게 틀린 마켓에서 정확히 그 상한에 빠르게 도달합니다. 정교한 트레이더가 많은 거래소에서 오퍼레이터는 구조적으로 항상 마지막에 아는 사람입니다.
  4. 상대방이 되는 것과 거래장소가 되는 것은 위치가 다르다. 주문만 매칭하는 CLOB 운영자는 중립적 중개자입니다. 양방향 호가를 내고 재고를 지는 운영자는 마켓메이킹 — 대리인(agent)이 아니라 본인(principal)입니다. Polymarket의 규제 이력을 보면 구조적 중립성 유지는 실수가 아니라 의도로 보입니다. "하우스가 자기 테이블에서 같이 플레이한다"는 인상 문제도 있고요.

그리고 역사적 사실 하나: 그들은 이미 AMM(FPMM)을 운영했고 폐기했습니다. 진짜 메이커들이 들어온 뒤로는 오더북보다 스프레드도 자본 효율도 나빴기 때문입니다. 이 설계를 건너뛴 게 아니라 졸업한 겁니다.

그럼에도 신규 거래소가 써야 하는 이유

그들이 다른 방식으로 푼 그 문제가 우리에겐 있고, 그들의 해법은 우리가 쓸 수 없다.

빈 거래소에 마켓메이커를 데려올 수는 없습니다. 빈 호가창 → 가격 없음 → 트레이더 없음 → 거래량 없음 → 메이커가 올 이유 없음 → 빈 호가창. Polymarket은 이미 그 루프를 빠져나왔기 때문에 빠져나온 상태입니다. 신규 거래소는 첫 유동성을 스스로 사는 것 외에 방법이 없고, LMSR은 그걸 미리 아는 상한으로 해내는 가장 저렴한 알려진 방법입니다.

위의 네 반론은 전부 규모(scale)에 관한 것이고, 초기 단계에서는 하나도 구속력이 없습니다:

그들의 반론초기 단계에서 안 걸리는 이유
진짜 메이커와 중복한 명도 없음
상장 수에 비례하는 보조금마켓 10개지 10,000개가 아님
역선택정보 흐름은 거래량의 함수 — 둘 다 없음
본인 vs 거래장소 포지션진짜 문제지만 출시 전이 아니라 제품화 이후의 문제

이 채택을 안전하게 만드는 설계 결정

정당한 수준을 넘어 안전하게 만드는 건, 이 단계가 제거를 전제로 만들어졌다는 점입니다. 풀 컨트랙트가 없습니다. LP 지분도 없습니다. 별도 거래장소도 없습니다. AMM이 시스템에 물리적으로 존재하는 형태는 같은 오더북 안의 평범한 지정가 주문뿐입니다. 그래서 끄는 방법은 — 그냥 게시를 멈추는 것. 마이그레이션 없음, LP 청산 없음, 폐기할 컨트랙트 없음, 자금이 묶이는 사용자 없음.

Polymarket이 자기 AMM을 떠나며 해야 했던 일과 비교해 보세요 — 실제 LP 자금이 든 라이브 컨트랙트를 폐기하고 전원을 이전시켜야 했습니다. 그들이 버린 아이디어인데도 이 버전이 옳은 이유가 그것입니다. 그들은 비계를 건물 안에 지어 넣었고, 이쪽은 바깥에 볼트로 붙였습니다.

솔직한 실패 시나리오

위험은 LMSR이 틀렸다는 게 아닙니다. 사다리가 영구화되는 것입니다 — 제3자 메이커가 끝내 오지 않고, 거래소는 영원히 하우스가 호가를 대는 곳으로 남아, 사용자는 계속 오퍼레이터를 상대로 거래하고 보조금은 무기한 나갑니다. 이건 버그가 아니라 사업 결과이고, 코드에서는 절대 보이지 않습니다.

그래서 명시적인 종료 조건이 필요합니다 — 예를 들어 제3자 메이커 체결 비중이 X%를 넘으면 그 마켓의 b를 낮추고, 오퍼레이터 비중이 일정 아래로 떨어지면 게시를 완전히 중단. 상수 b에 아무 정책도 붙어 있지 않다면, 그 공백 자체가 다음 단계 전에 짚어야 할 항목입니다.

한 줄 요약

Polymarket은 이게 필요 없고, 그들 규모에서는 감당이 안 되며, 채택하면 포지션이 나빠진다. 신규 거래소는 필요하고, 그 규모에서는 감당되며, 필요 없어지는 날 버릴 수 있게 만들면 된다. 성공한다면 결국 Polymarket처럼 보여야 한다 — 사다리는 거기까지 가는 수단이지 도착지가 아니다.

기술 노트

각 항목이 실제로 무엇을 보여주고 어떻게 동작하는지 — 위 카드보다 자세한 기술 설명입니다.

LMSR과 하이브리드 AMM — 첫 유동성을 돈으로 사기라이브

목적: 신규 거래소는 논리로 빠져나올 수 없는 루프에 갇힙니다: 빈 호가창 → 가격 없음 → 트레이더 없음 → 거래량 없음 → 마켓메이커가 올 이유 없음 → 빈 호가창. 빈 거래소에 메이커를 데려올 수는 없으니, 유일한 출구는 첫 유동성을 스스로 사는 것입니다. LMSR은 그것을 미리 아는 상한으로 해내는 가장 저렴한 알려진 방법입니다 — 최악의 보조금은 b·ln(n), 추정치가 아니라 최댓값입니다. 진짜 흥미로운 건 반대 증거입니다: Polymarket은 AMM을 운영했고 진짜 메이커들이 들어오자 폐기했습니다. 이건 설계의 흠이 아니라 설계의 유효기간이고, 자기가 그 날짜의 어느 쪽에 있는지 아는 것이 기술의 전부입니다.

동작 방식: 페이지는 논증을 두 덩어리로 나눠 짚습니다. 첫째, 스프레드를 누가 정하고 누가 지불하는가: 스프레드는 정보 거래자 때문에 설정되고 무지한 거래자에 의해 지불되며, 두 사실이 같은 숫자 안에 함께 삽니다. 정보 비율을 올리면 그것을 견디는 스프레드가 넓어지고 — 5%면 2센트, 15%면 8센트 — 어느 지점부터는 견딜 만큼 넓은 스프레드가 아무도 지불하지 않을 만큼 넓어져, 합리적인 메이커는 호가를 접습니다. 호가가 아예 없는 시장은 고장난 시장이 아니라 올바르게 가격이 매겨진 시장입니다. 둘째, 설계의 유효기간: Polymarket이 보조금 사다리를 쓰지 않는 네 가지 이유 — 이미 진짜 메이커가 있고, 보조금은 상장 수에 비례하며, LMSR은 견해가 없어 뉴스에 털리고, 양방향 호가는 운영자를 거래장소가 아닌 본인(principal)으로 만듭니다. 전부 규모에 관한 반론이고, 거래량이 없는 거래소에는 하나도 구속력이 없습니다. 채택을 단지 정당한 수준이 아니라 안전하게 만드는 건, 사다리가 같은 오더북 안의 평범한 지정가 주문뿐이라 제거가 그저 게시를 멈추는 일이라는 점입니다. 아직 계획 단계: 공식을 만질 수 있게 하는 인터랙티브 패널 — 미결제 주식 벡터 q 슬라이더, 항상 합이 1이 되는 가격 pᵢ = e^(qᵢ/b) / Σe^(qⱼ/b), 그리고 b·ln(n) 천장으로 다가가되 결코 넘지 못하는 누적 최악 손실.

콜드 스타트 루프, 그리고 유일한 출구
정보가 정하고 무지가 지불한다 — 둘 다 안 되는 지점까지
관련 코드:
"""LMSR (Logarithmic Market Scoring Rule): cost function C(q) = b*ln(sum(exp(q_i/b))),
prices p_i = exp(q_i/b) / sum(exp(q_j/b)). Buying shares of one outcome shifts
its price up and the cost paid is C(q_after) - C(q_before).
"""
import math

def cost(q, b):
    return b * math.log(sum(math.exp(qi / b) for qi in q))

def prices(q, b):
    exps = [math.exp(qi / b) for qi in q]
    total = sum(exps)
    return [e / total for e in exps]

def buy(q, outcome_idx, shares, b):
    q_after = list(q)
    q_after[outcome_idx] += shares
    trade_cost = cost(q_after, b) - cost(q, b)
    return q_after, trade_cost


b = 100  # liquidity parameter: higher b = deeper market, higher worst-case subsidy
n_outcomes = 2
q = [0.0, 0.0]  # outstanding shares per outcome, starts at zero net position

print(f"initial prices: {[round(p, 4) for p in prices(q, b)]} (should be uniform)")
print(f"worst-case subsidy bound b*ln(n) = {b * math.log(n_outcomes):.2f}\n")

q, paid = buy(q, outcome_idx=0, shares=50, b=b)
print(f"bought 50 shares of outcome 0, paid {paid:.2f}")
print(f"prices after trade: {[round(p, 4) for p in prices(q, b)]}")

q, paid = buy(q, outcome_idx=0, shares=50, b=b)
print(f"\nbought another 50 shares of outcome 0, paid {paid:.2f} (costs more -- price moved)")
print(f"prices after trade: {[round(p, 4) for p in prices(q, b)]}")

docs/code/pocs/lmsr-hybrid-amm.py