3.9 KiB
3.9 KiB
동적 증거금 비율 설계
날짜: 2026-03-01
목적: 잔고의 50%를 증거금으로 사용하되, 잔고가 늘어날수록 비율이 선형으로 감소하는 안전한 포지션 크기 계산 도입
배경
- 현재 포지션 크기 계산:
risk_per_trade = 0.02(잔고의 2%) × 레버리지 → 명목금액 - 현재 잔고 22 USDT 기준, 최소 명목금액(5 USDT) 보장 로직으로 5 USDT 포지션만 잡힘
- 목표: 잔고의 50%를 증거금으로 활용하여 실질적인 포지션 크기 확보
- 안전장치: 잔고가 늘수록 비율이 자동으로 줄어들어 과도한 노출 방지
아키텍처
데이터 흐름
bot.run()
└─ balance = await exchange.get_balance()
└─ risk.set_base_balance(balance) ← 봇 시작 시 1회
bot._open_position()
└─ balance = await exchange.get_balance()
└─ margin_ratio = risk.get_dynamic_margin_ratio(balance) ← 신규
└─ exchange.calculate_quantity(balance, price, leverage, margin_ratio)
비율 계산 공식
ratio = MAX_RATIO - (balance - base_balance) × DECAY_RATE
ratio = clamp(ratio, MIN_RATIO, MAX_RATIO)
base_balance: 봇 시작 시 바이낸스 API로 조회한 실제 잔고MAX_RATIO: 잔고가 기준값일 때 최대 비율 (기본 50%)MIN_RATIO: 잔고가 아무리 늘어도 내려가지 않는 하한 비율 (기본 20%)DECAY_RATE: 잔고 1 USDT 증가당 비율 감소량 (기본 0.0006)
시뮬레이션 (기본 파라미터 기준)
| 잔고 | 증거금 비율 | 증거금 | 명목금액(×10배) |
|---|---|---|---|
| 22 USDT | 50.0% | 11.0 USDT | 110 USDT |
| 100 USDT | 45.3% | 45.3 USDT | 453 USDT |
| 300 USDT | 33.2% | 99.6 USDT | 996 USDT |
| 600 USDT | 20.0% (하한) | 120 USDT | 1,200 USDT |
변경 파일
1. src/config.py
Config 데이터클래스에 3개 파라미터 추가:
margin_max_ratio: float = 0.50
margin_min_ratio: float = 0.20
margin_decay_rate: float = 0.0006
__post_init__에서 .env 값 읽기:
self.margin_max_ratio = float(os.getenv("MARGIN_MAX_RATIO", "0.50"))
self.margin_min_ratio = float(os.getenv("MARGIN_MIN_RATIO", "0.20"))
self.margin_decay_rate = float(os.getenv("MARGIN_DECAY_RATE", "0.0006"))
2. src/risk_manager.py
메서드 2개 추가:
def set_base_balance(self, balance: float) -> None:
"""봇 시작 시 기준 잔고 설정"""
self.initial_balance = balance
def get_dynamic_margin_ratio(self, balance: float) -> float:
"""잔고에 따라 선형 감소하는 증거금 비율 반환"""
ratio = self.config.margin_max_ratio - (
(balance - self.initial_balance) * self.config.margin_decay_rate
)
return max(self.config.margin_min_ratio, min(self.config.margin_max_ratio, ratio))
3. src/exchange.py
calculate_quantity 시그니처에 margin_ratio 파라미터 추가:
def calculate_quantity(self, balance: float, price: float, leverage: int, margin_ratio: float) -> float:
notional = balance * margin_ratio * leverage
if notional < self.MIN_NOTIONAL:
notional = self.MIN_NOTIONAL
...
기존 risk_per_trade 기반 로직 제거.
4. src/bot.py
run(): 시작 시 잔고 조회 후risk.set_base_balance(balance)호출_open_position():margin_ratio = self.risk.get_dynamic_margin_ratio(balance)호출 후calculate_quantity에 전달
5. .env
MARGIN_MAX_RATIO=0.50
MARGIN_MIN_RATIO=0.20
MARGIN_DECAY_RATE=0.0006
제거되는 설정
RISK_PER_TRADE—.env및Config에서 제거 (동적 비율로 대체)
리스크 고려사항
- 잔고 22 USDT × 50% × 10배 레버리지 = 명목금액 110 USDT 노출 (잔고의 5배)
- 손실 시 잔고가 줄어들면 다음 포지션 크기도 자동으로 줄어드는 자연스러운 안전장치 존재
MARGIN_DECAY_RATE조정으로 감소 속도 제어 가능