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

 

Уточню условия для получения денежного приза:

5 кредитов получит первый разгадавший задачу

Крайний срок рассмотрения решений:  30 июня 2016 г.

 

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

Наверное, вы читали мои блоги о Большом эксперименте: https://www.mql5.com/ru/blogs/post/661895

 

И вот такая картинка:

 

 

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

 

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

 

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

 

[1] "1.51%"

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

> names(sampleA)[final_vector]

[1] "lag_diff_45_var"      "lag_diff_128_var"     "lag_max_diff_8_var"   "lag_max_diff_11_var"  "lag_max_diff_724_var" "lag_sd_362_var"      

[7] "output"   

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

График сходимости (минимизация). 

 

 

Далее - построение модели.

 

У нас несколько категориальных предикторов. Строим "книгу правил" или то, какая именно зависимость есть между предикторами и output - лонг или шорт в перспективе 3х часов.

Как она выглядит в результате:

уровни предикторов
sell
buy
pval
concat
direction
121121
11
31
2.03E-03
121121
1
211112
3
15
4.68E-03
211112
1
222222
19
4
1.76E-03
222222
0
222311
8
0
4.68E-03
222311
0
321113
7
0
8.15E-03
321113
0
333332
53
19
6.15E-05
333332
0

 Видим перекос количества бай и селл в каждой строке и соответствующее таким цифрам значение p-value критерия хи-квадрат на соответствие распределению 50/50. Выбираем только те строки, где вероятность ниже 0.01.

 

 И код всего эксперимента, начиная с момента, когда входы уже отобраны:

dat_test <- sampleA[, c("lag_diff_45_var"      

  , "lag_diff_128_var"     

  , "lag_max_diff_8_var"   

  , "lag_max_diff_11_var"  

  , "lag_max_diff_724_var" 

  , "lag_sd_362_var"

  , "output")]


dat_test$concat <- do.call(paste0, dat_test[1:(ncol(dat_test) - 1)])


x <- as.data.frame.matrix(table(dat_test$concat

   , dat_test$output))


x$pval <- NA

for (i in 1:nrow(x)){

x$pval[i] <- chisq.test(x = c(x$`0`[i], x$`1`[i])

, p = c(0.5, 0.5))$p.value

}


trained_model <- subset(x

  , x$pval < 0.01)


trained_model$concat <- rownames(trained_model)


trained_model$direction <- NA

trained_model$direction [trained_model$`1` > trained_model$`0`] <- 1

trained_model$direction [trained_model$`0` > trained_model$`1`] <- 0


### test model


load('C:/Users/aburnakov/Documents/Private/big_experiment/many_test_samples.R')


many_test_samples_eurusd_categorical <- list()


for (j in 1:49){


dat <- many_test_samples[[j]][, c(1:108, 122)]

disc_levels <- 3

for (i in 1:108){

naming <- paste(names(dat[i]), 'var', sep = "_")

dat[, eval(naming)] <- discretize(dat[, eval(names(dat[i]))], disc = "equalfreq", nbins = disc_levels)[,1]

}

dat$output <- NA

dat$output [dat$future_lag_181 > 0] <- 1

dat$output [dat$future_lag_181 < 0] <- 0

many_test_samples_eurusd_categorical[[j]] <- subset(dat

   , is.na(dat$output) == F)[, 110:218]

many_test_samples_eurusd_categorical[[j]] <- many_test_samples_eurusd_categorical[[j]][(nrow(dat) / 5):(2 * nrow(dat) / 5), ]


}



correct_validation_results <- data.frame()


for (i in 1:49){

dat_valid <- many_test_samples_eurusd_categorical[[i]][, c("lag_diff_45_var"      

   , "lag_diff_128_var"     

   , "lag_max_diff_8_var"   

   , "lag_max_diff_11_var"  

   , "lag_max_diff_724_var" 

   , "lag_sd_362_var"

   , "output")]

dat_valid$concat <- do.call(paste0, dat_valid[1:(ncol(dat_valid) - 1)])

y <- as.data.frame.matrix(table(dat_valid$concat

   , dat_valid$output))

y$concat <- rownames(y)


valid_result <- merge(x = y, y = trained_model[, 4:5], by.x = 'concat', by.y = 'concat')

correct_sell <- sum(subset(valid_result

 , valid_result$direction == 0)[, 2])

correct_buys <- sum(subset(valid_result

     , valid_result$direction == 1)[, 3])

correct_validation_results[i, 1] <- correct_sell

correct_validation_results[i, 2] <- correct_buys

correct_validation_results[i, 3] <- sum(correct_sell

    , correct_buys)

correct_validation_results[i, 4] <- sum(valid_result[, 2:3])

correct_validation_results[i, 5] <- correct_validation_results[i, 3] / correct_validation_results[i, 4]


}


hist(correct_validation_results$V5, breaks = 10)


plot(correct_validation_results$V5, type = 's')

sum(correct_validation_results$V3) / sum(correct_validation_results$V4)

 

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

Смотрим - процент правильно угаданных сделок по выборкам и гистограмма этого значения:

 

 

И считаем сколько всего на всех выборках мы угадываем направление сделки:

> sum(correct_validation_results$`total correct deals`) / sum(correct_validation_results$`total deals`)

[1] 0.5361318

 Около 54%. Но без учета того, что нужно преодолеть расстояние между Ask & Bid. То есть, пороговая величина согласно выше приведенному графику примерно на уровне 53% при условии, что спред = 1 пункт.

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

 

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

 

 И детальная статистика по каждой валид. выборке.

sample
correct sell correct buy total correct deals total deals share correct
1 37 10 47 85 0.5529412
2 26 7 33 65 0.5076923
3 30 9 39 80 0.4875
4 36 11 47 88 0.5340909
5 33 12 45 90 0.5
6 28 10 38 78 0.4871795
7 30 9 39 75 0.52
8 34 8 42 81 0.5185185
9 24 11 35 67 0.5223881
10 23 14 37 74 0.5
11 28 13 41 88 0.4659091
12 31 13 44 82 0.5365854
13 33 9 42 80 0.525
14 23 7 30 63 0.4761905
15 28 12 40 78 0.5128205
16 23 16 39 72 0.5416667
17 30 13 43 74 0.5810811
18 38 8 46 82 0.5609756
19 26 8 34 72 0.4722222
20 35 12 47 79 0.5949367
21 32 11 43 76 0.5657895
22 30 10 40 75 0.5333333
23 28 8 36 70 0.5142857
24 21 8 29 70 0.4142857
25 24 8 32 62 0.516129
26 34 15 49 83 0.5903614
27 24 9 33 63 0.5238095
28 26 14 40 66 0.6060606
29 35 6 41 84 0.4880952
30 28 8 36 74 0.4864865
31 26 14 40 79 0.5063291
32 31 15 46 88 0.5227273
33 35 14 49 93 0.5268817
34 35 19 54 85 0.6352941
35 27 8 35 64 0.546875
36 30 10 40 83 0.4819277
37 36 9 45 79 0.5696203
38 25 8 33 73 0.4520548
39 39 12 51 85 0.6
40 37 9 46 79 0.5822785
41 41 12 53 90 0.5888889
42 29 7 36 59 0.6101695
43 36 14 50 77 0.6493506
44 36 15 51 88 0.5795455
45 34 7 41 67 0.6119403
46 28 12 40 75 0.5333333
47 27 11 38 69 0.5507246
48 28 16 44 83 0.5301205
49 29 10 39 72 0.5416667
СОПРОВОЖДЕНИЕ ЭКСПЕРИМЕНТА ПО АНАЛИЗУ ДАННЫХ ФОРЕКСА: доказательство значимости предсказаний
СОПРОВОЖДЕНИЕ ЭКСПЕРИМЕНТА ПО АНАЛИЗУ ДАННЫХ ФОРЕКСА: доказательство значимости предсказаний
  • 2016.03.02
  • Alexey Burnakov
  • www.mql5.com
Начало по ссылкам: https://www.mql5.com/ru/blogs/post/659572 https://www.mql5.com/ru/blogs/post/659929 https://www.mql5.com/ru/blogs/post/660386 https://www.mql5.com/ru/blogs/post/661062
 

Все исходные данные доступны по ссылкам в блоге.

И эта модель едва ли сильно прибыльна. МО на уровне пол пункта. Но направления придерживаюсь именно такого. 

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

Всегда учимся на прошлом.

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

А если задачу поставить так:

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

2. А годятся ли у нас те исходные данные, на которых мы автоматически ищем такие фигуры - паттерны.

Для ответа на первый вопрос рассмотрим алгоритм, который называется "лес случайных деревьев" - random forest. Алгоритм в качестве исходных данных для своей работы берет котировку одной или нескольких валют, индикаторы, приращения цен - все, что напридумывал человек. 10-5-100-200 ... входных переменных. Затем берет весь набор значений переменных, относящихся к одному моменту времени, соответствующих одному бару и ищет такую комбинацию этих входных переменных, которая бы соответствовала на исторических данных вполне определенному результату, например, ордеру BUY. А другой набор комбинаций другому ордеру - SELL. Каждому такому набору соответствует отдельное дерево. Опыт показывает, что для входного набора часовика из 18000 баров (около 3-х лет) алгоритм находит 200-300 деревьев. Это и есть набор паттернов, почти аналоги "голов и плеч", и целых рот солдатов.

Проблема в этом алгоритме состоит в том, что такие деревья могут ухватить некоторую конкретику, которая не встретится в будущем. Это называется здесь на форуме "сверхподгонка", в машинном обучении "переобучение".  Известно, что весь большой набор исходных переменных можно поделить на две части: относящиеся к выходной переменной и не имеющие отношение шум. Вот Бурнаков и пытается отсеять те, которые не имеют отношения к результату.

 

ПС.

При построении трендовых ТС (BUY, SELL) любые разновидности машек относятся к шуму! 

То что вы видите это малая часть рынка и то не самая важная. Никто не строит пирамиду вверх ногами.
 
yerlan Imangeldinov:
То что вы видите это малая часть рынка и то не самая важная. Никто не строит пирамиду вверх ногами.
А конкретнее, что не вижу?
 
yerlan Imangeldinov:
То что вы видите это малая часть рынка и то не самая важная. Никто не строит пирамиду вверх ногами.
 Вы можете добавить в систему информацию помимо истории цены. Но обучать все равно на истории придется. Или - Чуйка.
 

Попробовал обучить нейронку на входных данных, потом посмотрел на веса. Если у входных данных малый вес, то он видимо не нужен. Делал через R (Rattle), спасибо СанСанычу за его статью https://www.mql5.com/ru/articles/1165.

input input_1 input_2 input_3 input_4 input_5 input_6 input_7 input_8 input_9 input_10 input_11 input_12 input_13 input_14 input_15 input_16 input_17 input_18 input_19 input_20
вес -186.905 7.954625 -185.245 14.88457 -206.037 16.03497 190.0939 23.05248 -182.923 4.268967 196.8927 16.43655 5.419367 8.76542 36.8237 5.940322 8.304859 8.176511 17.13691 -0.57317
поднабор да   да   да   да   да   да                  

На практике я такой подход не проверял, интересно получилось или нет. Я бы взял input_1 input_3 input_5 input_7 input_9 input_11

Случайные леса предсказывают тренды
Случайные леса предсказывают тренды
  • 2014.09.29
  • СанСаныч Фоменко
  • www.mql5.com
В статье описано использование пакета Rattle для автоматического поиска паттернов, способных предсказывать "лонги" и "шорты" для валютных пар рынка Форекс. Статья будет полезна как новичкам, так и опытным трейдерам.
 
Dr.Trader:

Попробовал обучить нейронку на входных данных, потом посмотрел на веса. Если у входных данных малый вес, то он видимо не нужен. Делал через R (Rattle), спасибо СанСанычу за его статью https://www.mql5.com/ru/articles/1165.

input input_1 input_2 input_3 input_4 input_5 input_6 input_7 input_8 input_9 input_10 input_11 input_12 input_13 input_14 input_15 input_16 input_17 input_18 input_19 input_20
вес -186.905 7.954625 -185.245 14.88457 -206.037 16.03497 190.0939 23.05248 -182.923 4.268967 196.8927 16.43655 5.419367 8.76542 36.8237 5.940322 8.304859 8.176511 17.13691 -0.57317
поднабор да   да   да   да   да   да                  

На практике я такой подход не проверял, интересно получилось или нет. Я бы взял input_1 input_3 input_5 input_7 input_9 input_11

) хм. очень интересно получилось.

Уточняющий вопрос. А почему вы не включите тогда еще несколько входов, где вес небольшой, например, 13, 14, 16? Могли бы вы показать диаграмму входов и весов в упорядочиванием по весу? 

 

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

 

Визуально все веса делятся на две группы. Если нужно их поделить по принципу значимые/не значимые, то 5,11,7,1,3,9 явно выделяются, такого набора думаю хватит.