Разработка системы ребалансировки LP-позиций
LP-провайдер на Uniswap v3 с позицией в диапазоне $1800-$2200 для пары ETH/USDC. ETH уходит на $2500. Позиция полностью конвертировалась в USDC, перестала зарабатывать комиссии. Без ребалансировки она так и лежит мёртвым грузом — комиссии не капают, а IL зафиксирован. Ручной мониторинг и пересоздание позиции в нужный момент — задача, которую стоит автоматизировать сразу, как только количество позиций превышает одну.
Когда и как ребалансировать
Триггеры для ребалансировки
Три основных подхода к определению момента ребалансировки:
Price-based trigger. Ребалансировка, когда цена достигает границы диапазона или заходит в зону N% от границы. Простой, но реагирует только на ценовое событие. Подходит для большинства случаев.
Time-based trigger. Ребалансировка каждые N часов независимо от цены. Создаёт предсказуемые gas расходы, но часто делает ненужную работу.
Fee-accumulation trigger. Ребалансировка, когда накопленные несобранные комиссии превышают стоимость газа на ребалансировку умноженную на K (например, K=5). Это экономически оптимальный подход, но требует отслеживания tokensOwed из Uniswap v3 Position Manager.
На практике используем комбинацию: price-based как основной триггер, fee-accumulation как проверка целесообразности перед исполнением.
Стратегии выбора нового диапазона
После выхода цены из диапазона нужно выбрать новый. Варианты:
Fixed width centered on current price. Самое простое: новый диапазон ±N% от текущей цены. Ширина N зависит от волатильности актива: для ETH/USDC оптимально 10-20%, для стейблкоин-пар — 0.1-0.5%.
Volatility-adjusted width. Ширина диапазона = k * ATR(period), где ATR — Average True Range за период. При высокой волатильности диапазон шире (меньше ребалансировок, выше IL-риск), при низкой — уже (больше ребалансировок, выше комиссии). ATR считается off-chain по историческим ценам.
Asymmetric range. При трендовом рынке диапазон смещается в сторону тренда: [currentPrice * 0.95, currentPrice * 1.15] при восходящем тренде. Требует определения тренда — например, через отклонение от скользящей средней.
Технические проблемы ребалансировки
Gas optimization при remove + add liquidity
Одна операция ребалансировки в Uniswap v3 состоит из:
-
collect()— сбор накопленных fee -
decreaseLiquidity()— вывод ликвидности -
collect()повторно — получение оставшихся токенов - Swap для восстановления нужного ratio
-
mint()— создание новой позиции
Итого 4-5 транзакций при раздельном исполнении. Через multicall в NonfungiblePositionManager можно упаковать несколько вызовов в одну транзакцию. Это снижает gas на ~40% и убирает риск изменения состояния между шагами.
Swap для восстановления ratio — отдельная проблема. После вывода ликвидности у вас может быть 80% в токен A и 20% в токен B, а для нового диапазона нужно 50/50. Своп меняет соотношение, но двигает цену в пуле (slippage) и даёт MEV-ботам возможность для сэндвича.
Защита: minAmountOut в swap с допустимым slippage 0.3-0.5%. Или использование flash loans для атомарного ребалансирования без промежуточного свопа.
Минимизация impermanent loss при ребалансировке
Каждая ребалансировка фиксирует текущий IL. Если цена вернётся к начальному уровню — без ребалансировки IL исчезает, с ребалансировкой он зафиксирован. Слишком частые ребалансировки при боковом рынке = накопленный IL без достаточного дохода от комиссий.
Backtest стратегии на исторических данных перед деплоем — обязательный шаг. Для ETH/USDC на Arbitrum берём данные из Uniswap v3 subgraph за 6-12 месяцев, симулируем разные стратегии ребалансировки, сравниваем net APY после вычета gas и IL.
Keeper инфраструктура
Автоматические триггеры реализуются через:
Chainlink Automation. Контракт реализует интерфейс AutomationCompatibleInterface с функцией checkUpkeep (off-chain расчёт, нужна ли ребалансировка) и performUpkeep (on-chain исполнение). Оплата в LINK. Надёжно, но есть задержка до нескольких блоков.
Gelato Network. Аналогично, но с более гибкой логикой условий и оплатой в нативном токене. Поддерживает Web3 функции как триггеры (чтение из контракта).
Собственный keeper bot. Node.js/TypeScript сервис с cron или event-driven логикой. Дешевле по операционным расходам, но требует собственной инфраструктуры и мониторинга uptime.
Для production — Chainlink Automation или Gelato для надёжности. Собственный bot как fallback и для дополнительной логики (оценка целесообразности с учётом gas price).
Контракт ребалансировщика
interface IRebalancer {
function rebalance(
uint256 tokenId,
int24 newLowerTick,
int24 newUpperTick,
uint256 minAmount0,
uint256 minAmount1
) external returns (uint256 newTokenId);
function shouldRebalance(uint256 tokenId)
external view returns (bool, int24, int24);
}
shouldRebalance — view-функция для keeper checkUpkeep. Проверяет текущую цену относительно диапазона позиции и возвращает новые тики если нужна ребалансировка.
Доступ к функции rebalance — только owner позиции или авторизованный keeper. Никаких публичных функций изменения позиции.
Ориентиры по срокам
Базовая система ребалансировки для одной позиции с Chainlink Automation — 5 рабочих дней. Включает: контракт ребалансировщика, off-chain стратегию выбора диапазона, keeper setup и тесты на форке mainnet.







