전체 글로 돌아가기

백테스트 데이터 누수 방지: PIT 데이터와 생존편향 점검법

공시 기준기간·공개시각·수집시각을 분리하고 수정 공시, 현재 구성종목, 상장폐지 누락을 as-of replay로 점검하는 방법입니다.

백테스트 데이터 누수 방지: PIT 데이터와 생존편향 점검법 대표 이미지

백테스트에서 재무제표의 기준일과 정보 공개일을 같은 날로 처리하면 당시에는 알 수 없던 실적이 신호에 들어갑니다. 현재 남아 있는 종목과 최신 수정본만 쓰는 경우에도 과거 결과가 실제보다 좋아질 수 있어요.

해결 기준은 단순합니다. 판단시각보다 늦게 공개·수집됐거나 거래에 쓸 수 없었던 값은 제외하고, 공시 버전과 당시 유니버스를 보존한 뒤 과거 시점 재생으로 결과를 다시 확인해야 합니다. 이 구조가 Point-in-Time, 즉 PIT 데이터의 핵심이에요.

PIT 데이터는 기간보다 ‘언제 알았는가’를 함께 저장해요

회계기간 말일은 그 실적을 시장이 안 날이 아닙니다. 사건이 발생한 event time과 시스템이 처리한 processing time은 다른 시간축이며, 도착 지연에 따라 처리 결과도 달라질 수 있어요.C1 금융 데이터에서는 여기에 공개시각, 실제 수집시각, 첫 거래 가능 시각까지 분리해야 합니다.

  • period_end: 어떤 기간의 실적인가
  • publish_time: 외부에 언제 처음 공개됐는가
  • first_seen_time: 내 시스템이 언제 처음 받았는가
  • first_tradable_time: 전략 규칙상 언제 주문에 쓸 수 있었는가
  • known_to: 수정본이 나오기 전까지 언제 유효했는가

따라서 일봉 전략의 사용 가능 시각은 보수적으로 publish_time, first_seen_time, first_tradable_time 중 가장 늦은 시각으로 잡을 수 있습니다. 이는 공식 표준 공식이 아니라 누수를 막기 위한 운영 규칙이며, 데이터 공급 지연과 주문 규칙을 문서화해야 해요.

출처: Apache Flink, Timely Stream Processing, 발행일 미표기, 확인일 2026-08-03

수정 공시를 최신 값으로 덮어쓰면 과거 판단이 바뀌어요

SEC의 Financial Statement Data Sets는 제출자가 낸 XBRL을 as filed 형태로 제공하며, 원 공시를 대신하지 않는다고 명시합니다.C2 이 데이터에는 이전 제출의 수정본이 포함될 수 있고 접수 시각과 이후 수정 여부를 확인할 필드도 있어요.C3

예를 들어 최초 매출이 100, 한 달 뒤 수정값이 96이었다면 두 행을 남겨야 합니다.

100 | known_from=최초 공개시각 | known_to=수정 공개시각
 96 | known_from=수정 공개시각 | known_to=NULL

현재 값 96으로 과거 행을 업데이트하면 최초 공시 뒤 수정 전 기간의 백테스트도 96을 보게 됩니다. fiscal_yearperiod_end만으로 가격 데이터와 결합하지 말고, 판단시각이 known_fromknown_to 사이에 있는 버전을 선택해야 해요.

출처: SEC, Financial Statement Data Sets, 발행일 미표기, 확인일 2026-08-03

현재 구성종목은 과거 투자 가능 종목이 아니에요

오늘의 지수 구성종목이나 현재 상장종목을 10년 전으로 가져가면 파산·합병·상장폐지된 기업이 사라집니다. 성과에 따라 표본의 생존 여부가 달라질 때 생존편향은 성과 지속성이 있는 것처럼 보이는 잘못된 추론도 만들 수 있습니다.C4

가격열이 끝났다고 포지션을 자동 삭제해서도 안 됩니다. 마지막 거래 뒤의 합병대금, 청산가치, 상장폐지 손실 같은 최종 현금흐름을 확인해야 해요. 정확한 PIT 유니버스에는 종목의 편입·편출 유효기간, 그 사실을 안 시점, 제거 사유가 함께 있어야 합니다.

출처: Brown·Goetzmann·Ibbotson·Ross, Survivorship Bias in Performance Studies, 1992, 확인일 2026-08-03

As-of replay로 누수를 다섯 단계에서 찾아요

다음 절차는 수익률을 높이는 방법이 아니라 결과가 당시 정보로 재현되는지 확인하는 감사 순서입니다.

  1. 판단시각을 하나 고정해요. 신호 계산과 주문 시각을 분리합니다.
  2. 이후 공개된 행을 제거해요. known_from > decision_time인 재무·기업행동·구성종목 기록을 제외합니다.
  3. 당시 버전만 남겨요. 수정본이 나오기 전에는 최초 제출값을 사용합니다.
  4. 소멸 종목의 마지막 현금흐름을 확인해요. 행 종료를 정상 매도로 바꾸지 않습니다.
  5. 입력 ID와 결과를 비교해요. 최신 데이터 실행과 당시 버전 실행의 차이가 크면 어느 입력에서 벌어졌는지 추적합니다.

추가로 first_seen_time < publish_time, order_time < signal_time, known_from < publish_time 같은 모순을 자동 검사하면 시간대 오류와 잘못된 조인을 빨리 찾을 수 있어요.

데이터 계보는 결과에서 원문까지 돌아가는 경로예요

PIT 조건이 맞아도 어떤 원문과 코드로 팩터가 만들어졌는지 모르면 오류를 재현하기 어렵습니다. W3C PROV-O는 데이터·산출물인 Entity, 변환 과정인 Activity, 책임 주체인 Agent와 그 관계를 표현하는 모델을 제공합니다.C5

최소한 다음을 함께 저장하세요.

source_document_id → raw_record_id → normalized_record_id
→ feature_id → code_commit → parameter_hash → run_id

최종 팩터 값에서 원 공시, 사용한 버전, 계산 코드와 실행 시각까지 역추적할 수 있어야 수정 공시나 코드 변경의 영향을 구분할 수 있습니다.

출처: W3C, PROV-O: The PROV Ontology, 2013-04-30, 확인일 2026-08-03

이 신호가 보이면 결과 해석을 멈추고 다시 확인해요

  • 회계기간 말일과 사용 가능일이 항상 같습니다.
  • 현재 데이터베이스에서 과거 값이 한 버전만 나옵니다.
  • 과거 유니버스의 종목 수와 구성원이 비정상적으로 일정합니다.
  • 가격열이 끝난 종목의 제거 사유와 마지막 현금흐름이 없습니다.
  • 신호를 다음 거래일로 한 칸만 늦춰도 결과가 전부 사라집니다.
  • 최종 팩터에서 원 공시와 계산 코드를 찾을 수 없습니다.

이 중 하나가 발견됐다고 누수가 확정되는 것은 아닙니다. 다만 원인을 설명하기 전까지 성과 차이를 전략의 우월성으로 해석하면 안 돼요. 퀀트투자의 일반적인 오류 구조는 퀀트투자 뜻과 백테스트의 네 가지 오류에서 별도로 확인할 수 있습니다.

면책 및 정보 이용 안내

이 글은 공개된 공시와 관계기관 자료를 바탕으로 작성한 일반 정보이며, 독자의 재무상황·투자목표·위험수용도를 고려한 개인 맞춤형 투자·법률·세무 자문이나 특정 금융상품 또는 종목의 매수·매도 권유가 아닙니다. 투자에는 원금 손실 가능성이 있으며 과거의 성과가 미래의 결과를 보장하지 않습니다. 투자 결정 전 최신 공시, 상품설명서, 금융회사와 관계기관의 공식 자료를 직접 확인하고 필요한 경우 자격을 갖춘 전문가와 상담하세요. 글의 기준일 이후 정보가 변경될 수 있습니다.