삼각 차익거래(triangular arbitrage) — 원리와, 남기기 어려운 이유

🌐 English

삼각 차익거래의 아이디어는 한 문장으로 끝납니다. 토큰 A로 B를 사고, B로 C를 사고, C로 다시 A를 사서 — 처음보다 A가 많아지면 이익. 한 거래소(혹은 한 체인) 안에서 세 페어의 가격이 서로 어긋난 순간을 노리는 것이죠. 원리는 초등학교 산수지만, 실제로 순이익을 남기는 건 전혀 다른 이야기입니다.

한 바퀴를 곱으로 계산한다

경로를 WBNB → USDT → CAKE → WBNB라고 합시다. 각 홉에서 "1단위 넣으면 몇 단위 나오는지"의 환율을 곱해 나갑니다. 최종 결과가 시작 수량보다 크면 이론상 이익입니다.

// 각 홉의 실효 환율을 곱해 한 바퀴 결과를 구한다

// rateAB = B를 A로 나눈 실효 가격 (수수료 반영 후)

func cycleReturn(amountIn float64, rates []float64) float64 {

    out := amountIn

    for _, r := range rates {

        out = out * r   // 홉을 지날 때마다 환율을 곱한다

    }

    return out // out > amountIn 이면 (겉보기) 이익

}

실제 봇에서는 이 "경로"를 미리 등록해 둡니다. 아래는 사이클을 사람이 읽을 수 있는 라벨로 만드는 코드입니다 — 디버깅할 때 cycle#7보다 WBNB→USDT→CAKE→WBNB가 훨씬 낫죠.

// 등록된 사이클을 "WBNB→USDT→CAKE→WBNB" 문자열로

func cycleLabel(hops []Hop) string {

    if len(hops) == 0 {

        return "cycle(empty)"

    }

    parts := make([]string, 0, len(hops)+1)

    parts = append(parts, symbol(hops[0].TokenIn))

    for _, h := range hops {

        parts = append(parts, symbol(h.TokenOut))

    }

    return strings.Join(parts, "→")

}

함정 1 — 수수료가 세 번 누적된다

가장 먼저 발목을 잡는 건 수수료입니다. 홉마다 스왑 수수료(예: 0.25~0.3%)가 붙는데, 삼각 경로는 홉이 셋이라 세 번 물립니다. 각각은 작아 보여도 곱으로 쌓이면 만만치 않습니다.

// 수수료 0.3%짜리 홉을 세 번 지나면...

// 가격이 완벽히 균형이어도 (환율 1.0) 한 바퀴에 약 0.9% 손실

gross := 1.0 * 1.0 * 1.0

net := gross * 0.997 * 0.997 * 0.997 // ≈ 0.991

// 즉, 최소 0.9%를 이겨야 본전. 그 위로 남는 게 진짜 이익

다시 말해, 세 페어의 가격 어긋남이 누적 수수료(여기선 약 0.9%)를 넘어서야 비로소 본전입니다. 그 문턱을 넘는 기회 자체가 흔치 않죠.

함정 2 — 가스와 슬리피지

겉보기 이익이 수수료를 넘겼다 칩시다. 이제 가스비가 기다립니다. 세 번의 스왑(온체인이면 한 트랜잭션에 묶더라도)은 실제 실행 비용을 잡아먹습니다. 여기에 슬리피지까지 — 규모가 커지면 각 홉의 체결가가 불리해져, 계산했던 환율이 실제보다 나빠집니다.

func netProfit(amountIn, cycleOut, gasCost float64) float64 {

    grossProfit := cycleOut - amountIn

    return grossProfit - gasCost // 가스를 빼고도 양수여야 실행 가치

}

// 실행 가드: 순이익이 최소 문턱을 넘을 때만 보낸다

if netProfit(amountIn, out, gasCost) < minProfitThreshold {

    return // 스킵 — 실행 자체가 손해

}

함정 3 — 경쟁과 타이밍

가장 잔인한 함정입니다. 이런 기회는 당신만 보는 게 아닙니다. 화면에 뜬 이익은 이미 수십 개의 봇이 같이 보고 있고, 먼저 체결한 하나만 가져갑니다. 온체인이라면 멤풀에서 앞서가려는 경쟁(프론트러닝)까지 벌어지죠. 당신의 트랜잭션이 블록에 담길 때쯤이면, 그 어긋남은 이미 사라졌을 가능성이 높습니다.

그래서 실전에서는

  • 순이익 기준으로만 판단한다. 겉보기 이익이 아니라 수수료·가스·예상 슬리피지를 모두 뺀 값이 문턱을 넘을 때만 실행합니다.
  • 규모를 유동성에 맞춘다. 세 홉 중 가장 얇은 풀이 전체 규모를 제한합니다. 얇은 풀에 크게 넣으면 슬리피지가 이익을 통째로 먹습니다.
  • 빠른 스캔, 신중한 실행. 오프체인에서 닫힌 공식으로 후보를 넓게 훑고, 유망한 것만 정밀 검증한 뒤 실행합니다.
  • 기회는 드물다는 걸 받아들인다. 대부분의 스캔은 "이익 없음"으로 끝나는 게 정상입니다. 억지로 문턱을 낮추면 손해 보는 거래만 늘어납니다.

삼각 차익거래는 원리가 단순해서 매력적이지만, 그 단순함이 함정입니다. 진짜 실력은 "경로를 곱하는 것"이 아니라 겉보기 이익에서 수수료·가스·슬리피지·경쟁을 빼고도 남는 극소수의 기회를 골라내는 것에 있습니다. 대부분의 삼각 기회가 실제로는 남지 않는다는 사실을 아는 것 — 그게 첫 단추입니다.

이 글은 교육·정보 목적이며 투자 권유가 아닙니다. 차익거래를 포함한 모든 자동매매에는 원금 손실 위험이 있으며, 실제 순이익을 보장하지 않습니다. 결과에 대한 책임은 본인에게 있습니다.

댓글

이 블로그의 인기 게시물

한국투자증권 KIS API로 실시간 시세 받기 (WebSocket 실전)

파이썬으로 업비트 API 연동하기 — 시세 조회부터 주문까지 기초

Go로 자동매매 신호봇 프레임워크 설계하기