Разработка бота для ребалансировки портфеля

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1 услугВсе 1306 услуг
Разработка бота для ребалансировки портфеля
Средняя
~3-5 рабочих дней
Часто задаваемые вопросы
Направления блокчейн-разработки
Этапы блокчейн-разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1221
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1163
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    855
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1062
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    828

Разработка бота для ребалансировки портфеля

Ребалансирующий бот поддерживает заданную аллокацию активов в портфеле. Если BTC вырос с 50% до 65% из-за роста цены, бот продаёт часть BTC и докупает другие активы до целевых весов. Это дисциплинированный подход к управлению портфелем: автоматически фиксирует прибыль в выросших активах и покупает подешевевшие.

Стратегии ребалансировки

Calendar rebalancing (по времени)

Ребалансировка по расписанию независимо от отклонений:

# Еженедельная ребалансировка каждый понедельник в 12:00 UTC
schedule = {
    'type': 'calendar',
    'interval': 'weekly',
    'day': 'monday',
    'time': '12:00'
}

Просто и предсказуемо, но может совпасть с неблагоприятным рыночным моментом.

Threshold rebalancing (по отклонению)

Ребалансировка только когда вес актива отклонился от цели на N%:

def needs_rebalancing(
    current_weights: dict,
    target_weights: dict,
    threshold_percent: float = 5.0
) -> bool:
    for asset, target_weight in target_weights.items():
        current = current_weights.get(asset, 0)
        deviation = abs(current - target_weight)
        if deviation >= threshold_percent:
            return True
    return False

Более эффективно: ребалансируем только когда действительно нужно.

Hybrid approach

Проверяем ежедневно, но ребалансируем только при отклонении >5%:

class HybridRebalancer:
    def should_rebalance(self, portfolio: Portfolio) -> bool:
        current_weights = portfolio.get_weights()
        max_deviation = max(
            abs(current_weights[a] - self.target_weights[a])
            for a in self.target_weights
        )
        return max_deviation >= self.threshold

Реализация бота

Расчёт ребалансировочных ордеров

from decimal import Decimal
from typing import dict

class RebalancingCalculator:
    def calculate_trades(
        self,
        current_balances: dict[str, Decimal],
        current_prices: dict[str, Decimal],
        target_weights: dict[str, float]  # сумма = 100
    ) -> list[RebalanceTrade]:
        # Считаем текущую стоимость портфеля
        total_value = sum(
            current_balances[asset] * current_prices[asset]
            for asset in current_balances
        )

        trades = []

        for asset, target_weight in target_weights.items():
            target_value = total_value * Decimal(str(target_weight / 100))
            current_value = current_balances.get(asset, Decimal(0)) * current_prices[asset]

            diff_value = target_value - current_value

            if abs(diff_value) < Decimal('10'):  # Минимум $10 для торговли
                continue

            diff_quantity = diff_value / current_prices[asset]

            trades.append(RebalanceTrade(
                asset=asset,
                side='buy' if diff_value > 0 else 'sell',
                quantity=abs(diff_quantity),
                value_usd=abs(diff_value),
                current_weight=float(current_value / total_value * 100),
                target_weight=target_weight
            ))

        return trades

    def optimize_trade_order(self, trades: list[RebalanceTrade]) -> list[RebalanceTrade]:
        """Сначала продаём, потом покупаем — не нужен дополнительный USDT"""
        sells = [t for t in trades if t.side == 'sell']
        buys = [t for t in trades if t.side == 'buy']
        return sells + buys

Исполнение ребалансировки

class RebalancingBot:
    async def execute_rebalance(self) -> RebalanceReport:
        # Получаем текущее состояние
        balances = await self.exchange.get_balances()
        prices = await self.exchange.get_prices(list(self.target_weights.keys()))

        current_weights = self.calculate_weights(balances, prices)

        if not self.should_rebalance_now(current_weights):
            logger.info("Rebalancing not needed")
            return RebalanceReport(skipped=True)

        trades = self.calculator.calculate_trades(balances, prices, self.target_weights)
        optimized_trades = self.calculator.optimize_trade_order(trades)

        executed = []
        for trade in optimized_trades:
            try:
                order = await self.exchange.place_market_order(
                    symbol=f"{trade.asset}/USDT",
                    side=trade.side,
                    quantity=float(trade.quantity)
                )
                executed.append({
                    'trade': trade,
                    'fill_price': order.fill_price,
                    'actual_quantity': order.filled_quantity,
                    'fee': order.fee
                })
                logger.info(f"Rebalanced {trade.asset}: {trade.side} {trade.quantity:.4f}")
            except Exception as e:
                logger.error(f"Failed to execute {trade.asset} trade: {e}")

        return RebalanceReport(
            executed_trades=executed,
            portfolio_before=current_weights,
            total_cost_usd=sum(t['fee'] for t in executed),
            timestamp=datetime.utcnow()
        )

Целевые аллокации

Пример конфигурации

portfolio:
  target_weights:
    BTC: 40
    ETH: 30
    SOL: 15
    BNB: 10
    USDT: 5  # кэш-подушка

rebalancing:
  strategy: hybrid
  threshold_percent: 5.0
  check_interval_hours: 24
  min_trade_usd: 20

  # Временные ограничения
  rebalance_window:
    days: ['monday', 'tuesday', 'wednesday', 'thursday', 'friday']
    hours_utc: [8, 20]  # только с 8 до 20 UTC

risk:
  max_single_trade_percent: 20  # не более 20% портфеля за раз
  slippage_tolerance: 0.5

Динамические веса

Продвинутый вариант: веса меняются в зависимости от рыночных условий:

def calculate_dynamic_weights(market_data: dict) -> dict:
    """
    Risk-parity: распределяем вес обратно пропорционально волатильности.
    Активы с меньшей волатильностью получают больший вес.
    """
    assets = ['BTC', 'ETH', 'SOL', 'BNB']
    volatilities = {a: market_data[a]['vol_30d'] for a in assets}

    # Обратная волатильность
    inv_vol = {a: 1 / v for a, v in volatilities.items()}
    total_inv_vol = sum(inv_vol.values())

    weights = {a: inv_vol[a] / total_inv_vol * 100 for a in assets}
    return weights

Налоговые соображения

Каждая ребалансировка — это налогооблагаемое событие в большинстве юрисдикций (реализация capital gain или loss). При высокой частоте ребалансировок налоговые обязательства могут превысить выгоду от ребалансировки.

Оптимизация: ребалансировать через убыточные позиции (tax-loss harvesting) — продавать убыточные активы, перекладывая в растущие. Автоматизация tax-loss harvesting — отдельная и востребованная функция для налоговых юрисдикций с детальным crypto reporting (США, Германия).

Ребалансирующий бот — это дисциплина, автоматизированная в код. Исследования показывают: систематическая ребалансировка раз в квартал превосходит buy-and-hold на 0.5-2% в год на волатильных активах за счёт rebalancing premium.