how to detect if a transaction was actually a stop loss hit and that it had closed the position

 

folks,

how do i detect if a trade transaction was a stoploss hit and that it had closed the position? 

some code i tried :

void  OnTradeTransaction(
   const MqlTradeTransaction&    trans,     // trade transaction structure 
   const MqlTradeRequest&        request,   // request structure 
   const MqlTradeResult&         result     // response structure 
   )
{

if(trans.type == TRADE_TRANSACTION_DEAL_ADD)
      {
         ulong deal_ticket = trans.deal;
         long deal_entry = HistoryDealGetInteger(deal_ticket, DEAL_ENTRY);
         long deal_reason = HistoryDealGetInteger(deal_ticket, DEAL_REASON);
         Print("deal_entry: " + (string)deal_entry+ " deal_reason: "+ (string)deal_reason);
         if(deal_entry == DEAL_ENTRY_OUT && deal_reason == DEAL_REASON_SL)
         {
               Print("Position closed by hitting the stop loss. Deal Ticket: ", deal_ticket);
         }
      }

 }

        

both "deal_entry" and "deal_reason" are returning 0 in the strategy tester !


thx

 
chuckdavis:

folks,

how do i detect if a trade transaction was a stoploss hit and that it had closed the position? 

some code i tried :

both "deal_entry" and "deal_reason" are returning 0 in the strategy tester !


thx

Maybe you should use TRADE_TRANSACTION_HISTORY_ADD, instead?

 
Michael Charles Schefe #:

Maybe you should use TRADE_TRANSACTION_HISTORY_ADD, instead?

nah....

trans.type == TRADE_TRANSACTION_DEAL_ADD

fired correctly ....it's the stuff that comes after it that is not working ...namely the deal_entry and deal_reason...both returning 0s.
i am wondering if it has something to do with the strategy tester?

 

You have to select from history before you can access the properties ...

Forum on trading, automated trading systems and testing trading strategies

Error 4755 ERR_TRADE_DEAL_NOT_FOUND

Fernando Carreiro, 2024.12.19 02:20

You must first select the Deal History with HistoryDealSelect(). Take a close look at the example code in the documentation for OnTradeTransaction().

...

      case TRADE_TRANSACTION_DEAL_ADD:    // adding a trade
        {
         ulong          lastDealID   =trans.deal;
         ENUM_DEAL_TYPE lastDealType =trans.deal_type;
         double        lastDealVolume=trans.volume;
         //--- Trade ID in an external system - a ticket assigned by an exchange
         string Exchange_ticket="";
         if(HistoryDealSelect(lastDealID))
            Exchange_ticket=HistoryDealGetString(lastDealID,DEAL_EXTERNAL_ID);
         if(Exchange_ticket!="")
            Exchange_ticket=StringFormat("(Exchange deal=%s)",Exchange_ticket);
 
         PrintFormat("MqlTradeTransaction: %s deal #%I64u %s %s %.2f lot   %s",EnumToString(trans_type),
                     lastDealID,EnumToString(lastDealType),trans_symbol,lastDealVolume,Exchange_ticket);
        }

...
 
Fernando Carreiro #:

You have to select from history before you can access the properties ...

thanks ... i updated the code (below). this function is called from within OnTradeTransaction() and is used to count loosing trades for the current EA. Bear in mind there will be several EAs running on other charts.

gen.GetMagic() just returns the EA's magic number.

void Cmyclass::CountLosingTrades(const MqlTradeTransaction &trans, const MqlTradeRequest& request){

   if(request.magic != gen.GetMagic()){return;}
   // checkpoint 1

   if ((ENUM_TRADE_TRANSACTION_TYPE)trans.type == TRADE_TRANSACTION_DEAL_ADD)
   {
    // checkpoint 2
      if (HistoryDealSelect(trans.deal))
      {
         // checkpoint 3
         long deal_type = HistoryDealGetInteger(trans.deal, DEAL_ENTRY);
         if (deal_type == DEAL_ENTRY_OUT)
         {
            // checkpoint 4
            double deal_profit = HistoryDealGetDouble(trans.deal, DEAL_PROFIT);
            if (deal_profit < 0)
            {
                // checkpoint 5
               m_losingTradesCount++;               
               
            }
            
         }         
      }
   }
}

problem is ...during testing in the strategy tester...there are transactions where the code does not even reach checkpoint 1 because the request.magic is returning 0.

this is happening for trades that close by hitting the SL. 

given that i have multiple EAs running at the same time...how do i filter the transactions (SL hits) by the magic number ?

thx

 
chuckdavis #:

thanks…

I experienced a similar approach when creating a copy trader. Here’s the approach I followed:

Inside the OnTradeTransaction function,

  • printed all the members of the MqlTradeTransaction , MqlTradeRequest , and MqlTradeResult structs to a file (preferably in CSV format). Also use EnumToString to Convert an enumeration value of any type to a text form.

Then, attached the EA to a demo account and tested all possible scenarios.

Afterward, opened the file in Excel

  • to filter out duplicate values and identify the specific criteria I needed.

You can use this method to find yours as well.

 
MAHA #:

I experienced a similar approach when creating a copy trader. Here’s the approach I followed:

Inside the OnTradeTransaction function,

  • printed all the members of the MqlTradeTransaction , MqlTradeRequest , and MqlTradeResult structs to a file (preferably in CSV format). Also use EnumToString to Convert an enumeration value of any type to a text form.

Then, attached the EA to a demo account and tested all possible scenarios.

Afterward, opened the file in Excel

  • to filter out duplicate values and identify the specific criteria I needed.

You can use this method to find yours as well.

i did exactly that to develop the code above ....but i was surprised that when the SL gets hit ...the magic number is not reported in any of the  OnTradeTransaction structures.

which makes me wonder, how are we supposed to get the magic number for the recent transaction/deal resulting from a SL hit?

 
chuckdavis #:

i did exactly that to develop the code above ....but i was surprised that when the SL gets hit ...the magic number is not reported in any of the  OnTradeTransaction structures.

which makes me wonder, how are we supposed to get the magic number for the recent transaction/deal resulting from a SL hit?

I suspect that this is a broker-dealer issue.

Broker-dealers can overwrite or altogether delete historic deal comments and magic numbers following stoploss execution.

When a position hits the Stop Loss, why is the magic number removed in MT5? - Stop Loss - Expert Advisors and Automated Trading - MQL5 programming forum

When a position hits the Stop Loss, why is the magic number removed in MT5?
When a position hits the Stop Loss, why is the magic number removed in MT5?
  • 2024.12.23
  • Au Phuong Tan
  • www.mql5.com
Hello everyone! I'm using MT5 and facing an issue where, when a position with a set Stop Loss is closed, the magic number gets removed...
 
chuckdavis #:

i did …

How about writing trade details to a file in this format:

  • TRADE_POSITION_TICKET:EA_MAGIC_NUMBER

When the stop-loss is triggered, retrieve the TRADE_POSITION_TICKET. Once the ticket is found, extract the corresponding EA_MAGIC_NUMBER.
 
MAHA #:

How about writing trade details to a file in this format:

  • TRADE_POSITION_TICKET:EA_MAGIC_NUMBER

When the stop-loss is triggered, retrieve the TRADE_POSITION_TICKET. Once the ticket is found, extract the corresponding EA_MAGIC_NUMBER.

thanks ....will look into it

Ryan L Johnson #:

I suspect that this is a broker-dealer issue.

Broker-dealers can overwrite or altogether delete historic deal comments and magic numbers following stoploss execution.

When a position hits the Stop Loss, why is the magic number removed in MT5? - Stop Loss - Expert Advisors and Automated Trading - MQL5 programming forum

if i may add...this is happening in strategy tester....not sure if live will be the same.

 
chuckdavis #:

thanks ....will look into it

if i may add...this is happening in strategy tester....not sure if live will be the same.

Good point.

As a universal workaround, you could set a series of GlobalVariables (GV's) following your stoploss executions; setting the GV name (a string) to your symbol, timeframe, and/or whatever, and the GV value (a double) to the magic number. In this way, you'd have a readymade list to read in the terminal. Then you can get their values in a loop somewhat like it's an array.