Рисование индикатора на истории

 

Пытаюсь сделать рисование на истории для индикатора фракталов, но что то идет не так. 
Функция OnInit() срабатывает, но ничего не рисуется, хотя код в точности из OnCalculate() который работает, просто выполняется для каждого бара на истории.

Где я ошибся?

extern int FracPeriod=7;
bool FracUp, FracDown;

int OnInit()
  {
   FracUp=true;
   FracDown=true;
   for (int MainCandle=Bars-FracPeriod/2+1; MainCandle>=FracPeriod/2+1; MainCandle--)
       for (int FracBack=FracPeriod/2+2, FracFoward=FracPeriod/2; FracBack<=FracPeriod; FracBack++, FracFoward--)
         {  
         if (High[MainCandle] < High[FracBack] || High[MainCandle] < High[FracFoward])
            FracUp=false;
         
         if (Low[MainCandle] > Low[FracBack] || Low[MainCandle] > Low[FracFoward])
            FracDown=false;
         }
   
   if (FracUp) FracDraw(High[FracPeriod/2+1], OBJ_ARROW_UP);
   if (FracDown) FracDraw(Low[FracPeriod/2+1], OBJ_ARROW_DOWN);
   
//---
   return(INIT_SUCCEEDED);
  }

void FracDraw(double price, string ObjType)
{
   if (ObjType==OBJ_ARROW_UP)
      ObjectCreate("TrendLiner" + ObjectsTotal(),ObjType,0,Time[FracPeriod/2+1],High[FracPeriod/2+1]+4*Point);
   else
      ObjectCreate("TrendLiner" + ObjectsTotal(),ObjType,0,Time[FracPeriod/2+1],Low[FracPeriod/2+1]);
}
 

Значения FracUp и FracDown почти со 100%-ой вероятностью равны false. Поэтому функция FracDraw никогда не будет вызвана.

Также очень странно, что переменная ObjType, отвечающая за тип объекта, объявлена строковой. При этом в функцию FracDraw она передается с типом ENUM_OBJECT, затем неявно преобразуется в строку, а потом снова должна чудесным образом быть преобразована в ENUM_OBJECT. Зачем столько неявных преобразований с непонятным исходом?

Еще интересно, что перебираются все свечи графика, но в результате фрактал будет отображен на строго определенной свече. Зачем тогда весь цикл нужен?

 
Ihor Herasko:

Значения FracUp и FracDown почти со 100%-ой вероятностью равны false. Поэтому функция FracDraw никогда не будет вызвана.

Также очень странно, что переменная ObjType, отвечающая за тип объекта, объявлена строковой. При этом в функцию FracDraw она передается с типом ENUM_OBJECT, затем неявно преобразуется в строку, а потом снова должна чудесным образом быть преобразована в ENUM_OBJECT. Зачем столько неявных преобразований с непонятным исходом?

Еще интересно, что перебираются все свечи графика, но в результате фрактал будет отображен на строго определенной свече. Зачем тогда весь цикл нужен?


Главный внешний цикл задает бар, для которого будет искаться фрактал.

По поводу преобразований, всегда так писал и ничего не мешало. Оно мне надо для условия в функции FracDraw

 
RomanRott:

Главный внешний цикл задает бар, для которого будет искаться фрактал.

Вот этот цикл:

for (int MainCandle=Bars-FracPeriod/2+1; MainCandle>=FracPeriod/2+1; MainCandle--)

проходит практически по всей истории (исключая 2 бара слева по графику и 4 бара справа по графику). За время работы этого цикла, конечно же, выполняются условия, которые приводят к тому, что FracUp и FracDown становятся равными false. Следовательно, до выполнения FracDraw дело никогда не доходит. Чтобы было исполнение функции FracDraw, нужно изменить логику внутри циклов. Подсказать будет возможно, если опишите, что именно необходимо получить. Догадок о том, как должно быть, можно много привести.

По поводу преобразований, всегда так писал и ничего не мешало. Оно мне надо для условия в функции FracDraw

Тем не менее, стоит избегать неявных преобразований. Это в конце концов приводит к трудно обнаруживаемым ошибкам. Правильнее будет так:

void FracDraw(double price, ENUM_OBJECT ObjType)
{
   if (ObjType==OBJ_ARROW_UP)
      ObjectCreate("TrendLiner" + string(ObjectsTotal()),ObjType,0,Time[FracPeriod/2+1],High[FracPeriod/2+1]+4*Point);
   else
      ObjectCreate("TrendLiner" + string(ObjectsTotal()),ObjType,0,Time[FracPeriod/2+1],Low[FracPeriod/2+1]);
}

k

 
Ihor Herasko:

Вот этот цикл:

проходит практически по всей истории (исключая 2 бара слева по графику и 4 бара справа по графику). За время работы этого цикла, конечно же, выполняются условия, которые приводят к тому, что FracUp и FracDown становятся равными false. Следовательно, до выполнения FracDraw дело никогда не доходит. Чтобы было исполнение функции FracDraw, нужно изменить логику внутри циклов. Подсказать будет возможно, если опишите, что именно необходимо получить. Догадок о том, как должно быть, можно много привести.

Тем не менее, стоит избегать неявных преобразований. Это в конце концов приводит к трудно обнаруживаемым ошибкам. Правильнее будет так:

k


Главный цикл задает MainCandle свечу, потом ее High сравнивается с FracPeriod/2 свечей слева и справа. Если условия не выполняются, то есть High этой свечи действительно максимален, рисуется фрактал. Такая же логика для Low.

По поводу преобразований понял, не знал что можно просто писать ENUM_OBJECT

 
RomanRott:

Главный цикл задает MainCandle свечу, потом ее High сравнивается с FracPeriod/2 свечей слева и справа. Если условия не выполняются, то есть High этой свечи действительно максимален, рисуется фрактал. Такая же логика для Low.

В коде я вижу другое: High каждой свечи истории сравнивается с High свечей с индексами 5, 6 и 7, а Low свечей истории сравнивается с Low свечей 3, 2, 1 и 0. Причем, пока не будет пройдена вся история, переход к проверке значений FracUp и FracDown не происходит. Эта проверка находится вне цикла.

Чтобы включить ее в цикл, нужны дополнительные фигурные скобки. Ну и много, чего переделать:

int OnInit()
{
   int nHalfPeriod = FracPeriod / 2;
   for (int MainCandle=Bars - nHalfPeriod - 1; MainCandle > nHalfPeriod; MainCandle--)
   {
      FracUp = true;
      FracDown = true;
      for (int i = nHalfPeriod; i > 0; --i)
      {  
         if (High[MainCandle] < High[MainCandle - i] || High[MainCandle] < High[MainCandle + i])
            FracUp = false;
         
         if (Low[MainCandle] > Low[MainCandle - i] || Low[MainCandle] > Low[MainCandle + i])
            FracDown = false;
      }

      if (FracUp) 
         FracDraw(MainCandle, OBJ_ARROW_UP);

      if (FracDown) 
         FracDraw(MainCandle, OBJ_ARROW_DOWN);
   }
   
   
//---
   return(INIT_SUCCEEDED);
}

void FracDraw(int nBarIndex, ENUM_OBJECT ObjType)
{
   if (ObjType==OBJ_ARROW_UP)
      ObjectCreate("TrendLiner" + string(ObjectsTotal()), ObjType, 0, Time[nBarIndex], High[nBarIndex] + 4 * Point);
   else
      ObjectCreate("TrendLiner" + string(ObjectsTotal()), ObjType, 0, Time[nBarIndex], Low[nBarIndex]);
}
Причина обращения: