Разбор кода на MQL.

Программирование прибыли: от азов к секретам мастерства. Читайте, спрашивайте, делитесь опытом.
Бонус за сообщение 0.5$
Ответственный Модератор - Haos

Разбор кода на MQL.

Сообщение Рэндом » 21 авг 2013, 02:24

Здесь будет писаться разбор интересного кода. Будут объяснения почему что-то работает так а не иначе, а так же почему выбрано то или иное решение.
Аватар пользователя
Рэндом
Специалист MQL
 
Сообщений: 13700
Зарегистрирован: 18 июл 2013, 08:05
Средств на руках: 31.45 Доллар
Группа: Администраторы
Благодарил (а): 1131 раз.
Поблагодарили: 3174 раз.
Каждый заблуждается в меру своих возможностей.

Индикатор Stat

Сообщение Рэндом » 21 авг 2013, 02:53

Тема с индикатором viewtopic.php?f=9&p=798#p798
Код индикатора:
Код: выделить все
//+------------------------------------------------------------------+
//|                                                         Stat.mq4 |
//|                        Copyright 2013, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright 2013, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net"

#property indicator_chart_window
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
extern color TXTColor=White;
int init()
  {
//---- indicators
     
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   Comment("");
   ObjectDelete("Stat "+Symbol()+Period());
   ObjectDelete("TXT "+Symbol()+Period());
   ObjectDelete("TXT1 "+Symbol()+Period());
   ObjectDelete("TXT2 "+Symbol()+Period());
   ObjectDelete("TXT3 "+Symbol()+Period());
   ObjectDelete("TXT4 "+Symbol()+Period());
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
      datetime d1,d2;
      if(ObjectFind("Stat "+Symbol()+Period())==-1)
      {
        ObjectCreate("Stat "+Symbol()+Period(),OBJ_TREND,0,Time[30],High[30],Time[1],High[1]);
        ObjectSet("Stat "+Symbol()+Period(),OBJPROP_COLOR,Red);
        ObjectSet("Stat "+Symbol()+Period(),OBJPROP_RAY,false);
        d1=Time[30];
        d2=Time[1];
      }
      else
      {
         d1=ObjectGet("Stat "+Symbol()+Period(),OBJPROP_TIME1);
         d2=ObjectGet("Stat "+Symbol()+Period(),OBJPROP_TIME2);
      }
      int f1,f2,i,limit;
      f1=iBarShift(Symbol(),Period(),d1);
      f2=iBarShift(Symbol(),Period(),d2);
      if(f1==f2)
      {
         
         return (0);
      }
      if(f1>f2)
      {
         i=f2;
         limit=f1;
      }
      else
      {
         i=f1;
         limit=f2;
      }
      int vbars=limit-i+1;
      int bbars=0;
      double bpoints=0.0;
      int mbars=0;
      double mpoints=0.0;
      for(int shift=i;shift<=limit;shift++)
      {
         if(Open[shift]>Close[shift])
         {
            mbars++;
            mpoints=mpoints+(Open[shift]-Close[shift])/Point;
         }
         else
         {
            bbars++;
            bpoints=bpoints+(Close[shift]-Open[shift])/Point;
         }   
      }
      if(ObjectFind("TXT "+Symbol()+Period())==-1)
      {
         ObjectCreate("TXT "+Symbol()+Period(),OBJ_LABEL,0,0,0);
         ObjectSet("TXT "+Symbol()+Period(),OBJPROP_CORNER,0);
         ObjectSet("TXT "+Symbol()+Period(),OBJPROP_XDISTANCE,5);
         ObjectSet("TXT "+Symbol()+Period(),OBJPROP_YDISTANCE,20);
         ObjectSet("TXT "+Symbol()+Period(),OBJPROP_COLOR,TXTColor);
         ObjectCreate("TXT1 "+Symbol()+Period(),OBJ_LABEL,0,0,0);
         ObjectSet("TXT1 "+Symbol()+Period(),OBJPROP_CORNER,0);
         ObjectSet("TXT1 "+Symbol()+Period(),OBJPROP_XDISTANCE,5);
         ObjectSet("TXT1 "+Symbol()+Period(),OBJPROP_YDISTANCE,40);
         ObjectSet("TXT1 "+Symbol()+Period(),OBJPROP_COLOR,TXTColor);
         ObjectCreate("TXT2 "+Symbol()+Period(),OBJ_LABEL,0,0,0);
         ObjectSet("TXT2 "+Symbol()+Period(),OBJPROP_CORNER,0);
         ObjectSet("TXT2 "+Symbol()+Period(),OBJPROP_XDISTANCE,5);
         ObjectSet("TXT2 "+Symbol()+Period(),OBJPROP_YDISTANCE,60);
         ObjectSet("TXT2 "+Symbol()+Period(),OBJPROP_COLOR,TXTColor);
         ObjectCreate("TXT3 "+Symbol()+Period(),OBJ_LABEL,0,0,0);
         ObjectSet("TXT3 "+Symbol()+Period(),OBJPROP_CORNER,0);
         ObjectSet("TXT3 "+Symbol()+Period(),OBJPROP_XDISTANCE,5);
         ObjectSet("TXT3 "+Symbol()+Period(),OBJPROP_YDISTANCE,80);
         ObjectSet("TXT3 "+Symbol()+Period(),OBJPROP_COLOR,TXTColor);
         ObjectCreate("TXT4 "+Symbol()+Period(),OBJ_LABEL,0,0,0);
         ObjectSet("TXT4 "+Symbol()+Period(),OBJPROP_CORNER,0);
         ObjectSet("TXT4 "+Symbol()+Period(),OBJPROP_XDISTANCE,5);
         ObjectSet("TXT4 "+Symbol()+Period(),OBJPROP_YDISTANCE,100);
         ObjectSet("TXT4 "+Symbol()+Period(),OBJPROP_COLOR,TXTColor);
      }
      ObjectSetText("TXT "+Symbol()+Period(),"Всего баров ="+vbars,14);
     ObjectSetText("TXT1 "+Symbol()+Period(),"Бычих баров ="+bbars,14);
     ObjectSetText("TXT2 "+Symbol()+Period(),"Медвежьих баров ="+mbars,14);
     ObjectSetText("TXT3 "+Symbol()+Period(),"Бычих баров в пунктах ="+DoubleToStr(bpoints,0),14);
     ObjectSetText("TXT4 "+Symbol()+Period(),"Медвежьих баров в пунктах ="+DoubleToStr(mpoints,0),14);
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+

Прежде всего замете что в этом индикаторе нет ни одного буфера, так как индикатор работает с графическими объектами.

Код: выделить все
datetime d1,d2;
      if(ObjectFind("Stat "+Symbol()+Period())==-1)
      {
        ObjectCreate("Stat "+Symbol()+Period(),OBJ_TREND,0,Time[30],High[30],Time[1],High[1]);
        ObjectSet("Stat "+Symbol()+Period(),OBJPROP_COLOR,Red);
        ObjectSet("Stat "+Symbol()+Period(),OBJPROP_RAY,false);
        d1=Time[30];
        d2=Time[1];
      }
      else
      {
         d1=ObjectGet("Stat "+Symbol()+Period(),OBJPROP_TIME1);
         d2=ObjectGet("Stat "+Symbol()+Period(),OBJPROP_TIME2);
      }

Индикатор использует трендовую линию для определения первого и последнего бара для анализа. В этом фрагменте кода проверяется создана ли трендовая линия, если он не создана, то она создается, причем она создается как отрезок кодом ObjectSet("Stat "+Symbol()+Period(),OBJPROP_RAY,false). Далее определяются точки старта и финиша линии путем определения времени первого и последнего бара линии. Так в данном случае они равны временам создания линии, то они и используются. Если линия уже создана, то опредиляется время первого и последнего бара линии путем извлечения их из объекта трендовая линия.

Код: выделить все
 int f1,f2,i,limit;
      f1=iBarShift(Symbol(),Period(),d1);
      f2=iBarShift(Symbol(),Period(),d2);
      if(f1==f2)
      {
         
         return (0);
      }
      if(f1>f2)
      {
         i=f2;
         limit=f1;
      }
      else
      {
         i=f1;
         limit=f2;
      }

Здесь мы оприделяем индыксы баров по их времени, так как нам будет нужен доступ к ценовым данным, а он производиться по индексу. Далее нам необходимо определить первый и последний индекс для цикла, и тут важно чтобы первый индекс должен быть больше последнего. Но с трендовой линией это может оказаться не так в случае если последняя точка линии будет на более познем баре. Поэтому нужно сделать проверку на расположение индексов, что и сделано в данном куске кода.

Код: выделить все
int vbars=limit-i+1;
      int bbars=0;
      double bpoints=0.0;
      int mbars=0;
      double mpoints=0.0;
      for(int shift=i;shift<=limit;shift++)
      {
         if(Open[shift]>Close[shift])
         {
            mbars++;
            mpoints=mpoints+(Open[shift]-Close[shift])/Point;
         }
         else
         {
            bbars++;
            bpoints=bpoints+(Close[shift]-Open[shift])/Point;
         }   
      }

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

Код: выделить все
 if(ObjectFind("TXT "+Symbol()+Period())==-1)
      {
         ObjectCreate("TXT "+Symbol()+Period(),OBJ_LABEL,0,0,0);
         ObjectSet("TXT "+Symbol()+Period(),OBJPROP_CORNER,0);
         ObjectSet("TXT "+Symbol()+Period(),OBJPROP_XDISTANCE,5);
         ObjectSet("TXT "+Symbol()+Period(),OBJPROP_YDISTANCE,20);
         ObjectSet("TXT "+Symbol()+Period(),OBJPROP_COLOR,TXTColor);
         ObjectCreate("TXT1 "+Symbol()+Period(),OBJ_LABEL,0,0,0);
         ObjectSet("TXT1 "+Symbol()+Period(),OBJPROP_CORNER,0);
         ObjectSet("TXT1 "+Symbol()+Period(),OBJPROP_XDISTANCE,5);
         ObjectSet("TXT1 "+Symbol()+Period(),OBJPROP_YDISTANCE,40);
         ObjectSet("TXT1 "+Symbol()+Period(),OBJPROP_COLOR,TXTColor);
         ObjectCreate("TXT2 "+Symbol()+Period(),OBJ_LABEL,0,0,0);
         ObjectSet("TXT2 "+Symbol()+Period(),OBJPROP_CORNER,0);
         ObjectSet("TXT2 "+Symbol()+Period(),OBJPROP_XDISTANCE,5);
         ObjectSet("TXT2 "+Symbol()+Period(),OBJPROP_YDISTANCE,60);
         ObjectSet("TXT2 "+Symbol()+Period(),OBJPROP_COLOR,TXTColor);
         ObjectCreate("TXT3 "+Symbol()+Period(),OBJ_LABEL,0,0,0);
         ObjectSet("TXT3 "+Symbol()+Period(),OBJPROP_CORNER,0);
         ObjectSet("TXT3 "+Symbol()+Period(),OBJPROP_XDISTANCE,5);
         ObjectSet("TXT3 "+Symbol()+Period(),OBJPROP_YDISTANCE,80);
         ObjectSet("TXT3 "+Symbol()+Period(),OBJPROP_COLOR,TXTColor);
         ObjectCreate("TXT4 "+Symbol()+Period(),OBJ_LABEL,0,0,0);
         ObjectSet("TXT4 "+Symbol()+Period(),OBJPROP_CORNER,0);
         ObjectSet("TXT4 "+Symbol()+Period(),OBJPROP_XDISTANCE,5);
         ObjectSet("TXT4 "+Symbol()+Period(),OBJPROP_YDISTANCE,100);
         ObjectSet("TXT4 "+Symbol()+Period(),OBJPROP_COLOR,TXTColor);
      }
      ObjectSetText("TXT "+Symbol()+Period(),"Всего баров ="+vbars,14);
     ObjectSetText("TXT1 "+Symbol()+Period(),"Бычих баров ="+bbars,14);
     ObjectSetText("TXT2 "+Symbol()+Period(),"Медвежьих баров ="+mbars,14);
     ObjectSetText("TXT3 "+Symbol()+Period(),"Бычих баров в пунктах ="+DoubleToStr(bpoints,0),14);
     ObjectSetText("TXT4 "+Symbol()+Period(),"Медвежьих баров в пунктах ="+DoubleToStr(mpoints,0),14);

Здесь происходит вывод на экран информации, при этом использованы текстовые метки, т.к. функция Comment при больших разрешениях экрана, выдает практически не читаемый текст. Важнный монет необходимо добавить для меток внешний парметр цвет, чтобы можно было настроить индикатор для разных цветовых схем графика.
Аватар пользователя
Рэндом
Специалист MQL
 
Сообщений: 13700
Зарегистрирован: 18 июл 2013, 08:05
Средств на руках: 31.45 Доллар
Группа: Администраторы
Благодарил (а): 1131 раз.
Поблагодарили: 3174 раз.
Каждый заблуждается в меру своих возможностей.

Re: Разбор кода на MQL.

Сообщение Nord » 21 авг 2013, 05:55

Отличная тема! Наглядно и практично.
Аватар пользователя
Nord
Администратор
 
Сообщений: 8112
Зарегистрирован: 17 июл 2013, 15:55
Средств на руках: 193.10 Доллар
Откуда: Украина
Группа: Администраторы
Благодарил (а): 3187 раз.
Поблагодарили: 6752 раз.
Правила форума - залог долгой жизни на форуме!

Re: Разбор кода на MQL.

Сообщение Рэндом » 22 авг 2013, 04:11

Советник ThreeBars MT5. Тема с советником viewtopic.php?f=9&t=115
Код: выделить все
//+------------------------------------------------------------------+
//|                                                    ThreeBars.mq5 |
//|                                                           Рэндом |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Рэндом"
#property link      ""
#property version   "1.00"
//--- input parameters
input int      SL=20;
input int      TralingStop=20;
input int      Slipage=3;
input int      DLot=100;
input int      Filtr=10;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
datetime tt;
int OnInit()
  {
//---
   MqlRates rt[];
   CopyRates(_Symbol,_Period,0,1,rt);
   tt=rt[0].time;
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   MqlRates rt[];
   ArraySetAsSeries(rt,true);
   CopyRates(_Symbol,_Period,0,5,rt);
   if(tt==rt[0].time) return;
   tt=rt[0].time;
   if(!PositionSelect(_Symbol))
   {
      if(rt[2].high+Filtr*_Point<rt[1].high && rt[2].low+Filtr*_Point<rt[1].low &&
         rt[3].high+Filtr*_Point<rt[2].high && rt[3].low+Filtr*_Point<rt[2].low &&
         rt[4].high+Filtr*_Point<rt[3].high && rt[4].low+Filtr*_Point<rt[3].low)
      {
         MqlTradeRequest rq={0};
         MqlTradeResult rz={0};
         rq.action=TRADE_ACTION_DEAL;
         rq.symbol=_Symbol;
         rq.volume=FLot(DLot);
         rq.type=ORDER_TYPE_BUY;
         rq.price=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
         rq.sl=SymbolInfoDouble(_Symbol,SYMBOL_BID)-SL*_Point;
         OrderSend(rq,rz);
      }
      if(rt[2].high-Filtr*_Point>rt[1].high && rt[2].low-Filtr*_Point>rt[1].low &&
         rt[3].high-Filtr*_Point>rt[2].high && rt[3].low-Filtr*_Point>rt[2].low &&
         rt[4].high-Filtr*_Point>rt[3].high && rt[4].low-Filtr*_Point>rt[3].low)
      {
         MqlTradeRequest rq={0};
         MqlTradeResult rz={0};
         rq.action=TRADE_ACTION_DEAL;
         rq.symbol=_Symbol;
         rq.volume=FLot(DLot);
         rq.type=ORDER_TYPE_SELL;
         rq.price=SymbolInfoDouble(_Symbol,SYMBOL_BID);
         rq.sl=SymbolInfoDouble(_Symbol,SYMBOL_ASK)+SL*_Point;
         OrderSend(rq,rz);
      }
   }
   else
   {
      if(PositionGetInteger(POSITION_TYPE)==ORDER_TYPE_BUY)
      {
         if(PositionGetDouble(POSITION_SL)+SL*_Point+TralingStop*_Point<SymbolInfoDouble(_Symbol,SYMBOL_BID))
         {
            MqlTradeRequest rq={0};
            MqlTradeResult rz={0};
            rq.action=TRADE_ACTION_SLTP;
            rq.symbol=_Symbol;
           
            rq.sl=SymbolInfoDouble(_Symbol,SYMBOL_BID)-SL*_Point;
            OrderSend(rq,rz);
         }
      }
      if(PositionGetInteger(POSITION_TYPE)==ORDER_TYPE_SELL)
      {
         if(PositionGetDouble(POSITION_SL)-SL*_Point-TralingStop*_Point>SymbolInfoDouble(_Symbol,SYMBOL_ASK))
         {
            MqlTradeRequest rq={0};
            MqlTradeResult rz={0};
            rq.action=TRADE_ACTION_SLTP;
            rq.symbol=_Symbol;
           
            rq.sl=SymbolInfoDouble(_Symbol,SYMBOL_ASK)+SL*_Point;
            OrderSend(rq,rz);
         }
      }
   }
  }
 
double FLot(double Frac)
{
   double minl=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
   double maxl=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
   double lot=MathFloor(AccountInfoDouble(ACCOUNT_BALANCE)/Frac)*minl;
   if(lot>maxl) lot=maxl;
   if(lot<minl) lot=minl;
   return lot;
}
//+------------------------------------------------------------------+


С этим советником все просто. Единственный интересный момент это работа по ценам открытия.

Код: выделить все
datetime tt;


Прежде всего объявляется глобальная переменная в которой будет храниться время текущего последнего бара.

Код: выделить все
int OnInit()
  {
//---
   MqlRates rt[];
   CopyRates(_Symbol,_Period,0,1,rt);
   tt=rt[0].time;
//---
   return(INIT_SUCCEEDED);
  }


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

Код: выделить все
   MqlRates rt[];
   ArraySetAsSeries(rt,true);
   CopyRates(_Symbol,_Period,0,5,rt);
   if(tt==rt[0].time) return;
   tt=rt[0].time;


Здесь проверяется равно ли текущие время в глобальной переменной и время последнего бара. Если они равны, то выходим из советника. Если не равны, то записываем в глобальную переменную новое время и выполняем код советника.
Аватар пользователя
Рэндом
Специалист MQL
 
Сообщений: 13700
Зарегистрирован: 18 июл 2013, 08:05
Средств на руках: 31.45 Доллар
Группа: Администраторы
Благодарил (а): 1131 раз.
Поблагодарили: 3174 раз.
Каждый заблуждается в меру своих возможностей.

Re: Разбор кода на MQL.

Сообщение Рэндом » 23 авг 2013, 03:43

Библиотека martingail MT5. Тема с библиотекой viewtopic.php?f=9&t=120
Код: выделить все
//+------------------------------------------------------------------+
//|                                                   Martingail.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, Alf."
#property link      ""
//+------------------------------------------------------------------+
//| Martingail class                                                 |
//+------------------------------------------------------------------+
class Martingail
  {
private:
   int               ud;
public:
   double            Shape; //доля депозита на один минимальный лот
   int               DoublingCount;// количество удвоений
   string            GVarName;//Задвет имя глобальной переменной терминала.
   void              GVarGet();//Получить текущее количество удвоений из глобальной переменной терминала
   void              GVarSet();//Записать текущее количество удвоений в глобальную переменную терминала
   double            Lot();//Расчитать размер лота
  };
//+------------------------------------------------------------------+
//| GVarGet                                                          |
//+------------------------------------------------------------------+
void Martingail::GVarGet(void)
  {
   if(!GlobalVariableCheck(GVarName)) GlobalVariableSet(GVarName,0);
   ud=(int)GlobalVariableGet(GVarName);
  }
//+------------------------------------------------------------------+
//| GVarSet                                                          |
//+------------------------------------------------------------------+
void Martingail::GVarSet(void)
  {
   GlobalVariableSet(GVarName,ud);
  }
//+------------------------------------------------------------------+
//| Lot                                                              |
//+------------------------------------------------------------------+
double Martingail::Lot(void)
  {
   double Lot=MathFloor(AccountInfoDouble(ACCOUNT_BALANCE)/Shape)*SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
   if(Lot==0)Lot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
   if(DoublingCount<=0) return Lot;
   double MaxLot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);

   if(Lot>MaxLot)Lot=MaxLot;
   double lt1=Lot;
   HistorySelect(0,TimeCurrent());
   if(HistoryOrdersTotal()==0)return(Lot);
   double cl=HistoryOrderGetDouble(HistoryOrderGetTicket(HistoryOrdersTotal()-1),ORDER_PRICE_OPEN);
   double op=HistoryOrderGetDouble(HistoryOrderGetTicket(HistoryOrdersTotal()-2),ORDER_PRICE_OPEN);

   long typeor=HistoryOrderGetInteger(HistoryOrderGetTicket(HistoryOrdersTotal()-2),ORDER_TYPE);
   if(typeor==ORDER_TYPE_BUY)
     {
      if(op>cl)
        {
         if(ud<DoublingCount)
           {
            lt1=HistoryOrderGetDouble(HistoryOrderGetTicket(HistoryOrdersTotal()-2),ORDER_VOLUME_INITIAL)*2;
            ud++;
           }
         else ud=0;
        }
      else ud=0;
     }
   if(typeor==ORDER_TYPE_SELL)
     {
      if(cl>op)
        {
         if(ud<DoublingCount)
           {
            lt1=HistoryOrderGetDouble(HistoryOrderGetTicket(HistoryOrdersTotal()-2),ORDER_VOLUME_INITIAL)*2;
            ud++;
           }
         else ud=0;
        }
      else ud=0;
     }
   if(lt1>MaxLot)lt1=MaxLot;
   return(lt1);
  }
//+------------------------------------------------------------------+

Эта библиотека проста для понимания. Интересный момент это оформление библиотеки в виде класса. Почему она создана как класс? Прежде всего в работе библиотеки используется переменная для хранения количества удвоений. Это служебная переменная предназначенная для контроля количества удвоений и принятия решения о прекращении удвоений лота если они превысили заданное число. Желательно сделать так, чтобы у пользователя библиотеки не было доступа к ней. А сделать это можно объявив класс и сделав эту переменную приватной. Но это не единственный довод. Еще один довод связан с набором связанных функций. Нам недостаточно одной функции расчета лота, еще нужны служебные функции для обеспечения корректной работы бмблиотеки. Это функции работы с глобальными переменными терминала. Они нужны потому что нужно сохранять количество удвоений при выходе из терминала.
Аватар пользователя
Рэндом
Специалист MQL
 
Сообщений: 13700
Зарегистрирован: 18 июл 2013, 08:05
Средств на руках: 31.45 Доллар
Группа: Администраторы
Благодарил (а): 1131 раз.
Поблагодарили: 3174 раз.
Каждый заблуждается в меру своих возможностей.

Re: Разбор кода на MQL.

Сообщение Рэндом » 26 авг 2013, 02:46

Советник NeuroPipser МТ5. Тема с советником viewtopic.php?f=9&t=117
Код: выделить все
//+------------------------------------------------------------------+
//|                                                    SuperPips.mq5 |
//|                                                           Рэндом |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Рэндом"
#property link      ""
#property version   "1.00"
//--- input parameters
input int      SL=200;
input int      Slipage=30;
input int      DLot=100;
input double   OpenLongLevel=10;
input double   OpenShortLevel=10;
input double   CloseLongLevel=5;
input double   ClodeShortLevel=5;

input double   W1_1=-100;
input double   W1_2=-100;
input double   W1_3=-100;
input double   W1_4=-100;
input double   W1_5=-100;
input double   W1_6=-100;
input double   W1_7=-100;
input double   W1_8=-100;
input double   W1_9=-100;
input double   W1_10=-100;

input double   W2_1=-100;
input double   W2_2=-100;
input double   W2_3=-100;
input double   W2_4=-100;
input double   W2_5=-100;
input double   W2_6=-100;
input double   W2_7=-100;
input double   W2_8=-100;
input double   W2_9=-100;
input double   W2_10=-100;

input double   W3_1=-100;
input double   W3_2=-100;
input double   W3_3=-100;
input double   W3_4=-100;
input double   W3_5=-100;
input double   W3_6=-100;
input double   W3_7=-100;
input double   W3_8=-100;
input double   W3_9=-100;
input double   W3_10=-100;

input double   W4_1=-100;
input double   W4_2=-100;
input double   W4_3=-100;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+

datetime tt;
int OnInit()
  {
//---
   
   MqlRates rt[];
   CopyRates(_Symbol,_Period,0,1,rt);
   tt=rt[0].time;
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   MqlRates rt[];
   CopyRates(_Symbol,_Period,0,1,rt);
   if(rt[0].time==tt) return;
   tt=rt[0].time;
   
   MqlTradeResult result={0};
   MqlTradeRequest request={0};
   
   request.symbol=_Symbol;   
   request.deviation=Slipage;
   request.action=TRADE_ACTION_DEAL;
   
   MqlTick last_tick;
   SymbolInfoTick(_Symbol,last_tick);
   
   if(PositionsTotal()==0)
   {
      if(Long())
      {
         request.volume=FLot(DLot);
         request.price=last_tick.ask;
         request.type=ORDER_TYPE_BUY;
         request.sl=last_tick.bid-SL*Point();
     
         OrderSend(request,result);
      }
      if(Short())
      {
         request.volume=FLot(DLot);
         request.price=last_tick.bid;
         request.type=ORDER_TYPE_SELL;
         request.sl=last_tick.ask+SL*Point();
     
         OrderSend(request,result);
      }
   }
   else
   {
      if(PositionSelect(_Symbol))
      {
         long ty=PositionGetInteger(POSITION_TYPE);
         if(ty==POSITION_TYPE_BUY && CloseLong())
         {
            request.volume=PositionGetDouble(POSITION_VOLUME);
            request.price=last_tick.bid;
            request.type=ORDER_TYPE_SELL;
     
            OrderSend(request,result);
            if(Short())
            {
               request.volume=FLot(DLot);
               request.price=last_tick.bid;
               request.type=ORDER_TYPE_SELL;
               request.sl=last_tick.ask+SL*Point();
     
               OrderSend(request,result);
            }
         }
         if(ty==POSITION_TYPE_SELL && CloseShort())
         {
            request.volume=PositionGetDouble(POSITION_VOLUME);
            request.price=last_tick.ask;
            request.type=ORDER_TYPE_BUY;
     
            OrderSend(request,result);
            if(Long())
            {
               request.volume=FLot(DLot);
               request.price=last_tick.ask;
               request.type=ORDER_TYPE_BUY;
               request.sl=last_tick.bid-SL*Point();
     
               OrderSend(request,result);
            }
         }
      }
   }
  }
 
bool Long()
{
   double n=Net();
   if(n>0 && MathAbs(n)>OpenLongLevel) return true;
   return false;
}

bool Short()
{
   double n=Net();
   if(n<0 && MathAbs(n)>OpenShortLevel) return true;
   return false;
}

bool CloseLong()
{
   double n=Net();
   if(n<0 && MathAbs(n)>CloseLongLevel) return true;
   return false;
}

bool CloseShort()
{
   double n=Net();
   if(n>0 && MathAbs(n)>ClodeShortLevel) return true;
   return false;
}
double FLot(double Fract)
{
   double minl=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
   double maxl=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
   double lot=MathFloor(AccountInfoDouble(ACCOUNT_BALANCE)/Fract)*minl;
   if(lot>maxl) lot=maxl;
   if(lot<minl) lot=minl;
   return lot;
}

double Net()
{
   MqlRates rt[];
   CopyRates(_Symbol,_Period,1,10,rt);
   double med[10]={0};
   for(int i=0;i<10;i++)
      med[i]=(rt[i].high-rt[i].low)/2;
   double p1=med[0]*W1_1+med[1]*W1_2+med[2]*W1_3+med[3]*W1_4+med[4]*W1_5+med[5]*W1_6+med[6]*W1_7+med[7]*W1_8+med[8]*W1_9+med[9]*W1_10;
   double p2=med[0]*W2_1+med[1]*W2_2+med[2]*W2_3+med[3]*W2_4+med[4]*W2_5+med[5]*W2_6+med[6]*W2_7+med[7]*W2_8+med[8]*W2_9+med[9]*W2_10;
   double p3=med[0]*W3_1+med[1]*W3_2+med[2]*W3_3+med[3]*W3_4+med[4]*W3_5+med[5]*W3_6+med[6]*W3_7+med[7]*W3_8+med[8]*W3_9+med[9]*W3_10;
   double res= p1*W4_1+p2*W4_2+p3*W4_3;
   return res;
}
//+------------------------------------------------------------------+

Я считаю что код советника предельно понятен. Но и в нем есть интересные моменты. В советнике множество входных параметров, причем эти параметры можно подобрать только в тестере. Тестер МТ4 не справиться с таким количеством параметров, а тестер МТ5 прекрасно справляется. Еще один интересный момент в том, что советник разбит на функции, что упрощает его понимание и его можно использовать как шаблон переписывая лишь функции открытия и закрытия позиций.
Аватар пользователя
Рэндом
Специалист MQL
 
Сообщений: 13700
Зарегистрирован: 18 июл 2013, 08:05
Средств на руках: 31.45 Доллар
Группа: Администраторы
Благодарил (а): 1131 раз.
Поблагодарили: 3174 раз.
Каждый заблуждается в меру своих возможностей.

Re: Разбор кода на MQL.

Сообщение Рэндом » 27 авг 2013, 02:57

Советник Pipser MT5. Тема с советником viewtopic.php?f=9&t=95
Код: выделить все
//+------------------------------------------------------------------+
//|                                                       Pipser.mq5 |
//|                                             Copyright 2010, Alf. |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, Alf."
#property link      ""
#property version   "1.00"
//--- input parameters
input double   Lot=0.1;
input int      SL=150;
input int      Slipage=0;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   ObjectCreate(0,"BUY",OBJ_BUTTON,0,0,0);
   ObjectSetInteger(0,"BUY",OBJPROP_XDISTANCE,ChartGetInteger(0,CHART_WIDTH_IN_PIXELS)-100);
   ObjectSetInteger(0,"BUY",OBJPROP_YDISTANCE,50);
   ObjectSetString(0,"BUY",OBJPROP_TEXT,"Buy");
   ObjectCreate(0,"SELL",OBJ_BUTTON,0,0,0);
   ObjectSetInteger(0,"SELL",OBJPROP_XDISTANCE,ChartGetInteger(0,CHART_WIDTH_IN_PIXELS)-100);
   ObjectSetInteger(0,"SELL",OBJPROP_YDISTANCE,80);
   ObjectSetString(0,"SELL",OBJPROP_TEXT,"Sell");
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   ObjectDelete(0,"BUY");
   ObjectDelete(0,"SELL");
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
  }
//+------------------------------------------------------------------+
//| OnChart event handler                                            |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
   double SL2=SL;
   if(_Digits==5 || _Digits==3)  SL2=SL2*10;

   MqlTick last_tick;
   SymbolInfoTick(_Symbol,last_tick);
   MqlTradeResult result;
   MqlTradeRequest request;
   ZeroMemory(result);
   ZeroMemory(request);

   request.symbol=_Symbol;
   request.magic=777;
   request.deviation=Slipage;
   request.action=TRADE_ACTION_DEAL;
   request.type_filling=ORDER_FILLING_FOK;
   if(ObjectGetInteger(0,"BUY",OBJPROP_STATE)!=0)
     {
      ObjectSetInteger(0,"BUY",OBJPROP_STATE,0);
      request.volume=Lot;
      request.price=last_tick.ask;
      request.type=ORDER_TYPE_BUY;
      if(SL2!=0) request.sl=last_tick.bid-SL2*Point();
      else request.sl=0;
      request.tp=0;
      OrderSend(request,result);
      return;
     }
   if(ObjectGetInteger(0,"SELL",OBJPROP_STATE)!=0)
     {
      ObjectSetInteger(0,"SELL",OBJPROP_STATE,0);
      request.volume=Lot;
      request.price=last_tick.bid;
      request.type=ORDER_TYPE_SELL;
      if(SL2!=0) request.sl=last_tick.ask+SL2*Point();
      else request.sl=0;
      request.tp=0;
      OrderSend(request,result);
      return;
     }
  }
//+------------------------------------------------------------------+

Этот советник предназначен для сделок в один клик. В нем используются такие графические объекты как кнопки. Для обработки нажатия кнопки используется специальная функция
Код: выделить все
void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam)

Эта функция вызывается при действии с объектами на графике и вся обработка нажатия кнопок происходит в ней.
Замете так же что после нажатия кнопки она остается в нажатом состоянии до тех пор пока она не будет отжата кодом:
Код: выделить все
ObjectSetInteger(0,"BUY",OBJPROP_STATE,0);
ObjectSetInteger(0,"SELL",OBJPROP_STATE,0);

Кстати так же эти функции можно использовать для программного нажатия кнопки.
Аватар пользователя
Рэндом
Специалист MQL
 
Сообщений: 13700
Зарегистрирован: 18 июл 2013, 08:05
Средств на руках: 31.45 Доллар
Группа: Администраторы
Благодарил (а): 1131 раз.
Поблагодарили: 3174 раз.
Каждый заблуждается в меру своих возможностей.

Re: Разбор кода на MQL.

Сообщение Рэндом » 28 авг 2013, 02:24

Индикатор Volatility МТ5. Тема с индикатором viewtopic.php?f=9&t=105
Код: выделить все
//+------------------------------------------------------------------+
//|                                                   Volatility.mq5 |
//|                                                           Рэндом |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Рэндом"
#property link      "http://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot Main
#property indicator_label1  "Main"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- input parameters
input int      Interval=14;
//--- indicator buffers
double         MainBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,MainBuffer,INDICATOR_DATA);
   ArraySetAsSeries(MainBuffer,true);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   int limit;
   ArraySetAsSeries(high,true);
   ArraySetAsSeries(close,true);
   limit=Bars(_Symbol,_Period)-prev_calculated;
   for(int i=0;i<limit;i++)
   {
      if(i+Interval>Bars(_Symbol,_Period)-1) continue;
      double fist=(high[i]-low[i])/2;
      double end=(high[i+Interval]-low[i+Interval])/2;
      MainBuffer[i]=fist-end;
   }
//--- return value of prev_calculated for next call
   return(rates_total);
  }

Здесь самое интересное это буфер индикатора который отображается на графике.
Код: выделить все
double         MainBuffer[];

Буфер определяется как массив, причем замете что его размер не определен.
Код: выделить все
SetIndexBuffer(0,MainBuffer,INDICATOR_DATA);

Эта функция задает массив буфером индикатора. Это приводит к тому что размер массива всегда равен количеству баров на графике. При появлении новых баров размер массива меняется.
Код: выделить все
ArraySetAsSeries(MainBuffer,true);

Здесь устанавливается привычный способ (для МТ4) индексации буфера. Последний бар имеет индекс 0. Следует учесть что по умолчанию нумерация баров в буферах в МТ5 отличается от МТ4. По умолчанию последний индекс соответствует последнему бару на графике.
Аватар пользователя
Рэндом
Специалист MQL
 
Сообщений: 13700
Зарегистрирован: 18 июл 2013, 08:05
Средств на руках: 31.45 Доллар
Группа: Администраторы
Благодарил (а): 1131 раз.
Поблагодарили: 3174 раз.
Каждый заблуждается в меру своих возможностей.

Re: Разбор кода на MQL.

Сообщение Рэндом » 29 авг 2013, 02:48

Индикатор alfos MT5. Тема с индикатором viewtopic.php?f=9&t=78
Код: выделить все
//+------------------------------------------------------------------+
//|                                                        AlfOs.mq5 |
//|                                             Copyright 2009, Alf. |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright   "2009, MetaQuotes Software Corp."
#property link        ""
#property description "Alf of Oscillator"

#include <MovingAverages.mqh>

#property indicator_separate_window
#property indicator_buffers 5
#property indicator_plots   1
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_color1  Silver
#property indicator_width1  2

input int                MA1=12;
input int                MA2=26;
input int                CMO1=55;
input int                CMO2=55;
input int                Signal=9;
input ENUM_APPLIED_PRICE InpAppliedPrice=PRICE_CLOSE;

double                   ExtOsMABuffer[];
double                   ExtMacdBuffer[];
double                   ExtSignalBuffer[];
double                   ExtFastMaBuffer[];
double                   ExtSlowMaBuffer[];

int                      ExtFastMaHandle;
int                      ExtSlowMaHandle;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
   SetIndexBuffer(0,ExtOsMABuffer,INDICATOR_DATA);
   SetIndexBuffer(1,ExtMacdBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(2,ExtSignalBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(3,ExtFastMaBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(4,ExtSlowMaBuffer,INDICATOR_CALCULATIONS);
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits+2);

   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,MA2+Signal-2);

   IndicatorSetString(INDICATOR_SHORTNAME,"AlfOs("+string(MA1)+","+string(MA2)+","+string(Signal)+")");
   PlotIndexSetString(0,PLOT_LABEL,"AlfOs");

   ExtFastMaHandle=iVIDyA(NULL,0,CMO1,MA1,0,InpAppliedPrice);
   ExtSlowMaHandle=iVIDyA(NULL,0,CMO2,MA2,0,InpAppliedPrice);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,const int prev_calculated,
                const datetime &Time[],
                const double &Open[],
                const double &High[],
                const double &Low[],
                const double &Close[],
                const long &TickVolume[],
                const long &Volume[],
                const int &Spread[])
  {
   if(rates_total<Signal)
      return(0);

   int calculated=BarsCalculated(ExtFastMaHandle);
   if(calculated<rates_total)
     {
      Print("Not all data of ExtFastMaHandle is calculated (",calculated,"bars ). Error",GetLastError());
      return(0);
     }
   calculated=BarsCalculated(ExtSlowMaHandle);
   if(calculated<rates_total)
     {
      Print("Not all data of ExtSlowMaHandle is calculated (",calculated,"bars ). Error",GetLastError());
      return(0);
     }

   int to_copy;
   if(prev_calculated>rates_total || prev_calculated<0) to_copy=rates_total;
   else
     {
      to_copy=rates_total-prev_calculated;
      if(prev_calculated>0) to_copy++;
     }

   if(CopyBuffer(ExtFastMaHandle,0,0,to_copy,ExtFastMaBuffer)<=0)
     {
      Print("Getting fast EMA is failed! Error",GetLastError());
      return(0);
     }

   if(CopyBuffer(ExtSlowMaHandle,0,0,to_copy,ExtSlowMaBuffer)<=0)
     {
      Print("Getting slow SMA is failed! Error",GetLastError());
      return(0);
     }

   int i,limit;
   if(prev_calculated==0)
      limit=0;
   else limit=prev_calculated-1;

   for(i=limit;i<rates_total;i++)
     {

      ExtMacdBuffer[i]=ExtFastMaBuffer[i]-ExtSlowMaBuffer[i];
     }

   SimpleMAOnBuffer(rates_total,prev_calculated,0,Signal,ExtMacdBuffer,ExtSignalBuffer);

   for(i=limit;i<rates_total;i++)
     {
      ExtOsMABuffer[i]=ExtMacdBuffer[i]-ExtSignalBuffer[i];
     }

   return(rates_total);
  }
//+------------------------------------------------------------------+

Здесь интересна работа с индикаторами. В МТ4 при вызове встроенного индикатора мы получаем его данные. В МТ5 этот процесс несколько сложнее. Сначало нужно получить хэндл (индитификатор) индикатора.
Код: выделить все
 ExtFastMaHandle=iVIDyA(NULL,0,CMO1,MA1,0,InpAppliedPrice);
 ExtSlowMaHandle=iVIDyA(NULL,0,CMO2,MA2,0,InpAppliedPrice);

А затем копировать его в буфер.
Код: выделить все
CopyBuffer(ExtFastMaHandle,0,0,to_copy,ExtFastMaBuffer)
CopyBuffer(ExtSlowMaHandle,0,0,to_copy,ExtSlowMaBuffer)

Причем буфер должен быть объявлен следующим образом чтобы быть динамическим и соответствовать количеству баров на графике.
Код: выделить все
   SetIndexBuffer(3,ExtFastMaBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(4,ExtSlowMaBuffer,INDICATOR_CALCULATIONS);
Аватар пользователя
Рэндом
Специалист MQL
 
Сообщений: 13700
Зарегистрирован: 18 июл 2013, 08:05
Средств на руках: 31.45 Доллар
Группа: Администраторы
Благодарил (а): 1131 раз.
Поблагодарили: 3174 раз.
Каждый заблуждается в меру своих возможностей.

Re: Разбор кода на MQL.

Сообщение Рэндом » 30 авг 2013, 03:57

Индикатор IshOs МТ5. Тема viewtopic.php?f=9&t=37
Код: выделить все
//+------------------------------------------------------------------+
//|                                                        IshOs.mq5 |
//|                                                           Рэндом |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Рэндом"
#property link      ""
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 6
#property indicator_plots   2
//--- plot Main
#property indicator_label1  "Main"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot Signal
#property indicator_label2  "Signal"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrMediumBlue
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- input parameters
input int      Tekan_sen=9;
input int      Kijun_sen=26;
input int      Senkou_Span_B=52;
//--- indicator buffers
double         MainBuffer[];
double         SignalBuffer[];

double    ExtTenkanBuffer[];
double    ExtKijunBuffer[];
double    ExtSpanABuffer[];
double    ExtSpanBBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int ish;
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,MainBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,SignalBuffer,INDICATOR_DATA);
   SetIndexBuffer(2,ExtTenkanBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(3,ExtKijunBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(4,ExtSpanABuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(5,ExtSpanBBuffer,INDICATOR_CALCULATIONS);
   
   ish=iCustom(_Symbol,_Period,"Examples\Ichimoku",Tekan_sen,Kijun_sen,Senkou_Span_B);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   int calculated=BarsCalculated(ish);
   if(calculated<rates_total)
     {
      Print("Not all data of ExtFastMaHandle is calculated (",calculated,"bars ). Error",GetLastError());
      return(0);
     }
     int to_copy;
   if(prev_calculated>rates_total || prev_calculated<0) to_copy=rates_total;
   else
     {
      to_copy=rates_total-prev_calculated;
      if(prev_calculated>0) to_copy++;
     }

   if(IsStopped()) return(0); //Checking for stop flag
   if(CopyBuffer(ish,0,0,to_copy,ExtTenkanBuffer)<=0)
     {
      Print("Error",GetLastError());
      return(0);
     }

   if(IsStopped()) return(0); //Checking for stop flag
   if(CopyBuffer(ish,1,0,to_copy,ExtKijunBuffer)<=0)
     {
      Print("Error",GetLastError());
      return(0);
     }
     
   if(IsStopped()) return(0); //Checking for stop flag
   if(CopyBuffer(ish,2,0,to_copy,ExtSpanABuffer)<=0)
     {
      Print("Error",GetLastError());
      return(0);
     }
     
   if(IsStopped()) return(0); //Checking for stop flag
   if(CopyBuffer(ish,3,0,to_copy,ExtSpanBBuffer)<=0)
     {
      Print("Error",GetLastError());
      return(0);
     }
//---
   int limit;
   if(prev_calculated==0)
      limit=0;
   else limit=prev_calculated-1;

   for(int i=limit;i<rates_total && !IsStopped();i++)
   {
      int k=i-Kijun_sen;
      if (k<0) continue;
      MainBuffer[i]=ExtSpanABuffer[k]-ExtSpanBBuffer[k];
      SignalBuffer[i]=ExtTenkanBuffer[i]-ExtKijunBuffer[i];
   }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result)
  {
//---
   
  }
//+------------------------------------------------------------------+

Тут интересен следующий код
Код: выделить все
for(int i=limit;i<rates_total && !IsStopped();i++)
   {
      int k=i-Kijun_sen;
      if (k<0) continue;
      MainBuffer[i]=ExtSpanABuffer[k]-ExtSpanBBuffer[k];
      SignalBuffer[i]=ExtTenkanBuffer[i]-ExtKijunBuffer[i];
   }

Код: выделить все
 if (k<0) continue;

Дело в том что цикл определен так что может быть выход за границы буфера, и индикатор завершиться по ошибке. Этот код проверяет выходит ли индекс за границы, и если выходит, то начинается новая итерация цикла.
Аватар пользователя
Рэндом
Специалист MQL
 
Сообщений: 13700
Зарегистрирован: 18 июл 2013, 08:05
Средств на руках: 31.45 Доллар
Группа: Администраторы
Благодарил (а): 1131 раз.
Поблагодарили: 3174 раз.
Каждый заблуждается в меру своих возможностей.


Вернуться в MQL – теория и практика

Кто сейчас на форуме?

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 54

Права доступа к форуму

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения