feat: add get_dynamic_margin_ratio to RiskManager
Made-with: Cursor
This commit is contained in:
@@ -34,3 +34,14 @@ class RiskManager:
|
|||||||
"""매일 자정 초기화"""
|
"""매일 자정 초기화"""
|
||||||
self.daily_pnl = 0.0
|
self.daily_pnl = 0.0
|
||||||
logger.info("일일 PnL 초기화")
|
logger.info("일일 PnL 초기화")
|
||||||
|
|
||||||
|
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))
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ def config():
|
|||||||
"BINANCE_API_SECRET": "s",
|
"BINANCE_API_SECRET": "s",
|
||||||
"SYMBOL": "XRPUSDT",
|
"SYMBOL": "XRPUSDT",
|
||||||
"LEVERAGE": "10",
|
"LEVERAGE": "10",
|
||||||
"RISK_PER_TRADE": "0.02",
|
|
||||||
})
|
})
|
||||||
return Config()
|
return Config()
|
||||||
|
|
||||||
@@ -34,3 +33,51 @@ def test_position_size_capped(config):
|
|||||||
rm = RiskManager(config, max_daily_loss_pct=0.05)
|
rm = RiskManager(config, max_daily_loss_pct=0.05)
|
||||||
rm.open_positions = ["pos1", "pos2", "pos3"]
|
rm.open_positions = ["pos1", "pos2", "pos3"]
|
||||||
assert rm.can_open_new_position() is False
|
assert rm.can_open_new_position() is False
|
||||||
|
|
||||||
|
|
||||||
|
# --- 동적 증거금 비율 테스트 ---
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def dynamic_config():
|
||||||
|
c = Config()
|
||||||
|
c.margin_max_ratio = 0.50
|
||||||
|
c.margin_min_ratio = 0.20
|
||||||
|
c.margin_decay_rate = 0.0006
|
||||||
|
return c
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def risk(dynamic_config):
|
||||||
|
r = RiskManager(dynamic_config)
|
||||||
|
r.set_base_balance(22.0)
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def test_set_base_balance(risk):
|
||||||
|
assert risk.initial_balance == 22.0
|
||||||
|
|
||||||
|
|
||||||
|
def test_ratio_at_base_balance(risk):
|
||||||
|
"""기준 잔고에서 최대 비율(50%) 반환"""
|
||||||
|
ratio = risk.get_dynamic_margin_ratio(22.0)
|
||||||
|
assert ratio == pytest.approx(0.50, abs=1e-6)
|
||||||
|
|
||||||
|
|
||||||
|
def test_ratio_decreases_as_balance_grows(risk):
|
||||||
|
"""잔고가 늘수록 비율 감소"""
|
||||||
|
ratio_100 = risk.get_dynamic_margin_ratio(100.0)
|
||||||
|
ratio_300 = risk.get_dynamic_margin_ratio(300.0)
|
||||||
|
assert ratio_100 < 0.50
|
||||||
|
assert ratio_300 < ratio_100
|
||||||
|
|
||||||
|
|
||||||
|
def test_ratio_clamped_at_min(risk):
|
||||||
|
"""잔고가 매우 커도 최소 비율(20%) 이하로 내려가지 않음"""
|
||||||
|
ratio = risk.get_dynamic_margin_ratio(10000.0)
|
||||||
|
assert ratio == pytest.approx(0.20, abs=1e-6)
|
||||||
|
|
||||||
|
|
||||||
|
def test_ratio_clamped_at_max(risk):
|
||||||
|
"""잔고가 기준보다 작아도 최대 비율(50%) 초과하지 않음"""
|
||||||
|
ratio = risk.get_dynamic_margin_ratio(5.0)
|
||||||
|
assert ratio == pytest.approx(0.50, abs=1e-6)
|
||||||
|
|||||||
Reference in New Issue
Block a user