엔트로피 기반 시장 예측 전략

정보 엔트로피와 금융 시장

클로드 섀넌(Claude Shannon)이 1948년 제안한 정보 엔트로피는 시스템의 불확실성을 수치로 측정합니다. 금융 시장에 적용하면 “현재 시장이 얼마나 무질서한가”를 객관적으로 계량할 수 있습니다. 엔트로피가 높으면 시장 참여자 간 의견이 분산되어 방향성이 불명확하고, 낮으면 한 방향으로 합의가 형성되어 강한 추세가 나타날 가능성이 높습니다.

이 기법은 전통 기술적 지표와 달리 가격 자체가 아닌 가격 변동의 확률 분포를 분석하므로, RSI나 MACD가 놓치는 시장 구조 변화를 포착할 수 있습니다.

섀넌 엔트로피 계산법

섀넌 엔트로피 공식은 다음과 같습니다: H = -Σ p(x) · log₂(p(x)). 수익률을 구간별로 나누어 각 구간의 발생 빈도를 확률로 변환한 뒤, 이 공식에 대입합니다.

import numpy as np
import pandas as pd
import ccxt
from scipy.stats import entropy

# 바이낸스 1시간봉 데이터 수집
exchange = ccxt.binance()
ohlcv = exchange.fetch_ohlcv('BTC/USDT', '1h', limit=720)
df = pd.DataFrame(ohlcv, columns=['ts','open','high','low','close','volume'])
df['returns'] = df['close'].pct_change().dropna()

def shannon_entropy(returns, n_bins=20):
    """수익률 분포의 섀넌 엔트로피 계산"""
    counts, _ = np.histogram(returns.dropna(), bins=n_bins)
    probs = counts / counts.sum()
    probs = probs[probs > 0]  # log(0) 방지
    return entropy(probs, base=2)

# 롤링 엔트로피 (48시간 윈도우)
window = 48
df['entropy'] = df['returns'].rolling(window).apply(
    lambda x: shannon_entropy(x, n_bins=10), raw=False
)

max_entropy = np.log2(10)  # 균등분포일 때 최대 엔트로피
df['norm_entropy'] = df['entropy'] / max_entropy  # 0~1 정규화

print(f"현재 정규화 엔트로피: {df['norm_entropy'].iloc[-1]:.3f}")
print(f"높으면 무질서(레인지), 낮으면 질서(추세)")

시장 레짐 분류: 엔트로피 기반

엔트로피 수준에 따라 시장을 세 가지 레짐으로 분류하고, 각 레짐에 맞는 전략을 자동 전환합니다.

def classify_regime(norm_entropy, trend_strength):
    """엔트로피 + 추세 강도로 시장 레짐 분류"""
    if norm_entropy < 0.6:
        if abs(trend_strength) > 0.02:
            return 'STRONG_TREND'   # 낮은 엔트로피 + 방향성 → 강한 추세
        return 'COMPRESSION'        # 낮은 엔트로피 + 방향성 없음 → 압축 구간
    elif norm_entropy < 0.8:
        return 'NORMAL'             # 중간 엔트로피 → 일반 시장
    else:
        return 'HIGH_DISORDER'      # 높은 엔트로피 → 무질서/레인지

# 추세 강도: 롤링 평균 수익률
df['trend'] = df['returns'].rolling(window).mean()
df['regime'] = df.apply(
    lambda r: classify_regime(r['norm_entropy'], r['trend'])
    if pd.notna(r['norm_entropy']) else 'UNKNOWN', axis=1
)

print(df[['close','norm_entropy','regime']].tail(5))

전략 1: 엔트로피 브레이크아웃

엔트로피가 장기간 낮게 유지되다 급격히 상승하면, 시장 구조가 변화하고 있다는 신호입니다. 이는 큰 움직임의 시작점이 될 수 있습니다.

def entropy_breakout_signal(entropy_series, lookback=100, z_threshold=2.0):
    """엔트로피 급변 감지 — 시장 구조 변화 포착"""
    mean_ent = entropy_series.rolling(lookback).mean()
    std_ent = entropy_series.rolling(lookback).std()

    z_score = (entropy_series - mean_ent) / std_ent

    latest_z = z_score.iloc[-1]
    if latest_z > z_threshold:
        return 'ENTROPY_SPIKE', latest_z    # 무질서 급증 → 변동성 확대 예고
    elif latest_z < -z_threshold:
        return 'ENTROPY_DROP', latest_z     # 질서 급증 → 추세 강화 예고
    return 'NEUTRAL', latest_z

signal, z = entropy_breakout_signal(df['norm_entropy'])
print(f"엔트로피 신호: {signal} (z-score: {z:.2f})")

전략 2: 엔트로피 가중 모멘텀

기존 모멘텀 전략에 엔트로피를 가중치로 적용합니다. 엔트로피가 낮을 때(시장이 질서 있을 때) 모멘텀 신호를 강하게, 높을 때 약하게 반영합니다.

def entropy_weighted_momentum(df, mom_period=20, ent_col='norm_entropy'):
    """엔트로피 가중 모멘텀 — 질서 있는 추세에 집중"""
    # 기본 모멘텀
    momentum = df['close'].pct_change(mom_period)

    # 엔트로피 가중치: 낮은 엔트로피 → 높은 가중치
    weight = 1 - df[ent_col]  # 0~1 (엔트로피 역수)
    weight = weight.clip(0.1, 1.0)

    weighted_mom = momentum * weight

    # 신호 생성
    signals = pd.Series('HOLD', index=df.index)
    signals[weighted_mom > 0.02] = 'BUY'
    signals[weighted_mom < -0.02] = 'SELL'

    return weighted_mom, signals

df['w_momentum'], df['mom_signal'] = entropy_weighted_momentum(df)
print(f"가중 모멘텀: {df['w_momentum'].iloc[-1]:.4f}")
print(f"신호: {df['mom_signal'].iloc[-1]}")

전략 3: 교차 엔트로피 다이버전스

KL 다이버전스(Kullback-Leibler Divergence)로 두 기간의 수익률 분포 차이를 측정합니다. 최근 분포가 과거와 크게 달라지면 시장의 성격이 바뀌고 있다는 뜻입니다.

from scipy.stats import entropy as sp_entropy

def kl_divergence_signal(returns, recent_window=48, base_window=200, n_bins=15):
    """KL 다이버전스 — 수익률 분포 변화 감지"""
    recent = returns.iloc[-recent_window:].dropna()
    baseline = returns.iloc[-base_window:-recent_window].dropna()

    # 동일한 bin으로 히스토그램 생성
    bins = np.linspace(returns.min(), returns.max(), n_bins + 1)
    p_recent, _ = np.histogram(recent, bins=bins, density=True)
    q_baseline, _ = np.histogram(baseline, bins=bins, density=True)

    # 0 방지 (라플라스 스무딩)
    eps = 1e-10
    p_recent = p_recent + eps
    q_baseline = q_baseline + eps
    p_recent = p_recent / p_recent.sum()
    q_baseline = q_baseline / q_baseline.sum()

    kl_div = sp_entropy(p_recent, q_baseline)

    if kl_div > 0.5:
        return 'REGIME_CHANGE', kl_div   # 분포 크게 변화
    elif kl_div > 0.2:
        return 'SHIFTING', kl_div        # 점진적 변화
    return 'STABLE', kl_div

signal, kl = kl_divergence_signal(df['returns'])
print(f"KL 다이버전스: {kl:.4f} → {signal}")

통합 엔트로피 매매 시스템

세 전략을 통합하여 레짐별 자동 전략 전환을 구현합니다.

class EntropyTradingSystem:
    def __init__(self):
        self.regime_strategies = {
            'STRONG_TREND': self._trend_follow,
            'COMPRESSION': self._breakout_wait,
            'NORMAL': self._momentum,
            'HIGH_DISORDER': self._mean_revert
        }

    def _trend_follow(self, df):
        """추세 추종 — 엔트로피 낮고 방향성 있을 때"""
        return 'BUY' if df['trend'].iloc[-1] > 0 else 'SELL'

    def _breakout_wait(self, df):
        """압축 구간 — 돌파 대기"""
        return 'WAIT_BREAKOUT'

    def _momentum(self, df):
        """일반 시장 — 가중 모멘텀"""
        return df['mom_signal'].iloc[-1]

    def _mean_revert(self, df):
        """고엔트로피 — 평균회귀"""
        z = (df['close'].iloc[-1] - df['close'].rolling(20).mean().iloc[-1])
        z /= df['close'].rolling(20).std().iloc[-1]
        if z < -1.5: return 'BUY'
        if z > 1.5: return 'SELL'
        return 'HOLD'

    def execute(self, df):
        regime = df['regime'].iloc[-1]
        strategy_fn = self.regime_strategies.get(regime, self._momentum)
        action = strategy_fn(df)
        return {'regime': regime, 'action': action,
                'entropy': df['norm_entropy'].iloc[-1]}

system = EntropyTradingSystem()
# result = system.execute(df)

실전 적용 시 핵심 포인트

  • 빈(bin) 개수 최적화: 너무 적으면 정보 손실, 너무 많으면 노이즈 증가. Sturges' rule(k = 1 + 3.322·log(n))이나 교차 검증으로 최적값을 찾으세요.
  • 다중 타임프레임 분석: 1시간, 4시간, 일봉의 엔트로피를 동시에 모니터링하면 페어 트레이딩처럼 다양한 관점을 확보할 수 있습니다.
  • 전이 엔트로피(Transfer Entropy): 단순 엔트로피를 넘어, 한 자산이 다른 자산에 정보를 전달하는 방향성을 분석하면 선행 지표를 발굴할 수 있습니다.
  • 과적합 주의: 엔트로피 임계값을 과거 데이터에 맞춰 과도하게 최적화하면 백테스트 과적합에 빠질 수 있습니다. 워크포워드 테스트를 병행하세요.

마무리: 정보 이론이 퀀트에 주는 통찰

엔트로피 기반 분석의 가장 큰 장점은 "시장이 무엇을 할지"가 아니라 "시장이 얼마나 예측 가능한 상태인지"를 먼저 판단한다는 것입니다. 예측 불가능한 시장에서 무리하게 포지션을 잡는 것은 동전 던지기와 다름없습니다. 엔트로피가 높을 때는 관망하고, 낮을 때 집중 매매하는 것만으로도 승률을 크게 개선할 수 있습니다.

엔트로피 수준 시장 상태 최적 전략
낮음 (< 0.6) 질서 / 추세 추세추종, 모멘텀
중간 (0.6~0.8) 일반 가중 모멘텀
높음 (> 0.8) 무질서 / 레인지 평균회귀, 관망
급변 구조 변화 브레이크아웃 대비
위로 스크롤
WordPress Appliance - Powered by TurnKey Linux