Разработка торгового бота для маржинальной торговли
Маржинальная торговля на спотовых рынках (margin trading) отличается от perpetual futures: вы берёте взаймы реальные активы у биржи или других пользователей, торгуете ими, и платите процент за заимствование. Это позволяет открывать позиции больше имеющегося капитала и торговать в шорт на спотовом рынке.
Отличия margin trading от futures
| Параметр | Margin Trading | Futures |
|---|---|---|
| Актив | Реальный (BTC, ETH) | Контракт |
| Плечо | 3x–10x (обычно) | До 125x |
| Funding | Ежедневный % за займ | Funding rate каждые 8h |
| Expiration | Нет | Нет (perpetual) |
| Ликвидация | Есть | Есть |
Cross vs Isolated Margin
Cross Margin — весь баланс маржинального аккаунта является залогом для всех позиций. Одна позиция может использовать margin другой. Ликвидация одной позиции не обязательно означает потерю всего.
Isolated Margin — каждая позиция имеет свою изолированную маржу. Ликвидация одной позиции не затрагивает другие. Более предсказуемый риск.
Архитектура margin-бота
class MarginTradingBot:
def __init__(
self,
exchange,
symbol: str,
margin_type: str = 'isolated', # 'cross' или 'isolated'
max_leverage: float = 3.0,
):
self.exchange = exchange
self.symbol = symbol
self.margin_type = margin_type
self.max_leverage = max_leverage
async def borrow_and_buy(
self,
quantity: Decimal,
quote_asset: str = 'USDT',
) -> dict:
"""Занимаем USDT и покупаем BTC"""
current_price = await self.get_current_price()
borrow_amount = quantity * current_price
# Шаг 1: Занимаем quote asset
borrow_result = await self.exchange.borrow_margin(
asset=quote_asset,
amount=float(borrow_amount),
symbol=self.symbol, # для isolated margin
)
# Шаг 2: Покупаем base asset
order = await self.exchange.create_order(
symbol=self.symbol,
type='market',
side='buy',
amount=float(quantity),
params={'marginMode': self.margin_type},
)
return {
'borrow_amount': borrow_amount,
'borrow_asset': quote_asset,
'order': order,
}
async def sell_and_repay(self, quantity: Decimal, quote_asset: str = 'USDT'):
"""Продаём BTC и погашаем займ"""
# Шаг 1: Продаём
order = await self.exchange.create_order(
symbol=self.symbol,
type='market',
side='sell',
amount=float(quantity),
params={'marginMode': self.margin_type},
)
fill_price = Decimal(str(order['average']))
received_quote = quantity * fill_price
# Шаг 2: Погашаем займ
loan_info = await self.exchange.fetch_margin_loan(
asset=quote_asset,
symbol=self.symbol,
)
repay_amount = min(received_quote, Decimal(str(loan_info['amount'] + loan_info['interest'])))
await self.exchange.repay_margin(
asset=quote_asset,
amount=float(repay_amount),
symbol=self.symbol,
)
profit = received_quote - repay_amount
return {'profit': profit, 'repaid': repay_amount}
async def short_sell(self, quantity: Decimal, base_asset: str = 'BTC'):
"""Занимаем BTC и продаём (шорт)"""
# Занимаем base asset
await self.exchange.borrow_margin(
asset=base_asset,
amount=float(quantity),
symbol=self.symbol,
)
# Продаём заимствованный актив
order = await self.exchange.create_order(
symbol=self.symbol,
type='market',
side='sell',
amount=float(quantity),
params={'marginMode': self.margin_type},
)
return order
async def close_short(self, quantity: Decimal, base_asset: str = 'BTC'):
"""Покупаем обратно и возвращаем займ (закрытие шорта)"""
# Покупаем base asset для возврата займа
order = await self.exchange.create_order(
symbol=self.symbol,
type='market',
side='buy',
amount=float(quantity),
params={'marginMode': self.margin_type},
)
# Погашаем займ
await self.exchange.repay_margin(
asset=base_asset,
amount=float(quantity),
symbol=self.symbol,
)
return order
Управление маржинальным балансом
class MarginHealthMonitor:
CRITICAL_MARGIN_RATIO = 1.1 # близко к ликвидации
WARNING_MARGIN_RATIO = 1.3
async def get_margin_health(self, symbol: str) -> dict:
account = await self.exchange.fetch_margin_account()
for asset_info in account.get('userAssets', []):
if asset_info['asset'] in symbol:
equity = Decimal(asset_info['netAsset'])
borrowed = Decimal(asset_info['borrowed'])
interest = Decimal(asset_info['interest'])
total_debt = borrowed + interest
if total_debt > 0:
margin_ratio = equity / total_debt
return {
'equity': equity,
'borrowed': total_debt,
'margin_ratio': margin_ratio,
'health': 'CRITICAL' if margin_ratio < self.CRITICAL_MARGIN_RATIO
else 'WARNING' if margin_ratio < self.WARNING_MARGIN_RATIO
else 'OK',
}
return {'health': 'NO_POSITION'}
async def monitor_loop(self):
while True:
health = await self.get_margin_health(self.symbol)
if health['health'] == 'CRITICAL':
logger.critical(f"Margin ratio critical: {health['margin_ratio']:.2f}")
await self.emergency_deleverage()
elif health['health'] == 'WARNING':
logger.warning(f"Margin ratio warning: {health['margin_ratio']:.2f}")
await self.send_alert(f"Margin health: {health}")
await asyncio.sleep(30)
Стоимость заимствования
Маржинальный бот должен учитывать ежедневный процент за займ. На Binance это ~0.02–0.05% в день в зависимости от актива и объёма. При 10x плече на месяц это 0.6–1.5% только на процентах. Стратегия должна генерировать доходность выше стоимости займа.
def calculate_borrowing_cost(
borrowed_amount: Decimal,
daily_rate: Decimal,
days: int,
) -> Decimal:
"""Компаундный расчёт стоимости заимствования"""
return borrowed_amount * ((1 + daily_rate) ** days - 1)
Маржинальный бот — более сложная задача, чем спотовый, но значительно менее рискованная чем высоколеверажный futures-бот. Разумное плечо 2–3x с правильным risk management — хороший баланс между возможностями и рисками.







