2026년 11월 11일 · 체결

전략은 테스트를 통과했다. 그런데 거래소가 호가 단위를 바꿨다.

전략은 테스트를 통과했다. 그런데 거래소가 호가 단위를 바꿨다.

화요일 08:00 UTC, 한 암호화폐 거래소가 중간 가격대 무기한 계약의 호가 단위를 바꿨습니다. 우리 베이시스 전략은 이를 알아채지 못했습니다. 시그널은 현물과 선물 사이의 동일한 스프레드를 보고 있었고, 리스크 한도도 그대로였으며, 백테스트 결과도 계속 똑같이 나왔습니다.

모의 거래는 이를 감지했습니다. 주문 어댑터가 매수 지정가를 허용된 가격 중 가장 가까운 낮은 값으로 반올림했습니다. 그 결과 주문은 백테스트에서 모델링한 가격보다 1틱 낮아졌습니다. 시장 가격은 기존 가격에 닿아 시뮬레이션 주문은 체결됐지만, 모의 주문은 그대로 미체결 상태였습니다. 점심 무렵에는 전략의 보유 포지션이 한쪽으로 쏠렸습니다.

처음에는 작은 반올림 버그처럼 보였습니다. 실상은 모델 경계의 문제였습니다. 전략은 가격을 알고 있었지만, 백테스트는 거래소의 가격 그리드를 알지 못했습니다.

우리는 단순한 베이시스 시그널로 거래하고 있었습니다. 선물 프리미엄이 임계값을 넘으면 현물을 매수하고 무기한 계약을 매도하는 전략이었습니다. 기대 베이시스 수익이 작았기 때문에 주문은 지정가로 냈습니다. 몇 틱 차이로 진입 수익이 수수료와 최종 청산 비용을 감당할 수 있을지가 결정될 수 있었습니다.

호가 단위가 바뀌자 무엇이 달라졌을까요?

변경 전 무기한 계약은 0.01 단위 가격을 허용했습니다. 변경 후에는 해당 가격 구간에서 0.05 단위로만 주문을 받았습니다. 시그널은 42,318.03에 매도하는 목표가를 계산했습니다. 기존 규칙에서는 유효한 가격이었지만 새 규칙에서는 유효하지 않았습니다.

거래소는 유효하지 않은 가격을 거부했지만, 우리 어댑터에는 대체 처리가 있었습니다. 매도 가격을 42,318.00으로 낮춰 반올림했지만, 이 역시 유효하지 않았습니다. 두 번째 대체 처리에서 다시 반올림해 이번에는 42,318.05가 되었습니다. 유효한 가격이었지만 매도자에게는 덜 유리한 가격이었습니다. 이제 주문은 모델링한 가격에 매도할 수 없게 됐습니다. 이 코드 경로는 다른 시장을 대상으로 작성된 뒤, 거부 응답을 조용히 가격 조정으로 바꿔버렸습니다.

이 주문 하나에는 서로 다른 두 가지 질문이 얽혀 있었습니다. 첫째, 거래소가 허용하는 가격은 무엇인가? 둘째, 원하는 가격이 그리드에 맞지 않을 때 전략은 어떻게 대응해야 하는가? 첫 번째 질문에는 거래소가 답합니다. 두 번째 질문은 전략이나 실행 정책이 답해야 합니다.

주문 의도가격 그리드 규칙일반적인 반올림 방향달라질 수 있는 점
매수 지정가가격은 호가 단위의 배수여야 함지정가 이하를 유지하도록 내림체결 확률 하락
매도 지정가가격은 호가 단위의 배수여야 함지정가 이상을 유지하도록 올림체결 확률 하락
시장성 지정가가격 제한도 준수해야 함허용 가능한 최대 가격에 따라 달라짐스프레드를 넘는지 여부

모든 상황에 맞는 반올림 규칙은 없습니다. 매수 가격을 내리면 매수자의 가격 제약은 지킬 수 있지만 체결 가능성은 낮아질 수 있습니다. 가격을 올리면 주문이 시장성 주문이 되어 수수료와 시장 충격이 달라질 수 있습니다. 우리가 사용한 베이시스 지정가 진입에서는 주문 가격을 조용히 바꾸는 것이 잘못된 처리였습니다. 목표가는 전략이 정했지만, 어댑터가 그 경제적 조건을 바꿨습니다.

백테스트 결과는 왜 여전히 양호해 보였을까요?

과거 주문 시뮬레이터는 지정가를 연속적인 값으로 처리했습니다. 봉의 저가가 매수 가격에 닿거나 고가가 매도 가격에 닿으면 체결로 계산했습니다. 지정가에 거래된 가격이 있었다고 해서 대기열에서 우리 주문의 순번까지 알 수 있는 것은 아니므로, 이미 지정가 주문에 다소 유리한 근사치였습니다. 하지만 호가 단위 변경으로 더 근본적인 차이가 드러났습니다. 해당 가격에는 애초에 주문을 낼 수 없었습니다.

변경 적용 시점부터 새 그리드를 적용해 동일한 의사결정을 재생했습니다. 여러 체결이 사라졌습니다. 일부 주문은 스프레드를 넘는 가격으로 반올림되어 메이커 수수료 대신 테이커 수수료가 붙었습니다. 그 결과 포지션 경로가 달라졌고, 이후 헤지와 청산도 바뀌었습니다. 메타데이터처럼 보였던 규칙 하나가 전체 거래 순서를 바꿨습니다.

그리고 이 변경은 차트에 숨겨진 돌발 상황이 아니었습니다. 거래소는 적용 시각과 함께 상품 규칙 변경을 공지했습니다. 우리는 시장 데이터를 꼼꼼히 저장했지만, 상품 메타데이터는 시작할 때 갱신하는 캐시에 들어 있었습니다. 백테스트는 과거의 모든 날짜에 오늘의 규칙을 적용했고, 모의 거래는 프로세스를 재시작할 때까지 오래된 규칙을 사용했습니다. 어느 환경도 각 시점에 거래소가 허용한 주문을 제대로 나타내지 못했습니다.

백테스트에서 호가 단위 변경을 어떻게 모델링해야 할까요?

다른 시점별 입력값처럼 유효 기간을 지정해 상품 규칙을 버전별로 관리하세요. 최소한 적용 시각과 주문 유효성을 확인하는 데 필요한 규칙값을 보관해야 합니다. 여기에는 호가 단위, 수량 단위, 최소 수량, 가격 제한 구간이 포함됩니다. 시뮬레이터는 시뮬레이션 의사결정 시점에 유효했던 규칙 집합을 불러와야 합니다.

그다음 주문 처리를 명시적으로 정하세요. 목표가가 유효하지 않다면 주문을 거부하거나, 문서화된 정책에 따라 반올림하거나, 그리드에 맞춰 목표가를 다시 계산해야 합니다. 어떤 처리가 적용됐는지도 기록하세요. 모든 주문을 자동으로 수정하는 백테스트는 특정 실행 정책의 성과를 추정하는 데 유용할 수 있지만, 그 정책을 거래소 체결인 것처럼 감춰서는 안 됩니다.

지정가 주문은 가격이 호가 단위에 맞는 것만으로 체결이 보장되지 않습니다. 시장 가격이 우리 가격을 지나 거래됐는지, 앞에 대기 중인 주문이 얼마나 있는지, 취소가 어떻게 이뤄지는지, 적용받았을 수수료 등급은 무엇인지도 모델링해야 합니다.

검사 두 가지를 추가했습니다. 첫 번째 검사는 생성된 모든 주문을 시점별 상품 규칙으로 확인하고 유효하지 않은 가격이나 수량이 있으면 즉시 오류를 냅니다. 두 번째 검사는 백테스트와 모의 거래 어댑터가 최종 정규화한 주문을 비교합니다. 비교 항목은 매수·매도 방향, 가격, 수량, 주문 유효 기간, 수수료 의도입니다. 서로 다르면 두 결과를 비교 가능한 것으로 간주하지 않습니다.

그 후 화요일의 변경 상황을 다시 재생했습니다. 그리드 변경 이후 백테스트는 더 이상 42,318.03에서 체결됐다고 처리하지 않았습니다. 모의 거래와 시뮬레이션은 유효하지 않은 각 목표가에 대해 같은 결정을 내렸습니다. 주문을 건너뛰는 경우에도 마찬가지였습니다.

시그널은 고장 나지 않았습니다. 거래할 수 있는 대상에 대한 가정이 오래된 상태가 됐습니다. 전략은 새로운 호가 단위에도 대응할 수 있지만, 리서치 시스템이 거래소 규칙을 시뮬레이션하는 시장의 일부로 다뤄야 합니다.

거래소 규칙호가 단위주문 가격 반올림백테스팅모의 거래
← 전체 글