Этот пост основан на моем опыте участия в очень интересном конкурсе прогнозирования, организованном XTX. Перед участниками стояла задача спрогнозировать будущую доходность (предположительно) актива Forex на основе данных книги лимитных заказов (LOB). В рамках конкурса подробностей о датах активов или лимитных заявок не разглашалось.
В рамках конкурса XTX предоставила данные о разработке собственной модели. Данные включали 3 миллиона тиковых записей, каждая из которых содержала несколько уровней цен покупки и продажи. Соревнование было разработано таким образом, чтобы вся предыдущая история накопленных тиковых данных была доступна в каждый момент времени, но никакие исторические доходы не могут использоваться для будущего прогноза. Это устранило классические модели временных рядов и потребовало от участников в полной мере использовать модели прогнозирования книги лимитных ордеров.
В этом посте я сосредоточусь на применении фильтра Калмана для получения неявного состояния LOB. Подробное описание теории фильтров Калмана можно найти в широком диапазоне академических ресурсов (пример).
Каркас модели
Я придерживался относительно стандартного подхода к построению регрессионной модели:
- Модель регрессии XGBoost как ядро
- Поиск параметров в сетке на основе перекрестной проверки методом прямого перехода
- Генерация дополнительных динамических факторов на основе исторических тиковых данных
Я опущу подробности XGBoost и перекрестной проверки, все подробности можно найти на моем github. Вместо этого я сосредоточусь на технике разработки функций, основанной на фильтре Калмана.
Использование фильтра Калмана для вывода неявных потоков LOB
LOB-данные представлены в виде массивов размеров и цен предложения / продажи, разделенных на 15 сегментов: bidSize [0..14], askSize [0..14], bidPrice [0..14], askPrice. [0..14]. На приведенном ниже графике показаны кумулятивные объемы спроса и предложения в LOB за короткий период времени:
Чтобы отслеживать динамику LOB во времени, вводятся подразумеваемые скрытые денежные потоки между бакетами LOB. Для упрощения все сегменты [1..14] объединены в одну. Следовательно, наблюдения описываются как вектор [bidSize1_14, bidSize0, askSize0, askSize1_14]
Скрытые состояния системы определяются на основе следующих одиннадцати параметров:
- Четыре параметра, определяющие текущий объем в каждом из сегментов bidSize1_14, bidSize0, askSize0, askSize1_14; Несмотря на то, что эти параметры непосредственно наблюдаются в данных, фильтр Калмана считает, что на них влияют ошибки измерения и процесса;
- Четыре параметра, определяющие внешний денежный поток в / из соответствующих сегментов;
- Три параметра, определяющие следующие денежные потоки между бакетами:
- ask1_14 ⇆ ask_0
- bid1_14 ⇆ bid_0
- ask_0 ⇆ bid_0
Скрытые состояния предполагают наличие неявного потока между бакетами в дополнение к потоку из внешнего мира. Как мы увидим далее, оценки этих потоков используются в качестве факторов в регрессионной модели.
На основании состояний, приведенных выше, матрица переходов состояний Калмана размером 11 на 11 определяется следующим образом:
В матрице перехода между состояниями строки и столбцы упорядочены в соответствии со списком скрытых состояний выше. Начиная со строки 5 и далее это единичная матрица, показывающая, что никаких изменений в потоках не ожидается. Строки с 1 по 4 представляют собой изменение текущего объема спроса / предложения. Например, изменение BidSize для сегментов 1–14 с течением времени t выглядит следующим образом:
с ω, представляющим процесс белого шума.
Алгоритм фильтра Калмана реализован в приведенном ниже коде:
Код возвращает значения неявных потоков, которые в дальнейшем используются в качестве факторов прогнозирования в основной регрессионной модели. В качестве примера первые 20000 наблюдений за потоком (ask_0 ⇆ bid_0) представлены на временном ряду ниже:
Новые прогностические факторы используются в модели XGBoost, и их относительная важность оценивается на основе того, сколько раз они использовались в деревьях решений XGBoost.
Выдержка статистики важности переменных представлена на диаграмме ниже, где первая функция представляет собой поток ask_0 ⇆ bid_0:
Вывод
Мы рассмотрели пример фактора, который генерируется на основе неявного динамического денежного потока LOB актива. Несмотря на то, что поток является неявным и ненаблюдаемым в данных, использование алгоритма фильтра Калмана позволило сгенерировать фактор со значительной предсказательной силой при использовании в качестве входных данных в базовый алгоритм XGBoost.
Отказ от ответственности: метод, описанный в этом посте, использовался как часть более широкого диапазона факторов прогнозирования. В совокупности представленная модель заняла 13-е место в итоговом рейтинге конкурса.