Советники на нейросетях, делимся опытом. - страница 9

 
Andrey Emelyanov:

Тоже пытался реализовать подобный алгоритм в далеком 2013 году... Правда использовал 7 индикаторов, а Zigzag использовал для формирования вектора обучения НС. Но суть таже - искал реверсные позиции... ничего путного не получалось ни с данными от индикаторов, ни с торговыми сигналами от них... пока случайно не наткнулся на паттерны. Которые в корне изменили мою ТС. Теперь мой алгоритм стал проще:

1. Вычисление паттернов на минутном и часовом таймфрейме, за последний год;

2. Составление словаря переломных моментов (пар "минутный паттерн - часовой паттерн") ;

3. Обучение НС по словарю переломных моментов ( на 150-160 парах); 

 Вот результат моего подхода:

 

 К недостатки моего подхода:

1) Высокий риск ТС - так как точно нельзя определить значение цены перелома, ТС выставляет 9 отложенных ордеров с лотами: 1, 1, 3, 6, 14, 31, 70, 158, 355;

2) Сложно реализовать алгоритм выхода (трал ТС);

 

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

P/s: под паттернами понимаю паттерны А. Меррилла (M & W) .

Толковый подход. А паттерны описывали просто как положение баров в матрице, без учета фактической дельты цены - только относительное положение?

 У меня есть идея, попробовать паттерны индикаторов, но с разным фреймом - первых пять баров анализируем показатели на 5 последних индикаторах, и два показателя для анализа тенденции - анализируем с шагом 10 и при этом учитываем абсолютные изменения. 

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

 
-Aleks-:

Толковый подход. А паттерны описывали просто как положение баров в матрице, без учета фактической дельты цены - только относительное положение?

 У меня есть идея, попробовать паттерны индикаторов, но с разным фреймом - первых пять баров анализируем показатели на 5 последних индикаторах, и два показателя для анализа тенденции - анализируем с шагом 10 и при этом учитываем абсолютные изменения. 

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

Я делаю так:

Есть динамический массив который хранит исключительно пары паттернов (я называю его словарь), если пара паттернов попала в словарь второй раз её не записываю; и два массива счетчика старшего таймфрейма и младшего - они считают как часто участвовал паттерн в формировании пар, даже если его не записывали в словарь.

Формирование вектора обучения происходит по словарю, вес отдельного паттерна = счетчик_патерна / максимум_счетчика. Т.е. паттерн который чаще всего участвует в формировании пар равен 1, а все остальные меньше 1. Вот такая табличка получается после обучения НС:

Main Pattern Main Count Slave Pattern Slave Count Sum_Multilayer_Perceptron
W2 18 W2 21 0.94914702
W14 14 W2 21 0.84972197
M15 20 M15 14 0.83269191
W1 11 W2 21 0.77499075
W13 10 W2 21 0.75006553
M15 20 M3 10 0.73813147
M15 20 M10 10 0.73812512
M15 20 M16 10 0.738099
W5 9 W2 21 0.72506739
W10 9 W2 21 0.72505412
M15 20 M11 9 0.71431236
W2 18 W1 11 0.71204136
W2 18 W5 11 0.7118911
W4 8 W2 21 0.70017271
W2 18 W4 10 0.68815217
W2 18 W7 10 0.68802818
M15 20 M7 7 0.66682395
M15 20 M14 6 0.64291215
W2 18 W13 8 0.64045346
M3 12 M15 14 0.63254238
W9 5 W2 21 0.62522345
W3 5 W2 21 0.62509623
W7 5 W2 21 0.62505511
M15 20 M12 5 0.61917222
M15 20 M8 5 0.6191331
W14 14 W1 11 0.61210667
W6 4 W2 21 0.60012943
W2 18 W14 6 0.59301682

 Структура НС: 64 нейрона на входе, 4 внутренних, 1 выход. Т.е. один входной нейрон описывает один паттерн. Сетка обучается за 40-50 минут, ошибка НС не превышает 0,00001. 

Таким образом я имею модель которая может предсказывать значимость пар паттернов, даже если раньше её не было в словаре.  

С флэтом и ложными пиками борюсь давно, но на уровне расчета ZigZaga. Я немного переделал код стандартного Zigzag, а именно реализовал на его базе процентный ZZ. Пока более или менее потребный код выглядит так:

int MyCExtremum::GetCombiZigzag(const double    &high[],     // буфер цен high

                                const double    &low[],      // буфер цен low

                                const datetime  &time[],     // буфер время 

                                int             ExtDepth,    // глубина поиска экстремумов(первого прохода)

                                double          ExtDeviation,// "пороговое значение": жесткая ступенька + % роста цены

                                int             ExtBackstep  // глубина поиска экстремумов(второго прохода)

                               )

  {

   //--- value

   int    shift=0, whatlookfor=0, lasthighpos=0, lastlowpos=0, Deviat=1;

   double lasthigh=0.0, lastlow=0.0, percent=0.0;

   int    rates_total = ArraySize(time);          // размер входных таймсерий

   int    limit       = rates_total - ExtDepth;   // лимит на расчеты...

   //+---------------------------------------------------------------+

   //| ОЧЕНЬ ВАЖНАЯ ПРОВЕРКА ВЛИЯЮЩАЯ НА КОРРЕКТНОСТЬ ВЫЧИСЛЕНИЙ!    |

   //+---------------------------------------------------------------+

   if(ArrayIsSeries(high)) ArraySetAsSeries(high,false);

   if(ArrayIsSeries(low))  ArraySetAsSeries(low,false);

   if(ArrayIsSeries(time)) ArraySetAsSeries(time,false);

   //+---------------------------------------------------------------+

   //| ПРОВЕРКИ ВХОДНЫХ ПЕРЕМЕННЫХ                                   |

   //+---------------------------------------------------------------+

   if(rates_total<20)

     { 

      Print(__FUNCTION__," ERROR: the small size of the buffer.");

      return(-1);                                     

     }

   if(ExtDeviation<0 || ExtDeviation>100)

     { 

      Print(__FUNCTION__," ERROR: Is\'not correct a Deviation. The value of Deviation should be in the interval [0..100].");

      return(-1);                                     

     }

   //--- Проверка: Depth and Backstep

   if((ExtDepth < ExtBackstep)||(ExtDepth < 2))

     {

      Print(__FUNCTION__+" ERROR: Is\'not correct a Depth and Backstep. The value of Depth should be greater than Backstep.");

      return(-1);

     }

   //--- готовим буфер ZigzagBuffer[]

   if(ArraySize(ZigzagBuffer)>0) ArrayFree(ZigzagBuffer);               // Удаляем старые данные

   ArrayResize(ZigzagBuffer,rates_total, EXTREMUM_RESERVE);

   ArrayFill(ZigzagBuffer,0,rates_total,0.0);

   if(ArrayIsSeries(ZigzagBuffer))  ArraySetAsSeries(ZigzagBuffer,  false);

   //---

   if(ArraySize(HighMapBuffer)>0) ArrayFree(HighMapBuffer);             // Удаляем старые данные

   ArrayResize(HighMapBuffer,rates_total, EXTREMUM_RESERVE);

   ArrayFill(HighMapBuffer,0,rates_total,0.0);

   if(ArrayIsSeries(HighMapBuffer)) ArraySetAsSeries(HighMapBuffer, false);

   //---

   if(ArraySize(LowMapBuffer)>0) ArrayFree(LowMapBuffer);               // Удаляем старые данные

   ArrayResize(LowMapBuffer,rates_total, EXTREMUM_RESERVE);

   ArrayFill(LowMapBuffer,0,rates_total,0.0);

   if(ArrayIsSeries(LowMapBuffer))  ArraySetAsSeries(LowMapBuffer,  false);   

   //---

   if(ArraySize(TimeBuffer)>0) ArrayFree(TimeBuffer);                   // Удаляем старые данные

   ArrayResize(TimeBuffer,     rates_total, EXTREMUM_RESERVE);

   ArrayFill(TimeBuffer,    0, rates_total,   0);

   if(ArrayIsSeries(TimeBuffer))  ArraySetAsSeries(TimeBuffer,  false);   

   //--- корректировка Deviation

   if(ExtDeviation < 1)

     {

      Deviat = 1;

     }else

        {

         Deviat = (int)ExtDeviation;

        }

   //--- получаем "свежие" минимумы и максимумы

   if(GetHighMapZigzag(high,ExtDepth,Deviat,ExtBackstep) < 0) return(0);

   if(GetLowMapZigzag(low,ExtDepth,Deviat,ExtBackstep)   < 0) return(0);

   //--- final rejection

   for(shift=ExtDepth;shift<rates_total;shift++)

     {

      switch(whatlookfor)

        {

         case Start: // search for peak or lawn

            if(lastlow==0 && lasthigh==0)

              {

               if(HighMapBuffer[shift]!=0)

                 {

                  lasthigh=high[shift];

                  lasthighpos=shift;

                  whatlookfor=Sill;

                  ZigzagBuffer[shift]=lasthigh;

                  TimeBuffer[shift]=time[shift];

                 }

               if(LowMapBuffer[shift]!=0)

                 {

                  lastlow=low[shift];

                  lastlowpos=shift;

                  whatlookfor=Pike;

                  ZigzagBuffer[shift]=lastlow;

                  TimeBuffer[shift]=time[shift];

                 }

              }

            break;

         case Pike: // search for peak

            if(LowMapBuffer[shift]!=0.0 && LowMapBuffer[shift]<lastlow && HighMapBuffer[shift]==0.0)

              {

               //---

               ZigzagBuffer[lastlowpos] = 0.0;

               TimeBuffer[lastlowpos]   = 0;

               //---

               lastlowpos=shift;

               lastlow=LowMapBuffer[shift];

               ZigzagBuffer[shift]=lastlow;

               TimeBuffer[shift]=time[shift];

               //--- Обязательно: покинуть switch

               break;

              }

            //--- Обход "двойственности"

            if(LowMapBuffer[shift]!=0.0 && HighMapBuffer[shift]!=0.0 && LowMapBuffer[shift]<lastlow)

              {

               //---

               ZigzagBuffer[lastlowpos] = 0.0;

               TimeBuffer[lastlowpos]   = 0;

               //---

               lastlowpos=shift;

               lastlow=LowMapBuffer[shift];

               ZigzagBuffer[shift]=lastlow;

               TimeBuffer[shift]=time[shift];

               //--- Обязательно: покинуть switch

               break;

              }

            if(HighMapBuffer[shift]!=0.0 && LowMapBuffer[shift]==0.0)

              {

               //--- Проверка: % роста цены

               percent = (HighMapBuffer[shift]-lastlow)/(lastlow/100);

               if(percent > ExtDeviation)

                 {

                  lasthigh=HighMapBuffer[shift];

                  lasthighpos=shift;

                  ZigzagBuffer[shift]=lasthigh;

                  TimeBuffer[shift]=time[shift];

                  whatlookfor=Sill;

                 }

               percent = 0.0;

              }            

            break;

         case Sill: // search for lawn

            if(HighMapBuffer[shift]!=0.0 && HighMapBuffer[shift]>lasthigh && LowMapBuffer[shift]==0.0)

              {

               //--- 

               ZigzagBuffer[lasthighpos] = 0.0;

               TimeBuffer[lasthighpos]   = 0;

               //---

               lasthighpos=shift;

               lasthigh=HighMapBuffer[shift];

               ZigzagBuffer[shift]=lasthigh;

               TimeBuffer[shift]=time[shift];

               //--- Обязательно: покинуть switch

               break;

              }

            if(HighMapBuffer[shift]!=0.0 && LowMapBuffer[shift]!=0.0 && HighMapBuffer[shift]>lasthigh)

              {

               //--- 

               ZigzagBuffer[lasthighpos] = 0.0;

               TimeBuffer[lasthighpos]   = 0;

               //---

               lasthighpos=shift;

               lasthigh=HighMapBuffer[shift];

               ZigzagBuffer[shift]=lasthigh;

               TimeBuffer[shift]=time[shift];

               //--- Обязательно: покинуть switch

               break;

              }

            if(LowMapBuffer[shift]!=0.0 && HighMapBuffer[shift]==0.0)

              {

               //--- Проверка: % роста цены

               percent = (lasthigh-LowMapBuffer[shift])/(lasthigh/100);

               if(percent > ExtDeviation)

                 {

                  lastlow=LowMapBuffer[shift];

                  lastlowpos=shift;

                  ZigzagBuffer[shift]=lastlow;

                  TimeBuffer[shift]=time[shift];

                  whatlookfor=Pike;                  

                 }

               percent = 0.0;

              }

            break;

         default: 

            return(-1);

        }

     }

   //--- return value of prev_calculated for next call

   return(rates_total);   

  }

 В файле MyCExtremum - класс для расчета ZigZag...

Файлы:
MyCExtremum.mqh  37 kb
 
-Aleks-:

Толковый подход. А паттерны описывали просто как положение баров в матрице, без учета фактической дельты цены - только относительное положение?

 У меня есть идея, попробовать паттерны индикаторов, но с разным фреймом - первых пять баров анализируем показатели на 5 последних индикаторах, и два показателя для анализа тенденции - анализируем с шагом 10 и при этом учитываем абсолютные изменения. 

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

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

Andrey Emelyanov:

Структура НС: 64 нейрона на входе, 4 внутренних, 1 выход. Т.е. один входной нейрон описывает один паттерн.

Вы с такой моделью на результаты надеетесь? У вас внутренний слой выступает промежуточным компрессором, а не классификатором.
 
Andrey Emelyanov:

Я делаю так:

Есть динамический массив который хранит исключительно пары паттернов (я называю его словарь), если пара паттернов попала в словарь второй раз её не записываю; и два массива счетчика старшего таймфрейма и младшего - они считают как часто участвовал паттерн в формировании пар, даже если его не записывали в словарь.

Формирование вектора обучения происходит по словарю, вес отдельного паттерна = счетчик_патерна / максимум_счетчика. Т.е. паттерн который чаще всего участвует в формировании пар равен 1, а все остальные меньше 1. Вот такая табличка получается после обучения НС:

Main Pattern Main Count Slave Pattern Slave Count Sum_Multilayer_Perceptron
W2 18 W2 21 0.94914702
W14 14 W2 21 0.84972197
M15 20 M15 14 0.83269191
W1 11 W2 21 0.77499075
W13 10 W2 21 0.75006553
M15 20 M3 10 0.73813147
M15 20 M10 10 0.73812512
M15 20 M16 10 0.738099
W5 9 W2 21 0.72506739
W10 9 W2 21 0.72505412
M15 20 M11 9 0.71431236
W2 18 W1 11 0.71204136
W2 18 W5 11 0.7118911
W4 8 W2 21 0.70017271
W2 18 W4 10 0.68815217
W2 18 W7 10 0.68802818
M15 20 M7 7 0.66682395
M15 20 M14 6 0.64291215
W2 18 W13 8 0.64045346
M3 12 M15 14 0.63254238
W9 5 W2 21 0.62522345
W3 5 W2 21 0.62509623
W7 5 W2 21 0.62505511
M15 20 M12 5 0.61917222
M15 20 M8 5 0.6191331
W14 14 W1 11 0.61210667
W6 4 W2 21 0.60012943
W2 18 W14 6 0.59301682

 Структура НС: 64 нейрона на входе, 4 внутренних, 1 выход. Т.е. один входной нейрон описывает один паттерн. Сетка обучается за 40-50 минут, ошибка НС не превышает 0,00001. 

Таким образом я имею модель которая может предсказывать значимость пар паттернов, даже если раньше её не было в словаре.  

С флэтом и ложными пиками борюсь давно, но на уровне расчета ZigZaga. Я немного переделал код стандартного Zigzag, а именно реализовал на его базе процентный ZZ. Пока более или менее потребный код выглядит так:

Про массив интересное решение. А есть ли различия по статистике между парами/периодами, какая устойчивость вообще изменяемости частоты появления паттерна, дающего положительный результат предсказания?

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

 
Andrey Emelyanov:
На счет анализа индикаторов с помощью паттернов - это очень интересно... думаю на индикаторах меньше шума, но надо выбрать так индикаторы, чтобы одни подавляли "низкие шумы", а другие "высокие шумы", тогда получиться мультифильтр.
Индикаторов много разных. Я экспериментировал со стандартными осцилляторами (и их подобием беспроцентным), и на всех удалось получать прибыль - всё зависит от настроек... только вопрос в том, случайность это или закономерность.
 
Комбинатор:
Вы с такой моделью на результаты надеетесь? У вас внутренний слой выступает промежуточным компрессором, а не классификатором.
Так сжатие мне и нужно... в один момент времени (на текущем баре) из 64 входов только 2 входа отличны от нуля... и задача сети не делить на buy/sell, а измерить какова вероятность отскока при заданных входах. Или я не так рассуждаю? 
 
-Aleks-:

Про массив интересное решение. А есть ли различия по статистике между парами/периодами, какая устойчивость вообще изменяемости частоты появления паттерна, дающего положительный результат предсказания?

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

Как всем известно паттерны А. Меррилла не дают точного ответа будет ли паттерн далее развиваться (сохранять тренд) или перейдет в другой паттерн (отскок цены). Поэтому я решил искать ответ при использовании двух временных периодов часового и минутного. Статистику повторяемости пар собираю, и пока универсального словаря обучения не имею. Однако точно уверен что связь эта должна быть... иначе бы не существовало гармоничных моделей: бабочек, летучая мышь и т.п.
 
Andrey Emelyanov:
Как всем известно паттерны А. Меррилла не дают точного ответа будет ли паттерн далее развиваться (сохранять тренд) или перейдет в другой паттерн (отскок цены). Поэтому я решил искать ответ при использовании двух временных периодов часового и минутного. Статистику повторяемости пар собираю, и пока универсального словаря обучения не имею. Однако точно уверен что связь эта должна быть... иначе бы не существовало гармоничных моделей: бабочек, летучая мышь и т.п.
Модели воспринимаемые визуально человеком как "бабочек, летучая мышь и т.п." рождаются лишь в мозге человека, и , как я мыслю, нужно учитывать этот фактор - нужно изучить когнитивную психологию на эту тему, дабы понять, что для мозга существенно, а что нет в восприятии паттерна, т.е. какие погрешности допустимы, а какие нет. Мозг часто сам дорисовывает то, что ожидает увидеть - словарь у него по паттернам ограничен, а значит он похожие комбинации свечей складывает в единую картинку, т.е. не использует точную математическую модель для описания увиденного.
 

Моя детка пока еще тупая-притупая, но уже кое что умеет.. 8 индикаторов на входе, 1 выход, 15 нейронов в с крытом слое. 2000 входной вектор, 10000 эпох обучения. 

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

Примерно представляю себе закономерность, которую она должна уловить, и индикаторы специально подобрал с разных тф, и на выходы вроде бы осмысленная инфа подается. 

 

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