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

 
Dr.Trader:

Я пробовал Y-scale тоже, R^2 у меня в обоих случаях (с и без Y-scale) выходил одинаковый (даже не смотря на то что в этих случаях используются разные пакеты!).

Я так понял что Y-scale может дать тот-же хороший результат с меньшим числом главных компонент. Но, если используя даже все компоненты результат всё равно неудовлетворителен (как у меня сейчас) - то разницы не будет. Плюс так работает быстрее, что мне сейчас важнее. Правда я ещё не доказал себе теорией или практикой подходит ли вообще такой способ для отбора предикторов... Сначала была идея сделать модель главных компонент на всех предикторах, и отбирать предикторы смотря на коэффициенты в компонентах. Но потом я заметил что с добавлением мусора - R^2 модели падает. Логично попробовать разные наборы предикторов и искать те у которых R^2 выше, но всё-таки это просто теория.

Я тут регулярно вношу следующее предложение: если Вы мне перегоните свой набор, то мы сравним мои результаты с Вашими.

Для меня идеал - это .RData. Фрейм, в котором бинарная целевая, а предикторы желательно действительные числа.  

 
Dr.Trader:

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

Сейчас использую GetPCrsquared(), тот код что выше. Ещё есть ваш пример из feature_selector_modeller.txt, но там нужно разобраться и взять нужный кусок кода, поэтому ещё не проверял на своих данных.

там нужно взять вот что: 

library(infotheo) # measured in nats, converted to bits

library(scales)

library(GenSA)


#get data

sampleA <- read.table('C:/Users/aburnakov/Documents/Private/dummy_set_features.csv'

, sep= ','

, header = T)




#calculate parameters

predictor_number <- dim(sampleA)[2] - 1

sample_size <- dim(sampleA)[1]

par_v <- runif(predictor_number, min = 0, max = 1)

par_low <- rep(0, times = predictor_number)

par_upp <- rep(1, times = predictor_number)



#load functions to memory

shuffle_f_inp <- function(x = data.frame(), iterations_inp, quantile_val_inp){

mutins <- c(1:iterations_inp)

for (count in 1:iterations_inp){

xx <- data.frame(1:dim(x)[1])

for (count1 in 1:(dim(x)[2] - 1)){

y <- as.data.frame(x[, count1])

y$count <- sample(1 : dim(x)[1], dim(x)[1], replace = F)

y <- y[order(y$count), ]

xx <- cbind(xx, y[, 1])

}

mutins[count] <- multiinformation(xx[, 2:dim(xx)[2]])

}

quantile(mutins, probs = quantile_val_inp)

}



shuffle_f <- function(x = data.frame(), iterations, quantile_val){

height <- dim(x)[1]

mutins <- c(1:iterations)

for (count in 1:iterations){

x$count <- sample(1 : height, height, replace = F)

y <- as.data.frame(c(x[dim(x)[2] - 1], x[dim(x)[2]]))

y <- y[order(y$count), ]

x[dim(x)[2]] <- NULL

x[dim(x)[2]] <- NULL

x$dep <- y[, 1]

rm(y)

receiver_entropy <- entropy(x[, dim(x)[2]])

received_inf <- mutinformation(x[, 1 : dim(x)[2] - 1], x[, dim(x)[2]])

corr_ff <- received_inf / receiver_entropy

mutins[count] <- corr_ff

}

quantile(mutins, probs = quantile_val)

}


############### the fitness function

fitness_f <- function(par){

indexes <- c(1:predictor_number)

for (i in 1:predictor_number){

if (par[i] >= threshold) {

indexes[i] <- i

} else {

indexes[i] <- 0

}

}

local_predictor_number <- 0

for (i in 1:predictor_number){

if (indexes[i] > 0) {

local_predictor_number <- local_predictor_number + 1

}

}

if (local_predictor_number > 1) {

sampleAf <- as.data.frame(sampleA[, c(indexes[], dim(sampleA)[2])])

pred_entrs <- c(1:local_predictor_number)

for (count in 1:local_predictor_number){

pred_entrs[count] <- entropy(sampleAf[count])

}

max_pred_ent <- sum(pred_entrs) - max(pred_entrs)

pred_multiinf <- multiinformation(sampleAf[, 1:dim(sampleAf)[2] - 1])

pred_multiinf <- pred_multiinf - shuffle_f_inp(sampleAf, iterations_inp, quantile_val_inp)

if (pred_multiinf < 0){

pred_multiinf <- 0

}

pred_mult_perc <- pred_multiinf / max_pred_ent

inf_corr_val <- shuffle_f(sampleAf, iterations, quantile_val)

receiver_entropy <- entropy(sampleAf[, dim(sampleAf)[2]])

received_inf <- mutinformation(sampleAf[, 1:local_predictor_number], sampleAf[, dim(sampleAf)[2]])

if (inf_corr_val - (received_inf / receiver_entropy) < 0){

fact_ff <- (inf_corr_val - (received_inf / receiver_entropy)) * (1 - pred_mult_perc)

} else {

fact_ff <- inf_corr_val - (received_inf / receiver_entropy)

}

} else if (local_predictor_number == 1) {

sampleAf<- as.data.frame(sampleA[, c(indexes[], dim(sampleA)[2])])

inf_corr_val <- shuffle_f(sampleAf, iterations, quantile_val)

receiver_entropy <- entropy(sampleAf[, dim(sampleAf)[2]])

received_inf <- mutinformation(sampleAf[, 1:local_predictor_number], sampleAf[, dim(sampleAf)[2]])

fact_ff <- inf_corr_val - (received_inf / receiver_entropy)

} else  {

fact_ff <- 0

}

return(fact_ff)

}



########## estimating threshold for variable inclusion


iterations = 5

quantile_val = 1


iterations_inp = 1

quantile_val_inp = 1


levels_arr <- numeric()

for (i in 1:predictor_number){

levels_arr[i] <- length(unique(sampleA[, i]))

}


mean_levels <- mean(levels_arr)

optim_var_num <- log(x = sample_size / 100, base = round(mean_levels, 0))


if (optim_var_num / predictor_number < 1){

threshold <- 1 - optim_var_num / predictor_number

} else {

threshold <- 0.5

}



#run feature selection


start <- Sys.time()


sao <- GenSA(par = par_v, fn = fitness_f, lower = par_low, upper = par_upp

     , control = list(

      #maxit = 10

        max.time = 1200

        , smooth = F

        , simple.function = F))


trace_ff <- data.frame(sao$trace)$function.value

plot(trace_ff, type = "l")

percent(- sao$value)

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

names(sampleA)[final_vector]

final_sample <- as.data.frame(sampleA[, final_vector])


Sys.time() - start

 В датафрейме крайная правая колонка - целевая.

ВСЕ колонки должны быть категориями (ineteger, character or factor).

 

И загрузить все библы нужно. 

 

Кусок кода, который показывает, как перевести нюмерики в категориальные переменные:

disc_levels <- 3 # сколько равночастотных уровней переменной создается


for (i in 1:56){

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

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

}

 

Нашел в интернете такую интересную фунцыю

data_driven_time_warp <- function (y) {
  cbind(
    x = cumsum(c(0, abs(diff(y)))),
    y = y
  )
}


y <- cumsum(rnorm(200))+1000
i <- seq(1,length(y),by=10)
op <- par(mfrow=c(2,1), mar=c(.1,.1,.1,.1))
plot(y, type="l", axes = FALSE)
abline(v=i, col="grey")
lines(y, lwd=3)
box()
d <- data_driven_time_warp(y)
plot(d, type="l", axes=FALSE)
abline(v=d[i,1], col="grey")
lines(d, lwd=3)
box()
par(op)

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

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

Я тут регулярно вношу следующее предложение: если Вы мне перегоните свой набор, то мы сравним мои результаты с Вашими.

Для меня идеал - это .RData. Фрейм, в котором бинарная целевая, а предикторы желательно действительные числа.  

В атачменте мой лучший набор предикторов. trainData - D1 для eurusd за 2015 год, fronttestData - с 1 января 2016 по июнь. Фронттест длинноват, в реальной торговле я вряд ли буду торговать больше месяца с теми-же настройками, просто тут хотелось понаблюдать сколько реально продержится прибыльность модели. fronttestData1, fronttestData2, fronttestData3 - это отдельные вырезки из fronttestData, только за январь, только за февраль, только за март. Реально меня интересует понижение ошибки только на fronttestData1, остальное это просто для исследований.  В наборе предикторов содержатся в основном индикаторы и разные вычисления между ними. С nnet ошибка на фронттесте у меня 30% на fronttestData1, обучение с контролем итераций и подбором количества внутренних нейронов. Я считаю что 30% здесь это просто дело случая, модель поймала какую-то тенденцию на рынке с марта2015 по февраль2016. Но то что и остальные периоды не сливаются - уже хорошо.

Вот картинка с mt5 тестера 2014.01-2016.06, рамочкой я обозначил период тренировки. Уже лучше чем было :). Пока-что это мой предел, нужно решить очень много проблем с индикаторами, а именно то что их дефолтные параметры как будто строго привязаны к таймфреймам, например на H1 мой опыт совсем бесполезен, тот-же алгоритм отбора индикаторов на H1 всё считает мусором. Нужно или добавлять к первоначальному набору индикаторов кучу их вариаций с разными параметрами, или как-то самому генерировать рандомные индикаторы из ohlc.

 

Файлы:
 
Alexey Burnakov:

там нужно взять вот что: 

Так понятней, спасибо. Мне кажется всего 3 категории на индикатор не подойдёт. Логически я бы сделал хотябы 100 уровней, но будет ли так лучше, или от этого теряется весь смысл алгоритма?

 
Dr.Trader:

Так понятней, спасибо. Мне кажется всего 3 категории на индикатор не подойдёт. Логически я бы сделал хотябы 100 уровней, но будет ли так лучше, или от этого теряется весь смысл алгоритма?

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

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

Пример - хороший.

вход уровни | количество наблюдений

1                              150 

2                              120

...

9                              90

 здесь можно оценить значимость внутри отклика

Пример - плохой.

вход уровни

112                            5 

...

357                            2

... 

1045                          1

здесь нельзя оценить значимость внутри отклика 

 
Dr.Trader:

В атачменте мой лучший набор предикторов. trainData - D1 для eurusd за 2015 год, fronttestData - с 1 января 2016 по июнь. Фронттест длинноват, в реальной торговле я вряд ли буду торговать больше месяца с теми-же настройками, просто тут хотелось понаблюдать сколько реально продержится прибыльность модели. fronttestData1, fronttestData2, fronttestData3 - это отдельные вырезки из fronttestData, только за январь, только за февраль, только за март. Реально меня интересует понижение ошибки только на fronttestData1, остальное это просто для исследований.  В наборе предикторов содержатся в основном индикаторы и разные вычисления между ними. С nnet ошибка на фронттесте у меня 30% на fronttestData1, обучение с контролем итераций и подбором количества внутренних нейронов. Я считаю что 30% здесь это просто дело случая, модель поймала какую-то тенденцию на рынке с марта2015 по февраль2016. Но то что и остальные периоды не сливаются - уже хорошо.

Вот картинка с mt5 тестера 2014.01-2016.06, рамочкой я обозначил период тренировки. Уже лучше чем было :). Пока-что это мой предел, нужно решить очень много проблем с индикаторами, а именно то что их дефолтные параметры как будто строго привязаны к таймфреймам, например на H1 мой опыт совсем бесполезен, тот-же алгоритм отбора индикаторов на H1 всё считает мусором. Нужно или добавлять к первоначальному набору индикаторов кучу их вариаций с разными параметрами, или как-то самому генерировать рандомные индикаторы из ohlc.

 

 Неплохо, но сами периоды вне выборки невелики.

Еще не понятно, сколько сделок попадает вне выборки. Там десятки, сотни, какой порядок?

 
Dr.Trader:

В атачменте мой лучший набор предикторов. trainData - D1 для eurusd за 2015 год, fronttestData - с 1 января 2016 по июнь. Фронттест длинноват, в реальной торговле я вряд ли буду торговать больше месяца с теми-же настройками, просто тут хотелось понаблюдать сколько реально продержится прибыльность модели. fronttestData1, fronttestData2, fronttestData3 - это отдельные вырезки из fronttestData, только за январь, только за февраль, только за март. Реально меня интересует понижение ошибки только на fronttestData1, остальное это просто для исследований.  В наборе предикторов содержатся в основном индикаторы и разные вычисления между ними. С nnet ошибка на фронттесте у меня 30% на fronttestData1, обучение с контролем итераций и подбором количества внутренних нейронов. Я считаю что 30% здесь это просто дело случая, модель поймала какую-то тенденцию на рынке с марта2015 по февраль2016. Но то что и остальные периоды не сливаются - уже хорошо.

Вот картинка с mt5 тестера 2014.01-2016.06, рамочкой я обозначил период тренировки. Уже лучше чем было :). Пока-что это мой предел, нужно решить очень много проблем с индикаторами, а именно то что их дефолтные параметры как будто строго привязаны к таймфреймам, например на H1 мой опыт совсем бесполезен, тот-же алгоритм отбора индикаторов на H1 всё считает мусором. Нужно или добавлять к первоначальному набору индикаторов кучу их вариаций с разными параметрами, или как-то самому генерировать рандомные индикаторы из ohlc.

 

Посмотрел.

Правильно ли я понял, что в общем наборе данных 107 строчек (107 наблюдений)? 

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

Посмотрел.

Правильно ли я понял, что в общем наборе данных 107 строчек (107 наблюдений)? 

нет, в наборе для обучения 250-с-чем-то строк (количество торговых дней в 2015). Я обучал модель на таблице trainData. Тестировал - на fronttestData1. Всё остальное для дополнительных проверок, их можно игнорировать

trainData - весь год 2015.
fronttestData1 - январь 2016
fronttestData2 - февраль 2016
fronttestData3 - март 2016
fronttestData - январь 2016 - июнь 2016

 
Dr.Trader:

нет, в наборе для обучения 250-с-чем-то строк (количество торговых дней в 2015). Я обучал модель на таблице trainData. Тестировал - на fronttestData1. Всё остальное для дополнительных проверок, их можно игнорировать

trainData - весь год 2015.
fronttestData1 - январь 2016
fronttestData2 - февраль 2016
fronttestData3 - март 2016
fronttestData - январь 2016 - июнь 2016

Для меня это очень мало - я использую статистику. Даже для текущего окна 107 строк для меня очень мало. Я использую свыше 400 для текущего окна

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

К сожалению мои методы не пригодны для Ваших данных. 

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