OnTradeTransaction - página 8

 
Igor Zakharov:

Em robôs "normais", o caso que descrevi, não notei nada; mas em um caso me pediram para fazer um sistema de segurança: a condição era que as posições fossem sempre bloqueadas (seja com posições reais ou com uma ordem pendente), ou seja, o número de lotes de compra é igual ao número de lotes de venda. Este é o caso que me introduziu às nuances de ordem/posição/contagem de comércio em uma nota de cinco.

A diferença, como expliquei a mim mesmo :) é que os quatro, ao receber uma resposta do corretor, primeiro sincronizam suas "tabelas" com os pedidos abertos e o histórico, e depois informam o usuário sobre a resposta do corretor. Os cinco imediatamente nos transmitem esta resposta, e ao mesmo tempo corrigem suas "tabelas" (e todos os programas mql lêem dados destas "tabelas"). Este é o momento em que pegamos no timer de milissegundos. Mas então, por que não o apanhamos no testador?

Em geral, fiz a minha paz de espírito...

Não, as coisas estão piores.

A ordem no momento da transformação de uma ordem pendente (ou de mercado) em uma ordem histórica (executada ou cancelada), ela desaparece completamente do terminal por algum tempo. Ela não aparece nem entre os mercados pendentes (ou "iniciados"), nem entre os históricos.

Portanto, não se trata de uma questão de execução, mas de sincronização destas duas tabelas. A resposta do servidor veio ("Order executed, generated transaction so-and-so"), ela é removida de uma tabela, mas não é inserida na outra.

 
Andrey Khatimlianskii:

Não, as coisas estão piores.

Quando uma ordem muda de uma ordem pendente (ou de mercado) para uma ordem histórica (executada ou cancelada), ela desaparece completamente do terminal por algum tempo. Ela não aparece nem entre os mercados pendentes (ou "iniciados"), nem entre os históricos.

Portanto, não se trata de uma questão de execução, mas de sincronização destas duas tabelas. A resposta veio do servidor ("Ordem executada, acionou a transação mais ou menos") e é excluída de uma tabela mas não inserida na outra.

É interessante verificar.Igor Makanu me intrigou com a tarefahttps://www.mql5.com/ru/forum/6343/page1097#comment_12518742

Fiz a primeira aproximação no meu joelho. Depois farei algumasestatísticas sobre a operação OnOrder e OnOrderTransaction e o estado do ambiente comercial e, se eu não for muito preguiçoso, posso colocá-lo para teste de demonstração para ver o que está acontecendo em diferentes contas/corretores.

então, será possível analisar. Suposições feitas até agora: 1. nenhuma execução parcial é verificada e as peculiaridades da conta não são verificadas; enviei uma ordem de mercado, a posição aberta é lembrada, espero que a transação seja aberta no diário e a abro novamente na direção oposta. 2. Idealmente, uma determinada transação deveria ser capturada na OnOrderTransaction, mas até agora eu a fiz desta maneira - em ambos os casos, eu verifico tudo da mesma maneira.

Naturalmente, o código não é o ideal. Eu já posso ver onde as posições de pedidos serão perdidas se tudo for tão ruim quanto descrito no post acima.

//+------------------------------------------------------------------+
//|                                                 Test_Makalu2.mq5 |
//|                                           Copyright 2019, Allex@ |
//|                                                 alex-all@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, Allex@"
#property link      "alex-all@mail.ru"
#property version   "1.00"
#include <Expert\Expert.mqh>
//--- input parameters
input int      TP=200;
input int      SL=200;
input double   Lot=0.01;
input string   File;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CExpertTest : public CExpert
  {
public:
   int               type;
   ulong             order;
   ulong             deal;
   ulong             position;
   bool              send;
   bool              placed;
   bool              opened;
   bool              history;
   datetime          last_history;

                     CExpertTest() {order=0;};
                    ~CExpertTest() {};
   bool              Buy(double volume,double price,double sl,double tp,const string comment="") {return m_trade.Buy(volume, price, sl, tp,  comment);};
   bool              Sell(double volume,double price,double sl,double tp,const string comment="") {return m_trade.Sell(volume, price, sl, tp,  comment);};
   bool              CheckOrder(ulong order)
     {
      ulong state;
      if(OrderSelect(order))
        {
         if(OrderGetInteger(ORDER_STATE)==ORDER_STATE_FILLED)
            position=OrderGetInteger(ORDER_POSITION_ID);
        }
      else
         if(HistoryOrderSelect(order))
           {
            if(HistoryOrderGetInteger(order,ORDER_STATE,state)&& state==ORDER_STATE_FILLED)
               position=HistoryOrderGetInteger(order,ORDER_POSITION_ID);
           }
         else
           {
            return false;
           }
      return true;

     }
   virtual bool      Processing(void)
     {
      double price;
      if(order==0)
        {
         last_history=TimeCurrent();
         price=m_symbol.Ask();
         if(Buy(Lot,price,m_symbol.NormalizePrice(price-SL*m_symbol.Point()),m_symbol.NormalizePrice(price+TP*m_symbol.Point())))
            if(m_trade.ResultRetcode()==TRADE_RETCODE_DONE)
              {
               //ulong deal2;
               deal=m_trade.ResultDeal();
               order=m_trade.ResultOrder();
               if(order!=0 && CheckOrder(order))
                  return true;
              }
        }
      return false;
     }
   void              OnTrade()
     {
      if(order==0 || !CheckOrder(order))
         return;
      HistorySelect(last_history,TimeCurrent());
      for(int i=HistoryDealsTotal()-1; i>=0; i--)
        {
         ulong ticket=HistoryDealGetTicket(i);
         ulong ordticket=HistoryDealGetInteger(ticket,DEAL_ORDER);
         ulong pos=HistoryDealGetInteger(ticket,DEAL_POSITION_ID);
         if(pos==position || ordticket==order || ticket==deal)
           {
            int entry=HistoryDealGetInteger(ticket,DEAL_ENTRY);
            ulong type=HistoryDealGetInteger(ticket,DEAL_TYPE);
            if(pos==position && entry==DEAL_ENTRY_OUT)
              {
               Refresh();
               double price;
               double sl;
               double tp;
               bool result=false;
               datetime dt=TimeCurrent();
               if(type==DEAL_TYPE_SELL)
                 {
                  price=m_symbol.Bid();
                  sl=m_symbol.NormalizePrice(price+SL*m_symbol.Point());
                  tp=m_symbol.NormalizePrice(price-TP*m_symbol.Point());
                  result=Sell(Lot,price,sl,tp);
                 }
               if(type==DEAL_TYPE_BUY)
                 {
                  price=m_symbol.Ask();
                  sl=m_symbol.NormalizePrice(price-SL*m_symbol.Point());
                  tp=m_symbol.NormalizePrice(price+TP*m_symbol.Point());
                  result=Buy(Lot,price,sl,tp);
                 }
               if(result && m_trade.ResultRetcode()==TRADE_RETCODE_DONE)
                 {
                  deal=m_trade.ResultDeal();
                  order=m_trade.ResultOrder();
                  if(order!=0 && CheckOrder(order))
                     last_history=dt;
                 }
              }
           }
        }
     }
  };
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
CExpertTest Expert;
//---
int OnInit()
  {
   if(!Expert.Init(Symbol(),Period(),Point()))
      return INIT_FAILED;
   Expert.OnTradeProcess(true);
   return(INIT_SUCCEEDED);
  }
//---
void OnTick()
  {
   Expert.OnTick();
  }
//+------------------------------------------------------------------+
void OnTrade()
  {
   Expert.OnTrade();
  }
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result)
  {
   Expert.OnTrade();
  }
Вопросы от начинающих MQL5 MT5 MetaTrader 5
Вопросы от начинающих MQL5 MT5 MetaTrader 5
  • 2019.07.21
  • www.mql5.com
Подскажите пожалуйста, такой показатель тестера в жизни реален? И хороший это или плохой результат за год с депо 3000...
 
Aleksey Mavrin:

Isto é interessante de conferir.Igor Makanu me intriga com a tarefa https://www.mql5.com/ru/forum/6343/page1097#comment_12518742

houve uma solução na discussãohttps://www.mql5.com/ru/forum/6343/page1098#comment_12519819, parte da discussão, entretanto, foi eliminada (((
 
Há uma solução no fio MT4Orders. Mas você mesmo tem que sentir cada ancinho ;)
 
Aleksey Mavrin:

Fez uma primeira aproximação no joelho.

Esta demonstração é melhor para ver.ForexTimeFXTM-Demo01

 
Igor Zakharov:

Eu não notei o caso que descrevi em robôs comerciais "normais".

Qualquer biblioteca comercial pode e deve ser verificada para verificar a abundância, usando testes de estresse em várias contas de demonstração. Deve passar tudo sem nenhum impedimento.

Bem, para que isso aconteça, o autor tem que se familiarizar pessoalmente com as piadas do MT5. Em minha prática, descobri que mesmo isto não é suficiente.

Há algumas coisas muito específicas que não foram detectadas pelo terrível spamming das encomendas para os servidores comerciais. Graças ao feedback, foi possível encontrar um comportamento bastante estranho que nem mesmo os próprios desenvolvedores parecem perceber.

 
Igor Makanu:
houve uma solução na discussãohttps://www.mql5.com/ru/forum/6343/page1098#comment_12519819, parte da discussão foi eliminada (((
Andrey Khatimlianskii:
Existe uma solução no ramo de MT4Orders. Mas você mesmo tem que sentir cada ancinho ;)

Isso mesmo, o ancinho é sempre interessante, e então veja como os profissionais o fizeram. A soluçãofxsaber é brilhante em sua concisão, mas vejo um senão nessa solução em uma coisa - os manuais dizem que o bilhete de posição é EXATAMENTE o bilhete da ordem aberta, mas NÃO TUDO.

Na minha solução, eu estava procedendo a partir disso.

fxsaber
fxsaber
  • www.mql5.com
Опубликовал пост "Out-Of-Sample" - где расположить, справа или слева? Когда-то в паблике столкнулся с мнением, что OOS должен располагаться только справа. Т.е. расположение его слева от интервала Оптимизации - ошибка. Я с этим был категорически не согласен, т.к. не видел разницы. Теперь вижу. Ошибался, был не прав... Опубликовал пост...
 
fxsaber:

Qualquer biblioteca de negociação pode e deve ser verificada quanto a perspicácia através de testes de estresse em várias contas de demonstração. Deve passar tudo sem nenhum impedimento.

Usei 200ms para os testes e quando o devolvi, o homem o fixou em 5ms. Aos cinco, funcionou quase sempre, de qualquer forma.

Não sei se é importante, mas eles usaram o winapi timeBeginPeriod(1), ou seja, abaixo do padrão de 20ms tudo aconteceu

 
Aleksey Mavrin:

o bilhete de posição GERALMENTE o bilhete de ordem de abertura, mas NÃO SEMPRE.

Não me lembro muito bem, mas parece ser sempre.

 
fxsaber:

Não me lembro muito bem disso, mas acho que sempre esteve presente.

Sim, você está certo, pois neste caso é um identificador de posição, constante ao longo de sua vida. Confundi-o com o ticker de posição, que muda durante os rollovers e as redes.

Mas eu não entendo - quando uma posição é parcialmente fechada, o bilhete não muda para o bilhete da última ordem que afeta a posição?

Vou rever meus códigos, obrigado. Eu visitei o fórum não por nada)

Quanto à "ordem perdida" que não está na lista de ordens atuais ou históricas: Parece-me que não se trata de um bug, só preciso olhar cuidadosamente as características de

Acho que isto não é um bug, basta olhar com cuidado as peculiaridades do mercado de MT-servidor de terminais (no caso de execução instantânea o mercado não funciona). Acho que sim, veja - o terminal envia uma ordem de mercado, no caso de função síncrona - ele espera e recebe uma resposta do servidor,

Se não houver erro, a resposta pode ser apenas TRADE_RETCODE_DONE (no caso de execução instantânea, são requerimentos, mas até agora é o tipo de mercado), o que significa essencialmente que o servidor enviou a ordem para o mercado e ele

Na verdade, isso significa que o servidor enviou o pedido e espera por sua resposta. O estado do pedido neste momento éORDER_STATE_STARTED se eu não estiver enganado e seu bilhete for conhecido. Se o pedido for executado, o servidor envia a OnTradeTransaction ao terminal e o status do pedido muda para ORDER_STATE_FILLED e o comércio é conhecido

e a posição se torna conhecida. É somente neste ponto que o terminal registra a ordem na história. Não o faz de antemão, pois não temos certeza do que aconteceu com ele e já deu a resposta inicial do servidor.

Este é o tempo até que a ordem seja executada na rede ECN ou em outro lugar, eles não estão em nenhuma das duas listas. Isto é, no caso da ordem de mercado, ela só aparece na história (não tenho certeza sobre o caso das solicitações durante a execução imediata),

nunca aparecerá na lista de abertos. E quando uma ordem pendente é acionada, ela é removida da lista das abertas porque já se tornou uma ordem de mercado e esperamos que o servidor de mercado responda, e então ela é enviada para a história.

Eu estou certo?

Razão: