Это история про то, как я почти поверил в собственные расчёты, и про то, что меня остановило. Никакой мистики — просто хороший урок о том, как цифры врут, когда не задаёшь им правильных вопросов.
Сразу оговорюсь: я ничего не продаю и никуда не зову. Это разбор собственной ошибки, который, надеюсь, окажется полезен не только тем, кто интересуется биржей.
Я пишу программы, которые проверяют торговые идеи на истории. Работает это так: берёшь правило — например, «покупать, когда выполнилось вот такое условие», — и прогоняешь его по котировкам за несколько лет. Программа считает, что было бы, если бы ты все эти годы механически следовал правилу. На выходе — доходность, число сделок, максимальный убыток и прочая статистика.
Смысл в том, чтобы отсеивать плохие идеи, не теряя на них реальных денег. Большинство идей оказываются плохими, и это нормально: в том и работа.
Одну такую идею я проверял на акциях. Она показала скромный, но осмысленный результат. Дальше полагается проверить, работает ли она на других инструментах — если правило отражает что-то настоящее про рынок, оно должно хоть как-то держаться и в других местах. Если работает только на том, на чём его придумали, — скорее всего, ты просто подогнал его под конкретные данные.
Я взял десять биржевых инструментов и прогнал по ним ту же самую программу с теми же настройками. Ничего не подкручивал — в этом весь смысл проверки.
Девять из десяти
Результат вышел честный и скучный: на девяти инструментах идея не сработала. Где-то небольшой минус, где-то около нуля. Вывод очевидный — на этом типе инструментов моё правило не живёт.
А на десятом программа выдала +84%.
Для контекста: остальные девять дали от минус двадцати процентов до плюс одного. И тут — восемьдесят четыре. Причём по всем формальным признакам результат выглядел не просто хорошо, а образцово. Сорок пять сделок — не три штуки, на которых можно списать на случайность. Почти половина прибыльных. Средний выигрыш вдвое больше среднего проигрыша.
Если бы я хотел себя обмануть, момент был идеальный. Все нужные цифры на месте. Можно писать пост, что нашёл работающую систему.
Что меня смутило
Смутила ровно одна вещь: почему именно здесь?
Девять инструментов вели себя одинаково — никак. Десятый выстрелил вчетверо сильнее всего, что я вообще видел за это исследование. Так не бывает без причины. Либо этот инструмент чем-то принципиально отличается, либо я смотрю не на прибыль, а на ошибку.
Я полез разбирать. Ниже — четыре вещи, которые я нашёл. Каждая по отдельности уже приговор.
Улика первая: всю прибыль сделали пять сделок
Сорок пять сделок, суммарно +81%. Убираю три лучшие — остаётся +23,7%. Убираю пять лучших — остаётся +1,0%.
То есть сорок сделок из сорока пяти в сумме не заработали ничего. Весь результат — пять счастливых случаев.
Дальше я посмотрел медианную сделку. Медиана — это «средняя по середине»: выстраиваешь все сделки по результату и берёшь ту, что ровно посередине. В отличие от обычного среднего, её нельзя перекосить парой рекордов.
Медианная сделка оказалась убыточной: −0,34%.
Типичная сделка в этой «прибыльной системе» теряла деньги. Прибыль делали исключения. Это как хвастаться средней зарплатой в компании, где директор получает миллион, а сорок сотрудников — по двадцать тысяч.
Улика вторая: треть убыточных сделок закрылась в плюс
Вот это уже не про статистику, а про физику происходящего.
Объясню механику. Когда открываешь сделку, ставишь «стоп-лосс» — автоматический выход, если цена пошла против тебя. Это защита: страховка, ограничивающая убыток. Ключевое свойство стоп-лосса в том, что он фиксирует убыток. Такова его функция. Сработавший стоп — это по определению проигранная сделка.
В моих результатах из тридцати четырёх сработавших стопов одиннадцать закрылись в плюс. Причём две такие «убыточные» сделки принесли +11,7% и +9,96% и попали в ту самую пятёрку лучших.
Это невозможно. Как «я упал и в результате оказался выше».
Разгадка в том, как устроены цены на неактивном рынке. Обычно цена движется более-менее плавно: 100, 100.5, 101. Если мой стоп стоит на 99, цена по пути к 98 обязательно пройдёт через 99, и я выйду примерно там.
Но если сделок мало, цена не идёт — она прыгает. Была 100, следующая сделка вообще 105. Между ними ничего не было, потому что никто не торговал. И моя программа честно рассуждает: «стоп на 99 пробит? Да. Значит, выходим по первой доступной цене». А первая доступная — 105.
Программа записала прибыль. В реальности такой цены в тот момент на рынке не существовало — точнее, существовала, но по ней бы никто не продал.
Улика третья: пятиминутные данные не были пятиминутными
Я работал с данными, где каждая строка — это пять минут торгов. Открытие, максимум, минимум, закрытие за пятиминутку.
Решил проверить, действительно ли соседние строки отстоят друг от друга на пять минут.
Оказалось, медианный интервал между соседними «пятиминутками» — 25 минут. Треть пар разнесена больше чем на час. А максимальный разрыв между двумя соседними строками — 813 часов. Тридцать четыре дня.
Причина простая: строка в таких данных появляется только тогда, когда прошла хоть одна сделка. Нет сделок — нет строки. Инструмент торговался так вяло, что часами и днями не происходило вообще ничего, и эти пустоты просто выпали из таблицы, сомкнув края.
Теперь главное. Моё правило искало определённую фигуру из трёх идущих подряд отрезков времени. Логика была в том, что за пятнадцать минут произошло что-то резкое.
А программа честно брала три подряд идущие строки — и находила «резкое движение» там, где между строками лежал месяц. Ну разумеется, за месяц цена меняется. Это не открытие, это календарь.
Мой детектор ловил не рыночную ситуацию. Он ловил дырки в торгах.
Улика четвёртая: рынка там просто нет
Последнюю проверку я делаю теперь всегда первой. Померил, сколько вообще было торгов.
Медианный объём — 2 контракта за отрезок. Два. Не две тысячи.
Из всего времени, когда биржа была открыта, сделки шли лишь в 5,5%. Для сравнения, у нормально торгуемых инструментов из той же проверки — 85%.
Это значит, что моя гипотетическая заявка была бы не участником рынка, а всем рынком целиком. Купить по красивой цене из расчёта не вышло бы — не у кого. Любая реальная попытка сдвинула бы цену против меня сильнее, чем вся заложенная прибыль.
Я вычислял доходность торговли в месте, где торговать физически не с кем.
Что в итоге
Результат я выкинул. Записал в отчёт отдельным разделом с пометкой, что это артефакт, и вывел правило, которое теперь проверяется автоматически до всего остального: сначала смотрим, был ли там вообще рынок, и только потом — на доходность.
Программа не врала и не содержала ошибки. Она добросовестно посчитала ровно то, что я просил. Просто я задал ей вопрос «сколько бы я заработал», забыв спросить «а можно ли было там вообще торговать».
Самое неприятное осознание — задним числом. Если бы этот инструмент попался мне первым, а не десятым, я бы, скорее всего, поверил. Не с чем было бы сравнивать. Меня спасло не чутьё, а то, что девять предыдущих дали честный ноль, и на их фоне восемьдесят четыре процента выглядели странно. Повезло с порядком проверки, а не с проницательностью.
Зачем я это рассказываю
Ошибка тут не про биржу. Она общая, и встречается всюду, где считают по данным.
Красивый результат — повод для подозрения, а не для радости. Если что-то резко выбивается из общего ряда, первая гипотеза — ошибка в измерении, а не открытие. Проверка на «слишком хорошо» должна быть такой же обязательной, как проверка на «слишком плохо».
Среднее прячет структуру. Пять выбросов из сорока пяти нарисовали +84% при том, что типичный случай был убыточным. Всегда стоит смотреть, не сделали ли весь результат единицы наблюдений.
Отсутствие данных — тоже данные. Пустые места в таблице не были помечены как пустые. Строки просто сомкнулись, и程序 приняла соседство в таблице за соседство во времени. Пропуски имеют свойство выглядеть как обычные значения, если их специально не искать.
Невозможный результат — самый ценный. Прибыльные стоп-лоссы были подарком: событие, которое не может произойти при исправной работе, указывает на поломку точнее любой статистики. Такие вещи надо не объяснять, а расследовать.
Собственно, всё. Идея, которую я проверял, на этих инструментах не работает — девять честных нулей это и показали. А десятый научил меня большему, чем все остальные вместе.
Дополнение. В тексте выше опечатка — «程序» вместо «программа», не заметил при вычитке. Приношу извинения, исправить в опубликованном виде уже не могу, но пусть остаётся как есть — за честность.