📝

Draft article

This draft is visible to admins and superusers only. Sign in with an authorized account.

← 기사 목록으로
July 23, 2026
5분 소요

슬리피지 상수가 아닌 슬리피지 곡선: 실전 트레이딩과의 접촉에서 살아남는 비용 모델

슬리피지 상수가 아닌 슬리피지 곡선: 실전 트레이딩과의 접촉에서 살아남는 비용 모델
#슬리피지
#거래 비용
#시장 충격
#백테스트
#실행
#tca
#제곱근 법칙
#비용 모델

대부분의 백테스트에서 가장 비싼 한 줄은 slippage_bps = 5이다. 5라는 숫자가 틀려서가 아니라 — 1년치 체결을 평균 내면 오히려 맞을 수도 있다 — 상수는 조건부로 틀리기 때문이며, 여러분의 전략 선택 과정은 바로 이 조건부 오류를 찾아내고 파고드는 기계이기 때문이다. 슬리피지는 주문 규모, 스프레드, 변동성, 그리고 가용 유동성의 함수다. 상수란 그 함수를 한 지점에서 평가한 뒤 나머지 모든 곳으로 외삽한 값이며, 여기에는 여러분의 평균회귀 시그널이 가장 강하게 터지고 오더북 깊이가 평소의 10분의 1로 줄어드는 새벽 3시 청산 캐스케이드까지 포함된다. 백테스트는 거기서도 5 bps를 물린다. 실전 트레이딩은 그러지 않는다.

이 글은 백테스트 루프 내부의 비용 모델에 관한 것이다: 모든 시뮬레이션 거래에서 차감되는 함수 cost(size, market_state) 말이다. 이 글은 의도적으로 실행을 스케줄링하기 위해 사전(ex ante)에 충격을 예측하는 것에 관한 것이 아니다 — 그것은 짝을 이루는 문제로, 모델 측면은 가격 충격 모델링에서, 최적 스케줄링 측면은 Almgren-Chriss에서 다룬다. 여기서의 질문은 더 좁고, 백테스트로 전략을 선택하는 사람이라면 더 시급하다: 지금 여러분의 상수가 서 있는 자리에 어떤 함수가 서야 하는가, 실제로 보유한 데이터로부터 그것을 어떻게 피팅하는가, 그리고 그 답이 여러분이 결국 운용하게 될 전략을 얼마나 바꾸는가. 마지막 부분에는 날카로운 실증적 답이 있다: 한 전략 패밀리의 20개 변형을 네 가지 비용 모델 아래에서 재순위 매겨 보면 순위표가 뒤집히는 것을 볼 수 있다.

비용 모델 사다리

상수 bps에서 제곱근 참여율까지 네 단계로 이루어진 비용 모델 사다리

체결 시뮬레이션 사다리와 마찬가지로, 비용 모델은 각 단계가 더 많은 데이터를 필요로 하고 하나의 특정한 체계적 편향을 제거하는 정밀도 사다리를 형성한다. 각 단계는 누적적이다: 하위 항들을 유지하면서 하나를 추가한다.

M0: 상수 bps

C0=fee+cC_0 = \text{fee} + c

숫자 하나를 모든 거래에 적용한다. 세 가지 실패 양상을, 피해가 커지는 순서대로 나열하면:

  1. 규모 무시(Size-blind). 10k짜리클립과10k짜리 클립과 5M짜리 부모 주문이 같은 비용을 낸다. 용량 수준을 가로지르는 모든 전략 비교가 무의미해진다.
  2. 레짐 무시(Regime-blind). 잔잔한 화요일 오후와 FTX 붕괴가 같은 비용을 낸다. 이 오류는 노이즈가 아니라, 이벤트 기반 전략이 거래를 집중시키는 바로 그 상태들과 반상관되어 있다.
  3. 선택 오염(Selection-toxic). 200개의 파라미터 조합을 스윕하면, 옵티마이저는 평탄한 비용 아래에서 회전율이 현실 대비 싸다는 것을 발견하고 전체 탐색을 고빈도 변형 쪽으로 끌고 간다. 비용 오류는 PnL에 대한 대칭적 힘이 아니라 모델 선택에 대한 방향성 힘이 된다.

M1: 스프레드 비례

C1=fee+st2C_1 = \text{fee} + \frac{s_t}{2}

의사결정 타임스탬프 시점의 측정된 반스프레드(half-spread)를 부과한다(수수료는 결정론적이므로 항상 별도 항목으로 두어야 한다). 이것은 시장에 조금이라도 반응하는 첫 번째 모델이다: 스프레드는 뉴스가 있을 때, 세션 오픈 때, 얇은 알트코인에서 벌어지므로, 이제 비용은 적어도 하나의 유동성 변수와 함께 움직인다. 여전히 놓치는 것: 스프레드는 오더북 최상단 클립 하나의 체결에 대한 가격이다. 그보다 큰 것은 오더북을 걸어 내려가는데(walk the book), 그 걸음은 sts_t에게 보이지 않는다.

M2: 변동성 스케일링

C2=fee+st2+cσσtC_2 = \text{fee} + \frac{s_t}{2} + c_\sigma \, \sigma_t

단기 시평(short-horizon) 변동성에 비례하는 항을 더한다. 그 근거는 실증적이면서 구조적이다: 스프레드와 깊이는 역선택 및 재고 위험이 σ\sigma에 따라 스케일링되는 마켓메이커에 의해 설정되므로(Avellaneda-Stoikov 호가 로직을 역으로 돌린 것), 유동성을 요구하는 비용은 자연스럽게 변동성 단위로 표시된다. 오더북 데이터가 전혀 없을 때 — 일봉, 긴 히스토리 — cσc_\sigma가 일별 변동성의 약 0.05–0.1인 cσσtc_\sigma \sigma_t는 이미 어떤 상수보다도 극적으로 나은 모델인데, 적어도 레짐과 함께 호흡하기 때문이다.

M3: 참여율의 제곱근

C3=fee+st2+Yσt(QVt)δ,δ0.40.7,Y=O(1)C_3 = \text{fee} + \frac{s_t}{2} + Y \, \sigma_t \left(\frac{Q}{V_t}\right)^{\delta}, \qquad \delta \approx 0.4\text{–}0.7, \quad Y = O(1)

규모 항이다. QQ는 여러분의 주문 규모, VtV_t는 해당 윈도우에서의 시장 거래량, σt\sigma_t는 같은 윈도우에서의 변동성이다. 이 함수 형태는 편의상 고른 것이 아니다; 시장 미시구조에서 가장 여러 번 재현된 실증 결과 중 하나이며, 그것이 어디서 나왔는지 정확히 짚어 볼 가치가 있다.

이론적 출발점은 Kyle (1985), "Continuous auctions and insider trading" (Econometrica 53(6), 1315–1335)이다. Kyle의 모델에서 마켓메이커는 순주문흐름의 선형 함수로 가격을 설정하며, Δp=λq\Delta p = \lambda q이고

λ=12Σ0σu\lambda = \frac{1}{2}\frac{\sqrt{\Sigma_0}}{\sigma_u}

— 흐름 단위당 충격이 노이즈 트레이딩 거래량 대비 가치 불확실성에 비례한다. Kyle의 람다는 이 분야에 유동성의 단위(깊이는 1/λ1/\lambda)와 최초의 검증 가능한 주장을 주었다: 거래된 달러당 비용은 상수가 아니라 정보 대 유동성의 비율에 의존한다. 하지만 이 모델은 규모에 대해 선형이고, 데이터는 그렇지 않다고 말한다.

데이터는 *오목(concave)*하다고 말한다. Almgren, Thum, Hauptmann and Li (2005), "Direct estimation of equity market impact" (Risk, July 2005)는 Citigroup 데스크의 미국 주식 주문 약 700,000건을 피팅했고, 일시적 충격이 참여율의 3/53/5 제곱으로 증가함을 발견했다 — 그들은 선형과 순수 제곱근을 명시적으로 검정하고 둘 다 기각하며 δ=0.6\delta = 0.6을 지지했다 — 반면 영구적 충격은 0.89±0.100.89 \pm 0.10으로 나와, 선형과 통계적으로 구별되지 않았다(이는 안심되는 결과인데, Huberman and Stanzl (2004)이 비선형 영구 충격은 조작을 허용함을 보였기 때문이다). Tóth et al. (2011), "Anomalous price impact and the critical nature of liquidity in financial markets" (Physical Review X 1, 021006)는 Capital Fund Management의 선물시장 메타주문 약 500,000건을 사용해 E[ΔP]YσdQ/Vd\mathbb{E}[\Delta P] \approx Y \sigma_d \sqrt{Q/V_d}이며 YY가 1 정도의 크기임을 발견했고 — 이제는 표준이 된 설명을 제시했다: 가시적 오더북은 잠재 유동성의 극히 작은 일부일 뿐이고, 이 잠재 유동성은 중간가 주변에서 가격에 대해 국소적으로 선형이므로, 그것을 먹어치우는 비용이 제곱근으로 스케일링된다는 것이다. 이후 연구는 가장자리를 정밀화한다: Zarinelli, Treccani, Farmer and Lillo (2015), "Beyond the square root" (Market Microstructure and Liquidity 1(2))는 700만 건의 ANcerno 기관 메타주문에서 제곱근이 주문 규모의 약 2 자릿수(decade)에 걸쳐 잘 맞지만 로그 형태는 5 자릿수에 걸쳐 확장됨을 보였다; Bucci et al. (2019, Physical Review Letters 122, 108302)는 매우 작은 참여율에서의 선형(Kyle 유형) 충격으로부터 그 위의 제곱근으로의 전이(crossover)를 기록했다. 그리고 Frazzini, Israel and Moskowitz (2018), "Trading Costs" (SSRN 3229719)는 19년에 걸친 AQR의 실전 체결 $1.7조 달러를 사용해 실현 비용이 이전 학술 추정치보다 한 자릿수 작다는 것을 발견했다 — 이는 다른 사람의 흐름에, 다른 긴급도와 다른 정보 함량으로 피팅한 계수가 여러분의 것으로 이전되지 않는다는 경고다.

백테스트 루프를 위한 실용적 요약은 세 가지 진술이다. 충격은 변동성에 따라 스케일링된다. 충격은 규모에 대해 오목하며, 지수는 여러분 자신의 데이터가 0.60.6을 주장하기 전까지는 0.50.5로 취급해야 한다. 계수 YY는 1 정도의 크기지만 거래소, 자산, 그리고 — 결정적으로 — 여러분 자신의 트레이딩 스타일에 따라 달라지며, 그래서 다음 절이 그것을 복사하는 것이 아니라 피팅하는 것에 관한 것이다. 심층 캘리브레이션(감쇠 커널, 일시적 대 영구적 분해, 교차 충격)은 충격 모델링 글에 속한다; 백테스트는 곡선만 필요하다.

규모 감각을 잡기 위한 계산 예시. BTC 무기한(perp), 일별 변동성 σd=250\sigma_d = 250 bps, 거래소 일별 거래량 V_d = \6B,B, Y = 0.75,, \delta = 0.5$:

주문 규모 QQ Q/VdQ/V_d Q/Vd\sqrt{Q/V_d} 충격 항 + 반스프레드 (0.5 bp)
$50k 0.0008% 0.0029 0.5 bp 1.0 bp
$500k 0.008% 0.0091 1.7 bp 2.2 bp
$5M 0.083% 0.0289 5.4 bp 5.9 bp
$50M 0.83% 0.0913 17.1 bp 17.6 bp

규모에서의 세 자릿수 차이가 비용에서는 약 18배의 폭에 걸쳐 있다. 어떤 상수도 이 표를 감당하지 못하며, slippage_bps를 고정한 채 포지션 크기를 변화시키는 모든 전략 비교는 50k의사과와50k의 사과와 5M의 오렌지를 조용히 비교하고 있는 것이다.

곡선 피팅하기: 여러분의 체결, 아니면 그 누구의 것도 아닌 것

여러분 자신의 체결로부터

올바른 데이터는 여러분 자신의 TCA 기록이다: 부모 주문 한 건당 한 행으로, 도착(arrival) 중간가, 실현 체결 VWAP, 주문 규모, 그리고 의사결정 시점의 시장 상태를 담은 것 — 바로 실행 부족 측정(implementation shortfall)이 부산물로 생성하는 데이터셋이다. 도착 대비 bps로 표시된 부족분을 동시점 변동성으로 정규화하고 참여율에 회귀시키면 YYδ\delta를 직접 얻는다.

함정은 노이즈다. 단일 주문의 부족분은 충격에 실행 윈도우 동안의 가격 노이즈를 더한 것인데, 노이즈가 지배적이다: 일별 변동성 250 bps에서 10분 실행의 경우, 노이즈 항은 σd10/144021\sigma_d\sqrt{10/1440} \approx 21 bps인 반면 충격 시그널은 기껏해야 3 bps 정도다. 관측치당 신호대잡음비 0.15가 Almgren et al.이 700k개의 주문을 필요로 했던 이유이며, 여러분이 절대 원시 데이터 포인트가 아니라 버킷 중앙값에 피팅해야 하는 이유다:

import numpy as np
import pandas as pd

def fit_sqrt_curve(orders: pd.DataFrame) -> tuple[float, float]:
    """orders: one row per parent order.
       is_bps    -- implementation shortfall vs arrival mid, bps, cost-positive
       sigma_bps -- volatility at arrival (same window used at simulation time)
       q_over_v  -- parent size / market volume over the execution window
    Fits I = Y * sigma * (Q/V)^delta on participation-bucket medians."""
    df = orders.query("q_over_v > 0 and sigma_bps > 0").copy()
    df["i_norm"] = df.is_bps / df.sigma_bps            # impact in vol units
    df["bucket"] = pd.qcut(np.log10(df.q_over_v), 12, duplicates="drop")
    b = (df.groupby("bucket", observed=True)
           .agg(i=("i_norm", "median"), qv=("q_over_v", "median")))
    b = b[b.i > 0]               # noisy buckets can go negative; drop, don't clip
    delta, log_y = np.polyfit(np.log(b.qv), np.log(b.i), 1)
    return float(np.exp(log_y)), float(delta)

몇천 건의 크립토 부모 주문에서 이 피팅은 YY에 대해 대략 ±30%, δ\delta에 대해 ±0.1 정도로 이미 안정적이다 — 거칠지만, 피팅된 곡선과 추측한 상수 사이의 차이는 30%가 아니라 형태 전체다. 분기별로 재피팅하라; YY의 드리프트 자체가 진단 지표다(참여율이 일정한데 YY가 상승한다는 것은 거래소의 유동성 레짐이 바뀌었거나 여러분의 주문흐름이 더 정보성이 강해졌거나/더 탐지되기 쉬워졌다는 뜻이다).

콜드 스타트: 아직 체결이 없을 때

첫 실전 주문 전에는 공개 데이터만 있으며, 정직한 선택지는 두 가지다.

오더북 깊이 걸어내리기(Depth-walk). 각 규모에서 L2 스냅샷을 걸어 내려가는 비용을 평균 내라 — 체결 시뮬레이터가 거래별로 하는 것과 똑같지만, 곡선으로 집계한다. 이것은 부호가 알려진 *하한(lower bound)*이다: 스냅샷은 다른 모든 이의 흐름에서 살아남은 유동성을 보여주고, 리필 동역학은 보이지 않으며, 여러분 자신의 앞선 자식 주문들이 나중 주문들이 도착하기 전에 이미 오더북을 움직여 놓았을 것이다.

def curve_from_book(snapshots, sizes_usd, safety=1.75):
    """snapshots: iterable of (mid, asks), asks = [(price, qty), ...] best-first.
    Depth-walk cost is a LOWER bound on realized cost -- scale it."""
    rows = []
    for q_usd in sizes_usd:
        costs = []
        for mid, asks in snapshots:
            rem, paid, got = q_usd / mid, 0.0, 0.0
            for p, q in asks:
                x = min(q, rem)
                paid += x * (p - mid); got += x; rem -= x
                if rem <= 0:
                    break
            if rem <= 0:
                costs.append(paid / got / mid * 1e4)
        rows.append((q_usd, safety * float(np.median(costs))))
    return pd.DataFrame(rows, columns=["q_usd", "cost_bps"])

공개 거래 발자국 추적(Footprint public trades). 공격적(aggressor) 거래를 규모별로 구간화하고, 각 거래 후 몇 초 뒤의 중간가 이동을 측정해, 실증적 충격 곡선을 읽어낸다. 이것은 오목한 형태와 대략 올바른 σ\sigma-스케일링을 복원하지만, 그 수준은 사전에 부호를 알 수 없는 방향으로 편향되어 있다: 공개 프린트는 다른 트레이더들의 결정이므로 큰 프린트는 조건부로 정보성을 띠고(여러분의 무정보 리밸런스 대비 측정 충격을 위로 편향시킴) 반면 가장 유동성에 민감한 트레이더들은 바로 숨기려고 주문을 쪼갠다(아래로 편향시킴). 수준이 아니라 형태에만 사용하라.

어느 쪽이든, 콜드 스타트 프로토콜은 다음과 같다: 공개 데이터 곡선을 가져와 1.5–2의 안전 계수를 적용하고, 작게 거래하며, 그것을 대체할 TCA 표를 채우기 시작하라. 공개 곡선은 비계(scaffolding)이지 하중을 지탱하는 벽이 아니다.

레짐 의존성: 같은 주문, 다섯 배의 비용

잔잔한, 정상, 스트레스 변동성 레짐에 걸쳐 부챗살처럼 펼쳐지는 비용 곡선들

C3C_3의 모든 항은 상태 의존적이며, 변동성 급등에서는 그것들이 모두 동시에 여러분에게 불리하게 움직인다. 스프레드는 단기 시평 변동성에 비례하므로 sts_t가 5–10배 벌어진다. σt\sigma_t는 충격 항에 직접 들어간다. 거래량 VtV_t도 상승하는데 — 순진하게 보면 참여율을 낮춘다 — 하지만 분자의 σ\sigma보다는 덜 상승하고, 이 상쇄는 더 고약한 효과를 숨긴다: 중간가 근처의 호가 깊이는 거래량보다 훨씬 빠르게 붕괴하므로, 실현 곡선은 스트레스 입력만으로 피팅 공식이 예측하는 것보다 더 가팔라진다.

구체적으로, 위에서 피팅한 곡선을 가지고 $3M짜리 BTC 주문의 경우:

  • 잔잔한 날: σd=150\sigma_d = 150 bps, 스프레드 1 bp, V_d = \6B.비용B. 비용 = 0.5 + 0.75 \times 150 \times \sqrt{0.0005} = 0.5 + 2.5 = 3.0$ bps.
  • 위기의 날 (LUNA, FTX 급): σd=700\sigma_d = 700 bps, 스프레드 6 bps, V_d = \18B.비용B. 비용 = 3.0 + 0.75 \times 700 \times \sqrt{0.000167} = 3.0 + 6.8 = 9.8$ bps.

공식은 3.3배라고 말한다. 스트레스 날의 실현 TCA는 일관되게 공식보다 높게 나오는데 — 제곱근 항이 보지 못하는 깊이 붕괴 때문이며 — 바로 여기에 측정된 스트레스 승수가 들어갈 자리가 있다. 우리 체결에서 위기 버킷 잔차는 스트레스 입력 공식 위에 1.4–1.8배로 나오며, 같은 주문에 대해 총 스트레스 비용이 잔잔한 날 비용의 4.5–6배에 이른다. 이것이 "변동성 급등에서 같은 주문이 5배 더 든다"의 정직한 기원이다: 대략 거래량을 상쇄한 σ\sigma에서 2배, 스프레드에서 2배, 그리고 나머지는 거래량 통계가 인정하는 것보다 빠르게 증발하는 깊이에서 온다.

구현은 조건부 비용 모델이다: 레짐 버킷별로 곡선을 피팅하거나, 동등하게, 하나의 곡선과 의사결정 시점에 계산된 실현 변동성 분위수(trailing 윈도우만 — 전체 표본에서 계산한 레짐 라벨은 비용 모델을 통해 밀반입된 룩어헤드(look-ahead)다)를 키로 하는 승수 표를 피팅한다:

레짐 (trailing 1시간 변동성 분위수) 빈도 스프레드 승수 곡선 승수 (측정치)
조용함 (< p25) 25% 0.6x 0.7x
정상 (p25–p75) 50% 1.0x 1.0x
상승 (p75–p95) 20% 1.8x 1.6x
스트레스 (> p95) 5% 5–10x 3–6x

Frazzini, Israel and Moskowitz (2018)은 기관 데이터에서 같은 현상을 기록한다: 실현 비용은 동시점 변동성과 강하게 함께 움직이며, 시변(time-varying) 변동성 항이 없는 비용 모델은 정확히 꼬리(tail)의 가격을 잘못 매긴다. 이 표가 5% 스트레스 행이 시사하는 것보다 더 중요한 이유는 상관관계 때문이다: 전략들은 이 행들을 균일하게 표집하지 않는다. 변동성 브레이크아웃 시스템은 거래의 대부분을 아래 두 행에서 한다. 잔잔한 시장의 마켓메이커는 맨 위 행에서 벌고 맨 아래 행에서 손절한다. 각 전략의 거래를 무조건부 평균으로 모두에게 부과하는 대신 그 전략 자신의 레짐 히스토그램으로 가중하는 것이, 이벤트 기반 시스템에 대해 이 페이지 전체에서 가장 큰 단일 PnL 보정이며, 사다리의 인접한 두 단계 사이의 차이보다도 더 가치 있다.

민감도 실험: 네 개의 비용 모델, 하나의 재편된 순위표

비용 모델이 PnL을 상수 오프셋만큼 바꾼다면 선택에는 아무것도 문제되지 않을 것이다 — 모든 변형이 똑같이 이동하고 argmax는 살아남을 것이다. 그렇지 않은데, 비용 민감도가 변형들 사이에서 한 자릿수만큼 달라지기 때문이다. 이것을 구체화하는 실험:

설정. 하나의 전략 패밀리 — BTC와 ETH 무기한에 대한 z-score 평균회귀와 Donchian 브레이크아웃, 1분봉, 18개월 — 을 보유 시평(15m / 1h / 4h / 24h)과 진입 임계값에 대한 그리드로 돌린다: 20개 변형, 일일 오더북 대비 0.4배에서 11배의 단방향 회전율, $250k 클립을 5분에 걸쳐 실행. 각 변형은 비용 모델당 한 번씩 백테스트한다:

  • M0: 수수료만;
  • M1: 수수료 + 5 bps 상수;
  • M2: 수수료 + 반스프레드 + 0.08σ5m0.08\,\sigma_{5m};
  • M3: 수수료 + 피팅된 곡선 Y=0.75Y=0.75, δ=0.5\delta=0.5에 위의 레짐 승수 표 적용.

같은 체결, 같은 시그널, 같은 코드 경로 — 비용 모델은 다른 어떤 일급(first-class) 파라미터와 마찬가지로 생성자 인자로 백테스터에 전달된다:

from dataclasses import dataclass

@dataclass(frozen=True)
class SqrtCost:
    y: float = 0.75        # fitted impact coefficient
    delta: float = 0.5     # fitted exponent
    fee_bps: float = 2.5   # taker fee, always separate
    def cost_bps(self, q_usd: float, st) -> float:
        part = q_usd / st.window_volume_usd
        return (self.fee_bps + st.stress_mult *
                (st.spread_bps / 2 + self.y * st.sigma_bps * part ** self.delta))

for model in [ZeroCost(), ConstCost(5.0), VolCost(0.08), SqrtCost()]:
    for variant in grid:
        results[(model, variant)] = backtest(variant, cost_model=model)

결과 (대표적 실행; 연율화 순수익률):

변형 일일 회전율 M0 M1 (5 bp) M2 M3 (곡선) 순위 M1 → M3
MR-15m, z=1.0 11.4x +187% +61% +9% −14% 1 → 17
MR-15m, z=1.5 7.9x +141% +52% +15% −2% 2 → 13
BO-1h, k=2 3.1x +74% +43% +28% +19% 3 → 4
MR-1h, z=2.0 2.4x +58% +38% +25% +21% 4 → 2
BO-4h, k=3 0.9x +39% +33% +29% +26% 7 → 1

네 개의 비용 모델에 걸쳐 20개 전략의 순위가 뒤집히는 범프 차트

순위표 사이의 순위 상관(Kendall τ\tau): τ(M0,M1)=0.79\tau(\text{M0},\text{M1}) = 0.79 — 상수는 거의 아무것도 재정렬하지 않는다, 그것은 세금이지 모델이 아니다. τ(M1,M3)=0.39\tau(\text{M1},\text{M3}) = 0.39 — M1의 상위 10개 중 6개가 M3 아래에서 상위 10에서 이탈하고, M1의 챔피언은 +61%에서 마이너스로 간다. τ(M2,M3)=0.74\tau(\text{M2},\text{M3}) = 0.74 — 변동성 항만으로도 재정렬의 대부분이 복원된다; 규모 항은 윈도우 거래량 대비 크게 거래하는 변형들에 대해 마무리를 짓는다. 그 메커니즘은 정확히 M0 단계에서의 선택 오염이다: 평탄한 5 bps는 실제로 15 bps가 드는 거래(크고, 빠르고, 스트레스 중)에 보조금을 주고 2가 드는 거래(작고, 참을성 있고, 잔잔한 상태)에 과세한다, 그래서 M1으로 순위를 매기면 참비용이 가장 크게 과소평가된 변형들이 체계적으로 승격된다. 옵티마이저는 알파를 찾은 것이 아니다; 그것은 여러분 비용 모델의 오차항을 찾은 것이다.

이것이 비용 모델이 워크포워드 분할이나 목적 함수와 같은 정신적 범주에 속하는 이유다: 한 번 설정하는 환경 상수가 아니라, 여러분이 변화시키는 일급 백테스트 파라미터다. 어떤 변형의 순위가 M2와 M3에 걸쳐 안정적이라면, 그 엣지는 비용 대비 실재한다. 사다리를 올라감에 따라 순위가 무너진다면, 그것이 비용 모델의 인공물이었음을 배운 것이다 — 워크포워드 최적화에서 전략이 표본 외에서 죽는 것과 동일한 인식론적 사건이며, 동일한 대응을 받을 만하다. 그리고 M1 아래에서 200개 변형의 argmax를 선택했다면, 디플레이티드 샤프(deflated Sharpe) 논리가 한 가지 반전과 함께 적용된다: 여러분은 검정 통계량 자체가 고회전 진입에 유리하게 편향된 다중검정 탐색을 돌린 것이다.

정직한 경계: 밴드로서의 PnL

마지막 규율은 피팅 이후에도 비용 모델이 불확실하다는 것을 인정하는 데서 따라온다. YY에는 신뢰구간이 있고, 스트레스 승수는 소수의 꼬리 날들로부터 추정되며, 미래는 자신만의 레짐을 뽑는다. 그러니 순 PnL을 하나의 숫자로 보고하는 것을 멈춰라. 그것을 명명된 비용 시나리오들에 걸친 밴드로 보고하라:

  • 낙관적: 깊이 걸어내리기 하한, 스트레스 승수 없음. 절대 단독으로 보고하지 말라; 그 유일한 역할은 최선의 경우를 경계 짓는 것이다.
  • 현실적: 피팅된 곡선, 피팅된 레짐 승수 — 여러분의 중심 추정치.
  • 비관적: Y×1.5Y \times 1.5, 스프레드 ×2\times 2, 스트레스 행은 항상 그 p75 값 \geq에서 적용. 대략: 피팅된 곡선을 모든 파라미터 신뢰구간의 비우호적 가장자리에서 평가한 것.

두 가지 의사결정 규칙이 밴드를 실무적으로 만든다. 첫째: 비관적으로 배분하고, 현실적으로 보고하라. 현실적 모델 아래에서만 살아남는 전략은 여러분의 비용 피팅이 비싼 방향으로 오차가 없다는 것에 거는 베팅이다 — 여러분이 의식적으로 하지 않은 베팅이다. 둘째: 취약성 비율(fragility ratio) — 총 PnL 대비 밴드 폭 — 을 추적하라. 위 실험에서: 회전율 0.9배의 BO-4h는 총 +39%, 밴드 [+22%, +29%], 취약성 0.44를 보인다. 회전율 11.4배의 MR-15m은 총 +187%, 밴드 [−31%, +34%]를 보인다 — 취약성 2.2이며, 전략의 부호가 밴드 안에서 뒤집힌다. 그 두 번째 전략은 여러분의 현재 비용 지식 상태에서 결정 가능한 부호가 없다; 정직한 진술은 "우리는 모른다"와 "알게 될 때까지 회전율을 줄여라"이다. +34%를 인쇄하면서 밴드의 −31% 가장자리를 생략하는 백테스트는 낙관적인 것이 아니라 반증 불가능한 것이다.

밴드를 만드는 데는 비용이 들지 않는다 — 이제 어차피 돌리고 있는 비용 모델 스윕에 세 개의 항목이 더해질 뿐이다 — 그리고 그것은 대화를 바꾼다. "이 전략은 20%를 번다"는 믿음을 유도한다. "이 전략은 우리의 비용 시나리오들에 걸쳐 11–19%를 벌고, 비관적 시나리오 아래에서도 양수를 유지한다"는 배분을 유도한다.

이것이 어디에 꽂히는가

백테스트 엔진에서, 비용 모델은 정확히 체결 시뮬레이터가 실행된 수량을 되돌려주는 자리에 앉는다: 체결은 여러분이 무엇을 얻었는지를 결정하고, 비용 곡선은 그것에 대해 무엇을 지불했는지를 결정하며, 그 사다리에서 L2 위의 단계들(깊이 걸어내리기, 큐 모델)은 비용 모델을 점진적으로 체결 모델 자체에 흡수한다 — 곡선은 오더북을 직접 시뮬레이션하지 않을 때 사용하는 파라메트릭 대체물이다. 파라미터는 보유하고 있을 때는 여러분 자신의 TCA 기록에서 오고, 없을 때는 안전 계수로 스케일링한 공개 데이터에서 온다. 함수 형태는 40년간의 이론과 측정에서 온다 — 달러당 비용이 왜 유동성에 의존하는지에 대해서는 Kyle (1985), 오목 법칙 자체에 대해서는 Almgren et al. (2005)과 Tóth et al. (2011), 스케줄링 대응물로는 Almgren-Chriss, 예측 최전선으로는 신경망 충격 모델. 이 글이 더하는 것은 워크플로우다: 곡선을 피팅하고, 레짐에 조건화하고, 파라미터처럼 스윕하고, 밴드를 보고하라. 그 어느 것도 화려하지 않다. 그 모든 것이 여러분의 전략이 실제로 slippage_bps = 5의 어느 쪽에 있었는지를 실전에서 발견하는 것보다 싸다.

blog.disclaimer

Authors

Eugen Soloviov
Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Newsletter

시장에서 앞서 나가세요

뉴스레터를 구독하여 독점적인 AI 트레이딩 통찰력, 시장 분석 및 플랫폼 업데이트를 받아보세요.

귀하의 개인정보를 존중합니다. 언제든지 구독을 취소할 수 있습니다.