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

 
интересная статья https://geektimes.ru/post/144405/, может кто то поймет как такое в R с имитировать
Прогнозирование финансовых временных рядов
Прогнозирование финансовых временных рядов
  • geektimes.ru
Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста. Пометьте топик понятными вам метками, если хотите или закрыть
 

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

# типа какая то цена
dat <- cumsum(rnorm(1000))+1000
plot(dat,t="l")


# фун. матрицы хенкеля для имитации скользящего окна
hankel<- function(data, r=10) {
  do.call(cbind,
          lapply(0:(r-1),function(i) { data[(i+1):(length(data)-(r-1-i))]}))}
# делаем аналог скользящего окна глубиной в 50
glubina <- 50
D <- hankel(dat,r = glubina)


# скалирую и центрирую дату, проще сказать нормализирую
DC <- t(  apply(D, 1,    function(x) {  scale(x,T,T)  }    ))


library(SOMbrero)
# тренирую сеть кохонена на данных чтоб получить кластера
TS <- trainSOM(DC,  dimension=c(3,3))

# край матрицы будет вектор нашей цены без первых значений
dt <- D[,glubina] 
# полученые кластера
cl <- TS$clustering

# график цены , график кластеров этой цены
par(mfrow=c(2,1))
plot(dt,t="l")
plot(cl,t="l")
par(mfrow=c(1,1))


# пробую посмотреть склееный график только одного кластера 
one_clust <- dt[cl==3]
# график с разрывами в местах склейки
plot(one_clust,t="l")
 
Dr.Trader:

У меня тоже бывают такие проблемы. Обычно хватает выполнить attributes(KZP) чтобы узнать список доступных переменных, и затем просто пройтись по ним например KZP$window итд и найти нужные числа. Но тут эти числа генерируются в самой функции Summary и нигде не сохраняются.

Вот тут исходник есть: https://cran.r-project.org/web/packages/kza/index.html, надо выполнить что-то такое:

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

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

 
mytarmailS:

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

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

Узнал ещё пару интересных вещей:

Выложенная ранее функция для отсева предикторов (designTreatmentsN$scoreFrame) явно не даёт окончательный набор предикторов. Она не убирает даже 100% коррелирующие предикторы, плюс может убрать что-то нужное, плюс оставить мусор. Я немного усложнил метод их отсева - сначала отбираю предикторы по-старому, через designTreatmentsN$scoreFrame (порог увеличил в два раза - 2/N, чтобы отсеилось меньше потенциально хороших предикторов). Затем убираю все предикторы которые коррелируют между собой >0.99 (у меня таких много после рандомной генерации дельт и сумм. И я смотрю корреляцию предикторов между собой, а не с целевой переменной). Затем генетическим алгоритмом ищу лучший набор из оставшихся предикторов.

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

library('caret')
GetPCrsquared <- function(srcTable){
        targetName <- tail(colnames(srcTable),1)
        origVars <- setdiff(colnames(srcTable), targetName)
        # can try variations such adding/removing non-linear steps such as "YeoJohnson"
        prep <- preProcess(srcTable[,origVars], method = c("zv", "nzv", "center", "scale", "pca"))
        prepared <- predict(prep,newdata=srcTable[,origVars])
        newVars <- colnames(prepared)
        prepared$target <- srcTable$target
        modelB <- lm(paste(targetName, paste(newVars,collapse=' + '),sep=' ~ '),data=prepared)
        return(summary(modelB)$r.squared)
}

Если раньше R^2 у меня был около 0.1, то теперь я добился 0.3. Этого всё равно мало, рекомендуют хотя-бы 0.95. Ещё есть странный момент что с R^2=0.1 у меня была ошибка во фронттесте 37%, а с R^2=0.3 эта ошибка выросла до 45%. Возможно проблема в том что я добавил в набор предикторов больше баров, и больше индикаторов. Шаг вперёд и два назад, теперь нужно как-то анализировать весь набор индикаторов, и выкидывать ненужные. Или модель главных компонент просто не применима для форекса (проверить сложно, нужно сначала добиться R^2 > 0.95, и посмотреть какой результат будет во фронттесте, на недообученной модели ещё рано делать выводы). 

Ещё сравнил пакет GA (генетика) и GenSA (градиентный отжиг, из примера Алексея). Оба пакета добились одинакового результата. Генетика умеет работать многопоточно, за счёт этого выигрывала по времени. Но на одном потоке GenSA похоже побеждает. Ещё есть такой трюк с кэшированием результатов, Алексей думаю оценит:

fitness_GenSA_bin <- function(selectionForInputs){
        testPredictorNames <- predictorNames[ which(selectionForInputs == TRUE) ]
        #do the fitness calculation
}

library(memoise)
fitness_GenSA_bin_Memoise <- memoise(fitness_GenSA_bin)

fitness_GenSA <- function(selectionForInputs){
        selectionForInputs[selectionForInputs>=0.5] <- TRUE
        selectionForInputs[selectionForInputs<0.5] <- FALSE
        return(fitness_GenSA_bin_Memoise(selectionForInputs))
}

library(GenSA, quietly=TRUE)
GENSA <- GenSA(fn = fitness_GenSA,
                                lower = rep(0, length(predictorNames)),
                                upper = rep(1, length(predictorNames)),
                                control=list(smooth=FALSE, verbose=TRUE)
                                ) 

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

 

 

mytarmailS:

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

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

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

 
Dr.Trader:

Узнал ещё пару интересных вещей:

Выложенная ранее функция для отсева предикторов (designTreatmentsN$scoreFrame) явно не даёт окончательный набор предикторов. Она не убирает даже 100% коррелирующие предикторы, плюс может убрать что-то нужное, плюс оставить мусор. Я немного усложнил метод их отсева - сначала отбираю предикторы по-старому, через designTreatmentsN$scoreFrame (порог увеличил в два раза - 2/N, чтобы отсеилось меньше потенциально хороших предикторов). Затем убираю все предикторы которые коррелируют между собой >0.99 (у меня таких много после рандомной генерации дельт и сумм. И я смотрю корреляцию предикторов между собой, а не с целевой переменной). Затем генетическим алгоритмом ищу лучший набор из оставшихся предикторов.

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

Если раньше R^2 у меня был около 0.1, то теперь я добился 0.3. Этого всё равно мало, рекомендуют хотя-бы 0.95. Ещё есть странный момент что с R^2=0.1 у меня была ошибка во фронттесте 37%, а с R^2=0.3 эта ошибка выросла до 45%. Возможно проблема в том что я добавил в набор предикторов больше баров, и больше индикаторов. Шаг вперёд и два назад, теперь нужно как-то анализировать весь набор индикаторов, и выкидывать ненужные. Или модель главных компонент просто не применима для форекса (проверить сложно, нужно сначала добиться R^2 > 0.95, и посмотреть какой результат будет во фронттесте, на недообученной модели ещё рано делать выводы). 

Ещё сравнил пакет GA (генетика) и GenSA (градиентный отжиг, из примера Алексея). Оба пакета добились одинакового результата. Генетика умеет работать многопоточно, за счёт этого выигрывала по времени. Но на одном потоке GenSA похоже побеждает. Ещё есть такой трюк с кэшированием результатов, Алексей думаю оценит:

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

 

 

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

Про кэширование круто. Я пытался сам написать такое. А есть прямо готовое решение. Куэруть. Спасибо.

А какая у вас фитнесс-функция при переборе используется? Это пропустил. Линейная зависимость или статистика какая-то?
 
Dr.Trader:

Тут нету "Y-scale" как из ещё одного примера из статьи,

 Я думаю, что весь цимус статьи именно в этом. Я перечитал, там об этом прямо говориться.

 

 Если же вернуться к общей схеме подготовки перечня предикторов.

Отсев шума - это только часть проблемы, которая не решает остальных проблем и рекомендаций в этой области. 

Если все это выполнить, то дальше рабочий алгоритм в цикле, а именно.

1. Берем выделенный и обработанный набор предикторов. Этот перечень постоянный.

2. Для текущего окна  делаем отбор предикторов одним из алгоритмов. Например в caret их два.

3. Подгоняем модель.

4. Торгуем

5. Сдвигаем окно и переходим к п.2

Из тех первоначальных наборов предикторов, которые мне попадали в руки, число шумовых предикторов составляло свыше 80!

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

 

А какая у вас фитнесс-функция при переборе используется?

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

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

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

 Я думаю, что весь цимус статьи именно в этом. Я перечитал, там об этом прямо говориться.

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

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

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