Странное поведение индикатора

 

Индикатор изначально был основан на задаваемом пользователем количестве баров для работы, но это лишняя переменная и мне захотелось избавиться от неё, для упрощения вызова из советника. В результате советник перестал торговать, хотя остальная логика осталась без изменений.

Было:

 //это в OnInit: 
   //пользовательские переменные - period1,period2,drawbars,cper,csh,mshift,P,К
   per1=period1;
   per2=period2;
      if(per2==0) per2=per1;
   per=MathMax(per1,MathMax(per2,MathMax((cper+csh+mshift),(P+K))));
   db=drawbars;
   if(db<per) db=per;
   //цель - убедиться, что заданное drawbars не меньше самого большого периода, исключить вылет за пределы массива в расчётах индикатора
   
//дальше код в OnCalculate:
   
   if(rates_total-1 < per)   {Print("need more bars");   return(0);}
//---
   if(prev_calculated>rates_total || prev_calculated<=0)
     {
//--- обнуляем если не было обсчитано ни одного бара (первый запуск)
      for(int i=0; i<=rates_total-1; i++)//--- initial zero
        {
         buf1[i]=0.0;
         buf2[i]=0.0;
         buf3[i]=0.0;
        }
     }
    cnt=db;                                             
    if (cnt>(rates_total-1-per)) {cnt=rates_total-1-per;} //проверка, хватит ли баров для работы, есди нет - уменьшаем предел цикла
   
   for (int i=cnt; i>=0; i--) 
   { 
    //много кода, без изменений в обоих вариантах
   return(rates_total);
   }

//вызов из советника, советник открывает позиции, торгует как задано логикой
          if(iCustom(NULL,0,"abc_v2.22",db,P,K,"",cper,cpr,csh,cup,cdn,ocb,per1,per2,mshift,mode,price,diff,0,1)!=0.0 
          && iCustom(NULL,0,"abc_v2.22",db,P,K,"",cper,cpr,csh,cup,cdn,ocb,per1,per2,mshift,mode,price,diff,1,1)==0.0)
          { 
              myOrderType=0; 
          }
          if(iCustom(NULL,0,"abc_v2.22",db,P,K,"",cper,cpr,csh,cup,cdn,ocb,per1,per2,mshift,mode,price,diff,0,1)==0.0 
          && iCustom(NULL,0,"abc_v2.22",db,P,K,"",cper,cpr,csh,cup,cdn,ocb,per1,per2,mshift,mode,price,diff,1,1)!=0.0)
          { 
              myOrderType=1; 
          }

стало:

//блок расчёта кол-ва баров для работы
   //это в OnInit: 
   //пользовательские переменные - period1,period2,drawbars,cper,csh,mshift,P,К
   per1=period1;
   per2=period2;
      if(per2==0) per2=per1;
   per=MathMax(per1,MathMax(per2,MathMax((cper+csh+mshift),(P+K))));


   //дальше код в OnCalculate:
   
   if(rates_total-1 < per)   {Print("need more bars");   return(0);}
//---
   if(prev_calculated>rates_total || prev_calculated<=0)    //если это первый запуск 
     {
      cnt=rates_total-1-per;                                 //индикатор будет рассчитан для всех баров
//--- counting from 0 to rates_total
      for(int i=0; i<=cnt; i++)//--- обнуляем буферы
        {
         buf1[i]=0.0;
         buf2[i]=0.0;
         buf3[i]=0.0;
        }
     }
   else cnt=rates_total-1-prev_calculated; //индикатор будет рассчитан только для новых баров

   for (int i=cnt; i>=0; i--)
   { 
    //много кода, без изменений в обоих вариантах
   return(rates_total);
   }


//Вызов из советника, советник вообще не шевелится, ни в тестере, ни на демо, нет ошибок в журнале, просто нет торговли. Кроме исключения drawbars ничего не менялось...
          if(iCustom(NULL,0,"abc_v2.220",P,K,"",cper,cpr,csh,cup,cdn,ocb,per1,per2,mshift,mode,price,diff,0,1)!=0.0 
          && iCustom(NULL,0,"abc_v2.220",P,K,"",cper,cpr,csh,cup,cdn,ocb,per1,per2,mshift,mode,price,diff,1,1)==0.0)
          { 
              myOrderType=0; 
          }
          if(iCustom(NULL,0,"abc_v2.220",P,K,"",cper,cpr,csh,cup,cdn,ocb,per1,per2,mshift,mode,price,diff,0,1)==0.0 
          && iCustom(NULL,0,"abc_v2.220",P,K,"",cper,cpr,csh,cup,cdn,ocb,per1,per2,mshift,mode,price,diff,1,1)!=0.0)
          { 
              myOrderType=1; 
          }

Кто виноват и что делать, люди добрые???

 
evillive:

Индикатор изначально был основан на задаваемом пользователем количестве баров для работы, но это лишняя переменная и мне захотелось избавиться от неё, для упрощения вызова из советника. В результате советник перестал торговать, хотя остальная логика осталась без изменений.

Было:

стало:



В вызове пользовательского индикатора требуется переменная, от которой Вы отказались. Зачем Вы передаёте в параметры пустую строку ""? Ведь db было числом.
 

Если я из индикатора эту переменную изъял, то и в вызове тоже её быть не должно, разве нет?

Пустую строку я передаю и там, и там, это комментарий в настройках индикатора (input string _filter_="filter options";), если его не передать - нарушится порядок следующих за ним переменных. По крайней мере, при попытке исключить пустой строчный параметр из середины списка передаваемых советником для индикатора приводил к смещению всех последующих и неправильной работе индикатора и всей ТС в целом.



 
evillive:

Если я из индикатора эту переменную изъял, то и в вызове тоже её быть не должно, разве нет?

Пустую строку я передаю и там, и там, это комментарий в настройках индикатора (input string _filter_="filter options";), если его не передать - нарушится порядок следующих за ним переменных. По крайней мере, при попытке исключить пустой строчный параметр из середины списка передаваемых советником для индикатора приводил к смещению всех последующих и неправильной работе индикатора и всей ТС в целом.


Насчёт "" недосмотрел. 

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

cnt=rates_total-1-per;                                 //индикатор будет рассчитан для всех баров

 внутри цикла

if(prev_calculated>rates_total || prev_calculated<=0)    //если это первый запуск 
     {
      cnt=rates_total-1-per;                                 //индикатор будет рассчитан для всех баров
//--- counting from 0 to rates_total

 а раньше вычисляли cnt вычисляли за циклом:

if(prev_calculated>rates_total || prev_calculated<=0)
     {
//--- обнуляем если не было обсчитано ни одного бара (первый запуск)
      for(int i=0; i<=rates_total-1; i++)//--- initial zero
        {
         buf1[i]=0.0;
         buf2[i]=0.0;
         buf3[i]=0.0;
        }
     }
    cnt=db;                                             
    if (cnt>(rates_total-1-per)) {cnt=rates_total-1-per;} //проверка, хватит ли баров для работы, есди нет - уменьшаем предел цикла
   
   for (int i=cnt; i>=0; i--) 
 
В первом случае (вобще - вторая модификация - которая не работает) - стандартное вычисление кол-ва итераций расчета индикатора, охватывающем все бары минус периоды внутренних подциклов и прочих второстепенных индикаторов:
per=MathMax(per1,MathMax(per2,MathMax((cper+csh+mshift),(P+K))));

если эти периоды не вычесть - получаем вылет за пределы массива при расчёте тела индикатора - неоткуда взять лишние бары слева от самого старого ведь.

Так как кол-во баров не задано, необходимо рассчитать cnt дважды - весь диапазон для первого запуска индикатора и только новые бары - для продолжения работы, чтобы заново не считать индикатор для всех баров на графике.

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

 
В общем, вернулся обратно к старой версии индикатора, дубово, не очень красиво, зато работает. Просто интересно было, в чём тут дело, может я не так понял механизм расчёта баров для новой версии языка. Но взял-то я стандартный метод и вроде логика правильная. Но не работает, именно с советником. Сам по себе индикатор показывает точно те же значения, что тот вариант, что этот.
 
evillive:
В общем, вернулся обратно к старой версии индикатора, дубово, не очень красиво, зато работает. Просто интересно было, в чём тут дело, может я не так понял механизм расчёта баров для новой версии языка. Но взял-то я стандартный метод и вроде логика правильная. Но не работает, именно с советником. Сам по себе индикатор показывает точно те же значения, что тот вариант, что этот.

Если есть желание, помогу
 
Vinin:

Если есть желание, помогу

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

 
evillive:

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


drawbars во втором варианте существует? Просто в первом варианте Вы отрисовываете индикатор только на заданном количестве баров. А вот во-втором варианте вы отрисовываете индикатор всегда на нулевом баре. МОжет в индикаторе просто нет значений для нулевого бара и поэтому индикатор не отображаетс.я
 
нет, drawbars  во втором варианте не используется, там рассчитывается общее количество баров на графике. А из советника вызывается значение индикатора для 1-го бара, а не для 0, как легко заметить в стартовом посте темы. И если значения нет, то его нет для обоих вариантов, так как считаются они одинаково. Но значение на нулевом баре тем не менее рассчитывается, и оно появляется на графике, когда надо по логике индикатора, правда, перерисовывается, ну да этим многие индикаторы грешат, потому и использую стабильное значение с 1 бара.
Причина обращения: