MetaEditor build 1490 - página 3

 
fxsaber:
No hay manera de definirlo. SL y TP son únicamente la esencia del servidor MT.
La forma más fiable (a menos que el corredor cambie el formato de los comentarios, lo que es poco probable).
 

Así es como funciona:

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);
           }
        }
     }
  }
 
Opción de trabajo para la vida real (no para el probador)
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:
Variante de trabajo para la realidad (no para el probador)
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.");    
  }
}
Lo he comprobado en el probador - no funciona, creo que tampoco funcionará para el real, porque la posición para la que se comprueba ya no existe.
 
Andrey Dik:
He comprobado en el probador - no funciona, y creo que no funcionará en el real, porque la posición para la que va la prueba ya no existe.
Se trata de un error artificial en el probador (para no ralentizarlo en absoluto). Sólo por lógica, todo es correcto.
 
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);
}

Parece que se ha roto la selección del historial de transacciones por ID de posición.

Imprimir a veces (y a veces no) escribe

2016.12.05 11:26:11.767 Obtener la comisión actual de pos (GBPUSD,M5) 1

2016.12.05 11:26:11.767 Obtener la comisión actual de pos (GBPUSD,M5) GBPUSD

2016.12.05 11:26:11.767 Obtener la comisión actual de pos (GBPUSD,M5) Posición encontrada

2016.12.05 11:26:11.767 Obtener la comisión actual de la posición (GBPUSD,M5) Total de operaciones en la posición: 0


Mentiroso descarado, ¡la posición sigue ahí!
 
Andrey Dik:

Parece que la selección del historial de transacciones por ID de posición se ha roto.

Si ocurre después de OrderSend, está bien.
 
fxsaber:
Si ocurre después de OrderSend, es normal.
No, no es normal de ninguna manera. En cualquier caso, hay una posición, y por lo tanto hay tratos que participaron en su "vida". Pero lo que es más extraño es que el código no ve tratos aunque el EA ya esté en posición, lo vemos en los logs, el número de posiciones está definido, la posición para el símbolo está seleccionada, pero no hay tratos en ella...
 
Andrey Dik:
No, no es normal de ninguna manera. En cualquier caso, hay una posición y por lo tanto hay tratos que participaron en su "vida". Lo que es más extraño es que el código no ve las operaciones aunque el Asesor Experto ya haya tenido una posición...
Renat dice que es normal, ¡no discutas! Esta es la solución para OrderSend

Foro sobre comercio, sistemas de comercio automatizados y pruebas de estrategias

Cómo trabajar correctamente en MT5 con OrderSend

fxsaber, 2016.11.19 23:59

Arrancó OrderSendSync de la biblioteca aquí
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
La idea del código debe ser clara. Puede que haya pasado algo por alto. No he notado ningún error de funcionamiento.

Si utiliza este OrderSend, no tendrá esos problemas.

O bien esperar los mensajes apropiados en OnTradeTransaction.

 
fxsaber:
Renat dice que es normal, ¡no discutas! Esta es la solución para OrderSend

Si utiliza este OrderSend, no habrá esos problemas.

O esperar los mensajes apropiados en OnTradeTransaction.

No, esto no es normal.

Hay una posición. Enviamos el Asesor Experto al gráfico. No tenemos historial de operaciones para la posición seleccionada. ¿Qué es lo normal aquí?))