Problem with changing a Position triggered by a Buy-Stop order

To add comments, please log in or register
MT5-softcase
20
MT5-softcase  
Hi,

I'm placing BUY_STOP and SELL_STOP orders.

E.g. SELL_STOP oder gets Position/Ticket # 11

When SELL_STOP order triggers, the Open Position has also the Position/Ticket # 11.

Now I want to change the the TAKE PROFIT value of this Position. To select the order to be changed, I use this command, which gives me the Position # 11 for the ticket:

// in this loop we're checking all opened positions
   for(i=0; i<PositionsTotal(); i++)
     {
      // processing orders with "our" symbols only
      if((Symbol()==PositionGetSymbol(i)) && (PositionGetInteger(POSITION_MAGIC) == MA_MAGIC))
        {
         ticket = PositionGetInteger(POSITION_IDENTIFIER);
         request.order= ticket;
But I always get the errror:
 failed modify #11 sell 0.10 EURUSD sl: 1.11574, tp: 0.00000 -> sl: 1.11572, tp: 1.11105 [Position doesn't exist]

From OrderCheck i get the following Errors (see Code below):

2019.11.23 21:55:13.571 2019.11.01 01:16:24   Error: ERR_TRADE_SEND_FAILED (4756): Trade request sending failed
2019.11.23 21:55:19.105 2019.11.01 01:16:24   Error: 10036: Position with the specified POSITION_IDENTIFIER has already been closed


In the Trading Tab the open Position shows the open position with ticket # 11.

I try to change the TP with this code:

if((PositionGetDouble(POSITION_SL)==0 || NormalizeDouble(PositionGetDouble(POSITION_SL)-StopLoss,_Digits)>0
                // if TakeProfit is not defined or lower than needed
                || PositionGetDouble(POSITION_TP)==0 || NormalizeDouble(atr_l[0]-PositionGetDouble(POSITION_TP),_Digits)>0)
               // is new StopLoss close to the current price?
               && NormalizeDouble(StopLoss-SymbolInfoDouble(Symbol(),SYMBOL_ASK)-StopLevel,_Digits)>0
               // is new TakeProfit close to the current price?
               && NormalizeDouble(SymbolInfoDouble(Symbol(),SYMBOL_ASK)-atr_l[0]-StopLevel,_Digits)>0)
              {
               // putting new value of StopLoss to the structure
               request.sl=NormalizeDouble(StopLoss,_Digits);
               // putting new value of TakeProfit to the structure
               request.tp=NormalizeDouble(atr_l[0],_Digits);
               // sending request to trade server
               if(OrderCheck(request,testresult))
                 {
                  Print("Error: ",ReturnCodeDescription(GetLastError()));
                  Print("Error: ",ReturnCodeDescription(testresult.retcode));
                 }
               else
                  OrderSend(request,result);
              }


In the Journal I can find following information:

2019.11.23 21:36:34.397 2019.11.01 01:16:24   order [#11 sell stop 0.10 EURUSD at 1.11511] triggered
2019.11.23 21:36:34.397 2019.11.01 01:16:24   deal #10 sell 0.10 EURUSD at 1.11511 done (based on order #11)
2019.11.23 21:36:34.397 2019.11.01 01:16:24   deal performed [#10 sell 0.10 EURUSD at 1.11511]
2019.11.23 21:36:34.397 2019.11.01 01:16:24   order performed sell 0.10 at 1.11511 [#11 sell stop 0.10 EURUSD at 1.11511]

Do I have to use the 'deal number' instead (and how to get them)?

Could you plese help me, how to change TP in an open position triggered by a Buy-Stop order?

Vladimir Karputov
Moderator
163202
Vladimir Karputov  

This is the first:

Ticket position is:

(ulong)PositionGetInteger(POSITION_TICKET)

but not:

PositionGetInteger(POSITION_IDENTIFIER);


Second: the position must be bypassed TO ZERO (sample code from all my advisers)

   for(int i=PositionsTotal()-1; i>=0; i--) // returns the number of open positions
      if(m_position.SelectByIndex(i))
         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==InpMagic)
MT5-softcase
20
MT5-softcase  
Vladimir Karputov:

This is the first:

Ticket position is:

but not:


Second: the position must be bypassed TO ZERO (sample code from all my advisers)

Thank you for your response.

I tried

(ulong)PositionGetInteger(POSITION_TICKET)

as well, but I got the same as with:

PositionGetInteger(POSITION_IDENTIFIER);

(I'll change it back :-) )

My OnTick() Functuion starts with:

void OnTick()
  {
   MqlTradeRequest request;
   MqlTradeResult result;
   MqlDateTime dt;
   ZeroMemory(request);
I use 'ZeroMemory', is that what you mean?
Vladimir Karputov
Moderator
163202
Vladimir Karputov  
MT5-softcase:
Hi,

I'm placing BUY_STOP and SELL_STOP orders.

E.g. SELL_STOP oder gets Position/Ticket # 11

When SELL_STOP order triggers, the Open Position has also the Position/Ticket # 11.

Basic Principles

Interrelation of orders, deals and positions

The platform allows you to easily track how a position was opened or how a deal was performed. Each trading operation has its unique ID called a "ticket". Each order and deal receive a ticket relating to their relevant position. Each deal receives a ticket of an order, by which it was concluded.

If a position was affected by multiple deals, for example in the case of a partial closing or increasing volumes, each of the deals feature the position's ticket. This makes it easy to track the entire history of the position as a whole.

If trading operations are sent to an exchange or a liquidity provider, they additionally feature an ID from an external system. This allows additional tracking of the interrelation of operations away from the platform.

The history of opening a position can be tracked by tickets

Basic Principles - Trading Operations - MetaTrader 5 Help
Basic Principles - Trading Operations - MetaTrader 5 Help
  • www.metatrader5.com
is an instruction given to a broker to buy or sell a financial instrument. There are two main types of orders: Market and Pending. In addition, there are special Take Profit and Stop Loss levels. is the commercial exchange (buying or selling) of a financial security. Buying is executed at the demand price (Ask), and Sell is performed at the...
Vladimir Karputov
Moderator
163202
Vladimir Karputov  

Add:

Position Properties

POSITION_TICKET

Position ticket. Unique number assigned to each newly opened position. It usually matches the ticket of an order used to open the position except when the ticket is changed as a result of service operations on the server, for example, when charging swaps with position re-opening. To find an order used to open a position, apply the POSITION_IDENTIFIER property.
 

POSITION_TICKET value corresponds to  MqlTradeRequest::position.

long

Documentation on MQL5: Constants, Enumerations and Structures / Trade Constants / Position Properties
Documentation on MQL5: Constants, Enumerations and Structures / Trade Constants / Position Properties
  • www.mql5.com
Position ticket. Unique number assigned to each newly opened position. It usually matches the ticket of an order used to open the position except when the ticket is changed as a result of service operations on the server, for example, when charging swaps with position re-opening. To find an order used to open a position, apply the...
Vladimir Karputov
Moderator
163202
Vladimir Karputov  

And now attention to what your algorithm should look like:

* First: you need to use trading classes - they are lighter and require fewer lines

#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
//---
CPositionInfo  m_position;                   // object of CPositionInfo class
CTrade         m_trade;                      // object of CTrade class
CSymbolInfo    m_symbol;                     // object of CSymbolInfo class

* You place a pending order (DO NOT REMEMBER A TICKET)

* In the adviser, simply write the correct trailing procedure (AGAIN: THERE IS NO SENSE TO USE A SAVED TICKET OF A PENDING ORDER)

//+------------------------------------------------------------------+
//| Trailing                                                         |
//|   InpTrailingStop: min distance from price to Stop Loss          |
//+------------------------------------------------------------------+
void Trailing(const double stop_level)
  {
   /*
      Buying is done at the Ask price                 |  Selling is done at the Bid price
      ------------------------------------------------|----------------------------------
      TakeProfit        >= Bid                        |  TakeProfit        <= Ask
      StopLoss          <= Bid                        |  StopLoss          >= Ask
      TakeProfit - Bid  >= SYMBOL_TRADE_STOPS_LEVEL   |  Ask - TakeProfit  >= SYMBOL_TRADE_STOPS_LEVEL
      Bid - StopLoss    >= SYMBOL_TRADE_STOPS_LEVEL   |  StopLoss - Ask    >= SYMBOL_TRADE_STOPS_LEVEL
   */
   if(InpTrailingStop==0)
      return;
   for(int i=PositionsTotal()-1; i>=0; i--) // returns the number of open positions
      if(m_position.SelectByIndex(i))
         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==InpMagic)
           {
            double price_current = m_position.PriceCurrent();
            double price_open    = m_position.PriceOpen();
            double stop_loss     = m_position.StopLoss();
            double take_profit   = m_position.TakeProfit();
            double ask           = m_symbol.Ask();
            double bid           = m_symbol.Bid();
            //---
            if(m_position.PositionType()==POSITION_TYPE_BUY)
              {
               if(price_current-price_open>m_trailing_stop+m_trailing_step)
                  if(stop_loss<price_current-(m_trailing_stop+m_trailing_step))
                     if(m_trailing_stop>=stop_level && (take_profit-bid>=stop_level || take_profit==0.0))
                       {
                        if(!m_trade.PositionModify(m_position.Ticket(),
                                                   m_symbol.NormalizePrice(price_current-m_trailing_stop),
                                                   take_profit))
                           if(InpPrintLog)
                              Print(__FILE__," ",__FUNCTION__,", ERROR: ","Modify BUY ",m_position.Ticket(),
                                    " Position -> false. Result Retcode: ",m_trade.ResultRetcode(),
                                    ", description of result: ",m_trade.ResultRetcodeDescription());
                        if(InpPrintLog)
                          {
                           RefreshRates();
                           m_position.SelectByIndex(i);
                           PrintResultModify(m_trade,m_symbol,m_position);
                          }
                        continue;
                       }
              }
            else
              {
               if(price_open-price_current>m_trailing_stop+m_trailing_step)
                  if((stop_loss>(price_current+(m_trailing_stop+m_trailing_step))) || (stop_loss==0))
                     if(m_trailing_stop>=stop_level && ask-take_profit>=stop_level)
                       {
                        if(!m_trade.PositionModify(m_position.Ticket(),
                                                   m_symbol.NormalizePrice(price_current+m_trailing_stop),
                                                   take_profit))
                           if(InpPrintLog)
                              Print(__FILE__," ",__FUNCTION__,", ERROR: ","Modify SELL ",m_position.Ticket(),
                                    " Position -> false. Result Retcode: ",m_trade.ResultRetcode(),
                                    ", description of result: ",m_trade.ResultRetcodeDescription());
                        if(InpPrintLog)
                          {
                           RefreshRates();
                           m_position.SelectByIndex(i);
                           PrintResultModify(m_trade,m_symbol,m_position);
                          }
                       }
              }
           }
  }


Later I will give the full advisor code ...

MT5-softcase
20
MT5-softcase  
Vladimir Karputov:

And now attention to what your algorithm should look like:

* First: you need to use trading classes - they are lighter and require fewer lines

* You place a pending order (DO NOT REMEMBER A TICKET)

* In the adviser, simply write the correct trailing procedure (AGAIN: THERE IS NO SENSE TO USE A SAVED TICKET OF A PENDING ORDER)


Later I will give the full advisor code ...

Thank you very much for your detailed answer. It gave me a clearer understanding of differences between Orders, Positions, Tickets and deals.

I also found the core issue of my problem. It is in the first code snippet:

I tried do select the trading position by assigning the ticket number to the 'order' instead of the 'position'.
Using 'request.order' is correct for changing parametes of a pending order. But as soon the pending order has triggered 'request.position' has to be used.


// in this loop we're checking all opened positions
   for(i=0; i<PositionsTotal(); i++)
     {
      // processing orders with "our" symbols only
      if((Symbol()==PositionGetSymbol(i)) && (PositionGetInteger(POSITION_MAGIC) == MA_MAGIC))
        {
         ticket = PositionGetInteger(POSITION_IDENTIFIER);
         request.order= ticket;                     //Wrong, because the pending order has already triggert and we are now hav to handl 'Positions'
         request.position= ticket;                  //correct
To add comments, please log in or register