Erros típicos e como lidar com eles quando se lida com o ambiente comercial - página 3

 
fxsaber:

A opção certa usando um exemplo simples

Penso que é melhor esperar que a ordem seja levada em conta se ainda não estiver na posição.
 
Комбинатор:
Acho que é melhor se a ordem ainda não foi contabilizada na posição, basta esperar que ela seja contabilizada.

Eu não entendo a idéia.

 
Esquema de Implementação Condicional para o Envio Normal de Pedidos (No Timeout)
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 mostra que quando uma ordem de mercado é colocada usando OrderSendAsync em MetaQuotes-Demo, é impossível capturar com segurança a ordem correspondente sendo colocada até que a ordem seja executada ou rejeitada. Ou seja, não há mecanismos simples no MT5 para avaliar os resultados intermediários de seus OrderSendAsync.

 

parece estar em tema,

Gostaria de ressaltar que este código :

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

trabalha sem falhas na DEMO (resultado=pedido),

mas em REAL - é impossível obter um resultado (resultado=0,0). ... A menos que você espere alguns segundos.

 
Ivan Ivanov:

Parece estar no assunto,

Gostaria de ressaltar que tal código :

Na DEMO funciona sem falhas (resultado=pedido),

mas em REAL - é impossível obter resultado (resultado=0,0). ... A menos que você espere alguns segundos.

Faltam dados - logs, valores de campo de estrutura após OrderSend, nome do servidor comercial.

 
fxsaber:

O ponto em poucas palavras é o seguinte: se houver uma ordem de mercado, considere-a também uma "posição". Em aspas porque é uma posição embrulhada. O código destacado geralmente não aparece em nenhum lugar. Mas evita a reabertura de posições. A coisa mais interessante aqui é destacada em vermelho. A necessidade deste chip não é imediatamente aparente.

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++;  // если мы сюда попадаем при проверке состояния, не запускать стратегию вообще, т.к. это промежуточное состояние.
 
Комбинатор:

Pode não haver um sinal comercial no próximo tique. Eu mesmo uso o estilo MT4, por isso não posso deixar de ver tais "posições" sem me meter em problemas.

 
fxsaber:

Faltam dados - logs, valores de campo de estrutura após OrderSend, nome do 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 Pedido de compra nº 66745055 0.01 / 0.01 EURUSDeur no mercado feito em 610.625 ms

2018.02.20 15:20:35.935 Trades deal #5461453 comprar 0,01 EURUSDeur a 1,23403 feito (com base no pedido #66745055)

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

Se o pedido for atendido (10009) , por que negociar=0

 
Ivan Ivanov:

Se o pedido é feito (10009) , por que negociar=0

Foi quase aí que a discussão começou. Os links têm todos os detalhes.

Existe uma solução para que a OrderSend funcione perfeitamente, mas isso seria a publicidade.

 
fxsaber:

A opção certa usando um exemplo simples

O ponto em resumo é o seguinte: se existe uma ordem de mercado, considere-a também uma "posição". Em citações, porque é uma posição embrulhada. O código destacado geralmente não aparece em nenhum lugar. Mas evita a reabertura de posições. A coisa mais interessante aqui é destacada em vermelho. A necessidade deste chip não é imediatamente aparente.

A questão é que existem as chamadas ordens de fechamento de mercado. O mesmo SL/TP. Obviamente, não gostaríamos de ver tais ordens de mercado como "posições". E não gostaríamos de ver também os pedidos que fizemos para fechar. Portanto, a condição destacada é o filtro apropriado.

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 Insira este código aqui e verifique o resultado no servidor de demonstração.

Convido todos os interessados a discutir esta questão. Minha opinião sobre este assunto é a seguinte:


  1. Enviamos um pedido para o servidor.
  2. Uma ordem de mercado aparece e pode eventualmente ser cancelada, mas será que já a contamos como uma posição?
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 laço adiciona uma posição se for encontrada uma ordem que não tenha um identificador de posição (o ID é zero).

Retornamos mais uma posição.

E se o pedido for cancelado pelo servidor?

...

Penso que ao calcular as ordens de mercado, devemos retornar WRONG_VALUE, por exemplo, se encontramos uma - as posições não podem ser inferiores a zero. Isto será um sinal de que há uma ordem de mercado não gravada. Mas não para adicionar o número de posições.

Razão: