본문으로 건너뛰기

WebSocket 스트림

시장 데이터, 계정, 창 레이아웃, 설정을 하나의 연결로 받습니다.

주소: ws://127.0.0.1:48180/v1/stream · AsyncAPI 파일

연결

  • 주소: ws://127.0.0.1:48180/v1/stream.
  • 토큰은 핸드셰이크의 Authorization: Bearer <token> 헤더로 보냅니다. 핸드셰이크에는 market:read 권한이 필요합니다. HTTP 요청과 같은 규칙에 따라 401 또는 403으로 거부됩니다.
  • 서버는 20초마다 WebSocket ping을 보냅니다. 50초 동안 pong이 오지 않으면 서버가 연결을 닫습니다.
  • 클라이언트가 연결을 닫으면 서버는 클라이언트의 코드를 담은 close 프레임으로 응답합니다.
  • 소켓을 닫으면 연결의 모든 구독이 제거됩니다. 명시적인 unsubscribe는 구독 하나를 즉시 제거합니다.
  • 구독자가 없는 페어는 30초 뒤 거래소에서 해제됩니다.

종료 코드

코드의미
1001API가 꺼졌거나 토큰이 재발급됨
4008클라이언트가 너무 느려 5초 넘게 따라오지 못함
4029토큰당 스트림 연결 수 제한

제한

GET /v1/meta가 제한을 반환합니다. 거부는 요청에 대한 응답인 error 프레임에 rate_limited가 담겨 오거나, 4029 종료로 나타납니다.

제한값
토큰당 스트림 연결 수8
연결당 구독 수100
API만을 위해 열린 종목 수50, 창에 열려 있는 종목은 제외
초당 신규 거래소 구독 수5

느린 클라이언트

읽지 않는 클라이언트는 터미널도 다른 클라이언트도 느리게 만들지 않습니다. 제때 가져가지 않은 프레임은 버려집니다. trades의 경우 gap 프레임이 잃어버린 번호를 알려 줍니다. 다른 토픽에서는 다음 프레임이 그저 더 최신일 뿐입니다.

시퀀스 번호

seq는 구독의 이벤트에 번호를 매깁니다. trades에서는 1씩 증가합니다. 최신 값만 전송되는 토픽에서는 번호에 누락이 있는 것이 정상입니다.

클라이언트 요청

프로그램이 터미널로 보내는 메시지입니다.

subscribe

토픽을 요청합니다.

토픽에 필요한 것은 토픽의 종류에 따라 다릅니다:

  • 시장 토픽은 trades, ticker, mark_price, book.top, clusters입니다. instrument는 필수입니다. connection_id는 공통 규칙에 따라 선택됩니다. 권한은 market:read입니다.
  • 계정 토픽은 account.*입니다. connection_id는 필수입니다. instrument는 사용하지 않습니다. 권한은 account:read입니다.
  • workspace 및 settings 토픽은 둘 다 받지 않습니다. 권한은 workspace:read와 settings:read입니다.

book.top만 params를 사용합니다. 다른 토픽은 이를 무시합니다.

필드타입설명
type필수"subscribe"
request_idstring선택 사항입니다. 응답에 그대로 반환됩니다.
topic필수Topic
instrumentstring종목 주소, exchange:market:symbol. 시장 토픽에는 필수입니다.
connection_idinteger계정 토픽에는 필수입니다. 시장 토픽에는 선택 사항입니다.
paramsobjectbook.top의 매개변수입니다.
params.depthinteger각 방향의 레벨 수입니다. Range: 1–200. 기본값: 50.
params.interval_msinteger두 프레임 사이의 최소 시간, 밀리초입니다. Range: ≥ 50. 기본값: 100.
Trades of a pair
{
  "type": "subscribe",
  "request_id": "r1",
  "topic": "trades",
  "instrument": "binance:futures:BTCUSDT",
  "connection_id": 12
}
Top of the book, 10 levels every 250 ms
{
  "type": "subscribe",
  "request_id": "r2",
  "topic": "book.top",
  "instrument": "binance:futures:BTCUSDT",
  "params": {
    "depth": 10,
    "interval_ms": 250
  }
}
Fills of a connection
{
  "type": "subscribe",
  "request_id": "r3",
  "topic": "account.fills",
  "connection_id": 12
}
The layout of the windows
{
  "type": "subscribe",
  "request_id": "r4",
  "topic": "workspace"
}

unsubscribe

구독을 해제합니다.

subscribed가 반환한 sub만 받습니다.

필드타입설명
type필수"unsubscribe"
request_idstring
sub필수stringsubscribed에서 받은 식별자입니다.
예시
{
  "type": "unsubscribe",
  "request_id": "r5",
  "sub": "7:trades"
}

서버 프레임

이벤트 외에 터미널이 응답하거나 직접 보내는 메시지입니다.

subscribed

구독이 설정되었습니다.

sub는 이후의 모든 프레임에서 구독을 식별합니다. 시장 토픽은 "{stream}:{topic}", 계정 토픽은 "{connection}:account.<topic>", 나머지 둘은 "workspace" 또는 "settings"입니다. 같은 페어와 토픽을 구독한 모든 클라이언트는 같은 sub를 받습니다. connection_id는 시장 토픽과 계정 토픽에 있습니다. workspace와 settings에는 없습니다.

필드타입설명
type필수"subscribed"
request_idstring
sub필수string
connection_idinteger선택된 연결입니다. workspace와 settings에는 없습니다.
예시
{
  "type": "subscribed",
  "request_id": "r1",
  "sub": "7:trades",
  "connection_id": 12
}

unsubscribed

구독이 제거되었습니다.

필드타입설명
type필수"unsubscribed"
request_idstring
sub필수string
예시
{
  "type": "unsubscribed",
  "request_id": "r5",
  "sub": "7:trades"
}

error

요청이 거부되었거나 서버가 구독을 제거했습니다.

request_id가 있으면 클라이언트의 요청에 대한 응답입니다. sub는 있고 request_id가 없으면 서버가 구독을 제거한 것입니다. 코드는 HTTP 작업의 코드와 같습니다.

필드타입설명
type필수"error"
request_idstring프레임이 요청에 대한 응답일 때 있습니다.
substring프레임이 구독과 관련될 때 있습니다.
code필수ErrorCode
message필수string사람이 읽기 위한 텍스트입니다.
A refused request
{
  "type": "error",
  "request_id": "r1",
  "code": "not_found",
  "message": "no connection for the instrument"
}
A subscription removed by the server
{
  "type": "error",
  "sub": "7:trades",
  "code": "unavailable",
  "message": "the exchange refused the subscription"
}

gap

클라이언트가 놓친 체결입니다.

trades에만 전송되며, 손실 뒤 첫 프레임 앞에 옵니다. 클라이언트가 읽지 않고 있었고, from_seq부터 to_seq까지의 이벤트가 손실되었습니다. GET /v1/market/trades와 since_ts로 다시 읽습니다.

필드타입설명
type필수"gap"
sub필수string
from_seq필수integer
to_seq필수integer
reason필수stringslow_consumer.
예시
{
  "type": "gap",
  "sub": "7:trades",
  "from_seq": 42,
  "to_seq": 57,
  "reason": "slow_consumer"
}

토픽

모든 이벤트는 같은 봉투를 사용하며 data는 토픽에 따라 다릅니다.

필드타입설명
type필수"event"
sub필수string이벤트가 속한 구독입니다.
seq필수integer구독 내 이벤트의 번호입니다.
ts필수integer프레임이 만들어진 시각, UTC 밀리초입니다.
data필수any이벤트의 데이터입니다. 형태는 토픽에 따라 다릅니다.
토픽필수 항목권한전달 방식
tradesinstrumentmarket:read순서대로 전달, 누락은 통지됨
tickerinstrumentmarket:read최신 값만 전달
mark_priceinstrumentmarket:read최신 값만 전달
book.topinstrumentmarket:read최신 값만 전달
clustersinstrumentmarket:read최신 값만 전달
account.ordersconnection_idaccount:read최신 값만 전달
account.positionsconnection_idaccount:read최신 값만 전달
account.balancesconnection_idaccount:read최신 값만 전달
account.fillsconnection_idaccount:read이벤트마다 프레임 하나
workspace없음workspace:read최신 값만 전달
settings없음settings:read이벤트마다 프레임 하나

trades

페어의 체결이며, 순서대로 전달됩니다.

data는 체결 배열이며, GET /v1/market/trades에서와 같습니다. 체결은 순서대로 옵니다. 클라이언트가 뒤처지면 gap 프레임이 무엇을 놓쳤는지 알려 줍니다.

데이터: Trade[]

예시
{
  "type": "event",
  "sub": "7:trades",
  "seq": 41,
  "ts": 1730294400130,
  "data": [
    {
      "id": null,
      "price": "67000.1",
      "qty": "0.012",
      "side": "buy",
      "ts": 1730294400125,
      "exchange_ts": 1730294400119
    }
  ]
}

ticker

페어의 24시간 티커입니다.

data는 티커이며, GET /v1/market/snapshot의 ticker와 같습니다. 최신 값만 전송됩니다.

데이터: Ticker

예시
{
  "type": "event",
  "sub": "7:ticker",
  "seq": 12,
  "ts": 1730294400130,
  "data": {
    "price": "67000.1",
    "change_24h_pct": "1.25",
    "volume_24h": "81234.5",
    "high_24h": null,
    "low_24h": null,
    "best_bid": null,
    "best_ask": null,
    "ts": 1730294400120
  }
}

mark_price

페어의 마크 가격입니다.

최신 값만 전송됩니다.

데이터: MarkPrice

예시
{
  "type": "event",
  "sub": "7:mark_price",
  "seq": 5,
  "ts": 1730294400130,
  "data": {
    "mark_price": "67001.0",
    "ts": 1730294400120
  }
}

book.top

페어의 호가창 상단입니다.

구독자마다 자신의 depth와 interval_ms를 설정합니다. 범위를 벗어난 값은 invalid_request로 거부됩니다. 첫 프레임은 호가창이 준비되는 즉시 옵니다. 그 뒤로는 interval_ms마다 최대 한 프레임이 최신 호가창과 함께 옵니다. seq는 호가창의 버전입니다.

데이터: BookTop

예시
{
  "type": "event",
  "sub": "7:book.top",
  "seq": 9031,
  "ts": 1730294400130,
  "data": {
    "ts": 1730294400123,
    "depth": 10,
    "bids": [
      [
        "67000.1",
        "1.25"
      ]
    ],
    "asks": [
      [
        "67000.2",
        "0.40"
      ]
    ]
  }
}

clusters

종목의 거래량 클러스터입니다.

data는 버킷 하나이며, GET /v1/market/clusters의 data 요소와 같습니다. 변경된 버킷마다 최대 16ms에 한 번, 최신 상태를 담은 프레임이 옵니다. 터미널에서 인터벌을 바꾸면 interval에 나타납니다.

데이터: ClusterBucket

account.orders

변경 후 한 종목의 주문과 트리거 주문입니다.

종목의 최신 상태만 전송됩니다. 구독은 거래소를 건드리지 않으며, 이벤트는 연결이 보내는 시점부터 옵니다. 구독 시 스냅샷 프레임은 없습니다. 현재 상태는 GET /v1/account/orders로 읽습니다.

데이터: InstrumentOrders

account.positions

변경 후 한 종목의 포지션입니다.

최신 상태만 전송됩니다. 청산된 포지션은 "position": null로 도착합니다. 구독 시 스냅샷 프레임은 없습니다.

데이터: InstrumentPosition

account.balances

한 통화의 잔고입니다.

data는 잔고 하나이며, GET /v1/account/balances의 data 요소와 같습니다. 최신 값만 전송됩니다. 구독 시 스냅샷 프레임은 없습니다.

데이터: Balance

account.fills

체결 내역 하나입니다.

체결 내역마다 프레임 하나가 옵니다. 클라이언트가 뒤처지면 프레임이 손실되고 seq에 누락이 나타납니다. GET /v1/account/fills와 since_ts로 체결 내역을 다시 읽습니다.

데이터: Fill

workspace

창의 전체 레이아웃입니다.

data는 레이아웃이며, GET /v1/workspace의 data와 같습니다. 첫 프레임은 현재 레이아웃이며 구독 즉시 전송됩니다. 그 뒤로는 변경이 있을 때마다 프레임이 옵니다. 최신 상태만 전송됩니다.

데이터: WorkspaceSnapshot

settings

기록된 설정 행 하나입니다.

설정 테이블에 쓸 때마다 프레임 하나가 옵니다: API, Settings App, 창 자체에서 쓴 경우 모두 해당합니다. 구독 시 스냅샷은 없습니다. 현재 값은 GET /v1/settings로 읽습니다. 클라이언트가 뒤처지면 프레임이 손실되고 seq에 누락이 나타납니다.

데이터: SettingWritten

예시
{
  "type": "event",
  "sub": "settings",
  "seq": 3,
  "ts": 1730294400130,
  "data": {
    "scope": "global",
    "scope_id": "default",
    "connection_id": null,
    "category": "multiview",
    "key": "stack_width_px",
    "value": 300
  }
}

데이터 타입

이벤트에 담기는 객체입니다. HTTP 작업도 같은 객체를 반환합니다.

Topic

tradestickermark_pricebook.topclustersaccount.ordersaccount.positionsaccount.balancesaccount.fillsworkspacesettings

ErrorCode

unauthorizedforbiddenforbidden_scopenot_foundinvalid_requestunsupportednot_activenot_tradablerate_limitedunavailable

안정적인 코드이며 계약의 일부입니다. 새 코드가 추가될 수 있습니다.

코드HTTP발생 조건
unauthorized401토큰이 틀리거나 API가 꺼져 있음
forbidden403Origin 헤더 또는 외부 Host
forbidden_scope403토큰에 해당 작업의 권한이 없음
not_found404그런 작업이나 연결이 없거나, 종목에 대한 연결이 없음
invalid_request400잘못된 매개변수: 종목, 인터벌, 깊이, 다른 거래소나 마켓의 connection_id
unsupported501거래소가 MOEX이거나, 터미널이 시장 데이터 없이 빌드되었거나, API로 쓸 수 없는 설정임
not_active409종목의 클러스터가 아직 계산되지 않았거나, 레버리지를 아직 불러오지 않음
not_tradable409연결이 거래할 수 없음: 비활성화되어 있거나, 읽기 전용이거나, 자격 증명이 없음
rate_limited429제한을 초과함: 연결, 구독, 종목, 초당 신규 구독, 거래 명령, 워크스페이스 명령 또는 설정 쓰기
unavailable503저장소, 거래소 또는 창이 응답하지 않았거나, 터미널이 바쁘거나, 아직 데이터가 없음

Trade

필드타입설명
id필수string | nullv1에서는 항상 null입니다.
price필수string
qty필수string
side필수"buy" | "sell"
ts필수integer터미널이 체결을 받은 시각, UTC 밀리초입니다.
exchange_ts필수integer거래소 시간입니다.

Ticker

24시간 티커입니다.

필드타입설명
price필수string
change_24h_pct필수string | null
volume_24h필수string
high_24h필수string | null
low_24h필수string | null
best_bid필수string | null
best_ask필수string | null
ts필수integer

MarkPrice

필드타입설명
mark_price필수string
ts필수integer

BookTop

호가창 상단입니다: 매수 호가는 최우선 가격부터 아래로, 매도 호가는 최우선 가격부터 위로.

필드타입설명
ts필수integer
depth필수integer
bids필수PriceLevel[]
asks필수PriceLevel[]

ClusterBucket

필드타입설명
interval필수string
ts필수integer버킷의 시작 시각, UTC 밀리초입니다.
end_ts필수integer
volume필수string
buy_volume필수string
sell_volume필수string
trades필수integer
vwap필수string | null
min_price필수string | null
max_price필수string | null
completed필수boolean
last_trade_ts필수integer버킷의 마지막 체결 시각입니다. 히스토리에서 온 버킷에 이 시각이 없으면 0입니다.
levels필수ClusterLevel[]버킷의 모든 가격 레벨이며, 가장 낮은 가격부터 가장 높은 가격 순입니다.

InstrumentOrders

필드타입설명
instrument필수string
orders필수Order[]
triggers필수Trigger[]

InstrumentPosition

필드타입설명
instrument필수string
position필수Position | null

Balance

필드타입설명
currency필수string
total필수string
available필수string | null
locked필수string | null
ts필수integer

Fill

필드타입설명
trade_id필수string
order_id필수string거래소의 주문 id입니다.
instrument필수string
side필수stringbuy 또는 sell.
price필수string
qty필수string
fee필수string
fee_currency필수string
position_side필수string | null헤지 모드가 있는 거래소에서는 long 또는 short, 그 외에는 null입니다.
ts필수integer거래소 시간입니다.

WorkspaceSnapshot

필드타입설명
windows필수Window[]id 오름차순입니다.

SettingWritten

기록된 그대로의 설정 행이며, writable은 없습니다.

필드타입설명
scope필수string
scope_id필수string | null
connection_id필수integer | null
category필수string
key필수string
value필수any임의의 JSON 값입니다.

PriceLevel

string[]

[price, size], 둘 다 10진수 문자열입니다.

ClusterLevel

필드타입설명
price필수string
volume필수string
buy_volume필수string
sell_volume필수string
buy_trades필수integer
sell_trades필수integer

Order

필드타입설명
key필수string | null터미널의 주문 키 t-…입니다. 알려질 때까지 null입니다.
exchange_id필수string | null거래소의 주문 id입니다. 거래소가 주문을 접수할 때까지 null입니다.
instrument필수string
side필수"buy" | "sell"
type필수"limit" | "market"
price필수string
size필수string기준 코인 단위입니다.
filled필수string
remaining필수string
notional필수string | null트레이더가 입력한 호가 통화 금액입니다. 거래소 스냅샷에서 온 주문은 null입니다.
status필수"pending" | "open" | "partially_filled"
created_ts필수integer | null거래소 스냅샷에서 온 주문에 시간이 없으면 null입니다.

Trigger

필드타입설명
id필수string트리거를 취소하고 수정할 때 쓰는 숫자 id입니다.
instrument필수string
type필수TriggerKind
trigger_price필수string
rule필수TriggerRule
size필수string | null기준 코인 단위입니다.
notional필수string | null호가 통화 단위입니다.
status필수"open" | "finished" | "inactive" | "invalid"
order_type필수string | null거래소의 주문 유형이며, 받은 그대로입니다.
client_id필수string | null트리거를 넣을 때 반환된 키입니다.
created_ts필수integer | null

Position

필드타입설명
instrument필수string
side필수"long" | "short"
size필수string기준 코인 단위입니다.
lot_size필수string1랏(lot)에 해당하는 기준 코인 수량입니다.
entry_price필수string
notional필수string호가 통화 단위입니다.
unrealized_pnl필수string터미널이 계산한 값입니다.
mark_price필수string | null롱이면 최우선 매수 호가, 숏이면 최우선 매도 호가입니다. 호가창의 첫 틱이 올 때까지 null입니다.

Window

필드타입설명
id필수integer
main필수boolean메인 창입니다. 이 창을 닫으면 터미널이 종료됩니다.
chart_window필수boolean분리된 차트 창입니다.
focused필수booleanOS 포커스를 가진 창입니다.
geometry필수object화면의 논리 픽셀 단위로 나타낸 위치와 크기입니다.
geometry.x필수integer
geometry.y필수integer
geometry.width필수integer
geometry.height필수integer
geometry.maximized필수boolean
monitor필수string | nullOS가 알려 주는 모니터 이름입니다.
tabs필수Tab[]

TriggerKind

stop_losstake_profitstop

TriggerRule

price_above_or_equalprice_below_or_equal

Tab

필드타입설명
id필수integer각 창 안에서 1부터 번호가 매겨집니다.
name필수string
active필수boolean한 창에서 활성 탭은 정확히 하나입니다.
stacks필수Stack[]
charts필수Chart[]

Stack

체결 테이프와 클러스터가 있는 호가창입니다.

필드타입설명
widget_id필수integer
instrument필수string | null스택이 비어 있는 동안에는 null입니다.
connection_id필수integer | null
empty필수boolean
frozen필수boolean스택이 동결된 상태입니다.
position필수Cell | null

Chart

필드타입설명
widget_id필수integer
instrument필수string | null
connection_id필수integer | null
interval필수string캔들 인터벌입니다: 1m, 5m, …
owner_widget_id필수integer | null차트가 따르는 스택입니다. 독립된 차트는 null입니다.
position필수Cell | null

Cell

탭 그리드의 셀입니다: 왼쪽부터의 열, 위부터의 행, 행 안의 셀.

필드타입설명
column필수integer
row필수integer
cell필수integer

이 페이지의 내용