O grande e terrível MT4 para sempre (ou como fazer uma transição estratégica) - página 13

 
JRandomTrader:

Aqui está a partir da documentação:

"a ordem em que estas transações chegam ao terminal não é garantida, portanto não se pode basear seu algoritmo de negociação na espera de que algumas transações comerciais cheguem depois que outras tenham chegado. " https://www.mql5.com/ru/docs/event_handlers/ontradetransaction

E, por experiência, TRADE_TRANSACTION_ORDER_DELETE, TRADE_TRANSACTION_DEAL_ADD, TRADE_TRANSACTION_HISTORY_ADD transactions can arrive in any order.

Portanto, temos situações em que ainda não há acordo e ordem na história, mas a ordem já existe. Ou vice versa, a ordem ainda está lá, mas o negócio já foi executado. Mas a situação quando a ordem está presente no ativo, assim como na história, dificilmente é possível.

Eu não pego os eventos, eu olho para o quadro completo em um novo tick.


JRandomTrader:

Na verdade, é por isso que eu me recusei a usar a classe CTrade - está pisando em todas essas armadilhas.

Eu tenho uma solução - cada EA mantém uma lista de suas ordens e monitora seu estado. Isto inclui estados 'não-standard' - 'ordem enviada mas ainda não presente nas ordens ativas' (é aqui que podem dobrar), 'ordem apagada mas não presente na história'. Isto também ajuda no trabalho simultâneo sobre o mesmo símbolo quando se faz a rede.

Até recentemente eu usava uma muleta universal que verificava a falta de encomendas. Mas em algum momento começou a falhar.

Acrescentei mais uma muleta pessoal ao Expert Advisor que agora monitora suas próprias encomendas separadamente.

Isso é um monte de muletas...

 
Andrey Khatimlianskii:

Isso é um monte de muletas...

Estudando a questão. Eu até me deparo com isto: OrderSend market order true, então PositionsTotal= 0, OrdersTotal = 0, tabelas históricas inalteradas.

Parece ter sido bem sucedido na escrita IsSynchronized(). O código é um pouco pesado. Ainda não decidi qual a forma de afixar.

 
// Демонстрация открытия дубля позиции в MT5.

#include <Trade\Trade.mqh>

void OnStart()
{
  CTrade Trade;
  
  while (!IsStopped() && (PositionsTotal() <= 1)) // Закончим, когда появится более одной позиции.
    if (PositionsTotal() == 1)
      Trade.PositionClose(PositionGetTicket(0)); // Если есть позиция - закрываем.
    else if (!OrdersTotal())
      Trade.Buy(0.01); // Если нет позиции и ордера - открываем позицию.
}

Execute este código em uma conta demo vazia e veja se duas posições se abrem após alguns segundos.


A mesma lógica no MT4 se parece com isto.

void OnStart()
{
  while (!IsStopped() && (OrdersTotal() <= 1)) // Закончим, когда появится более одной позиции.
    if (OrderSelect(0, SELECT_BY_POS))
      OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0) // Если есть позиция - закрываем.
    else
      OrderSend(_Symbol, OP_BUY, 0.01, Ask, 0, 0, 0) // Если нет позиции и ордера - открываем позицию.
}

É evidente que tal código no MT4 não causará inversão de posição. Mas não no MT5.

 
fxsaber:

Execute este código em uma conta demo vazia e veja se duas posições abrem após alguns segundos.


A mesma lógica no MT4 se parece com isto.

É evidente que tal código no MT4 não causará inversão de posição. Mas não no MT5.

Finalmente, você acabou de descobri-lo? Este problema é tão antigo quanto o próprio terminal. Mas finalmente os usuários de terminais notaram... após uma década.

Quando você mesmo realiza ações comerciais, o problema pode ser resolvido de uma maneira simples - inserir Sleep() por um segundo após a ação ser realizada. Mas quando a EA usa stoploss/stackprofit e o mercado fecha, há o perigo de encontrar este problema e, neste caso, não há solução.

 
Dmitry Fedoseev:

Finalmente, você acabou de descobrir isso? Este problema é tão antigo quanto o próprio terminal. Mas os usuários de terminais finalmente notaram... após uma década.

O problema já vem sendo discutido há muito tempo. Quase todos já o encontraram. É a primeira vez que um código estável o reproduz.

Quando você mesmo realiza uma ação comercial, você pode resolver o problema de uma maneira simples - insira Sleep() por um segundo após a ação ser realizada. Mas quando o Stop Loss/StackProfit e o fechamento do mercado são usados em uma EA, há o perigo de encontrar o problema, e não há solução neste caso.

A solução foi encontrada.

 
fxsaber:

Execute este código em uma conta demo vazia e veja se duas posições abrem após alguns segundos.

Estranho. Não está se reproduzindo. Verificado em demonstração da MQ, build 2900, EURUSD, spread zero. Esperou cerca de cinco minutos.

Talvez eu precise usar algum servidor específico de um verdadeiro DC/broker e não o servidor MQ?

 
Ihor Herasko:

Estranho. Não está se reproduzindo. Verificado em demonstração da MQ, build 2900, EURUSD, spread zero. Esperou cerca de cinco minutos.

Talvez eu precise usar algum servidor específico de um verdadeiro DC/broker e não o servidor MQ?

ForexTimeFXTM-Demo01

 
fxsaber:

ForexTimeFXTM-Demo01

Sim, agora o roteiro pára. Mas ainda resta uma posição. Acho que o segundo tem tempo para fechar?

 
Ihor Herasko:

Sim, agora o roteiro pára. Mas ainda resta uma posição. O segundo deve ter tempo para fechar?

Sempre me restam dois. Se restar um, é ainda mais um bug:

  1. PositionsTotal = 1 - envia uma ordem de fechamento.
  2. Então PositionsTotal = 2 e a ordem do ponto 1 é fechada.
 
fxsaber:

Sempre me restam dois. Se restar um, é um bug ainda maior:

  1. PositionsTotal = 1 - envia uma ordem de fechamento.
  2. Então PositionsTotal = 2 e a ordem do ponto 1 é fechada.

Sim, é isso que quero dizer. Acontece que o roteiro consegue fechar uma das posições quando há realmente duas delas, mas PositionsTotal() retorna 1. E então, após o fechamento, a condição de terminação do loop é cumprida, ou seja, PositionsTotal() retorna 2.