Características da linguagem mql5, subtilezas e técnicas - página 70

 

Fórum sobre negociação, sistemas de negociação automatizados e testes de estratégia de negociação

Como identificar um substituto de gráfico?

fxsaber, 2018.02.08 12:39

void OnTick()
{  
  const long Chart = ChartID();
  string PrevSymbol = _Symbol;
  ENUM_TIMEFRAMES PrevTF = _Period;
    
  while (!IsStopped())
  {
    if ((PrevSymbol != ChartSymbol(Chart)) || (PrevTF != ChartPeriod(Chart))) // ноль указывать НЕЛЬЗЯ!
    {      
      PrevSymbol = ChartSymbol(Chart);
      PrevTF = ChartPeriod(Chart);
      
      Alert(PrevSymbol + " " + EnumToString(PrevTF));      
    }
    
    Sleep(0);
  }
}

Zero parâmetro de entrada ChartID em algumas funções não causa recálculo de valores. Se você quiser dados reais do gráfico atual, você precisa usar a identificação completa.

 

Fórum sobre negociação, sistemas de negociação automatizados e testes estratégicos

POSITION_TICKET != IDENTIFICADOR_DE_POSIÇÃO

fxsaber, 2018.02.12 20:14

Conclusões

Se assumirmos que este é um comportamento normal do MT5 e não uma peculiaridade do hack do corretor, então

  • ORDER_STATE_PARTIAL não ocorre em ordens históricas.
  • As ordens executadas têm sempre o status ORDER_STATE_FILLED.
  • Quando uma ordem é parcialmente executada, uma nova ordem de mercado correspondente é criada pelo servidor de negociação (ORDER_REASON_CLIENT - mesmo que a ordem inicial seja colocada automaticamente (EXPERT)).
  • A antiga ordem ao vivo (o bilhete não é alterado) permanece pendente com um volume reduzido (ORDER_VOLUME_CURRENT).
  • A antiga ordem ao vivo neste caso tem o status ORDER_STATE_PARTIAL. Na verdade, esta bandeira é o resultado da comparação entre ORDER_VOLUME_CURRENT e ORDER_VOLUME_INITIAL.
  • Todas as posições em aberto recebem ID == OrderTicket. Onde OrderTicket é o bilhete gerado pelo servidor comercial.
  • Um comércio tem sempre exactamente uma ordem histórica e o seu estatuto é ORDER_STATE_FILLED.
  • Cada ordem histórica executada tem exatamente uma negociação.
  • O ORDER_VOLUME_INITIAL de qualquer ordem executada é igual ao volume pelo qual foi executada. Ou seja, mesmo a ordem inicial que foi cancelada tem um ORDER_VOLUME_INITITAL que é igual ao volume do comércio que desovou.
  • O tempo da ordem inicial (que foi parcialmente executada) não se altera e não é igual ao tempo da sua negociação.
  • A tabela do histórico é ordenada por tempo de ordem (ORDER_TIME_SETUP), mas não por tempo de negociação. Portanto, se fizermos HistorySelect da DEAL_TIME, não podemos obter a ordem correspondente na tabela do histórico.
  • HistorySelectByPosition devolve sempre o conjunto necessário de acordos/ordens.
  • Você pode calcular o escorregamento para qualquer negócio.

Pontos fracos

  • Os ORDER_REASON_PARTIAL, DEAL_REASON_PARTIAL e POSITION_REASON_PARTIAL estão em falta. Estas bandeiras devem ser colocadas imediatamente após REASON_EXPERT nas respectivas listagens.
  • As ordens de mercado correspondentes, ao executar parcialmente ordens limitadas, podem, pela sua natureza, ter um deslize negativo. Isto parece ser apenas um erro no tipo de ordem e não há realmente nenhuma ordem de mercado - é criada apenas dentro do MT5 e não vai para fora.

ZZY Hipótese totalmente confirmada.

Fórum sobre negociação, sistemas de negociação automatizados e teste de estratégias de negociação

POSITION_TICKET != IDENTIFICADOR_DE_POSIÇÃO

Pavel Kolchin, 2018.02.12 13:31

(não sei ao certo, difícil de verificar, semelhante ao fechamento parcial da posição)

Tudo funciona assim:

1) ordem pendente acionada parcialmente - posição com Position_ID = Order_Ticket1 é aberta

2) a ordem restante é formada em uma nova ordem Order_Ticket2 e está aguardando sua execução; a nova Order_Ticket2 != Order_Ticket1 pois não pode haver 2 ordens com a mesma Order_Ticket na história

3) a ordem restante foi executada - uma posição com Position_ID = Order_Ticket2 é aberta

há duas ordens no histórico, duas posições no terminal, tudo corresponde

 

Fórum sobre negociação, sistemas de negociação automatizados e teste de estratégias de negociação

Discussão sobre "LifeHack for trader: misturando ForEach on define (#define)".

fxsaber, 2018.02.14 10:54

Medição de desempenho

#define  BENCH(A)                                                              \
{                                                                             \
  const ulong StartTime = GetMicrosecondCount();                              \
  A;                                                                          \
  Print("Time[" + #A + "] = " + (string)(GetMicrosecondCount() - StartTime)); \
}

double GetAsk()
{
  static MqlTick tick = {0};
  
  return(SymbolInfoTick(Symbol(),tick) ? tick.ask : 0);
}

#define  AMOUNT 1 e6

void OnStart()
{
  double Sum = 0;
  
  BENCH(for (int i = 0; i < AMOUNT; i++) Sum += GetAsk())
  BENCH(for (int i = 0; i < AMOUNT; i++) Sum += SymbolInfoDouble(_Symbol, SYMBOL_ASK))
  
  Print(Sum);
}


Resultado

Time[for(inti=0;i<AMOUNT;i++)Sum+=GetAsk()] = 78952
Time[for(inti=0;i<AMOUNT;i++)Sum+=SymbolInfoDouble(_Symbol,SYMBOL_ASK)] = 162606

Eu estava totalmente errado! SymbolInfoDouble é duas vezes mais lento do que SymbolInfoTick.

Fórum sobre negociação, sistemas de negociação automatizados e testes de estratégia de negociação

Discussão sobre "LifeHack for trader: misturando ForEach on define (#define)".

fxsaber, 2018.02.14 11:58

Incompetente. Resultado em Testador.

2017.09.01 00:00:10   Time[for(inti=0;i<AMOUNT;i++)Sum+=GetAsk()] = 87424
2017.09.01 00:00:10   Time[for(inti=0;i<AMOUNT;i++)Sum+=SymbolInfoDouble(_Symbol,SYMBOL_ASK)] = 83410

Onde o desempenho é necessário (Optimizer), é melhor usar o SymbolInfoDouble. No mundo real, não faz diferença.


Função ZZY A medição da velocidade deve ser feita num ambiente onde o desempenho é importante - Testador.

 

Fórum sobre negociação, sistemas de negociação automatizados e testes de estratégia de negociação

Bugs, bugs, perguntas

fxsaber, 2018.02.12 23:10

Abertura da posição BUY à mão em dois servidores de demonstração de negociação


RoboForex-MetaTrader 5

2018.02.13 00:02:08.424 '8520459': market buy 1.00 GBPUSD
2018.02.13 00:02:10.101 '8520459': accepted market buy 1.00 GBPUSD
2018.02.13 00:02:10.101 '8520459': deal #90389019 buy 1.00 GBPUSD at 1.38387 done (based on order #107426544)
2018.02.13 00:02:10.101 '8520459': order #107426544 buy 1.00 / 1.00 GBPUSD at 1.38387 done in 1683.949 ms


FXOpen-MT5

2018.02.13 00:00:25.780 '18000903': market buy 1.00 GBPUSD
2018.02.13 00:00:25.912 '18000903': accepted market buy 1.00 GBPUSD
2018.02.13 00:00:25.922 '18000903': market buy 1.00 GBPUSD placed for execution
2018.02.13 00:00:25.942 '18000903': order #896454 buy 1.00 / 1.00 GBPUSD at market done in 154.252 ms
2018.02.13 00:00:25.942 '18000903': deal #80559 buy 1.00 GBPUSD at 1.38387 done (based on order #896454)

As linhas da mesma cor indicam a mesma coisa. No entanto, vê-se claramente que eles estão em ordem diferente. Para Robo, a mensagem sobre a execução da ordem vem após a execução da operação. Em aberto vem ANTES! Por este motivo, a OrderSend devolve a sorte, mas nenhuma transação ainda. Isto é, recebemos pedidos não sincronizados com o histórico.

Código para FXOpen-MT5

#define  PRINT(A) Print(#A + " = " + (string)(A))

void OnStart()
{
  MqlTradeRequest Request = {0};
  
  Request.action = TRADE_ACTION_DEAL;
  Request.symbol = _Symbol;
  Request.volume = 1;
  Request.type_filling = ORDER_FILLING_IOC;
  
  MqlTradeResult Result;
  
  PRINT(OrderSend(Request, Result));
  PRINT(Result.deal);
}


Resultado

OrderSend(Request,Result) = true
Result.deal = 0


Esta situação tem a seguinte explicação

Fórum sobre negociação, sistemas de negociação automatizados e testes estratégicos

Bugs, bugs, perguntas

Rashid Umarov, 2018.02.15 06:25

Se uma ordem é enviada para um sistema de trading externo, o servidor de trading MetaTrader 5 não espera por uma resposta do mesmo e retorna imediatamente o resultado do pedido como "ordem colocada". Por este motivo, a OrderSend devolverá sempre o negócio=0, pois ainda não há informação sobre o negócio executado. Apanhe-o na OnTrade ou OnTradeTransaction.

Um exemplo de ouvinte de eventos comerciais é dado no artigo Where to start when creating a trading robot for MOEX - TradeTransactionListener.mq5

OrderSend - envia uma ordem para executar uma operação de mercado.A ordem é colocada- precisamos ler Result.order. Mas ninguém espera pelo(s) acordo(s) - pode haver muitos deles e o tempo total da sua execução não está definido.

Depende da implementação específica do resultado do lado do corretor. No caso geral, não está definido.

Por isso, recomendo vivamente usar a conta demo no FXOpen-MT5 como um teste para o seu código, porque ela se destaca de outras demos.


Por exemplo, sugiro tentar escrever um script em MQL5 com tal lógica de negociação (estilo MQL4 apenas para visualização de sentido rápido)

void OnStart()
{
  OrderCloseBy(OrderSend(_Symbol, OP_BUY, 1, Ask, 0, 0, 0), OrderSend(_Symbol, OP_SELL, 1, Bid, 0, 0, 0));
}

Não é nada fácil. Também recomendo o servidor de demonstração mencionado para trabalhar na execução parcial.

 
fxsaber:
Apagou um post que dava uma explicação de um dos erros mais comuns no MT5.
Não está entre as eliminadas. Isso é estranho. Pode postar de novo?
 
fxsaber:

O posto era grande. Não esperava ser apagado. Eu gostaria de ouvir a razão para a remoção. Porque é masoquista ser apagado novamente.

Estou a dizer-te, não está entre os apagados. Talvez tenha havido uma falha?
 

Fórum sobre negociação, sistemas de negociação automatizados e teste de estratégias de negociação

Organização de um ciclo de encomendas

fxsaber, 2018.02.16 09:40

As coisas não estão a correr nada bem no MT5. Exemplo mostrando o problema

// Пример неправильного считывания торгового окружения на каждом тике
// Скрипт эмулирует два тика ТС, которая должна открыть одну позицию, если ее нет.

#include <Trade/Trade.mqh>

// Возвращает количество позиций по символу
int GetAmountPositions( const string Symb )
{
  int Res = 0;
  
  // Этот MQL5-код с ошибкой
  for (int i = PositionsTotal() - 1; i >= 0; i--)
    if (PositionGetSymbol(i) == Symb)
      Res++;

/*
  // В MT4 такой код выполняется без ошибки
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS) && (OrderType() <= OP_SELL) && (OrderSymbol() == Symb))
      Res++;
*/      
  return(Res);
}

// Пример OnTick
void ExampleOnTick()
{
  static CTrade Trade;
  
  // Если нет позиции, открываем
  if (!GetAmountPositions(_Symbol))
    Trade.Buy(1);    
}

// Эмуляция прихода двух Tick-событий
void OnStart()
{
  ExampleOnTick(); 
  
  Sleep(10); // Между двумя тиками ~10 мс.
  
  ExampleOnTick();
}

Você acha que se você executar este script em um símbolo sem posições, o que vai acabar acontecendo?

A resposta correta é que uma ou duas posições serão abertas.

A razão pela qual isto acontece. Após o primeiro OrderSend, uma ordem de mercado aparece e se um novo tick chega antes do momento de sua execução, ainda não há posição e o segundo OrderSend é feito.

Devido a isso, um padrão MT5 aparentemente normalnão funcionará adequadamente e, como consequência, a maioria dos Expert Advisors MT5 em codobase. Ao mesmo tempo, o modelo quase idêntico do MT4 continuará a funcionar sem qualquer problema.

A ideia aparentemente boa do PositionsTotal é um pouco ofuscada pela necessidade do MT5 de também analisar OrdensTotal para ordens de mercado.

Tenha cuidado!

 
fxsaber:

Devido a isso, um padrão MT5 aparentemente normalnão funcionará adequadamente e, como consequência, a maioria dos MT5 EAs na kodobase.

Como prova desta afirmação podemos levar quase qualquer Expert Advisor na kodobase MT5. Não vamos escolher algo, mas sim o último Expert Advisor no momento. É bom que tenha sido escrito por um autor com uma grande experiência de MT5-publicação em QB.

O código fonte tem as seguintes cordas (os meus comentários são destacados)

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//....
   int total=0; // для расчета количества открытых советником позиций
//....
//--- main cycle
   for(int i=PositionsTotal()-1;i>=0;i--)
      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)
           {
            total++; // расчет количества открытых позиций
//....
   if(total==0) // Если нет открытых советником позиций
     {
      if(!RefreshRates())
        {
         PrevBars=iTime(1);
         return;
        }
      //--- open BUY 
      if(MACD_MAIN_2>MACD_SIGNAL_2 && MACD_MAIN_4<MACD_SIGNAL_4) // Сигнал на покупку
        {
         double sl=(InpStopLoss!=0)?m_symbol.Ask()-ExtStopLoss:0.0;
         double tp=(InpTakeProfit!=0)?m_symbol.Ask()+ExtTakeProfit:0.0;
         OpenBuy(sl,tp); // Отправка маркет-ордера на покупку
         return;
        }
      //--- open SELL
      if(MACD_MAIN_2<MACD_SIGNAL_2 && MACD_MAIN_4>MACD_SIGNAL_4) // Сигнал на продажу
        {
         double sl=(InpStopLoss!=0)?m_symbol.Bid()+ExtStopLoss:0.0;
         double tp=(InpTakeProfit!=0)?m_symbol.Bid()-ExtTakeProfit:0.0;
         OpenSell(sl,tp); // Отправка маркет-ордера на продажу
        }
     }
   return;
  }

Temos uma situação idêntica à descrita acima.

Fórum sobre negociação, sistemas de negociação automatizados e testes estratégicos

Peculiaridades da linguagem mql5, dicas e truques

fxsaber, 2018.02.16 19:52

Após a primeira OrderSend aparece uma ordem de mercado e se um novo tick chega antes da sua execução então ainda não há posição e uma segunda OrderSend é feita.

A ideia aparentemente boa do PositionsTotal é de certa forma obscurecida pela necessidade de o MT5 também analisar OrdensTotal para ordens de mercado.

Isso significa que no caso geral, em vez de uma posição, o Expert Advisor abrirá duas, três, etc. Dependendo da frequência com que os ticks são recebidos e do tempo de execução das ordens de mercado.


Como quase todos os EAs MT5 no kodobase são escritos com a mesma lógica do modelo MT5, eles também têm o mesmo bug que está contido nele. Isto é verdade para quase todos os MT5 EAs em KB, infelizmente.

MACD EA
MACD EA
  • votos: 4
  • 2018.02.15
  • Vladimir Karputov
  • www.mql5.com
При поступлении сигнала противоположная позиция закрывается. Также советник может закрывать половину позиции (параметр Profit for closing half of the position), может переводить позицию в безубыток (параметр Breakeven). Размер открываемой позиции может задавать вручную (параметр Lots) или в процентах риска от свободной маржи (параметр Risk in...
 

Em uma rede pode haver uma posição aberta e várias ordens de mercado de qualquer direção no mesmo símbolo, ao mesmo tempo. Por exemplo, uma posição COMPRAR e uma ordem COMPRAR. É verdade, não consegui encontrar tal conta demo, porque havia uma regra com assíncrono por todo o lado.

Fórum sobre negociação, sistemas de negociação automatizados e teste de estratégias de negociação

Bugs, bugs, perguntas

fxsaber, 2018.02.14 08:58

Toda a sequência de eventos da OnTradeTransaction vem após a conclusão do OrderSend.

EA

void OnTradeTransaction ( const MqlTradeTransaction &Trans, const MqlTradeRequest&, const MqlTradeResult& )
{ 
  static bool FirstRun = true;  
  static ulong StartTime;
  
  if (FirstRun)
  {
    StartTime = GetMicrosecondCount();
    
    FirstRun = false;
  }

  Print(EnumToString(Trans.type));
  Print((GetMicrosecondCount() - StartTime) / 1000);    
}

Envio manual de uma ordem comercial.

Diário de Bordo

2018.02.14 09:41:46.671 '8854170': instant sell 1.00 EURUSD at 1.23673
2018.02.14 09:41:46.853 '8854170': accepted instant sell 1.00 EURUSD at 1.23673
2018.02.14 09:41:46.853 '8854170': deal #192088422 sell 1.00 EURUSD at 1.23673 done (based on order #208541700)
2018.02.14 09:41:46.853 '8854170': order #208541700 sell 1.00 / 1.00 EURUSD at 1.23673 done in 190.608 ms


Resultado do Expert Advisor

2018.02.14 09:41:46.853 TRADE_TRANSACTION_ORDER_ADD
2018.02.14 09:41:46.853 0
2018.02.14 09:41:46.853 TRADE_TRANSACTION_DEAL_ADD
2018.02.14 09:41:46.853 1
2018.02.14 09:41:46.853 TRADE_TRANSACTION_ORDER_DELETE
2018.02.14 09:41:46.853 1
2018.02.14 09:41:46.853 TRADE_TRANSACTION_HISTORY_ADD
2018.02.14 09:41:46.853 2
2018.02.14 09:41:46.853 TRADE_TRANSACTION_REQUEST
2018.02.14 09:41:46.853 2


Podemos ver perfeitamente pela coluna de tempo e pelos dados numéricos da EA que a duração da execução da ordem de negociação não tem efeito na sequência de eventos da OnTradeTransaction. Toda a assíncronia vai para o inferno! Conseguiram estragar tudo tão mal. Construir 1755.

Por exemplo, quando a ordem de mercado OrderSendAsync é colocada no Terminal, a ordem de mercado não aparece nem por um momento. Talvez os desenvolvedores tenham decidido fazer isso para acelerar um pouco as coisas.

 

Fórum sobre negociação, sistemas de negociação automatizados e testes de estratégia de negociação

Discussão sobre o artigo "Visualizando a otimização da estratégia comercial no MetaTrader 5".

fxsaber, 2018.02.22 08:39

No modo frame, OnInit, OnDeinit, OnTick, OnTrade, OnTradeTransaction e OnTimer são ignorados. Apenas o OnChartEvent funciona.

Claro que, devido à excepção OnChartEvent, requer uma verificação obrigatória para a bandeira do modo de enquadramento.

Razão: