Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

슬리피지 모델링

우리가 거래할 때는 현재 시장 가격으로 거래하는 것이 아니라, 시장이 우리 주문을 체결해 주는 가격으로 거래합니다. 우리가 보는 가격과 실제로 받는 가격 사이에는 차이가 있습니다. 이 차이를 슬리피지라고 합니다. 슬리피지를 사전에 예측하는 것은 경험적인 문제이지만, 이를 모델링하면 단순히 추측하거나 모델에서 완전히 배제하는 것보다 더 나은 결과를 얻을 수 있습니다.

단순 슬리피지 모델

다른 주문의 규모에 비해 지나치게 큰 주문을 시장에 내면, 우리 주문은 우리가 보는 가격과 다른 가격에 체결됩니다. 그러나 자산의 최근 가격 이력을 바탕으로 예상 슬리피지를 해석적으로 모델링한 다음, 슬리피지의 영향을 최소화하도록 주문 규모를 정할 수 있습니다. 이는 세 가지 구성 요소의 함수입니다.

자산의 변동성은 슬리피지의 주된 요인입니다. 자산의 변동성이 클수록 더 큰 슬리피지가 예상됩니다. 최근 가격 이력으로부터 자산의 변동성을 추정한 다음, 이를 이용해 슬리피지를 추정하는 방식으로 이를 모델링할 수 있습니다. 변동성은 단순 이동 윈도 평균을 사용하여 계산할 수 있습니다.

슬리피지의 또 다른 구성 요소는 거래량 영향 계수입니다. 이는 평균 일일 거래량에 비해 우리 주문의 규모가 얼마나 큰지에 따라 가격이 움직이는 정도입니다. 최근 가격 이력으로부터 자산의 평균 일일 거래량을 추정한 다음, 이를 이용해 슬리피지를 추정하는 방식으로 이를 모델링할 수 있습니다.

슬리피지의 세 번째 구성 요소는 스프레드입니다. 이는 매수 호가와 매도 호가의 차이입니다. 자산의 최근 가격 이력으로부터 스프레드를 추정하는 방식으로 이를 모델링할 수 있습니다. 전체 슬리피지는 이러한 구성 요소의 합으로 모델링할 수 있습니다:

여기서:

여기서:

  • 는 현재 가격입니다
  • 는 거래량 영향 계수입니다
  • 는 스프레드 계수입니다
  • 는 주문 규모입니다
  • 는 평균 일일 거래량입니다
  • 는 변동성입니다
  • 는 매수-매도 스프레드입니다
  • 은 베이시스 포인트 단위의 최소 슬리피지입니다
import numpy as np
import pandas as pd
from typing import Union, Optional

class SlippageModel:
    def __init__(
        self,
        volatility_window: int = 20,
        volume_impact_factor: float = 0.1,
        spread_factor: float = 0.5,
        min_slippage_bps: float = 1.0
    ):
        self.volatility_window = volatility_window
        self.volume_impact_factor = volume_impact_factor
        self.spread_factor = spread_factor
        self.min_slippage_bps = min_slippage_bps

    def estimate_slippage(
        self,
        price: float,
        order_size: float,
        avg_daily_volume: float,
        volatility: Optional[float] = None,
        bid_ask_spread: Optional[float] = None
    ) -> float:
        # Base slippage on minimum bps
        base_slippage = price * (self.min_slippage_bps / 10000)

        # Volume impact component
        volume_ratio = order_size / avg_daily_volume
        volume_impact = price * self.volume_impact_factor * volume_ratio

        # Volatility component (if provided)
        volatility_impact = 0
        if volatility is not None:
            volatility_impact = price * volatility * self.volume_impact_factor

        # Spread component
        spread_impact = 0
        if bid_ask_spread is not None:
            spread_impact = bid_ask_spread * self.spread_factor
        else:
            # Estimate spread as 0.1% of price if not provided
            spread_impact = price * 0.001 * self.spread_factor

        # Combine all components
        total_slippage = base_slippage + volume_impact + volatility_impact + spread_impact

        return total_slippage

    def calculate_volatility(self, prices: pd.Series) -> float:
        returns = prices.pct_change().dropna()
        volatility = returns.rolling(window=self.volatility_window).std()
        return volatility.iloc[-1]

    def estimate_trade_price(
        self,
        current_price: float,
        order_size: float,
        avg_daily_volume: float,
        is_buy: bool,
        volatility: Optional[float] = None,
        bid_ask_spread: Optional[float] = None
    ) -> float:
        slippage = self.estimate_slippage(
            current_price,
            order_size,
            avg_daily_volume,
            volatility,
            bid_ask_spread
        )

        # Add slippage for buys, subtract for sells
        execution_price = current_price + (slippage if is_buy else -slippage)
        return execution_price

이제 이 모델을 사용하려면 자산의 변동성과 매수-매도 스프레드를 추정해야 합니다. 이 예제에서는 주식과 유사한 자산을 사용하겠습니다.

# Initialize model
model = SlippageModel(
    volatility_window=20,
    volume_impact_factor=0.1,
    spread_factor=0.5,
    min_slippage_bps=1.0
)

# Example trade
current_price = 100.0
order_size = 1000
avg_daily_volume = 1000000
volatility = 0.02  # 2% daily volatility
bid_ask_spread = 0.05

# Estimate slippage for a buy order
slippage = model.estimate_slippage(
    current_price,
    order_size,
    avg_daily_volume,
    volatility,
    bid_ask_spread
)

execution_price = model.estimate_trade_price(
    current_price,
    order_size,
    avg_daily_volume,
    is_buy=True,
    volatility=volatility,
    bid_ask_spread=bid_ask_spread
)

print(f"Current Price: ${current_price:.2f}")
print(f"Estimated Slippage: ${slippage:.4f}")
print(f"Execution Price: ${execution_price:.2f}")
print(f"Slippage Impact (bps): {(slippage/current_price)*10000:.2f}")

Abdi와 Ranaldo 모델

Abdi와 Ranaldo(2017) 모델은 금융 시장에서 매수-매도 스프레드를 추정하기 위한 포괄적인 프레임워크를 제공합니다. 이 모델은 자산 가격의 근본적인 변동성을 반영하는 효율적 가격 분산이라는 개념에 기반을 두고 있습니다. 이 모델은 고가, 저가, 종가를 분석하여 매수-매도 스프레드를 더 정확하게 추정하는 것을 목표로 합니다. 이 모델의 핵심(Core)은 각 거래 기간의 평균 가격을 계산하는 것이며, 이는 다음과 같이 표기합니다:

이는 각 거래 기간에 대해 계산됩니다. 이 평균 가격은 가격 움직임을 평가하기 위한 기준점 역할을 합니다. 그다음 모델은 시간에 따른 가격 변동의 동역학을 포착하기 위해 로 표현되는 이 평균 가격 변화량의 분산을 살펴봅니다. 효율적 가격 분산을 추정하기 위해, 모델은 평균 가격 변화량의 분산을 상수 계수로 조정하여 사용합니다. 효율적 가격 분산은 다음과 같이 계산됩니다:

여기서 은 모델의 이론적 기초에서 도출된 상수입니다(유도 과정은 원 논문을 참고하십시오). 이 조정은 시장 미시구조가 가격 형성에 미치는 영향을 반영합니다. 마지막으로, 모델은 종가의 분산과 효율적 가격 분산 사이의 관계를 이용하여 매수-매도 스프레드를 도출합니다. 스프레드()는 다음과 같이 추정됩니다:

이 식은 스프레드가 관측된 가격 움직임과 근본적인 시장 상황 모두에 의해 어떻게 영향을 받는지 보여 주며, 트레이더에게 슬리피지 추정을 위한 견고한 도구를 제공합니다. 자세한 내용은 원 논문을 여기에서 참고하십시오.

def abdi_ranaldo_spread_estimator(
    highs: pd.Series,
    lows: pd.Series,
    closes: pd.Series
) -> tuple[float, float]:
    k1 = 4 * np.log(2)  # Constant used in the model

    # Calculate η_t = (high + low)/2 for each day
    eta = (highs + lows) / 2

    # Calculate variance of η changes
    eta_changes = eta.diff().dropna()
    var_eta_changes = eta_changes.var()

    # Estimate efficient price variance
    efficient_variance = var_eta_changes / (2 - k1/2)

    # Calculate variance of close vs average etas
    eta_avg = (eta + eta.shift(-1)) / 2  # (η_t + η_{t+1})/2
    close_vs_eta = closes - eta_avg
    var_close_eta = close_vs_eta.dropna().var()

    # Solve for spread
    spread = np.sqrt(4 * (var_close_eta - (0.5 + k1/8) * efficient_variance))

    return spread, efficient_variance

이 함수를 사용하면 매수-매도 스프레드를 추정한 뒤, 이를 이용해 이전과 동일한 클래스 인터페이스로 거래의 슬리피지를 추정하는 모델을 만들 수 있습니다.

class AbdiRanaldoModel(SlippageModel):
    def __init__(
        self,
        volatility_window: int = 20,
        volume_impact_factor: float = 0.1,
        spread_factor: float = 0.5,
        min_slippage_bps: float = 1.0
    ):
        super().__init__(volatility_window, volume_impact_factor, spread_factor, min_slippage_bps)

    def estimate_market_spread(
        self,
        highs: pd.Series,
        lows: pd.Series,
        closes: pd.Series
    ) -> float:
        """
        Estimates the bid-ask spread using the Abdi-Ranaldo method.
        """
        spread, _ = abdi_ranaldo_spread_estimator(highs, lows, closes)
        return spread

이제 이 모델을 사용하여 개별 거래의 최근 가격 이력으로부터 해당 거래의 슬리피지를 추정할 수 있습니다.

model = AbdiRanaldoModel()

# Estimate the market spread
estimated_spread = model.estimate_market_spread(
    data['High'],
    data['Low'],
    data['Close']
)

# Use the estimated spread in slippage calculation
slippage = model.estimate_slippage(
    price=data['Close'].iloc[-1],
    order_size=1000,
    avg_daily_volume=data['Volume'].iloc[-1],
    bid_ask_spread=estimated_spread
)

# Estimate the execution price
execution_price = model.estimate_trade_price(
    current_price=data['Close'].iloc[-1],
    order_size=1000,
    avg_daily_volume=data['Volume'].iloc[-1],
    is_buy=True,
    bid_ask_spread=estimated_spread
)

원문 © Stephen Diehl, stephendiehl.com · 글 CC BY-SA 4.0, 코드 MIT · Stephen Diehl은 런던의 소프트웨어 엔지니어이자 작가입니다(저자가 정한 소개 문구). 이 글은 저자가 개인 자격으로 쓴 것이며 어떤 조직과의 연관도 밝히거나 암시해서는 안 됩니다 (라이선스와 고지).
이 페이지는 원문을 한국어로 옮기며 변경한 비공식 번역이며 같은 CC BY-SA 4.0으로 제공합니다 · yeokja 한국어 번역 · Anthropic 사의 claude-opus-5-5 모델을 활용하여 번역되었으며 학습을 모두 비허용한 상태로 작업하였습니다.