곱셈으로 강해지다, 그리고 점수판의 진실 (월드퀀트 브레인 4편)
퀀트 트레이딩 플랫폼 WorldQuant BRAIN에서 “제출 가능한 알파”를 쌓아 점수를 올리는 공개 기록. 3편에서 현금흐름 대비 주가의 평균회귀(pcf)로 첫 제출 알파를 만들고 게이트를 넘었다. 이번 편에서는 두 번째 알파를 찾고, 점수판이 실제로 어떻게 굴러가는지를 직접 확인했다. 그리고 “닮은 알파는 하나만”이라는 규칙의 진짜 무게를 배웠다.
0. 한 줄 요약
검증된 신호(pcf)에 직교하는 약한 신호를 더하지 않고 곱했더니 Sharpe가 1.57에서 1.91로 뛰었다. “싸면서 동시에 실적 전망이 상향 중”인 종목의 교집합이 두 번째 제출 알파가 됐다. 그리고 점수판을 열어 보니, 내가 들었던 “하루에 한 개만 점수에 반영된다”는 속설은 틀렸고, 진짜 규칙은 따로 있었다. 첫 점수는 브론즈 1,854점이었다.
1. 출발점: 통과는 했는데 점수가 안 보였다
3편에서 pcf를 제출했다. 게이트 8개를 다 넘은 알파였다. 그런데 막상 제출하고 나니 점수판에 뭐가 어떻게 찍히는지가 깜깜했다. 알파 하나하나에는 등급(grade)이 붙는데, 그게 대회 점수와 같은 건지 다른 건지부터 불분명했다. 점수 규칙을 모르면 “어떤 알파를 언제 내야 유리한가”를 판단할 수 없다. 그래서 이번 세션의 목표는 둘이었다. 하나는 pcf와 닮지 않은 두 번째 알파를 찾는 것, 다른 하나는 점수판의 작동 원리를 실제 데이터로 확인하는 것.
먼저 알파 사냥부터 갔다. 3편 끝에서 17명의 에이전트가 만들어 둔 우선순위 큐 34개가 있었다. 그중 강해 보이는 후보들을 동시에 시뮬할 수는 없다. 이 계정은 한 번에 딱 하나의 시뮬만 돌릴 수 있어서, 큐를 한 줄로 세워 직렬로 훑어야 했다.
2. 큐를 직렬로 훑다: 혼자서는 다 약했다
큐의 후보들을 차례로 돌렸다. 신호축별로 결과를 적어 둔다. 어떤 데이터를 어떻게 받아 어떤 신호로 바꿨는지가 핵심이다.
- 애널리스트 추정치 변화 (
analyst4): 애널리스트들의 합의 EPS 예상치를 가져와, 그 변화량과 추정치들의 흩어짐(분산)으로 나눴다. “전망이 상향 중이고 의견도 일치하는” 종목을 잡으려는 신호다. 단독 Sharpe 0.4. 약했다. - 뉴스 감성 (
news18): Ravenpack의 종합 감성 점수를 며칠 평균 내어 표류를 노렸다. Sharpe 0.02. 거의 0이었다. - 소셜 감성과 관심도 (
socialmedia12): 버즈가 식는 종목을 역추세로 잡으려 했다. 음수로 나오기도 했다. - 기업 관계 lead-lag (
pv13): 고객사 평균 수익률이 먼저 오르면 공급사가 뒤따른다는 정보 확산을 노렸다. 부호가 거꾸로 나와 손실권이었다.
큐 전체에서 단독으로 게이트를 넘긴 건 하나도 없었다. 유일하게 강했던 건 3편에서 이미 만난 옵션의 콜-풋 내재변동성 스프레드(Sharpe 1.83)였지만, 그건 작은 유니버스에서 무너지는 집중 과적합이라 보류한 카드였다. 직교하는 신호들은 죄다 혼자서는 약했다. 이게 이번 사냥의 벽이었다. 닮지 않은 신호는 많은데, 닮지 않은 신호는 약했다.
3. 돌파: 더하지 말고 곱하라
2편에서 배운 게 있었다. 약한 신호를 검증된 신호에 등가중으로 더하면 분산이 아니라 물타기가 된다는 것. 강한 신호가 약한 신호에 끌려 내려갔다. 그래서 이번엔 더하지 않고 곱해 보기로 했다.
더하기와 곱하기는 의미가 다르다. 더하기는 “둘 중 하나라도 강하면 베팅”이라 약한 쪽이 잡음을 보탠다. 곱하기는 “둘 다 같은 방향일 때만 베팅”이라 교집합을 만든다. 두 신호를 각각 종목 순위(rank)로 바꾼 뒤 곱하면, 양쪽에서 동시에 높은 종목만 살아남고 한쪽만 높은 종목은 눌린다.
곱할 짝으로 고른 건 애널리스트 EPS 추정치의 변화였다. pcf는 “현금흐름 대비 주가가 자기 역사보다 싸졌나”를 본다. 거기에 “애널리스트들이 실적 전망을 상향 조정 중인가”를 곱했다.
rank( -ts_zscore(cap / cashflow_op, 63) )
× rank( ts_delta( ts_backfill(anl4_fs_detail_estimates_basic_af_v4_nd_eps_mean, 120), 66 ) )
anl4_fs_detail_estimates_basic_af_v4_nd_eps_mean이 애널리스트 합의 EPS 예상치다. 분기 단위로 띄엄띄엄 갱신되는 데이터라 빈 날이 많아서 ts_backfill로 마지막 값을 채워 넣고, ts_delta로 66거래일(약 한 분기) 전 대비 변화량을 봤다. 이게 양수면 전망이 상향 중이라는 뜻이다.
이 곱셈이 노리는 건 밸류 함정 필터다. 싸 보이는 주식이 사실은 망해 가는 중이라 싼 경우가 있다. 그런 종목은 애널리스트들이 전망을 깎고 있다. 반대로 “싸졌는데 전망은 오히려 상향 중”인 종목은 진짜 저평가일 확률이 높다. 싼 것과 좋아지는 것의 교집합. 곱셈은 그 교집합을 정확히 집어냈다.
결과는 Sharpe 1.91, Fitness 1.6. pcf 단독(1.57)보다 확연히 높았다. 더했을 땐 물탔는데 곱하니 강해졌다. 검증된 베이스에 직교 신호를 곱한다는 전략이 그대로 적중했다.
4. 두 번째 문을 넘다
서버의 8개 점검을 다시 받았다. 전부 통과였다. 턴오버는 11.3%로 낮았고(펀더멘털 신호라 원래 느리게 변한다), 작은 유니버스 Sharpe도 1.61로 견고했다. 큰 시장에서만 우연히 맞는 알파가 아니었다.
가장 중요한 문은 자기상관이었다. 두 번째 알파는 첫 번째와 너무 닮으면 안 된다(기준 0.7 미만). pcf와 실제로 얼마나 닮았는지 재 보니 0.61. 같은 cashflow 재료를 베이스로 쓰는데도, 곱한 애널리스트 신호가 충분히 달라서 전체가 pcf에서 멀어졌다. 0.7 밑이라 통과. 두 번째 제출 알파(cau_pcfleg)가 확정됐다.
rank(-ts_zscore(cap / cashflow_op, 63)) × rank(ts_delta(ts_backfill(...eps_mean, 120), 66))
USA / TOP3000 / 지연 1일 / decay 4 / 업종 중립화 / 비중상한 2%
→ Sharpe 1.91, Fitness 1.6, 턴오버 11.3%, 작은 유니버스 1.61, pcf와 자기상관 0.61, 8/8 통과
5. 점수판을 열다: 속설은 틀렸다
이제 두 번째 목표. 점수가 실제로 어떻게 매겨지는지였다. 알파의 등급이 곧 점수일 거라고 막연히 생각했는데, 직접 점수 조회를 해 보니 그게 아니었다. 대회 점수판은 따로 있었다.
확인한 규칙은 이렇다.
- 점수는 누적이고 깎이지 않는다. 한 번 쌓으면 남는다. 레벨은 누적 점수로 정해진다. 1,000점 위가 브론즈, 5,000점 위가 실버, 10,000점 위가 골드다. 골드를 넘으면 컨설턴트 초대 자격이 생긴다.
- 하루 점수에는 상한이 있다. 하루에 약 2,000점까지만 들어오고, 미국 동부 새벽 3시에 갱신된다. 그 위로 아무리 좋은 알파를 몰아 내도 버려진다.
- 점수는 알파 단위가 아니라 날짜 단위다. 내가 들었던 “하루에 한 개만 점수에 반영된다”는 속설은 틀렸다. 그날 낸 알파들이 함께 그날의 점수를 만든다. 개수가 많을수록(수량) 그리고 그날 알파들의 평균 품질이 높을수록 점수가 오른다.
이 “평균 품질”이라는 게 묘하다. 약한 알파를 좋은 날에 같이 내면 그날 평균을 깎아 손해다. 그렇다고 강한 알파 여러 개를 하루에 몰면 2,000점 상한에 잘려 버려진다. 그래서 결론은 강한 알파는 날짜를 나눠서, 약한 알파는 좋은 날에 섞지 말고다. 점수 자체는 미래 데이터(아웃샘플)를 기다리지 않고, 제출 다음 갱신 때 곧바로 붙는다는 것도 확인했다.
품질을 끌어올리는 레버도 분명해졌다. 작은 유니버스에서 강할수록, 자기상관이 낮을수록, Fitness가 높을수록 점수가 오른다. 특히 자기상관은 0.7이라는 통과 기준에서만 끝나는 게 아니라, 낮을수록 점수에 계속 유리하게 작용했다. 상위 풀(Power Pool)은 아예 자기상관 0.5 이하를 요구했다. 닮지 않은 알파를 모으는 일이 통과의 문제만이 아니라 점수의 문제이기도 했던 것이다.
첫 점수가 찍혔다. 브론즈, 1,854점. pcf 하나로 거의 하루 상한을 채운 셈이다. 두 번째 알파의 점수는 다음 날 갱신에 붙을 예정이었다.
6. 닮은 알파는 하나만: cau 가족의 함정
두 번째 알파를 낸 기세로 세 번째를 노렸다. 곱셈이 통했으니 비슷한 곱셈을 하나 더 만들면 되겠다 싶었다. EV/EBITDA 회귀에 같은 애널리스트 신호를 곱한 변형(cau_rev132)을 만들었다. 자기상관을 재 보니 0.42, 넉넉히 통과로 보였다.
그런데 함정이 있었다. 그 0.42는 두 번째 알파를 제출하기 전에 잰 값이었다. 두 번째 알파를 정식으로 제출하고 나서 다시 재 보니, 세 번째 후보의 자기상관이 0.83으로 폭증해 있었다. 통과 기준을 한참 넘은 탈락이었다.
이유는 분명했다. 두 번째와 세 번째가 같은 애널리스트 변화 신호(revision leg)를 곱셈 짝으로 공유하고 있었다. 베이스(pcf냐 EV냐)만 다를 뿐 곱한 쪽이 같으니, 둘은 사실상 사촌이었다. 두 번째를 제출하는 순간, 그와 닮은 세 번째가 막혀 버린 것이다.
여기서 큰 그림이 보였다. pcf, 그리고 거기에 애널리스트 변화를 곱한 cau 계열은 서로 너무 닮아서, 첫 번째와 두 번째로 이미 포화됐다. 이 가족에서 또 만들면 자기상관에 막힌다. 세 번째 알파는 이 가족 바깥에서, 가격도 애널리스트 변화도 아닌 진짜 다른 신호에서 찾아야 한다. 그게 다음 편의 숙제가 됐다.
7. 이번 편에서 배운 것
- 더하기와 곱하기는 다른 무기다. 약한 직교 신호를 더하면 물타기, 곱하면 교집합 강화다. 검증된 베이스에 곱하는 쪽이 Sharpe를 올렸다.
- 점수는 날짜 단위다. 알파 하나가 아니라 그날 낸 알파들의 수량과 평균 품질이 점수를 만든다. 강한 알파는 날짜를 쪼개고, 약한 알파로 좋은 날을 희석하지 않는다.
- 자기상관은 통과만의 문제가 아니다. 낮을수록 점수에도 계속 유리하다. 닮지 않은 알파를 모으는 게 곧 점수를 쌓는 길이다.
- 닮은 알파는 서로를 막는다. 같은 곱셈 짝을 공유하면 베이스가 달라도 사촌이다. 하나를 제출하면 나머지가 닫힌다. 그래서 한 가족에서 하나만 내고, 다음은 진짜 다른 가족에서 찾아야 한다.
- 상관은 제출 후에 다시 재라. 제출 전에 통과로 보였던 후보가 제출 직후 막힐 수 있다. 기준이 “내가 이미 낸 알파들” 대비라 움직이는 표적이다.
다음 편에서는 가격도 애널리스트 변화도 쓰지 않는, pcf 가족 바깥의 세 번째 신호를 사냥한다. 닮지 않으면서 강하고 견고한 알파를 새로 발굴하는, 가장 어려운 회차다.
기술 메모 (부록)
- 제출 알파 2호 (cau_pcfleg):
rank(-ts_zscore(cap / cashflow_op, 63)) * rank(ts_delta(ts_backfill(anl4_fs_detail_estimates_basic_af_v4_nd_eps_mean, 120), 66)), USA/TOP3000/delay1/decay4/INDUSTRY/truncation0.02. Sharpe 1.91, Fitness 1.6, turnover 0.113, sub-universe 1.61, pcf와 self-corr 0.61. 서버 8개 체크 전부 PASS. grade GOOD. - 곱셈 vs 덧셈: 덧셈(
a + w*b)은 OR에 가까워 약신호가 잡음을 보탠다(2편에서 fitness 천장 0.96). 곱셈(rank(a) * rank(b))은 AND라 양쪽 동시 강세 종목만 남는다. pcf(1.57) × revision = 1.91. - revision leg:
ts_delta(ts_backfill(eps_mean, 120), 66). 분기 갱신이라 결측이 많아 ts_backfill(120)로 마지막 값을 끌고 오고, 66거래일 변화로 “상향 조정 중”을 측정. 턴오버가 낮아 곱해도 전체 턴오버를 11.3%로 유지. - 점수(Challenge) 규칙: 조회는
GET /competitions/challenge의 leaderboard{rank, level, score, alphas}. 일일 캡 약 2,000점, 미국 동부 3AM 갱신, 누적이며 깎이지 않음. per-day(그날 알파들의 수량 + 평균 품질), per-alpha 아님. 품질 레버 = 작은 universe↑ / self-corr↓ / Fitness↑ / decay1>decay0. Power Pool은 self-corr ≤ 0.5. 점수는 아웃샘플을 기다리지 않고 제출 다음 갱신에 인샘플 기준으로 붙음. 레벨 = Bronze>1,000 / Silver>5,000 / Gold>10,000(누적), Gold+10,000 → Consultant 초대 자격. - 현황: BRONZE, 1,854점, rank 35,958 (pcf 1개 반영 시점). 2호는 다음 갱신에 가산 예정.
- 3호 cau_rev132 (탈락):
rank(-ts_zscore(enterprise_value/ebitda, 63)) * rank(<2호와 동일 revision leg>). Sharpe 1.33, Fitness 1.1로 단독 지표는 좋았으나, 2호 제출 후 self-corr가 0.42에서 0.83으로 폭증해 FAIL. 같은 revision leg 공유가 원인. pcf/cau 계열은 1, 2호로 포화. - 자기상관의 이동 표적성: self-corr는 “내가 제출한 알파” 대비라, 새 알파를 제출할 때마다 기준집합이 바뀐다. 제출 전 통과로 보여도 제출 직후 재측정 필수.