Универсальный шаблон индикатора

 

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

ПеременнаяN(i) = ФункцияN( ПеременнаяN(i+1))

Эту проблему уже пытались решить вот тут 'Многократный пересчет нулевого бара в некоторых индикаторах' . Мне показалось, что нашел более лучший способ. Предложенный вот тут 'Как писать быстрые неперерисовывающиеся зигзаги', т.е. отказ от использования функции IndicatorCounted(). Пока данные поступают нормально, производить расчет по сформированному бару. Если сбой пересчитать весь индикатор заново.

Вот пример реализации этой идеи

//+------------------------------------------------------------------+
//|                                               ideal-EURUSD.mq4   |
//|                                                   Привалов С.В.  |
//|                                           Skype -> privalov-sv   |
//|  13.01.2009  Индикатор точного курса EURUSD                      |
//+------------------------------------------------------------------+
#property copyright "Prival"
//----
#property indicator_chart_window
//#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1 Aqua
#property indicator_color2 Blue
//------- Внешние параметры индикатора -------------------------------
extern int k;
extern int    NumberOfBars=1440;     // Количество баров обсчёта (0-все)
//------- Буферы индикатора ------------------------------------------
double buf0[], buf1[];
int      PreBars, LoopBegin;
datetime BarTime;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
  void init() 
  {
   SetIndexBuffer(0, buf0);
   SetIndexStyle (0, DRAW_LINE, STYLE_SOLID, 1);
   SetIndexEmptyValue(0, 0);
   SetIndexBuffer(1, buf1);
   SetIndexStyle (1, DRAW_LINE, STYLE_SOLID, 1);
   SetIndexEmptyValue(1, 0);
   IndicatorDigits(Digits+Digits);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
  void deinit() 
  {
   Comment("");
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
  void start() 
  {
   int sh, n;
   double   V[13], VV[7], sum, delta;
// Работаем только по закончившимся барам
   if (Bars == PreBars) return(0);  
   //  Если не было докачки истории, обсчитываем только закончившийся бар
   if (Bars-PreBars == 1 && BarTime==Time[1]) LoopBegin = 1;
   //  Иначе пересчитываем заданное в функции Reset() количество баров 
   else LoopBegin = Reset();
   // Модифицируем контрольные переменные
   PreBars = Bars;  
   BarTime = Time[0];
   // Цикл по истории
  for ( sh=LoopBegin; sh>0; sh--) {
      
      ArrayInitialize(V,0.0);
      V[ 0]=iClose("EURUSD", 0, sh); VV[0]=V[0];
      V[ 1]=iClose("EURGBP", 0, iBarShift("EURGBP",0,Time[sh],false));
      V[ 2]=iClose("EURCHF", 0, iBarShift("EURCHF",0,Time[sh],false));
      V[ 3]=iClose("EURJPY", 0, iBarShift("EURJPY",0,Time[sh],false));
      V[ 4]=iClose("EURCAD", 0, iBarShift("EURCAD",0,Time[sh],false));
      V[ 5]=iClose("EURAUD", 0, iBarShift("EURAUD",0,Time[sh],false));
      V[ 6]=iClose("EURNZD", 0, iBarShift("EURNZD",0,Time[sh],false));
      V[ 7]=iClose("GBPUSD", 0, iBarShift("GBPUSD",0,Time[sh],false));
      V[ 8]=iClose("USDCHF", 0, iBarShift("USDCHF",0,Time[sh],false));
      V[ 9]=iClose("USDJPY", 0, iBarShift("USDJPY",0,Time[sh],false));
      V[10]=iClose("USDCAD", 0, iBarShift("USDCAD",0,Time[sh],false));
      V[11]=iClose("AUDUSD", 0, iBarShift("AUDUSD",0,Time[sh],false));
      V[12]=iClose("NZDUSD", 0, iBarShift("NZDUSD",0,Time[sh],false));
      sum=0;
      n=0;
      //EURGBP * GBPUSD
      if(V[1]!=0 && V[ 7]!=0) VV[1]=V[1]*V[7]; 
      //EURCHF : USDCHF
      if(V[2]!=0 && V[ 8]!=0) VV[2]=V[2]/V[8]; 
      //EURJPY : USDJPY
      if(V[3]!=0 && V[ 9]!=0) VV[3]=V[3]/V[9];
      //EURCAD : USDCAD
      if(V[4]!=0 && V[10]!=0) VV[4]=V[4]/V[10]; 
      //EURAUD * AUDUSD
//      if(V[5]!=0 && V[11]!=0) VV[5]=V[5]*V[11];
      //EURNZD * NZDUSD
//      if(V[6]!=0 && V[12]!=0) VV[6]=V[6]*V[12]; 

      for( int i=0; i<8; i++ )   {
         if(VV[i]!=0) {
            sum+=VV[i];
            n++;
         }
      }
      sum/=n;
      buf0[sh]=VV[0];
      buf1[sh]=sum;
      delta=(buf0[sh]-buf1[sh])*10000.0;
  if(sh==1)    Comment(DoubleToStr(sum,8)," n=",n," Дельта=",DoubleToStr(delta,8)," пункта");
      
      }
  }
//+------------------------------------------------------------------+
//| Перезагрузка, отработка сбоев                                    |
//+------------------------------------------------------------------+
int Reset() {
   if (NumberOfBars==0) LoopBegin=Bars-1;
   else LoopBegin=NumberOfBars-1;
   LoopBegin=MathMin(Bars-1, LoopBegin);
   PreBars = 0;
   BarTime = 0;
   return(LoopBegin);
}
   
 

Но сегодня произошел сбой. Вот лог из журнала

2009.01.16 00:43:31 Old tick USDCHF1 1.12360/1.12400

2009.01.16 00:43:31 Old tick USDCHF60 1.12360/1.12400

2009.01.16 00:43:31 Old tick USDCHF1 1.12370/1.12410

2009.01.16 00:43:31 Old tick USDCHF60 1.12370/1.12410

2009.01.16 00:42:31 '1317923': login

2009.01.16 00:42:28 '1317923': login

2009.01.16 00:41:34 '1317923': DataCenter connecting failed [6]

2009.01.16 00:40:58 '1317923': login

2009.01.16 00:40:46 Custom indicator ideal-EURUSD EURUSD,M1: loaded successfully

После этого индикатор перестал считать. Вот рисунок.

Помогите доработать, этот шаблон с целью устойчивой работы на реале.

Как обойти возникшую проблему ?

Какие еще могут быть подводные камни, при таком варианте построения индикатора, и как их можно обойти ?

Заранее спасибо.

З.Ы. Для модераторов. Выскакивала ошибка текст слишком большого размера. пришлось делать 2 поста.

Файлы:
 

Причем в этоже время на графике EURAUD и EURUSD. Висел шаблон индикатора (0_Bolvanka), тот же самый принцип. Он не остановился и прекрасно работал. Вот его код

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Red
#property indicator_width1 1

extern int  MinBars = 20;

int PreBars;
datetime BarTime;
int StartPos;
int pos;

double Bufer_0[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init() {
  SetIndexBuffer(0,Bufer_0);
  SetIndexStyle(0,DRAW_LINE);
  SetIndexEmptyValue(0,0.0);
  return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit() {
  return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator reset function                                  |
//+------------------------------------------------------------------+
int Reset() {
  if (MinBars == 0) MinBars = Bars-1;
  StartPos = MinBars;
  PreBars = 0;
  BarTime = 0;
  return(StartPos);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start() {
//  Работаем только по закончившимся барам
  if (Bars == PreBars) return(0);  
//  Проверим, достаточно ли баров на графике
  if (Bars < MinBars)  return(0);
//  Если не было докачки истории, обсчитываем только закончившийся бар
  if (Bars-PreBars == 1 && BarTime==Time[1]) StartPos = 1;
//  Иначе пересчитываем заданное в функции Reset() количество баров 
  else StartPos = Reset();
// Модифицируем контрольные переменные
  PreBars = Bars;  
  BarTime=Time[0];
// Цикл по истории
Print("Bars=",Bars," StartPos=",StartPos); 
  for (pos=StartPos;pos>0;pos--) {
// Эта операция обязательна для корректного персчёта индикатора
    Bufer_0[pos-1] = 0;
    Bufer_0[pos] = Close[pos];
    Print("Расчет ",pos); 
  }  //  pos=StartPos;pos>0;pos--) 
  return(0);

Вот лог

2009.01.16 00:44:11 0_Bolvanka EURUSD,M1: Расчет 1
2009.01.16 00:44:11 0_Bolvanka EURUSD,M1: Bars=65476 StartPos=1
2009.01.16 00:44:10 0_Bolvanka EURAUD,M1: Расчет 1
2009.01.16 00:44:10 0_Bolvanka EURAUD,M1: Bars=45245 StartPos=1
2009.01.16 00:43:48 0_Bolvanka EURAUD,M1: Расчет 1
2009.01.16 00:43:48 0_Bolvanka EURAUD,M1: Bars=45244 StartPos=1
2009.01.16 00:43:44 0_Bolvanka EURUSD,M1: Расчет 1
2009.01.16 00:43:44 0_Bolvanka EURUSD,M1: Bars=65475 StartPos=1
2009.01.16 00:42:01 0_Bolvanka EURUSD,M1: Расчет 1

 

Хоть бы кто слово сказал.

Разработчики, ну хоть вы поругайте. Типа руки у меня кривые, но скажите почему он (индикатор) остановился? Как его програмно запустить снова ? ошибку эту отработать ?

Renat, Rosh .... ну хоть так отпишитесь http://forum.alpari-idc.ru/post493864-329.html

 

жесткие равенства могут приводить к зацикливаниям или пропускам,
рецепт от подвохов использовать неравенства


if (Bars-PreBars == 1 && BarTime==Time[1]) StartPos = 1;
if (Bars-PreBars >= 1 && BarTime>=Time[1]) StartPos = 1;
 

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

Там же конструкция

  if (Bars-PreBars == 1 && BarTime==Time[1]) StartPos = 1;
//  Иначе пересчитываем заданное в функции Reset() количество баров 
  else StartPos = Bars-1; 
т.е. если не выполнилось главное условие, считать все заново. А индикатор остановился.
 
Prival >>:

Хоть бы кто слово сказал.

Разработчики, ну хоть вы поругайте. Типа руки у меня кривые, но скажите почему он (индикатор) остановился? Как его програмно запустить снова ? ошибку эту отработать ?

Renat, Rosh .... ну хоть так отпишитесь http://forum.alpari-idc.ru/post493864-329.html

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

 
Rosh >>:

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

Нет. В этом случае была бы вертикальная линия вниз на разрыве. Окончание может быть таким если след. значение EMPTY_VALUE или если расчет пррервался совсем.

Поправьте если я неправ.

 
TheXpert >>:

Нет. В этом случае была бы вертикальная линия вниз на разрыве. Окончание может быть таким если след. значение EMPTY_VALUE или если расчет пррервался совсем.

Поправьте если я неправ.

Я как раз и подозреваю, что нулевые значения индикатора и есть те значения, которые не рисуются. Потому что в коде явно указано:

  SetIndexEmptyValue(0,0.0)
 
Rosh >>:

Я как раз и подозреваю, что нулевые значения индикатора и есть те значения, которые не рисуются. Потому что в коде явно указано:

Угу, не увидел. Тогда тут:

 V[ 0]=iClose("EURUSD", 0, sh); VV[0]=V[0];

в VV[0] должен получиться 0

 
Rosh писал(а) >>

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

Rosh

Спасибо.

Возможно ошибка, где то в запросе котировок других валют, т.к. 0_Bolvanka (пустой индикатор) с той же логикой построения, продолжал работать, и отработал все сбои. Я чуть выше приводил его и лог.

К сожалению, ждать ошибки DataCenter connecting failed [6] (я так понимаю это рестарт сервера), можно очень долго. Легче её смоделировать. Но у меня нет такой возможности.

А может и не стоит заморачиваться ?

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

З.Ы. Если есть необходимость могу выслать полный лог.

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