How to start with MQL5 - page 12

 

Example: tracking the triggering of Stop Loss or Take Profit

Code: 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");
     }
  }
//+------------------------------------------------------------------+


Algorithm of actions: we catch the transaction 'TRADE_TRANSACTION_DEAL_ADD' (adding a deal to history). Next, we check the property of the deal from the ENUM_DEAL_REASON (The reason or source for deal execution) enumeration - if it is 'DEAL_REASON_SL' or 'DEAL_REASON_TP', we send a signal.

Files:
 

Example: a simple Expert Advisor at the intersection of two iMA (Moving Average, MA) indicators.

Code: Simple Two iMA Crossing.mq5

ATTENTION: To get indicator data in an MQL5 Expert Advisor, you must adhere to the following rules:

  1. The indicator handle is created in OnInit
  2. Then (as a rule, in OnTick), the indicator data is received using CopyBuffer

Creating indicator handles in 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);
  }


So, the EA will look for a signal only at the moment of a new bar birth. The code responsible for finding a new bar:

//+------------------------------------------------------------------+
//| 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;
***
  }


If a new bar is found, look for a signal: compare the values of the two iMA indicators ('Fast' and 'Slow') on bar # 2 and on bar # 1. Please note that the current bar - bar # 0 is not used. When a signal is received to open a BUY position, we issue an order to close SELL positions and vice versa: when a signal is received to open a SELL position, we issue an order to close a 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[]...
 

Example: if the Moving Average indicator dropped below the Close price, close the BUY positions, if the Moving Average indicator rose above the Close price, close the SELL positions.

Code: Simple iMA Above Below Close.mq5

An example of creating an indicator is described in detail above (), and here I will dwell in more detail on receiving a signal and not implementing a signal.

So, at the moment of the birth of a new bar

//--- 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;
//---


check if it is necessary to close positions (compare the Moving Average indicator value on bar #1 and the Close price of bar #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;
     }


In OnTick (that is, at each tick) we check the ' m_need_close_buys ' and ' m_need_close_sells ' flags - and, if necessary, close the positions of the selected direction.

//+------------------------------------------------------------------+
//| 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...
 

We catch the transaction

Code: We catch the transaction.mq5

We catch the transaction


This is a blank - an example of how to control a trading signal. This code avoids the situation: opening multiple positions. How it works: after a trade order is generated, we increase the 'SPosition' structure. In OnTick, if 'SPosition' is greater than zero, go to the block for opening positions. In OnTradeTransaction, we monitor the situation when a position appears exactly on our signal.

 

Example: find the most losing position and the most profitable position

Сode: Search Max Loss and Max Profit.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);
  }
//+------------------------------------------------------------------+
 

Example: catching a Take Profit trigger

The code: Last Deal Take Profit activation.mq5


An example of online work (via OnTradeTransaction).

  • We catch the transaction 'TRADE_TRANSACTION_DEAL_ADD' (adding a deal to history)
  • We are trying to find the deal (which generated this transaction) in the trading history
  • If the deal type is BUY or SELL ('DEAL_TYPE_BUY' || 'DEAL_TYPE_SELL')
  • If this trade is a market exit trade ('DEAL_ENTRY_OUT')
  • If this deal occurred as a result of Take Profit ('DEAL_REASON_TP')
  • We get in the trade history all deals belonging to the position and print out a little information on each deal
//+------------------------------------------------------------------+
//|                             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));
                       }
                    }
                 }
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+


 

Receiving data from an indicator in an MQL5.

Scheme:

Getting data from indicators in an MQL5 Expert Advisor

An example for the iMA indicator:

Forum on trading, automated trading systems and testing trading strategies

How to start with MQL5

Vladimir Karputov, 2020.03.08 09:04

Creating an iMA indicator handle, getting indicator values

(code: iMA Values on a Chart)

The main rule: the indicator handle needs to be received once (it is optimal to do this in the OnInit function).

Input parameters and the variable in which the indicator handle is stored:

//+------------------------------------------------------------------+
//|                                        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                                   |


Creating a handle (checking the result)

//+------------------------------------------------------------------+
//| 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);
  }


Getting values (I use the iGetArray generic function). Please note: for the array "array_ma" I use "ArraySetAsSeries" - in this case, in the “array_ma” array, the element with the index “0” corresponds to the rightmost bar on the chart (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);
  }


The result of work:


Pic. 1. Get value on bar #0, #1, #2

 
Hey, new here. Im unsure if it was mentioned before but im trying to figure out how to open a position on the NEW Candle open price. is this possible? 
 
Patrine Peniston :
Hey, new here. Im unsure if it was mentioned before but im trying to figure out how to open a position on the NEW Candle open price . is this possible? 

No, this is impossible: since the candle has opened and this event is IN THE PAST :)

But the problem can be formulated differently: how to catch the moment of the birth of a new bar and open a position at that moment. Will this formulation of the question suit you?

 

Example: at the moment of the birth of a new bar, a position of 1.0 lot is opened

The code: Open a position on a new bar.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);
  }
//+------------------------------------------------------------------+
Reason: