Машинное обучение в трейдинге: теория, модели, практика и алготорговля - страница 7

 
Dr.Trader:

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

Результаты ниже относятся к обучению на R1.F3

1) С Rattle вышел забавный результат. НН со стандартной конфигурацией показала ошибки train/validate/testing - 30%/29%/33%. Ошибка на R2.F3 - 35%. Но всё это просто удачный случай на самом деле, в другой конфигурации она бы легко недо- или переобучилась, тут просто повезло.

2) Потом я взял простой грубый подход с обучением без контроля, 200 скрытых нейронов, сеть обучалась пока результат не перестал улучшаться. Ошибки train/validate/testing/R2.F3  -  2%/30%/27%/45%. Ну это понятно, сеть переобучилась.

3) Обучение с контролем. Это отличается от деревьев, но с нейронкой так вообще всегда надо делать чтоб её не переобучить. Суть в том чтобы иногда приостанавливать обучение, и сверять результаты train/validate/testing. Золотого правила сверки результатов я не знаю, но вполне нормальный подход это обучать на train датасете, потом смотреть на ошибки в validate и testing датасетах, прекратить обучение когда ошибки в validate/testing перестанут понижаться. Это даёт какую-то гарантию от переобучения. R2.F3 во время всего этого процесса считается недоступным, и тест на нём делается только после конца обучения. В этом случае ошибки train/validate/testing/R2.F3  -  27%/30%/31%/37%. Тут опять наблюдается переобученность, но небольшая. Можно было остановить процесс обучения пораньше, после того как ошибка train стала заметно меньше ошибок validate/testing, но это уже гадание... могло помочь, а могло бы и нет.

 

У "R1.F1" целевая переменная имеет три значения, Rattle так не умеет с нейронкой, и нужно писать свой код на R, я этот датасет пропустил.

"R1.F4" "R1.F5" "R1.F6" давали в нейронке в Rattle примерно такие-же результаты для всех 4 ошибок, мне кажется адекватный подход с нейронкой тоже даст примерно теже результаты, я с ними дальше не занимался.

Я имею аналогичные цифры для леса и ada.

А теперь, если вернуться к нашим "баранам" - как отбросить из произвольного перечня предикторов шум? У меня имеется некий эмпирический алгоритм, который отобрал мои 27 предикторов из 170. Кроме этого я его использовал  для анализа чужих наборов предикторов и тоже удачно. На основании этого опыта я утверждаю, что все методы из R, которые в своих алгоритмах используют "важность" переменных, не могут очистить набор предикторов от шума. 

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

 Кроме этого.

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

Файлы:
 
СанСаныч Фоменко:

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

Спасибо, полистал документ, но то что мне нужно не нашёл. Я пытаюсь свою модель обучить для форекса, где-то в переделах M15-H4. Мне не достаточно просто взять данные за последний бар, нужно их брать за десятки баров сразу, и ставить друг за другом в один длинный массив для входов модели. Например (open_bar1, close_bar1, hh_bar1, open_bar2, close_bar2, hh_bar2, open_bar3, close_bar3, hh_bar3,...). Если какой-то способ отбора скажет мне что нужно убрать время второго бара, то мне не поможет, способ должен сказать что можно убрать например все данные о времени (индексы 3,6,9...).

Я правильно понял что в вашем файле  ALL_cod.RData можно использовать для обучения также Rat_DF1 (указав нужный таргет), а затем для проверки использовать Rat_DF2 и Rat_DF3? Я приатачил свой код на R для тех кому интересно, он реализует обучение нейронной сети с контролем ошибки. Для выбора другой целевой переменной можно просто заменить в файле автозаменой "Short_Long.75" на что-то из "Short_Long.35", "Flet_Long", "Short_Flet", "Flet_In". Так удобней чем подставлять разные датасеты.

Файлы:
 
Dr.Trader:
Я пытаюсь свою модель обучить для форекса, где-то в переделах M15-H4. Мне не достаточно просто взять данные за последний бар, нужно их брать за десятки баров сразу, и ставить друг за другом в один длинный массив для входов модели. Например (open_bar1, close_bar1, hh_bar1, open_bar2, close_bar2, hh_bar2, open_bar3, close_bar3, hh_bar3,...). Если какой-то способ отбора скажет мне что нужно убрать время второго бара, то мне не поможет, способ должен сказать что можно убрать например все данные о времени (индексы 3,6,9...).

mmm Данные о времени могут быть нужны, так рынки по сессиям различно работают.

Посмотрите, какой у меня набор фичей для форекса:

 

> names(sampleA)

  [1] "lag_diff_2"        "lag_diff_3"        "lag_diff_4"        "lag_diff_6"        "lag_diff_8"        "lag_diff_11"       "lag_diff_16"     

  [8] "lag_diff_23"       "lag_diff_32"       "lag_diff_45"       "lag_diff_64"       "lag_diff_91"       "lag_diff_128"      "lag_diff_181"    

 [15] "lag_diff_256"      "lag_diff_362"      "lag_diff_512"      "lag_diff_724"      "lag_mean_diff_2"   "lag_mean_diff_3"   "lag_mean_diff_4" 

 [22] "lag_mean_diff_6"   "lag_mean_diff_8"   "lag_mean_diff_11"  "lag_mean_diff_16"  "lag_mean_diff_23"  "lag_mean_diff_32"  "lag_mean_diff_45"

 [29] "lag_mean_diff_64"  "lag_mean_diff_91"  "lag_mean_diff_128" "lag_mean_diff_181" "lag_mean_diff_256" "lag_mean_diff_362" "lag_mean_diff_512"

[36] "lag_mean_diff_724" "lag_max_diff_2"    "lag_max_diff_3"    "lag_max_diff_4"    "lag_max_diff_6"    "lag_max_diff_8"    "lag_max_diff_11" 

 [43] "lag_max_diff_16"   "lag_max_diff_23"   "lag_max_diff_32"   "lag_max_diff_45"   "lag_max_diff_64"   "lag_max_diff_91"   "lag_max_diff_128"

 [50] "lag_max_diff_181"  "lag_max_diff_256"  "lag_max_diff_362"  "lag_max_diff_512"  "lag_max_diff_724"  "lag_min_diff_2"    "lag_min_diff_3"  

 [57] "lag_min_diff_4"    "lag_min_diff_6"    "lag_min_diff_8"    "lag_min_diff_11"   "lag_min_diff_16"   "lag_min_diff_23"   "lag_min_diff_32" 

 [64] "lag_min_diff_45"   "lag_min_diff_64"   "lag_min_diff_91"   "lag_min_diff_128"  "lag_min_diff_181"  "lag_min_diff_256"  "lag_min_diff_362"

 [71] "lag_min_diff_512"  "lag_min_diff_724"  "lag_sd_2"          "lag_sd_3"          "lag_sd_4"          "lag_sd_6"          "lag_sd_8"        

 [78] "lag_sd_11"         "lag_sd_16"         "lag_sd_23"         "lag_sd_32"         "lag_sd_45"         "lag_sd_64"         "lag_sd_91"       

 [85] "lag_sd_128"        "lag_sd_181"        "lag_sd_256"        "lag_sd_362"        "lag_sd_512"        "lag_sd_724"        "lag_range_2"     

 [92] "lag_range_3"       "lag_range_4"       "lag_range_6"       "lag_range_8"       "lag_range_11"      "lag_range_16"      "lag_range_23"    

 [99] "lag_range_32"      "lag_range_45"      "lag_range_64"      "lag_range_91"      "lag_range_128"     "lag_range_181"     "lag_range_256"   

[106] "lag_range_362"     "lag_range_512"     "lag_range_724"     "symbol"            "month"             "day"               "week_day"        

[113] "hour"              "minute"            "future_lag_2"      "future_lag_3"      "future_lag_4"      "future_lag_6"      "future_lag_8"    

[120] "future_lag_11"     "future_lag_16"     "future_lag_23"     "future_lag_32"     "future_lag_45"     "future_lag_64"     "future_lag_91"   

[127] "future_lag_128"    "future_lag_181"    "future_lag_256"    "future_lag_362"    "future_lag_512"    "future_lag_724"

 

 Я беру и данные от скользящих средних, и максимумы, и минимумы, и размах цен в окне. И время, и дни и даже месяцы )

 

Мои алгоритмы могут реально оставить из 114 предикторов 10 или даже 5. Это нормально. В таких данных сильная корреляция между ПРЕДИКТОРАМИ и следовательно присутствует сильная избыточность. 

 

Расскажу про свой метод отбора информативных признаков кратко. Код прилагается.

 

Есть две стороны вопроса - как отбирать поднаборы и как мерять релевантность отобранных предикторов выходной переменной.

 

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

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

 

Второй вопрос - еще более тонкий. Фитнесс-функция.

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

 

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

 

Я остановил выбор на категориальных данных, так как под них есть хорошие средства из Теории информации. Если сказать совсем просто: есть вход и выход. Если состояние выхода хотя-бы чуть чуть зависит от входа (вероятностно), то они зависимы. Есть такая штука - взаимная информация. Она это и меряет.

Теперь глубже. ВИ меряет нечто на наблюдаемом распределении на выборке конечного размера. Это конечно точечная оценка.

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

Еще глубже. Если у нас два и более предиктора - что с ними делать?

 

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

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

 

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

 

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

 

В принципе результат таков обычно:

 

[1] "1.69%"

> final_vector <- c((sao$par >= threshold), T)

> names(sampleA)[final_vector]

 [1] "lag_diff_23"      "lag_diff_45"      "lag_mean_diff_2"  "lag_mean_diff_8"  "lag_max_diff_11"  "lag_max_diff_181" "lag_min_diff_3"   "lag_min_diff_724"

 [9] "lag_sd_724"       "lag_range_32"     "symbol" "future_lag_181"  

 

 После полутора суток работы и перебора десятков тысяч комбинаций предикторов функция выдает значение фитнесс-функции - это значимая взаимная информация пенализированная на наличие избыточности в наборе предикторов. И сами предикторы.

 

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

Вот, например, выше у меня 1.7% от полной детерминированности (что для форекса неплохо) и куча входов, которые в совокупности значимо на уровне доверия 0.1 (я так поставил эксперимент) определяют состояние выхода (бинарного). То есть, явно информация в форексных данных присутствует. Вопрос - доказан экспериментально.

После этого можно оценивать на валидации прибыльность и кодить торговую систему.

 

Алексей 

Файлы:
 
Dr.Trader:


Я правильно понял что в вашем файле  ALL_cod.RData можно использовать для обучения также Rat_DF1 (указав нужный таргет), а затем для проверки использовать Rat_DF2 и Rat_DF3? Я приатачил свой код на R для тех кому интересно, он реализует обучение нейронной сети с контролем ошибки. Для выбора другой целевой переменной можно просто заменить в файле автозаменой "Short_Long.75" на что-то из "Short_Long.35", "Flet_Long", "Short_Flet", "Flet_In". Так удобней чем подставлять разные датасеты.

Да. Именно для удобства в rattle.

Еще один нюанс.

Все целевые переменные получены из двух ЗЗ: ЗЗ(35) и ЗЗ(25). И вот здесь один очень неприятный нюанс, который перекликается с Вашим.

Целевая переменная - это последовательность 0 и 1, что соответствует плечу ЗЗ. Но мы ВСЕГДА предсказываем отдельный элемент  плеча ЗЗ, а не само плечо. Поэтому говорить, что мы предсказываем тренды, неправильно. Правильно говорить, что предсказывается элемент тренда. А если сложить все предсказанные элементы тренда, то тренд скорее всего и не получится.

 

Спасибо за feature_selector_modeller.zip, буду разбираться. 

СанСаныч Фоменко:

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

Я приатачил файл, это набор данных с форекса. Внутри RData с двумя датасетами, для тренировки и для валидации. Физически данные в двух датасетах идут друг за другом, они поделены на два файла просто для удобства тестирования модели. Модель на этом датасете обучить можно, я вручную отсеивал предикторы и обучал нейронку, в итоге минимальная ошибка на валидационном датасете была 46%, что на самом деле не прибыльно. О реальном профите можно думать если ошибка упадёт меньше 40%. Попробуйте отсеять предикторы из этого файла пожалуйста.

СанСаныч Фоменко:

Целевая переменная - это последовательность 0 и 1, что соответствует плечу ЗЗ. Но мы ВСЕГДА предсказываем отдельный элемент  плеча ЗЗ, а не само плечо. Поэтому говорить, что мы предсказываем тренды, неправильно. Правильно говорить, что предсказывается элемент тренда. А если сложить все предсказанные элементы тренда, то тренд скорее всего и не получится.

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

Другой вариант это зигзаг, или другие трендовые индикаторы. У меня с ним получались какие-то положительные результаты, но при условии что результат нейронки проходил через фильтр. Например брать среднее от результатов за последние бары, или использовать результаты только выше какого-то порогового значения. Я считаю что это всё не стоит применять, тут больше гадания чем точных вычислений. Проблема в том что от модели требуется давать только сигналы на покупку следующих 10-20 баров, а она иногда среди них даёт сигнал на продажу. В таком случае сделка переворачивается, платится комиссия и спред, и так несколько раз за тренд. Поэтому нужно либо добиться высокой точности, либо сглаживать результат чтоб не было таких переворотов на всего один бар. То есть да, как вы и сказали предсказывается только элемент тренда, а сам тренд из таких элементов сложить не очень получается.

Файлы:
set56.RData.zip  525 kb
 
Dr.Trader:


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


У меня результаты стабильно противоположные. Я легко прогнозирую движение цены на несколько минут вперед (до часа) с точностью 55% (Ask to Ask). Лучший результат для 23 минут. Это бинарная классификация на валидационных выборках.

А при повышении горизонта прогноза точность медленно падает вплоть до 51% на 12 часов вперед. И эта зависимость есть на всей истории. Но точность должна быть еще выше, чтобы выйти в плюс (преодолеть расстояние Ask - Bid).

 

 Обсудим потом еще. 

 
Dr.Trader:

Спасибо за feature_selector_modeller.zip, буду разбираться. 

Я приатачил файл, это набор данных с форекса. Внутри RData с двумя датасетами, для тренировки и для валидации. Физически данные в двух датасетах идут друг за другом, они поделены на два файла просто для удобства тестирования модели. Модель на этом датасете обучить можно, я вручную отсеивал предикторы и обучал нейронку, в итоге минимальная ошибка на валидационном датасете была 46%, что на самом деле не прибыльно. О реальном профите можно думать если ошибка упадёт меньше 40%. Попробуйте отсеять предикторы из этого файла пожалуйста.


Не нашел ни одного предиктора - все шум. Предсказательной способностью Ваши предикторы для Вашей целевой переменной не обладают. Некие намеки 54,55,56. Из них может быть удастся что-получить... А так,  по моим представлениям, все можно выкинуть.
 
Ясно, спасибо, буду искать другие исходные данные.
 
Dr.Trader:
Ясно, спасибо, буду искать другие исходные данные.

Подождите. Я тоже прогоню ваши данные на предмет зависимостей.

 

Один вопрос пока я не начал. Ваши данные включают в себя все бары подряд, или было прореживание баров перед составлением выборок? 

Причина обращения: