В период с 18 января по 18 июля на сайте Kaggle проходило соревнование Ubiquant Market Prediction от китайской компании Ubiquant Investment. Я поучаствовал в этом соревновании и мой опыт участия оказался скорее негативным, в первую очередь из-за плохой организации соревнования, но об этом позже. Для начала давайте расскажу, что это было за соревнование.

Про соревнование

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

Изначально не было понятно, с какими конкретно финансовыми инструментами мы работаем. На входе имелся датасет на 18.5 Гб, состоящий из id актива , id таймфрейма (опять таки была неизвестна его величина - полчаса/час/день/неделя, плюс к тому же на тестовых и реальных данных его величина могла быть другой), id строки (тупо id таймфрейма + id актива), 300 анонимизированных признаков (проведена нормализация, устранены или сглажены периодические изменения, добавлен шум и т.д.) и таргет, тоже анонимизированный.

Соответственно нашей задачей было по имеющимся признакам для каждого временного промежутка и финансового инструмента предсказать его таргет в будущем. В качестве метрики использовалась Корреляция Пирсона. Особенностью данного соревнования было то, что итоговый результат оценивался на текущих реальных рыночных данных, собранных после закрытия соревнования в период с 18 апреля по 18 июля 2022 года. То есть такая традиционная для соревнований проблема, как утечка данных, в данном случае возникнуть не могла. Вторым следствием из этого являлось то, что для успешного сабмита недостаточно загрузить сам файл с предсказаниями модели, нужно загрузить весь код + модели, необходимые для предсказания, что с моей точки зрения хорошо, так как накладывает ограничения на время работы кода (9 часов) и размер, занимаемый в оперативной памяти (13-16 Гб в зависимости от конфигурации железа, на котором Kaggle исполняет код), что позволяет отметать безумные решения вроде пятиуровневых ансамблей на 1000 моделей или адовых нейросетей с миллиардами параметров.

Так что же тогда пошло не так?

Кривой датасет

Формат данных (в частности ID строки = id таймфрейма + id актива) на тренировочных данных был всегда один и тот же, но не всегда был одним и тем же на тестовых данных. Соответственно сабмиты участников, которые использовали эту колонку в своих предсказаниях, нормально отрабатывали на тренировочных данных, но выдавали ошибку на тестовых. Поскольку из-за соревновательной специфики Kaggle определить источник ошибки не представлялось возможным, приходилось работать методом тыка: по очереди комментить определенные участки кода либо добавлять к ним try/except.

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

Кривой API

Буквально через неделю после начала соревнования первое место занимает участник с фантастическим по меркам финансовых рынков результатом в 0.663. Так в чем же дело? Нет, не в утечке данных.

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

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

Правила нужны, чтобы их нарушать

В пункте 7.С правил соревнования было написано прямым текстом, что публичные внешние данные (т.е. различные микро- и макрофинансовые показатели + другая общедоступная информация) можно использовать.

Довольно быстро, анализируя зависимость таргета от времени, участники поняли, что финансовые инструменты, с которыми они работают, это так называемые китайские А-акции, размер таймфрейма равен одному дню, а данные собраны в период с 2014 по 2018 годы. Понять это получилось потому, что на некотором временном промежутке таргет большинства активов вел себя нестабильно, и длительность этой нестабильности совпадала с длительностью турбулентности на Китайском рынке акций в период с 2015 по 2016 годы.

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

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

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

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

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

Нужно боооольше данных!

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

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

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

Кривой API vol. 2

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

Кривой API vol. 3

Угадайте, что произошло с сабмитами некоторых участников в последний день? Правильно! Они снова начали вылетать с ошибками! Ведь сегодня последний день соревнования, самое время поковыряться в API! В итоге организаторам таки пришлось отложить финал соревнования на 48 часов.

Дедлайны нужны, чтобы их не соблюдать

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

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

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

Победители

Кто же победил в этом соревновании?

1 место - 5 LGBM + 5 Tabnet, добавили 100 новых признаков, использовали часть тренировочных данных + дополнительные данные.

2 место - 5 LGBM, добавили 100 новых признаков, использовали все доступные тренировочные данные + дополнительные данные.

3 место - 5 трансформеров по 6 слоев, использовали 300 оригинальных признаков, использовали все доступные тренировочные данные + дополнительные данные; замечу, что данное решение выдало ошибку после первого обновления таблицы лидеров, к счастью команда Kaggle смогла все исправить.

5 место - одна полносвязная сеть на 4 слоя, использовали 300 оригинальных признаков, использовали часть тренировочных данных + дополнительные данные.

Как видите, как минимум 4 команды из топ 5 использовали дополнительные данные. Которые, напомню, добавили буквально за несколько недель перед концом соревнования и использование которых регулярно приводило к ничем не объяснимым ошибкам.

Итоги

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

P.S.

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

Комментарии (2)


  1. dimka11
    05.08.2022 19:11

    Почему использование предыдущих предсказаний запрещено? В реальности тоже по одной акции предсказывают?


    1. beatwad Автор
      07.08.2022 00:21

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

      А вот что было запрещено, так это напрямую вытаскивать предыдущие значения таргета из коррелирующих с ним признаков и модифицировать ими уже сделанные предсказания задним числом. Это было возможно из-за кривого API и за это банили.