В 08:08 UTC наш сторож сообщил, что 21 контракт INJ лежит без единой защитной заявки, и назвал систему-владельца — удалённую.
В тот же час биржа показывала длинную позицию на 24 контракта и reduce-only заявку на продажу ровно на 24. Сторона была прикрыта целиком. Ничего незащищённого не было, и число 21 вообще не описывало позицию.
Это был остаток: позиция биржи минус та часть, которую в это мгновение могли объяснить наши собственные книги. Секундами раньше каскадом исполнились два тейка, книги догнали в 08:07:05, и в окне между этими двумя событиями разность осела на мёртвом адресе.
Это была одна из трёх ложных тревог того утра. У каждой свой дефект. И все три — один и тот же вопрос, заданный неправильно.
Почему ложная тревога дорога
Канал, который кричит о том, на что нельзя ответить, глушат — а теряется следующей настоящая тревога. Мы за это уже платили: демо-площадка однажды отказала на одном классе эндпоинтов, и владельцу за час ушло больше двадцати одинаковых сообщений «позиция может быть без управления» — про симуляцию.
Поэтому для системы мониторинга доля ложных срабатываний — не косметика. Это то, от чего зависит, прочитают ли когда-нибудь истинное.
Что мы мерили
Журнал тревог (он существует с 18 сентября 2026 года; до этого единственным следом был чат владельца) за утро 19 сентября, 00:41–08:08 UTC.
Полезное свойство здесь в том, что каждая тревога печатает факты, на которых сработала, поэтому ложность проверяема задним числом — ничьей памяти доверять не надо:
- •возраст стороны в момент тревоги против порога отсрочки;
- •была ли защитная заявка снята секундами раньше;
- •была ли сторона уже полностью покрыта reduce-only заявкой.
Три тревоги того утра по этим признакам доказательно ложны. Во всех трёх позицию вёл движок, а наш прибор сверки позиций, спрошенный о тех же системах, отвечал «находок нет».
Три дефекта
1. Свежесть мерилась нашим филлом, а не биржей
06:38 UTC, INJ, 4 контракта. Биржа открыла сторону в 06:36:06 — возраст 114 секунд при пороге отсрочки в 180. Тревога не должна была сработать.
Сработала потому, что на вопрос «сколько этой позиции лет» отвечала наша собственная запись о филле, а записана она была в 06:38:07 — через две минуты после действия биржи. В окне между «площадка открыла» и «мы записали» источник, которого мы спрашиваем, не говорит ничего.
Тейк исполнился в 06:40:05. Позицию вели всё это время.
2. Не учтено окно «движок сам снял защиту и сейчас закрывает»
07:53 UTC, ARB, 18,2 контракта. Тейк снят в 07:52:57.429, рыночная продажа исполнена в 07:53:02.735. Окно в 5,3 секунды — и это самое обыкновенное событие: штатное закрытие цикла, которое неизбежно означает момент без лежащей защиты.
Починка потребовала третьего источника свежести: возраста последней отмены защитной строки. Обратите внимание, насколько узким обязан быть этот признак. «Возраст последнего изменения книг» у системы, тикающей каждые 30 секунд, не истекал бы никогда — гард был бы подавлен навсегда, а это то же самое, что его отсутствие.
3. Вычитание разнородных величин, у остатка назначен владелец
Случай из первого абзаца. Для системы, которая больше не под опросом, остаток считался как позиция биржи минус объяснённое нашими книгами.
Это не два измерения одной величины. Первое — правда площадки на эту миллисекунду, второе — наша запись о ней, которая отстаёт. Вычтите их в момент отставания, и получится число, не описывающее ни того, ни другого.
Но дефект не в вычитании. Дефект в том, что случилось с результатом: необъяснённому остатку назначили владельца — удалённую систему, чьи книги к этим контрактам отношения не имеют.
И здесь продукт противоречит сам себе внутри одного сообщения. Текст тревоги прямо говорит, что владелец не установлен: *«имя системы здесь только адрес двери»*. И всё равно называет систему — и предлагает дверь, закрывающую позицию.
Напечатать остаток как «необъяснённое» было бы честной неопределённостью. Назвать владельца — значит превратить неопределённость в утверждение.
Тем же числом урезалось и покрытие — из него вычиталась наша оценка чужой доли, — поэтому сторона, прикрытая целиком, выглядела непокрытой. Починка проверяет полное покрытие сразу, как только заявки получены, — раньше, чем покрытие уменьшат на эту оценку. Частичное покрытие остаётся находкой: частично прикрытая позиция таковой и является.
В том, КУДА пришлось поставить эту проверку, есть деталь интереснее самой починки. Чтобы судить о покрытии, надо спросить заявки у биржи — а этот вопрос задаётся намеренно последним, по одному на инструмент, и только после того, как всё, что дешевле, уже сошлось на том, что дело неладно. Поставь проверку выше — и сторож опрашивал бы каждую систему каждого счёта на каждом проходе.
То есть порядок проверок здесь продиктован ценой вопроса, а не логикой правила. Починка обязана была встроиться в этот порядок, а не переставить его под себя. Код мониторинга этим полон: сначала идут дешёвые вопросы, значит самый авторитетный ответ приходит последним — и гард, которому нужен авторитетный ответ, обязан жить там, где тот становится доступен, а не там, где его удобнее читать.
Обобщение, которое стоит забрать
Так ломается любая сверка, где одну сторону вычитания берут у площадки, другую из собственных записей, а остаток приписывают третьему лицу.
Ловится двумя вопросами:
- Однородны ли уменьшаемое и вычитаемое — то же ли это число, измеренное в тот же момент тем же источником?
- Кому принадлежит остаток, если честный ответ — «никому»? Если ваша система не умеет напечатать «необъяснённое», она назовёт кого-нибудь.
Второй вопрос обобщается дальше всех. На систему мониторинга постоянно давит требование быть действенной: тревога с именем и кнопкой полезнее тревоги «что-то не сходится». Ровно это давление и превращает честное незнание в уверенный неверный ответ.
Что говорят числа на сегодня и чего они не говорят
Семь тревог этого класса за 40 часов. Три из них — все за утро, наступившее после появления журнала, — доказательно ложны по признакам выше. Остальные четыре, вчерашние, по признаку свежести ложными не выглядят, но проверить их по двум другим признакам мы не можем: свидетельства, которые для этого нужны, тогда ещё не записывались.
Итого: три доказательно ложных из семи, на отрезке, в течение которого класс ещё чинился.
Это не результат «до и после», и выдавать его за таковой мы не станем. Правильный замер обязан быть долей — ложные как часть всех тревог класса, у каждой свой проверяемый признак, — потому что ложные срабатывания здесь липнут к *событиям* (смена цикла, каскад тейков), а частота событий зависит от того, сколько систем торгует. Считайте их в штуках за сутки — и замерите активность флота, а не починку.
Все три дефекта закрыты. Долю замерим после того, как правка постоит достаточно циклов сторожа, чтобы у дроби появился знаменатель, который не стыдно делить.
Границы этого замера
- •Один флот, одно утро, журнал двухдневного возраста. Числа малы, и мы говорим это, а не масштабируем их.
- •Четвёртого признака тогда не существовало. У вчерашних тревог мы можем проверить свежесть, но не покрытие: отсутствие свидетельства — не свидетельство отсутствия.
- •«Доказательно ложна» — наш собственный критерий. Он проверяем кем угодно по тексту самой тревоги, за это мы его и выбрали; выбор всё равно наш.
- •Это не инвестиционная рекомендация, и ничто из перечисленного не является советом торговать.
Если вы держите мониторинг над своими ботами
Три вопроса в порядке того, во сколько обходится неверный ответ:
- Какой источник отвечает на вопрос «сколько этой позиции лет» — площадка или ваша запись о ней? Ваша запись отстаёт ровно на столько, сколько работает путь записи, и это отставание в точности совпадает с моментом, когда только что открытая позиция выглядит брошенной.
- Знает ли ваш гард о моментах, когда ваша же программа снимает защиту намеренно? Закрытие цикла означает окно без лежащей заявки. Если гард не знает, что такое окно существует, он объявит аварией каждое штатное закрытие.
- Что ваша система печатает, когда не может чего-то объяснить? Если ответ «приписывает ближайшему правдоподобному владельцу» — у вас не система мониторинга. У вас система, производящая обвиняемых.