박스권 24시간 무중단 그리드 봇 알고리즘
업데이트: 2026-10-02
그리드 트레이딩은 특정 가격 범위(박스권) 내에 촘촘한 격자 형태로 매수와 매도 지정가 주문을 배치하고, 시세가 오르내릴 때마다 저가 매수 ➔ 고가 매도를 24시간 무한 반복하여 횡보장에서 안정적인 현금 흐름을 창출하는 대표적인 퀀트 전략입니다.
하지만 거래소 수수료를 고려하지 않은 잘못된 간격 설정으로 인한 잔고 잠식, 그리고 서버 재부팅 시 수십 개의 체결 주문 짝을 잃어버리는 사고를 방어하는 정밀한 상태 복원 엔지니어링을 상세히 다룹니다.
그리드 간격과 거래소 수수료의 손익분기점 공식
초보 퀀트 개발자가 그리드 봇을 가동할 때 가장 많이 하는 실수는 호가 체결 횟수에만 집착하여 그리드 간격을 0.1% 수준으로 지나치게 촘촘하게 설정하는 것입니다.
[ 매매 1회 왕복 수수료 계산 ]
매수 수수료: 0.05%
매도 수수료: 0.05%
왕복 합산 수수료 = 0.10%
[ 수익 시뮬레이션 ]
만약 그리드 간격을 0.15%로 설정했다면:
순이익 = 0.15% (매매차익) - 0.10% (왕복 수수료) = 단 0.05% (슬리피지 발생 시 실제 손실로 전락!)최소 권장 그리드 간격: 수수료의 2.5배 이상
수수료 잠식과 슬리피지 위험을 피하려면, 그리드 간격은 **왕복 거래 수수료율의 최소 2.5배 이상(예: 업비트/바이낸스 수수료 0.1% 시 최소 그리드 간격 0.35%~0.60% 권장)**으로 설정해야 실질적인 복리 수익이 누적됩니다.
등차 vs 등비 그리드 격자 설계
def generate_arithmetic_grid(lower_price: float, upper_price: float, grid_count: int):
"""등차 그리드: 가격 간격이 일정 금액(원/USDT)으로 균등 분할"""
step = (upper_price - lower_price) / grid_count
return [lower_price + i * step for i in range(grid_count + 1)]
def generate_geometric_grid(lower_price: float, upper_price: float, grid_count: int):
"""등비 그리드: 가격 간격이 일정한 백분율(%) 비율로 분할 (장기 추세에 유리)"""
ratio = (upper_price / lower_price) ** (1.0 / grid_count)
return [lower_price * (ratio ** i) for i in range(grid_count + 1)]- 등차 그리드: 1,000만 원~1,200만 원 박스권에서 20만 원 간격으로 균등하게 주문을 걸 때 유리합니다 (단기 횡보장).
- 등비 그리드: 가격 변동 폭이 크고 자산 가치가 우상향할 때 각 격자층마다 동일한 수익률(예: 매 층마다 정확히 0.8% 익절)을 거둘 때 유리합니다.
서버 재시작 시 활성 주문 복원: grid_state.json 영구화
그리드 봇은 거래소에 수십~수백 개의 매수/매도 주문을 동시에 걸어둡니다. 서버가 재부팅되었을 때 메모리 변수만 쓰면 이미 거래소에 나가 있는 주문들의 짝을 잃어버려 중복 매수가 발생합니다.
DashCloud의 **영구 디스크(/app/data/grid_state.json)**에 매 체결 순간마다 상태를 기록하여 1초 만에 복원하는 구조를 구현합니다.
{
"symbol": "BTC/USDT",
"lower_bound": 60000,
"upper_bound": 70000,
"last_updated": "2026-10-02T12:00:00Z",
"levels": [
{ "level": 1, "target_price": 60000, "status": "BUY_FILLED", "order_id": "ord_101" },
{ "level": 2, "target_price": 61000, "status": "SELL_PENDING", "order_id": "ord_102" },
{ "level": 3, "target_price": 62000, "status": "BUY_PENDING", "order_id": "ord_103" }
]
}완성형 프로덕션 그리드 상태 관리자 모듈
import json
import logging
from pathlib import Path
from typing import Dict, Any
logger = logging.getLogger("GridState")
STATE_FILE = Path("/app/data/grid_state.json")
class GridStateManager:
def __init__(self, state_file: Path = STATE_FILE):
self.state_file = state_file
self.state_file.parent.mkdir(parents=True, exist_ok=True)
self.state = self.load_state()
def load_state(self) -> Dict[str, Any]:
"""재부팅 시 디스크에서 이전 그리드 상태 로드"""
if self.state_file.exists():
try:
with open(self.state_file, "r", encoding="utf-8") as f:
data = json.load(f)
logger.info(f"✅ 이전 그리드 상태를 디스크에서 성공적으로 복원했습니다: {len(data.get('levels', []))}개 층")
return data
except Exception as e:
logger.error(f"상태 파일 파싱 실패, 신규 생성합니다: {e}")
return {"symbol": "", "levels": []}
def save_state(self, state: Dict[str, Any]):
"""매 체결 시마다 원자적 디스크 쓰기"""
self.state = state
temp_file = self.state_file.with_suffix(".tmp")
# 쓰기 중단으로 파일이 깨지는 것을 방지하기 위해 임시 파일 후 교체
with open(temp_file, "w", encoding="utf-8") as f:
json.dump(state, f, indent=2, ensure_ascii=False)
temp_file.replace(self.state_file)
logger.debug("그리드 상태가 디스크에 안전하게 동기화되었습니다.")
def update_level_status(self, level: int, status: str, order_id: str):
for item in self.state.get("levels", []):
if item["level"] == level:
item["status"] = status
item["order_id"] = order_id
self.save_state(self.state)
break박스권 상하단 가격 이탈 리스크 대응
가격이 내가 지정한 상한선이나 하한선을 뚫고 한쪽 방향으로 강하게 추세를 형성할 때의 방어 전략입니다:
- 하방 돌파 (급락장) ➔ 손절 스탑로스: 하한선 아래로 떨어지면 모든 매수 그리드가 체결되어 코인을 100% 보유한 상태가 됩니다. 추가 폭락에 따른 자산 손실을 방지하기 위해 하한선 2% 아래 지점에 전량 손절 시장가 매도 주문을 반드시 연동하세요.
- 상방 돌파 (급등장) ➔ 트레일링 그리드: 모든 매도 그리드가 체결되어 코인이 전량 현금화된 경우, 상승 추세를 따라 그리드 범위 전체를 상향 이동시켜 추가 상승 수익을 추적할 수 있습니다.