From aa5c0afce6f44f8a7794f8738e47eed50d490644 Mon Sep 17 00:00:00 2001 From: 21in7 Date: Sun, 22 Mar 2026 20:58:34 +0900 Subject: [PATCH] fix: use isolated margin to prevent cross-position liquidation risk Add set_margin_type("ISOLATED") call before each position entry. With cross margin, a single bad trade's loss draws from the entire account balance. Isolated margin caps loss to the position's allocated margin only. Binance returns -4046 if already ISOLATED, which is silently ignored. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/bot.py | 1 + src/exchange.py | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/bot.py b/src/bot.py index 3415dc1..15f0c1f 100644 --- a/src/bot.py +++ b/src/bot.py @@ -437,6 +437,7 @@ class TradingBot: return side = "BUY" if signal == "LONG" else "SELL" + await self.exchange.set_margin_type("ISOLATED") await self.exchange.set_leverage(self.config.leverage) await self.exchange.place_order(side=side, quantity=quantity) diff --git a/src/exchange.py b/src/exchange.py index f398066..3795d3e 100644 --- a/src/exchange.py +++ b/src/exchange.py @@ -107,6 +107,21 @@ class BinanceFuturesClient: ), ) + async def set_margin_type(self, margin_type: str = "ISOLATED") -> None: + """마진 타입을 변경한다. 이미 동일 타입이면 무시.""" + try: + await self._run_api( + lambda: self.client.futures_change_margin_type( + symbol=self.symbol, marginType=margin_type + ), + ) + logger.info(f"[{self.symbol}] 마진 타입 변경: {margin_type}") + except BinanceAPIException as e: + if e.code == -4046: # "No need to change margin type." + logger.debug(f"[{self.symbol}] 마진 타입 이미 {margin_type}") + else: + raise + async def get_balance(self) -> float: balances = await self._run_api(self.client.futures_account_balance) for b in balances: