Moss 가 수수료를 보고 올린 목표비 3.0→3.3 — 같은 호가에 둘을 함께 걸어 봤습니다
우리 수수료 기록을 먹은 Moss 가 `tp_rr_ratio` 를 3.0 에서 3.3 으로 올렸습니다. 그 두 목표가를 같은 시각·같은 호가에 함께 걸었더니, 올린 3.3 이 바로 그 근거였던 거래를 목표가로 못 닫았습니다.
Moss 가 수수료를 보고 올린 목표비 3.0→3.3 — 같은 호가에 둘을 함께 걸어 봤습니다이 글의 완료 조건: 독자가 「도구가 되먹임을 받고 고친 칸」 하나를 골라, 고치기 전 값과 고친 값을 같은 밀리초에 함께 걸고 그 한 칸이 무엇을 바꿨는지 기록으로 읽을 수 있으면 성공입니다.
| 하는 일 | 도구가 우리 비용 기록을 보고 고친 파라미터를 가격 레벨로 번역해, 고치기 전·후 두 값을 같은 호가에 함께 걸고 그 칸의 효과만 읽습니다 |
| 맞는 사람 | 도구에게 실행 기록을 되먹여 설정을 고쳐 본 적이 있는데, 그 수정이 좋아진 건지 확인 못 한 사람 |
| 안 맞는 사람 | 비율 파라미터만 있고 거래별 레벨을 못 내는 도구를 쓰는 사람. 번역할 기준점이 없으면 이 경로가 안 섭니다 |
| 이 글의 결과물 | 고치기 전·후 두 목표가가 같은 체결 위에서 어떻게 갈리는지 보여 주는 대조 한 장과, 그것을 뽑는 레시피 |
| 준비물·비용 | 코드 0원 · 모델 비용 0원 · weltiq pro 계정. 대조군 N개 = 한도 N회 |
| 시간·난도 | 20분 · 중 (curl·JSON, 그리고 비율→레벨 변환) |
| weltiq 와의 관계 | 이 글이 전부 그 이야기입니다 — 절차 글이라 5절이 따로 없습니다 |
| 검증 환경·날짜 | 2026-09-28 (KST) · 격리 서버 · 합성 호가 (5절에 한계를 그대로 적었습니다) |
| 제휴 고지 | 필자는 weltiq 로부터 이 연재의 원고료를 받습니다. 도구의 수정이 그 근거를 스스로 죽였다는 것까지 그대로 적었습니다 |
사람 쪽 문장은 실제로 친 명령을 대화로 옮긴 것이고, 출력은 실측이며 숫자는 손대지 않았습니다.
1. 이 도구가 남기던 빈칸
15편에서 moss-trade-bot-skills 를 돌렸습니다. 미션 한 문장을 주면 LLM 이 파라미터 36칸을 전부 채우고, 그 설정으로 자기 백테스트를 돌려 스스로 채점하는 물건입니다.
Moss 가 36칸을 채워 내놓는 화면입니다. 미션 한 문장에서 이만큼이 한 번에 나옵니다. 보실 곳은 **칸이 전부 비율·배수라는 것** — tp_rr_ratio, sl_atr_mult, risk_per_trade … 절대 가격이 하나도 없습니다. 이게 3절에서 걸립니다
그리고 이 도구의 자기 백테스트에는 수수료가 없습니다.
두 엔진을 대조한 화면입니다. 보실 곳은 **수수료 문자열 0건** — Moss 의 백테스트 코드에는 수수료를 다루는 줄이 아예 없습니다. 자기 세계에서 비용이 0이면, 비용 때문에 설정을 고칠 이유도 영원히 안 생깁니다
그래서 우리 비용 기록을 그대로 먹여 봤습니다 — pnl -98.02 fees 247.83. 가공 없이 한 줄로 넘겼습니다. Moss 가 36칸 중 여섯 칸을 고쳤고, 다섯 칸의 이유에 「수수료」가 들어갔습니다.
weltiq 기록을 받은 Moss 가 여섯 칸을 고치는 화면입니다. 위 파란 한 줄이 넘겨준 전부이고 아래가 도구의 답입니다. 보실 곳은 노랗게 걸린 **수수료** — 자기 백테스트에는 존재하지도 않는 항목이 여섯 칸 중 다섯 칸의 이유에 들어가 있습니다
그중 하나가 이 글의 주인공입니다.
| 칸 | 전 | 후 | Moss 가 밝힌 이유 |
|---|---|---|---|
tp_rr_ratio |
3.0 | 3.3 | "높은 수수료 부담을 감안해 이익 실현 시 비용을 흡수할 여지를 늘린다" |
바뀐 여섯 칸 중 가격 레벨로 번역 가능한 칸이 이것 하나입니다. 나머지는 진입 임계·이동평균 기간·거래당 위험 같은 것이라 주문 한 건의 레벨로 안 내려옵니다.
여기가 빈칸입니다. Moss 는 3.3 으로 고쳤다고 말했고, 그게 나아졌는지는 아무도 안 쟀습니다. 재려면 3.0 과 3.3 을 같은 조건에서 돌려야 하는데, 그 조건이 만들어지지 않았습니다.
2. 왜 지금까지 못 쟀나
Moss 자기 세계에서는 이 질문 자체가 안 나옵니다.
자기 백테스트에 수수료가 0이라 rr 을 올릴 이유가 없고, 올린 뒤에 어떤 거래가 죽는지도 안 보여 줍니다. 되먹임의 근거가 바깥에서 오는데 검증할 자리는 안에 없습니다.
바깥에서 재려면 3.0 과 3.3 을 나란히 돌려야 하는데, 실행하는 순간 나머지가 같기 어렵습니다.
- 두 설정을 차례로 돌리면 시각이 달라지고, 시각이 다르면 진입가가 달라집니다
- 동시에 돌리면 포지션이 섞이고 자본을 나눠 써서 수량이 달라집니다
- 백테스트로 다시 돌리면 그건 과거 재생입니다 — 실물 비용·틱 격자·최소 주문금액이 그 엔진의 가정대로 돕니다. 애초에 Moss 의 문제가 그 가정이었습니다
같은 시각·같은 호가에 한 칸만 바꿔 내면, 차이가 그 칸에서만 납니다.
시험 주문은 잔고를 안 쓰고 수량을 서버가 정하므로, 두 팔이 자본을 두고 다투지 않습니다. 같은 밀리초에 던지면 같은 호가를 봅니다.
3. 레시피 — 그대로 도는 것
레시피 한 장을 올려 뒀습니다: 10-trial-order-moss-cost-feedback-ab.sh.
| 칸 | 무엇 |
|---|---|
| ⓪ 번역 | 비율을 가격 레벨로 유도하고 틱 격자에 맞춥니다. 유도 과정을 전부 적습니다 |
| ① 심기 | 두 팔을 동시에 던집니다. client_tracking_id 는 둘 다 같고, metadata.arm 이 팔을 가릅니다 |
| ② 회수 | GET /v1/forward-tests?tracking=<런 ID> |
| ③ 집행 기록 | GET /v1/forward-tests/orders?format=csv&tracking=… — 계정 전체를 한 번에 |
| ④ 조인 | 추적 ID + client_order_id 로 도구 로그와 잇고, published_at 이 두 팔 같은지 셉니다 |
의도는 도구가 갖습니다. 서버로 가는 것은 client_order_id·client_tracking_id·문자열 metadata 뿐이고, tp_rr_ratio 라는 이름도 Moss 가 그것을 올린 이유도 tool_log.csv 에만 씁니다. metadata 에 float 을 넣으면 canonical_json 이 결정론 규칙으로 거부해서 500 이라, 3.3 도 문자열로 실었습니다.
비율을 레벨로 — 유도를 전부 적습니다
Moss 기록에는 비율만 있고 절대 레벨이 없습니다. 기준점은 도구 자신의 거래 행입니다(21-moss-own-backtest-30d.json trades[1]): SHORT · entry 76863.2 → exit 75943.85 · exit_reason: take_profit · pnl_pct 0.1196.
기록된 tp 거리 = 76863.2 − 75943.85 = 919.35 (rr 3.0 에서 실제로 난 거리)
→ sl 거리 = 919.35 / 3.0 = 306.45
→ SL = 76863.2 + 306.45 = 77169.65 → 77169.6 (틱 0.1, 버림)
rr 3.3 의 tp 거리 = 306.45 × 3.3 = 1011.285
→ TP(비교군) = 76863.2 − 1011.285 = 75851.915 → 75851.9 (틱 0.1, 버림)
TP(기준안) = 75943.85 → 75943.8 (틱 0.1, 버림 — 숏 목표가는 내리는 쪽이 보수적)
sl_atr_mult 은 2.0 으로 안 바뀐 칸이라 손절 거리도 안 바뀝니다 → 두 팔의 손절을 같은 값으로 놓았습니다. 진입가·방향·시한도 같습니다. 다른 것은 목표가 하나입니다.
원값은 그대로 안 들어갑니다
75943.85 는 binance-usdm BTCUSDT 틱 0.1 의 배수가 아닙니다. 이관 검증에서 그대로 보내 확인했습니다.
422 invalid_take_profit "75943.85 is not a multiple of tick 0.1"
시한을 안 넣으면 그보다 먼저 422 exit_plan_deadline_required 를 받습니다 — 시한 검증이 가격 검증보다 앞섭니다.
거래소를 바꿔야 했습니다
binance-spot 은 shortable=false 라 숏을 못 받습니다. 그래서 binance-usdm 을 썼습니다(틱 0.1 · 로트 0.001 · 최소 주문금액 50 USDT). 이것도 한 칸을 바꾼 것이지만, 두 팔이 같은 거래소를 쓰므로 대조 안에서는 상수입니다.
아래 숫자의 환경: 격리 임시 서버 · 합성 호가 · 운영이 아닙니다 · 손익은 시장 사실이 아닙니다.
4. 돌려 본 결과
두 팔을 13:28:50.398 / .406 에 던졌습니다. 8밀리초 차이입니다.
| 팔 | tp_rr_ratio |
목표가 | 접수 (KST) | 진입 체결가 | 진입 호가 공개 시각 | 청산가 | exit_trigger |
exit_trigger_px |
close_reason |
수수료 | 순손익 | 소요 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
15-rr-30 (기록) |
3.0 | 75943.8 | 13:28:50.398 | 76855.363685 | 13:28:51.240 | 75951.444375 | take_profit |
75943.8 | take_profit |
0.07640340 | +0.827515910 | 2.9초 |
15-rr-33 (Moss 수정) |
3.3 | 75851.9 | 13:28:50.406 | 76855.363685 | 13:28:51.240 | 75951.444375 | — | — | close_after |
0.07640340 | +0.827515910 | 46.0초 |
두 팔의 진입 체결가와 그 체결이 참조한 호가의 공개 시각이 밀리초까지 같습니다. 한 호가가 둘을 다 채웠습니다.
우리 쪽 시험 상세 — 한 칸만 다른 두 팔이 나란히 붙은 화면입니다. 보실 곳은 **close_reason 열** — 한쪽은 take_profit, 다른 쪽은 close_after 입니다. 같은 체결·같은 청산가인데 **왜 닫혔는지가 갈렸습니다**
그 칸이 결과를 갈랐나 — 갈랐고, 방향이 뼈아픕니다
시장이 실제로 간 곳은 75943.85 였습니다. 그 값은
- rr 3.0 의 목표가 75943.8 에 닿습니다 → 2.9초에
take_profit - rr 3.3 의 목표가 75851.9 에 91.95 만큼 못 미칩니다 → 목표로 못 닫고 시한에 걸립니다
Moss 가 수수료를 보고 올린 3.3 이, 그 수수료 판단의 근거였던 바로 그 거래를 목표가로 못 닫습니다.
되먹임 자체가 틀렸다는 뜻이 아닙니다. 비용을 흡수하려고 목표를 멀리 두는 것은 말이 됩니다. 다만 그 대가가 무엇인지가 Moss 자기 세계에서는 절대 안 보입니다 — 수수료가 0인 백테스트에는 "목표를 올려서 죽은 거래" 같은 게 없으니까요. 같은 시각·같은 호가에 두 목표가를 함께 걸면 그게 바로 보입니다.
순손익은 두 팔이 같습니다. +0.827515910 로 소수점 끝까지 같습니다. 합성 호가가 청산 뒤로 안 움직여 시한 청산도 같은 가격에 났기 때문입니다. 갈린 것은 손익이 아니라 「왜·언제 닫혔나」 입니다 — 그리고 되먹임을 검증할 때 필요한 정보가 바로 그쪽입니다.
내보내기 화면 — 팔마다의 기록이 CSV 로 나오는 자리입니다. 보실 곳은 끝쪽 열들 — exit_trigger·exit_trigger_px·close_reason 이 있어야 "3.3 은 왜 목표로 안 닫혔나"를 스프레드시트에서 읽을 수 있습니다
몇 팔까지 되나, 얼마나 드나
| 실측 | |
|---|---|
| 한 호가에 6팔 동시 발주 | 6/6 전부 201, 실패·거절 0, 전체 0.02초, 접수 시각이 6.5밀리초 안에 분포. 막히는 코드 없음 |
| 한도 소모 | N팔 = N회. 15편 2팔에 used 가 5 → 7 |
| 재전송·거절·청산 | 0회 (같은 본문 재전송 200 · 다른 본문 409 · 자동 청산은 counted: false) |
pro 월 1,000회 기준으로 2팔짜리 대조는 월 500회입니다. 되먹임 한 번마다 한 쌍을 돌려도 한참 남습니다.
5. 이 조합의 한계
① 표본 하나로는 아무 말도 못 합니다. 위는 거래 한 건입니다. "3.3 이 3.0 보다 나쁘다"가 전혀 아닙니다 — 그 한 거래에서 3.3 이 목표로 못 닫았다는 사실 하나입니다. 다른 거래에서는 3.3 이 더 크게 먹을 수도 있고, 그게 애초에 rr 을 올리는 이유입니다. 분포가 필요합니다.
② 반사실은 한쪽만 잽니다. "3.3 으로 걸었으면 어떻게 닫혔나"는 재지만 "3.3 덕분에 무엇을 더 벌었나"는 여전히 판단입니다. 목표를 멀리 둬서 더 간 거래는 이 창에 안 들어옵니다.
③ 우리는 Moss 의 수정이 옳다/틀리다를 말하지 않습니다. 재고 기록할 뿐입니다. 위 표가 말하는 것은 "그 수정이 이 거래 하나를 목표가로 못 닫게 만들었다" 이고, 그 이상이 아닙니다.
④ 손익은 시장 사실이 아닙니다. 합성 호가 위의 산술입니다. 선 것은 rr 대조 설계입니다.
⑤ 레벨이 유도값입니다. 75851.9 는 Moss 기록에 없는 숫자입니다 — 도구의 거래 행에서 필자가 유도했습니다. 유도 규칙(3절)이 바뀌면 이 숫자가 바뀌고, 그러면 결론도 바뀔 수 있습니다. 도구가 낸 값은 3.3 이라는 비율 하나뿐입니다.
⑥ 미체결 팔은 자기가 본 호가가 기록에 안 남습니다. 이번 두 팔은 다 체결됐지만, 지정가로 대조한 다른 회차에서 미체결 팔이 나왔습니다. reference_px 는 접수 시점의 기준가일 뿐이고 published_at 은 체결 뒤에만 생깁니다. 게다가 미체결 팔은 close_after_seconds 시계가 시작조차 안 합니다 — 관측 창 안에서 아무 결과도 안 냅니다.
⑦ 「같은 호가였다」는 정황이지 식별이 아닙니다. 호가 스냅샷에 id 가 없습니다. published_at 이 밀리초까지 같다는 것이 현재의 최선입니다.
⑧ 추적 ID 로 실험을 되찾는 길은 이 실행 직후에 열렸습니다. 이 회차를 돌릴 때는 ?tracking= 교차 조회가 없어서 실제로는 태그로 되찾았습니다. 레시피는 열린 쪽을 쓰지만, 위 실측이 그것을 증명한 것은 아닙니다.
6. 언제 쓰고 언제 쓰지 마라
쓰세요.
- 도구에게 실행 기록을 되먹여 설정을 고쳤을 때. 고친 칸 하나를 이렇게 놓고 보면 그 수정의 대가가 바로 보입니다
- 도구가 거래별 레벨을 내줄 때. Moss 의
trades[]처럼 진입·청산·사유가 든 배열이 있어야 비율을 레벨로 번역할 기준점이 생깁니다 - 궁금한 것이 「어느 조건이 먼저 발동하나」 일 때. 발동 조건·발동 호가·시각이 팔마다 따로 남습니다
쓰지 마세요.
- 손익 차이를 보려고 할 때. 호가를 고정하면 손익이 안 갈립니다. 갈리는 것은 발동 조건입니다
- 도구가 비율만 내고 거래 목록이 없을 때. 다른 편에서 격자 최적값 두 개를 대조하려다 막혔습니다 — 그 도구의 격자 결과에 거래별 진입·청산 레벨이 없어서, 「두 최적점이 같은 봉에서 어떻게 갈리나」를 기록으로 답할 수 없었습니다
- 두 칸 이상을 같이 바꿀 때. 거래소를 바꾸면 수수료만이 아니라 로트·최소 주문금액까지 같이 바뀌어 수량이 13배 갈립니다
- 한 거래로 되먹임을 판정하려 할 때. 한 쌍이 2회고 월 500쌍이 가능합니다. 한 쌍으로 끝낼 이유가 없습니다
이 글의 증거: B축 대조 측정 기록 · 케이스별 요청·응답 원문 · 이관 판정 · 레시피. 원 도구 회차는 15편 moss-trade-bot-skills에 있습니다.