Как я заработал $500K на машинном обучении и высокочастотном трейдинге » Элитный трейдер
Элитный трейдер


Как я заработал $500K на машинном обучении и высокочастотном трейдинге

От переводчика: На днях на Хабре был опубликован топик о том, как IT-специалисту сохранить и приумножить свои деньги, который вызвал довольно большой интерес. Я с недавних пор интересуюсь финансовой темой, и мне на глаза попалась интересная история парня, который, применив свои технологические навыки, смог за год заработать полмиллиона долларов. Мне кажется, его опыт может быть интересен многим хабражителям (хоть у него и уже был опыт работы на бирже), поэтому решил перевести этот текст (он очень объемный, так что будет две части).
27 марта 2014

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

Ключ к моему успеху, на мой взгляд, заключался не в использовании сложных финансовых уравнений, а скорее в применении общего алгоритмического подхода, который увязал вместе множество простых компонент и включал в себя принцип машинного обучения для оптимизации алгоритма и достижения максимальной прибыльности. При чтении этой статьи вам не понадобится знание какой-либо специфической терминологии – когда я запустил мою программу, я полагался лишь на интуицию. (К сожалению, прекрасный курс Эндрю Нг’а (Andrew Ng) по машинному обучению тогда еще не был доступен публике – между прочим, если пройдете по ссылке, попадете на мой текущий проект: CourseTalk, сайт отзывов на массовые открытые онлайновые курсы/MOOC).

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

Как я заработал $500K на машинном обучении и высокочастотном трейдинге


(Поправка: это показатели за вычетом комиссий)

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

Как я заработал $500K на машинном обучении и высокочастотном трейдинге


Мой опыт торговли на бирже

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

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

API для трейдинга

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

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

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

Как я заработал $500K на машинном обучении и высокочастотном трейдинге


Проектирование собственного алгоритма

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

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

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

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

Предсказание движения цен
Организация прибыльных торгов

Предсказание движения цен

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

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

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

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

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

Точные предсказания поведения цен

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

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

Как я заработал $500K на машинном обучении и высокочастотном трейдинге


На основе подобного графика я смог создать формулу, которая соответствовала полученной кривой. Вначале я делал эту «подгонку под кривую» вручную, но вскоре написал небольшую подпрограмму, которая автоматизировала этот процесс.

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

Компоновка индикаторов для получения однозначного предсказания поведения цен

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

Для того, чтобы подогнать под заданную кривую все индикаторы одновременно я настроил оптимизатор так, чтобы с каждой итерацией кривая прогнозирования менялась в сторону заданной только на 30%. Этот скачок в 30% позволял кривым прогнозирования стабилизироваться за небольшое количество итераций.

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

Почему недостаточно просто предсказывать цены

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

Сложности при создании системы, позволяющей заключать прибыльные сделки, можно выделить следующие:
С каждой торговой операции мне нужно платить комиссию и моему брокеру, и бирже.
Факт существования спреда (разницы между лучшей ценой покупки и продажи) означает, что если бы я просто в случайном порядке покупал и продавал, то потерял бы массу денег.
Большую часть рынка занимают другие боты, которые заключат со мной сделку только если сочтут ее статистически выгодной.
Найти привлекательное предложение – не значит заключить сделку. К тому моменту, когда приказ на покупку достигнет биржи, предложение, скорее всего, может стать неактуальным.
Как мелкий игрок на рынке, я не могу в одиночку конкурировать только за счет скорости.

Создание полноценного симулятора торгов

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

Создать такой фреймворк было бы непросто – в некотором смысле даже невозможно смоделировать в точности, но я сделал все, что мог. И вот некоторые вопросы, с которыми мне пришлось столкнуться:

Когда команда отправляется на рынок в симуляторе я должен смоделировать временной лаг. Тот факт, что моя система «увидела» предложение, не означает, что она может его сразу купить. Система пошлет команду, подождет примерно 20 миллисекунд и только тогда, если предложение все еще будет в силе, будет рассматривать его, как закрытую сделку. Это не совсем точно, так как длительность реального лага не всегда одинакова и не регистрируется.
Когда я размещаю предложения купить или продать акции, мне нужно учитывать поток исполнения сделок (который обеспечивает API) и использовать его, чтобы отслеживать, когда мой заказ будет исполнен. Чтобы сделать это правильно, я должен отслеживать позицию моей команды в очереди (очередь формируется по системе first-in first-out). И снова я не смог сделать это в точности, но смоделировал максимально приближенную к реальности систему.

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

Обеспечение прибыльных торгов

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

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

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

Счета для разных уровней цен подсчитывались на основе следующих факторов:

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

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

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

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

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

Цена входа на позицию – В офисе трейдинговой компании нередки разговоры о цене, по которой кто-либо заключает длинные и короткие сделки, как будто это должно повлиять на принятие подобных решений в будущем. Несмотря на то, что такие данные имеют некоторое значение в рамках стратегии сокращения рисков, они не имеют никакого отношения к дальнейшему развитию рыночных событий. Поэтому моя программа полностью игнорировала эту информацию. Это все равно, что игнорировать необратимые издержки.
Заключение длинной/короткой сделки – Как правило, у трейдера-человека был бы специальный критерий, определяющий, где продавать длинную позицию, а где – заключать короткую сделку. Однако, с точки зрения моего алгоритма, не было никакой разницы между этими двумя понятиями. Если мой алгоритм ожидал падение цен, то продажа была логичным шагом вне зависимости от того, какой характер имела сделка: «лонг», «шорт» или «флэт».
Стратегия «удвоения» – Это общепринятая стратегия, согласно которой трейдеры покупают больше акций в том случае, если изначально торги идут не в их пользу. Как следствие, ваша средняя цена покупки снижается, а это означает, что когда (если) цена на акции изменит курс, вы «отобьете» свои расходы в кратчайшие сроки. Мне кажется, это просто кошмарная стратегия, если только вы не Уоррен Баффет. Вы обманываете себя, думая, что у вас все хорошо, потому что большая часть ваших сделок выгорит. Проблема заключается в том, что если вам не повезет, то проигрыш будет ошеломляющий. Другое следствие этого подхода заключается в том, что становится крайне сложно определить, действительно ли вы получили рыночное преимущество, или вам просто повезло. Важным качеством моей программы было как раз то, что я мог отслеживать и подтверждать ситуации, когда моя программа действительно таковым преимуществом обладала.

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

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

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

Работа с алгоритмом

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

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

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

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

Примечание: Я опубликовал этот пост на Hacker News, где он приобрел большую популярность. Я просто хочу сказать, что не пытаюсь защитить тех, кто сейчас пытается сделать нечто подобное самостоятельно. Вам понадобится команда очень умных коллег с большим количеством навыков, чтобы просто попытаться составить кому-либо конкуренцию на рынке. Даже тогда, когда я писал свою программу, одиночки крайне редко достигали успеха (но я слышал о таких).

Наверху страницы [в оригинальном посте – прим. переводчика] есть комментарий, в котором встречаются такие выражения, как «манипулирование статистикой», а меня называют одним из «инвесторов-ритейлеров», про которых настоящие кванты [кванты/квонты – в российской переводческой практике используются оба варианта перевода – прим. переводчика] говорят, что их «отстреливать надо». Это весьма неудачный комментарий, попросту далекий от реальности. А между тем, существуют и более интересные отзывы на мою статью.

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

(C) Источник
Не является индивидуальной инвестиционной рекомендацией
При копировании ссылка обязательна Нашли ошибку: выделить и нажать Ctrl+Enter