День, когда я отключил собственный аварийный выключатель

Где-то в истории моего первого живого торгового бота есть коммит, которым я не горжусь. Он состоит из двух слов. Прямо в работающей системе, чтобы заставить проблему исчезнуть, я залез в защитный механизм, который должен был оберегать счёт, и написал: if False.

Это сработало в том смысле, в каком «работает» выключение датчика дыма. Сигнал прекратился. То, за чем этот сигнал следил, — нет.

Защита, которая никак не переставала срабатывать

В самом начале я сделал одну вещь правильно: я задал живому боту дневной лимит убытка. Если счёт за один день проседал слишком сильно, система должна была остановить торговлю и дождаться меня. Это самый базовый вид предохранителя, и на бумаге это была ровно та дисциплина, которую советуют выстраивать новичку.

Проблема была в том, что он продолжал срабатывать, когда на самом деле ничего не было не так. Каждый раз, когда бот вкладывал деньги в позицию, защита видела, что денежный баланс падает, и читала это как убыток. Так что она делала свою работу, громко и постоянно, останавливая систему, которая не переживала тот убыток, о котором заявляла защита. Сигнализация, которая срабатывает каждые несколько минут без причины, — это не защитная функция; это шум. А шум в конце концов заставляют замолчать.

Хотфикс из двух слов

Так что я заставил её замолчать. Посреди сессии, при работающем боте, я отключил проверку дневного убытка — if False — и отгрузил это. Остановки прекратились. Бот снова торговал свободно. На несколько минут это ощущалось как исправление.

Это не было исправлением. Это было одним из самых опасных решений, что я принял за весь тот проект, и стоит быть точным в том, почему.

Что я на самом деле сделал

Защита срабатывала, потому что её кормили плохой информацией — она путала трату денег на позицию с потерей денег. Это был настоящий баг, и у него было настоящее исправление: научить защиту различать покупку и убыток.

Я этого не сделал. Я выключил защиту. Я отнёсся к проблеме измерения так, будто это проблема защиты, и решил её, убрав защиту. Это инженерный эквивалент того, чтобы вытащить батарейку из датчика дыма, потому что он постоянно пищит. Писк прекращается. Защита тоже.

Отключённая защита — это долг, который накапливается

Вот та часть, которая должна была напугать меня сильнее, чем напугала тогда. До хотфикса моя проблема была всего лишь раздражающей: защита, которая останавливала меня слишком часто. После хотфикса моя проблема стала невидимой и неограниченной — живой бот, торгующий реальными деньгами, вообще без работающего лимита убытка.

У ложных тревог была цена, которую я мог видеть: прерванная торговля. У отключённой защиты была цена, которую я видеть не мог, — до того дня, когда настоящий убыток мог прийти и обнаружить, что на его пути ничего не стоит. Я обменял видимое, переживаемое раздражение на невидимый, неограниченный риск, и сделал это, чтобы красный свет быстрее стал зелёным.

В этом и есть соблазн отключения предохранителя: цена откладывается. Ничего плохого не происходит немедленно. Счёт, если он придёт, приходит позже и весь сразу — в наихудший возможный момент, а именно в тот момент, ради которого защита и существовала.

Правильный ход: чинить защиту, а не глушить её

Правильным ответом был скучный. Задуманный предохранитель был верным, но его входные данные по измерению и учёту были сломаны. Так что чинишь вход: разделяешь сигналы, питающие его, чтобы он реагировал на реальные убытки, а не на обычное движение денег в позиции. Как только защита смогла отличить настоящий убыток от нормальной покупки, она перестала кричать «волки!» — и она была на месте, целая, для тех убытков, которые действительно имели бы значение.

Правило, которое я из этого вынес, почти неловко простое, и теперь я отношусь к нему почти как к абсолютному: ты не продолжаешь торговать с отключённым защитным механизмом. Если защита срабатывает ошибочно, диагностируй её входы и её собственную логику, прежде чем менять или отключать её, — и почини или замени её перед тем, как возобновить, вместо того чтобы работать без защиты.

Весь смысл защиты — в тот момент, когда тебя нет рядом

Есть причина, по которой это важнее для автоматизированной системы, чем почти для всего, чем ты управляешь вручную. Живой бот работает, пока ты спишь, пока ты на работе, пока ты наполовину забыл о его существовании. Его защитные механизмы нужны не для тех моментов, когда ты наблюдаешь, — тогда они тебе едва нужны. Они нужны для моментов, когда тебя нет: резкое движение в 4 часа утра, баг, который срабатывает только в праздник, каскад, который разворачивается за те девяносто секунд, на которые ты отошёл от стола.

Когда ты отключаешь защиту, чтобы сегодня обойти раздражение, ты берёшь в долг под залог именно этих моментов. Ты ставишь на то, что час без присмотра окажется спокойным. Рынок не предлагает эту ставку на честных условиях.

Я держу тот коммит из двух слов в голове как своего рода предупреждающую этикетку. if False — самое лёгкое исправление в мире, и зачастую это вовсе не исправление — это способ превратить проблему, которую ты видишь, в катастрофу, которую ты не видишь.

— Никаких сигналов, никакой доходности, не инвестиционная рекомендация.