Market 객체
GET /v2/markets와 GET /v2/pairs/{market_id}가 반환하는 표준 market 객체, 그리고 실시간 스트림 봉투(envelope).
API는 REST와 스트림 전반에서 하나의 표준 market 객체를 제공합니다. GET /v2/markets는 그 목록을 반환하고, GET /v2/pairs/{market_id}는 전체 상세 블록이 첨부된 하나의 객체를 반환합니다. 더 이상 별도의 lean-tick 형태는 없습니다. 같은 객체가 식별 정보, 가격, 정산 정보를 모두 담으며, 가격과 정산 블록은 요청에서 요구한 부분만 채워집니다.
GET /v2/markets: 카탈로그로, 매칭된 경기당 한 행입니다. 필터 없이는 가격이null입니다.signal=arb는 실시간 스냅샷에서 가격이 매겨지고 확정된 arb로 필터링된 동일한 행을 반환합니다.GET /v2/pairs/{market_id}: id로 조회하는 하나의 마켓이며, 기본적으로include=ids,depth,settlement가 적용됩니다: 거래소 식별자, 신뢰도, 결과별 북 상세 정보, 정산 공개 정보.
market 객체
{
"id": "dino_8f3a1c92-47e8-4c3f-b9d2-f1a8e6c4d5f2",
"slug": null,
"sport": "baseball",
"league": "MLB",
"title": "Nyy vs Bos",
"home": null,
"away": null,
"start_time": "2026-07-01T23:05:00+00:00",
"status": "open",
"match": "high_confidence",
"signal": "arb",
"spread_pts": 2.0,
"potential_arb_pct": 1.83,
"coverage": { "kalshi": true, "polymarket": true },
"outcomes": [
{ "key": "NYY", "name": "NYY", "kalshi": 0.52, "polymarket": 0.54, "cheaper": "kalshi" },
{ "key": "BOS", "name": "BOS", "kalshi": 0.50, "polymarket": 0.46, "cheaper": "polymarket" }
],
"result": null,
"updated_at": "2026-07-01T22:55:00+00:00",
"priced_at": "2026-07-01T22:55:00+00:00",
"links": { "kalshi": "https://kalshi.com/markets/KXMLBGAME-26JUL01NYYBOS", "polymarket": null }
}
객체 필드
| Field | Type | Meaning |
|---|---|---|
id | string | 안정적인 표준 id, dino_<uuid>. GET /v2/pairs/{market_id}를 호출할 때 사용합니다. |
slug | string|null | 정돈된 이름 식별자입니다. 아직 채워지지 않았으며, 현재는 항상 null입니다. |
sport | string | 넓은 범주의 스포츠 키. |
league | string|null | 스포츠 내의 대회로, MLB와 같습니다. 거래소 시리즈가 이름을 지정하지 않으면 null입니다. |
title | string|null | 매칭된 팀 식별자로부터 만든 최선형 타이틀. |
home / away | string|null | 아직 채워지지 않았으며, 현재는 항상 null입니다. |
start_time | string|null | ISO-8601 UTC 킥오프 시각. |
status | string | open, live, closed, settled 중 하나. Status를 참고하세요. |
match | string | 매치 신뢰도 라벨. 현재 제공되는 행은 항상 high_confidence입니다. |
signal | string | "arb" 또는 "spread". Signal을 참고하세요. |
spread_pts | number|null | 결과별 크로스벤뉴 갭의 최댓값(백분점 기준). 모든 결과가 두 거래소에서 가격이 매겨지지 않은 한 null입니다. |
potential_arb_pct | number|null | 거래소 수수료를 반영하기 전, ask 대 ask 기준의 총수익률. signal이 "arb"일 때만 채워집니다. priced_at 시점의 스냅샷에 대한 관측값입니다. |
coverage | object | { kalshi, polymarket }. 각 결과에 해당 거래소의 가격이 모두 있을 때만 true입니다. |
outcomes | array | 결과별 가격 정보. Outcomes를 참고하세요. 행에 가격이 없으면 빈 배열입니다. |
result | object|null | 정산 결과이며, status가 settled가 된 이후에만 채워집니다. |
updated_at | string|null | 매칭 엔진이 이 페어의 식별 정보와 정산 조건을 마지막으로 다시 분석한 시점. |
priced_at | string|null | 신선도 신호입니다. REST에서는 현재 updated_at과 같은 값입니다. 행별로 별도의 실시간 가격 타임스탬프가 아직 저장되지 않기 때문이며, "마지막 가격 틱"이 아니라 "이 페어에 대한 마지막 기록"으로 취급하세요. WebSocket markets:* 스트림에서는 두 프레임 유형(market과 price) 모두 실제 캡처 시점을 전달합니다. updated_at도 없는 행에서만 null입니다. |
links | object | { kalshi, polymarket } 거래소 URL. 안정적인 링크 형태가 준비되기 전까지 polymarket은 null입니다. |
Outcomes
outcomes의 각 항목은 두 거래소에서의 가격을 포함한 하나의 마켓 결과(예: 한 팀)입니다.
| Field | Type | Meaning |
|---|---|---|
key / name | string | 팀명과 같은 결과 라벨. |
kalshi | number|null | Kalshi의 ask 가격, 0에서 1. 사용할 수 없으면 null이며, 부재를 나타내는 데 0을 쓰지 않습니다. |
polymarket | number|null | Polymarket의 ask 가격, 0에서 1. 사용할 수 없으면 null입니다. |
cheaper | string|null | 이 결과에서 ask가 더 낮은 거래소, "kalshi" 또는 "polymarket". 어느 한쪽이라도 가격이 없으면 null입니다. |
include=depth를 사용하면 각 결과에 kalshi_book과 polymarket_book도 실립니다. 이는 ask, depth, 거래소 티커 또는 토큰 id를 담은 부가 객체이며, 스칼라 kalshi / polymarket 가격 필드를 대체하지 않습니다.
Status
| Value | Meaning |
|---|---|
open | 활발히 매칭되고 추적 중입니다(내부적으로 active와 review 대상 페어를 모두 포함합니다). |
live | 진행 중인 경기를 위해 예약된 값입니다. 아직 제공되지 않으며, 오늘 기준 어떤 행도 live를 반환하지 않습니다. |
closed | 정산 결과 없이 취소된 상태입니다. |
settled | 정산 결과가 기록된 채 취소된 상태이며, result가 채워집니다. |
open 상태의 행만 spread 외의 signal을 가질 수 있습니다. open이 아닌 행은 어떤 가격이 붙어 있든 항상 signal을 spread로, potential_arb_pct를 null로 강제합니다.
Signal
signal은 매칭 엔진이 해당 마켓에 대해 찾아낸 정산 관계를 나타내며, 매 요청마다 현재 행과 가격을 기준으로 다시 도출됩니다. 캐시된 라벨을 그대로 신뢰하는 일은 없습니다.
| Value | Meaning |
|---|---|
"arb" | 획득된 상태입니다. 다음을 모두 충족합니다: 상태가 open이고 확인이 2건 이상, 정산 정합성 확인됨, 페어의 전체 내부 리스크 셋에 high 또는 critical 심각도 리스크 없음, 모든 결과가 두 거래소에서 가격이 매겨져 있음. potential_arb_pct가 채워집니다. |
"spread" | 확정된 arb가 아닌 모든 경우입니다. 정산 리스크가 공개된, 올바르게 매칭된 경기, 가격이 없는 카탈로그 행, 검토 대상 candidate가 포함됩니다. spread 행을 거래 가능한 것으로 취급하기 전에 반드시(include=settlement 또는 /v2/pairs/{market_id}를 통해) settlement.risks를 확인하세요. |
응답되는 settlement.risks에는 취소(cancel_*) 이벤트가 서버 측에서 필터링되어 절대 포함되지 않지만, signal 게이트는 여전히 전체 내부 셋을 대상으로 평가됩니다. arb 행도 통상적인 정산 정합성을 깨뜨리지 않는 범위 내의 비취소성 항목을 여전히 가질 수 있으므로, arb이 곧 빈 risks[]를 의미하지는 않습니다. 실행하기 전에는 항상 정산 블록을 확인하세요.
이 점수들이 어떻게 산출되는지, 즉 매칭 스윕, 퍼지 상한, 자동 승격 게이트까지 포함한 내용은 매칭 및 신뢰도에서 다룹니다.
WebSocket에서
market 객체는 markets:* 채널에서 평평한(flat) 프레임으로 전달됩니다: market 프레임(상태 변경 시 전달되는 전체 표준 객체)과 price 프레임(가격 변동 시 전달되는, 결과 key 기준의 압축 델타)입니다. 두 프레임 유형 모두 WebSocket 스트림 페이지에 문서화되어 있습니다.
REST로 부트스트래핑하기
GET /v2/markets는 stream-offset 필드를 갖지 않습니다. v2에는 as_of_offset이 없습니다. 완전한 그림으로 시작한 다음 실시간을 유지하려면: 먼저 /v2/markets?signal=arb로 지금 열려 있는 arb를 읽은 다음 WebSocket 스트림에 연결하세요. 연결 이후 도착하는 메시지는 그 시점부터 끊김이 없습니다. v2에는 스냅샷-오프셋 이어붙이기가 없으므로, REST 읽기와 스트림 연결을 두 개의 독립적인 뷰로 취급하세요. WebSocket 스트림 페이지는 연결 방법과 연결 끊김 복구를 다룹니다.