Блог им. AleksandrBaryshnikov

Кросс-валидация в трейдинге

    • 22 ноября 2023, 00:22
    • |
    • bascomo
  • Еще
Доброй ночи вам.

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

Итак, начнём.

Само понятие кросс-валидации пришло к нам из машинного обучения.

Кросс-валидация в трейдинге



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

Давайте рассмотрим пример для ML, где мы используем 12-кратную кросс-валидацию для оценки качества модели. У нас есть набор данных, который мы разбиваем на 12 частей. Затем мы проводим обучение модели на 11 частях данных и тестируем на 1 части данных. Далее мы меняем тестовую часть и повторяем процесс обучения и тестирования. После завершения всех итераций у нас есть 12 наборов результатов (один для каждой части данных).

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

Справедливости ради, отмечу, что в ML существует много различных типов кросс-валидации, и тот, что описан выше, называется K-fold. Из популярных есть ещё 6 (наиболее распространенных) типов — Holdout, Stratified k-fold, Rolling, Monte Carlo, Leave-p-out и Leave-one-out, но большинство из них не подойдёт для задач трейдинга от слова «совсем». Кстати говоря, Holdout — это тот самый любимый большинством In Sample / Out of Sample. Видите, как много дал трейдингу ML? А вы его ругаете :)

Кросс-валидация в трейдинге

Думаю, тут практикующим алготрейдерам понятно, что данный подход в трейдинге «в лоб» не применим, поскольку «много неясного».
Более того, используя конкретные торговые терминалы, мы получаем профдеформацию, которая выглядит как представление о том, что есть только два куска: train и test или in sample и out of sample, если угодно. Если на train мы получили минус, то подавляющее большинство не видит смысла проводить с такой торговой системой какие-либо ещё упражнения в смысле тестирования / проверки её профпригодности на других временных отрезках.
Кроме того, для классической интерпретации термина не существует понятия времени. Там каждый кусок данных условно равнозначен, он как бы ни в прошлом, ни в будущем, ни в настоящем. Он просто есть. Мы же понимаем, что на небольших интервалах цена в прошлом всё-таки определяет в подавляющем большинстве случаев диапазон цены в будущем. Сбер не может стоить сегодня 15 рублей, завтра 300, потом 25. Выбросы, конечно, есть, кто же с этим спорит, но они есть везде, и их меньшинство. ML этого не учитывает, а нам стоит задуматься.

Дальше — больше. Мы ищем торговые системы на train и проверяем их на test. Если мы возьмём ценовой ряд, разобьём его на несколько кусков и скажем, что один из них — это test, а остальные — train, то что с этим делать дальше?
Обыкновенно, если результаты торговой системы на train нас не устраивают, есть ли (и какой) смысл проверять её на test?
С другой стороны, если на 5 кусках train у нас одни и те же параметры и одна и та же торговая система, как предполагает подход ML, то какие, к чёрту, это train? Train там будет только один, а остальные будут test — очевидно.

Вот и получается, что у нас, в алготрейдинге, должно быть наоборот: один train и несколько test. Нашли на train, и последовательно проверяем на всех test. А train меняем так, как это описано применительно к test в кросс-валидации для ML. Но так никто не делает, потому что у большинства выученная привычка, см. далее. Я бы даже сказал: привычка, навязанная терминалами.

Следующая проблема состоит в том, что нам эти результаты нужно сохранять, так как следует провести множество вычислений для разных инструментов, кусков train/test и самих торговых систем, а какие-то выводы можно сделать только на сводных результатах исследований. В штатной комплектации существующие торговые терминалы делать этого не позволяют. Собственно, и автоматизированно тестировать торговые системы, меняя смысл отдельных участков входных данных с train на test или наоборот, даже без записи результатов тестирования, они тоже не позволяют. Нужно всё это прикручивать сбоку руками. Как-то и где-то.

Ну и ещё вот эта привычка большинства, о которой тоже хочется сказать пару слов: взять тики лет за 20, и прогнать стратегию на них целиком. Без разделения на серии кусков. Имеет ли право такой подход на существование? Очевидно, да. Будет ли он эффективнее, чем разбиение ценовой истории на относительно небольшие куски и валидация каждого куска отдельно? Очевидно, нет, ведь в этом случае ТС должна подстроиться под 20 лет, да и оптимизируем мы её «на глаз» по кривой доходности и нашим внутренним убеждениям, зачастую, в отрыве от контекста (ведь мы не наблюдаем параллельно с кривой эквити кривую цены, чтобы чётко понимать, что происходило с доходом в моменты тех или иных движений цены, смены трендов, боковика или резких движений рынка, а главное — почему: проанализировать все эти кейсы)
В «кусочном» варианте такой задачи не стоит, поскольку мы отдаляемся от точки «торговая система должна быть эффективна всегда и вечно, как в прошлом, так и в будущем» и приближаемся к «эта конкретная торговая система должна быть эффективна здесь и сейчас, были до неё, будут и после». Не встаём на эту точку, а именно приближаемся к ней, поскольку крайностей вообще не существует.

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

Первый вариант совершенно очевиден, понятен и логичен, если… мы говорим, что мы будем всегда торговать одним инструментом, одной системой и на одном таймфрейме. Что далеко от реальности, ведь сила алготрейдинга состоит именно в массовости совершения торговых операций разными алгоритмами и на разных рынках, что недоступно человеку. А чтобы торговать одним алгоритмом на одном инструменте — алготрейдинг не нужен. Всегда следует помнить, что алготрейдинг — это не про «торговать лучше, чем человек», а про «торговать больше, чем человек».

Не будучи осведомлён о всём том, что написано выше, я раньше определял для себя кросс-валидацию как валидацию ТС, найденной на одном инструменте, на ценовых данных других инструментов. Это совершенно нетривиальная задача, учитывая иногда на порядки различающиеся параметры тех или иных инструментов между собой. Я её для себя решил, а как — писал ранее.
Кросс-валидация в трейдинге
Я пришёл к моему решению задачи кросс-валидации в трейдинге интуитивно.
В моём подходе, все имеющиеся данные — это пространство поиска торговых систем, и все же имеющиеся данные — это пространство для их проверки. Условие тут, очевидно, только одно: для каждой конкретной торговой системы данные, на которых она была найдена, и данные, на которых она будет тестироваться, не должны пересекаться. Звучит очень просто, а по факту так оно и есть.

Есть и другие любопытные факты, которые говорят о бесполезности идеи тестирования торговой системы на всей ценовой истории испокон веков.
Один из них состоит в том, что, действительно, в дремучей древности цен можно найти алгоритмы, которые успешно будут работать сегодня. Но в недалёком прошлом таких алгоритмов находится в разы, если не на порядки, больше, чем в прошлом. Следовательно, данные годичной давности более репрезентативны для поиска торговых систем, чем данные 20-летней давности. Это элементарно объясняется тем, что в разные временные отрезки на одном и том же рынке работают разные игроки с разными паттернами поведения и торговыми стратегиями, которые и определяют эффективность тех алгоритмов, которые там находятся.

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

И, наконец, ещё такой: даже использование 20 лет истории не гарантирует того, что ваша ТС не подстроена. Да-да, я о том самом пресловутом курва-фиттинге. Если же использовать адаптированный K-fold, вероятность подгонки существенно снижается, как, впрочем, и число валидных торговых систем. Думаю, это нормально. И зависимость подгонки от коэффициента вероятности, про который пишу ниже, не линейная, а обратно пропорциональная. Чем на большем количестве test имеем позитивный результат, тем ниже вероятность подгонки. А в классике IS /OOS test у вас всего один, не так ли?

Гарантий заработка на финансовых рынках нет, а потому мы оперируем вероятностями.
В этом и состоит краеугольный камень моего подхода.
Разбив ценовые данные инструментов моего портфеля на отдельные дискретные интервалы, а именно — месяц, я тестирую каждую торговую систему на каждом интервале каждого инструмента. Получаю число интервалов, где она прибыльна, и число, где она убыточна и, следовательно, вероятность её успешности на заданном наборе данных — число успешных интервалов к их общему числу. Собственно, я писал об этом ранее. Тут — и меня снова не затруднит бросить камень в окно популярных и не очень терминалов — мне достаточно рассчитать один раз и записаться, между тем, как в других нужно считать снова и снова. Это на порядки сокращает число расчётов при поступлении новых данных.
Проранжировав торговые системы по рассчитанной, как описано выше, вероятности их успешности и не только на «родном» инструменте, уже и науськиваю их лучший топ на те или иные торговые инструменты. Работает превосходно.

В принципе, вроде это и кросс-валидация, если не присматриваться к деталям, но и понятие получилось шире, с одной стороны, и, с другой стороны, как-то по-другому в сравнении с классическими формулировками. Вроде бы и усреднение есть, только оно выражается в вероятности. А усреднение параметров торговой стратегии мы знаем, к чему приведёт, и это никого не порадует. Но когда читаешь классическое описание, звучит именно так: посчитайте, смешайте всё в кучу, сложите, разделите, посчитайте среднее. Авось, что-то и получится. А если говорить об усреднении чистой прибыли — какой смысл делить на отрезки? Можно и сразу тестирование захерачить на всех данных, с начала времён. И лучше, непременно, на тиках. Собственно, так большинство и делает. И, вроде, работает. А тогда зачем что-то менять?

Доброй ночи вам и приятных снов и лёгкой кросс-валидации ваших торговых систем :)
Кросс-валидация в трейдинге
★4
24 комментария
Добрый день. Просьба научиться концентрировать мысли
avatar
оптимизация кривой доходности «на глаз» — это зло
есть четко описанные математические механизмы, упрощение которых даже до уровня 8-го класса школы вполне понятно большинству читателей
avatar
Когда адекватное проскальзывание будешь учитывать? Одно это в корне поменяет твой подход, а есть ещё и другие факторы.

Разбивка на месяцы далека от реальности, большинству систем входных данных для разгона индикаторов нужны недели, иногда месяцы. Ещё у большинства практиков среднее время удержания это неделя, а это значит что бывают сделки с удержанием месяц и больше, при таком подходе их нормально не протестируешь. В итоге получится что когда-нибудь ты откажешься от своего подхода и будешь делать типа как все, но до этого тоже ещё дожить надо,  и даже к этому прийти будет не так просто как тебе кажется.
avatar
Artemunak, зачем нужен алготрейдинг, если позиция удерживается неделю или даже месяц?
avatar
bascomo, месяц не предел, бывают длинные тренды, и если на них перезаходить то нифига не заработаешь. Я бы сам рад торговать быстрые системы но чёто они первыми всегда умирают.
avatar
Artemunak, чем меньше сделок в году, тем меньше транзакционные потери и тем больший объем можно в такие системы засунуть. Многие склонны недооценивать этот момент.
avatar
SergeyJu, я смотрю не на транзакционные потери, а на чистую прибыль
avatar
bascomo, главное, чтобы при расчете чистой прибыли не были забыты все реальные издержки.
Когда триумфатор въезжал в Рим, специальный человек шел за ним и повторял «Помни о смерти». 
А я постоянно повторяю на смартике
Помни о рисках.  
avatar
SergeyJu, помни, не помни, толку нет. В этом мире вообще и в трейдинге в частности есть слабопредсказуемые вещи, например, проскальзывание. Чем добавлять ещё одну переменную, оценивать её, прогнозировать, как по мне, лучше повысить норму доходности алгоритмов, чтобы заведомо перекрыть проскальзывания. А ещё лучше минимизировать влияние такой переменной на результаты торгов, по возможности, сведя её к нулю. В данном случае  минимизировав объёмы сделок. Меньше объём сделки, больше инструментов, чаще сделки. Да, выше транзакционные издержки, ну и плевать, если доходность та же или выше. Зато устойчивость тоже вырастет, и чем меньше продолжительность сделки — тем меньше потенциальные просадки. Это всегда как качели или весы — одно улучшаешь, другое ухудшается. А в золотой середине нулевая прибыль :)
avatar
bascomo, Вы, главное, не пропадайте. С моей точки зрения Вы делаете нечто оригинальное, хотелось бы приглядеться хотя бы в течение 2-3 лет. Лучше — больше.
avatar
SergeyJu, Этого я Вам обещать не могу 😄
avatar
bascomo, перекрывать проскальзывание уменьшением продолжительности сделки — это примерно как тушить пожар бензином. Чем быстрее стратегия, тем сильнее транзакционные издержки влияют на результат. Если ваша «норма доходности» образуется алгоритмами со средней сделкой < 0.1%, тестировать их без учета накладных расходов нет смысла, в топы вылезет дребедень.
Существуют активы с ярко выраженной сезонностью, и без сезонности. Есть и другие существенные отличия активов друг от друга. И если с Си на юань системы переносятся, то на спай уже нет. Поэтому при поиске систем «на все рынки» мы теряем в эффективности. 
Можно подбирать «системы на все рынки», а можно портфель из систем «на каждый рынок свои». Второй подход дает бОльшую робастность уже не в каждой системе, а в портфеле. 
avatar
SergeyJu, это верно лишь отчасти.
Если изменить мышление и искать системы иначе, они необязательно будут работать хуже на других рынках. И потом, рынок — это слишком общее понятие, тут о конкретных инструментах, видимо, нужно говорить.

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

Ключевое я выделил жирным и ни у кого пока таких систем не видел. Все всё подстраивают руками вне торгов. Система, которая сама адаптируется к рынку в ходе торгов должна быть, но никто её не видел :)

avatar
bascomo, вне практического смысла, не сложно написать систему, которая подстраивается под рынок на каждый новый такт данных. Достаточно жесткие системы, к которых подстраивается один, максимум два простых параметра. Например, % тейка и %профита. Но в  этой ситуации проще иметь набор систем с разными тейками и профитами в общем пятне пригодных значений, чем заниматься постоянной подгонкой. 
С другой стороны, существенное изменение рыночных условий — это недели, месяцы, годы. Только при накоплении достаточного в каком-то смысле объема данных, переоптимизация систем начинает иметь смысл. Для меня этот параметр  примерно полгода-год, не менее, часто более. И зачастую речь идет не о перенастройке систем, сколько о вводе небольшого количества новых, изъятии нескольких старых или о просто балансировке их весов.
avatar
SergeyJu, практический смысл — чистый финрез, если у подстраивающейся системы он выше, то о чём дискутировать?
avatar
bascomo, кроме финреза важно кое-что еще. Емкость, проскальзывание, просадка, устойчивость например. И ПЕРЕподгонка тоже имеет значение. 

avatar
SergeyJu, финрез, по сути, это есть производная от всех этих параметров. Они в нём уже учтены. Если он правильно посчитан, конечно.
avatar
bascomo, блажен, кто верует, тепло ему на свете.
avatar
SergeyJu, кто верует, тот просто спит, как 99% населения планеты
avatar
bascomo, финрез_посчитанный(tm) имеет нулевую ценность, если он далек от финреза, полученного в торгах. И раздувание виртуального финреза не помогает в уменьшении разницы с реальным. На тестах может быть +1000%, а в торгах нехилый минус. И оптимизация тестов до 10000% не сделает реальный минус плюсом, а скорее всего приведет к всплытию еще более стремных стратегий.
Хорошая статья
Я не математик. Но вроде как кросс-валидация рекомендуется, если данных недостаточно. К тому же увеличение K-fold может привести к переподгонке.  Мне кажется, если данных достаточно, то форвардного тестирования вполне хватит.
avatar
Riskplayer, рецептов безграничное множество, каждый может составить блюдо по своему вкусу.
avatar

теги блога bascomo

....все тэги



UPDONW
Новый дизайн