Обсуждение статьи "Глубокая нейросеть со Stacked RBM. Самообучение, самоконтроль" - страница 7

 
Ilya Kosarev:

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

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

Приложил результаты тестирования (по барам в 2017 гг) DNSAE и моей SAE на GPBUSD и EURUSD.

Имена файлов с порядковыми номерами 1, 2 и 5, это DNSAE, другие - мой SAE (по сути тоже самое, только настройки и код другие). Нумерация - признак разных настроек. Увеличение тестов внутри одних и тех же настроек дает похожий и стабильный результат (не всегда положительный). В моем варианте SAE модель обновляется каждый день.

В архив положил e_DNSAE.r и e_DNSAE_FUN.r немного модифицированные для стабильной работы на разных ТФ.


Если кто-то поможет решить проблему DNRBM для DateSet'a 

dataSet <- createDataSet(

    data = DT$train[ ,best] %>% as.matrix(), 

    targets = y,

    scale = F

  )

Error in createDataSet(data = DT$train[, best] %>% as.matrix(), targets = y,  : 

  unused arguments (data = DT$train[, best] %>% as.matrix(), targets = y, scale = F)

То сделаю тестирование и для этого варианта на данных.

Добрый день.

Посмотрю что можно сделать. Хорошая работа. 

Удачи

 

1. пакет deepnet (v 0.2) - имеет две функции

  • sae.dnn.train() - она используется в эксперте e_DNSAE 
  • dbn.dnn.train() - которую можно использовать вместо первой, особо не изменяя скрипт. Но использование dbn  в моих экспериментах с этим пакетом не дали хороших результатов. Вы легко можете проверить этот вариант просто заменив одну функцию на другую.

2. Эксперт e_DNRBM в статье использовал пакет darch(v0.10). Эта версия устарела и не поддерживается больше. Использование новой версии пакета darch(v0.12) в экспертах описана в статье 1 а оптимизация ее гиперпараметров в статье 2. Посмотрите, если будут вопросы я отвечу с удовольствием.

У меня два вопроса:

1. Вы тестировали в тестере МТ5 или МТ4? Код эксперта можете сбросить мне в личку? 

2. Если есть интерес в дальнейшем обсуждении, предлагаю перенести его в отдельную ветку RuserGroup? Я давно хотел открыть ее для обсуждения только конкретных скриптов на R и реализаций в моих статьях. 

Удачи

 
Vladimir Perervenko:

1. пакет deepnet (v 0.2) - имеет две функции

  • sae.dnn.train() - она используется в эксперте e_DNSAE 
  • dbn.dnn.train() - которую можно использовать вместо первой, особо не изменяя скрипт. Но использование dbn  в моих экспериментах с этим пакетом не дали хороших результатов. Вы легко можете проверить этот вариант просто заменив одну функцию на другую.

2. Эксперт e_DNRBM в статье использовал пакет darch(v0.10). Эта версия устарела и не поддерживается больше. Использование новой версии пакета darch(v0.12) в экспертах описана в статье 1 а оптимизация ее гиперпараметров в статье 2. Посмотрите, если будут вопросы я отвечу с удовольствием.

У меня два вопроса:

1. Вы тестировали в тестере МТ5 или МТ4? Код эксперта можете сбросить мне в личку? 

2. Если есть интерес в дальнейшем обсуждении, предлагаю перенести его в отдельную ветку RuserGroup? Я давно хотел открыть ее для обсуждения только конкретных скриптов на R и реализаций в моих статьях. 

Удачи

Спасибо.

По версиям, разобрался.

1. МТ4, но есть и МТ5 (не проверял)

2. ОК

# Просьба внести исправления в скрипт "e_DNSAE_FUN.r"

Все совпадения price[, 6], лучше поменять на price[, "CO"]

В функциях testAcc и testBal, необходимо добавить 

if(!soft) out <- ifelse(out > mean(out), 1, 0); //после out <- nn.predict(obj, x.ts) и if(soft){out <- max.col(out)-1} else {out %<>% as.vector()} соответсвенно

или иной способ декодирования для случая "не софт", иначе вектор с одинаковыми значениями.

 
out <- classmat2classvec(out, threshold = 0.5) 
или
out <- max.col(out)-1

Если установить порог равным 0.5 и наибольшая вероятность в столбцах будет меньше этого порога, мы получим дополнительный класс "не_определен". Это нужно учитывать при вычислении таких метрик, как Accuracy.

#

Решил немного иначе, но и в этом случае необходимо изменить некоторые функции:


testAcc <- function(obj){
           require(deepnet)
          x.ts <- DT$test[ ,best] %>% as.matrix()
          y.ts <- DT$test$y %>% as.integer() %>% subtract(1)
          out <- nn.predict(obj, x.ts) 
          
          if(soft){
            out <- max.col(out)-1
          } else {
            out %<>% as.vector()
            out <- ifelse(out > mean(out), 1, 0);
          }
          
          acc <- length(y.ts[y.ts == out])/length(y.ts) %>% 
                  round(., digits = 4)
          return(list(Acc = acc, y.ts = y.ts, y = out))
        }
        #---12-----
        testBal <- function(obj, typ = "bin") {
          x <- DT.test[ ,best]
          CO <- DT.test$CO
          out <- nn.predict(obj, x)
          if(soft){
            pr.out <- max.col(out)-1;
            if(exists("enable_dn_probability")){
              if(enable_dn_probability){
                n_pr <- 1:length(pr.out);
                sig<-0;
                for(i in n_pr)
                {
                  j <- pr.out[i] + 1;
                  sig[i] <- 0;
                  if(pr.out[i] == 0) if(out[i, j] > dn_probability) sig[i] <- (-1);
                  if(pr.out[i] == 1) if(out[i, j] > dn_probability) sig[i] <- 1;
                }
                sig %<>% as.vector()  
              } else{
                sig <- ifelse(pr.out == 0, -1, 1)
              }
            } else {
              sig <- ifelse(pr.out == 0, -1, 1)
            }
            
            #if(length(sig) < length(pr.out)){
             # sig<-0;
              #for(i in n_pr)
              #{
             #   j <- pr.out[i] + 1;
             #   sig[i] <- 0;
             #   if(pr.out[i] == 0) if(out[i, j] > mean(out[,j])) sig[i] <- (-1);
             #   if(pr.out[i] == 1) if(out[i, j] > mean(out[,j])) sig[i] <- 1;
             # }
            #}
            sig %<>% as.vector()  
          } else {
            out %<>% as.vector()
            pr.out <- ifelse(out > mean(out), 1, 0);
            if(exists("dec")){
              if(dec == 2) sig <- ifelse(out > left, -1, ifelse(out < right, 1, 0))
              if(dec == 1) sig <- ifelse(pr.out == 0, -1, 1)
            } else sig <- ifelse(pr.out == 0, -1, 1)
          }
          
          sig1 <- Hmisc::Lag(sig) %>% na.omit
          bal <- cumsum(sig1 * tail(CO, length(sig1)))
          K <- tail(bal, 1)/length(bal) * 10 ^ Dig
          Kmax <- max(bal)/which.max(bal) * 10 ^ Dig
          dd <- fTrading::maxDrawDown(bal)
          return(list(sig = sig, bal = bal, K = K, 
                                  Kmax = Kmax, dd = dd))
        }
        #---13----------------------------------
        sig2stat <- function(x) {
          use3pos<-FALSE
          use3pos<- '0' %in% sig
          if(use3pos){
            return(ifelse(x==-1, 1, ifelse(x==1, 2, 3)) %>% as.numeric)   
          } else {
            return (x %>% as.factor %>% as.numeric)
          }
          
        }
        stat2sig <- function(x) {
          use3pos<-FALSE
          use3pos<- '0' %in% sig
          if(use3pos){
            return(ifelse(x==1, -1, ifelse(x==2, 1, 0)))
          } else {
            return(ifelse(x==1, -1, 1))
          }
          #ifelse(x==1, -1, 1)
        }

Новые переменные из советника: "enable_dn_probability" и "dn_probability".

Есть идеи, как упростить, в студию.

Вот результаты отладки советником:

GBPUSD 18.03.2018 - 18.04.2018


Приб Сделки Прибыльность Мат Просадка абс Просадка отн
775,83 43 1,34 18,04 1012,71 6,39% 0 dn_probability=0,1
262,19 41 1,09 6,39 1111,05 7,09% 0 dn_probability=0,2
481,57 42 1,2 11,47 1048,21 6,67% 0 dn_probability=0,3
1007 40 1,63 25,18 679,33 4,52% 0 dn_probability=0,4
2052,32 43 1,85 47,73 964,9 5,91% 0 dn_probability=0,5
996,61 28 2,32 35,59 1119,52 7,11% 0 dn_probability=0,6
234,54 2 0 117,27 99,39 0,66% 0 dn_probability=0,7
NA dn_probability=0,8
NA dn_probability=0,9


Комментарий к стабильности. Иногда есть вылеты с ошибкой:

[7056] Ошибка в conditionalDistribution(object, lastState) :

[7056]   атрибут 'names' [1] должен быть той же длины, что и вектор [0]

 
Ilya Kosarev:

Если установить порог равным 0.5 и наибольшая вероятность в столбцах будет меньше этого порога, мы получим дополнительный класс "не_определен". Это нужно учитывать при вычислении таких метрик, как Accuracy.

#

Решил немного иначе, но и в этом случае необходимо изменить некоторые функции:


Новые переменные из советника: "enable_dn_probability" и "dn_probability".

Есть идеи, как упростить, в студию.

Вот результаты отладки советником:

GBPUSD 18.03.2018 - 18.04.2018


Приб Сделки Прибыльность Мат Просадка абс Просадка отн
775,83 43 1,34 18,04 1012,71 6,39% 0 dn_probability=0,1
262,19 41 1,09 6,39 1111,05 7,09% 0 dn_probability=0,2
481,57 42 1,2 11,47 1048,21 6,67% 0 dn_probability=0,3
1007 40 1,63 25,18 679,33 4,52% 0 dn_probability=0,4
2052,32 43 1,85 47,73 964,9 5,91% 0 dn_probability=0,5
996,61 28 2,32 35,59 1119,52 7,11% 0 dn_probability=0,6
234,54 2 0 117,27 99,39 0,66% 0 dn_probability=0,7
NA dn_probability=0,8
NA dn_probability=0,9


Комментарий к стабильности. Иногда есть вылеты с ошибкой:

[7056] Ошибка в conditionalDistribution(object, lastState) :

[7056]   атрибут 'names' [1] должен быть той же длины, что и вектор [0]

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

Удачи

 

Работа над своими ошибками:

testAcc <- function(obj){
           require(deepnet)
          x.ts <- DT$test[ ,best] %>% as.matrix()
          y.ts <- DT$test$y %>% as.integer() %>% subtract(1)
          out <- nn.predict(obj, x.ts) 
          
          if(soft){
            out <- max.col(out)-1
          } else {
            out %<>% as.vector()
            #out <- ifelse(out > mean(out), 1, 0);
            out <- ifelse(out > 0.5, 0, 1)
          }
          
          acc <- length(y.ts[y.ts == out])/length(y.ts) %>% 
                  round(., digits = 4)
          return(list(Acc = acc, y.ts = y.ts, y = out))
        }
#---12-----
        testBal <- function(obj, typ = "bin") {
	  x <- DT.test[ ,best]
	  CO <- DT.test$CO
	  out <- nn.predict(obj, x)
	  if(soft){
	    pr.out <- max.col(out)-1;
	    if(exists("enable_dn_probability")){
	      if(enable_dn_probability){
	        n_pr <- 1:length(pr.out);
	        sig<-0;
	        for(i in n_pr)
	        {
	          j <- pr.out[i] + 1;
	          sig[i] <- 0;
	          if(pr.out[i] == 0) if(out[i, j] > dn_probability) sig[i] <- -1;
	          if(pr.out[i] == 1) if(out[i, j] > dn_probability) sig[i] <- 1;
	        }
	        sig %<>% as.vector()  
	      } else{ sig <- ifelse(pr.out == 0, -1, 1) }
	    } else { sig <- ifelse(pr.out == 0, -1, 1) }
	    
	    sig %<>% as.vector() 
	  } else {
	    pr.out <- out %>% as.vector()

	    if(exists("dec")){
	      if(dec == 2) sig <- ifelse(pr.out > left, -1, ifelse(pr.out < right, 1, 0))
	      if(dec == 1) sig <- ifelse(pr.out > 0.5, -1, 1)
	    } else sig <- ifelse(pr.out == 1, -1, 1)
	  }
	  sig1 <- Hmisc::Lag(sig) %>% na.omit
	  bal <- cumsum(sig1 * tail(CO, length(sig1)))
	  K <- tail(bal, 1)/length(bal) * 10 ^ Dig
	  Kmax <- max(bal)/which.max(bal) * 10 ^ Dig
	  dd <- fTrading::maxDrawDown(bal)
	  return(list(sig = sig, bal = bal, K = K, 
				  Kmax = Kmax, dd = dd))
	}
        #---13----------------------------------
        sig2stat <- function(x) {
          use3pos<-FALSE
          use3pos<- '0' %in% sig
          if(use3pos){
            return(ifelse(x==-1, 1, ifelse(x==1, 2, 3)) %>% as.numeric)   
          } else {
            return (x %>% as.factor %>% as.numeric)
          }
          
        }
        stat2sig <- function(x) {
          use3pos<-FALSE
          use3pos<- '0' %in% sig
          if(use3pos){
            return(ifelse(x==1, -1, ifelse(x==2, 1, 0)))
          } else {
            return(ifelse(x==1, -1, 1))
          }
          #ifelse(x==1, -1, 1)
        }
 

У меня таки вышло запустить RBM на тестере советника M30

СимволEURUSD (Euro vs US Dollar)
Период30 Минут (M30) 2016.10.03 - 2017.05.25 

Баров в истории

30877

Смоделировано тиков

60750

Качество моделирования

n/a

Ошибки рассогласования графиков

0

Начальный депозит

10000.00

Спред

Текущий (70)

Чистая прибыль

-280.46

Общая прибыль

5542.86

Общий убыток

-5823.33

Прибыльность

0.95

Матожидание выигрыша

-1.75

Абсолютная просадка

320.28

Максимальная просадка

1924.03 (16.54%)

Относительная просадка

16.54% (1924.03)

Всего сделок

160

Короткие позиции (% выигравших)

160 (74.38%)

Длинные позиции (% выигравших)

0 (0.00%)

Прибыльные сделки (% от всех)

119 (74.38%)

Убыточные сделки (% от всех)

41 (25.63%)

Самая большая

прибыльная сделка

175.00

убыточная сделка

-660.00

Средняя

прибыльная сделка

46.58

убыточная сделка

-142.03

Максимальное количество

непрерывных выигрышей (прибыль)

19 (654.31)

непрерывных проигрышей (убыток)

3 (-747.31)

Макс.

непрерывная прибыль (число выигрышей)

654.31 (19)

непрерывный убыток (число проигрышей)

-747.31 (3)

Средний

непрерывный выигрыш

5

непрерывный проигрыш

2

Немного поправленный код

train_SAE <- function(dt,  
                      h = c(70, 70, 70), LR = 0.9, Mom = 0.5,
                      act = "tanh", out = "sigm", sae = "linear", 
                      Ep = 250, Bs = 50, hd.out = 0.0, in.out = 0.0, bst, sig_type = 0){
  require(deepnet)
  x <- dt$train[ ,bst]%>% as.matrix
  if (soft) { y <- dt$train$y %>% classvec2classmat()}
  if (!soft){ y <- dt$train$y %>% as.integer() %>% subtract(1)}
  #Обучаем модель
  if(sig_type == 0){
    sae <- sae.dnn.train(x = x , y = y , hidden = h,
                  activationfun = act, output = out, sae_output = sae,
                  learningrate = LR, learningrate_scale = 1,
                  momentum = Mom,
                  numepochs = Ep, batchsize = Bs,
                  hidden_dropout = hd.out, visible_dropout = in.out)
  }
  if(sig_type == 8){
    sae <- dbn.dnn.train(x = x , y = y , hidden = h,
                  activationfun = act, output = out, 
                  learningrate = LR, learningrate_scale = 1,
                  momentum = Mom,
                  numepochs = Ep, batchsize = Bs,
                  hidden_dropout = hd.out, visible_dropout = in.out)
  }
  return (sae)
}

Еще

testBal <- function(obj, typ = "bin", dt, bst) {
  require(deepnet)
  x <- dt$test[ ,bst]
  CO <- dt$test$CO
  out <- nn.predict(obj, x)
  if(soft){
    pr.out <- max.col(out)-1;
    if(exists("enable_dn_probability")){
      if(enable_dn_probability){
        n_pr <- 1:length(pr.out);
        sig<-0;
        for(i in n_pr)
        {
          j <- pr.out[i] + 1;
          sig[i] <- 0;
          if(!is.na(pr.out[i]) && !is.na(out[i, j])){
            if(pr.out[i] == 0) if(out[i, j] > dn_probability) sig[i] <- -1;
            if(pr.out[i] == 1) if(out[i, j] > dn_probability) sig[i] <- 1;
          }
        }
        sig %<>% as.vector()  
      } else{ sig <- ifelse(pr.out == 0, -1, 1) }
    } else { sig <- ifelse(pr.out == 0, -1, 1) }
    
    sig %<>% as.vector() 
  } else {
    pr.out <- out %>% as.vector()
    
    if(exists("dec")){
      if(dec == 2) sig <- ifelse(pr.out > left, -1, ifelse(pr.out < right, 1, 0))
      if(dec == 1) sig <- ifelse(pr.out > 0.5, -1, 1)
    } else sig <- ifelse(pr.out == 1, -1, 1)
  }
  sig1 <- Hmisc::Lag(sig) %>% na.omit
  #
  if(is.null(CO)){
    Kmax <- 0
    K <- 0
    Acc <- 0
    maxDD<-0
    bal<-0
    K<-0
    dd<-0
  } else {
    
    #bal <- cumsum(sig1 * tail(CO, length(sig1)))
    bal <- tryCatch({
      bal <- cumsum(sig1 * tail(CO, length(sig1)))
    }, error = function(e){
      bal<-0
      return(bal)})
    #K <- tail(bal, 1)/length(bal) * 10 ^ Dig
    K <- tryCatch({
      K <- tail(bal, 1)/length(bal) * 10 ^ Dig
    },error = function(e){
      K<-0
      return(K)})
    #Kmax <- max(bal)/which.max(bal) * 10 ^ Dig
    Kmax <- tryCatch({
      Kmax <- max(bal)/which.max(bal) * 10 ^ Dig
    },error = function(e){
      Kmax<-0
      return(Kmax)})
    #dd <- fTrading::maxDrawDown(bal)
    dd <- tryCatch({
      dd <- fTrading::maxDrawDown(bal)
    },error = function(e){
      dd<-0
      return(dd)})
  }
  return(list(sig = sig, bal = bal, K = K, 
              Kmax = Kmax, dd = dd))
}
#---13----------------------------------
sig2stat <- function(x) {
  use3pos<-FALSE
  use3pos<- '0' %in% x
  if(use3pos){
    return(ifelse(x==-1, 1, ifelse(x==1, 0, 2)) %>% as.numeric)   
  } else {
    return (x %>% as.factor %>% as.numeric)
  }
  
}
stat2sig <- function(x) {
  use3pos<-FALSE
  use3pos<- '2' %in% x
  if(use3pos){
    return(ifelse(x==1, -1, ifelse(x==0, 1, 0)))
  } else {
    return(ifelse(x==1, -1, 1))
  }
  #ifelse(x==1, -1, 1)
}

В этой нейронке Acc было < 0.5

dn_probability = off

 
Ilya Kosarev:

У меня таки вышло запустить RBM на тестере советника M30

СимволEURUSD (Euro vs US Dollar)
Период30 Минут (M30) 2016.10.03 - 2017.05.25 

Баров в истории

30877

Смоделировано тиков

60750

Качество моделирования

n/a

Ошибки рассогласования графиков

0

Начальный депозит

10000.00

Спред

Текущий (70)

Чистая прибыль

-280.46

Общая прибыль

5542.86

Общий убыток

-5823.33

Прибыльность

0.95

Матожидание выигрыша

-1.75

Абсолютная просадка

320.28

Максимальная просадка

1924.03 (16.54%)

Относительная просадка

16.54% (1924.03)

Всего сделок

160

Короткие позиции (% выигравших)

160 (74.38%)

Длинные позиции (% выигравших)

0 (0.00%)

Прибыльные сделки (% от всех)

119 (74.38%)

Убыточные сделки (% от всех)

41 (25.63%)

Самая большая

прибыльная сделка

175.00

убыточная сделка

-660.00

Средняя

прибыльная сделка

46.58

убыточная сделка

-142.03

Максимальное количество

непрерывных выигрышей (прибыль)

19 (654.31)

непрерывных проигрышей (убыток)

3 (-747.31)

Макс.

непрерывная прибыль (число выигрышей)

654.31 (19)

непрерывный убыток (число проигрышей)

-747.31 (3)

Средний

непрерывный выигрыш

5

непрерывный проигрыш

2

Немного поправленный код

Еще

В этой нейронке Acc было < 0.5

dn_probability = off

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

Удачи

 

Ноу проблем.

Сорри, там сверху опечатка про преобразование сигнала в состояние. Состояние "0" для markovchain не существует, поэтому сделал "3"

sig2stat <- function(x) {
  use3pos<-FALSE
  use3pos<- '0' %in% x
  if(use3pos){
    return(ifelse(x==-1, 1, ifelse(x==1, 2, 3)) %>% as.numeric)   
  } else {
    #return (x %>% as.factor %>% as.numeric)
    return (ifelse(x==-1, 1, 2) %>% as.numeric)
  }
  
}
stat2sig <- function(x) {
  use3pos<-FALSE
  use3pos<- '3' %in% x
  if(use3pos){
    return(ifelse(x==1, -1, ifelse(x==2, 1, 0)))
  } else {
    return(ifelse(x==1, -1, 1))
  }
  #ifelse(x==1, -1, 1)
}

Ну и жду, когда эксперт обсчитает данные.

Хочу сказать, что если подавать сетке данные о реальных объемах пары, то точность возрастает очень сильно, так, что эксперту практически не требуется задействовать механизм мани-менеджемент

 
Ilya Kosarev:

Ноу проблем.

Сорри, там сверху опечатка про преобразование сигнала в состояние. Состояние "0" для markovchain не существует, поэтому сделал "3"

Ну и жду, когда эксперт обсчитает данные.

Хочу сказать, что если подавать сетке данные о реальных объемах пары, то точность возрастает очень сильно, так, что эксперту практически не требуется задействовать механизм мани-менеджемент

Как объем добавляли? Просто объем свечи?

Реальный или тиковый?

В моих экспериментах объем ничего не дал.

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