12. 트레이딩 에이전트 설계 — 상태·행동·보상과 백테스트
백테스트에서 좋은 결과를 내는 건 쉽다 — 그 결과를 못 믿게 만드는 것들을 없애는 게 일이다
이 장에서 처음 나오는 말6개
미래 정보 누출Look-ahead Bias- 그 시점에 알 수 없던 정보가 상태에 들어가는 것. 백테스트를 통째로 거짓으로 만든다.
생존 편향Survivorship Bias- 지금 살아남은 종목만으로 과거를 시험하는 것. 상장폐지된 종목이 빠져 성적이 부풀려진다.
워크포워드Walk-forward- 학습 → 그 다음 기간에서 검증 → 창을 밀며 반복. 시계열의 표준 검증 절차.
퍼지·엠바고Purge · Embargo- 학습과 검증 구간 사이를 일부러 비워 정보가 새는 것을 막는 기법.
최대 낙폭MDD · Maximum Drawdown- 고점 대비 최대 하락폭. 운용에서 수익률보다 먼저 보는 숫자다.
샤프 지수Sharpe Ratio- 무위험 수익을 뺀 초과수익을 변동성으로 나눈 값. 위험 대비 성과의 대표 척도.
상태 — 무엇을 보여 줄 것인가
섹션 제목: “상태 — 무엇을 보여 줄 것인가”특징 자체는 기존 퀀트와 다르지 않다. 강화학습에서 달라지는 것은 “내 상태”가 반드시 들어가야 한다는 점이다.
| 묶음 | 예 | 주의 |
|---|---|---|
| 가격 파생 | 여러 기간 수익률, 이동평균 이격, 변동성 | 가격 원값을 그대로 넣지 않는다 |
| 거래 활동 | 거래량 변화, 호가 스프레드, 호가 불균형 | 미시구조 전략의 핵심 |
| 레짐 | 변동성 국면, 금리·지수 상태 | 비정상성 대응 (11장) |
| 내 상태 | 보유 비중 · 미실현 손익 · 남은 시간 · 남은 수량 | 빠뜨리면 안 된다 (2장) |
| 시간 | 장중 시각(개장·마감 근처), 요일 | 절대 날짜는 넣지 않는다 |
새기 쉬운 자리들
섹션 제목: “새기 쉬운 자리들”| 누출 경로 | 어떻게 생기나 | 막는 법 |
|---|---|---|
| 전체 기간 정규화 | 위 함정 1 | 확장·이동 창으로 |
| 지표 계산의 중심 이동 | 중심 이동평균, 미래를 보는 필터 | 후행(causal) 지표만 |
| 재무·공시 데이터 | 실제 공표 시점이 아니라 기준일로 붙임 | 공표 시점 기준 정렬 |
| 수정주가 | 지금 기준의 소급 수정 값 | 그 시점의 정보로 |
| 종목 유니버스 | 지금 상장된 종목만 | 시점별 유니버스 재구성 |
| 하이퍼파라미터 선택 | 검증 구간을 보고 골랐다 | 선택용 구간을 따로 (10장) |
마지막 것이 가장 교묘하다. 코드에는 누출이 없는데, 사람이 검증 구간을 보고 설정을 골랐기 때문에 결과가 낙관적이 된다.
행동 — 목표 비중이 낫다
섹션 제목: “행동 — 목표 비중이 낫다”| 설계 | 성격 | 판단 |
|---|---|---|
| 매수 / 관망 / 매도 (이산 3) | 단순, 학습이 쉽다 | 시작점으로 좋다. 다만 “얼마나” 를 못 쓴다 |
목표 비중 [−1, 1] (연속) | 포지션 크기까지 결정 | 권장 비용 계산이 자연스럽다 |
| 주문 수량·가격 직접 | 표현력이 최대 | 학습이 어렵다. 체결 로직과 얽힌다 |
| 다종목 비중 벡터 | 포트폴리오 배분 | 제약(합=1, 한도)을 마스킹으로 건다 |
행동은 여기서 끝내고 실제 주문 실행은 별도 로직에 맡긴다(2장의 “행동을 한 층 올린다”). 체결 자체를 최적화하는 것은 13장의 다른 문제다.
보상 — 수익률만 주면 안 되는 이유
섹션 제목: “보상 — 수익률만 주면 안 되는 이유”r_t = (자산가치_t − 자산가치_{t−1}) / 자산가치_{t−1} ← 이것만 주면이 보상의 최적해는 기대 수익이 조금이라도 양수인 방향으로 최대한 크게 베팅하는 것이다. 파산이 보상에 안 들어 있기 때문이다.
실무에서 쓰는 항들이다.
| 항 | 형태 | 왜 |
|---|---|---|
| 손익 | 자산가치 변화 | 기본 |
| 거래 비용 | −(수수료 + 세금 + 슬리피지) × 거래량 | 없으면 초단타로 수수료를 태운다 |
| 위험 벌점 | −λ · (수익률 분산) 또는 하방 변동성 | 레버리지 폭주를 막는다 |
| 낙폭 벌점 | 고점 대비 하락에 벌점 | 운용 현실에 맞춘다 |
| 재고·보유 비용 | −c · abs(포지션) | 마켓메이킹·헤징에서 필수 |
| 한도 위반 | 벌점보다 마스킹 | 확실하다 (8장) |
환경 구현 — 체결 가정이 결과를 만든다
섹션 제목: “환경 구현 — 체결 가정이 결과를 만든다”백테스트 결과의 상당 부분은 알고리즘이 아니라 환경 코드의 가정에서 나온다.
| 가정 | 낙관적 (흔한 실수) | 현실적 |
|---|---|---|
| 체결 시점 | 그 봉의 종가에 체결 | 다음 봉 시가, 또는 지연을 명시 |
| 체결 가격 | 중간가 | 스프레드를 넘어간 가격 + 슬리피지 |
| 체결 수량 | 항상 전량 | 거래량 대비 상한 (예: 그 봉 거래량의 일부) |
| 수수료·세금 | 무시 | 실제 요율 (매도세 포함) |
| 공매도 | 항상 가능 | 대차 가능 여부·비용 |
| 지연 | 없음 | 신호 → 주문 → 체결의 지연을 넣는다 |
def step(self, action): target = float(np.clip(action[0], -1, 1)) # 목표 비중 trade = target - self.position # 바꿔야 하는 양 price = self.data["open"][self.t + 1] # 다음 봉 시가에 체결 slip = self.slippage_bps * 1e-4 * np.sign(trade) # 방향에 불리하게 fill = price * (1 + slip) traded_notional = abs(trade) * self.equity explicit_cost = traded_notional * (self.fee + self.tax) # 슬리피지는 fill에 이미 반영 ...슬리피지를 fill 가격에 반영했으므로 비용 항에는 수수료·세금만 넣는다. 같은 슬리피지를
체결가와 비용에 모두 넣으면 두 번 차감하는 버그가 된다.
검증 — 백테스트를 믿을 수 있게 만들기
섹션 제목: “검증 — 백테스트를 믿을 수 있게 만들기”-
시간 분할부터 한다.
무작위 K-겹 교차검증은 시계열에서 금지다. 미래로 학습하고 과거로 시험하게 된다.
-
워크포워드로 민다.
[ 학습 2015-2019 ][검증 2020][ 학습 2016-2020 ][검증 2021][ 학습 2017-2021 ][검증 2022]각 검증 구간의 성적을 이어 붙인 것이 보고할 성과다.
-
퍼지와 엠바고를 넣는다.
라벨·특징이 여러 날에 걸쳐 있으면 학습 구간 끝과 검증 시작 사이가 샌다. 사이를 며칠 비운다.
-
시드를 여러 개 돌린다.
RL은 시드마다 다른 정책이 나온다. 시드별 성과 분포를 보고한다 (10장).
-
기준선과 비교한다.
매수 후 보유, 동일비중, 기존 규칙 전략, 그리고 지도학습 예측 + 단순 규칙. 마지막 것을 못 이기면 RL을 쓸 이유가 없다.
-
비용을 두 배로 올려 다시 본다.
-
페이퍼 트레이딩으로 시간을 보낸다.
실시간 데이터·지연·주문 흐름이 붙는다. 백테스트와 다른 곳을 찾는 것이 목적이다.
-
소액으로 나간다.
언제 RL이 예측 모델을 이기나
섹션 제목: “언제 RL이 예측 모델을 이기나”11장에서 “소액 개인 매매면 예측 문제”라고 했다. 그렇다면 RL이 값을 하는 지점은 어디인가.
| RL이 이기는 상황 | 왜 |
|---|---|
| 거래 비용이 결정에 크게 영향 | “바꾸는 것 자체가 비용”을 다기간으로 최적화해야 한다 |
| 포지션 크기·재고 관리가 핵심 | 예측은 방향만 준다. 크기는 다기간 문제다 |
| 제약이 얽힘 (한도·회전율·리스크) | 예측 + 사후 규칙으로는 최적이 안 나온다 |
| 실행이 여러 스텝에 걸침 | 대량 주문 분할 (13장) |
| 재고를 들고 있는 것이 위험 | 마켓메이킹·헤징 |
공통점은 “무엇을 살까”가 아니라 “얼마나·어떻게·언제 바꿀까” 라는 것이다. 방향 예측은 지도학습에 맡기고, RL은 그 위에서 크기와 실행을 맡는 하이브리드가 현실적인 구조다.
설계 점검표
섹션 제목: “설계 점검표”| 확인 | 어디서 |
|---|---|
| 상태에 내 포지션·현금·남은 시간이 있는가 | 2장 |
| 정규화가 그 시점까지의 정보만 쓰는가 | 위 함정 1 |
| 유니버스가 시점별로 재구성되는가 (생존 편향) | 위 표 |
| 행동이 목표 비중인가, 그래서 비용이 정의되는가 | 위 |
| 보상에 거래 비용과 위험 항이 있는가 | 8장 |
| 한도가 마스킹으로 걸려 있는가 | 8장 |
| 체결이 다음 봉·슬리피지·수량 상한을 반영하는가 | 위 |
| 검증이 워크포워드 + 퍼지인가 | 위 |
| 시드 여러 개의 분포를 보는가 | 10장 |
| 지도학습 + 규칙 기준선을 이기는가 | 위 |
| 비용을 2배로 해도 남는가 | 위 |
참고 자료
섹션 제목: “참고 자료”- The Probability of Backtest Overfitting — 반복 탐색과 백테스트 선택 편향
- Advances in Financial Machine Learning: Purged K-Fold Cross-Validation — 퍼지·엠바고와 시계열 검증의 배경
- FinRL Documentation — 금융 RL 환경과 학습·검증 파이프라인의 공개 구현
12장 요약
섹션 제목: “12장 요약”- 상태에는 시장 특징뿐 아니라 내 포지션·현금·남은 시간이 반드시 들어간다
- 전체 기간 통계로 정규화하는 것이 가장 흔하고 치명적인 미래 정보 누출이다
- 누출은 코드뿐 아니라 사람이 검증 구간을 보고 설정을 고르는 데서도 생긴다
- 행동은 목표 비중이 좋다 — 직전 비중과의 차이가 곧 거래량이라 비용이 자연히 정의된다
- 보상에 거래 비용과 위험 항이 없으면 초단타로 수수료를 태우거나 레버리지를 폭주시킨다
- 샤프는 스텝 보상이 아니라 평가 지표로 쓴다
- 백테스트 성과의 상당 부분은 체결 가정에서 나온다. 슬리피지를 중복 차감하지 않고, 비용을 2~3배로 올려도 남는지 본다
- 검증은 워크포워드 + 퍼지·엠바고 + 시드 분포 + 기준선 비교 + 페이퍼 트레이딩 순서다
- 시험 횟수를 세어 두고 최종 성과를 할인해 해석한다. 최종 구간은 한 번만 쓰고 봉인한다
- RL이 값을 하는 자리는 “무엇을 살까”가 아니라 “얼마나·어떻게 바꿀까” 다