Skip to content
← 블로그

Kalshi와 Polymarket 안전하게 비교하기

dino.markets

Kalshi와 Polymarket을 비교하는 작업은 계약 조건에서 시작합니다. 두 리스팅은 같은 이벤트를 평범한 문장으로 설명하면서도, 서로 다른 결과, 관측 기간, 데이터 소스, 또는 경계 기준에 따라 정산될 수 있습니다. 이 조건을 확인하기 전에 두 가격을 나란히 놓으면, 서로 다른 두 주장을 정밀해 보이게 비교하는 결과가 됩니다.

Dino는 관련된 리스팅을 하나의 Market 객체로 매칭하고, 정산 차이를 그 객체에 함께 담아 둡니다. 이 튜토리얼은 Python SDK를 사용해 한 쌍을 확인하고, 계약 조건 검토가 끝난 뒤에만 가격 차이를 계산합니다.

매칭된 Market과 상세 정보 가져오기

무료 API 키를 생성하고 클라이언트를 설치합니다. 그런 다음 열려 있는 시장 패밀리를 요청합니다. 이 예제는 관측소와 버킷 차이가 공시 정보에서 쉽게 드러나는 날씨를 사용합니다:

export DINO_API_KEY=sk_live_...
pip install dino-markets
from dino_markets import Dino

client = Dino()
catalog = client.markets(
    category="weather",
    market_type="weather_high",
    status="open,live",
    limit=20,
)

summary = next(
    (
        market
        for market in catalog["markets"]
        if market["coverage"]["kalshi"]
        and market["coverage"]["polymarket"]
    ),
    None,
)
if summary is None:
    raise SystemExit("No two-venue weather comparison is available right now.")

market = client.market(summary["id"])

목록 결과는 안정적인 Dino id와 현재 지연된 가격을 제공합니다. client.market(id)는 정규화된 컨텍스트, 거래소 정체성, 뎁스, 정산 공시를 추가해 완전한 비교를 가능하게 합니다.

공시 정보를 검토 체크리스트로 바꾸기

다음 함수는 가격을 계산하기 전에 네 가지 확인 사항을 눈에 보이게 만듭니다:

def comparison_checks(market):
    settlement = market.get("settlement") or {}
    risks = settlement.get("risks") or []
    served_blocking = [
        risk
        for risk in risks
        if risk.get("severity") == "high"
    ]
    fully_priced = bool(market["outcomes"]) and all(
        outcome.get("kalshi") is not None
        and outcome.get("polymarket") is not None
        for outcome in market["outcomes"]
    )

    return {
        "entity_match_served": market["match"] == "high_confidence",
        "full_price_coverage": fully_priced,
        "settlement_parity": settlement.get("parity") is True,
        "served_blocking_risks": served_blocking,
    }

checks = comparison_checks(market)
print(checks)

match는 정체성 질문에 답합니다. 즉 두 리스팅을 함께 제공해도 될 만큼, 그것들이 같은 이벤트나 근본적인 주장을 나타낸다는 충분한 근거를 Dino가 가지고 있는지를 뜻합니다. 전체 가격 커버리지는 모든 결과를 두 거래소에서 비교할 수 있는지를 답합니다. 정산 패리티와 노출된 리스크 목록은, 아래의 취소 공시 사항을 전제로, 매칭된 결과가 호환되는 조건으로 정산되는지를 보여줍니다.

Market은 정산상의 유의 사항을 지니고 있으면서도 유효한 거래소 간 비교가 될 수 있습니다. 이 경우 signalspread로 유지되며, 그 유의 사항은 가격 옆에 함께 표시되어야 합니다. 확정된 Opportunity는 더 높은 기준을 통과해야 하며, 별도의 /v2/arbitrage 리소스에서 제공됩니다.

계약 조건을 계층별로 읽기

Market 상세 필드를 고정된 검토 순서로 사용합니다:

확인 항목필드확인할 내용
정체성match, title, 카테고리 맥락두 거래소의 리스팅이 같은 이벤트나 주장을 가리킵니다.
결과outcomes[].key, outcomes[].name버킷이 실제 세계의 결과와 같은 범위를 다룹니다.
커버리지coverage, 결과 가격비교가 필요한 모든 지점에서 두 거래소 모두 실제 가격을 보유합니다.
정산settlement.parity, settlement.risks[], settlement.kalshi_text, settlement.poly_text정산 소스와 컷오프 기준이 서로 호환되거나 공시되어 있습니다. 취소 관련 문구는 각 거래소의 규정 텍스트에서 확인합니다.

노출되는 settlement.risks[]는 내부 cancel_* 이벤트를 의도적으로 제외합니다. 각 거래소의 취소 조건은 kalshi_textpoly_text에서 확인합니다. Dino는 이러한 이벤트를 공개 리스크 목록에서 걸러내기 전, 전체 내부 리스크 집합을 바탕으로 settlement.paritysignal을 계산합니다.

날씨 시장은 각 계층이 왜 중요한지 보여줍니다. 두 개의 일일 최고기온 계약이 같은 도시를 이름으로 내걸면서도, 서로 다른 기상 관측소 데이터로 정산될 수 있습니다. 기온 구간도 1도 차이로 어긋나 있을 수 있습니다. Dino는 각 거래소의 실제 버킷을 그대로 유지하며, 결합된 가격을 임의로 만들어내는 대신 겹치는 부분을 보고합니다.

암호화폐 임계값 시장은 또 다른 경계 문제를 드러냅니다. 한 거래소는 '해당 가격 이상'으로 정산하는 반면, 다른 거래소는 '해당 가격 초과'를 기준으로 사용할 수 있습니다. 이 경우 정확히 그 임계값에서 발생하는 가격 차이는, 두 제목이 같은 자산과 숫자를 언급하더라도, 실제로는 승리 조건이 다른 계약을 가리키는 것입니다.

가격 차이는 마지막에 계산하기

공시 정보를 검토한 뒤에는, 가격이 온전히 매겨진 결과별로 관측된 차이를 계산합니다:

for outcome in market["outcomes"]:
    kalshi = outcome.get("kalshi")
    polymarket = outcome.get("polymarket")
    if kalshi is None or polymarket is None:
        continue

    gap_pts = abs(kalshi - polymarket) * 100
    print(
        outcome["name"],
        f"Kalshi {kalshi:.2f}",
        f"Polymarket {polymarket:.2f}",
        f"gap {gap_pts:.1f} pts",
    )

이 결과는 Market의 priced_at 타임스탬프 시점에서의 거래소 간 스프레드입니다. 이는 두 관측 가격이 얼마나 떨어져 있는지를 나타낼 뿐입니다. 실제 체결에는 현재 오더북 데이터, 이용 가능한 사이즈, 수수료, 호환되는 정산 조건이 필요합니다. 개발자용 데이터이며 거래 또는 금융 조언이 아닙니다.

정체성 확인과 발동 게이트에 대해서는 Dino가 시장을 매칭하는 방식을, 위에서 사용된 모든 필드에 대해서는 Market 객체 레퍼런스를 참고합니다. 라이브 보드에서는 같은 공시 정보를 사람이 읽기 쉬운 형태로 확인할 수 있습니다.

블로그의 다른 글