Order flow 방법론, OBI × CVD 분면
Order flow 분면이 어떻게 소싱·크기 조정·해석되는가: 깊이에서 도출한 호가 불균형, taker 흐름 CVD, 롤링 P95 정규화, 존 분류, HTF 레짐, 신선도 규칙.
실시간 위젯 보기: /perpetuals/positioning.
데이터 출처
분면은 대기 깊이와 taker 흐름을 네 개의 무기한 거래소, Binance, Bybit, OKX, Hyperliquid, 에서 두 축 모두에 대해 집계합니다. 런타임은 전부 Rust이며, hot path에 Python 데몬은 없습니다.
- 깊이 인제스트.
mt-ingest바이너리가 각 거래소의 선물 깊이 피드를 여섯 자산 모두에 대해 구독하고, 거래소별 책을TOP_LEVELS_PER_SIDE = 200레벨(측면당)로 유지하며, 각 책을prod:<venue>:<asset>:depth에 게시합니다. 이 거래소별 책이 OBI 계산을 뒷받침합니다. - Taker 흐름 / CVD.
mt-cvd바이너리가 각 거래소의 체결 스트림을 크로스 거래소 체결 테이프(prod:trades:*)와 부호 있는 러닝 CVD(prod:*:cvd)로 소비합니다. 거래소별 taker 측 의미론은 이 단계에서 정규화됩니다, Bybit, OKX, Hyperliquid는 공격자 측을 Binance와 다르게 인코딩하며, 모두 하나의 부호 규약으로 매핑됩니다. - 크로스 익스체인지 집계.
mt-aggd바이너리가 거래소별 책과 흐름을 10 Hz로 결합하고, 거래소가 찍은event_ts로 거래소를 정렬하여, 병합된 스냅샷을prod:agg:<asset>:*에 게시합니다. - 오버레이 + 바.
mt-microstructure바이너리가 OBI/CVD 오버레이(prod:agg:*:micro)를 계산하고 분당 한 바를data/<asset>/microstructure_bars.jsonl(잔상 히스토리 표면)에 씁니다.
백엔드 /ws/market WebSocket은 ~10초마다 스냅샷을 푸시하고, 구독과 윈도우 변경 시 trail/normaliser 프레임을 푸시합니다.
호가 불균형 (OBI)
OBI는 중간가 주변 좁은 대역 내 대기 유동성 편향을 측정합니다. 먼저 거래소별로, 각 거래소 자신의 책 위에서 계산되며, 크로스 거래소 혼합은 다음 섹션에서 설명합니다. 대역 밖 레벨은 제외, 스프레드를 가져가는 거래에 영향을 주지 않기 때문.
mid = (best_bid + best_ask) / 2 // 거래소별 band = [mid * 0.998, mid * 1.002] // ±0.2 % bid_qty = 대역 내 매수 qty 합 ask_qty = 대역 내 매도 qty 합 OBI = (bid_qty - ask_qty) / (bid_qty + ask_qty) 범위: [-1, +1] +1 → 매도 비어 있음, 모든 가중치 매수에 -1 → 매수 비어 있음, 모든 가중치 매도에 0 → 대역 내 균형
계산은 대역 내 측면당 상위 200 레벨을 가져옵니다(TOP_LEVELS_PER_SIDE = 200). 플롯되는 X축은 아래의 크로스 거래소 혼합이며 이 단계에서는 평활화 없음. 위젯은 OBI 라벨을 소수 3자리로 표시하여 0.01 이동이 보이게 합니다.
크로스 거래소 OBI 집계 (flow-weighted)
각 거래소의 거래소별 OBI(위)는 그 거래소의 최근 taker 흐름으로 가중된 단일 크로스 거래소 OBI로 결합됩니다, flow-weighted (FW), 역분산이 아님. 거래소의 가중치는 실제로 체결이 찍히는 곳을 따라가므로, 조용한 책은 거의 기여하지 않고 활발한 책이 컨센서스를 주도합니다.
2026-05-26에 집계는 역분산 가중(IVW)에서 FW로 전환되었습니다. IVW에서는 Hyperliquid가 혼합을 지배했습니다: nSigFigs로 양자화된(거친) 책이 인위적으로 낮은 분산의 OBI를 만들고, IVW는 그 뒤에 얼마나 적은 크기가 있든 상관없이 높은 가중치로 보상합니다. Flow-weighting은 가중치를 실현된 공격자 볼륨에 묶으므로, 거친 양자화 거래소가 더 이상 병합된 판독을 지배할 수 없습니다.
누적 거래량 델타 (CVD)
CVD는 롤링 윈도우 내 부호 있는 taker 명목가를 네 거래소 전체에 걸쳐 합산합니다. 부호 규약은 업계 테이프 리딩 관행을 따릅니다, taker 매수는 위로, taker 매도는 아래로. 각 거래소의 공격자 측은 인제스트에서 정규화되어(Bybit, OKX, Hyperliquid는 Binance와 다르게 인코딩) 모든 출력이 같은 부호를 기여합니다.
각 taker 출력(모든 거래소)에 대해: notional = qty * price // USD 공격자 == 매수이면: delta = +notional // taker 매수 그렇지 않으면: delta = -notional // taker 매도 (ts, delta)를 2시간 deque에 추가 cvd_30m_usd = Σ delta, ts ∈ [now - 30m, now] cvd_2h_usd = Σ delta, ts ∈ [now - 2h, now]
2시간 deque가 가장 긴 호라이즌. 30분 윈도우는 매 쓰기마다 같은 버퍼에서 슬라이스. bars 파일은 분당 한 행과 두 윈도우를 모두 보존해 재시작 후에도 잔상이 히스토리를 리플레이할 수 있게 합니다. 네 거래소 합산 처리량은 활성에 따라 ~40–200 prints/s.
Y축 정규화기
원시 30분 CVD 크기는 BTC($1M급 이동)와 ETH·SOL·소형 무기한 사이에서 두 자릿수 차이가 납니다. 원시 USD 플롯은 작은 자산을 평평한 선으로 누릅니다. 따라서 Y축은 자산별로 롤링 7일 |cvd_30m_usd| P95로 나눠 결과를 [-1, +1]로 클램프합니다.
y_norm = clamp(cvd_30m_usd / p95_30m_usd, -1, +1)
p95_30m_usd: 롤링 7일 백분위, 스냅샷 엔드포인트에서 갱신
fallback: 롤링 백분위가 아직 사용 불가일 때(콜드 스타트 또는 얇은 표본)
2_000_000 USD 사용엔드포인트 /api/market/cvd-normalizer?asset=…가 자산별 P95 값을 제공하며 WebSocket의 normalizer 프레임으로 미러링되어, FE는 그 값이 잔상 데이터 이후에 도착할 때 잔상을 일관되게 재스케일할 수 있습니다.
존 분류 (v2)
원시 분면 규칙(OBI 부호, CVD 부호)은 sub-bp 노이즈로 판정이 깜빡이지 않도록 3계층 파이프라인으로 감쌌습니다. 각 계층이 순차로 발화하며, 세 계층 모두를 통과하는 신호만 표시되는 존이 됩니다.
계층 1, OBI에 EMA (CVD는 이미 슬라이딩 윈도우 집계)
obi_ema(t) = α · obi_raw(t) + (1 - α) · obi_ema(t-1)
α = 1 - exp(-dt / span_seconds)
span_seconds 30m 자산별: BTC/ETH/SOL/DOGE 120s, BNB 60s, XRP 5s
계층 2, 크기 데드밴드 (Schmitt-trigger 하단)
두 축 모두 데드밴드 안 → 후보 = "balanced" (평평한 시장:
|obi_ema| < OBI_DB 그리고 |cvd| < CVD_DB_PCT × p95_30m_usd, 어느 쪽도 편향 없음).
정확히 한 축만 안 → 현재 존 유지 (모호).
두 축 모두 밖 → 후보 = (obi_ema, cvd)의 분면.
OBI_DB 자산별: BTC 0.12, ETH 0.20, SOL 0.12, BNB 0.12, XRP 0.05, DOGE 0.20
CVD_DB_PCT 자산별, 롤링 |cvd_30m| p95의 분수:
BTC 0.15, ETH 0.05, SOL 0.20, BNB 0.10, XRP 0.20, DOGE 0.20
계층 3, 최소 체류 (Schmitt-trigger 상단)
새 후보는 현재가 되려면 ≥ MIN_TENURE_S 동안 유지되어야 합니다. 데드밴드로의
한 번의 딥은 더 이상 성숙 중인 후보를 지우지 않습니다; 타이머는 연속 홀드의
최대 3s 유예 동안 유지됩니다 (CVD는 평활화되지 않음).
MIN_TENURE_S 30m 잔상 300s (DOGE 30s); 4h 300s; 24h 1800s.네 개의 방향성 분면, 그리고 어느 축도 편향이 없을 때의 balanced 상태:
x >= 0 그리고 y >= 0 → "매수 우위" x < 0 그리고 y < 0 → "매도 우위" x < 0 그리고 y >= 0 → "수요 흡수 중" x >= 0 그리고 y < 0 → "오더북 지지" 두 축 모두 데드밴드 내 → "Balanced" (뚜렷한 우위 없음)
후보가 아직 체류를 채우는 중일 때 FE는 판정 아래에 명시적 candidate_pending서브라인을 렌더링합니다 (“매도 · 4m 22s 동안 유지 · 매수 후보 18s / 5m”). 분류기는 블랙박스가 아니라 가시적 상태 기계.
파라미터는 자산별 7일 그리드 스윕(scripts/replay_classifier.py)에서 튜닝. 선택된 값은 backend/classifier/config.py에 위치하며 재배포 없이 핫패치를 위해 env 오버라이드(예: MICRO_DEADBAND_DOGE=0.20) 가능. 상태(OBI EMA, 후보 타이머, entered-at)는 애그리게이터 사이클 사이에 Redis에 지속되므로 데몬 재시작은 콜드 스타트가 아니라 같은 존에서 재개됩니다.
잔상 히스토리
잔상은 최근 N개 분면 위치를 나이별로 페이드되는 폴리라인으로 그립니다. 선택 가능한 윈도우는 30m, 4h, 24h. 각 윈도우는 bars 파일에서 다운샘플링된 시퀀스를 가져와 24시간 리플레이가 1440개 원시 분을 스트리밍할 필요가 없게 합니다:
- 30 분. 1분 버킷.
- 4 시간. 5분 버킷.
- 24 시간. 30분 버킷.
FE는 렌더링된 잔상을 60점으로 제한해 24시간 윈도우가 오버플로팅 없이 들어가게 합니다. 실시간 스냅샷은 같은 버퍼에 추가되어 버킷 시퀀스 뒤로 흔적을 남깁니다. 자산 전환 시 로컬 버퍼가 재설정되어 새 분면이 이전 자산의 잔상으로 오염되지 않습니다.
HTF 레짐 태그
위젯 헤더의 Trend BULL/BEAR/NEUTRAL 태그는 scripts/btc_monitor.py(유지되는 cron writer)의 htf_regime()가 스냅샷 cron 5분 케이던스로 계산:
300 1분 캔들 가져오기 (>= 289 유효 바 필요) pct_4h = (close - close_4h_ago) / close_4h_ago * 100 pct_24h = (close - close_24h_ago) / close_24h_ago * 100 BULL if pct_4h > +0.5 or pct_24h > +1.5 BEAR if pct_4h < -0.5 or pct_24h < -1.5 NEUTRAL 그렇지 않으면 (표본 부족 시에도)
태그는 HTF 컨텍스트일 뿐 흐름 리딩이 아닙니다. 분면의 단기 윈도우 판정(30분 CVD)이 다중 시간 방향에 대해 sanity check 받을 수 있도록 존재합니다.
Long/Short 비율
L/S 통계는 Binance의 globalLongShortAccountRatio(15분 주기)를 스냅샷 cron이 ~5분마다 폴링. 1.0 위는 리테일 계정 net long, 아래는 net short. 이는 계정의 포지셔닝이지 흐름이 아닙니다, 분면 평면이 아니라 OBI·CVD와 함께 사이드 패널에 위치합니다.
신선도
세 독립 신호가 위젯을 비실시간으로 표시할 수 있습니다:
micro_book_state≠"ok", WS 재연결 후 데몬이 재동기화 중. REST 스냅샷이 다시 도착할 때까지 OBI 만료. 상태 pill이Daemon <state>로 전환.micro_stale, 하트비트가 윈도우보다 오래됨. FE는 잔상에 새 점 추가 중지.- 잔상이
partial: true표시, 윈도우를 지지하는 jsonl이 요청된 lookback보다 짧음(데몬 재시작 직후 흔함). 캔버스에 앰버 pill 표시.
한계
- 크로스 익스체인지 시간 스큐. 애그리게이터는 거래소가 찍은
event_ts로 거래소를 결합하지만, 10 Hz에서 정렬 윈도우는 ~100 ms에 불과합니다. 빠른 움직임 동안 같은 가격 이벤트가 거래소마다 인접한 스냅샷에 떨어질 수 있어, 단일 프레임의 크로스 거래소 OBI가 잠시 스스로 어긋날 수 있습니다. - 거친 양자화 거래소. Hyperliquid는
nSigFigs로 양자화된 책을 게시하므로 거래소별 OBI가 거칩니다. Flow-weighting(2026-05-26에 역분산 가중을 대체)은 그것이 혼합을 얼마나 움직일 수 있는지 제한하지만 여전히 컨센서스에 들어갑니다, HL의 기여는 정밀이 아니라 방향성으로 읽으세요. - ±0.2 % 대역은 고정 노브. OBI 대역은 모든 자산과 거래소에서 동일. 타이트 스프레드 메이저(BTC, ETH)는 얇은 책 알트보다 대역 내에서 더 깊은 책을 봅니다, 이것이 CVD가 1차 판정이고 OBI가 보조 축인 이유 중 하나.
- L/S는 Binance의 리테일 포지셔닝. 비율은 Binance의 계정을 세며 크로스 익스체인지 집계가 아니고 모든 계정을 크기와 무관하게 동등 가중. 흐름 입력이 아니라 부드러운 컨텍스트로 사용하세요.
- HTF 레짐은 모든 자산에 BTC 스타일 임계값 사용. 4h ±0.5 % / 24h ±1.5 % 임계값은 BTC 대비 튜닝되었음. 고변동성 자산(DOGE, SOL)에서 BULL/BEAR는 직관보다 일찍 발화, 태그를 보정된 트렌드 필터가 아니라 거친 컨텍스트로 다루세요.
- 분면은 서술적이며 예측적이지 않음. 현재 오더북과 taker 압력을 읽으며, 다음 움직임의 예보가 아닙니다. 존을 지금 흐름이 있는 위치의 스냅샷으로 다루세요.
버전
방법론 버전 v2.0.0 · 업데이트 2026-07-04. 중요 변경(추가 거래소, 공식 조정, 임계값 변경)은 버전을 올리고 위의 구조화 데이터의 dateModified를 갱신.