Jesse Spaulding: Как я заработал 500 тысяч долларов с помощью машинного обучения и высокочастотной торговли (HFT)

В этом посте детально описано как с 2009 по 2010 г. я заработал примерно 500 тыс. долларов используя высокочастотную торговлю. Поскольку я торговал совершенно независимо и больше не использую свою программу, то счастлив рассказать вам обо всем. Я торговал в основном на Russel 2000 и фьючерсных контрактах DAX.

Я считаю, что ключ к моему успеху заключался не в сложных финансовых уравнениях, а скорее в полной разработке алгоритма, который связал много простых компонентов и использовал машинное обучение для оптимизации и получения максимального дохода. Вам не нужно знать сложную терминологию, потому что после того как я установил свою программу, все остальное было основано на интуиции (удивительный курс машинного обучения Эндрю Нг (Andrew Ng) тогда еще не был доступен, но если Вы пройдете по ссылке, то попадете на мой текущий проект: CourseTalk – обзорный сайт для Массового открытого онлайн-курса (Massive open online course, MOOC)).

Во-первых, я только хочу продемонстрировать, что мой успех не был просто результатом удачи. Моя программа совершала 1000-4000 торговых сделок в день (половина лонг, половина шорт) и никогда не входила в позицию несколькими контрактами одновременно. Это означало, что случайная удача от любой отдельной торговой сделки довольно быстро сводилась на нет. В результате этого я никогда не терял больше чем 2000 долларов за день и никогда не проигрывал по итогам месяца.

Эта диаграмма даст представление о суточном изменении. На графике отсутствуют данные за предыдущие 7 месяцев, потому что рост прекратился, и я потерял мотивацию к фиксированию данных.

Моя квалификация в трейдинге

До установки своей программы автоматизированной торговли у меня было 2 года опыта в качестве внутридневного трейдера, торгующего вручную. Далекий 2001 год – первая электронная торговля и возможности для «спекулянтов» заработать хорошие деньги. Могу только описать это как видеоигру / азартную игру с предполагаемыми границами. Быть успешным – это значит быть быстрым, дисциплинированным и иметь хорошие интуитивные способности распознавать паттерны. Я смог заработать около 250 тыс. долларов, заплатить кредит за образование и отложить про запас. Победа!

Пять лет спустя, получив за это время некоторые программные навыки, я запустил два стартапа. К концу 2008 года я вернулся в трейдинг. Деньги от продажи моего первого стартапа подходили к концу, а трейдинг давал надежду на некоторые быстрые наличные деньги, пока я рассчитывал свой следующий ход.

Торговый API (Application Programming Interface)

В 2008 году я вручную занимался внутридневной фьючерсной торговлей, используя программное обеспечение T4. Я хотел настроить ввод заявки на горячие клавиши, поэтому после того как обнаружил, что T4 построен на базе API, то взялся за изучение C# (язык программирования, необходимый для использования API), и изучил его, и настроил клавиши.

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

Ниже представлен скриншот торгового окна T4. Было классно, что когда я заставил свою программу работать, то мог смотреть на компьютерную торговлю на том же самом интерфейсе. Наблюдать за реальными заявками, внезапно появляющимися и исчезающими (самостоятельно и за счет моих настоящих денег) было волнительно и страшно.

Разработка своего алгоритма

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

Торгуя вживую было необходимо переработанные обновления рынка пропускать через API, а для режима имитации требовалось читать обновления рынка из файла с данными. Чтобы собрать эти данные я установил первую версию своей программы, которая просто соединялась с API и записывала данные обновления рынка с отметками времени. Я закончил тем, что использовал значения последних данных рынка за 4 недели для обучения и проверки своей системы.

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

— прогнозирование динамики цен;

— совершение прибыльных сделок.

Прогнозирование динамики цен

Наверное, самый очевидный компонент любой торговой системы – способность спрогнозировать, куда будут двигаться цены. И мой не был исключением. Я определил текущую цену как среднее значение между внутренней заявкой на покупку и заявкой на продажу. И целью прогноза была цена через 10 секунд. Мой алгоритм должен был выдавать этот прогноз в каждый момент в течение торгового дня.

Создание и оптимизация индикаторов

Я создал небольшое количество индикаторов, у которых важной способностью было прогнозирование краткосрочной динамики цен. Каждый индикатор рассчитывал число, которое было положительным или отрицательным. Индикатор был полезен, если отрицательное число соответствовало падающему рынку чаще, чем положительное – растущему.

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

Все самые полезные индикаторы были относительно просты и основывались на последних событиях на рынке, на котором я торговал, и на рынке коррелированных ценных бумаг.

Создание точного прогноза движения цены

Иметь индикаторы только для прогноза движения цены вверх или вниз было не достаточно. Я должен был точно знать на сколько верно спрогнозировано изменение цены каждым возможным значением каждого индикатора. Мне нужна была формула, которая преобразует значение индикатора в прогноз цены.

Чтобы получить ее, я отследил прогноз изменения цены в 50 сегментах, которые зависели от диапазона, куда попадало значение индикатора. Это дало уникальный прогноз для каждого сегмента, который я тогда смог изобразить в виде графика в Excel. Можно увидеть, что изменение ожидаемой цены растет, когда растет значение индикатора.

Основываясь на таком графике, я смог вывести формулу для подгонки под кривую. Сначала я «подгонял» вручную, но вскоре написал некоторый код, автоматизирующий этот процесс.

Заметьте, что не все кривые индикатора имели одинаковую форму. Также заметьте, что сегменты были распределены логарифмически, чтобы точки располагались равномерно. И, наконец – отрицательные значения индикатора (и соответствующие убывающие прогнозы цены) были перевернуты и объединены с положительными (мой алгоритм одинаково рассматривал движение вверх и вниз).

Объединение индикаторов для одного прогноза

Важный момент состоял в том, что каждый индикатор не был полностью независимым. Я не мог просто сложить все прогнозы, которые сделал по отдельности каждый индикатор. Важно было выяснить дополнительное спрогнозированное значение, которое индикатор имел дополнительно к тому, что уже было спрогнозировано. Это было не сложно сделать, но поскольку “подгонялись” многие индикаторы, я должен был быть осторожным – изменение одного индикатора оказало бы влияние на прогноз другого.

Для одновременной «подгонки» всех индикаторов я установил оптимизатор, чтобы двигаться с шагом только 30% к новому прогнозу с каждым проходом. С этим 30%-ым скачком я обнаружил, что кривые прогноза стабилизируются за несколько проходов.

Теперь каждый индикатор давал нам дополнительный прогноз цены, я мог просто сложить их, чтобы получить единственный прогноз того, где рынок будет через 10 секунд.

Почему прогноза цен недостаточно

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

Следующие факторы затрудняют создание прибыльной системы:

— С каждой торговой сделки я должен был заплатить комиссию и своему брокеру, и бирже.

— Спрэд (разница между самым высоким бидом и самым низким оффером) означало, что если бы я просто покупал и продавал случайно, то потерял бы кучу денег.

— Большую часть рыночного объема делают другие роботы, которые торговали бы со мной только если бы считали, что имеют некоторые статистические преимущества.

— Видеть оффер еще не значит его купить. К тому времени, когда моя заявка на покупку доберется до биржи, было бы очень вероятно, что предложение уже отменено.

— Поскольку я был мелким участником рынка, то не мог конкурировать на одной только скорости.

Создание полного торгового имитатора

Таким образом, у меня была структура, которая позволила мне проводить тесты на исторических данных и оптимизировать индикаторы. Но я должен был выйти за пределы этого – мне нужна была структура, которая позволила бы проводить тесты на исторических данных и оптимизировать полную торговую систему; такую, куда я посылал бы заявки и получал бы позиции. В этом случае я оптимизировал бы полные прибыль/убыток, и до некоторой степени средние прибыль/убыток за сделку.

Было бы сложнее, а в некоторых случаях и невозможно смоделировать точно, но я сделал настолько хорошо, насколько мог. Вот некоторые проблемы, с которыми я столкнулся:

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

— Когда я делал заявки на покупку или продажу, то должен был наблюдать за потоком исполнения сделок (обеспеченного API) и использовать для определения момента, когда моя заявка могла бы выполниться. Чтобы сделать это правильно, я должен был отследить положение своей заявки в очереди (система «первый пришел – первый вышел»). И снова я не мог сделать это идеально, но делал лучшее приближение.

Для усовершенствования своей имитации выполнения заявки, я взял свои лог-файлы регистрации торговли вживую из API и сравнил их с лог-файлами, полученными с помощью имитации торговли за тот же период времени. Мне удалось смоделировать довольно достоверную систему даже для тех компонентов, которые было невозможно смоделировать точно, и я удостоверился, что, по крайней мере, получил статически подобные результаты (для тех показателей, которых я считал важными).

Прибыльные сделки

С готовой к использованию моделью имитации подачи заявки теперь я мог посылать заявки в режиме имитации и видеть смоделированные прибыль и убытки. Но как моя система узнает, когда и что купить и продать?

Прогнозы движения цены были лишь отправной точкой. Я создал систему оценки для каждого из 5 уровней цен для бидов и офферов. Она включала один уровень выше внутреннего бида (для заявки на покупку) и один уровень ниже внутреннего оффера (для заявки на продажу).

Если бы значение оценки на каком-либо уровне цен было выше определенного порога, то это означало бы, что у системы должна быть активная заявка на покупку/ продажу; если ниже порога, тогда все активные заявки должны быть отменены. Основываясь на этом, было обычным случаем, что моя система внезапно подает заявку на покупку, а затем сразу же отменяет ее (хотя я попытался минимизировать такое поведение, поскольку это раздражает любого человека, смотрящего на экран, включая меня).

Оценки множества уровней цен были вычислены, основываясь на следующих факторах:

— Прогноз движения цены (рассмотрено выше).

— Рассматриваемый уровень цен (внутренние уровни означали, что требовалось большее число прогнозов движения цены).

— Число контрактов перед моей заявкой в очереди (чем меньше, тем лучше).

— Число контрактов после моей заявки в очереди (чем больше, тем лучше).

По существу эти факторы служили для идентификации «безопасных» мест покупки или продажи. В одиночку прогноз движения цены не был достаточным, поскольку он не учитывал факт, что посылая заявку на покупку, я не покупал автоматически – а покупал только тогда, когда кто-то мне продавал. Действительность заключалась в том, что простой факт продажи кем-то мне по определенной цене менял статистическую вероятность заключения сделки.

Все переменные, используемые на этом шаге, были предметом оптимизации. Она была проведена аналогично оптимизации переменных в индикаторах движения цены, за исключением того, что в этом случае я оптимизировал полные прибыль/убыткок.

Что игнорировала моя программа

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

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

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

— Стратегия «усреднения». Это известная стратегия, при которой трейдеры покупают большее количество акций, в случае если рынок идет против них. Это приводит к тому, что ваша средняя покупная цена будет ниже, а это означает, что когда (или если) акция развернется, вы быстро получите свои деньги назад. По-моему, это ужасная стратегия, если Вы не Уоррен Баффет (Warren Buffet). Вы заблуждаетесь, думая, что преуспеваете из-за того, что большинство ваших сделок приносят прибыль. Проблема состоит в том, что когда вы проигрываете, то проигрываете по-крупному. Другой эффект этой стратегии в том, что становится трудно судить имеете ли вы преимущество относительно рынка или вам пока просто везет. Подтверждение того, что моя программа действительно давала преимущество, было важной целью.

Управление рисками

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

Для управления рисками я установил максимальный размер позиции – 2 контракта за один раз, который иногда увеличивал в дни высоких объемов. У меня также было максимальное ежедневное ограничение потерь для предохранения против любого неожиданного состояния рынка или ошибки в программном обеспечении. Эти ограничения были установлены и в моем коде, и кроме того на стороне брокера. После этого я никогда не сталкивался ни с какими серьезными проблемами.

Запуск алгоритма

С момента, когда я начал работать над своей программой, приблизительно через 6 месяцев я добрался до точки получения прибыли и запустил систему вживую. Хотя справедливости ради стоить отметить, что много времени ушло на изучение нового языка программирования. Когда я работал над улучшением программы, то в течение каждого из следующих четырех месяцев получал увеличенную прибыль.

Каждую неделю я переобучал свою систему, основываясь на данных предыдущих 4-х недель. Я обнаружил, что в результате получился правильный баланс между сбором последних поведенческих тенденций рынка и страховкой, что у моего алгоритма достаточно данных для получения значащих моделей. Поскольку обучение начало занимать все больше времени, я разделил его выполнение между 8 виртуальными машинами, используя веб-сервис Amazon EC2. Результаты объединялись на моей локальной машине.

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

Расстроившись от неспособности улучшить систему, и не видя смысл развивать проект дальше, я начал думать о новой сфере работы. Я написал 6-ти различным высокочастотным трейдерским фирмам письма по электронной почте с предложением покупки моего программного обеспечения и предоставлением мне работы. Никто не ответил. У меня было несколько новых идей стартапов, над которыми я хотел работать, так что я на этом закончил с системой.

Источник:

Jesse Spaulding: How I made $500k with machine learning and HFT (high frequency trading)

Комментарии:

Intro: Странно, что ему никто не предложил работу. Да и разочаровался он рано, нужно было продолжить исследования имхо.

Intro: Probably 90% of all orders sent to the exchange were cancelled. (A mark of HFT.) Вероятнее всего в какой-то момент его просто сделали по скорости.

mehanizator: Да, я тоже так думаю. Он на индексных фьючах играл, надо было поискать менее активные площадки.

Andrew Kartashov: Красивый подход. Действительно зря забросил, поискал бы менее конкурентные темы.

Shevtsov Alexandr: Не понял насчет «дополнительное спрогнозированное значение». Что это ? Степень влияния на другие индикаторы?

valmac: а мне наоборот понравилось — что у парня чуйка и сила воли развита — чуть ROI пошел вниз — соскочил с темы …
молодец 🙂


Подпишитесь на уведомления о новых постах

И получите доступ к специальным материалам сайта