У нас уже есть WordNet и ImageNet, и вот наконец настало время MarketNet. Как трейдерам нам нужно отслеживать различные классы активов на разных временных интервалах. Зрительные способности человека невероятны, но мы устаем, становимся невнимательными и предвзятыми. И вот я подумал, что было бы неплохо, если бы у трейдеров была система поддержки принятия решений, непредвзятое второе мнение для подтверждения наших решений. На создание MarketNet меня вдохновили некоторые вопросы, которыми я задавался уже довольно долгое время:
Способна ли нейронная сеть идентифицировать рынок? Это снапшот фьючерсов E‑Mini S&P 500 или акций GOOGL?
Способна ли сеть предсказывать будущие ходы? Очевидно же, что на этом можно заработать? Но как трейдеры, мы знаем, что то, что очевидно, очевидно неправильно [Дракенмиллер].
Способна ли сеть определять прибыльные сделки?
Ниже приводится краткое описание экспериментов, которые я провел, работа над этим проектом, начиная с 27.09.2022.
Первый вопрос, который у меня возник при работе с данными, — способна ли модель идентифицировать рынок? Очевидно, что мы знаем, за каким рынком мы сейчас наблюдаем и где торгуем, но действительно ли они все фундаментально отличаются?
model = tf.keras.Sequential([
tf.keras.layers.Rescaling(1./255),
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(num_classes)
])
В качестве сетапа здесь используется простенькая базовая модель из руководства по загрузке и предварительной обработке TensorFlow. Здесь нет ничего сложного, я растянул размер входного изображения до квадрата с шириной в 200 пикселей и увеличил количество эпох, чтобы выявить переобучение. Данные хранились в отдельных папках для каждого рынка. Первый эксперимент проводится в рамках класса активов акций, включая ES, NQ, YM и RTY.
Модель оказалась плохой и начала переобучаться, что в итоге и погубило ее. Затем я решил попробовать ту же идею для класса активов с процентными ставками.
Определение процентных ставок (ZB, ZN или FGBL) также не дало впечатляющих результатов, и в конечном итоге также началось переобучение.
Я попробовал перебрать различные классы активов: пытаемся определить рынок с целями ES, RTY, ZB и FGBL.
В целом, в области идентификации активов я не увидел ничего интересного, но мы пока просто разогреваемся.
Теперь давайте разделим изображения на дни покупки и дни продажи. Любое положительное изменение за день (Close — Open) считается покупкой, и наоборот.
Используемые здесь данные предоставлены IB TWS API и собираются с 2020 года. Также важно отметить, что генерация изображений занимает много времени из‑за множества операций, связанных с Matplotlib.
Цена открытия определяется как цена открытия CME, а цена закрытия — как цена закрытия NYSE. Бары здесь 30-минутные.
И вот, модель способна обнаружить сторону за период в один день. Ранняя остановка здесь не имеет решающего значения, так как модель хоть по факту и переобучается, но сохраняет стабильные метрики. По большому счету, все в порядке. Это впечатляет, но, очевидно, не имеет абсолютно никакой ценности. Нам не нужно констатировать очевидное, и мы знаем, как определить тренд за день (особенно после окончания торгового дня), нам нужно больше.
Хорошо, теперь давайте попробуем построить что‑то более полезное, чтобы можно было бы реально использовать в ежедневной торговле. Предположим, у вас есть преимущество, система правил, которая получает на вход текущее состояние рынка и выдает предлагаемые варианты действий. Вы должны купить, продать или не предпринимать никаких действий. В самом базовом виде это и есть торговая стратегия. Теперь давайте повысим эффективность принятия решений, получив дополнительную пару глаз в виде модели машинного обучения.
Проанализировав исторические данные, можно смоделировать результаты ваших преимуществ (сделок). По сути, у нас есть четыре переменные класса (цели). Первая цель — это четкий сигнал на покупку, при котором STP (стоп‑лосс) не сработал. Дополнительный класс — это тот же сигнал на покупку, когда STP сработал, и мы потеряли деньги. В некотором смысле это похоже на обнаружение спама для обеих (возможных) сторон сделки. То же самое касается и стороны продажи: истинные сигналы на продажу, которые (возможно) принесут прибыль, и сигналы на продажу, которые пробьют STP и (наверняка) потеряют деньги.
Важно отметить, что положительный результат не означает, что мы точно заработали деньги, и не означает, что мы не потеряли деньги. Все, что он пытается предсказать, — это то, что сделка не попала в STP и точно потеряла деньги. Это очень важный нюанс в постановке задачи. Если предположить, что у вас есть какое‑либо преимущество, то при достаточной выборке (торговля, сделки, продвижение) вы должны быть в порядке (зарабатывать деньги). Все, что мы пытаемся здесь сделать, — это, по сути, улучшить само преимущество как таковое. Поскольку мы обязаны совершать каждую сделку, моделирование помогает отфильтровать только хорошие.
Нужно сказать несколько слов о парадоксе, представленном здесь. Чтобы стать стабильно прибыльным трейдером, вы должны иметь преимущество (edge) и торговать на его основе, как робот. Преимущество — это торговая система, которая при хорошей выборке точно приносит деньги. Ментальная выносливость и фанатичное следование системе — вот где терпит неудачу подавляющее большинство. Торговые системы найти трудно, но гораздо труднее не возиться с ними и не менять их, когда у вас начнется полоса неудач (а она обязательно начнется). Но опять же, мы пытаемся построить модель, которая по сути меняет нашу стратегию и позволяет нам отклоняться от нее время от времени, что, как мы только что упомянули, является большим таким знаком стоп для того, чтобы стать профессионалом.
Позвольте мне уточнить. Это одновременно и правильно, и нет. До тех пор, пока мы не меняем правила системы, можно вводить систематическую осторожность в процедуру исполнения. Например, даже если у вас есть сигнал на вход, но через пару минут начнется какое‑нибудь CPI / GDP / FOMC, то лучше его пропустить. Лучше пожертвовать этими деньгами, чем войти без ликвидности и с хаотичным поведением рынка до и после этого события (просто попробуйте сделать это один раз чисто для опыта). Моделирование, которое мы проводим, — это систематическое принятие решения о том, когда не стоит заключать сделку, поэтому оно приемлемо и даже поощряется. Я думаю, что мы все понимаем, что крупные организации уже много лет работают над чем‑то подобным.
Если вы хотите прочитать больше о том, что можно сделать, чтобы обрести преимущество, предлагаю вам ознакомиться с моими предыдущими статьями:
Уроки, которые я усвоил за год ежедневного трейдинга — очень подробное описание взлетов и падений моих первых попыток в трейдинге.
Трейдинг как основной источник дохода — еще одно подробное описание взлетов и падений моих последующих попыток.
Первым испытанием было обучение на всех целях вместе. Модель была явно неудачной и непрактичной.
Я решил попробовать построить модель только для стороны покупки: покупать или не покупать? Для этого потребуется две модели (для каждой стороны), но поскольку мы точно знаем, какую сторону собираемся занять, можно провести различие между моделями. Очевидно, что теперь задача намного проще. Хоть это и компромисс, но мы можем себе его позволить.
Показатели приемлемые, но требуется ранняя остановка, иначе начинается переобучение.
Теперь давайте попробуем отличить (потенциально) прибыльный сигнал на продажу от (наверняка) убыточного сигнала на продажу.
Опять же, производительность приемлемая, но требуется ранняя остановка.
Пока что у нас слишком много шума и ненадежных моделей.
Важно сказать еще несколько слов о генерации синтетических данных. Некоторые состояния рынка имеют очень маленькое количество баров (сигнал на покупку появляется сразу после открытия CME). Другие сигналы содержат почти все бары за день (сигнал на продажу за 1 час до закрытия Нью‑Йоркской фондовой биржи). Очевидно, что генерация изображений с разной шириной требует некоторой корректировки (чтобы они были квадратными). Поэтому мы рассчитываем определенный диапазон для конкретного состояния рынка и добавляем дополнительные столбцы, чтобы компенсировать рынки с малым количеством баров. Рынки с большим количеством баров и/или меньшим диапазоном естественным образом генерируют квадратные изображения и иногда даже не требуют никаких корректировок. Но зачем вообще этим заниматься? Потому что иногда важно проверять все вручную, а мы предпочитаем сохранять синтетические данные в унифицированном похожем формате: квадраты, черное и белое и т. д.
Еще одно замечание о статистике и трейдинге: вы, вероятно, знакомы с двумя подходами/школами/методологиями — фриквентисты против байесовцев. В трейдинге необходимо и то, и другое: вам нужен классический статистический анализ для определения риска и байесовский анализ для оценки вашего преимущества. ATR основан на классической статистике. Зональный трейдинг [Марк Дуглас] и знаменитый эксперимент «20 сделок» — это классный байесовский анализ. Инь и янь трейдинга — это сбалансированное и правильное использование этих двух подходов.
Да, и не забудьте про остальное:
Одураченные случайностью. Скрытая роль Шанса на Рынках и в Жизни [Нассим Талеб]
Шум. Изъяны человеческого суждения [Даниэль Канеман, Оливер Сибони, Касс Санстейн]
Следующим шагом будет введение цен открытия и закрытия. Сначала мы использовали только диапазоны с максимальными и минимальными ценами, но очевидно, что важны метаданные всего бара — они могут улучшить моделирование. Мы используем модифицированную версию утилиты для создания изображений, на этот раз с ценами открытия, максимума, минимума и закрытия. Обратите внимание, что мы придерживаемся черно‑белых цветных карт, чтобы сохранить простоту. Пиксельная матрица задает 1 для хвостов баров и 2 для тела бара. В настоящее время нет различия между зелеными и красными барами (но это может быть следующим нашим улучшением — размышления вслух).
С визуальной точки зрения, данные гораздо проще понять и протестировать с простыми метаданными «открытие/закрытие». Но сейчас не мы обучаемся на этих данных.
Попытка классифицировать все 4 цели вместе: снова переобучение и плохая модель.
Покупать или не покупать: неплохо, но начинает переобучаться.
Продавать или не продавать: снова неплохо, но тоже переобучается.
Может быть, делать снапшот всего дня целиком — это слишком? Может быть, нам нужна только пара последних баров? Но сколько конкретно? Я решил попробовать ряд вариантов, от непрактичных 4 баров (кажется слишком мало) до оригинальной задумки (взять все бары за день).
Наборы данных, начинающиеся с HL (HighLow), используют для создания изображений только максимальные и минимальные цены. Наборы данных, начинающиеся с OHLC (OpenHighLowClose), используют для создания изображений цены открытия, максимума, минимума и закрытия. Разница была описана выше. Теперь давайте попробуем различные подсчеты TPO. TPO означает Time Price Opportunity (цено‑временная возможность) в рыночной терминологии, и это просто еще одно название для одного 30-минутного бара. Если счетчик TPO отсутствует, мы берем все доступные бары, когда был сигнал на покупку или продажу. Если счетчик TPO присутствует, мы берем последнее количество баров: 4, 8, 12 и 16. По сути, теперь сеть видит все данные за день или последние 2, 4, 6 или 8 часов.
Давайте подведем итоги для всех возможных моделей. Начнем с простой (и непрактичной) идентификации всех 4 целей (покупать, не покупать, продавать и не продавать). Мы продолжаем с более релевантной классификации для стороны покупки и стороны продажи отдельно. У обеих сторон есть две цели: совершить сделку или не совершать ее.
Очевидно, что использование только последнего числа баров не имеет никакого значения, но предоставление сети всех баров увеличивает риск переобучение. Результаты проверки не впечатляют, но модель можно использовать. Добавление цен открытия и закрытия, похоже, тоже не сильно помогло. В целом, эти модели хороши, но я пока не решаюсь использовать их в своей повседневной торговле. Даже если производительность приемлема, в ней очень много шума, а метрики хрупки и волатильны.
И еще одно замечание о лучших практиках машинного обучения. Я не являюсь членом команды Андрея Карпати (Andrej Karpathy) или что‑то в этом роде, но его лекции заставляют вас чувствовать себя так, будто вы с ним коллеги.
В любом случае, когда‑то давно я занимался моделированием для различных компаний в качестве Big Data Engineer / Data Scientist. Вот пара моментов, которые я понял на собственном опыте:
Меньше — значит больше. Простые модели — это круто, вычурные‑ отстой.
Разработка характеристик гораздо важнее, чем (простые) модели.
Качество данных никогда не бывает идеальным, просто расслабьтесь, у вас никогда не будет log loss (функция потерь) равной 0 при обучении и проверке.
Современные подходы к решению задач компьютерного зрения можно изучить на онлайн-курсе Otus.
Теперь попробуем уменьшить масштаб: предоставим сети гораздо больше входных баров, чем нужно. Если сигнал создается на протяжении дня, история предыдущего дня легко доступна и может быть добавлена к изображениям.
Более широкие изображения сжимаются до старых добрых квадратов, просто чтобы быть последовательными в формате данных. Результаты значительно лучше, особенно для данных OHLC. Это, наконец, улучшает моделирование.
Теперь это модели, на которые я собираюсь опираться в своем повседневном трейдинге. Несмотря на то, что все они были отмечены как переобученные, их log loss была намного ниже, чем 0.5, а точность практически не изменилась в ходе итераций. Кроме того, теперь у нас гораздо более высокие уровни точности, которые были замечены как на обучающих, так и на проверочных наборах. В целом все это выглядит приемлемо.
Теперь давайте немного сойдем с ума: построим не просто графики, а изображения рыночных профилей (Market Profile). В некотором смысле изображения, созданные до сих пор, — это просто гистограммы. Если вы включаете только диапазоны максимумов и минимумов, это график диапазонов. Если же вы включаете open, high, low и close, то это гистограмма. В нашем эксперименте мы не заботимся о раскраске красных и зеленых баров, поэтому это не 100% гистограмма. Но если вы будете возиться с раскраской баров, то это действительно будет гистограмма.
Гистограммы — это здорово, и, чтобы не быть голословным, я действительно зарабатываю деньги, полагаясь только на 30-минутные бары, но мой секретный ингридиент — это рыночный профиль (который изначально построен на основе 30-минутных баров).
В двух словах, рыночный профиль — это просто применение группировки по цене на необработанных исторических данных 30-минутных баров. Технически можно использовать любой размер бара, но оригинальная идея придерживается 30-минутных баров. Я настоятельно рекомендую вам самим попробовать поработать с этим. Я потратил 3 месяца на рисование рыночных профилей вручную, и это навсегда изменило мой подход. Во‑первых, я нашел свое первое преимущество, занимаясь этим. Во‑вторых, я могу построить рыночный профиль в своей голове для любого рынка, просто взглянув на любой график (бары, линии и т. д.). Очень рекомендую это упражнение.
Существует множество понятий и терминов, связанных с рыночным профилем (POC, Value Area, single prints и т. д.), но эта статья не об этом. В двух словах, все, что вас должно волновать (на мой взгляд) — это clock (текущее время) и single print (хвосты). Особых возможностей нет, когда CME открыта или собирается закрыться. Рынок, делающий новый максимум/минимум за день, напротив очень интересен и предоставляет возможности. Рынки с диапазонами очень сложны и рискованны для торговли.
Теперь вместо того, чтобы рисовать графики, мы строим простой рыночный профиль и превращаем его в изображение. Важно отметить, что первоначально рыночные профили в значительной степени опирались на буквы, где каждая буква представляет собой предопределенный TPO (Time Price Opportunity). Проще говоря, буквы представляют собой определенные 30-минутные отрезки дня. Это дело вкуса и/или того, как программное обеспечение нарисует и определит их для вас. Приведем пример: рыночный профиль, начинающийся с буквы «a», означает, что каждый раз, когда вы видите «a» в рыночном профиле, вы знаете, что этот диапазон торговался в течение первых 30 минут после открытия CME. Соответственно, буква «R» показывает на рыночном профиле торговую активность в течение последних 30 минут перед закрытием NYSE. Излишне говорить, что я настоятельно рекомендую вам прекратить чтение этой статьи, взять лист бумаги и ручку и как следует разобраться в логике, лежащей в основе этого примера. Поверьте, это принесет вам прибыль. Важно отметить, что в этом примере наш рыночный профиль начинается со строчной буквы «а», но в некоторых приложениях/реализациях он может начинаться с прописной «А», но это не имеет особого значения, если вы придерживаетесь одного варианта и будете в этом последовательны.
Обучение модели на изображениях рыночных профилей не впечатляет, здесь наблюдается регресс по всем показателям. Как было замечено ранее, нам может помочь включение данных за предыдущий день. Давайте попробуем.
После некоторой доработки мне удалось создать изображение для многодневного рыночного профиля. Основной принцип любой торговой стратегии заключается в том, что вы опираетесь на что‑то и сравниваете это с какой‑то предыдущей деятельностью. Всегда важен контекст. Детально анализировать последние 3 месяца, наверное, — слишком большая крайность, но шансы заработать на жизнь только на последних 3 барах тоже невелики.
Несколько слов о смешивании моделей. Смешивание — это всегда круто. Нет никакого способа снизить качество моделирования, если вы добавляете новые (хорошие) модели и усредняете результаты. Методики усреднения также не имеют значения. Однако следует помнить о том, что все должно быть просто. Смешивание слишком большого количества моделей в целом неэффективно, потому что на организацию моделирования уходит гораздо больше времени, и оно гораздо более подвержено ошибкам.
Наконец‑то достойная модель! Метрики были хорошими на протяжении всего пути. Даже несмотря на то, что модель отмечена как переобученная, метрики были очень хорошими с небольшими скачками в локальный минимум, но все время оставались близкими.
До сих пор мы моделировали только фьючерс E‑mini S&P 500, давайте попробуем смоделировать другие рынки: E‑mini Nasdaq-100, E‑mini Dow Jones Industrial Average Index и E‑mini Russell 2000 Index. На мой взгляд, это лучшие рынки для торговли с точки зрения ликвидности (спред/глубина), возможностей и важности. Ликвидность определяется многими параметрами, но ключевыми компонентами являются узкие спреды и глубокие биды/аски. Возможности — субъективный показатель, но объемы на этих рынках не врут, а дневные колебания впечатляют. Наконец, важность — опять же субъективная мера, но эти индексы охватывают любую известную вам компанию. Плохие/хорошие новости реально отражаются, если кто‑то участвует в игре. Помните, что любой финансовый профессионал/советник/гуру/специалист по подбору акций — это, как правило, просто напуганный неженка без денег/риска на кону, особенно если этот человек считает делом своей жизни делиться своим мнением с другими. Можете ли вы представить себе Пола Тюдора Джонса (Paul Tudor Jones), который делится своими сигналами о покупке/продаже акций X? Вы понимаете, о чем я говорю.
К сожалению, моделирование и создание изображений внезапно стало очень медленным. Поскольку теперь нам нужны образы OHLC и рыночных профилей для 4 рынков, вместо минут это превратилось в часы пакетной обработки. Очевидно, что если данные создаются изначально для всего хранилища данных, то мы могли бы постепенно добавлять новые образы, скажем, раз в неделю, но тогда возникает проблема хранения данных. Как всегда в компьютерной науке, существует компромисс между пространством и временем. Что‑то можно сделать быстрее, если увеличить объем памяти или хранилища, и наоборот. Это искусство гораздо более тонкое, чем многие подозревают или даже знают.
Теперь данных и каталогов стало гораздо больше, давайте наведем здесь порядок. Каталог верхнего уровня 'ML' содержит каталоги для каждого рынка 'ES', 'NQ' и т. д. Каждый каталог рынка, например 'ES', содержит два каталога для каждого типа изображения: OHLC (гистограмма открытия, максимума, минимума и закрытия) и MP (рыночный профиль). Каждый каталог типа изображения, например 'OHLC', содержит возможные стороны входа для торговли 'Buy' против 'Sell'. Наконец, каждый каталог сторон входа, например 'Buy', содержит данные для интересующего нас «да/нет»‑вопроса: торговать или не торговать на основе преимущества?
Благодаря функции tf.keras.utils.image_dataset_from_directory мы можем легко указать желаемую цель и построить отдельные модели. Например, укажите '.../ML/ES/MP/Buy/', чтобы построить модель для входящих сделок по ES на стороне покупки, используя изображения рыночного профиля. Кроме того, мы можем легко проверить данные вручную (на всякий случай).
Несколько слов о причудливых форматах данных и эффективном хранении изображений. Хотя MNIST использует сложную кодировку и собственный формат для эффективности, мы оставляем его таким, какой он есть (наивным). Опять же, это все для одного странного дня (новости/сумасшедшие скачки/объявления FED и т. д.), который мы должны будем увеличить и тщательно проверить, потому что это был либо впечатляющий день, либо очень плохой (с точки зрения P&L).
Давайте предварительно установим окончательные результаты для 4 индексов фьючерсов, перечисленных выше, OHLC и MP‑изображений с помощью простой ванильной модели, с которой мы начали.
Та‑да! Выглядит отлично и к тому же это для нас полезно. Смешивание моделей определенно улучшит качество моделирования еще больше.
Итак, у нас есть несколько достойных метрик и хороших моделей. Все приведенные выше примеры основаны на 30-минутных барах, но одно из моих преимуществ — это спекулирование на одноминутных графиках. Я подумал, можно ли моделировать меньшие таймфреймы? Давайте попробуем.
И я сразу же понял, что мой локальный компьютер для этого не подойдет. Я решил использовать свою резервную торговую машину AWS (t3a.medium). Генерация изображений для одноминутных баров занимала 24 часа только для того, чтобы сделать 1 год симуляции. Я приостановил эту работу, потому что она занимала слишком много времени, а у нас уже было более 150 тысяч изображений, что более чем достаточно для проверки этой концепции.
Эпохи теперь проходят более чем за полчаса. Машина лагала и работала очень тяжело, а я сделал всего две модели для OHLC. Метрики были отстойными, и я не видел смысла продолжать это начинание.
Очевидно, что если бы мы были вынуждены заставить это заработать, то могли бы использовать гораздо более мощные машины, GPU, TPU и т. д. В общем, это непрактично, и именно поэтому я бросил это дело в самом начале. Как трейдеры мы знаем, что нужно быстро минимизировать свои потери. Так и здесь.
Торговля — это чистая меритократия. Вы получаете то, что смогли поймать, и политика здесь не поможет. Навыки обязательны, но смелость и умственная выносливость иногда даже важнее.
Нет смысла проводить исследования без реальных испытаний с реальным риском. Я могу провести бесконечное количество экспериментов и показать вам, насколько хороши/плохи их результаты, но это не будет иметь никакой ценности.
В трейдинге все зависит от размера выборки. Вы совершили одну жирную сделку, и думаете, что можете назвать себя трейдером? К сожалению, нужно гораздо больше. Я не могу вспомнить, сколько раз я держал в руках большую прибыль на день, которая срывалась, и в итоге день оказывался неудачным. Я также не могу вспомнить, сколько раз сделка флиртовала с моим уровнем стоп‑лосса, который я уже классифицировал как верный убыток, а в итоге получала прибыль и достигала уровня тейк‑профита. Вы поняли, о чем идет речь. Известно, что в этом бизнесе прибыль — как улов в рыбалке.
Время денег, хватит алгоритмов и теории, это конечно интересно и все такое, но я не занимаюсь благотворительностью. Нужно оплачивать счета и налоги, откладывать что‑то на черный день. Это бизнес, которым я занимаюсь, и все это связано с теорией игр. Нет смысла проводить тщательное исследование, если оно не может дать что‑то взамен.
Вдохновившись книгой «Зональный трейдинг» Марка Дугласа», я с тех пор оцениваю эффективность торговли только по группам из 20 сделок. Чем больше, тем лучше, но 20 — это абсолютный минимум. Все, что меньше 20, — просто шум. Давайте теперь проторгуем 20 новых входящих преимуществ/сделок и воспользуемся нашей причудливой системой поддержки принятия решений. Вопрос в том, что если я буду использовать эту модель для строгой фильтрации входящих сделок, улучшу ли я свой P&L или нет?
Я перехожу на свои самые прибыльные рынки на данный момент: ES и YM. На обоих рынках применяется одна и та же идея. Сделки заключаются на 30-минутных барах, обычно вход/выход из сделки занимает пару минут, поэтому добавление прогноза на основе машинного обучения в реальном времени не является большой проблемой (спешить некуда).
Поскольку теперь у нас есть входящий поток сделок с причудливыми предсказаниями машинного обучения, давайте решим, как их интерпретировать. Есть много правильных способов, это не детерминировано. У нас есть два прогноза для каждой сделки: прогноз, основанный на графике OHLC (open, high, low и close), и прогноз, основанный на графике MP (Market Profile). Каждый прогноз состоит из названия класса (Y — да / N — нет) и вероятности (диапазон [50, 100]). Я решил упростить прогнозы, разделив их на 3 группы.
Три группы (сценария):
Y — принять сделку.
N — не принимать сделку.
A — неоднозначность (ambiguity), OHLC и MP имеют неоднозначные прогнозы, поэтому это в некотором роде похоже на отказ от сделки.
Конечно, мы могли бы добавить квантильный анализ вероятностей и несколько комбинаций двух прогнозов, но, как уже говорилось, меньше — значит больше.
К сожалению, как и большинство торговых идей и вещей на рынках, это гораздо сложнее, чем кажется. После приличной выборки (торговли) кажется, что все эти новомодные технологии и сетапы не имеют никакой ценности!
Система практически не возражает против любого результата DSS. Мы ожидали, что метки «N» будут плохими сделками, но они оказались прибыльными. Как и ожидалось, метки «A» следует избегать, и действительно, их P&L плох.
Попытки использовать различные пороги отсечения для кластеризации DSS также не улучшили результаты. Разделение на OHLC и MP в явном виде также не помогло. Все они либо хороши вместе, либо плохи вместе (с точки зрения общего P&L).
В другом исследовании, которое я проводил в тот же период, использовался простой древовидный подход. И с ним также не было впечатляющих результатов. Все метки приносят деньги, поэтому не использовать сигнал или использовать его не имеет никакого значения.
В итоге, с одной стороны, эксперимент оказался неудачным, а с другой — это большое путешествие на пути обучения, полном проб и ошибок.
Возможные причины неудачи:
Проклятие размерности — данных слишком много, и мы не можем обработать их все. Если вы институциональный трейдер и у вас есть соответствующие ресурсы, вы можете добиться лучших результатов.
Сезонность — рынки имеют экстремальные эффекты сезонности, а данные все время меняются со случайной волатильностью (гетероскедастичность). Существует огромная разница между классификацией кошек и снапшотами рынков. Кошки — это кошки, а на рынках у кошек могут быть рога и крылья.
Человеческий фактор — что‑то могло быть неправильно выровнено, оптимизировано или некачественно написано. Неважно, насколько вы опытны или насколько хороши линтеры, некоторые ошибки трудно обнаружить, особенно в машинном обучении.
В любом случае, это был очень интересный опыт.
Я думал закончить историю на этом. Эксперимент завершен, размер выборки достаточно хорош, а результаты плохи. Но я вдруг решил попробовать еще раз. У меня ушло много месяцев на разработку и тестирование этой инфраструктуры, и даже несмотря на плохие результаты, я хотел продолжить тестирование. Я не хотел бросать это дело.
Поэтому вместо этого я решил изменить настройки моделирования. Сначала я уменьшил минимальный порог точности для пользовательского коллбэка. Требование порога в 0.95 кажется слишком жестким — 0.8 лучше, так как сходимость гарантированно происходит быстро, и, по сути, мы призываем к ранней остановке, чтобы не переобучаться.
Затем я уменьшил размер изображения до 32 вместо 200. Эти изменения привели к молниеносной скорости обработки и гораздо меньшему размеру моделей (~1 Гб и ~500 Мб). Наконец, я перестал предоставлять данные обучения в качестве данных для проверки. Вначале это было сделано для того, чтобы сформировать хоть какой‑то отзыв о работе модели. Но после изучения статистики настоящих вневыборочных экспериментов стало ясно, что в этом деле валидация бесполезна. Единственная настоящая валидация — это эксперимент вне выборки. Нет нужды говорить, что это еще больше сократило время работы.
Давайте теперь поторгуем с новым сетапом и посмотрим, получим ли мы лучшие результаты.
Модифицированная нейронная сеть также не улучшила производительность. Более того, она стала работать еще хуже. Классы «Да» имеют отрицательный P&L, а классы «Нет» — положительный P&L. Я думаю не нужно объяснять, что должно быть наоборот.
И получаем, что простой древовидный подход намного лучше! Обратите внимание, что все ложные классы (независимо от отсечения вероятности) имеют в сумме отрицательный P&L, в то время как истинные классы имеют в сумме положительный P&L. Также обратите внимание, что подавляющее большинство сделок являются проигрышными (что характерно для этого бизнеса), но простой алгоритм способен отфильтровать хорошие сделки (а это именно то, что нам нужно).
Принцип KISS (Keep It Simple, Stupid) очень важен в этом бизнесе. К сожалению, со всеми этими причудливыми пробами и ошибками очевидно, что простое ML‑моделирование гораздо лучше. Еще одно соображение, которым пренебрегали на протяжении всего эксперимента, — это время предсказания. Импорт модулей Python и время предсказания гораздо тяжелее для TensorFlow по сравнению с LightGBM. На практике время предсказания для обоих потоков моделирования обычно составляет не менее 6 секунд. Сокращение моделирования до древовидного подхода сокращает это время лишь вдвое. Важно отметить, что время загрузки (импорта) значительно превышает время предсказания (которое составляет менее одной секунды для обоих подходов).
В этих экспериментах мы получили несколько важных выводов, которые важно запомнить. Давайте подытожим самые важные из них.
Больше данных — это хорошо: добавление вчерашних цен привело к серьезному прорыву.
Использование всех четырех векторов исторических данных: open, high, low и close — улучшает моделирование.
Цены на NQ имеют огромные диапазоны, и обычно создание изображений для них занимает гораздо больше времени (итераций), чем для других рынков, но при этом производительность немного выше (такой компромисс).
Размер выборки в этих экспериментах, по сути, крошечный. Я профессионально занимаюсь этим бизнесом с 2017 года и начал заниматься моделированием на основе машинного обучения с хранилищем данных всего за 3 года, этого недостаточно. Мои исследования могла нарушить любая случайность.
Трейдинг — это тяжелый бизнес. Требуются годы, чтобы развить преимущество. Годы уходят на его совершенствование. Обучение никогда не прекращается.
Современные подходы к решению задач компьютерного зрения (от алгоритмов до внедрения в продакшн в разных средах) можно изучить на онлайн-курсе Otus.