How to detect if stop loss is hit

I’ve read this post. But I am still not clear.

Here is my log when stop loss is executed in strategy tester.

Now I have a position.

It looks like OnTradeTransaction() is triggered 3 times.

The MqlTradeTransaction is: TRADE_TRANSACTION_HISTORY_ADD

The MqlTradeTransaction is: TRADE_TRANSACTION_ORDER_DELETE

The MqlTradeTransaction is: TRADE_TRANSACTION_DEAL_ADD

position is closed.

There is no transaction type called “stop_loss_executed”. The right way to detect stop loss transaction is to do what?

My idea is if a position is closed, then it can be result from a stop loss on a position, or user manually send an order. There is no way to tell the difference. Is this correct?

If I am wrong, please tell me how to detect a stop loss event.

Here is my log for that minute when stop loss event is triggered.

Thanks!

Files:

onTradeTransaction.txt 10 KB

You know your posittion (symbol, buy or sell), your volume, your sl price : EURUSD BUY 1.0 sl:1.27526

So if you detect a opposite deal, with the same volume and your sl price, it means stoploss has been triggered.

LO 0 22:11:32.125 A1 (EURUSD,M1) 2014.09.26 03:00:39 The MqlTradeTransaction is: TRADE_TRANSACTION_DEAL_ADD PM 0 22:11:32.125 A1 (EURUSD,M1) 2014.09.26 03:00:39 Symbol: EURUSD GG 0 22:11:32.125 A1 (EURUSD,M1) 2014.09.26 03:00:39 Deal ticket: 5 IQ 0 22:11:32.125 A1 (EURUSD,M1) 2014.09.26 03:00:39 Deal type: DEAL_TYPE_SELL LD 0 22:11:32.125 A1 (EURUSD,M1) 2014.09.26 03:00:39 Order ticket: 5 IS 0 22:11:32.125 A1 (EURUSD,M1) 2014.09.26 03:00:39 Order type: ORDER_TYPE_BUY NL 0 22:11:32.125 A1 (EURUSD,M1) 2014.09.26 03:00:39 Order state: ORDER_STATE_STARTED HI 0 22:11:32.125 A1 (EURUSD,M1) 2014.09.26 03:00:39 Order time type: ORDER_TIME_GTC FQ 0 22:11:32.125 A1 (EURUSD,M1) 2014.09.26 03:00:39 Order expiration: 1970.01.01 00:00 CR 0 22:11:32.125 A1 (EURUSD,M1) 2014.09.26 03:00:39 Price: 1.27526 HJ 0 22:11:32.125 A1 (EURUSD,M1) 2014.09.26 03:00:39 Price trigger: 0 KL 0 22:11:32.125 A1 (EURUSD,M1) 2014.09.26 03:00:39 Stop Loss: 0 HE 0 22:11:32.125 A1 (EURUSD,M1) 2014.09.26 03:00:39 Take Profit: 0 QL 0 22:11:32.125 A1 (EURUSD,M1) 2014.09.26 03:00:39 Volume: 1

Got it… Thanks!

enum postype {BUY,SELL,NONE};
static int prevposition=NONE;

void  OnTradeTransaction( 
   const MqlTradeTransaction&    trans,        // estrutura das transações de negócios 
   const MqlTradeRequest&        request,      // estrutura solicitada 
   const MqlTradeResult&         results        // resultado da estrutura 
   )
{  
   HistorySelect(TimeCurrent()-3600,TimeCurrent());
   if(trans.type==TRADE_TRANSACTION_DEAL_ADD && trans.deal_type==DEAL_TYPE_SELL 
   && PositionsTotal()==0 && prevposition==BUY)
   {  
      if(HistoryDealGetInteger(trans.deal,DEAL_REASON)==DEAL_REASON_TP){
      Print("BUY + DEAL_REASON_TP");
      prevposition=NONE;}
      if(HistoryDealGetInteger(trans.deal,DEAL_REASON)==DEAL_REASON_SL){
      Print("BUY + DEAL_REASON_SL")
      prevposition=NONE;}
   }
   
   if(trans.type==TRADE_TRANSACTION_DEAL_ADD && trans.deal_type==DEAL_TYPE_BUY 
   && PositionsTotal()==0 && prevposition==SELL)
   {
      if(HistoryDealGetInteger(trans.deal,DEAL_REASON)==DEAL_REASON_TP){
      Print("SELL + DEAL_REASON_TP");
      prevposition=NONE;}
      if(HistoryDealGetInteger(trans.deal,DEAL_REASON)==DEAL_REASON_SL){
      Print("SELL + DEAL_REASON_SL");
      prevposition=NONE;}
   }
   
}

This code works for me!!! Note I assign BUY/SELL to prevposition when I send the order and get confirmation.

Isn’t that a bit risky: “You know your position (symbol, buy or sell), your volume, your sl price : EURUSD BUY 1.0 sl:1.27526” ??

Why don’t you use the Order-Ticket to identify the opposite deal? Is it changed or different compared to the original order?

For centuries we have learned to use the ticket number to identify the positions, open and closed?

#include <MT4Orders.mqh>      // https://www.mql5.com/en/code/16006

void OnTrade()
{
  static int PrevTotal = OrdersHistoryTotal();
  const int Total = OrdersHistoryTotal();
  
  for (int i = Total - 1; i >= PrevTotal; i--)
    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) && (OrderCloseReason() == DEAL_REASON_SL))
      Alert("Stop!");
    
  PrevTotal = Total;
}

Alternative

void OnTradeTransaction( const MqlTradeTransaction &Trans, const MqlTradeRequest&, const MqlTradeResult& )
{
  if (HistoryDealSelect(Trans.deal) && (HistoryDealGetInteger(Trans.deal, DEAL_REASON) == DEAL_REASON_SL))
    Alert("Stop2!");
}