Как начать работу с MQL5

 

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


Если вы только начинаете знакомиться с терминалом MetaTrader 5, то могу порекомендовать следующие темы:

 

Недавно мне задали такой вопрос: как получить данные из индикатора iBearsPower?

Прежде чем показать код, начну с основных моментов работы с индикаторами в экспертах MQL5:

Шаг 1: на глобальном уровне программы объявляем переменную - в ней будет храниться хэндл индикатора iBearsPower.

Шаг 2: в OnInit () создаем индикатор iBearsPower и записываем хэндл в переменную. Примечание: индикатор создается ОДИН раз в OnInit ().

Шаг 3: в OnTick () мы получаем данные из индикатора.


Пример находится в CodeBase в коде MySystem.

Шаг 1:

double ExtStopLoss=0.0;
double ExtTakeProfit=0.0;

int    handle_iBullsPower;          // variable for storing the handle of the iBullsPower indicator 
int    handle_iBearsPower;          // variable for storing the handle of the iBearsPower indicator 

double m_adjusted_point;            // point value adjusted for 3 or 5 points
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()


Шаг 2:

     }
//--- create handle of the indicator iBearsPower
   handle_iBearsPower=iBearsPower(m_symbol.Name(),Period(),Inp_ma_period);
//--- if the handle is not created 
   if(handle_iBearsPower==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code 
      PrintFormat("Failed to create handle of the iBearsPower indicator for the symbol %s/%s, error code %d",
                  m_symbol.Name(),
                  EnumToString(Period()),
                  GetLastError());
      //--- the indicator is stopped early 
      return(INIT_FAILED);
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)


Шаг 3:

   double bulls[];
   ArraySetAsSeries(bulls,true);
   double bears[];
   ArraySetAsSeries(bears,true);
   if(!iBullsPowerGetArray(InpBarCurrent,2,bulls) || !iBearsPowerGetArray(InpBarCurrent,2,bears))
     {
      PrevBars=0;
      return;

     }


Функция iBearsPowerGetArray: используется CopyBuffer

//+------------------------------------------------------------------+
//| Get value of buffers for the iBearsPower in the array            |
//+------------------------------------------------------------------+
bool iBearsPowerGetArray(const int start_pos,const int count,double &arr_buffer[])
  {
//---
   bool result=true;
   if(!ArrayIsDynamic(arr_buffer))
     {
      Print("This a no dynamic array!");
      return(false);
     }
   ArrayFree(arr_buffer);
   int       buffer_num=0;          // indicator buffer number 
//--- reset error code 
   ResetLastError();
//--- fill a part of the iBearsPower array with values from the indicator buffer that has 0 index 
   int copied=CopyBuffer(handle_iBearsPower,buffer_num,start_pos,count,arr_buffer);
   if(copied!=count)
     {
      //--- if the copying fails, tell the error code 
      PrintFormat("Failed to copy data from the iBearsPower indicator, error code %d",GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated 
      return(false);
     }
   return(result);
  }
 

Как получать данные от индикаторов из нескольких символов.

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

Итак, советник получает данные с текущего символа и еще с одного (" Символ 1 "), период усреднения задается в параметре Bulls Power:

 //--- input parameters 
 input string    InpSybmol_1 = "USDJPY" ;           // Symbol 1 (non-existent symbol -> parameter is disabled) 
 input int       Inp_BullsPower_ma_period   = 5 ;   // Bulls Power : averaging period  


В поле глобальных переменных программы создаем две переменные - в них будут храниться хэндлы индикаторов Bulls Power:

 //--- 
 int      handle_iBullsPower_current ;               // variable for storing the handle of the iBullsPower indicator 

 int      handle_iBullsPower_symbol_1 ;             // variable for storing the handle of the iBullsPower indicator 
 int     m_digits_symbol_1;

m_digits_symbol_1 - вспомогательная переменная, в ней хранится количество знаков после запятой для символа 1.


Создание хендлов совмещено с проверкой символа: если символ существует, то мы создаем хендл:

 //+------------------------------------------------------------------+ 
 //| Expert initialization function                                   | 
 //+------------------------------------------------------------------+ 
 int OnInit ()
  {
 //--- 
   handle_iBullsPower_symbol_1= INVALID_HANDLE ;
   m_digits_symbol_1= 0 ;
   if (m_symbol.Name(InpSybmol_1)) // sets symbol name 
     {
      m_digits_symbol_1=m_symbol. Digits ();
      CreateBullsPower(handle_iBullsPower_symbol_1,m_symbol.Name(), Period (),Inp_BullsPower_ma_period);
     }

   handle_iBullsPower_current= INVALID_HANDLE ;
   if (m_symbol.Name( Symbol ())) // sets symbol name 
      CreateBullsPower(handle_iBullsPower_current,m_symbol.Name(), Period (),Inp_BullsPower_ma_period);
 //--- 
   return ( INIT_SUCCEEDED );
  }

Хендлы создаются в функции CreateBullsPower:

 //+------------------------------------------------------------------+ 
 //| Create Bulls Power                                               | 
 //+------------------------------------------------------------------+ 
 bool CreateBullsPower( int                  &handle,     // handle of the indicator 
                       const      string      symbol,     // symbol name  
                       ENUM_TIMEFRAMES      timeframe,   // timeframe  
                       int                  ma_period   // averaging period  
                      )
  {
   handle= INVALID_HANDLE ;
 //--- create handle of the indicator iBullsPower 
   handle= iBullsPower (symbol,timeframe,ma_period);
 //--- if the handle is not created  
   if (handle== INVALID_HANDLE )
     {
       //--- tell about the failure and output the error code  
       PrintFormat ( "Failed to create handle of the iBullsPower indicator for the symbol %s/%s, error code %d" ,
                  symbol,
                   EnumToString (timeframe),
                   GetLastError ());
       //--- the indicator is stopped early  
       return ( false );
     }
 //--- 
   return ( true );
  }


Осталось получить данные от индикатора в OnTick () (получаем данные с помощью функции iGetArray)

 //+------------------------------------------------------------------+ 
 //| Expert tick function                                             | 
 //+------------------------------------------------------------------+ 
 void OnTick ()
  {
 //--- 
   string text= "" ;
   double value[];
   ArraySetAsSeries (value, true );
   int buffer= 0 ,start_pos= 0 ,count= 2 ;

   if (handle_iBullsPower_current!= INVALID_HANDLE )
       if (iGetArray(handle_iBullsPower_current,buffer,start_pos,count,value))
        {
         text=text+ "\n" +m_symbol.Name();
         for ( int i= 0 ;i<count;i++)
           {
            text=text+ " #" + IntegerToString (i)+ "+: " + DoubleToString (value[i],m_symbol. Digits ()+ 1 )+ "; " ;
           }
        }
   if (handle_iBullsPower_symbol_1!= INVALID_HANDLE )
       if (iGetArray(handle_iBullsPower_symbol_1,buffer,start_pos,count,value))
        {
         text=text+ "\n" +InpSybmol_1;
         for ( int i= 0 ;i<count;i++)
           {
            text=text+ " #" + IntegerToString (i)+ "+: " + DoubleToString (value[i],m_digits_symbol_1+ 1 )+ "; " ;
           }
        }

   Comment (text);
  }


Итого:

Мультисимвол BullsPower

Файлы:
 
Возможно ли перенести часть ручки в секции OnInit() в секцию OnTick()?
 
budiali:
Возможно ли перенести часть хэндла из секции OnInit() в секцию OnTick()?

Хендл ДОЛЖЕН быть создан ТОЛЬКО ОДИН раз. Наиболее удобным местом для создания хэндла является OnInit ().

 

Пример работы с индикатором ZigZag

Код: ZigZag Example.mq5

Обратите внимание на алгоритм поиска экстремума: если значение в буфере индикатора не равно "0.0" и не равно "PLOT_EMPTY_VALUE" - это значит, что мы обнаружили экстремум.


Поиск экстремума происходит в барах " ZigZag: сколько свечей проверять назад ".


Алгоритм работы стандартный: ОДИН раз в OnInit () мы создаем индикатор.

//---
int   handle_iCustom;                  // variable for storing the handle of the iCustom indicator
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create handle of the indicator iCustom
   handle_iCustom=iCustom(Symbol(),Period(),"Examples\\ZigZag",InpDepth,InpDeviation,InptBackstep);
//--- if the handle is not created 
   if(handle_iCustom==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code 
      PrintFormat("Failed to create handle of the iCustom indicator for the symbol %s/%s, error code %d",
                  Symbol(),
                  EnumToString(Period()),
                  GetLastError());
      //--- the indicator is stopped early 
      return(INIT_FAILED);
     }
//---
   return(INIT_SUCCEEDED);
  }


Далее в OnTick () мы делаем копию данных индикатора, используя при этом хэндл индикатора.

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   static long counter=0;
   counter++;
   if(counter>=15)
      counter=0;
   else
      return;
//---
   double ZigzagBuffer[];
   ArraySetAsSeries(ZigzagBuffer,true);
   int start_pos=0,count=InpCandlesCheck+1;
   if(!iGetArray(handle_iCustom,0,start_pos,count,ZigzagBuffer))
      return;

   string text="";
   for(int i=0;i<count;i++)
     {
      if(ZigzagBuffer[i]!=PLOT_EMPTY_VALUE && ZigzagBuffer[i]!=0.0)
         text=text+"\n"+IntegerToString(i)+": "+DoubleToString(ZigzagBuffer[i],Digits());
     }
   Comment(text);
  }


Функция, с помощью которой копируются данные индикатора:

//+------------------------------------------------------------------+
//| Get value of buffers                                             |
//+------------------------------------------------------------------+
double iGetArray(const int handle,const int buffer,const int start_pos,const int count,double &arr_buffer[])
  {
   bool result=true;
   if(!ArrayIsDynamic(arr_buffer))
     {
      Print("This a no dynamic array!");
      return(false);
     }
   ArrayFree(arr_buffer);
//--- reset error code 
   ResetLastError();
//--- fill a part of the iBands array with values from the indicator buffer
   int copied=CopyBuffer(handle,buffer,start_pos,count,arr_buffer);
   if(copied!=count)
     {
      //--- if the copying fails, tell the error code 
      PrintFormat("Failed to copy data from the indicator, error code %d",GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated 
      return(false);
     }
   return(result);
  }


Результат работы:

Пример работы с индикатором ZigZag

Файлы:
 

Пример работы с графическим объектом OBJ_HLINE.

Советник OBJ_HLINE, следующий за ценой, имеет два параметра: Отступ вверх - отступ вверх от текущей цены и Отступ вниз - отступ вниз от верхней строки:

OBJ_HLINE следует за ценой

Анимация работы советника:

OBJ_HLINE следует за ценой

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

Я новичок в программировании mql и делаю код у меня есть только несколько проблем с которыми я столкнулся, программа для чтения тиков не запускается полностью. пожалуйста, помогите, если кто-то может исправить программу, которую я сделал.

спасибо.

void OnTick()
  {
      scanTicks();
         
  }
  
  
bool NewBar(void)
  {
   bool iNewBar=false;
   static double currPeriodProgress=0;

   double lastPeriodProgress=MathMod(TimeCurrent(),PeriodSeconds());

   if(lastPeriodProgress<currPeriodProgress) 
      iNewBar=true;
      currPeriodProgress=lastPeriodProgress;
   return(iNewBar);
  }
  
  
void scanTicks()
   {
            NewBar();
            
            double waktuSekarang;
            
            if(NewBar()==true)
            {
               waktuSekarang=MathMod(TimeCurrent(),PeriodSeconds());
            }
            
            
            MqlTick tick_array[]; 
            
            int copied=CopyTicks(_Symbol,tick_array,COPY_TICKS_ALL,0,1);
            // Latest loop
            for(int i=copied-1; i>=0;i--) 
            {
                MqlTick tick = tick_array[i]; 

                //debug
                Print("Bid : ", tick.bid, " Ask : ", tick.ask, " Array ", i);
            }
   }
Файлы:
 

Пример:

//+------------------------------------------------------------------+
//|                                                         Temp.mq5 |
//|                              Copyright © 2019, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2019, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Enum Copy Ticks Flags                                            |
//+------------------------------------------------------------------+
enum ENUM_COPY_TICKS_FLAGS
  {
   info=0,     // COPY_TICKS_INFO
   trade=1,    // COPY_TICKS_TRADE
   all=2,      // COPY_TICKS_ALL
  };
//--- input parameters
input ENUM_COPY_TICKS_FLAGS   InpFlags = trade; // The Copy Ticks Flags: 
input uint                    InpCount = 10;    // The number of ticks that you want to receive 
//---
datetime ExtPrevBars=0;        // "0" -> D'1970.01.01 00:00';
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- we work only at the time of the birth of new bar
   datetime time_0=iTime(Symbol(),Period(),0);
   if(time_0==ExtPrevBars)
      return;
   ExtPrevBars=time_0;
//---
   MqlTick tick_array[];   // Tick receiving array 
//--- Measuring start time before receiving the ticks 
   uint start=GetTickCount();
//--- Requesting the tick history since 1970.01.01 00:00.001 (parameter from=1 ms) 
   int received=CopyTicks(Symbol(),tick_array,InpFlags,(ulong)(TimeCurrent()+60),InpCount);
   if(received!=-1)
     {
      //--- Showing information about the number of ticks and spent time 
      PrintFormat("%s: received %d ticks in %d ms",Symbol(),received,GetTickCount()-start);
      //--- If the tick history is synchronized, the error code is equal to zero 
      if(GetLastError()==0)
        {
         int limit=(received>10)?10:received;
         for(int i=0;i<limit;i++)
            Print("Bid : ",tick_array[i].bid," Ask : ",tick_array[i].ask," Array ",i);
        }
      else
         PrintFormat("%s: Ticks are not synchronized yet, %d ticks received for %d ms. Error=%d",
                     _Symbol,received,GetTickCount()-start,_LastError);
     }
  }
//+------------------------------------------------------------------+

Результат:

2019.08.18 09:29:02.686 2019.03.11 02:00:00   EURUSD: received 9 ticks in 0 ms
2019.08.18 09:29:02.686 2019.03.11 02:00:00   Bid : 1.12343 Ask : 1.1236 Array 0
2019.08.18 09:29:02.686 2019.03.11 02:00:00   Bid : 1.12344 Ask : 1.12361 Array 1
2019.08.18 09:29:02.686 2019.03.11 02:00:00   Bid : 1.12342 Ask : 1.12359 Array 2
2019.08.18 09:29:02.686 2019.03.11 02:00:00   Bid : 1.12343 Ask : 1.1236 Array 3
2019.08.18 09:29:02.686 2019.03.11 02:00:00   Bid : 1.12341 Ask : 1.12358 Array 4
2019.08.18 09:29:02.686 2019.03.11 02:00:00   Bid : 1.12342 Ask : 1.12359 Array 5
2019.08.18 09:29:02.686 2019.03.11 02:00:00   Bid : 1.1234 Ask : 1.12357 Array 6
2019.08.18 09:29:02.686 2019.03.11 02:00:00   Bid : 1.12341 Ask : 1.12358 Array 7
2019.08.18 09:29:02.686 2019.03.11 02:00:00   Bid : 1.1234 Ask : 1.12357 Array 8
Файлы:
Temp.mq5  7 kb
 
Anggono Utomo:

Не публикуйте двойные сообщения!

Я удалил ваше дублирующее сообщение.

 
Keith Watford :

Не делайте двойных сообщений!

Я удалил ваше дублирующее сообщение.

Никто не делал двойного сообщения. Я сделал перенос сообщения из одной темы в другую: