0.95의 벽, 그리고 직교라는 정공법 (월드퀀트 브레인 2편)
월드퀀트 브레인 프로젝트를 세션마다 공개용으로 기록하는 시리즈의 2편. 1편에서 멈춘 0.95의 벽을 직교 신호로 넘어보려 한 하루의 기록이다.
1편은 솔직한 패배로 끝났다. 흔한 단기 역추세 알파를 다섯 라운드나 튜닝해 Fitness를 0.95까지 끌어올렸지만, 제출 기준인 1.0 앞에서 딱 0.05를 못 넘기고 멈춰 섰다. 서버에게 직접 물어보니 다른 항목은 다 통과인데 오직 Fitness 하나만 미달이었다. 결론은 분명했다. 이 신호는 단독으로는 여기가 천장이고, 더 넘어가려면 역추세와 상관 없는 다른 신호를 섞어야 한다. 2편은 바로 그 일을 해본 이야기다.
직교라는 발상
핵심 아이디어는 분산 투자와 똑같다. 서로 잘 맞아 떨어지지 않는, 그러니까 수학에서 말하는 직교(orthogonal)에 가까운 신호 둘을 섞으면, 한쪽이 흔들릴 때 다른 쪽이 받쳐준다. 그래서 둘을 합친 포트폴리오는 위험 대비 수익, 즉 샤프가 각각보다 높아질 수 있다. 내 역추세 알파에 그런 짝을 붙여 샤프를 끌어올리면, 0.95의 벽도 넘을 수 있지 않을까 하는 계산이었다.
여기서 한 가지 약속을 정했다. 1편에서 고생해서 찾은 그 0.95짜리 역추세 신호를 ‘앵커’로 못 박고 절대 건드리지 않기로 한 것이다. 검증된 코어는 그대로 두고, 거기에 다른 신호를 얼마만큼 얹느냐만 실험하기로 했다. 변수를 하나로 줄여야 무엇이 효과가 있었는지 깨끗하게 읽힌다.
조합 공장 짓기
1편에서 알파를 대량으로 찍어내는 채굴기를 지어둔 덕에, 이번엔 그 위에 조합 전용 모듈만 얹으면 됐다. 앵커를 고정해두고, 직교 후보 신호 여섯 개를 라이브러리로 준비한 다음, 둘을 정해진 가중치로 섞어 다시 거래 게이트로 감싸는 생성기였다. 후보 신호는 모두 가격과 거래량처럼 이미 유효성이 확인된 데이터만 썼다. 1편에서 연구 자료에 적힌 항목 이름을 그대로 넣었다가 “그런 변수 없다”며 튕긴 적이 있어서, 이번엔 실재하는 이름만 골라 함정을 피했다.
직교 후보로 고른 여섯 개는 이랬다. 장기 모멘텀(최근 1년의 흐름), 저변동성(조용히 움직이는 종목 선호), 거래량 급증 되돌림, 거래량 추세 되돌림, 변동폭 압축(하루 고가와 저가 차이가 작은 종목), 그리고 vwap 갭(거래량 가중 평균가보다 꾸준히 위에서 거래되는 종목을 되판다)이었다. 단기 역추세와 성격이 겹치지 않을 만한 것들을 모은 셈이다.
1라운드, 누가 진짜 직교인가
여섯 개를 각각 절반 가중치로 앵커에 섞어 돌렸다. 결과는 냉정했다. 장기 모멘텀, 저변동성, 변동폭 압축, 이 셋은 오히려 앵커를 희석시켜 샤프를 1.1대로 끌어내렸다. 좋은 신호처럼 보였지만 내 역추세와는 궁합이 나빴던 것이다. 거래량 계열 둘은 샤프는 버텼지만 회전율을 올려서 Fitness를 깎았다.
딱 하나, vwap 갭만 달랐다. Fitness가 앵커와 똑같은 0.95로 나왔는데, 흥미롭게도 회전율이 오히려 줄었다. 샤프가 살짝 빠진 걸 회전율 감소가 메워 비긴 모양새였다. 회전율을 깎으면서도 신호를 망치지 않는 것, 그게 바로 진짜 직교의 표시였다. 다른 다섯은 떨어뜨리고, 이 하나만 들고 다음으로 갔다.
곡선을 그려보다
비겼다면, 무게를 더 가볍게 줬을 때 앵커의 샤프를 더 살릴 수 있지 않을까. 그래서 vwap 갭의 가중치를 0.2부터 1.0까지 바꿔가며 곡선을 그렸다. 그러자 깨끗한 그림이 나왔다. 가중치 0.2와 0.3에서 Fitness가 0.96으로 올라섰고, 0.5에서 0.95, 0.75에서 0.92, 1.0에서 0.89로 쭉 내려갔다.
작지만 의미 있는 승리였다. 1편의 0.95를 처음으로 넘겨 0.96을 찍은 것이다. 더 반가운 건 그게 한 점이 아니라 평평한 봉우리였다는 사실이다. 0.2와 0.3 두 군데서 똑같이 0.96이 나왔으니, 운 좋게 한 숫자에 걸린 게 아니라 그 근방이 다 좋다는 뜻이다. 억지로 끼워 맞춘 값은 이렇게 너른 평지를 만들지 못한다. 그러니 이 0.96은 진짜다. 가중치를 올릴수록 점수가 단조롭게 떨어진 것도 해석과 들어맞았다. vwap 갭은 소량일 때만 거들고, 과하게 주면 앵커를 덮어버린다.
욕심을 내서 둘을 얹다
0.96까지 왔으니 신호를 하나 더 얹으면 어떨까 싶었다. 거래량 급증 되돌림은 1라운드에서 샤프가 가장 높았으니, vwap 갭의 회전율 감소와 이 신호의 샤프를 합치면 둘 다 챙길 수 있을 것 같았다. 그런데 결과는 0.93으로 도리어 내려갔다. 신호를 더할수록 회전율만 늘고 샤프는 그대로였다. 욕심은 여기서 접었다.
펀더멘털이라는 기대와 배신
진짜 기대를 건 건 따로 있었다. 펀더멘털, 그러니까 회사의 가치 지표였다. 이런 지표는 분기마다 한 번씩 천천히 바뀌니 거래가 잦지 않아 회전율이 낮을 것이고, 단기 가격 움직임과도 상관이 없다. 회전율을 안 올리면서 수익을 보태는 것, 그게 내가 줄곧 찾던 바로 그 레버였다. 1편에서 “그런 변수 없다”며 막혔던 걸 떠올려, 이번엔 데이터 항목 목록부터 조회해 실재하는 가치 점수와 품질 점수의 정확한 이름을 받아왔다.
그런데 기대는 절반만 맞고 절반은 빗나갔다. 가치 점수를 가볍게 얹자 Fitness가 0.86으로 떨어졌다. 펀더멘털은 회전율이 낮을 거라던 내 가정이 틀렸던 것이다. 오히려 회전율이 살짝 올랐다. 종합 점수를 얹은 건 0.56으로 더 심하게 무너졌는데, 알고 보니 그 종합 점수 안에 모멘텀 성분이 섞여 있어 내 역추세와 정면으로 싸우고 있었다.
그래도 한 줄기 신호는 분명히 보였다. vwap 갭과 가치 점수를 함께 얹은 조합에서 샤프가 1.39까지 올랐다. 그날 본 가장 높은 샤프였고, 앵커의 1.37도 넘은 숫자였다. 가치 지표가 진짜 방향성 있는 수익을 보탰다는 증거다. 다만 그 대가로 회전율이 또 올라서, Fitness는 결국 0.95에서 멈췄다.
벽의 정체
여기서 하루 종일 따라다니던 패턴이 한 문장으로 정리됐다. 이 단기 역추세 알파의 Fitness는 회전율에 묶여 있다. Fitness가 샤프에 ‘수익을 회전율로 나눈 값의 제곱근’을 곱하는 구조이다 보니, 샤프와 회전율이 한 몸처럼 움직이는 게 문제였다. 샤프를 올려주는 신호(가치 점수)는 어김없이 회전율도 같이 올렸고, 회전율을 깎아주는 신호(vwap 갭)는 어김없이 샤프를 같이 깎았다. 두 레버가 서로의 발목을 잡으니, 1.0 바로 앞에서 늘 상쇄돼버렸다.
그러니 남은 0.04를 가중치 미세 조정으로 긁어낼 수야 있겠지만, 그건 1편에서 이미 경계한 함정이다. 과거 데이터에 딱 맞게 비튼 알파는 미래의 실제 데이터 앞에서 무너진다. 0.96이 이 신호의 정직한 한계라는 걸 받아들이는 게 맞았다.
하루가 남긴 깨달음
하나, 직교는 공짜 점심이 아니다. 분산이 샤프를 올린다는 교과서 문장은 맞지만, 회전율이라는 비용을 함께 본 순간 이야기가 달라졌다. 여섯 후보 중 다섯이 앵커를 도리어 깎아먹은 게 그 증거다. 어떤 신호가 ‘진짜 직교’인지는 머리로 정하는 게 아니라 돌려봐야 안다.
둘, 가설은 틀려도 데이터가 길을 알려준다. 펀더멘털이 회전율을 낮춰줄 거란 내 가정은 틀렸다. 하지만 그게 샤프를 1.39로 올린 걸 보고, 가치 지표에 진짜 수익이 들어 있다는 더 중요한 사실을 얻었다. 틀린 가설 하나가 다음 방향을 가리켜준 셈이다.
셋, 벽의 정체를 알면 더는 헛심을 안 쓴다. ‘Fitness가 회전율에 묶여 있다’는 한 문장을 손에 쥐고 나니, 같은 신호를 더 비틀어봐야 소용없다는 게 명확해졌다. 멈춰야 할 곳을 아는 것도 성과다.
다음 이야기
이제 방향이 분명해졌다. 역추세를 코어로 삼는 한 회전율의 덫에서 못 벗어난다. 그렇다면 애초에 회전율이 낮은 신호를 코어로 세워야 한다. 가치 점수가 보조로서 수익을 보탰다면, 그걸 보조가 아니라 주인공으로 올렸을 때는 또 다른 그림이 나올지 모른다. 느리게 변하는 가치나 품질, 애널리스트의 시각 변화 같은 신호를 중심에 두고, 거기에 오늘 찾은 vwap 갭 같은 직교 양념을 더하는 알파. 다음 세션은 그 방향을 파볼 생각이다. 물론 친구가 넘겨주기로 한 전략을 바로 검증하는 빠른 길도 여전히 열려 있다.
벽을 넘진 못했지만, 벽이 무엇으로 만들어졌는지는 알아냈다. 그게 0.96이 내게 준 것이다.
기술 메모 (부록)
산문에 다 못 담은 디테일을 남긴다. 기술적인 독자를 위한 부분이다.
새 최고 후보 (앵커 0.95를 갱신, 여전히 Fitness 게이트 1.0 미달이라 제출 불가):
trade_when(ts_rank(ts_std_dev(returns, 22), 252) > 0.55,
rank(-ts_sum(returns, 5)) + 0.3 * rank(-ts_mean(close / vwap - 1, 22)),
-1)
- 설정: USA / TOP3000 / delay 1 / decay 2 / neutralization INDUSTRY / truncation 0.01
- 결과: Sharpe 1.36, Fitness 0.96, turnover 0.246, returns 0.124
- 구조: 검증된 역추세 앵커
rank(-ts_sum(returns, 5))에 vwap 갭 직교 신호를 소량(가중치 0.2 ~ 0.3) 더한 것
조합 실험 기록 (4라운드, 15회 시뮬레이션):
- 1라운드 (직교 6종, 가중치 0.5): vwap 갭 0.95(회전율 감소), 거래량 급증 0.84, 거래량 추세 0.81, 장기 모멘텀/저변동성/변동폭 0.76. vwap 갭만 비용 없이 직교.
- 2라운드 (vwap 갭 가중치 곡선): 0.2 → 0.96, 0.3 → 0.96, 0.5 → 0.95, 0.75 → 0.92, 1.0 → 0.89. 낮은 가중치에 평평한 봉우리(과적합 아님), 가중치 증가에 단조 감소.
- 3라운드 (스택): vwap 갭 0.3 + 거래량 급증 0.3 → 0.93, + 거래량 추세 0.3 → 0.89. 둘째 신호는 회전율만 추가.
- 4라운드 (펀더멘털 틸트, 데이터 항목 조회로 실명 확인): 가치 점수 0.3 → 0.86, 종합 점수 0.3 → 0.56(모멘텀 성분이 역추세와 충돌), vwap 갭 0.2 + 가치 점수 0.3 → Sharpe 1.39(세션 최고) / Fitness 0.95(회전율 0.263으로 상승).
핵심 구조: Fitness = Sharpe x sqrt(returns / max(turnover, 0.125)). 이 단기 역추세 앵커에서는 샤프를 올리는 신호가 회전율도 올리고, 회전율을 깎는 신호가 샤프도 깎는다. 두 레버가 1.0 직전에서 상쇄되어 0.96이 정직한 한계. 1.0 돌파의 정공법은 회전율이 본래 낮은 신호(펀더멘털, 애널리스트)를 보조가 아니라 코어로 쓰는 새 알파를 설계하는 것.
도구 추가: 기존 채굴기 위에 조합 모듈을 얹었다. 앵커 고정 + 직교 신호 라이브러리(가격거래량 6종 + 펀더멘털 4종) + rank/zscore 블렌드 + 다중 신호 스택 + 거래 게이트 래핑. 단독 진단, 가중치 스윕, 조합 형태 전환, 스택 모드를 옵션으로 지원.