MetaEditor build 1490 - page 3

 
fxsaber:
There is no way to define it. SL and TP are solely the essence of the MT server.
The most reliable way (unless the broker changes the comment format, which is an unlikely event).
 

That's how it works:

void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
   if(trans.type==TRADE_TRANSACTION_DEAL_ADD)
     {
      datetime end=TimeCurrent();
      datetime start=end-end%PeriodSeconds(PERIOD_D1);
      ResetLastError();
      if(!HistorySelect(start,end))
        {
         Print("Getting deals history failed. Error ",GetLastError());
         return;
        }
      ulong ticket=HistoryDealGetTicket(HistoryDealsTotal()-1);
      if(ticket==trans.deal)
        {
         if(HistoryDealGetInteger(ticket,DEAL_ENTRY)==DEAL_ENTRY_OUT &&
            (StringFind(HistoryDealGetString(ticket,DEAL_COMMENT),"tp")!=-1
            || StringFind(HistoryDealGetString(ticket,DEAL_COMMENT),"sl")!=-1))
           {
            Print(HistoryDealGetString(ticket,DEAL_SYMBOL),"  Profit= ",HistoryDealGetDouble(ticket,DEAL_PROFIT),"  ticket=",ticket);
           }
        }
     }
  }
 
Working option for real life (not for the tester)
void OnTradeTransaction ( const MqlTradeTransaction &Trans, const MqlTradeRequest &Request, const MqlTradeResult &Result )
{
  if ((Trans.type == TRADE_TRANSACTION_ORDER_ADD) &&
       PositionSelectByTicket(Trans.position) && OrderSelect(Trans.order) &&
       (PositionGetInteger(POSITION_TYPE) == 1 - OrderGetInteger(ORDER_TYPE)))
  {
    const double Price = OrderGetDouble(ORDER_PRICE_OPEN);
    
    if (Price == PositionGetDouble(POSITION_TP))
      Print("Position #" + (string)Trans.position + " - triggered TP.");    
    else if (Price == PositionGetDouble(POSITION_SL))
      Print("Position #" + (string)Trans.position + " - triggered SL.");    
  }
}
 
fxsaber:
Working variant for real (not for tester)
void OnTradeTransaction ( const MqlTradeTransaction &Trans, const MqlTradeRequest &Request, const MqlTradeResult &Result )
{
  if ((Trans.type == TRADE_TRANSACTION_ORDER_ADD) &&
       PositionSelectByTicket(Trans.position) && OrderSelect(Trans.order) &&
       (PositionGetInteger(POSITION_TYPE) == 1 - OrderGetInteger(ORDER_TYPE)))
  {
    const double Price = OrderGetDouble(ORDER_PRICE_OPEN);
    
    if (Price == PositionGetDouble(POSITION_TP))
      Print("Position #" + (string)Trans.position + " - triggered TP.");    
    else if (Price == PositionGetDouble(POSITION_SL))
      Print("Position #" + (string)Trans.position + " - triggered SL.");    
  }
}
I checked in the tester - it does not work, I think it will not work for real as well, because the position for which it is checked does not exist anymore.
 
Andrey Dik:
I checked in the tester - it does not work, and I think it will not work on the real, because the position for which the test is going already does not exist.
This is an artificial error in the tester (so as not to slow it down at all). Just by logic, everything is correct.
 
void OnTick ()
{
  string s = DoubleToString(PosTotalCommissSwap (Symbol (), true, true), 4);
  
  Comment (s);
}
//+------------------------------------------------------------------+


// Подсчет комиссий и свопов указанной позиции по символу
double PosTotalCommissSwap (string symb, bool commiss, bool swap)
{
  int posTotal = PositionsTotal (); //всего открытых позиций
  Print (posTotal);
  
  //пройдем по всем открытым позициям
  for(int i = posTotal - 1; i >=0; i--)
  {
    string posSymb = PositionGetSymbol (i);
    Print (posSymb);
    
    //если найдена позиция по указанному символу
    if(symb == posSymb)
    {
      Print ("Позиция найдена");
      long posID  = PositionGetInteger (POSITION_IDENTIFIER);
      
      //выберем историю сделок, относящуюся к выбранной позиции
      if(HistorySelectByPosition (posID))
      {
        int dealsTotal = HistoryDealsTotal ();  //всего сделок в истории позиции
        Print ("Всего сделок в позиции: " + dealsTotal);
        double fees = 0.0; //все комиссии и свопы
        
        //пройдем по всем сделкам позиции
        for(int k = 0; k < dealsTotal; k++)
        {
          ulong dealTicket = HistoryDealGetTicket (k); //тикет сделки
          
          if(commiss)
            fees += HistoryDealGetDouble (dealTicket, DEAL_COMMISSION);
            
          if(swap)
            fees += HistoryDealGetDouble (dealTicket, DEAL_SWAP);
        }
        
        return (fees);
      }
      else
        Print ("Историю сделок выбрать не удалось");
    }
  }
  
  return (0.0);
}

Seems to have broken the selection of transaction history by position ID.

Print sometimes (and sometimes not) writes

2016.12.05 11:26:11.767 Get current commission of pos (GBPUSD,M5) 1

2016.12.05 11:26:11.767 Get current commission of pos (GBPUSD,M5) GBPUSD

2016.12.05 11:26:11.767 Get current commission of pos (GBPUSD,M5) Position found

2016.12.05 11:26:11.767 Get current commission of pos (GBPUSD,M5) Total trades in position: 0


Cheeky liar, the position is still there!
 
Andrey Dik:

It looks like the selection of transaction history by position ID has broken down.

If it happens after OrderSend, it's OK.
 
fxsaber:
If it happens after OrderSend, it is normal.
No, it is not normal in any way. In any case, there is a position, and therefore there are deals that participated in its "life". But what is stranger is that the code does not see deals even if the EA is already in position, we see this in the logs, the number of positions is defined, the position for the symbol is selected, but there are no deals in it...
 
Andrey Dik:
No, it's not normal in any way. In any case, there is a position and therefore there are deals that participated in its "life". What is stranger is that the code does not see trades even if the Expert Advisor has already had a position...
Renat says it's normal, don't argue! Here is the solution for OrderSend

Forum on trading, automated trading systems and strategy testing

How to work correctly in MT5 with OrderSend

fxsaber, 2016.11.19 23:59

Ripped OrderSendSync from the library here
uint OrderSend_MaxPause = 1000000; // максимальное время на синхронизацию в мкс.

const bool IsTester = (::MQLInfoInteger(MQL_TESTER) || ::MQLInfoInteger(MQL_OPTIMIZATION) ||
                       ::MQLInfoInteger(MQL_VISUAL_MODE) || ::MQLInfoInteger(MQL_FRAME_MODE));
                      
                      

bool Waiting( const bool FlagInit = false )
{
  static ulong StartTime = 0;

  if (FlagInit)
    StartTime = ::GetMicrosecondCount();

  const bool Res = (::GetMicrosecondCount() - StartTime < OrderSend_MaxPause);

  if (Res)
    ::Sleep(0);

  return(Res);
}

bool EqualPrices( const double Price1, const double Price2, const int digits)
{
  return(::NormalizeDouble(Price1 - Price2, digits) == 0);
}

#define WHILE(A) while (!(Res = (A)) && Waiting())

bool OrderSendSync( const MqlTradeRequest &Request, MqlTradeResult &Result )
{
  bool Res = ::OrderSend(Request, Result);

  if (Res && !IsTester && (Result.retcode < TRADE_RETCODE_ERROR) && (OrderSend_MaxPause > 0))
  {
    Res = (Result.retcode == TRADE_RETCODE_DONE);
    Waiting(true);

    if (Request.action == TRADE_ACTION_DEAL)
    {
      WHILE(::HistoryOrderSelect(Result.order))
        ;

      Res = Res && (((ENUM_ORDER_STATE)::HistoryOrderGetInteger(Result.order, ORDER_STATE) == ORDER_STATE_FILLED) ||
                    ((ENUM_ORDER_STATE)::HistoryOrderGetInteger(Result.order, ORDER_STATE) == ORDER_STATE_PARTIAL));

      if (Res)
        WHILE(::HistoryDealSelect(Result.deal))
          ;
    }
    else if (Request.action == TRADE_ACTION_PENDING)
    {
      if (Res)
        WHILE(::OrderSelect(Result.order))
          ;
      else
      {
        WHILE(::HistoryOrderSelect(Result.order))
          ;

        Res = false;
      }
    }
    else if (Request.action == TRADE_ACTION_SLTP)
    {
      if (Res)
      {
        bool EqualSL = false;
        bool EqualTP = false;

        const int digits = (int)::SymbolInfoInteger(Request.symbol, SYMBOL_DIGITS);

        if ((Request.position == 0) ? ::PositionSelect(Request.symbol) : ::PositionSelectByTicket(Request.position))
        {
          EqualSL = EqualPrices(::PositionGetDouble(POSITION_SL), Request.sl, digits);
          EqualTP = EqualPrices(::PositionGetDouble(POSITION_TP), Request.tp, digits);
        }

        WHILE((EqualSL && EqualTP))
          if ((Request.position == 0) ? ::PositionSelect(Request.symbol) : ::PositionSelectByTicket(Request.position))
          {
            EqualSL = EqualPrices(::PositionGetDouble(POSITION_SL), Request.sl, digits);
            EqualTP = EqualPrices(::PositionGetDouble(POSITION_TP), Request.tp, digits);
          }
      }
    }
    else if (Request.action == TRADE_ACTION_MODIFY)
    {
      if (Res)
      {
        bool EqualSL = false;
        bool EqualTP = false;

        const int digits = (int)::SymbolInfoInteger(Request.symbol, SYMBOL_DIGITS);

        if (::OrderSelect(Result.order))
        {
          EqualSL = EqualPrices(::OrderGetDouble(ORDER_SL), Request.sl, digits);
          EqualTP = EqualPrices(::OrderGetDouble(ORDER_TP), Request.tp, digits);
        }

        WHILE((EqualSL && EqualTP))
          if (::OrderSelect(Result.order))
          {
            EqualSL = EqualPrices(::OrderGetDouble(ORDER_SL), Request.sl, digits);
            EqualTP = EqualPrices(::OrderGetDouble(ORDER_TP), Request.tp, digits);
          }
      }
    }
    else if (Request.action == TRADE_ACTION_REMOVE)
      if (Res)
        WHILE(::HistoryOrderSelect(Result.order))
          ;
  }

  return(Res);
}

#undef WHILE
The idea of the code should be clear. I may have missed something. I haven't noticed any errors in operation.

If you use this OrderSend, you won't have such problems.

Either wait for appropriate messages in OnTradeTransaction.

 
fxsaber:
Renat says it is normal, do not argue! Here is the solution for OrderSend

If you use this OrderSend, there will be no such problems.

Or wait for appropriate messages in OnTradeTransaction.

No, this is not normal.

There is a position. We are sending the Expert Advisor to the chart. We have no trade history for the selected position. What is normal here?)))

Reason: