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

 

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

Bugs, bugs, perguntas

fxsaber, 2016.07.19 12:41

De que serve ter oENUM_DEAL_PROPERTY_INTEGER::DEAL_TICKET se o único local para o aplicar é o HistoryDealGetInteger(TicketDeal, DEAL_TICKET)?

Pelo exemplo de ORDER_TICKET a idéia deve ser clara.

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

OrderCloseTime () em MQL5?

fxsaber, 2018.07.18 03:51

datetime OrderCloseTime( const ulong Ticket )
{
  return((HistoryOrderGetInteger(Ticket, ORDER_TICKET) == Ticket) || HistoryOrderSelect(Ticket) ? (datetime)HistoryOrderGetInteger(Ticket, ORDER_TIME_DONE) : 0);
}

Assim podemos verificar se a tabela do histórico atual, previamente gerada através da função HistorySelect, contém o registro que precisamos. O mesmo se aplica ao DEAL_TICKET.

 

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

Salvar nível de preço da posição através de compensação (é possível?)

fxsaber, 2018.07.17 20:45

// Возвращает цену открытия выбранной позиции без учета клиринга
double GetSummaryPositionPrice()
{
  double TotalVolume = 0;
  double TotalDealPrice = 0;
  
  if (HistorySelectByPosition(PositionGetInteger(POSITION_IDENTIFIER)))
  {
    const int DealsTotal = HistoryDealsTotal();
    
    for (int i = 0; i < DealsTotal; i++)
    {
      const ulong DealTicket = HistoryDealGetTicket(i);
      
      if (HistoryDealGetInteger(DealTicket, DEAL_ORDER))
      {
        const double DealVolume = (HistoryDealGetInteger(DealTicket, DEAL_TYPE) ? -1 : 1) * HistoryDealGetDouble(DealTicket, DEAL_VOLUME);
        const double DealPrice = HistoryDealGetDouble(DealTicket, DEAL_PRICE);
  
        if (TotalVolume * DealVolume >= 0)
          TotalDealPrice = (TotalDealPrice * TotalVolume + DealPrice * DealVolume) / (TotalVolume + DealVolume);
        else if (MathAbs(DealVolume) - MathAbs(TotalVolume) > 0.005)
          TotalDealPrice = DealPrice;
          
        TotalVolume += DealVolume;
      }      
    }
  }
  
  return(TotalDealPrice);
}
 

Nem todos sabem que a função GetMicrosecondCount, ao contrário da GetTickCount, está ligada à hora local do computador. Isto significa que se esta hora mudar (por exemplo, devido à sincronização com a hora da Internet), os valores da GetMicrosecondCount também mudarão por um valor correspondente.Isto deve ser tido em conta se esta função for usada para medir intervalos de tempo; na verdade, não deve ser usada para este fim. GetTickCount, por outro lado, não tem estes problemas.

Como demonstração, você pode executar este código e mudar o tempo do computador enquanto ele está rodando.

  datetime time= TimeLocal();
  ulong    microsec= GetMicrosecondCount();
  uint     ticks= GetTickCount();
  
  while(!IsStopped())
  {
    Comment(int(TimeLocal()-time),"   ",(GetMicrosecondCount()-microsec)/1000000,"   ",(GetTickCount()-ticks)/1000);
    Sleep(10);
  }
 
Alexey Navoykov:

Talvez nem todos saibam que a função GetMicrosecondCount, ao contrário da GetTickCount, está ligada à hora local do computador.

Eu não sabia, obrigado!

 

Uma variante da função GetTickCount que evita transbordamentos (desde que o intervalo entre chamadas para a função não exceda 50 dias)

ulong GetTickCountLong()
{
  static ulong sum=0;
  static uint  lasttickcount=0;
  uint tickcount= GetTickCount();
  if (tickcount<lasttickcount) sum+=0x100000000;
  lasttickcount= tickcount;
  return sum + tickcount;
}
 
Alexey Navoykov:

Pode não ser conhecido que a função GetMicrosecondCount, ao contrário da GetTickCount, esteja ligada à hora local do computador. Isto significa que se esta hora mudar (por exemplo, devido à sincronização com a hora da Internet), os valores da GetMicrosecondCount também mudarão por um valor correspondente.Isto deve ser tido em conta se esta função for usada para medir intervalos de tempo; na verdade, não deve ser usada para este fim. GetTickCount, por outro lado, não tem estes problemas.

Para demonstrar isso, você pode executar esse código e alterar o tempo do computador durante a execução do código.

Bem, este é um bug que os desenvolvedores devem corrigir. A função então não se encaixa na descrição:

Функция GetMicrosecondCount() возвращает количество микросекунд, прошедших с момента начала работы MQL5-программы.
O valor desta função em comparação com GetTickCount é microssegundos, não milissegundos (1000 vezes maior precisão). É também não insuflável.
É por isso que não é muito correcto falar sobre a sua substituibilidade.
 
Alexey Navoykov:

Nem todos sabem que a função GetMicrosecondCount, ao contrário da GetTickCount, está ligada à hora local do computador. Isto significa que se esta hora mudar (por exemplo, devido à sincronização com a hora da Internet), os valores da GetMicrosecondCount também mudarão por um valor correspondente.Isto deve ser tido em conta se esta função for usada para medir intervalos de tempo; na verdade, não deve ser usada para este fim. GetTickCount, por outro lado, não tem estes problemas.

Para demonstrar isso, você pode executar esse código e mudar o tempo do computador enquanto ele está rodando.

Mais uma observação importante - daí decorre que é absolutamente inadequado usar a função GetTickCount em vez de GetMicrosecondCount.
Acho que será uma surpresa para muitas pessoas.

Examinando a operação de um simples roteiro:

void OnStart()
  {
   uint i=GetTickCount();
   uint i0=GetTickCount();
   while(i==i0) i0=GetTickCount(); 
   
   int N1=1;
   ulong t1=GetMicrosecondCount();
   uint i1=GetTickCount();
   uint i2=GetTickCount();
   while(i1==i2) { i2=GetTickCount(); N1++;}
   t1=GetMicrosecondCount()-t1;
   
   ulong t=GetMicrosecondCount();
   ulong t0=GetMicrosecondCount();
   while(t==t0) t0=GetMicrosecondCount(); 
   int N2=1;
   ulong t2=GetMicrosecondCount();
   ulong t3=GetMicrosecondCount();
   while(t2==t3) { t3=GetMicrosecondCount(); N2++;}
   ulong t4=t3-t2;

   Print("1 значение в милисекундах:  " +(string)i1+", следующее значение   "+ (string)i2 + ", разница - " +(string)t1 + 
   " микросекунд, время выполнения функции GetTickCount (одного прохода цикла) = " +DoubleToString((double)t1*1000.0/N1,3)+ " наносекунды");
   
   Print("1 значение в микросекундах: " +(string)t2+", следующее значение   "+ (string)t3 + ", разница - " +(string)t4 + 
   " микросекунд, время выполнения функции GetMicrosecondCount (одного прохода цикла) = " +DoubleToString((double)t4*1000.0/N2,3)+ " наносекунды");
  }

O resultado do trabalho:

2018.07.27 00:23:02.261 TestTimeCount   1 значение в милисекундах:  25225093, следующее значение   25225109, разница - 15663 микросекунд, время выполнения функции GetTickCount (одного прохода цикла) = 2.323 наносекунды
2018.07.27 00:23:02.261 TestTimeCount   1 значение в микросекундах: 20247, следующее значение   20248, разница - 1 микросекунд, время выполнения функции GetMicrosecondCount (одного прохода цикла) = 33.333 наносекунды
2018.07.27 00:23:03.590 TestTimeCount   1 значение в милисекундах:  25226421, следующее значение   25226437, разница - 15586 микросекунд, время выполнения функции GetTickCount (одного прохода цикла) = 2.324 наносекунды
2018.07.27 00:23:03.590 TestTimeCount   1 значение в микросекундах: 22835, следующее значение   22836, разница - 1 микросекунд, время выполнения функции GetMicrosecondCount (одного прохода цикла) = 30.303 наносекунды
2018.07.27 00:23:04.920 TestTimeCount   1 значение в милисекундах:  25227750, следующее значение   25227765, разница - 15657 микросекунд, время выполнения функции GetTickCount (одного прохода цикла) = 2.309 наносекунды
2018.07.27 00:23:04.920 TestTimeCount   1 значение в микросекундах: 23701, следующее значение   23702, разница - 1 микросекунд, время выполнения функции GetMicrosecondCount (одного прохода цикла) = 27.027 наносекунды

podemos tirar as seguintes conclusões:

  • O valor da função GetTickCount() muda a cada 15,625milissegundos(1/64 de segundo, 64=2^6), enquanto o valor da função GetMicrosecondCount() muda a cada micro segundo. Isso significa que a função GetMicrosecondCount é 15625 vezes mais precisa do que GetTickCount, e não 1000.
  • mas a função GetTickCount() é aproximadamente 12-15 vezes mais rápida do que GetMicrosecondCount().
 
Nikolai Semko:

Bem, então, este é um bug que os desenvolvedores fariam bem em consertar. Porque então a função não corresponde à descrição:

O valor desta função em comparação com GetTickCount é microssegundos, não milissegundos(1000 vezes mais preciso). Também é não insuflável.
É por isso que não é muito correcto falar sobre a sua substituibilidade.

Se você medir o tempo de execução de algumas seções do programa, as flutuações de desempenho do sistema nivelam toda essa precisão e há um erro em milissegundos ou mesmo dezenas de milissegundos. Se você medir segmentos muito pequenos com duração inferior a 1 milissegundo, então qual é o ponto. A proporção de erro de medição será muito alta.

 
Alexey Navoykov:

Eu ainda não vi nenhum uso prático de microssegundos. Se você medir o tempo de execução de algumas seções do programa, as flutuações de desempenho do sistema irão nivelar toda essa precisão, e o erro está em milissegundos, ou mesmo dezenas de milissegundos. Se você medir segmentos muito pequenos com duração inferior a 1 milissegundo, então qual é o ponto. O erro de medição será muito alto.

  1. ver o meu post anterior
  2. Eu tenho muitos exemplos com o uso prático de microssegundos.

 
Nikolai Semko:

Outra observação importante sugere que o uso da função GetTickCount em vez de GetMicrosecondCount é bastante inapropriado.
Acho que vai ser uma surpresa para muitos programadores.

Examinando a operação de um simples roteiro:

as seguintes conclusões podem ser tiradas:

  • O valor da função GetTickCount () muda a cada 15,6 milissegundos em vez de a cada milissegundo, enquanto o valor da função GetMicrosecondCount() muda a cada micro segundo. Isso significa que GetMicrosecondCount é 15600 vezes mais preciso do que GetTickCount, não 1000.
  • mas GetTickCount() é aproximadamente 12-15 vezes mais rápido do que GetMicrosecondCount().

O argumento significativo

Razão: