Частичные исполнения: тихий способ терять деньги на торговом боте
Наполовину налитая лимитка оставляет вам позицию, которую никто не планировал, стоп, рассчитанный на позицию, которой нет, и среднюю цену, которую код не пересчитал.
Инженеры Vizanix · об авторе
- РАЗДЕЛ
- Bybit API
- ОПУБЛИКОВАНО
- 2026-08-28
- ГЛАВ
- 6
- ЧИТАТЬ ДАЛЬШЕ
- 3
- ЯЗЫК
- написано на русском
Спросите разработчика, как его бот обрабатывает частичное исполнение, и вы узнаете почти всё, что нужно знать об этом боте. Ответы делятся на три группы: те, кто об этом не думал; те, кто ждёт истечения времени жизни ордера; и те, кто уже обжёгся.
Что происходит на самом деле
Вы ставите лимитную покупку на 10 единиц. Рынок касается вашей цены, забирает 3 и уходит. Теперь у вас 3 единицы в позиции и висящий ордер на 7. Одновременно верны три вещи, и каждая ломает наивного бота:
- У вас незапланированная позиция. Стратегия считала риск на 10 единиц. У вас 3. Расстояние до стопа, посчитанное от задуманного объёма, теперь неверно в безопасную сторону — но частичные take-profit, рассчитанные как доли от 10, неверны так, что попытаются продать единицы, которых вы не покупали.
- У вас остаётся экспозиция к остатку. Эти 7 могут налиться в любой момент, в том числе по цене, где схема уже не работает.
- Ваша средняя цена — не цена лимитки. Если остаток нальётся позже на другом уровне, средняя цена позиции сместится, и каждый уровень, посчитанный от входа — стоп, цели, безубыток — должен сместиться вместе с ней.
Неправильные решения
Ждать TTL. Самый частый подход: дать ордеру дожить своё время жизни и разобраться с той позицией, которая останется в конце. Исполненная часть при этом всё окно остаётся полностью незащищённой. Если TTL — одна свеча, то это одна свеча голого риска на каждом частичном исполнении.
Отменить и забыть. Снять остаток правильно; забыть выставить брекет на исполненную часть — это то, как позиция остаётся вообще без стопа. Именно этот сценарий выглядит потом как «у бота была позиция, о которой я не знал».
Считать брекет от задуманного объёма. Если take-profit посчитаны фиксированными количествами от планируемых 10 единиц, их отправка против позиции в 3 единицы даёт в лучшем случае отказы по reduce-only, а на площадке, которая это позволит, — незапланированный шорт.
Что делаем мы
В нашем исполнителе под Bybit правило записано явно: частично исполненный вход снимает остаток немедленно, не дожидаясь TTL. Дальше исполненная часть обрабатывается по настройке — либо закрывается по рынку, либо получает брекет.
Закрытие по рынку звучит расточительно и часто таковым не является. Если ваша схема рассчитывала получить объём на уровне, а вы получили треть, то сделка, в которой вы сейчас находитесь, — не та сделка, которую выбрала стратегия. Заплатить taker-комиссию за выход из позиции, которую вы не хотели, дешевле, чем нести её со стопом, спроектированным для чего-то другого.
Когда исполненную часть оставляют, всё дальнейшее пересчитывается от фактического объёма и фактической средней цены — никогда от задуманных. Частичные take-profit — это доли того, что существует, а не того, что планировалось.
def on_partial(order, position):
# 1. Сначала убиваем остаток. Пока он может налиться, ничто не безопасно.
exchange.cancel(order.id)
filled, avg = order.cum_exec_qty, order.avg_price
if filled <= 0:
return
if config.reject_partial_entry:
exchange.close_market(position.symbol, filled) # не та сделка, что мы выбирали
return
# 2. Брекет считаем от того, что есть, а не от того, что задумывалось.
stop = level_from(avg, config.sl_k)
legs = [(share * filled, level_from(avg, k)) for k, share in config.tp_legs]
exchange.place_bracket(position.symbol, filled, stop, legs)GTC или FOK
Fill-or-kill снимает проблему, отказываясь от всего, что меньше полного объёма. Это настоящий вариант, и у него настоящая цена: вы платите taker-комиссию и теряете сделки, где полного объёма по вашей цене не было, а большая часть — была.
| GTC лимит | FOK | |
|---|---|---|
| Частичные исполнения | Возможны — надо обрабатывать | Невозможны по построению |
| Сторона комиссии | Maker на висящей части | Taker на весь ордер |
| Пропущенные входы | Меньше | Больше — всё или ничего |
| Сложность кода | Выше | Ниже |
| Подходит для | Терпеливых входов, широких спредов | Узких окон, малого объёма |
Универсально правильного ответа нет. Есть правильный ответ для конкретной стратегии, и он должен быть флагом конфигурации, а не допущением, зашитым в слой исполнения.
Сверка ловит то, что пропустил поток
Уведомления об исполнениях приходят по приватному потоку. Если поток оборвался — см. WebSocket и переподключение — вы можете держать частично исполненную позицию и не знать об этом.
Поэтому сверка после каждого переподключения не опциональна. Сравните позицию и открытые ордера биржи со своими и считайте любое расхождение решённым в пользу биржи. Самое дорогое частичное исполнение — то, о котором бот так и не узнал.
Короткий чек-лист
- Снимать остаток сразу при частичном исполнении, не дожидаясь TTL.
- Пересчитывать среднюю цену и объём по отчётам об исполнении, а не по намерению.
- Считать каждый выход от фактически исполненного объёма.
- Явно решить для каждой стратегии: частичный вход оставляем или отклоняем.
- Сверяться с биржей после каждого обрыва связи.
- Логировать долю частичных исполнений. Её рост означает, что лимитки стоят слишком далеко.
Статья описывает инженерную практику. Это не инвестиционная рекомендация. Vizanix разрабатывает программное обеспечение и не обещает торговую доходность.