Экспотенциальные значения во фракталах

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Ilya Rebenok
310
Ilya Rebenok  

День добрый.

Имеется доработанный стандартный индикатор фракталов, в котором можно задавать значение  кол-ва свечек по обе стороны от фрактала.

В исходнике индикатора явно прописано в любые значения, кроме high/low вставлять EMPTY_VALUE (что свою очередь соответствует DBL_MAX=1.7976931348623158e+308)

if(UpFound) ExtUpperBuffer[i]=high[i];
      else ExtUpperBuffer[i]=EMPTY_VALUE;
      if(DownFound) ExtLowerBuffer[i]=low[i];
      else ExtLowerBuffer[i]=EMPTY_VALUE;

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

ArrayResize(LowFArray,needCountFractals); // ставим размер массивов = кол-во необходимых фракталов
   ArrayResize(UpFArray,needCountFractals);
   ArrayResize(LowFNumber,needCountFractals);
   ArrayResize(UpFNumber,needCountFractals);
   double copyBufferUp[],copyBufferLow[];
//скопировали массив верхних и нижних фракталов
   if(CopyBuffer(FHandle,0,start_pos,BarCount,copyBufferUp)==-1 || CopyBuffer(FHandle,1,start_pos,BarCount,copyBufferLow)==-1)
     {
      drop_message("Ошибка при копировании массивов фракталов");
      return false;
     }
   ArraySetAsSeries(copyBufferUp,true); // порядок как в таймериях. От нового к старому
   ArraySetAsSeries(copyBufferLow,true);
   int FromBarUp=start_pos;
   int FromBarLow=start_pos;
   for(int i=0;i<needCountFractals;i++)
     {
      for(int n=FromBarUp; n<BarCount; n++)
        {
         //--- если непустое значение, прерываем цикл
         if(copyBufferUp[n]!=EMPTY_VALUE && copyBufferUp[n]>0)
           {
            UpFArray[i]=copyBufferUp[n]; //запишем ценовое значение  фрактала в массив
            FromBarUp=n+1; //--- запишем новый стартовый индекс в переменную
            UpFNumber[i]=n; //записываем порядковый номер в массив
            break;
           }
        }
      for(int n=FromBarLow; n<BarCount; n++)
        {
         //--- если непустое значение, прерываем цикл
         if(copyBufferLow[n]!=EMPTY_VALUE && copyBufferLow[n]>0)
           {
            LowFArray[i]=copyBufferLow[n]; //запишем ценовое значение  фрактала в массив
            FromBarLow=n+1; //--- запишем новый стартовый индекс фрактала в переменную
            LowFNumber[i]=n; //записываем порядковый номер в массив
            break;
           }
        }
     }


Теперь собственно проблема. Не смотря на условия индикатора по записи EMPTY_VALUE , в советнике в буфер я периодически получаю значения экспотенциального вида (например, 3.3745345789435e-308, -9.43251234232-e309 и т.д.). Они проходят условия проверки (не являются EMPTY_VALUE и больше 0),советник думает, что это фрактал и пытается зайти в рынок. Данные значения никак не пересекаются с именованными константами.

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

Уже дня 3 экспериментирую, пробую разные "залепы", но пока безуспешно. Замечу, что экспотенциальные значения появляются не все время, а периодически.

Помогите разобраться пожалуйста.

Igor Zakharov
6490
Igor Zakharov  

-9.xxx не больше нуля (минус же!)

3.3745345789435e-308 меньше DBL_EPSILON, я бы его тоже считал нулём.

вместо >0 попробуйте >DBL_EPSILON или >0.0001... В зависимости от ваших допусков. Обычно, вещественные числа строгими рамками не сравнивают.

Есть тут темка про число знаков после запятой - вопрос из той же серии. 

Ilya Rebenok
310
Ilya Rebenok  

я пробывал нормализовывать вот таким образом

copyBufferLow[n]!=EMPTY_VALUE && NormalizeDouble(copyBufferLow)[n])>0

Большая часть экспотенциальных значений становится =0, но попадаются те, которые например стали =5 (хотя цена 60+ $). Сейчас пробую снова отловить такие моменты, чтобы понять какое экс число было.

Непонятно в принципе почему такое происходит вопреки логике индикатора.

Ihor Herasko
21102
Ihor Herasko  
Илья Ребенок:

В исходнике индикатора явно прописано в любые значения, кроме high/low вставлять EMPTY_VALUE (что свою очередь соответствует DBL_MAX=1.7976931348623158e+308)

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

Поэтому для начала нужно проверить наличие инициализации каждого элемента буфера индикатора.

Ilya Rebenok
310
Ilya Rebenok  
Ihor Herasko:

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

Поэтому для начала нужно проверить наличие инициализации каждого элемента буфера индикатора.

Могло ли данное поведение быть связано с тем, что в индикаторе у меня инициализация буферов происходила таким образом
ArrayInitialize(ExtUpperBuffer,0); // инициализируем массивы
ArrayInitialize(ExtLowerBuffer,0);

При этом буферы типа double. По мне так в этом случае при инициализации массива могло записываться эксп число очень высокой точности, но при этом больше 0. Могла быть в этом причина?

Сейчас изменил на

ArrayInitialize(ExtUpperBuffer,EMPTY_VALUE); // инициализируем массивы
ArrayInitialize(ExtLowerBuffer,EMPTY_VALUE);

Буду проводить тесты.

Ilya Rebenok
310
Ilya Rebenok  

хотя странно все равно получается.

При первичном запуске индикатора инициализируется общий массив без размера

ArrayInitialize(ExtUpperBuffer,EMPTY_VALUE); // инициализируем массивы
ArrayInitialize(ExtLowerBuffer,EMPTY_VALUE);

Новые элементы массива могут быть уже не EMPTY_VALUE, но ведь эти кодом мы им явно назначаем значение

if(UpFound) ExtUpperBuffer[i]=high[i];
else ExtUpperBuffer[i]=EMPTY_VALUE;
if(DownFound) ExtLowerBuffer[i]=low[i];
else ExtLowerBuffer[i]=EMPTY_VALUE;

Здесь мы явно указываем что и как, то есть неопределенных элементов быть не должно. Они либо EMPTY_VALUE, либо цена high/low.

Ihor Herasko, как считаете?

Ihor Herasko
21102
Ihor Herasko  
Илья Ребенок:
Могло ли данное поведение быть связано с тем, что в индикаторе у меня инициализация буферов происходила таким образом

При этом буферы типа double. По мне так в этом случае при инициализации массива могло записываться эксп число очень высокой точности, но при этом больше 0. Могла быть в этом причина?

Сейчас изменил на

Буду проводить тесты.

Я имею в виду немного другое. К примеру, на момент выполнения инициализации буферов индикатора размер этого массива составляет 1 000 баров. Затем образуется новый бар. Терминал изменяет размер массива (индикаторного буфера), добавляя еще один элемент. Теперь массив имеет 1 001 элемент, но инициализация всего массива ведь не происходила. Получаем, что в этом новом элементе содержится мусор.

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

Ilya Rebenok
310
Ilya Rebenok  

я к тому, что в индикаторе при инициализации нового элемента сразу присваивается значение. Вот тело  onCalculate.

int i,limit;
//---Если всего свечей меньше суммы левого, правого диапазона и центальной свечи, то ничего не делаем
   if(rates_total<LeftBars+RightBars+1)
      return(0);

   if(prev_calculated<1) 
     {
      limit=LeftBars;
      //--- clean up arrays
      ArrayInitialize(ExtUpperBuffer,EMPTY_VALUE); // инициализируем массивы
      ArrayInitialize(ExtLowerBuffer,EMPTY_VALUE);
     }
   else
      limit=rates_total-RightBars-2; 
   for(i=limit;i<rates_total-RightBars-1 && !IsStopped();i++) // от стартовой свечи до общего кол-ва свечей - правый диапазон
     {
      bool UpFound=true;
      bool DownFound=true;
      //циклами проходимся по свечам обоих диапазонов и сравниваем с центральной
      for(int j=1;j<=LeftBars;j++) 
        {
         if(high[i-j]>high[i]) UpFound=false;
         if(low[i-j]<low[i]) DownFound=false;
        }
      for(int j=1;j<=RightBars;j++)
        {
         if(high[i+j]>=high[i]) UpFound=false;
         if(low[i+j]<=low[i]) DownFound=false;
        }
      if(UpFound) ExtUpperBuffer[i]=high[i];
      else ExtUpperBuffer[i]=EMPTY_VALUE;
      if(DownFound) ExtLowerBuffer[i]=low[i];
      else ExtLowerBuffer[i]=EMPTY_VALUE;
     }
   return (rates_total); 

По идее элемент не может остаться не инициализированным при таком коде.

Ihor Herasko
21102
Ihor Herasko  
Илья Ребенок:

я к тому, что в индикаторе при инициализации нового элемента сразу присваивается значение. Вот тело  onCalculate.

По идее элемент не может остаться не инициализированным при таком коде.

Чтобы правильно понять логику, укажите, являются ли буфера ExtUpperBuffer и ExtLowerBuffer таймсериями? То есть какое значение указано для них при использовании ArraySetAsSeries. Или же эта функция к ним вообще не применялась? 

Ilya Rebenok
310
Ilya Rebenok  
Ihor Herasko:

Чтобы правильно понять логику, укажите, являются ли буфера ExtUpperBuffer и ExtLowerBuffer таймсериями? То есть какое значение указано для них при использовании ArraySetAsSeries. Или же эта функция к ним вообще не применялась? 

На уровне индикатора ArraySetAsSeries не применялось. По сути это стандартный индикатор фракталов MT5, но с возможностью выбора кол-ва свечей.

В советнике в функции получения данных с этого индикатора после копирования в буфер применяю ArraySetAsSeries .

ArraySetAsSeries(copyBufferUp,true); // порядок как в таймериях. От нового к старому
ArraySetAsSeries(copyBufferLow,true);

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

Ihor Herasko
21102
Ihor Herasko  
Илья Ребенок:

На уровне индикатора ArraySetAsSeries не применялось. По сути это стандартный индикатор фракталов MT5, но с возможностью выбора кол-ва свечей.

Понятно. Тогда ответ тот, о котором я говорю с самого начала: цикл 

for(i=limit;i<rates_total-RightBars-1 && !IsStopped();i++)

обрабатывает не все бары.

Например, rates_total = 100, RightBars = 5 и это не первый вызов индикатора.

Тогда limit = 93, а цикл i обработает только один бар - 93. Остальные бары (94 - 99) останутся неинициализированными. Вот там и будет мусор. Нужно позаботиться об инициализации этих элементов массива сразу при появлении соответствующих баров.

12
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий