0. 하루에 담긴 세 가지

2026년 5월 28일 저녁은 이 봇의 역사에서 가장 밀도 높은 몇 시간이다. 저녁 7시부터 밤 8시 반까지 버전이 여섯 개 넘게 쌓였다.

앞 글에서는 그중 “숫자를 다루는 자리를 지운” 버전들을 봤다. 이 글은 나머지 셋이다. 성격이 완전히 다르다.

2026-05-28 저녁 · 이 글이 다루는 세 버전
19:07  v1.09  668줄  +216/-190  눌림목 대기 로직 신설
                              이 시대 최대 규모의 수술
19:24  v1.11  704줄  +0/-0       코드 동일. 번호만 상승
                              git 없던 시절의 세이브 포인트
20:22  v1.15  775줄  +52/-21   알림 토큰 원클릭 발급
                              매매 로직은 한 줄도 안 건드림
--------------------------------------------------
전략이 태어나고 · 겁을 먹고 · 화면에서 벗어나려 한 하루

1. 눌림목이 태어난 날

1-1. 이 시대 최대의 수술

이틀 만에 돌아온 버전이다. 668줄, +216/-190줄. 이 시대에서 손꼽는 대수술이다. 코드의 3분의 1이 바뀌었다. 그리고 이 봇 역사에서 가장 중요한 한 줄이 여기서 들어간다.

빗썸 스마트 자동 매매 봇 v1.9 — 감시 엔진 로그
🚀 V1.0 엔진 로그인 성공!
⚙️ 24시간 감시 엔진 가동
   진입 대기 폭 -0.5% · 익절 +2.0% · 손절 -4.5%
⏳ [눌림목 대기] 현재 4,120원 ➔ 4,099원까지 하락 대기
   … 대기 … 대기 … 목표가 미달, 진입 보류
🤖 [알고리즘 진입] 50,000원 매수 시도
💥 [매수] 50,000원
🎯 1차 목표 도달. 50% 익절
🔥 [Trailing] 잔여 청산

1-2. target_entry_price

target_entry_price라는 변수가 처음 생겼다. 그리고 사용자가 조절하는 대기 폭, 기본값 -0.5%.

동작의 차이는 이렇다.

진입 방식의 전환
[ 이전 ] 조건 성립 → 즉시 시장가 매수
   조건 판정 시점의 가격에 그대로 산다
   → 신호가 늦으면 고점에 산다

[ v1.09 ] 조건 성립 → 목표가 산출 → 대기 target = 현재가 × (1 - 0.005) 현재가가 target 이하로 내려오면 매수 → 안 내려오면 안 산다 ————————————————– “진입 조건"과 “진입 가격"이 분리된 순간

이게 왜 큰 변화인지는 조금 뜯어봐야 한다. 이전 봇에서 조건 판정과 주문은 하나의 사건이었다. 조건이 서면 곧바로 산다. 그러니까 봇이 판단하는 건 “살까 말까” 하나뿐이었다.

v1.09부터는 두 개다. 살까 말까, 그리고 얼마에 살까. 조건이 서도 가격이 안 맞으면 안 산다. 신호와 체결 사이에 조건이 하나 더 끼어든 것이다.

1-3. 버튼 문구가 바뀌었다

재밌는 흔적이 하나 있다. UI 버튼 문구까지 같이 바뀌었다.

버튼 문구의 변화
- [ 감시 엔진 시동 ]
+ [ 감시 엔진 시동 (눌림목 대기 가능) ]
--------------------------------------------------
이 시점에 이미 스스로 "눌림목"이라는 단어를 쓰고 있었다
이름이 붙었다는 건 개념이 정리됐다는 뜻이다

기능에 이름이 붙는 순간이 있다. 그전까지는 “조금 기다렸다 사는 로직"이었을 텐데, 이 버전에서 눌림목이라는 단어가 나온다. 이름이 붙으면 그 뒤로는 그 이름으로 사고하게 된다. 지금 봇의 전략을 한 줄로 부르면 “과매도 눌림목 반등"이다. 그 단어가 여기서 처음 코드에 들어왔다.

1-4. 첫날 메모가 여기서 코드가 됐다

이 버전의 로그를 다시 보면 마지막 두 줄이 눈에 걸린다.

메모 → 코드 · 사흘 만에
05-25 메모
 · 목표 수익률 도달 시 50% 물량 즉시 익절
 · 나머지 50%는 트레일링 스톱으로 추세 추적

05-28 로그 🎯 1차 목표 도달. 50% 익절 🔥 [Trailing] 잔여 청산 ————————————————– 문장으로 적어둔 요구사항이 사흘 만에 로그가 됐다

첫 글에서 봤던 요구사항 메모의 두 문장이 여기서 실제 동작으로 나타난다. 목표 도달 시 절반 익절, 나머지는 트레일링. 사흘 걸렸다.

분할 청산의 논리는 단순하다. 전량을 목표가에서 팔면 그 뒤 상승을 놓치고, 전량을 트레일링으로 끌면 목표가에서 확보할 수 있던 이익을 되돌릴 수 있다. 절반씩 나누면 둘 다 조금씩 가져간다. 최적해는 아니지만 후회를 반으로 줄이는 구조다.

현행 봇은 다른 방식을 쓴다. +0.8%에 도달하면 +0.4%를 잠그는 본전 사수(SAFE), 그리고 포트폴리오 전체의 예상 실현액이 기준에 닿으면 전량 수확하는 방식이다. 물량을 쪼개는 대신 가격 하한을 올리는 쪽으로 진화했다. 하지만 뿌리는 같다 — 이익이 났을 때 그걸 어떻게 지킬 것인가.

1-5. 손절선을 넓힌 이유

같이 들어간 변화도 방향이 같다. 손절선을 -3.00%에서 -4.50%로 넓혔다.

왜 손절을 넓히는가 — 진입가와의 관계
[ 즉시 진입 + 좁은 손절 ]
  진입 4,120  손절 -3.00% → 3,996
  진입 직후 노이즈만으로 닿는다

[ 대기 진입 + 넓은 손절 ] 대기 4,099 손절 -4.50% → 3,914 더 낮게 사서 더 넓게 버틴다 ————————————————– 진입가를 낮추면 손절 여유가 생긴다 두 파라미터는 따로 노는 값이 아니다

추정하자면 -3%는 노이즈에 자꾸 걸렸을 것이다. 진입가가 높으면 손절선이 시세 근처에 붙는다. 조금만 흔들려도 잘린다. 손절이 자주 걸리는 봇은 방향을 맞춰도 돈을 잃는다.

여기서 배운 게 하나 있다. 진입가와 손절 폭은 따로 정하는 값이 아니다. 하나를 바꾸면 다른 하나도 다시 봐야 한다. 지금 봇에서 파라미터를 바꿀 때마다 매매기록 시뮬레이션을 다시 돌리는 이유가 이거다. 값 하나가 독립적으로 존재하지 않는다.

감시 종목 기본값도 이때 변동성이 큰 쪽으로 바꿨다. 눌림목 전략은 애초에 움직임이 있어야 성립한다. 하루에 0.3% 움직이는 종목에서 -0.5% 대기는 영원히 안 채워진다.

1-6. 안 사고 지나가는 것도 결과다

대기 진입에는 대가가 있다. 안 내려오면 못 산다.

대기 진입의 두 얼굴
[ 잘 되는 경우 ]
  4,120 → 4,099 터치 → 매수 → 반등
  같은 신호를 0.5% 싸게 잡았다

[ 놓치는 경우 ] 4,120 → 안 내려옴 → 그대로 상승 신호는 맞았는데 못 샀다 ————————————————– 놓친 상승은 로그에 안 남는다 그래서 이 손해는 체감이 안 된다

이게 은근히 까다로운 문제다. 물려서 잃은 돈은 계좌에 찍히지만, 못 사서 놓친 수익은 아무 데도 안 찍힌다. 그러니까 대기 폭을 넓힐수록 성적이 좋아 보이는 착시가 생긴다. 진입 횟수가 줄면서 승률이 올라가기 때문이다.

이 착시를 깨려면 놓친 신호도 기록해야 한다. 지금 봇이 “게이트에서 탈락한 종목"을 로그에 남기는 이유 중 하나가 이거다. 안 산 것도 결정이고, 결정은 기록으로 남아야 나중에 평가할 수 있다.

이 시점의 봇에는 그 기록이 없었다. [눌림목 대기] … 목표가 미달, 진입 보류 로그가 화면에 뜨고 끝이다. 며칠 뒤 그 종목이 얼마나 올랐는지는 아무도 모른다. 대기 폭을 -0.5%로 정한 근거가 감일 수밖에 없었던 이유이기도 하다. 비교할 데이터가 없으면 튜닝이 아니라 취향이다.

1-7. 조급함을 코드로 눌러두기

지금 봇은 열 겹 게이트로 과매도 눌림목을 노린다. RSI, 거래량, 저점 근접도, 호가 단위 같은 조건을 전부 통과해야 진입 후보가 된다. 그 물건의 씨앗이 여기 있다.

“지금 사지 말고 조금 더 빠지면 사라.” 문장 하나가 두 달을 버텼다.

v1.09 → 현행 · 같은 문장의 진화
v1.09  조건 성립 → -0.5% 대기 → 진입
        게이트 1개 (가격)

현행 게이트 10개 통과 → 진입 후보 RSI · 거래량 · 저점 근접 · 호가 단위 … 4슬롯 · 손절 -5% · SAFE 본전 사수 BTC 4시간봉 하락 시 신규 진입 차단 ————————————————– 늘어난 건 전부 “안 사는 이유"다

돌아보면 기술이 아니라 성격의 문제였다. 조급함을 코드로 눌러둔 첫 시도다.

사람이 직접 매매하면 -0.5%를 못 기다린다. 화면을 보고 있으면 지금 사야 할 것 같다. 놓칠 것 같다. 그 감각을 이길 방법이 나한테는 없었고, 그래서 봇에게 넘겼다. -0.50%는 내 인내심을 처음으로 숫자로 적어본 값이다.


2. 한 줄도 안 바뀐 버전

2-1. diff가 비어 있다

17분 뒤. 704줄. 직전 버전 대비 +0 / -0줄. diff를 돌리면 아무것도 안 나온다. 파일명만 바뀌었다.

diff — bithumb_bot_v1_10.py ↔ v1_11.py
$ diff bithumb_bot_v1_10.py bithumb_bot_v1_11.py
$ _
--------------------------------------------------
$ ls -l
 19:20  704 lines  bithumb_bot_v1_10.py
 19:24  704 lines  bithumb_bot_v1_11.py  ← 내용 동일
 19:27  697 lines  bithumb_bot_v1_14.py  ← 3분 뒤 대수술 시작

아무것도 안 바꿨다. 그래서 이 절은 코드가 아니라 당시의 개발 방식에 대한 기록이다.

2-2. 버전 관리가 파일 복사였던 시절

이때는 git이 없었다. 버전 관리라는 게 파일을 복사해서 번호를 하나 올려 저장하는 것이었다.

git 없는 형상 관리
저장       파일 복사 → 번호 +1
되돌리기   예전 파일을 연다
비교       두 파일을 나란히 놓고 눈으로 본다
브랜치     폴더를 하나 더 판다
기록       파일 헤더 주석
--------------------------------------------------
문제 1  무엇을 왜 바꿨는지 안 남는다
문제 2  폴더 이름이 사람 손을 타서 어긋난다
문제 3  변경 하나를 되돌릴 수 없다 (파일 통째로만)

되돌리고 싶으면 예전 파일을 열면 되고, 그게 전부다. 원시적이지만 작동은 한다. 실제로 이 시대의 461개 중 상당수가 이 방식으로 남았고, 덕분에 지금 이 글을 쓸 수 있다.

2-3. 왜 똑같은 파일을 하나 더 만들었나

추정은 둘이다.

+0/-0 버전의 두 가지 해석
[가설 A] 세이브 포인트
  "지금부터 크게 건드린다. 망하면 여기로 돌아온다."
  근거: 3분 뒤 버전에서 폰트·UI 구조가 크게 흔들린다

[가설 B] 실행 테스트용 사본 원본은 두고 사본으로 돌려본다 근거: 이 시기 파일 간격이 3~7분으로 매우 짧다 ————————————————– 공통점: 되돌아갈 자리를 먼저 만들어두는 습관

가설 A가 유력하다. 실제로 3분 뒤 버전에서 폰트 체계와 UI 구조가 크게 흔들린다. 큰 걸 건드리기 직전에 복사부터 해둔 것이다.

어느 쪽이든 공통점이 있다. 되돌아갈 자리를 먼저 만들어두는 습관. git을 안 쓰던 시절에도 그 본능은 있었던 셈이다.

2-4. 이 방식이 남긴 상처

이 시절의 파일 복사 방식은 지금 아카이브를 정리하면서 대가를 치르게 했다.

461개 버전을 정리하며 만난 문제들
· 폴더명과 파일 헤더 버전이 어긋난다
· 같은 번호가 두 번 나온다
· 무엇을 왜 바꿨는지 대부분 안 남아 있다
· 중간 시대 파일이 초기 폴더에 섞여 들어와 있다
--------------------------------------------------
해결: 폴더명·번호를 무시하고 파일 시각으로 전부 재정렬
     내용은 diff 로 복원, 의도는 추정으로 표시

그래서 이 아카이브의 글에는 “추정"이라는 단어가 자주 나온다. 코드 변화는 확실하지만 의도는 남아 있지 않기 때문이다. 확실한 것과 추정한 것을 섞어 쓰면 기록으로서 가치가 없어지니, 굳이 매번 표시한다.

git을 쓰기 시작한 뒤로 이 문제가 사라졌다. 커밋 메시지에 이유를 적고, 근거 수치를 동봉하고, 시각은 시스템이 알아서 남긴다. 지금의 규율은 미래의 나를 위한 게 아니라, 과거의 나에게 당해본 사람의 방어에 가깝다.

2-5. 겁이 데이터가 될 때

지금 봇은 git으로 관리되고, 커밋마다 근거 수치를 같이 적고, 파라미터는 시뮬레이션을 통과해야만 배포된다. 그 규율의 원형이 여기 있다고 하면 과장일까.

같은 본능, 다른 도구
2026-05-28  파일 복사 → 번호 +1
              "망하면 돌아온다"
현행         브랜치 → 시뮬레이션 → 커밋 → 배포
              "검증 안 된 값은 안 올린다"
--------------------------------------------------
방법은 조잡했지만 행동은 같다
실패했을 때 돌아갈 곳을 먼저 확보한다

방법이 조잡했을 뿐, 실패하면 돌아갈 곳을 확보하는 행동은 같다. 그리고 그 행동의 출처는 자신감이 아니라 겁이다. 자동매매에서 겁은 나쁜 감정이 아니다. 겁이 습관이 되면 규율이 된다.

아무것도 안 바뀐 버전을 아카이브에서 안 지운 것도 같은 이유다. 빈 페이지도 기록이다. 이 파일은 코드를 한 줄도 안 남겼지만, 그날 저녁 내가 무엇을 앞두고 긴장했는지를 남겼다.


3. 봇이 나에게 말을 걸게 만들기

3-1. 그날의 마지막 버전

밤 8시 22분. 775줄, +52/-21줄. 이날 마지막 버전이다. 매매 로직은 한 줄도 안 건드렸다. 대신 알림 채널을 손봤다.

bithumb_bot_v1_15.py — 토큰 원클릭 발급
# 이전: 브라우저 → 별도 도구 → 복사 → 붙여넣기 (3단계, 손으로)
+ def generate_kakao_token(self):
+     auth_code = self.ent_auth_code.get().strip()
+     tokens = requests.post(AUTH_URL, data={...}).json()
+     json.dump(tokens, open("kakao_token.json", "w"))
--------------------------------------------------
✅ 카카오 토큰이 성공적으로 발급 및 저장되었습니다!
❌ 인가 코드가 이미 사용되었거나 만료되었습니다.
   → 인가 코드는 일회용이고 금방 만료된다
⚠️ client_id / 콜백 서버 주소가 소스에 하드코딩됨 (지금은 안 하는 방식)

3-2. 3단계를 1단계로

토큰 발급 함수가 새로 생겼다. 브라우저에서 받은 인가 코드를 붙여넣고 버튼을 누르면, 봇이 직접 인증 서버에 토큰 교환을 요청하고 받아온 토큰을 파일로 저장한다.

토큰 발급 절차 — 이전 / 이후
[ 이전 ]
 1. 브라우저에서 인가 코드 받기
 2. 별도 도구로 토큰 교환
 3. 결과를 복사해 봇에 넣기
 → 중간에 꼬이면 1번부터 다시

[ v1.15 ]

  1. 인가 코드를 붙여넣고 버튼 → 교환·저장까지 봇이 한다 ————————————————– 인가 코드는 일회용 · 유효 시간이 짧다 단계를 줄이는 게 곧 성공률이다

문제는 인가 코드가 일회용이고 금방 만료된다는 점이다. 브라우저에서 받아서 다른 도구를 열고 붙여넣는 사이에 시간이 간다. 한 번 실패하면 그 코드는 죽는다. 처음부터 다시다. 실패 메시지에 그 좌절이 그대로 적혀 있다.

여기서도 원칙은 앞 글과 같다. 사람이 손으로 옮기는 단계를 지운다. 앞에서는 숫자였고 여기서는 문자열이다.

3-3. 왜 이 시점이었을까

매매 로직을 한 줄도 안 건드리고 알림만 손봤다는 게 힌트다.

추정: 화면을 안 보고도 봇을 돌리고 싶어졌기 때문이다.

보고 있어야 하는 봇 → 알려주는 봇
[ 그때까지 ]
  윈도우 PC에 창을 띄운 채 실행
  창을 봐야만 상황을 안다
  외출하면 봇이 뭘 하는지 모른다
  봇이 죽어도 모른다

[ 알림이 붙으면 ] 매수했는지 · 손절했는지 · 죽었는지 밖에서도 안다 ————————————————– 전략이 아니라 운영 방식의 변경이다

당시 봇은 윈도우 PC에 창을 띄운 채 돌았다. 창을 봐야만 상황을 아는 구조다. 알림이 휴대폰으로 오면 매수했는지, 손절했는지, 죽었는지를 밖에서 알 수 있다.

이건 성능 개선이 아니다. 운영 형태의 변경이다. 그리고 자동매매에서 운영 형태는 전략만큼 중요하다. 하루 종일 화면 앞에 앉아 있어야 하는 봇은 아무리 성적이 좋아도 오래 못 돌린다. 사람이 먼저 지친다.

3-4. GUI를 버리는 결정의 예고편

나중에 맥북으로 넘어가며 GUI를 버리고 터미널만 남기는 결정을 하게 되는데, 그 예고편이 여기다.

화면의 역할이 옮겨간 순서
1단계  창이 유일한 정보원        v1.04 ~
2단계  창 + 알림 (이중화)        v1.15 ← 지금 여기
3단계  알림이 주 · 화면은 보조
4단계  터미널 대시보드 + 알림   현행
--------------------------------------------------
GUI를 버릴 수 있었던 건 알림이 먼저 있었기 때문이다

순서가 중요하다. GUI를 먼저 버리고 알림을 붙였다면 중간에 아무것도 모르는 구간이 생겼을 것이다. 알림을 먼저 만들어두고, 그게 믿을 만해진 뒤에 창을 버렸다. 보고 있어야 하는 봇에서, 알려주는 봇으로.

3-5. 알림이 만드는 새로운 문제

알림을 붙이면 곧바로 다음 문제가 생긴다. 얼마나 자주 보낼 것인가.

알림 빈도의 함정
너무 많이  틱마다 · 감시 상태마다 알림
            → 하루 수십 건
            → 읽지 않게 된다정작 손절 알림도 놓친다

너무 적게 하루 요약 한 번 → 사고를 몇 시간 뒤에 안다

적절히 진입 · 청산 · 손절 · 사망 상태가 바뀔 때만 보낸다

알림이 많으면 안 읽는다. 안 읽으면 없는 것과 같다. 오히려 “알림을 받고 있다"는 착각 때문에 더 위험하다.

원칙은 하나다. 상태가 바뀔 때만 보낸다. 감시 중은 상태 변화가 아니다. 매수, 청산, 손절, 그리고 봇이 죽는 것 — 이 넷만 상태 변화다. 이 시절엔 그 구분이 아직 없었지만, 알림 채널을 만들자마자 곧 마주하게 되는 질문이었다.

3-6. 신뢰의 문제

자동매매에서 제일 어려운 건 전략이 아니라 신뢰다.

켜놓고 잠들 수 있어야 자동매매지, 창을 지키고 있으면 도구 붙은 수동매매다. 그리고 그 신뢰는 성적에서 오지 않는다. 아무 일도 없을 때 아무 알림이 안 오고, 뭔가 일어났을 때 반드시 알림이 오는 것 — 그 예측 가능성에서 온다.

지금 봇의 알림 설계도 같은 원칙 위에 있다. 진입, 청산, 손절, 그리고 죽었을 때. 그 네 가지만 확실하면 나머지는 화면을 안 봐도 된다.

참고로 이 시절 코드엔 인증 식별자와 콜백 서버 주소가 파일에 그대로 박혀 있었다. 지금 기준으로는 절대 안 하는 방식이고, 이 글의 화면에도 자리만 표시해두고 값은 비웠다. 이런 값이 코드에 박히는 건 편의 때문이다 — 설정 파일을 따로 만들 시간이 아까워서. 그 편의의 대가가 몇 달 뒤 아카이브를 공개할 때 돌아온다.


4. 하루가 남긴 것

4-1. 세 버전, 세 개의 축

2026-05-28 저녁 · 무엇이 바뀌었나
v1.09  전략    조건과 가격을 분리했다
                 진입가와 손절 폭이 한 쌍이 됐다
v1.11  규율    되돌아갈 자리를 먼저 만든다
                 겁이 습관이 되고 습관이 규율이 된다
v1.15  운영    화면에서 벗어나기 시작했다
                 알림이 먼저, GUI 폐기는 나중
--------------------------------------------------
전략 · 규율 · 운영 — 지금 봇을 지탱하는 세 축이
하루 저녁에 전부 씨앗을 뿌렸다

세 버전이 각각 다른 축을 건드렸다는 게 지금 보면 신기하다. 그날은 그냥 손에 잡히는 대로 고쳤을 텐데, 지나고 보니 봇을 지탱하는 세 기둥이 그날 저녁에 다 세워졌다.

4-2. 가장 중요한 값은 대개 가장 단순하다

-0.50%는 계산해서 나온 값이 아니다. 시뮬레이션도 백테스트도 없던 시절의 감이다. 지금 기준으로는 배포할 자격이 없는 값이다.

그런데 이 값이 두 달을 버텼다. 정확히는 값이 아니라 구조가 버텼다. “조건이 서도 가격이 안 맞으면 안 산다"는 구조 말이다. 값은 나중에 시뮬레이션으로 몇 번이나 바뀌었지만 구조는 그대로다.

값과 구조 — 무엇이 오래 사는가
    -0.50% · -4.50% · +2.0%
      시뮬레이션으로 계속 바뀐다
      현행 봇의 손절은 -5%, 익절 구조도 다르다

구조 “조건 성립 ≠ 즉시 매수” “진입가와 손절 폭은 한 쌍이다” 두 달 넘게 안 바뀌었다 ————————————————– 파라미터 튜닝으로 얻는 것과 구조 변경으로 얻는 것은 크기가 다르다

이 아카이브를 다시 읽으며 얻은 교훈 중 제일 실용적인 게 이거다. 성적이 안 나올 때 파라미터부터 만지게 되는데, 대부분의 큰 개선은 값이 아니라 구조에서 나왔다. +216/-190줄짜리 수술이 -0.5%라는 숫자보다 중요했다.

4-3. 그리고 아직 없던 것

물론 이 시점에도 계좌 전체를 지키는 로직은 없었다. 슬롯 제한도, 일일 한도도, 시장 레짐 판단도 없다. 눌림목 대기는 더 좋은 가격에 사는 장치안 사는 장치가 아니다.

v1.09 시점의 빈칸
✔ 진입가 통제 (눌림목 대기)
✔ 개별 손절 -4.50%
✔ 분할 익절 + 트레일링
✘ 동시 보유 슬롯 제한
✘ 재진입 쿨다운
✘ 일일 손실 한도
✘ 시장 레짐 판단
--------------------------------------------------
"더 잘 사는 것"과 "안 사는 것"은 다른 문제다
후자를 배우는 데 시대가 몇 개 더 걸린다

하락장에서는 눌림목이 계속 나온다. 계속 나오고, 계속 더 빠진다. 대기 폭만 있는 봇은 그 장에서 열심히 잘 산다 — 그리고 계속 물린다. BTC 4시간봉으로 레짐을 판단해 신규 진입 자체를 차단하는 로직이 왜 필요했는지는 그 장을 겪어봐야 안다.

4-4. 하루의 밀도

마지막으로 하나. 이날 저녁 한 시간 반 동안 여섯 개 넘는 버전이 나왔다. 지금 기준으로는 커밋 두세 개 분량이다.

그렇게 빨리 돌 수 있었던 건 검증 절차가 없었기 때문이다. 고치고, 돌리고, 눈으로 보고, 다음. 시뮬레이션도 백테스트도 없으니 배포까지 3분이면 된다. 그 속도가 이 시대의 장점이자 전부였다.

지금은 파라미터 하나 바꾸는 데 시뮬레이션을 돌리고 근거 수치를 커밋에 적는다. 훨씬 느리다. 대신 틀린 값이 실계좌로 나가지 않는다. 어느 쪽이 낫냐고 물으면, 초기엔 속도가 맞았고 지금은 규율이 맞다고 답하겠다. 순서를 바꿨으면 둘 다 못 얻었을 것 같다.

짐 로저스는 돈이 구석에 놓일 때까지 기다렸다 줍는다고 했다. 나는 그 기다림을 못 하는 사람이라 봇에게 넘겼다. -0.50%는 내 인내심의 첫 수치화였다.

레이 달리오는 실패보다 실패에서 아무것도 안 남기는 게 문제라고 했다. +0/-0 버전엔 코드가 안 남았지만 겁먹고 백업부터 뜬 흔적이 남았다. 그것도 데이터다.

에드 세이코타는 좋은 트레이딩은 지루해야 한다고 했다. 지루하려면 안 보고 있어도 괜찮아야 한다. 알림을 붙인 그날 밤은 지루해지기 위한 첫 투자였다.