Я пытался найти одну закономерность для пяти пар и задетектировать процент правильно угаданных сделок на валидационной выборке в 25 лет примерно. Не получилось с ходу. Для любого взятого горизонта прогноза не достиг желаемой точности.
Далее, возьмем лишь одну пару eurusd. У нее я обнаружил зависимость исхода движения цены на 3 часа вперед от некоторого поднабора моих предикторов.
Я привел предикторы к категориальному виду и запустил свою функцию поиска значимых предикторов. Сделал прямо сейчас, пока на работе, за 20 минут.
Сходимости так быстро не добился, но некоторый результат на уровне полтора процента объясняющей способности получил.
График сходимости (минимизация).
Далее - построение модели.
У нас несколько категориальных предикторов. Строим "книгу правил" или то, какая именно зависимость есть между предикторами и 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.
И код всего эксперимента, начиная с момента, когда входы уже отобраны:
Далее, есть 49 валидационных выборок, каждая покрывающая 5 лет примерно. Вот на них валидируем модель, будем считать процент правильно угаданных направлений торговли.
Смотрим - процент правильно угаданных сделок по выборкам и гистограмма этого значения:
И считаем сколько всего на всех выборках мы угадываем направление сделки:
Около 54%. Но без учета того, что нужно преодолеть расстояние между Ask & Bid. То есть, пороговая величина согласно выше приведенному графику примерно на уровне 53% при условии, что спред = 1 пункт.
То есть, мы за 30 минут состряпали простую модель, которую легко захардкодить в терминале, например. И это даже не комитет. И искал зависимости я 20 минут вместо 20 часов. В общем, что-то есть.
И все благодаря правильному отбору информативных признаков.
Начало по ссылкам: 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) любые разновидности машек относятся к шуму!
То что вы видите это малая часть рынка и то не самая важная. Никто не строит пирамиду вверх ногами.
Попробовал обучить нейронку на входных данных, потом посмотрел на веса. Если у входных данных малый вес, то он видимо не нужен. Делал через 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
В статье описано использование пакета Rattle для автоматического поиска паттернов, способных предсказывать "лонги" и "шорты" для валютных пар рынка Форекс. Статья будет полезна как новичкам, так и опытным трейдерам.
Попробовал обучить нейронку на входных данных, потом посмотрел на веса. Если у входных данных малый вес, то он видимо не нужен. Делал через 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 явно выделяются, такого набора думаю хватит.
Уточню условия для получения денежного приза:
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х часов.
Как она выглядит в результате:
Видим перекос количества бай и селл в каждой строке и соответствующее таким цифрам значение 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 часов. В общем, что-то есть.
И все благодаря правильному отбору информативных признаков.
И детальная статистика по каждой валид. выборке.
Все исходные данные доступны по ссылкам в блоге.
И эта модель едва ли сильно прибыльна. МО на уровне пол пункта. Но направления придерживаюсь именно такого.
Всегда учимся на прошлом.
Смотрим столетиями на график. Оба на и видим "три солдата", потом видим "голова и плечи". Сколько уже таких фигур увидели и верим в эти фигуры, торгуем...
А если задачу поставить так:
1. Автоматические найти такие фигуры, причем не вообще ко всем графикам, а к конкретной валютной паре, те которые встречались недавно, а не три века назад у японцев при торговле рисом.
2. А годятся ли у нас те исходные данные, на которых мы автоматически ищем такие фигуры - паттерны.
Для ответа на первый вопрос рассмотрим алгоритм, который называется "лес случайных деревьев" - random forest. Алгоритм в качестве исходных данных для своей работы берет котировку одной или нескольких валют, индикаторы, приращения цен - все, что напридумывал человек. 10-5-100-200 ... входных переменных. Затем берет весь набор значений переменных, относящихся к одному моменту времени, соответствующих одному бару и ищет такую комбинацию этих входных переменных, которая бы соответствовала на исторических данных вполне определенному результату, например, ордеру BUY. А другой набор комбинаций другому ордеру - SELL. Каждому такому набору соответствует отдельное дерево. Опыт показывает, что для входного набора часовика из 18000 баров (около 3-х лет) алгоритм находит 200-300 деревьев. Это и есть набор паттернов, почти аналоги "голов и плеч", и целых рот солдатов.
Проблема в этом алгоритме состоит в том, что такие деревья могут ухватить некоторую конкретику, которая не встретится в будущем. Это называется здесь на форуме "сверхподгонка", в машинном обучении "переобучение". Известно, что весь большой набор исходных переменных можно поделить на две части: относящиеся к выходной переменной и не имеющие отношение шум. Вот Бурнаков и пытается отсеять те, которые не имеют отношения к результату.
ПС.
При построении трендовых ТС (BUY, SELL) любые разновидности машек относятся к шуму!
То что вы видите это малая часть рынка и то не самая важная. Никто не строит пирамиду вверх ногами.
То что вы видите это малая часть рынка и то не самая важная. Никто не строит пирамиду вверх ногами.
Попробовал обучить нейронку на входных данных, потом посмотрел на веса. Если у входных данных малый вес, то он видимо не нужен. Делал через R (Rattle), спасибо СанСанычу за его статью https://www.mql5.com/ru/articles/1165.
На практике я такой подход не проверял, интересно получилось или нет. Я бы взял input_1 input_3 input_5 input_7 input_9 input_11
Попробовал обучить нейронку на входных данных, потом посмотрел на веса. Если у входных данных малый вес, то он видимо не нужен. Делал через R (Rattle), спасибо СанСанычу за его статью https://www.mql5.com/ru/articles/1165.
На практике я такой подход не проверял, интересно получилось или нет. Я бы взял input_1 input_3 input_5 input_7 input_9 input_11
) хм. очень интересно получилось.
Уточняющий вопрос. А почему вы не включите тогда еще несколько входов, где вес небольшой, например, 13, 14, 16? Могли бы вы показать диаграмму входов и весов в упорядочиванием по весу?
Сори, не понял сначала. Да у указанных входов большой по модулю вес, как и должно быть.
Визуально все веса делятся на две группы. Если нужно их поделить по принципу значимые/не значимые, то 5,11,7,1,3,9 явно выделяются, такого набора думаю хватит.