Thu 08-06 · 오늘 0건 · 통산 1,372호
falette
스크랩 쪽지 로그인
업비트 자동매매 봇 만들기
 

③ 업비트 자동매매 봇 만들기 — 손절선을 세 번 끌어올렸는데, 마지막 계단은 4개월에 한 번뿐이었다

봇이 이익을 지키려고 손절선을 끌어올린 건 넉 달 동안 71번 있었다. 그중에서 한 단계를 더 올려 진짜 수익 구간까지 방어선을 세운 건 딱 한 번이다. 그리고 그 한 번마저, 수수료 앞에서는 이긴 거래가 아니었다.

4개월 매도
374건
왕복 수수료
−0.10%p
실제 승률
45.7%
3단 발동
1건

②편에서 이긴 거래의 평균 수익이 +0.72%에 그친다고 썼다. 그 숫자를 다시 보자. 그건 사실 이미 수수료가 빠진 숫자였다. 이번 편은 그 계산식부터 다시 세운다.

그리고 그 계산식 위에, 이 봇의 매도 로직이 어떻게 손절선을 계단처럼 끌어올리는지를 놓는다. 3단짜리 계단인데, 맨 위 칸을 밟은 기록은 4개월 374건 중 단 하나다. 그 하나가 왜 하나뿐이었는지, 그리고 그 하나가 실제로는 무엇이었는지를 끝까지 따라간다.

시리즈 지도
1부 · 설계
  1. ① 113일이 남긴 숫자와 이 시리즈의 질문
  2. ② 매수 로직 해부 — 다섯 개의 관문
  3. ③ 매도 로직 해부 — 손절·익절·트레일링의 3층 구조 — 지금 글
  4. ④ 시장 국면을 셋으로 나눈다는 것
2부 · 운영
  1. ⑤ NAS에서 24시간 — 부팅 스크립트가 조용히 실패하던 이유
  2. ⑥ 워치독과 중복 프로세스
  3. ⑦ 웹에서 봇에게 명령 보내기
3부 · 부검
  1. ⑧ 6월 −53% ① 용의자 지우기
  2. ⑨ 6월 −53% ② 진범
  3. ⑩ 패치 이후 — 승률이 두 배 올랐는데 손익비는 반토막
4부 · 정리
  1. ⑪ 계측 없는 봇은 고칠 수 없다
  2. ⑫ 다음 버전 — 무엇을 버릴 것인가

수수료부터 — 어디서도 못 피하는 0.1%p

이 봇의 매도 코드는 수익률을 계산할 때 가격만 보지 않는다. 매수 체결가에는 0.05%를 더하고, 매도 체결가에서는 0.05%를 뺀 다음에야 진짜 수익률을 계산한다. 업비트 원화마켓 수수료를 왕복으로 미리 반영해두는 방식이다.

순수익률 = (매도가 × 0.9995 − 매수가 × 1.0005) / (매수가 × 1.0005) × 100

이 배수를 풀어보면 결과는 거래 규모와 거의 무관하게 일정한 값으로 수렴한다. 어떤 거래든 가격만으로 계산한 수익률에서 약 0.10%p가 고정적으로 깎여 나간다는 뜻이다. 그리고 이 봇의 DB에 남는 "수익률"은 전부 이미 이 0.10%p가 빠진 뒤의 숫자다. ②편에서 인용한 +0.72%도, −0.95%도 전부 그렇다.

그럼 수수료를 빼기 전, 즉 가격만으로 이겼는지 졌는지를 다시 계산하면 어떻게 달라질까. 374건 전체를 역산해봤다.

구분승률평균 수익평균 손실4개월 합계
가격만(수수료 전)46.5%+0.80%−0.87%−34.63%p
실제 기록(수수료 후)45.7%+0.71%−0.96%−71.98%p

승률은 거의 안 바뀐다. 46.5%에서 45.7%로, 0.8%p 차이다. 그런데 374건의 수익률(%)을 단순 합산한 값은 −34.63%p에서 −71.98%p로, 거의 두 배가 된다. 왕복 0.10%p가 별거 아닌 것처럼 보여도, 374번 누적되면 절반 가까운 낙폭이 수수료 하나에서 나온다는 뜻이다.

승패가 뒤집힌 거래 374건 중 3건은 가격만 보면 이긴 거래였는데, 수수료 때문에 최종 기록은 손실로 남았다. 셋 다 낙폭이 크지 않은 근소한 승부였다 — 그리고 이 셋 중 하나가, 바로 다음 절에서 다룰 "3단이 발동한 유일한 거래"다.
사진: Maxim Hopman (Unsplash). 캔들 하나하나의 색이 승패를 가르는 것 같지만, 이 봇에서는 그 뒤에 붙는 0.10%p가 더 자주 승패를 갈랐다.

손절선은 한 자리에 머물지 않는다

계단식 3층 구조

이 봇의 매도 코드에서 가장 먼저 확인하는 건 진입가 기준으로 고정된 손절선이다. 시장 국면(하락장·중립·상승장)마다 그 폭이 다르게 설정돼 있고, 여기 걸리면 무조건 정리한다. 이게 1단이다.

그런데 이 손절선은 거래가 진행되는 동안 가만히 있지 않는다. 포지션이 어느 정도 수익 구간에 들어서면, 코드는 두 번에 걸쳐 손절선 자체를 위로 끌어올린다.

1단
기본 손절 — 진입가 기준 고정

국면별로 폭만 다를 뿐, 위치는 거래 내내 움직이지 않는다. 이 선에 닿으면 다른 조건과 무관하게 즉시 정리한다. 4개월간 43건이 이 선에서 청산됐다.

2단
본절 방어 — 최소한 잃지는 않게

포지션이 고점 대비 일정 비율 이상 오른 적이 있고, 그 뒤 작게라도 되돌림이 오면, 손절선을 진입가 근처까지 끌어올린다. 오른 걸 다 지키진 못해도 원금은 지키자는 단계다. 4개월간 71건 — 세 단계 중 가장 자주 발동했다.

3단
수익 보호 — 벌어둔 걸 지킨다

고점 대비 훨씬 큰 폭으로 올랐던 적이 있고, 그 이익의 상당 부분을 지킨 채로 되돌림이 왔을 때만 발동한다. 손절선이 진입가보다 , 즉 플러스 구간으로 올라가는 유일한 단계다. 4개월간 1건.

진입가 보유 시간 · 고점 대비 수익 진행 → 1단 · 기본 손절 43건 발동 2단 · 본절 방어 71건 발동 3단 · 수익 보호 1건 발동 되돌림이 오면 여기서 청산
손절선(초록 선)은 거래가 진행되며 세 번 중 최대 두 번 위로 밟아 올라간다. 계단이 높아질수록 그 계단에 도달하는 거래 수는 급격히 줄어든다 — 43건, 71건이 아니라 43건 → 71건 → 1건 순으로, 정확히는 "그 단계에서 청산된" 거래 수다.

트레일링(고점 대비 일정폭 하락 시 청산, 4개월 112건)은 이 계단과는 별개의 안전장치다. 수익 구간 진입 여부와 무관하게, 고점에서 얼마나 되돌렸는지만 본다. 계단식 손절은 "수익을 얼마나 지킬 것인가"의 문제고, 트레일링은 "고점에서 얼마나 빠지면 무조건 나올 것인가"의 문제다. 겹치는 것 같지만 다른 질문이다.

3단이 4개월간 단 한 번만 발동한 이유

3단이 발동하려면 조건이 세 개 동시에 맞아야 한다. 고점 대비 상당히 큰 폭으로 올랐던 적이 있어야 하고, 그 시점에 여전히 뚜렷한 수익 구간에 있어야 하며, 거기서 다시 일정 폭 이상 되돌려야 한다.

문제는 이 봇의 이긴 거래 평균 수익이 +0.72%라는 데 있다(②편). 3단이 요구하는 고점 상승폭은 이 평균 승리 폭보다 훨씬 크다. 즉 3단은 애초에 "이 봇이 평소에 내는 수익의 몇 배를 벌었을 때만" 작동하도록 설계된 계단이다. 그런데 이 봇은 애초에 그만큼 크게 이기는 경우가 거의 없다. 계단 자체는 정상 작동했다. 다만 그 계단에 오를 만한 거래가 4개월간 딱 한 번밖에 없었을 뿐이다.

4개월간의 그 한 건 5월 28일 오전, 비트코인을 매수했다. 이후 어느 시점에 고점 대비 큰 폭으로 올랐고, 3단 조건이 실제로 걸렸다. 3일 가까이 들고 있다가 5월 31일 자정 무렵, 되돌림이 조건을 채우면서 3단이 발동해 정리됐다.

그런데 이 거래를 실제 체결가로 다시 계산해보면 결과가 이상하다. 매수 109,330,000원, 매도 109,422,000원. 가격만 보면 +0.08%, 아주 작지만 분명한 승리다.

그런데 이 봇의 로그에 남은 수익률은 −0.02%다. 앞서 본 그 0.10%p가 여기서도 정확히 작동했다. 고점 대비 크게 올랐다가 힘겹게 지켜낸 이익의 대부분을 반납하고, 마지막 남은 0.08%마저 수수료가 가져갔다.

계단의 끝에서 확인한 것 이 봇이 넉 달 동안 손절선을 두 단계나 끌어올려가며 수익을 지키려 한 유일한 순간은, 사실 진 거래로 기록됐다. 3단은 "큰 이익을 지키기 위한 마지막 방어선"으로 설계됐지만, 실제로 그 방어선이 작동한 유일한 사례는 애초에 지킬 만한 이익이 남아 있지 않았다. 방어선은 정상 작동했다. 방어할 대상이 이미 사라진 뒤였을 뿐이다.

그래서 이 계단은 필요했나

여기서 솔직해질 필요가 있다. 2단(본절 방어)은 71건이나 발동했으니 실제로 손실을 줄이는 데 기여했을 가능성이 높다. 하지만 3단은 존재 자체가 통계적으로 거의 의미가 없다. 4개월에 1건이면, 이 계단을 아예 만들지 않았어도 결과는 거의 같았을 것이다.

더 근본적인 문제는 순서가 거꾸로였다는 점이다. 3단의 발동 조건(고점 상승폭)을 먼저 정하고, 그게 이 봇의 평균 승리 폭과 어떤 관계인지는 나중에도 확인하지 않았다. 손절선을 얼마나 계단식으로 올릴지보다, 이 봇이 평소에 얼마나 버는지를 먼저 알았어야 순서가 맞았다. ②편에서 매수 조건을 다룰 때 나온 결론과 정확히 같은 자리로 돌아온다 — 구조를 만들기 전에, 그 구조가 실제로 다룰 숫자의 크기부터 쟀어야 했다.

다음 편

④편에서는 이 모든 손절선·익절선·트레일링 폭을 다르게 만드는 기준, 시장 국면을 셋으로 나누는 로직을 본다. 하락장·중립·상승장이라는 세 개의 이름이 실제로는 무엇을 기준으로 갈리는지, 그리고 그 구분이 매매 결과를 정말로 바꿔놓았는지에 대해.

개인 운영 기록이며 투자 권유가 아닙니다. 자동매매는 원금 손실 위험이 있고, 이 봇은 실제로 손실을 냈습니다. 전략 파라미터 일부는 구체적 수치 대신 상대적 표현으로 적었습니다.

거래소 API 키를 코드나 설정 파일에 평문으로 저장하지 마세요. ⑤편에서 함께 다룹니다.

댓글 0
첫 번째 댓글을 남겨보세요
댓글 작성
LOGIN