#01 HMA 트레이딩 봇 — 자동매매 봇 개발기, v1 베이스라인을 기록하다

2024년 초부터 만들기 시작한 자동매매 봇이 어느덧 1년 넘게 돌아가고 있다. 처음에는 “파이썬으로 바이낸스 API 찍어보자” 수준이었는데, 하다 보니 전략 설계, 백테스트 엔진, 리스크 관리, 서버 운영까지 풀스택(?) 프로젝트가 되어버렸다.

이제 좀 크게 전략을 개선해보려고 하는데, 그 전에 지금 상태를 베이스라인으로 박제해두려고 한다. 나중에 “이때보다 나아졌나?”를 비교하려면 기준점이 있어야 하니까.


어떤 전략인가

한 줄로 요약하면 “HMA(Hull Moving Average) 기울기로 추세를 잡고, 적응형 트레일링으로 수익을 보호하는 전략”이다.

바이낸스 USDT-M 선물에서 ETHUSDT를 30분봉 기준으로 양방향(Long/Short) 매매한다. 철학은 단순하다 — 진입은 까다롭게, 손절은 빠르게, 수익 구간에서는 최대한 오래 버텨라.

진입은 이렇게

HMA의 기울기(slope)를 ATR로 정규화하고, 그 기울기의 변화율(acceleration)을 본다. 쉽게 말하면 “추세가 시작되면서 가속이 붙는 순간”을 잡는 거다. MACD 히스토그램이랑 비슷한 구조인데, HMA 특유의 빠른 반응성 덕분에 일반 이동평균보다 진입이 빠르다.

다만 노이즈 구간에서 헛신호가 많이 나오기 때문에, slope의 변동성을 기반으로 한 dynamic deadzone을 깔아서 “방향성이 약한 구간”은 아예 무시한다.

청산은 여러 겹으로

진입보다 중요한 게 청산이라는 걸 뼈저리게 느꼈다. 지금 청산 체계는 이렇게 겹겹이 쌓여있다:

  1. SL (손절) — ATR 기반 고정 손절. 서버사이드 Stop Market으로 걸어둬서 봇이 죽어도 작동한다.
  2. Early Stop — 진입 직후 역행이 심하고 유리한 움직임이 거의 없으면 빨리 탈출.
  3. MFE_R Stop — 몇 봉이 지나도 수익 방향으로 진전이 없으면 “이거 잘못 탄 거다” 하고 나온다.
  4. 적응형 트레일링 스탑 — 이게 핵심이다. 아래에서 자세히.

적응형 트레일링 — 수익의 핵심

고정 배수 트레일링은 한계가 명확하다. 추세가 강할 때는 너무 빨리 털리고, 추세가 약해질 때는 수익을 다 반납한다. 그래서 추세 강도와 현재 수익 크기에 따라 트레일링 폭을 동적으로 조절하는 방식을 만들었다.

  • 추세가 강하면 → 넓게 잡아서 추세를 타게 놔둔다
  • 수익이 커지면 → 점점 타이트하게 조여서 수익을 보호한다
  • 수익이 일정 수준 이상 나면 → 30분봉 대기 없이 1분 단위로 트레일링을 업데이트한다

이 “조건부 1분 트레일링”이 꽤 효과적이었다. 30분봉만으로는 수익을 많이 반납하는 경우가 있었는데, 수익 구간에서 1분 단위로 전환하면서 훨씬 세밀하게 보호할 수 있게 됐다.


백테스트 결과 (2024.01 ~ 2026.03, 약 27개월)

자, 숫자를 까보자.

전체 요약

지표
총 수익률+700.1% (레버리지 10x 기준)
최대 낙폭 (MDD)-40.17%
샤프 비율1.91 (10x) / 0.61 (1x 등가)
총 트레이드1,990건 (Long 1,011 / Short 979)
승률42.3%
평균 수익 : 평균 손실1.74 : 1
Profit Factor1.28
최대 연속 손실10회

승률 42%라고 하면 “그거 지는 거 아냐?” 싶을 수 있는데, 추세추종 전략은 원래 이렇다. 이길 때 평균적으로 질 때보다 1.74배를 벌기 때문에 전체적으로 수익이 난다. 야구로 치면 타율은 낮은데 장타율이 높은 타자랄까.

청산 사유별로 보면

청산 사유횟수승률비고
Trailing Stop847건97.9%수익의 거의 전부
SL Hit779건0.0%손실의 주요 원인
MFE_R Stop233건1.3%저품질 진입 필터
Reverse79건12.7%반대 방향 전환
Early Stop52건0.0%초반 조기 탈출

이 표가 전략의 성격을 가장 잘 보여준다. Trailing Stop 승률 97.9% — 트레일링까지 살아남은 트레이드는 거의 다 수익이라는 뜻이다. 반면 손절에 걸리는 건 어쩔 수 없는 비용. Early Stop과 MFE_R Stop은 “이건 아닌 것 같다” 싶은 트레이드를 SL까지 가기 전에 미리 잘라내는 안전장치 역할을 한다.

진입 품질은?

진입의 질을 MFE_R(최대 유리 이동)과 MAE_R(최대 불리 이동)로 분류해봤다:

  • 완벽한 진입 (MFE_R ≥ 1, MAE_R < 0.5): 552건 — 진입 후 순조롭게 수익 방향으로 간 케이스
  • 흔들렸지만 성공 (MFE_R ≥ 1, MAE_R ≥ 0.5): 326건 — 한번 흔들렸지만 결국 수익
  • 최악의 진입 (MFE_R < 0.5, MAE_R ≥ 0.5): 691건 (43.9%) — 역행만 하다가 끝난 케이스

최악의 진입이 44%나 된다는 건, 진입 시점의 필터링이 아직 부족하다는 뜻이다. 여기가 가장 큰 개선 포인트.

월별 흐름

27개월 중 22개월 수익, 5개월 손실. 손실월의 최대폭은 초기 자산 대비 약 -20% 수준이었다. 추세가 잘 나오는 달에는 확실하게 먹고, 횡보장에서는 조금씩 까이는 전형적인 추세추종 패턴이다.


놓친 수익 — 아쉬운 131건

백테스트를 돌리면서 가장 아쉬웠던 건, MFE_R > 1R까지 갔다가 결국 손실로 끝난 트레이드가 131건(6.6%)이나 된다는 거다. 한번은 수익 구간까지 갔는데 결국 손절당한 거지.

  • SL Hit 중 13.6%가 이 케이스
  • Reverse 중 22.8%가 이 케이스
  • Trailing Stop은 0.8%로 양호

트레일링 자체는 잘 작동하는데, 트레일링에 진입하기 전 단계에서 수익을 지키지 못하는 경우가 있다는 뜻이다. BE(Break-Even) Stop이나 TP1 부분청산을 활성화하면 이 부분이 개선될 수 있을 것 같다.


지금까지 삽질하면서 배운 것들

1년 넘게 개발하면서 겪은 시행착오를 좀 적어보면:

  • 레짐 필터는 빼는 게 나았다 — 처음에는 시장 상태(추세/횡보/급등락)를 분류해서 진입을 필터링했는데, 오히려 좋은 진입을 놓치는 경우가 많았다. 과적합의 냄새가 나서 걷어냈다.
  • TOD(시간대) 필터도 제거 — 특정 시간대에만 매매하는 필터를 넣었다가, 백테스트에서는 좋아 보이는데 라이브에서 효과가 없어서 뺐다.
  • Journal 시스템 → Google Sheets — 자체 매매일지 시스템을 만들었다가, 결국 Google Sheets가 훨씬 실용적이라 갈아탔다.
  • 고정 트레일링 → 적응형 — 이게 가장 큰 전환점이었다. 고정 배수로는 추세장과 횡보장을 동시에 커버할 수 없다.
  • 30분 트레일링 → 조건부 1분 — 수익 구간에서 30분을 기다리는 동안 수익이 녹는 게 아까워서 도입. 체감 효과가 꽤 크다.

다음에 할 것들

이 베이스라인을 기준으로 앞으로 테스트해볼 것들:

  1. 진입 필터 강화 — 최악의 진입 44%를 줄이는 게 최우선. 볼륨, 변동성, 추가 확인 조건 등을 실험해볼 예정.
  2. TP1 부분청산 테스트 — 수익 초기에 일부 물량을 확보하면 MDD가 개선될지 확인.
  3. 트레일링 파라미터 미세 조정 — MFE_R > 1R인데 손실로 끝나는 131건을 줄이기.
  4. MDD 개선 — 현재 40%인 MDD를 30% 이하로 낮추는 게 목표.

각 개선안은 브랜치에서 구현하고, 이 베이스라인과 백테스트 A/B 비교 후 채택/폐기를 결정할 계획이다.


이 글은 HMA 트레이딩 봇 v1의 베이스라인 기록이다. 이후 개선 작업은 이 데이터를 기준으로 비교된다.

기록일: 2026-03-25

댓글 남기기