Розробка AI-системи ребалансировки портфеля
Ребалансировка — повернення портфеля до цільових ваг після дрейфу. Найпростіша стратегія: раз в квартал продати те, що зросло, купити те, що впало. AI-підхід оптимізує час, частоту та метод ребалансировки з урахуванням витрат на угоди та податкових наслідків.
Чому час ребалансировки важливий
Calendar Rebalancing (щомісячно/щокварталу) — ігнорує умови ринку:
- На зростаючому ринку постійно продає зросши активи → drag
- На волатильному ринку може ребалансуватись перед розворотом
Threshold Rebalancing (при відхиленні > N%): краще, але все ще статичне правило.
Smart Rebalancing:
- Враховує transaction costs: не ребалансувати, якщо TC > очікуваної користі
- Використовує market timing сигнал: затримує ребалансировку при сильному тренді
- Податкова оптимізація: переважає продавати збиткові позиції (tax-loss harvesting)
Формалізація задачі
Вартість відхилення від цільових ваг:
def drift_cost(current_weights, target_weights, penalty=0.5):
"""
Tracking error через дрейф: annualized vol × drift_magnitude
"""
drift = current_weights - target_weights
drift_variance = drift @ cov_matrix @ drift
return np.sqrt(drift_variance * 252)
Вартість ребалансировки:
def rebalancing_cost(current_weights, new_weights, portfolio_value, tc=0.001):
trades = np.abs(new_weights - current_weights)
return trades.sum() * portfolio_value * tc
Оптимальна ребалансировка: мінімізувати drift_cost + rebalancing_cost + tax_cost.
AI-алгоритм оптимальної ребалансировки
Стохастичне управління (неперервний час): Оптимальна "no-trade zone" — діапазон ваг, в якому не ребалансуємо через TC. Рішення дифференціального рівняння (Almgren, 2005).
RL для ребалансировки:
# State: current_weights, target_weights, market_conditions
# Actions: [partial rebalance 50%, full rebalance, no action]
# Reward: -drift_cost - tc_cost + return_capture
class RebalancingEnv(gym.Env):
def step(self, action):
if action == 2: # full rebalance
cost = rebalancing_cost(self.weights, self.targets)
self.weights = self.targets.copy()
elif action == 1: # partial rebalance
self.weights = 0.5 * self.weights + 0.5 * self.targets
cost = rebalancing_cost(self.weights, self.targets) * 0.5
else: # no action
cost = 0
self.weights = apply_market_returns(self.weights)
reward = portfolio_return - cost - drift_penalty(self.weights, self.targets)
return self.state, reward, done, {}
Tax-Loss Harvesting
Ключова можливість для оподатковуваних рахунків:
Принцип: продавати позиції зі збитками для фіксації tax loss, одночасно замінюючи на корельований актив (уникаючи wash-sale rule в США — 30-денне обмеження).
def tax_loss_harvesting(portfolio, tax_rate=0.20, wash_sale_window=30):
"""
Ідентифікуємо позиції з нереалізованими збитками.
Якщо tax_savings > transaction_costs → harvest.
Замінюємо на корельований актив зі списку substitutes.
"""
harvest_candidates = []
for ticker, position in portfolio.items():
unrealized_loss = position.unrealized_pnl
if unrealized_loss < 0:
tax_benefit = abs(unrealized_loss) * tax_rate
tc = abs(unrealized_loss) * 0.001 # 10 bps TC
if tax_benefit > tc:
harvest_candidates.append({
'ticker': ticker,
'net_benefit': tax_benefit - tc,
'substitute': find_substitute(ticker)
})
return harvest_candidates
Backtesting показує: автоматичний tax-loss harvesting додає 0.5-1.5% after-tax returns щорічно.
Drift Monitoring та триггери
Неперервний моніторинг:
def check_rebalance_triggers(current_weights, target_weights, thresholds):
drift = np.abs(current_weights - target_weights)
# Threshold триггери
if drift.max() > thresholds['single_asset']: # e.g., 5%
return 'REBALANCE_PARTIAL'
if (current_weights / target_weights).max() > thresholds['concentration']: # e.g., 1.5×
return 'REBALANCE_FULL'
# Correlation breakdown триггер (кризис detection)
if regime == 'crisis' and drift.sum() > thresholds['crisis_drift']:
return 'REBALANCE_IMMEDIATE'
return 'NO_ACTION'
Алерти:
- Щоденна перевірка ваг → якщо дрейф > 3% → warning
- Щотижневий звіт: поточні vs. цільові ваги, рекомендації
- Автоматичне виконання при перевищенні critical threshold (конфігурується)
Інтеграція з брокером
Prime Broker / Custody:
- Interactive Brokers API: FIX protocol + REST API для реальних ордерів
- Alpaca: REST API, доступна для автоматичної торгівлі
- Saxo Bank / Dukascopy: FIX + REST для інституційних клієнтів
Workflow:
- Розрахунок поточних ваг (ринкова вартість позиції / NAV)
- AI-рішення: ребалансувати чи ні
- Розрахунок ордерів (net difference, round-lot)
- Відправлення ордерів через брокерський API
- Підтвердження виконання, оновлення book
Часовая шкала: threshold-based ребалансировка з TC-optimization — 2-3 тижні. RL-агент з tax harvesting та broker integration — 8-12 тижнів.







