콘텐츠로 건너뛰기
Reddit

워밍업 기간 문제 — 백테스트가 거짓말하는 이유 😕

r/Daytrading 조회 40
원문 보기 →
💡

백테스트는 워밍업 기간 때문에 실전과 다른 신호를 잡아내며, 그 결과 수익률 차이가 발생할 수 있다. 실제 트레이딩은 지표가 유효해진 이후의 '새로운' 신호만 보고 거래하므로 과거 교차를 소급 적용하지 않는다. 백테스트를 할 때는 워밍업 로직(초기 기간 처리)을 명시적으로 반영하거나 지표 초기화 방식을 점검하자.

같은 SMA 크로스오버 전략을 파이썬/pandas 백테스트와 실거래 시뮬레이터에 그대로 돌려봤더니 결과가 완전히 달라졌습니다.

파이썬 백테스트: 3번 트레이드, 수익률 13.23%

실거래 시뮬레이터: 2번 트레이드, 수익률 16.77%

버그 찾느라 한참 헤맸는데 문제는 버그가 아니었습니다.

문제는 워밍업 기간(warmup period)이었습니다.

예를 들어 50일 SMA는 계산하려면 50일치 데이터가 필요합니다. 많은 pandas 기반 백테스트는 이렇게 처리합니다: SMA를 계산한 뒤 처음 49개 행을 dropna()로 제거합니다.

이 방법은 지표 계산에는 문제가 없지만 미묘한 문제가 생깁니다. 백테스트가 과거 교차를 마치 실시간으로 봤던 것처럼 처리해 버린다는 점입니다.

실제로 봇을 배포하면 보통 다음처럼 동작합니다: 1) SMA 계산을 위해 과거 50일 데이터를 불러오고, 2) 그 이후에 발생하는 '새로운' 교차만 관찰해서, 3) 봇이 가동된 이후에 발생한 시그널에만 거래합니다. 즉, 지난주에 일어난 교차에 대해 거래할 수는 없습니다.

제가 파이썬 백테스트에서 잡아낸 트레이드 중 실거래 시뮬레이터가 건너뛴 트레이드 예시는 다음과 같습니다:

2025-06-10: BUY @ $202.67

2025-06-16: SELL @ $198.42

손실: -$208.25

이 교차는 워밍업 기간 동안 발생했기 때문에 실제로는 봇이 관찰 중이었을 때 나온 신호가 아닙니다. 파이썬은 역사적 데이터에서 그 교차를 보고 거래했지만, 라이브 시스템은 그 신호를 놓쳤습니다.

이번 경우 놓친 거래가 손실이라 실거래 시뮬레이터가 더 좋은 성과를 냈지만, 반대의 경우(승리한 거래를 놓침)도 충분히 발생할 수 있습니다.

요약: pandas 기반 백테스트는 완벽한 선견지명을 가정합니다. 실전은 그렇지 않습니다. 백테스트와 실거래 결과가 몇 퍼센트 차이가 난다면 워밍업 기간 문제를 먼저 의심해 보세요.

다른 분들은 어떻게 처리하시나요? 백테스트에 명시적 워밍업 로직을 넣으시나요, 아니면 차이를 수용하시나요?


🧐 배경 설명 및 요약

1) 왜 이 글이 나왔나: 작성자는 동일한 규칙·동일한 데이터로 백테스트와 라이브 시뮬레이터를 돌렸는데 거래 수와 수익률이 달라져서 원인을 찾던 중 '워밍업 기간' 차이를 발견했습니다. 많은 백테스트 프레임워크가 지표 계산 후 초기 NA 값을 제거해 과거 발생한 신호들을 마치 실시간에 발생한 것처럼 포함시키는 경우가 있어 이런 혼란이 생깁니다.

2) 작성자가 실제로 걱정하는 점: 작성자는 백테스트가 실전보다 낙관적(또는 단지 다른) 결과를 보여주는 이유를 알고 싶어 합니다. 핵심 질문은 "백테스트에서 발생한 신호들이 실제로 봇이 가동된 이후의 신호인지 어떻게 보장하느냐"입니다. 특히 워밍업 기간 동안 나온 교차를 백테스트가 거래에 포함시키면 실전 성과와 괴리가 발생합니다.

3) 어려운 개념을 아주 간단히 설명:

- 워밍업 기간(warmup period): 어떤 지표(예: 50일 SMA)는 유효한 값을 계산하려면 일정 기간의 과거 데이터가 필요합니다. 그 기간 동안 지표값은 완전하지 않으므로 실전에서는 그 기간이 지나야 '관찰'을 시작합니다.

- pandas의 dropna() 문제: 많은 백테스트 코드는 지표를 계산한 뒤 초기 NA(값 없음) 행들을 삭제합니다. 그러면 백테스트는 삭제된 구간의 과거 데이터를 이미 알고 있는 상태에서 나머지 시계열을 처리하게 되어, 실제 봇이 가동된 시점 이후의 신호만 보도록 설정하지 않으면 '선견지명(lookahead)' 오류와 유사한 상황이 됩니다.

- 실무에서의 대응 방법(간단 요약): 백테스트에 명시적 워밍업 로직을 넣어 "봇 가동 이후"의 신호만 거래에 포함시키거나, 지표 함수를 직접 구현해 초기 n개 바(bar)에 대해 NA를 유지하도록 하고 백테스트에서 해당 구간 동안의 거래를 금지하는 방식으로 처리합니다. EMA 같은 재귀적 지표는 초기값 처리(그레디언트 초기화 등)가 더 까다로우므로 특히 주의해야 합니다.

이 글은 백테스트와 라이브 간의 작은 차이(몇 퍼센트)가 실제로는 구현 세부사항에서 비롯될 수 있음을 상기시켜 주기 위해 쓰였습니다. 실전과 백테스트를 최대한 일치시키려면 초기 지표값 처리·워밍업 논리를 명확히 설계하세요.

💬 원문 댓글 (2)

u/Ok_Can_5882 ▲ 1
좋은 관찰입니다! 이런 식의 함정은 더 많습니다. 예를 들어 표준 EMA는 각 값이 이전 값에 부분적으로 의존하는(재귀적인) 성격 때문에 정확한 룩백(lookback)을 정의하기 어렵습니다.

제가 개인적으로 하는 방법은 사용하는 지표를 직접 구현하는 것입니다. 그래서 SMA 함수, 유한 룩백(finite lookback) EMA 함수 등을 만들어 사용합니다. 이렇게 하면 지표 수준에서 워밍업 기간을 처리하게 되어 문제를 피할 수 있습니다. 예컨대 제 SMA 함수는 룩백보다 작은 첫 n개 바에서는 NA를 반환합니다.

노력이 좀 들지만 그렇게 하면 모든 것이 원하는 방식으로 정확히 동작합니다. 그런 차이를 그대로 받아들이지 않는 것이 좋습니다 :)
원문 보기
Good observation! There are lots more potential pitfalls like this! For example, if you're using a standard EMA, the lookback is undefined because each value is based partially on the previous one (recursive).

What I personally do to get around this type of problem is to code all the indicators I use myself. So I have an SMA function, a finite lookback EMA function, etc. And then I'm essentially adding the warmup period to the indicator so it takes care of itself. For example my SMA function just returns NAs in the first n<lookback bars.

Takes a bit of work, but then everything works exactly how you want it! Definitely don't accept those differences :)
u/UseUseAccount ▲ 1
또한 백테스트에는 한계가 있습니다. 예를 들어 트럼프가 트윗 한마디로 가격이 미친 듯이 움직일 때 과거 데이터로 그런 사건을 정확히 재현하는 백테스트는 없습니다. 특정 트윗 때문에 가격이 급등락한 이유를 전형적인 지표 백테스트만으로 찾아내기도 어렵습니다. 백테스트의 한계를 받아들여야 할 때가 있습니다.
원문 보기
Also there is limits to back test how you going to back to something when price moves like crazy when Trump tweets something. There's no back test in 10 years that's going to be able to emulate something like that. Also it's going to be hard to find the reasons why the price moved like crazy on certain tweets that Trump made just doing back tests on typical indicators. You just have to accept the limits of back testing

댓글 (0)

로그인하고 댓글을 작성하세요.

아직 댓글이 없습니다.