월가 필살기 페어트레이딩 돌려봤다 — 승률 60%인데 돈이 녹는 이유
상관계수와 공적분으로 페어를 찾고 칼만 필터로 헷지하는 시장중립 전략을 백테스트로 돌려봤습니다. 높은 승률에도 불구하고 수수료와 손익비 구조 때문에 왜 계좌가 녹는지 그 기록입니다.
유튜브에서 시장 방향과 상관없이 수익을 내는 전략으로 페어 트레이딩을 다뤘습니다. 결론부터 말하면, 백테스트 그래프는 그럴싸했지만 막상 돌려보니 돈이 녹았습니다. 이 글은 그 정리본에 영상에는 안 넣은 최소 실행 코드를 붙인 것입니다. 제 수익률은 여기에 옮겨 적지 않겠습니다. 제가 유리한 구간만 고르게 되니까요. 대신 승률은 높은데 왜 계좌는 우하향했는지 그 구조를 추적해 봤습니다.
시장중립이라는 말은 공짜 점심이 아니다
페어 트레이딩의 아이디어는 간단합니다. ETH와 ETC처럼 원래 같이 움직이던 두 자산의 가격이 일시적으로 벌어졌을 때, 비싸진 쪽을 팔고(숏) 싸진 쪽을 사서(롱) 그 차이가 다시 좁혀지면 청산해 차익을 얻는 전략입니다. 시장 전체가 오르든 내리든 두 자산의 '상대적 가격'에만 베팅하기 때문에 '시장중립'이라고 부릅니다. 방향을 예측할 필요가 없다는 점에서 아주 매력적으로 들리죠.
그런데 이 전략의 모든 것은 "원래 같이 움직이던"이라는 가정이 진짜일 때만 성립합니다. 그냥 우연히 지난 6개월간 같이 우상향한 두 코인을 묶으면, 그 관계는 언제든 깨질 수 있습니다. 관계가 깨진다는 건 벌어진 격차가 영원히 돌아오지 않는다는 뜻이고, 제 계좌는 그대로 박살 나는 겁니다. 그래서 이 전략의 성패는 '진짜 관계'를 어떻게 찾아내느냐에 달려 있습니다.
진짜 '목줄'은 상관계수가 아니라 공적분이다
흔히 쓰는 상관계수는 함정입니다. 두 코인 가격이 그냥 같이 오르기만 해도 0.9 넘게 찍히거든요. 이건 진짜 관계가 아니라 같은 추세를 공유했을 뿐인 '허상 관계'일 가능성이 높습니다. 진짜 관계, 즉 한 놈이 멀리 도망가면 다른 한 놈이 끌어당기는 '목줄'이 있는지를 통계적으로 검증하는 방법이 바로 공적분(Cointegration)입니다.
원리는 이렇습니다. 두 코인 가격(y와 x)을 회귀분석해서(y = α + βx + e) 그 잔차(e, 오차)를 뽑아냅니다. 이 잔차가 바로 두 코인 간의 스프레드, 즉 벌어진 정도입니다. 만약 두 코인에 목줄이 있다면 이 스프레드는 평균값 0 주변을 계속 맴돌아야 합니다. 즉, 스프레드가 안정적 시계열(Stationary Series)이어야 합니다. 이걸 ADF(Augmented Dickey-Fuller) 검정으로 확인하는 겁니다. 진짜 관계는 상관계수가 아니라 공적분입니다.
// ---- 공적분(목줄) 판정용 도우미 ----
// y 를 x 로 회귀 -> 그 잔차(스프레드)에 ADF 걸어서 t값 리턴.
// 이 t값이 임계값(-3.34쯤)보다 더 아래(더 음수)면 목줄 있음 판정.
public static double EngleGranger(double[] x, double[] y)
{
double a, b;
double[] resid;
Ols(x, y, out a, out b, out resid);
// 잔차(스프레드)가 평균으로 회귀하는 성질이 있는지 검사한다.
// 이게 페어 트레이딩의 심장이다.
// 통계적으로 유의미하게 회귀하지 않으면(목줄 없으면), 그 페어는 그냥 남남이다.
return Adf(resid, 1, false);
}
// ADF 검정 (Augmented Dickey-Fuller)
// 시계열이 평균으로 되돌아오는 성질(정상성)이 있는지 확인.
// t값이 특정 임계치보다 낮으면 정상성이 있다고 본다.
public static double Adf(double[] y, int lags, bool withConst)
{
// (내부 구현은 회귀분석이라 복잡해서 생략)
// ...
// 핵심: 회귀계수가 통계적으로 유의미한 음수인지 확인하는 과정
double tstat = coef[gIdx] / se[gIdx];
return tstat;
}헷지 비율은 칼만 필터로 실시간 보정한다
목줄이 있는 페어를 찾았다고 끝이 아닙니다. ETH 1개를 살 때 ETC를 몇 개 팔아야 정확히 시장중립이 될까요? 이 비율(헷지 비율, 베타)은 고정된 값이 아닙니다. 시장 상황에 따라 계속 변합니다. 과거 6개월 데이터로 구한 베타 값이 다음 달에도 유효하리란 보장이 없습니다.
여기서 쓰는 게 칼만 필터입니다. 칼만 필터는 새로운 가격 데이터가 들어올 때마다 헷지 비율을 아주 조금씩, 실시간으로 보정해줍니다. 과거 데이터에 박제된 비율을 쓰는 게 아니라, 현재 시장의 반응을 보고 계속 미세조정하는 겁니다. 이렇게 하면 관계가 서서히 변하는 것에 어느 정도 대응할 수 있습니다. 물론 이것도 만능은 아닙니다. 관계가 갑자기 부러지는 것까진 못 막거든요.
아래 코드는 실제 백테스트 로직의 일부입니다. 칼만 필터로 계산된 스프레드가 z스코어(평소 출렁임의 몇 배나 벌어졌는지)를 기준으로 진입(EntryZ)과 청산(ExitZ), 손절(StopZ)을 결정합니다. 여기서 수수료(Fee)를 빼먹으면 백테스트는 무조건 우상향하는 그림만 보여주게 됩니다.
// ---------- 진입 판단 (쉬고 있을 때) ----------
if (zReady && pos == 0)
{
// z가 +로 튐 = Y가 비쌈 -> Y 숏 / X 롱 = 스프레드 숏(-1)
// z가 -로 튐 = Y가 쌈 -> Y 롱 / X 숏 = 스프레드 롱(+1)
int dir = 0;
if (z >= cfg.EntryZ) dir = -1;
if (z <= -cfg.EntryZ) dir = +1;
if (dir != 0)
{
// ... 수량 계산 후 ...
pos = dir;
// 진입 수수료는 비용이다. 양쪽 다리에서 두 번 나간다.
// 수익률 계산할 때 이걸 빼먹는 실수를 정말 많이 한다.
double entryNotional = qtyY * curY + qtyX * curX;
realized -= cfg.Fee * entryNotional;
}
}
// ---------- 청산 판단 (포지션 있을 때) ----------
if (zReady && pos != 0)
{
bool doClose = false;
if (Math.Abs(z) <= cfg.ExitZ) doClose = true; // 익절: 다시 붙었다
if (Math.Abs(z) >= cfg.StopZ) doClose = true; // 손절: 목줄 끊어졌다
if (doClose)
{
// ... 손익(pnl) 계산 후 ...
// 청산 수수료 또 나간다. 이게 진짜 아프다.
double exitNotional = qtyY * curY + qtyX * curX;
pnl -= cfg.Fee * exitNotional;
realized += pnl;
pos = 0; // 이제 쉬자
}
}왜 이게 실전에서 깨지는가
- 수수료가 생각보다 훨씬 큽니다. 진입 시 롱/숏 양쪽에서 한 번, 청산 시 또 양쪽에서 한 번, 총 네 번의 수수료를 냅니다. 우리가 얻으려는 스프레드 차익이 이 수수료보다 커야 하는데, 대부분 그렇지 못합니다.
- 손익비 구조가 치명적입니다. 스프레드가 다시 붙어서 얻는 익절(Win)은 폭이 제한적인데, 목줄이 끊어져서 맞는 손절(Loss)은 무한대에 가깝습니다. 승률이 60%를 넘어도 한 번의 큰 손절이 아홉 번의 작은 익절을 모두 삼켜버릴 수 있습니다.
- 관계는 영원하지 않습니다. 과거 1년간 공적분 관계였던 페어가 다음 달에 깨지는 일은 비일비재합니다. 가장 위험한 건 깨진 페어가 아니라 '이 페어는 영원할 거야'라는 믿음입니다.
- 유동성과 슬리피지가 빠져있습니다. 백테스트는 어제 종가에 정확히 체결됐다고 가정하지만, 실전에서는 매수/매도 호가 갭(스프레드)만큼의 슬리피지가 발생합니다. 이것도 전부 비용입니다.
- 파라미터 과최적화의 덫에 빠지기 쉽습니다. 진입/청산 z스코어, 롤링 윈도우 같은 파라미터를 과거 데이터에 가장 잘 맞는 값으로 설정하면, 그건 미래에 통하지 않는 '정답지'를 만드는 것과 같습니다.
- 동시 체결이 불가능합니다. 롱 포지션과 숏 포지션을 원자적으로 동시에 체결할 수 없습니다. 한쪽 다리만 체결되고 다른 쪽이 실패하면, 저는 시장중립 포지션이 아니라 방향성에 노출된 위험한 포지션을 떠안게 됩니다.
이 글과 첨부 코드는 전략 구조를 설명하려고 만든 교육·연구 자료입니다. 특정 종목이나 매매를 권하지 않습니다.
첨부파일
영상에 사용된 소스코드와 설명서입니다. 로그인 없이 받을 수 있습니다.
페어트레이딩 백테스터 전체 소스