Как начать работу с MQL5 - страница 12

 

Пример: отслеживание срабатывания стоп-лосса или тейк-профита

Код: SL TP Triggered.mq5

//+------------------------------------------------------------------+
//|                                              SL TP Triggered.mq5 |
//|                              Copyright © 2020, Vladimir Karputov |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2020, Vladimir Karputov"
#property version   "1.001"
/*
   barabashkakvn Trading engine 3.137
*/
#include <Trade\DealInfo.mqh>
//---
CDealInfo      m_deal;                       // object of CDealInfo class
//--- input parameters
//---
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
  }
//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result)
  {
//--- get transaction type as enumeration value
   ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
//--- if transaction is result of addition of the transaction in history
   if(type==TRADE_TRANSACTION_DEAL_ADD)
     {
      if(HistoryDealSelect(trans.deal))
         m_deal.Ticket(trans.deal);
      else
        {
         Print(__FILE__," ",__FUNCTION__,", ERROR: HistoryDealSelect(",trans.deal,")");
         return;
        }
      //---
      long reason=-1;
      if(!m_deal.InfoInteger(DEAL_REASON,reason))
        {
         Print(__FILE__," ",__FUNCTION__,", ERROR: InfoInteger(DEAL_REASON,reason)");
         return;
        }
      if((ENUM_DEAL_REASON)reason==DEAL_REASON_SL)
         Alert("Stop Loss activation");
      else
         if((ENUM_DEAL_REASON)reason==DEAL_REASON_TP)
            Alert("Take Profit activation");
     }
  }
//+------------------------------------------------------------------+


Алгоритм действий: ловим транзакцию'TRADE_TRANSACTION_DEAL_ADD' (добавление сделки в историю). Далее проверяем свойство сделки из перечисления ENUM_DEAL_REASON (Причина или источник исполнения сделки) - если это 'DEAL_REASON_SL' или 'DEAL_REASON_TP', то отправляем сигнал.

Файлы:
 

Пример: простой советник на пересечении двух индикаторов iMA (Moving Average, MA).

Код: Simple Two iMA Crossing.mq5

ВНИМАНИЕ: Чтобы получить данные индикатора в MQL5-эксперте, необходимо придерживаться следующих правил:

  1. Хендл индикатора создается в OnInit
  2. Затем (как правило, в OnTick) данные индикатора получаются с помощью CopyBuffer

Создание хэндлов индикаторов в OnInit

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   ResetLastError();
   if(!m_symbol.Name(Symbol())) // sets symbol name
     {
      Print(__FILE__," ",__FUNCTION__,", ERROR: CSymbolInfo.Name");
      return(INIT_FAILED);
     }
   RefreshRates();
//---
   m_trade.SetExpertMagicNumber(InpMagic);
   m_trade.SetMarginMode();
   m_trade.SetTypeFillingBySymbol(m_symbol.Name());
   m_trade.SetDeviationInPoints(InpDeviation);
//--- create handle of the indicator iMA
   handle_iMA_Fast=iMA(m_symbol.Name(),Period(),Inp_MA_Fast_ma_period,Inp_MA_Fast_ma_shift,
                       Inp_MA_Fast_ma_method,Inp_MA_Fast_applied_price);
//--- if the handle is not created
   if(handle_iMA_Fast==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code
      PrintFormat("Failed to create handle of the iMA ('Fast') indicator for the symbol %s/%s, error code %d",
                  m_symbol.Name(),
                  EnumToString(Period()),
                  GetLastError());
      //--- the indicator is stopped early
      return(INIT_FAILED);
     }
//--- create handle of the indicator iMA
   handle_iMA_Slow=iMA(m_symbol.Name(),Period(),Inp_MA_Slow_ma_period,Inp_MA_Slow_ma_shift,
                       Inp_MA_Slow_ma_method,Inp_MA_Slow_applied_price);
//--- if the handle is not created
   if(handle_iMA_Slow==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code
      PrintFormat("Failed to create handle of the iMA ('Slow') 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 tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
***
//--- we work only at the time of the birth of new bar
   datetime time_0=iTime(m_symbol.Name(),Period(),0);
   if(time_0==m_prev_bars)
      return;
   m_prev_bars=time_0;
***
  }


Если новый бар найден, ищем сигнал: сравниваем значения двух индикаторов iMA ('Fast' и 'Slow') на баре № 2 и на баре № 1. Обратите внимание, что текущий бар - бар № 0 - не используется. Когда поступает сигнал на открытие позиции BUY, мы выставляем ордер на закрытие позиций SELL, и наоборот: когда поступает сигнал на открытие позиции SELL, мы выставляем ордер на закрытие BUY.

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
***
//---
   double fast[],slow[];
   ArraySetAsSeries(fast,true);
   ArraySetAsSeries(slow,true);
   int start_pos=0,count=6;
   if(!iGetArray(handle_iMA_Fast,0,start_pos,count,fast) || !iGetArray(handle_iMA_Slow,0,start_pos,count,slow))
     {
      m_prev_bars=0;
      return;
     }
//--- check signal close SELL and open BUY
   if(fast[1]>slow[1]&&fast[2]<slow[2])
     {
      m_need_close_sells=true;
      m_need_open_buy=true;
      return;
     }
//--- check signal close BUY and open SELL
   if(fast[1]<slow[1]&&fast[2]>slow[2])
     {
      m_need_close_buys=true;
      m_need_open_sell=true;
      return;
     }
  }
Documentation on MQL5: Timeseries and Indicators Access / CopyBuffer
Documentation on MQL5: Timeseries and Indicators Access / CopyBuffer
  • www.mql5.com
Counting of elements of copied data (indicator buffer with the index buffer_num) from the starting position is performed from the present to the past, i.e., starting position of 0 means the current bar (indicator value for the current bar). When copying the yet unknown amount of data, it is recommended to use a dynamic array as a buffer[]...
Файлы:
 

Пример: если индикатор Moving Average опустился ниже цены закрытия, закройте позиции BUY, если индикатор Moving Average поднялся выше цены закрытия, закройте позиции SELL.

Код: Simple iMA Above Below Close.mq5

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

Итак, в момент рождения нового бара

//--- we work only at the time of the birth of new bar
   datetime time_0=iTime(m_symbol.Name(),Period(),0);
   if(time_0==m_prev_bars)
      return;
   m_prev_bars=time_0;
//---


проверяем необходимость закрытия позиций (сравниваем значение индикатора Moving Average на баре №1 и цену закрытия бара №1)

//--- check signal close BUY 
   if(ma[1]<rates[1].close)
     {
      m_need_close_buys=true;
      return;
     }
//--- check signal close SELL
     if(ma[1]>rates[1].close)
     {
      m_need_close_sells=true;
      return;
     }


В OnTick (то есть на каждом тике) проверяем флаги ' m_need_close_buys ' и ' m_need_close_sells ' - и, если необходимо, закрываем позиции выбранного направления.

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- need close BUY positions OR SELL positions
   if(m_need_close_buys || m_need_close_sells)
     {
      int count_buys    = 0;
      int count_sells   = 0;
      CalculateAllPositions(count_buys,count_sells);
      //---
      if(m_need_close_buys)
        {
         if(count_buys>0)
           {
            ClosePositions(POSITION_TYPE_BUY);
            return;
           }
         else
            m_need_close_buys=false;
        }
      //---
      if(m_need_close_sells)
        {
         if(count_sells>0)
           {
            ClosePositions(POSITION_TYPE_SELL);
            return;
           }
         else
            m_need_close_sells=false;
        }
     }
How to start with MQL5
How to start with MQL5
  • 2020.09.17
  • www.mql5.com
This thread discusses MQL5 code examples. There will be examples of how to get data from indicators, how to program advisors...
Файлы:
 

Мы ловим транзакцию

Код: Мы ловим сделку.mq5

Мы поймали транзакцию


Это заготовка - пример того, как управлять торговым сигналом. Этот код позволяет избежать ситуации: открытия нескольких позиций. Как это работает: после генерации торгового ордера мы увеличиваем структуру 'SPosition'. В OnTick, если 'SPosition' больше нуля, переходим к блоку открытия позиций. В OnTradeTransaction отслеживаем ситуацию, когда позиция появляется точно по нашему сигналу.

Файлы:
 

Пример: найти самую убыточную позицию и самую прибыльную позицию

Код: Поиск максимального убытка и максимальной прибыли.mq5

//+------------------------------------------------------------------+
//|                               Search Max Loss and Max Profit.mq5 |
//|                              Copyright © 2020, Vladimir Karputov |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2020, Vladimir Karputov"
#property version   "1.000"
/*
   barabashkakvn Trading engine 3.143
*/
#include <Trade\PositionInfo.mqh>
//---
CPositionInfo  m_position;                   // object of CPositionInfo class
//--- input parameters
input int      Input1=9;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   double d_max_loss    = 0.0;
   string s_max_loss    = "";
   double d_max_profit  = 0.0;
   string s_max_profit  = "";
   for(int i=PositionsTotal()-1; i>=0; i--)
      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
        {
         double profit=m_position.Commission()+m_position.Swap()+m_position.Profit();
         if(profit>0.0 && profit>d_max_profit)
           {
            d_max_profit=profit;
            s_max_profit=m_position.Symbol()+" | "+IntegerToString(m_position.Ticket())+" | "+DoubleToString(profit,2);
            continue;
           }
         if(profit<0.0 && profit<d_max_loss)
           {
            d_max_loss=profit;
            s_max_loss=m_position.Symbol()+" | "+IntegerToString(m_position.Ticket())+" | "+DoubleToString(profit,2);
           }
        }
   Comment("Max Loss: "+s_max_loss+"\n"+
           "Max Profit: "+s_max_profit);
  }
//+------------------------------------------------------------------+
 

Пример: ловля триггера тейк-профита

Код: Last Deal Take Profit activation.mq5


Пример работы в режиме онлайн (через OnTradeTransaction).

  • Мы ловим транзакцию 'TRADE_TRANSACTION_DEAL_ADD' (добавление сделки в историю).
  • Мы пытаемся найти сделку (которая породила эту транзакцию) в истории торговли
  • Если тип сделки - BUY или SELL ('DEAL_TYPE_BUY' || 'DEAL_TYPE_SELL')
  • Если эта сделка является сделкой выхода с рынка ('DEAL_ENTRY_OUT')
  • Если эта сделка произошла в результате тейк-профита ('DEAL_REASON_TP')
  • Мы получаем в истории торговли все сделки, относящиеся к данной позиции, и выводим небольшую информацию по каждой сделке
//+------------------------------------------------------------------+
//|                             Last Deal Take Profit activation.mq5 |
//|                              Copyright © 2020, Vladimir Karputov |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2020, Vladimir Karputov"
/*
   barabashkakvn Trading engine 3.143
*/
#include <Trade\DealInfo.mqh>
//---
CDealInfo      m_deal;                       // object of CDealInfo class
//--- input parameters
input int      Input1=9;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
  }
//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
//--- get transaction type as enumeration value
   ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
//--- if transaction is result of addition of the transaction in history
   if(type==TRADE_TRANSACTION_DEAL_ADD)
     {
      ResetLastError();
      if(HistoryDealSelect(trans.deal))
         m_deal.Ticket(trans.deal);
      else
        {
         Print(__FILE__," ",__FUNCTION__,", ERROR: ","HistoryDealSelect(",trans.deal,") error: ",GetLastError());
         return;
        }
      if(m_deal.DealType()==DEAL_TYPE_BUY || m_deal.DealType()==DEAL_TYPE_SELL)
        {
         if(m_deal.Entry()==DEAL_ENTRY_OUT)
           {
            long deal_reason=-1;
            if(m_deal.InfoInteger(DEAL_REASON,deal_reason)==DEAL_REASON_TP)
              {
               long position_id=m_deal.PositionId();
               if(HistorySelectByPosition(position_id))
                 {
                  uint     total = HistoryDealsTotal();
                  ulong    ticket= 0;
                  //--- for all deals
                  for(uint i=0; i<total; i++)
                    {
                     //--- try to get deals ticket
                     if((ticket=HistoryDealGetTicket(i))>0)
                       {
                        //--- get deals properties
                        long     lng_time=HistoryDealGetInteger(ticket,DEAL_TIME);
                        datetime dat_time=(datetime)lng_time;
                        long     entry    = HistoryDealGetInteger(ticket,DEAL_ENTRY);
                        //long     type     = HistoryDealGetInteger(ticket,DEAL_TYPE);
                        double   volume   =HistoryDealGetDouble(ticket,DEAL_VOLUME);
                        double   price    = HistoryDealGetDouble(ticket,DEAL_PRICE);
                        Print(dat_time,", ",DoubleToString(price,8));
                       }
                    }
                 }
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+


 

Получение данных от индикатора в MQL5.

Схема:

Получение данных из индикаторов в эксперте MQL5

Пример для индикатора iMA:

функции OnInit).

Входные параметры и переменная, в которой хранится хэндл индикатора:

//+------------------------------------------------------------------+
//|                                        iMA Values on a Chart.mq5 |
//|                              Copyright © 2019, Vladimir Karputov |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2019, Vladimir Karputov"
#property version   "1.00"
//--- input parameters
input int                  Inp_MA_ma_period     = 12;          // MA: averaging period
input int                  Inp_MA_ma_shift      = 5;           // MA: horizontal shift
input ENUM_MA_METHOD       Inp_MA_ma_method     = MODE_SMA;    // MA: smoothing type
input ENUM_APPLIED_PRICE   Inp_MA_applied_price = PRICE_CLOSE; // MA: type of price
//---
int    handle_iMA;                           // variable for storing the handle of the iMA indicator
//+------------------------------------------------------------------+
//| Expert initialization function                                   |


Создание хэндла(проверка результата)

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create handle of the indicator iMA
   handle_iMA=iMA(Symbol(),Period(),Inp_MA_ma_period,Inp_MA_ma_shift,
                  Inp_MA_ma_method,Inp_MA_applied_price);
//--- if the handle is not created
   if(handle_iMA==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code
      PrintFormat("Failed to create handle of the iMA indicator for the symbol %s/%s, error code %d",
                  Symbol(),
                  EnumToString(Period()),
                  GetLastError());
      //--- the indicator is stopped early
      return(INIT_FAILED);
     }
//---
   return(INIT_SUCCEEDED);
  }


Получение значений (я использую общую функцию iGetArray). Обратите внимание: для массива"array_ma" я использую"ArraySetAsSeries" - в этом случае в массиве "array_ma" элемент с индексом "0" соответствует самому правому бару на графике (bar # 0)

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   double array_ma[];
   ArraySetAsSeries(array_ma,true);
   int start_pos=0,count=3;
   if(!iGetArray(handle_iMA,0,start_pos,count,array_ma))
      return;

   string text="";
   for(int i=0; i<count; i++)
      text=text+IntegerToString(i)+": "+DoubleToString(array_ma[i],Digits()+1)+"\n";
//---
   Comment(text);
  }


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


Рис. 1. Получение значений на барах #0, #1, #2

Файлы:
 
Привет, я здесь новичок. Не знаю, упоминалось ли это раньше, но я пытаюсь понять, как открыть позицию по цене открытия НОВОЙ свечи. возможно ли это?
 
Patrine Peniston :
Привет, я здесь новичок. Не знаю, упоминалось ли это раньше, но я пытаюсь понять, как открыть позицию по цене открытия НОВОЙ свечи. возможно ли это?

Нет, это невозможно: так как свеча уже открылась и это событие В ПРОШЛОМ :)

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

 

Пример: в момент рождения нового бара открывается позиция размером 1,0 лот

Код: Открыть позицию на новом баре.mq5

//+------------------------------------------------------------------+
//|                                 Open a position on a new bar.mq5 |
//|                              Copyright © 2020, Vladimir Karputov |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2020, Vladimir Karputov"
#property version   "1.000"
/*
   barabashkakvn Trading engine 3.143
*/
#include <Trade\Trade.mqh>
//---
CTrade         m_trade;                      // object of CTrade class
//--- input parameters
input ENUM_POSITION_TYPE   InpPosType  = POSITION_TYPE_BUY; // Position type
//---
datetime m_prev_bars                   = 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==m_prev_bars)
      return;
   m_prev_bars=time_0;
//---
   if(InpPosType==POSITION_TYPE_BUY)
      m_trade.Buy(1.0);
   else
      m_trade.Sell(1.0);
  }
//+------------------------------------------------------------------+
Причина обращения: