Errores típicos y cómo afrontarlos en el entorno comercial - página 3

 
fxsaber:

La opción correcta con un ejemplo sencillo

Creo que es mejor esperar a que la orden se tenga en cuenta si todavía no está en la posición.
 
Комбинатор:
Creo que es mejor si la orden aún no ha sido contabilizada en la posición, sólo esperar a que se contabilice.

No entiendo la idea.

 
Esquema de implementación condicional para OrderSend normal (sin tiempo de espera)
static MqlTradeResult LastResult = {0};

void OnTradeTransaction( const MqlTradeTransaction&, const MqlTradeRequest&, const MqlTradeResult &Result )
{ 
  LastResult = Result;
}

// Условный алгоритм реализации штатной OrderSend
bool OrderSend( const MqlTradeRequest &Request, MqlTradeResult &Result )
{  
  bool Res = OrderSendAsync(Request, Result);
  
  if (Res)
  {
    while (LastResult.request_id != Result.request_id)
      OnTradeTransaction(); // условно-схематичный вызов
          
    Result = LastResult;    
    Res = (Result.retcode == TRADE_RETCODE_PLACED) ||
          (Result.retcode == TRADE_RETCODE_DONE) ||
          (Result.retcode == TRADE_RETCODE_DONE_PARTIAL);

    LastResult.request_id = 0;
  }
    
  return(Res);
}


Este diagrama muestra que cuando se coloca una orden de mercado utilizando OrderSendAsync en MetaQuotes-Demo, es imposible captar de forma fiable la orden correspondiente que se coloca hasta que la orden se ejecuta o se rechaza. Es decir, no hay mecanismos simples en MT5 para evaluar los resultados intermedios de su OrderSendAsync.

 

parece estar en el tema,

Me gustaría señalar que este código :

if ( !OrderSend(request,result) ) PrintFormat("OrderSend error %d",GetLastError());
else Print(result.price);

funciona sin problemas en la DEMO (result=request),

pero en REAL - es imposible obtener un resultado (resultado=0.0). ... A menos que esperes unos segundos.

 
Ivan Ivanov:

Parece que está en el tema,

Me gustaría señalar que dicho código :

En la DEMO funciona sin problemas (result=request),

pero en REAL - es imposible obtener el resultado (resultado=0.0). ... A menos que esperes unos segundos.

Faltan datos - registros, valores de campos de estructura después de OrderSend, nombre del servidor comercial.

 
fxsaber:

La cuestión, en pocas palabras, es la siguiente: si hay una orden de mercado, considérela también una "posición". Entre comillas porque es una posición envuelta. El código resaltado no suele aparecer en ningún sitio. Pero evita reabrir posiciones. Lo más interesante aquí está resaltado en rojo. La necesidad de este chip no es evidente.

for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderGetTicket(i) && (OrderGetInteger(ORDER_TYPE) <= ORDER_TYPE_SELL) &&
        !OrderGetInteger(ORDER_POSITION_ID) && (OrderGetString(ORDER_SYMBOL) == Symb))
      Res++;  // если мы сюда попадаем при проверке состояния, не запускать стратегию вообще, т.к. это промежуточное состояние.
 
Комбинатор:

Puede que no haya una señal de negociación en el siguiente tick. Yo también uso el estilo MT4, así que no puedo evitar ver esas "posiciones" sin meterme en problemas.

 
fxsaber:

Faltan datos - registros, valores de campos de estructura después de OrderSend, nombre del servidor comercial.

//+------------------------------------------------------------------+
//|                                                      TestBUY.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{//--- объявление и инициализация запроса и результата
  MqlTradeRequest request={0};
  MqlTradeResult result={0};
//--- параметры запроса
  request.action =TRADE_ACTION_DEAL;
  request.symbol=_Symbol; 
  request.volume=0.01;
  request.type=ORDER_TYPE_BUY;
  request.price=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
  request.deviation=5;
  request.magic=1234;
  request.tp=0.0;
  request.comment=DoubleToString(request.price,_Digits);
//--- отправка запроса
  if ( !OrderSend(request,result) )
    PrintFormat("OrderSend error %d",GetLastError()); // если отправить запрос не удалось, вывести
//--- информация об операции
  PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order," NewOrder");
}


2018.02.20 15:20:35.845 Operaciones orden #66745055 comprar 0.01 / 0.01 EURUSDeur en el mercado hecho en 610.625 ms

2018.02.20 15:20:35.935 Trades deal #5461453 buy 0.01 EURUSDeur at 1.23403 done (based on order #66745055)

2018.02.20 15:20:35.845 TestBUY (EURUSDeur,M15) retcode=10009 deal=0 order=66745055

Si la solicitud se cumple (10009) , por qué tratar=0

 
Ivan Ivanov:

Si la solicitud está hecha (10009) , por qué deal=0

Ahí es casi donde empezó la discusión. Los enlaces tienen todos los detalles.

Existe una solución para que OrderSend funcione perfectamente, pero eso sería publicidad.

 
fxsaber:

La opción correcta con un ejemplo sencillo

La cuestión, en pocas palabras, es la siguiente: si hay una orden de mercado, considérela también una "posición". Entre comillas, porque es una posición envuelta. El código resaltado no suele aparecer en ningún sitio. Pero evita reabrir posiciones. Lo más interesante aquí está resaltado en rojo. La necesidad de este chip no es evidente.

El asunto es que existen las llamadas órdenes de cierre de mercado. El mismo SL/TP. Obviamente, no nos gustaría ver esas órdenes de mercado como "posiciones". Y no nos gustaría que se cerraran también esos pedidos que hemos hecho. Así que la condición resaltada es el filtro apropiado.

for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderGetTicket(i) && (OrderGetInteger(ORDER_TYPE) <= ORDER_TYPE_SELL) &&
        !OrderGetInteger(ORDER_POSITION_ID) && (OrderGetString(ORDER_SYMBOL) == Symb))
      Res++;  

SZY Inserte este código aquí y compruebe el resultado en un servidor de demostración.

Invito a todos los interesados a debatir esta cuestión. Mi opinión al respecto es la siguiente:


  1. Enviamos una orden al servidor.
  2. Aparece una orden de mercado que puede llegar a anularse, pero ¿la hemos contabilizado ya como posición?
for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderGetTicket(i) && (OrderGetInteger(ORDER_TYPE) <= ORDER_TYPE_SELL) &&
        !OrderGetInteger(ORDER_POSITION_ID) && (OrderGetString(ORDER_SYMBOL) == Symb))
      Res++;  

Este bucle añade una posición si se encuentra un pedido que no tiene un identificador de posición (el ID es cero).

Hemos devuelto un puesto más.

¿Qué pasa si el pedido es cancelado por el servidor?

...

Creo que al calcular las órdenes de mercado, deberíamos devolver WRONG_VALUE, por ejemplo, si hemos encontrado una - las posiciones no pueden ser inferiores a cero. Esto será una señal de que hay una orden de mercado no registrada. Pero no para añadir el número de puestos.