실험 0004 · 국채선물

계수 두 개가 피처 일흔 개를 따라잡는다

KAIST 석사논문(김종재, 2024)의 장마감 동시호가 수익률 예측 모델을 그대로 구현해 재현하고, 실험 0003 과 같은 조건에서 시험했다.

채택 3년 국채선물 근월 · 시험 2019~2026 · n=1,491 승률 60.30% · 누적 +661틱 런 1회

논문의 모델은 설명변수 한 개짜리 단순회귀다 — r_auc = α + β·r_final. 그것을 그대로 구현해 논문 표본에서 재현하고(성과 지표가 왜도·첨도까지 맞는다), 0003 과 같은 조건으로 시험했다. 시험 2019~2026 승률 0.6030·누적 +661틱으로 기준선 넷을 모두 넘었고, 무엇보다 0003 이 7그룹 150피처에서 고른 ExtraTrees 후보 (0.6030 · +663틱)와 점수가 같다. 짝지은 검정은 정확히 반으로 갈린다 (b=150 : c=150 · p=1.0).

무엇을 물었나

사용자 지시(2026-09-17): “논문에 나온 동시호가 수익률 예측 모델을 그대로 구현해서 학습하고 실험 0003 과 같은 조건으로 테스트해서 실험 목록에 추가해라.” 그래서 물음이 둘이다 — A. 우리 구현이 논문과 같은가, B. 그 모델이 우리 대회 조건에서 쓸 만한가.

원문: 김종재, 「대한민국 국채 선물 시장 장마감 동시호가 수익률 예측 / Predicting Closing Call Auction Return in the Korean Treasury Bond Futures Market」, 한국과학기술원 금융공학프로그램 석사학위논문, 2024.2, 24+iii쪽, 지도교수 류혁선. hdl.handle.net/10203/321898. KOASAS 항목에는 첨부 파일이 없다(Download 0) — 공개된 것은 서지와 초록뿐이고, 본문은 사용자가 KAIST 도서관에서 받은 인쇄본 PDF 를 literature/kim2024_closing_call_auction.pdf 로 두고 읽었다. 텍스트 레이어가 없는 스캔본이라 페이지 이미지를 읽어 옮겼다.

논문이 정의한 모델

기호는 논문 Table 1 그대로다. 하루를 30분으로 잘라 r_1(09:00→09:30) … r_12(14:30→15:00) 를 두고, 정규장 마지막 35분을 r_final(15:00→15:35), 장마감 동시호가 구간을 r_auc(15:35→15:45) 라 부른다. 예측 대상은 r_auc 다.

논문의 두 모델 — src: code/paper_model.py
모델정의학습
윈도우 롤링 회귀§3.1 r_auc,t = α + β·r_final,t + ε_t, 매일 갱신. 표본 밖 평가는 Campbell·Thompson(2008) R²_OS, t 값은 Newey·West(1987)있다
바이너리 시그널§3.2 15:00→15:34:59 가 오르면 15:34:59 에 롱·동시호가에 매도 청산, 내리면 숏 — sign(r_final)없다

컷오프를 둘로 가른다. 논문의 r_final 은 15:35 가격 (P_ref)으로 끝난다. 논문 안에서는 look-ahead 가 아니다 — 15:35 에 들어가 15:45 에 나오는 전략이니까. 그런데 우리 대회는 15:35 전에 제출한다. 그래서 P_ref 는 제출 시점에 없다. 0003 이 0001 의 sign(ŷ−d)(60.05%)를 후보에서 뺀 것과 같은 성격이라 같은 취급을 한다:

  • P — 논문 그대로P(15:35) / P(15:00) − 1 · 대회 제출 불가
  • C — 0003 봉 컷오프P(15:34) / P(15:00) − 1 · 대회 제출 가능

둘을 한 숫자로 섞지 않는다. 표에는 둘 다 싣되 후보는 C 만이다.

A. 재현

논문 표본(2016-08-01 ~ 2023-07-01)·논문 분할로 3선·10선 둘 다 돌려 논문 표와 나란히 놓았다. 우리 1분봉이 2016-12-14 부터라 논문의 앞 넉 달이 없다 (표본 1,599일 vs 논문 1,702일).

바이너리 시그널(논문 Table 5) — 우리 vs 논문. results/20260917_172623_paper/repro_table5.csv
상품 · 기간nSRatio왜도첨도승률(%)
KTB3 전체 · 우리1,599 1.5950.4226.77357.157
KTB3 전체 · 논문1,702 1.6560.4556.78657.30
KTB3 OOS · 우리470 1.8190.3442.42157.341
KTB3 OOS · 논문474 1.7070.3452.41356.99
KTB10 전체 · 우리1,599 1.3430.5777.37755.296
KTB10 전체 · 논문1,702 1.4600.5737.31156.00

KTB3 표본 밖에서 왜도 0.344 vs 0.345 · 첨도 2.421 vs 2.413 이 나온다. 이 정도로 맞는 것은 같은 r_auc 계열을 보고 있다는 뜻이다 — 승률은 정의를 고르면 맞출 수 있지만 첨도는 못 맞춘다.

논문의 “In sample” 은 학습창이 아니라 전체 표본이다

사전등록한 재현 기준 1·2 는 논문의 “In sample statistics” 를 1,228일 학습창으로 읽고 세운 문장이고, 그 읽기로는 둘 다 실패했다(KTB3 학습창 β 4.516 · t 1.865). 그런데 원문 안에 답이 있었다. 논문 Table 9 는 “the application of the regression model to the total dataset that from August 1, 2016, to July 1, 2023” 이라고 적고, 그 마지막 행 (r_auc = α + β·r_final)의 값이 KTB3 8.251 (4.466) 2.310 · KTB10 5.908 (3.062) 1.234 로 Table 2 의 “In sample” 열과 글자 그대로 같다. Table 8 의 “In sample” 패널도 같은 값이다.

재현 판정 두 갈래. 사전등록 문장은 고치지 않았고 두 판정을 metrics.json 에 다 남겼다 (replication.criteria · …_corrected_reading).
기준글자 그대로 (학습창)교정 (전체 표본)
1. β>0 이고 |t|>2 (KTB3·KTB10 둘 다) ✗ KTB3 4.516 (t 1.865) KTB3 8.386 (4.460) · KTB10 5.837 (2.905)
2. r_final 의 R² 가 r_1r_12 전부보다 큼 ✗ KTB3 는 r_3 가 이긴다 둘 다 r_final
3. 바이너리 승률 ±5%p✓ (최대 1.076%p)
→ 판정부분 재현재현 성공

결과를 보고 기준을 옮긴 것이 아니라 원문을 잘못 읽었던 것을 원문 안의 증거로 고친 것이다 — 근거는 Table 9 의 자기 진술이고 우리 숫자와 무관하게 논문 안에서 확인된다. r_final 정의를 달리 읽는 가능성(15:05→15:35 로 정확히 30분)도 재 봤지만 계수가 거의 안 움직여 원인이 아니다(repro_rfinal_variants.csv).

연도별 베타 꺾은선 — 3선과 10선
남는 차이 하나. 표본 밖 β 는 여전히 벌어진다(KTB3 10.828 vs 논문 5.886). 이 그림이 이유의 절반이다 — β 가 해마다 −2.4 에서 13.4 까지 흔들린다. 다만 표본 넉 달 차이만으로 4.5↔8.25 를 다 설명하기엔 부족하고, 봉 간격(논문 5분 / 우리 1분)과 벤더 차이가 남은 후보다 [U].

어떻게 쟀나 — 0003 조건

「같은 조건」의 내용은 0003 의 protocol.mdrun.py 가 정한 것을 그대로 가져왔다: 3선 근월 · note 가드와 0틱 무효일 제외 · 연도 확장창(학습 2017~) · 시험 2019~2026 n=1,491 · 방향 승률과 누적 틱. 기준선 넷·컨셉1·게이트 열·채점·McNemar 는 0003 의 코드를 그대로 호출한다(experiments/0003_contest_model_selection/code/models.py) — 같은 조건이라고 말하려면 같은 코드를 밟아야 한다.

워크포워드 분할 간트와 갱신 주기 비교 — 위는 폴드 여덟 개, 아래는 세 갈래의 학습일수 곡선
계수 두 개도 시험연도를 보지 않고 뽑는다. 위: 판정 갈래의 폴드 여덟 개. 시험연도 Y의 α·β 는 2017년부터 Y−1년 말까지의 날들로만 적합하고(짙은 막대), 채점은 Y년만(주황 막대) 한다. 막대 안 숫자는 그 폴드가 쓴 날 수이고 학습 쪽은 contest_coefs.csvn_train 그대로다. 주황 막대의 합 1,491일이 승률의 분모이며, 0003 과 같은 날 집합이다. 아래: 같은 시험일을 세 가지 갱신 주기로 본 것 — 판정 갈래는 해마다 한 번만 계수를 갱신하고(계단), 논문 §3.1 의 일별 확장창과 길이 1,228일 고정 롤링창은 민감도로만 싣는다. 세 갈래 모두 그날 이전 데이터만 쓴다. 2023년 무렵 초록 점선이 갈라지는 지점이 롤링창이 상한 1,228일에 닿아 옛 날을 버리기 시작하는 자리다.
그림 A · 모델 구조 — 논문 회귀(C 컷오프), 시험 2026 (학습 1,693행) 입력 데이터 3년 국채선물 근월 1분봉 2016-12-20 ~ 2026-09-11 유효일 1,841 · 하루 1행 학습 2017~2025 · 1,693행 0틱 무효일 제외 (대회 규칙) 피처 1개 r_final = P(15:34) / P(15:00) − 1 논문 §3.1 의 유일한 설명변수 논문 정의는 15:35 로 끝나지만 제출 시점에 없어 15:34 로 당겼다 LinearRegression — 논문 Kim(2024) §3.1 · 시험 2026 폴드 모델 1. 선형 결합 z = b + Σ wᵢ·xᵢ (계수 1개) 2. 링크 z → 예상 r_auc, 부호가 방향 출력 r̂_auc (동시호가 수익률) ↓ 부호만 읽는다 상승 / 하락 r_final = 0 인 날은 적응 상수로 채운다 매일 1건 제출 계수 — 세팅과 학습 결과 피처 1개 원공간의 계수 — 표준화 단계가 없다 0 이 아닌 계수 1개 절편 b = -1.717e-05 모든 피처가 학습창 평균일 때의 출발점 평균적인 r_auc 변화 |w| 최대 = 0.0881 가장 센 피처: r_final |w| 중앙값 0.0881 부호 규칙 — 절편이 문턱이 된다
선형 모델의 구조는 분기가 아니라 파이프라인 단계다. 여기서는 그 단계가 하나뿐이다 — 결측 대치도 표준화도 없다(설명변수가 하나라 필요 없다). 이 그림의 빈약함이 결론이다: 이 두 숫자가 0003 의 70피처 ExtraTrees 와 같은 승률 0.6030 을 낸다.
그림 B · 계수 — 설명변수가 하나뿐이다 ← 하락 쪽 상승 쪽 → r_final +0.0881 원공간의 계수 상위 1개 · 절편 b = -1.717e-05 · 전체 1개 중
계수는 표준화하지 않은 원공간이다(변수가 하나라 비교 대상이 없다). 절편 -1.717e-05 가 이 모델의 일 절반이다 — β 와 나누면 1.95bp(≈2틱) 라는 문턱이 되고, 15:00→15:34 가 그보다 더 올라야 롱을 낸다. 동시호가가 평균적으로 내리쪽으로 기운다는 기저율이 이 한 숫자에 들어 있다.

B. 결과

시험 2019~2026 · n=1,491 · 같은 날 집합. results/20260917_172623_paper/contest_table.csv
갈래승률누적 틱적응 상수 대비 McNemar b:cp제출
paper_reg_C 논문 회귀 · 15:00→15:34 0.6030+661 +5.23%p268:1900.0003가능
paper_reg_C_daily 일별 갱신 0.5942+619+4.36%p 260:1950.0027가능
paper_bin_C 논문 바이너리 · 15:00→15:34 0.5936+627+4.29%p 338:2740.0108가능
paper_reg_C_roll1228 1,228일 롤링 0.5922+611+4.16%p 254:1920.0038가능
paper_reg_P 논문 회귀 · 15:00→15:35 0.5889+587+3.82%p 262:2050.0095불가
b_rule20 규칙 20분 모멘텀 0.5875+609+3.69%p 315:2600.0242가능
paper_bin_P 논문 바이너리 · 15:00→15:35 0.5748+485+2.41%p 331:2950.1618불가
e_adaptive 적응 상수(후행 120일 다수) 0.5506+229 가능
c_concept1 0.5399+183−1.07%p 334:3500.5663가능
a_random 0.4950−37−5.57%p 345:4280.0032가능

판정: 채택. paper_reg_C·paper_bin_C 둘 다 기준선 넷을 모두 넘고 적응 상수 대비 McNemar 에서 b>c 다 — 사전등록 문장이 요구한 것이 정확히 이것이다.

누적 틱 곡선 네 갈래
같은 1,491일의 누적 틱. 한 변수 회귀(짙은 선)와 0003 의 70피처 ExtraTrees(초록 점선)가 같은 자리에 도착한다(+661 vs +663틱). 같은 예측을 내는 것이 아니다 — 예측 일치율은 79.9% 이고 300일에서 갈린다.
0003 후보와 나란히 — 같은 1,491일. 이 비교는 보고이지 판정이 아니다.
승률누적 틱vs 0003 McNemar
0003 후보 T0_core/et/none (70피처 ExtraTrees) 0.6030+663
paper_reg_C (피처 1개) 0.6030+661 b=150 : c=150 · p=1.0
paper_bin_C0.5936+627 b=161 : c=175 · p=0.478
b_rule200.5875+609 b=149 : c=172 · p=0.219

갈리는 300일에서 둘 다 정확히 50.0% 다(150:150). 합의하는 1,191일의 승률은 62.9%. 즉 두 모델은 같은 신호를 다른 경로로 잡고, 서로 다른 곳에서는 둘 다 아무것도 모른다. 앙상블 재료가 없다 — 0002 가 H6 를 접은 것과 같은 모양이다.

연도별 승률 막대그래프
여덟 해 전부 50% 위. 다만 2026 이 약하다paper_reg_C 0.5704 가 규칙(0.6197)과 적응 상수(0.5845) 둘 다에 진다(0003 의 ET 는 그해 0.6127 였다). 표본 142일이라 ±4%p 는 잡음 안이지만, 대회가 도는 해가 하필 그 해다.

왜 그런가 — 절편이 절반이다

부호만 쓰는 paper_bin_C 0.5936 에서 회귀 paper_reg_C 0.6030 으로 +0.94%p. 그것을 만든 것은 β 가 아니라 α 다. β>0 인 단순회귀에서 sign(α + β·x)x > −α/β 와 같으므로, 회귀가 배우는 것은 기울기가 아니라 문턱이다.

연도 확장창이 해마다 배운 문턱 — 15:00→15:34 가 이보다 더 올라야 롱. contest_coefs.csv
시험연도2019202020212022 2023202420252026
문턱 (틱)1.061.15 3.012.811.84 1.091.562.05
15:00→15:34 등락 구간별 동시호가 상승 비율 막대그래프
문턱이 0 이 아닌 이유. 15:00→15:34 가 0틱 근처면 동시호가 상승 비율이 46%, +1틱에서도 46% 이고 +2틱을 넘어서야 60% 다. 동시호가는 평균적으로 내리쪽으로 기운다 — 0002·0003 이 “기저율 드리프트” 라 부른 것이고, 논문의 절편이 그것을 흡수한다.

0003 의 ExtraTrees 와 같은 점수가 나오는 이유도 여기 있다. 0003 의 SHAP 에서 상위였던 g1_pos_20m·g1_pos_day 는 결국 “마감 무렵 가격이 당일 범위의 어디에 있나” 이고 g6_baserate_* 는 기저율이다. 모멘텀 × 기저율 이 그 모델이 배운 것의 대부분이었고, 논문의 두 계수가 같은 것을 더 짧게 적는다.

PC 보다 나쁘다. 논문 정의(15:35 까지)의 승률이 대회 컷오프(15:34)보다 낮다(0.5889 vs 0.6030). 마지막 1분의 움직임(d = P_ref − P34)이 동시호가로 되돌아오기 때문이다 — 0001 이 sign(−d) 만으로 54.9% 를 얻었던 그 사실이다. 창을 1분 줄이는 것이 정보를 버리는 게 아니라 반대 부호 성분을 빼는 것이고, 우리 대회 규칙이 우연히 더 나은 컷오프를 강제한다.

한계

  1. P 갈래는 대회에서 낼 수 없다. r_final 이 15:35 가격으로 끝나는데 제출은 그 전이다. 표에 실었지만 후보로 올리지 않는다(0003 의 d1_nonlive 와 같은 취급).
  2. 2026 이 약하다. paper_reg_C 2026 0.5704 가 규칙·적응 상수 둘 다에 진다. 대회 라이브가 2026-09-28~ 이라 이 한 칸이 가장 불편한 숫자다.
  3. 레짐 분해를 안 했다(지표 계약 경고 1건). 0003 이 게이트 7종을 재서 미지지(H9)로 끝냈기 때문에 같은 축을 다시 열지 않았다.
  4. 재현의 남은 구멍은 표본 밖 β [U] — 표본 넉 달 차이로는 다 설명이 안 된다.
  5. Success(%) 정의가 논문에 없다. 두 정의를 다 냈더니 Table 5 는 “움직인 날만”, Table 3 은 “전체 날” 과 맞는다. 바이너리는 움직임 0 인 날 포지션을 안 잡고 회귀는 언제나 잡기 때문이면 논문 안에서 일관되지만, 확인할 길이 없어 둘 다 싣는다.
  6. 진짜 블라인드 구간은 없다. 2026-09-11 이전을 전부 봤다. 대회 라이브가 유일한 최종 OOS 다.
  7. 캐파시티 비해당 — 방향 채점 게임이라 체결·수량 축이 없다.

산출물

  • 사전등록protocol.md
  • 분석·판정analysis.md
  • 논문 모델 정본code/paper_model.py
  • 시각 격자 캐시code/build_grid.py
  • results/20260917_172623_paper/
  • 배포용 적합results/…/model_candidate.joblib
  • 원문 사본literature/kim2024_closing_call_auction.pdf