마틴게일 봇을 직접 실거래로 돌려봤다 — 승률 95%의 결과
바이낸스 선물거래소에서 헷지 모드로 롱숏 마틴게일 그리드 봇을 돌려봤습니다. 잦은 익절에도 불구하고 왜 계좌가 박살 나는지, 파라미터와 수수료의 함정을 정리했습니다.
유튜브 영상 '묻고 더블로 가 - 마틴게일 최종편'에서 실제로 돌렸던 마틴게일 그리드 봇 소스 전체를 공개합니다. 이 글은 그 정리본에 영상에는 안 넣은 최소 실행 코드를 붙인 것입니다. 결론부터 말하면, 마틴게일은 승률을 높이는 기술이 아니라 손실을 뒤로 미루는 기술이었습니다. 수익률 숫자는 여기에 옮겨 적지 않겠습니다. 제가 유리한 구간만 고르게 되니까요. 대신 어떤 구조 때문에 결국 깨지게 되는지를 기록했습니다.
원리가 간단한 게 함정이다
마틴게일 그리드의 기본 아이디어는 아주 단순합니다. 가격이 특정 범위 안에서 오르락내리락할 것이라 보고, 현재가를 기준으로 위아래에 촘촘하게 주문을 깔아두는 겁니다. 가격이 내려가면 롱 포지션에 진입하고, 올라가면 숏 포지션에 진입합니다. 여기서 핵심은 '물타기'예요. 가격이 예측과 반대로 가서 손실이 나면, 더 큰 수량으로 추가 진입해서 평균 단가를 유리하게 만듭니다. 그러다 약간만 가격이 돌아와도 바로 익절할 수 있게 되거든요. 박스권 장세에서는 양방향으로 계속해서 짧은 익절을 반복하며 수익을 쌓아가는 구조입니다. 이론상으론 지지 않는 게임처럼 보입니다.
모든 파라미터는 질문이다
하지만 이 전략은 수많은 파라미터의 집합입니다. config.ini 파일을 열어보면 '어떤 간격으로 그리드를 깔 건가(Spacing)', '몇 단계까지 물을 탈 건가(Levels)', '단계별로 얼마나 더 실을 건가(SizeSteps)', '얼마나 먹고 나올 건가(TpPct)', 그리고 '어디까지 버티다 손절할 건가(RangePct)' 같은 변수들이 가득합니다. 이 설정값 하나하나가 사실은 시장에 대한 질문이자 트레이드오프입니다. 예를 들어 손절 범위를 넓히면 당장 터지는 일은 줄어들지만, 한번 터질 때 모든 수익을 반납하고도 남을 만큼 크게 터집니다. 반대로 범위를 좁히면 손절은 잦아지지만 손실액은 작아지죠. 이 파라미터들을 과거 데이터에 맞춰 아무리 정교하게 최적화해도, 그건 과거에 대한 답일 뿐 미래를 보장해주지 않습니다.
아래 코드는 바로 이 설정값들을 이용해 실제로 롱/숏 진입 가격과 단계별 배팅액을 계산하는 부분입니다. 파라미터를 없앤 게 아니라 이름을 바꾼 것에 가깝습니다.
void BuildGrid(double mid, Config cfg, BinanceFutures ex)
{
refPrice = mid;
int N = cfg.Levels;
longLvl = new double[N]; shortLvl = new double[N]; sizeUsdt = new double[N];
// 누적 간격 %. fixed 모드면 (k+1) * 고정 스텝.
double[] cum = new double[N];
for (int k = 0; k < N; k++) cum[k] = (k + 1) * cfg.FixedStep;
for (int k = 0; k < N; k++)
{
longLvl[k] = refPrice * (1 - cum[k] / 100.0);
shortLvl[k] = refPrice * (1 + cum[k] / 100.0);
}
// 단계별 배팅금액. double 모드면 2배씩.
sizeUsdt[0] = cfg.BaseUsdt;
for (int k = 1; k < N; k++)
{
// progressive 모드면 설정된 배수를 따름. 기본은 2.0
double m = cfg.SizeMode == "double" ? 2.0 : cfg.SizeSteps[k-1];
sizeUsdt[k] = sizeUsdt[k - 1] * m;
}
longLevel = 0; shortLevel = 0;
Log("그리드 설정 기준가 " + FmtP(refPrice));
}진짜 비용은 수수료와 슬리피지
마틴게일 봇은 아주 짧은 익절을 자주 반복하는 구조입니다. 익절 목표(TpPct)가 0.3%라면, 한 번 거래할 때마다 내는 수수료와 슬리피지의 합이 이보다 작아야만 계좌에 돈이 쌓입니다. 바이낸스 선물 시장가(Taker) 수수료가 0.05%이니, 진입과 청산 왕복이면 0.1%입니다. 여기에 슬리피지까지 더하면 0.15%는 우습게 사라집니다. 0.3%를 먹어도 절반이 비용으로 나가는 셈입니다. 이 비용은 이기든 지든 무조건 나가는 확정값입니다. 반면 '가격이 다시 돌아올 것'이라는 기대는 어디까지나 확률에 기댄 추정값이죠. 이 싸움에서 이기기가 정말 어렵습니다.
실제 코드에서도 익절로 번 돈(gross)에서 수수료를 빼야 비로소 순손익(TotalPnl)이 됩니다. 익절을 아무리 많이 해도 수수료를 못 이기면 계좌는 서서히 녹아내립니다.
if (longQty > 0)
{
double avg = longCost / longQty;
// 평단가(avg) 대비 목표 익절률(TpPct) 도달했는지 체크
if (mid >= avg * (1 + cfg.TpPct / 100.0))
{
// 실제 청산될 가격. useMaker 시뮬이 아니면 슬리피지 반영.
double closeP = cfg.UseMaker ? avg * (1 + cfg.TpPct / 100.0) : bid * (1 - cfg.SlippagePct / 100.0);
// 수수료 빼기 전 총수익
double gross = (closeP - avg) * longQty;
// 수수료(taker 기준)를 뺀 최종 손익을 누적.
TotalPnl += gross - cfg.FeeTaker * closeP * longQty;
if (!cfg.DryRun) ex.MarketOrder(Symbol, "SELL", "LONG", FmtQty(longQty));
Log("롱 익절 @ " + FmtP(closeP));
Wins++;
ResetLong();
}
}
// 비용은 확정, 수익은 불확실. 이게 핵심이다.왜 이게 실전에서 깨지는가
- 승률이 높다는 착시를 일으킵니다. 100번의 작은 익절보다 1번의 큰 손절이 계좌에 더 치명적입니다.
- 손익비가 구조적으로 불리합니다. 익절 폭(TpPct)은 좁고, 손절 폭(RangePct + 물타기로 악화된 평단)은 훨씬 큽니다.
- 파라미터 과최적화의 덫에 빠지기 쉽습니다. 특정 기간의 박스권에 잘 맞춘 설정값은 시장이 추세로 바뀌는 순간 바로 깨집니다.
- 비용은 확정값이고 엣지는 추정값입니다. 수수료와 슬리피지는 무조건 내야 하지만, '가격이 박스권에 머물 것'이라는 가정은 언제든 깨질 수 있습니다.
- 마틴게일은 사실상 레버리지를 숨기고 있습니다. 물을 탈수록 총 포지션과 리스크가 기하급수적으로 커져, 작은 가격 변동에도 강제청산 위험에 노출됩니다.
- 시뮬레이션은 현실이 아닙니다. 이 코드처럼 '메이커 수수료'로 모의 테스트를 하고 실전에서 '테이커 수수료'로 돌리면 결과가 완전히 달라집니다.
- 가장 위험한 건 코드가 아니라 손입니다. 계속된 손실에 조급해져서 손절 범위를 넓히거나 초기 배팅액을 늘리는 순간, 봇은 도박 기계가 됩니다.
이 글과 첨부 코드는 전략 구조를 설명하려고 만든 교육·연구 자료입니다. 특정 종목이나 매매를 권하지 않습니다.
첨부파일
영상에 사용된 소스코드와 설명서입니다. 로그인 없이 받을 수 있습니다.
마틴게일 그리드 봇 C# 전체 소스