볼륨 프로파일이란?
볼륨 프로파일(Volume Profile)은 특정 가격대에서 거래된 총 거래량을 수평 히스토그램으로 표시하는 분석 도구입니다. 일반적인 거래량 지표가 시간 축 기반인 반면, 볼륨 프로파일은 가격 축 기반으로 어떤 가격대에서 가장 많은 거래가 발생했는지를 보여줍니다.
기관 투자자와 마켓 메이커가 활발히 거래하는 가격대를 파악할 수 있어, 지지·저항 수준을 객관적으로 판단하는 데 핵심적인 역할을 합니다. 퀀트 자동매매에서 볼륨 프로파일을 활용하면 감에 의존하지 않고 데이터 기반의 매매 결정이 가능합니다.
핵심 구성 요소: POC, VAH, VAL
볼륨 프로파일에서 반드시 알아야 할 세 가지 핵심 지표가 있습니다.
- POC (Point of Control): 가장 많은 거래량이 발생한 가격대. 시장의 “공정 가치(Fair Value)”로 해석
- VAH (Value Area High): 전체 거래량의 상위 70%가 발생한 영역의 상단
- VAL (Value Area Low): 전체 거래량의 상위 70%가 발생한 영역의 하단
- Value Area: VAL~VAH 사이 구간으로, 전체 거래의 약 70%가 집중된 “가치 영역”
가격이 Value Area 밖으로 이탈하면 추세 발생 신호, Value Area 안으로 회귀하면 평균회귀 신호로 활용할 수 있습니다.
파이썬으로 볼륨 프로파일 계산
아래 코드는 OHLCV 데이터에서 볼륨 프로파일의 POC, VAH, VAL을 계산하는 클래스입니다.
import numpy as np
import pandas as pd
class VolumeProfile:
def __init__(self, num_bins=50, value_area_pct=0.70):
self.num_bins = num_bins
self.value_area_pct = value_area_pct
def calculate(self, df, period=20):
"""최근 N봉 기준 볼륨 프로파일 계산"""
data = df.tail(period).copy()
price_min = data['low'].min()
price_max = data['high'].max()
# 가격대별 빈(bin) 생성
bins = np.linspace(price_min, price_max, self.num_bins + 1)
bin_centers = (bins[:-1] + bins[1:]) / 2
volume_at_price = np.zeros(self.num_bins)
# 각 캔들의 거래량을 가격 범위에 분배
for _, row in data.iterrows():
candle_low = row['low']
candle_high = row['high']
candle_vol = row['volume']
# 해당 캔들이 걸치는 빈에 거래량 균등 분배
mask = (bin_centers >= candle_low) & (bin_centers <= candle_high)
n_bins_hit = mask.sum()
if n_bins_hit > 0:
volume_at_price[mask] += candle_vol / n_bins_hit
# POC: 최대 거래량 가격대
poc_idx = np.argmax(volume_at_price)
poc_price = bin_centers[poc_idx]
# Value Area 계산 (POC에서 양쪽으로 확장)
total_volume = volume_at_price.sum()
target_volume = total_volume * self.value_area_pct
va_low_idx = poc_idx
va_high_idx = poc_idx
accumulated = volume_at_price[poc_idx]
while accumulated < target_volume:
expand_up = (volume_at_price[va_high_idx + 1]
if va_high_idx + 1 < self.num_bins else 0)
expand_down = (volume_at_price[va_low_idx - 1]
if va_low_idx - 1 >= 0 else 0)
if expand_up >= expand_down and va_high_idx + 1 < self.num_bins:
va_high_idx += 1
accumulated += expand_up
elif va_low_idx - 1 >= 0:
va_low_idx -= 1
accumulated += expand_down
else:
break
return {
'poc': poc_price,
'vah': bin_centers[va_high_idx],
'val': bin_centers[va_low_idx],
'volume_profile': dict(zip(bin_centers, volume_at_price))
}
볼륨 프로파일 기반 자동매매 전략
볼륨 프로파일의 핵심 지표를 활용한 자동매매 전략을 구현합니다. Value Area 이탈·회귀 패턴을 기반으로 매매 신호를 생성합니다.
class VolumeProfileStrategy:
def __init__(self, lookback=20, num_bins=50):
self.vp = VolumeProfile(num_bins=num_bins)
self.lookback = lookback
self.position = 0 # 1: 롱, -1: 숏, 0: 없음
def generate_signal(self, df, current_idx):
"""현재 시점에서 매매 신호 생성"""
if current_idx < self.lookback:
return 0
window = df.iloc[current_idx - self.lookback:current_idx]
profile = self.vp.calculate(window, period=self.lookback)
current_price = df.iloc[current_idx]['close']
prev_price = df.iloc[current_idx - 1]['close']
poc = profile['poc']
vah = profile['vah']
val = profile['val']
signal = 0
# 전략 1: VAL 하향 이탈 후 복귀 → 롱
if prev_price < val and current_price > val:
signal = 1 # 롱 진입
# 전략 2: VAH 상향 이탈 후 복귀 → 숏
elif prev_price > vah and current_price < vah:
signal = -1 # 숏 진입
# 전략 3: POC 도달 → 포지션 청산
elif self.position != 0:
if abs(current_price - poc) / poc < 0.002:
signal = 0 # 청산
return signal
def backtest(self, df):
"""백테스트 실행"""
results = []
for i in range(self.lookback, len(df)):
signal = self.generate_signal(df, i)
if signal != self.position:
self.position = signal
daily_return = df.iloc[i]['close'] / df.iloc[i-1]['close'] - 1
strategy_return = self.position * daily_return
results.append({
'date': df.index[i],
'price': df.iloc[i]['close'],
'signal': signal,
'strategy_return': strategy_return
})
return pd.DataFrame(results)
고급 활용: 복합 볼륨 프로파일
단일 기간이 아닌 다중 타임프레임 볼륨 프로파일을 결합하면 더 정확한 지지·저항 수준을 파악할 수 있습니다.
def multi_timeframe_profile(df, periods=[5, 20, 60]):
"""다중 기간 볼륨 프로파일에서 겹치는 POC 영역 탐지"""
vp = VolumeProfile(num_bins=100)
profiles = {}
for period in periods:
if len(df) >= period:
profiles[period] = vp.calculate(df, period=period)
# POC 수렴 영역 탐색
poc_prices = [p['poc'] for p in profiles.values()]
poc_mean = np.mean(poc_prices)
poc_std = np.std(poc_prices)
# POC가 수렴할수록 강한 지지/저항
confluence_score = 1.0 / (1.0 + poc_std / poc_mean * 100)
return {
'profiles': profiles,
'poc_confluence': poc_mean,
'confluence_strength': round(confluence_score, 3),
'is_strong_level': confluence_score > 0.8
}
다중 기간의 POC가 비슷한 가격대에 수렴하면 해당 가격은 매우 강력한 지지/저항선으로 작용합니다. 이를 통해 진입·청산 정확도를 높일 수 있습니다.
실전 적용 체크리스트
- 데이터 품질: 틱 데이터 또는 1분봉 이상의 고해상도 데이터 사용 권장
- 빈(bin) 개수 설정: 너무 적으면 해상도 부족, 너무 많으면 노이즈 — 자산 변동성에 따라 30~100개 조절
- 리스크 관리: Value Area 이탈 시 추세 추종과 평균회귀 중 시장 상황에 맞는 전략 선택
- 거래량 필터: 거래량이 극단적으로 낮은 시간대(새벽 등)는 프로파일 신뢰도 하락
- 갱신 주기: 실시간 자동매매에서는 매 봉마다 프로파일을 재계산하여 최신 상태 유지
볼륨 프로파일 전략은 오더플로우 자동매매 분석과 결합하면 더욱 강력해집니다. 또한 자동매매 슬리피지 최소화 전략을 함께 적용하여 실전 수익률을 개선할 수 있습니다.
결론
볼륨 프로파일은 가격대별 거래량 분포를 통해 시장 참여자들의 실제 관심 가격을 파악하는 핵심 도구입니다. POC, VAH, VAL을 활용한 자동매매 전략은 기술적 지표만으로는 알 수 없는 수급 기반의 매매 근거를 제공합니다. 파이썬으로 직접 구현하여 자신만의 퀀트 전략에 통합해 보세요.