Ликвидация при установленном стопе: что должен учитывать бэктест

Рассмотрим длинную позицию. Вход по 100, стоп на 92, расчётная ликвидация на 90. На первый взгляд всё просто: цена обязана пройти 92 раньше, чем дойдёт до 90, значит стоп успеет закрыть позицию.
Так и будет, если стоп и ликвидация следят за одной ценой, рынок движется без разрыва, а закрывающий ордер исполняется сразу. На бирже эти условия выполняются не всегда. Бэктест, который их принимает по умолчанию, может показать выход по стопу там, где реальная позиция была бы ликвидирована.
Один уровень, разные цены
У фьючерсного контракта есть несколько ценовых потоков. Last Price — цена последней сделки. Index Price рассчитывается по внешним рынкам. Mark Price используется для оценки позиции и, на многих биржах, для контроля ликвидации.
Стоп при этом может быть настроен на Last Price. В документации Bybit прямо разобран случай, когда Mark Price достигает уровня ликвидации раньше, чем Last Price успевает активировать стоп. Binance также использует Mark Price в механизме ликвидации фьючерсных позиций.
Пример за одну минуту:
| Параметр | Значение |
|---|---|
| Вход | 100 |
| Стоп по Last Price | 92 |
| Ликвидация по Mark Price | 90 |
| Минимум Last Price | 93 |
| Минимум Mark Price | 89 |
В Last Price уровень 92 не достигнут. Стоп не активирован. В Mark Price пройден уровень 90, поэтому биржа запускает ликвидацию. Здесь нет нарушения порядка: два события смотрят на разные данные.
Самодельный симулятор часто хранит только свечи Last Price и рассчитывает по ним всё остальное. Для обычных входов этого иногда достаточно. Для плечевой позиции такая подмена уже меняет результат.
Срабатывание стопа ещё не означает закрытие позиции
После достижения стоп-цены биржа должна создать и исполнить закрывающий ордер. Это отдельное событие.
Stop-market отправляет рыночный ордер. Он обычно закрывает позицию, но цена исполнения зависит от стакана. На резком движении она может оказаться заметно хуже стоп-цены.
С stop-limit риск другой. Допустим, триггер стоит на 92, а лимит продажи — 91,8. Цена перескакивает с 92,1 на 89. Стоп сработал, лимитная заявка появилась, но продать по 91,8 или выше уже некому. Позиция остаётся открытой.
Распространённая ошибка в бэктесте — считать касание стопа готовой сделкой. В отчёте сразу появляется закрытие по заданной цене, хотя на рынке в этот момент был только триггер. Такая модель особенно сильно приукрашивает стратегии с узкими стопами и большим плечом.
Чего не видно внутри свечи
OHLC-свеча хранит начало периода, максимум, минимум и закрытие. Последовательности сделок внутри неё нет.
По минутной свече можно увидеть, что цена коснулась нужного уровня. Нельзя установить, сколько времени там была ликвидность, какой объём прошёл, успел ли исполниться ордер и как в ту же секунду двигалась Mark Price. Если в одном баре произошло несколько зависимых событий, их порядок приходится восстанавливать по более мелким данным или задавать правилами симулятора.
Переход с часовых свечей на минутные уменьшает неопределённость, но не устраняет её. Для точной проверки защитных ордеров нужны как минимум отдельные потоки Last Price и Mark Price. Для чувствительных к исполнению стратегий могут потребоваться сделки или снимки стакана.
Если таких данных нет, лучше принять консервативный сценарий или пометить сделку как неоднозначную. Автоматически выбирать более прибыльный вариант нельзя: на серии сделок небольшое допущение превращается в заметную прибавку к результату.
Cross и Isolated считаются по-разному
В Isolated риск позиции ограничен выделенной ей маржой. Другой баланс на счёте обычно не должен автоматически отодвигать ликвидацию.
В Cross используется общий пул маржи. На состояние позиции влияют баланс счёта, нереализованный результат других позиций, комиссии, финансирование, открытые ордера и требования maintenance margin.
Поэтому приближённая формула вида «ликвидация равна цене входа минус процент по плечу» годится только для предварительной оценки. В симуляторе приходится воспроизводить правила конкретной биржи и пересчитывать состояние счёта после каждого исполнения и списания.
Отдельный случай — несколько роботов на одном Cross-счёте. Их нельзя тестировать как полностью независимые позиции, если в реальной торговле они используют одну маржу. Убыток одного робота меняет запас прочности остальных.
Как это считать в симуляторе
В симуляторе эти события нужно разделить:
- достижение триггерной цены;
- создание закрывающего ордера;
- частичное или полное исполнение;
- изменение позиции и доступной маржи;
- проверку условий ликвидации;
- остановку торговли, если счёт больше не может продолжать работу.
Для каждого события должен быть указан ценовой поток. Если Mark Price в исторических данных отсутствует, это ограничение стоит записать в параметры прогона. Подмена её Last Price должна быть явным режимом, а не незаметной деталью движка.
Ликвидацию также не стоит записывать как обычный выход стратегии. В статистике это отдельная причина закрытия. Иначе робот, который регулярно доводит позицию до принудительного закрытия, может выглядеть как стратегия с необычно широким стопом.
Одной прибыли и просадки в отчёте мало. Нужны число ликвидаций, сработавшие, но не исполненные защитные ордера, фактическое проскальзывание, минимальный запас маржи и неоднозначные свечи. По ним видно, какая часть результата получена стратегией, а какая зависит от правил исполнения в симуляторе.
Если стоп и ликвидация рассчитаны по одной цене, стоп стоит выше, рынок не перепрыгнул уровень, а рыночный ордер исполняется без задержки, стоп действительно должен сработать первым. Любой другой результат требует объяснения. Обычно причина находится в ценовом потоке, типе ордера, исполнении или расчёте маржи.

