WebSocket 틱 데이터로 수급 흐름을 간접 추적하는 법 - 체결강도·VWAP·대량체결 감지 패턴
외인·기관 수급 정보는 WebSocket으로 직접 받을 수 없습니다. 하지만 S3_/K3_ 틱 데이터에서 체결강도·VWAP·대량체결 신호를 뽑아내면, REST 조회 시점을 정확하게 잡을 수 있습니다. 실전 3-Layer 패턴을 정리합니다.
틱 데이터로 수급을 알 수 있을까
결론부터 말하면 “직접은 안 된다, 간접은 된다”입니다.
증권사 WebSocket(xingAPI S3_, K3_)에서 오는 실시간 체결 데이터에는 외인이 샀는지 기관이 샀는지 구분하는 필드가 없습니다.
실제로 수급 정보를 얻으려면 REST 조회가 필요합니다.
t1702: 종목별 외인·기관 일별 매매동향t1602: 시장 전체 투자자별 순매수 흐름
그런데 REST를 모든 종목에 항상 호출하면 Rate Limit에 걸립니다.
바로 이 지점에서 WebSocket 틱 데이터가 역할을 가집니다.
틱 데이터 = REST 조회 타이밍을 정하는 감지기
S3_/K3_ 에서 읽어야 하는 필드
보통 구현에서는 price, volume, cvolume만 읽는 경우가 많습니다.
하지만 수급 추적에 쓰이는 핵심 필드가 따로 있습니다.
| 필드 | 설명 | 활용 |
|---|---|---|
cvolume | 이 틱의 체결량 | 대량체결 감지 |
msvolume | 매수 체결수량 | 체결강도 계산 |
mdvolume | 매도 체결수량 | 체결강도 계산 |
volume | 누적 거래량 | 가속도 계산 |
price | 현재가 | VWAP 누적 |
msvolume과 mdvolume이 빠지면 체결 방향을 알 수 없습니다.
패턴 1: 체결강도 지수 (Buy Pressure Index)
# 틱마다 계산
buy_pressure = msvolume / (msvolume + mdvolume)
# 해석 기준
# 0.65 이상 지속 → 매수 주도 체결 구간
# 0.35 이하 지속 → 매도 주도 체결 구간
단일 틱보다 롤링 윈도우로 봐야 합니다.
from collections import deque
class BuyPressureTracker:
def __init__(self, window: int = 50):
self._buy = deque(maxlen=window)
self._sell = deque(maxlen=window)
def push(self, ms: int, md: int):
self._buy.append(ms)
self._sell.append(md)
@property
def pressure(self) -> float:
total_buy = sum(self._buy)
total_sell = sum(self._sell)
denom = total_buy + total_sell
return total_buy / denom if denom > 0 else 0.5
50틱 누적 기준으로 pressure > 0.65가 유지되면
”지금 이 종목에 매수 수요가 공급을 압도하고 있다”는 신호입니다.
패턴 2: 실시간 VWAP 계산
VWAP은 기관이 분할 매수 집행 시 기준으로 삼는 지표입니다.
현재가가 VWAP 위에서 계속 거래되면 “기관이 VWAP보다 비싸게 사도 계속 사고 있다”는 의미입니다.
class VWAPTracker:
def __init__(self):
self._cum_pv = 0.0 # 가격 × 체결량 누적
self._cum_vol = 0 # 체결량 누적
def push(self, price: int, cvolume: int):
self._cum_pv += price * cvolume
self._cum_vol += cvolume
@property
def vwap(self) -> float:
return self._cum_pv / self._cum_vol if self._cum_vol > 0 else 0.0
def above_vwap(self, price: int) -> bool:
return self.vwap > 0 and price > self.vwap
장 시작 시 초기화하고 틱마다 업데이트합니다.
패턴 3: 대량체결 감지 (Block Trade Detector)
기관 주문은 분할되지만, 특정 시점에 평균보다 훨씬 큰 틱이 터지는 경우가 있습니다.
from collections import deque
import statistics
class BlockTradeDetector:
def __init__(self, window: int = 100, threshold: float = 5.0):
self._history = deque(maxlen=window)
self._threshold = threshold
def push(self, cvolume: int) -> bool:
self._history.append(cvolume)
if len(self._history) < 20:
return False
avg = statistics.mean(self._history)
return avg > 0 and cvolume > avg * self._threshold
단일 틱에서 평균 체결량의 5배 이상이 터지면 플래그를 올립니다.
이 플래그가 올라간 직후 t1702 REST 조회를 트리거하면 됩니다.
패턴 4: 거래량 가속도 (Volume Acceleration)
분 단위 거래량이 갑자기 늘어나는 구간을 잡는 패턴입니다.
class VolumeAccelerationDetector:
def __init__(self, window_minutes: int = 5, threshold: float = 3.0):
self._minute_vols: deque[int] = deque(maxlen=window_minutes)
self._current_minute_start_vol = 0
self._threshold = threshold
def update(self, cumulative_volume: int, minute_changed: bool):
if minute_changed:
minute_vol = cumulative_volume - self._current_minute_start_vol
self._minute_vols.append(minute_vol)
self._current_minute_start_vol = cumulative_volume
@property
def is_accelerating(self) -> bool:
if len(self._minute_vols) < 3:
return False
avg = statistics.mean(list(self._minute_vols)[:-1])
latest = self._minute_vols[-1]
return avg > 0 and latest > avg * self._threshold
3-Layer 패턴으로 조합하기
이 네 가지 신호를 단독으로 쓰면 오탐이 많습니다.
조건을 조합해서 REST 조회 트리거를 만드는 것이 핵심입니다.
틱 푸시 (S3_/K3_)
│
├─ buy_pressure > 0.65 (50틱 롤링)
├─ is_accelerating (분 단위 가속)
└─ block_trade 감지
│
└─ 2개 이상 동시 충족
│
▼
t1702 REST 조회 → 5일 외인·기관 순매수 추세 확인
t1602 REST 조회 → 시장 전체 외인 자금 방향 확인
│
▼
✅ REST도 같은 방향 → 진입 시그널
❌ REST가 다른 방향 → HOLD
조건 하나만 봐서는 노이즈입니다.
WebSocket이 먼저 “지금 뭔가 일어나고 있다”를 알려주고,
REST가 “그게 외인인지 기관인지”를 확인해주는 역할 분리가 핵심입니다.
구현 시 주의할 점
하루 시작마다 초기화
VWAP, 누적 거래량은 장 시작(09:00)에 리셋해야 합니다.
Rate Limit 고려
REST 트리거는 종목당 최소 30초 간격을 두는 것이 좋습니다.
짧은 시간 안에 같은 종목의 조건이 반복 충족되면 첫 번째만 트리거합니다.
코스피와 코스닥 분리
S3_는 코스피, K3_는 코스닥입니다.
같은 로직을 각각 인스턴스로 만들어 독립 운영해야 합니다.
정리
| 신호 | 계산 근거 | REST 연계 |
|---|---|---|
| 체결강도 | msvolume / (msvolume + mdvolume) | t1702 트리거 |
| VWAP 이탈 | 가격 × 체결량 누적 | t1702 트리거 |
| 대량체결 | cvolume vs 평균 | t1702 즉시 트리거 |
| 거래량 가속 | 분 단위 비율 | t1602 트리거 |
WebSocket은 감지기, REST는 확인기.
이 역할 분리가 실시간 수급 추적의 핵심 구조입니다.