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

 

o que um começo frio leva a um caso como este.

2017.04.17 00:27:51.705 Core 1  GOLD-6.17: generate 48836 ticks in 0:00:00.000, passed to tester 48984 ticks
2017.04.17 00:27:51.705 Core 1  GOLD-9.17: generate 3184 ticks in 0:00:00.000, passed to tester 35192 ticks

e é disso que se trata.

2017.04.17 00:22:16.126 Trade   2017.04.07 10:00:00   deal performed [#247  buy 1.00 GOLD-9.17 at 0.0]

agora execute-o novamente

2017.04.17 00:31:51.123 Core 1  GOLD-6.17: passed to tester 48984 ticks
2017.04.17 00:31:51.123 Core 1  GOLD-9.17: passed to tester 35192 ticks

e o resultado do teste é completamente diferente


Arquivos anexados:
 

@Renat Fatkhullin, forneça fortes evidências de que o testador está preciso e pronto para uso.

Onde estão os critérios claros para a validação do testador? Onde está a reprodutibilidade a 100% e o acordo com o benchmark?

Onde está a argumentação de ferro das suas palavras?


Proponho que TODOS os vossos peritos em validação para o testador sejam colocados no domínio público. Sugiro pagar às pessoas que escrevem os EAs que falham ao testador. E incluí-los na base de verificação depois de ajustar o testador.


O testador está em bruto e todos o estão a provar. Por que se você quiser encontrar um bug no testador, ele é encontrado muito rapidamente? Por que 16 anos de experiência em plataformas de escrita não nos permitem escrever um testador em que possamos confiar? Cada construção tem um sentimento do testador - perplexidade.

 
kaus_bonus:

com o lançamento do build 1583 voltaremos à questão do desencontro de carrapatos na história com carrapatos no testador sobre carrapatos de baixa liquidez


O Service Desk respondeu-lhe que o problema foi resolvido? A última resposta foi "estamos a trabalhar nisso".

O problema ainda não foi resolvido. Infelizmente, nem tudo depende dos desenvolvedores, parte do problema depende da qualidade dos carrapatos no servidor de troca.

Estamos a tratar disso. Espere um pouco, por favor.

 

Aqui está um roteiro de verificação, por exemplo. Ele verifica a correspondência entre carrapatos e barras de minutos. Ainda não está optimizado. Pode ser acelerado solicitando carrapatos em uma faixa mais ampla. Mas nesta forma é mais claro, porque pede carrapatos para cada minuto separadamente.

//+------------------------------------------------------------------+
//|                                                    TestTicks.mq5 |
//|                        Copyright 2017, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property script_show_inputs
//--- input parameters
input datetime InpBeginDate=D'2017.01.01 0:00:00';
input datetime InpEndDate=D'2017.12.31 0:00:00';
input bool     InpFullLogs=false;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   MqlRates rates[];
   MqlTick  ticks[];
   datetime begin_date,end_date=(datetime)SymbolInfoInteger(_Symbol,SYMBOL_TIME);
   datetime prev_date,cur_date; 
   int      cnt_rates,cnt_ticks;
   int      i,j,book_depth=(int)SymbolInfoInteger(_Symbol,SYMBOL_TICKS_BOOKDEPTH);
   int      bars_absent=0,bars_absent_wrong=0,tickminutes_absent=0;
   int      bars_volume=0,bars_highlow=0;
   string   str_ticks=(book_depth>0)?" bid/ask":" last/volume";
//--- настроим даты
   if(InpEndDate<end_date && InpEndDate>InpBeginDate)
      end_date=InpEndDate;
   end_date/=60;
   end_date*=60;
   end_date--;
   if(InpBeginDate>=end_date)
      begin_date=end_date-24*3600;
   else
     {
      begin_date=InpBeginDate;
      begin_date/=60;
      begin_date*=60;
     }
//---
   cnt_rates=CopyRates(_Symbol,PERIOD_M1,begin_date,end_date,rates);
   Print(cnt_rates," M1 bars from ",begin_date," to ",end_date);
   for(i=0; i<cnt_rates; i++)
     {
      if(IsStopped())
        {
         Print("stopped on ",i," at ",rates[i].time);
         break;
        }
      if(i==0)
         prev_date=begin_date-60;
      else
         prev_date=rates[i-1].time;
      cur_date=rates[i].time;
      Comment(cur_date,"  ",i+1," / ",cnt_rates,"\n",tickminutes_absent,"  ",bars_volume,"  ",bars_highlow,"  ",bars_absent_wrong);
      //--- отсутствуют минутки
      if(cur_date-prev_date>60)
        {
         prev_date+=60;
         cnt_ticks=CopyTicksRange(_Symbol,ticks,COPY_TICKS_ALL,prev_date*1000,cur_date*1000-1);
         if(cnt_ticks>0)
           {
            datetime next_minute=(ticks[0].time/60+1)*60;
            int absent=1;
            int trades=0,infos=0;
            for(j=0; j<cnt_ticks; j++)
              {
               if((ticks[j].flags&(TICK_FLAG_BID|TICK_FLAG_ASK))!=0)
                  infos++;
               if((ticks[j].flags&(TICK_FLAG_LAST|TICK_FLAG_VOLUME))!=0)
                  trades++;
               //--- считаем реально отсутствующие минутки
               if(ticks[j].time>=next_minute)
                 {
                  next_minute=(ticks[j].time/60+1)*60;
                  absent++;
                 }
              }
            //--- тики не соответствуют барам
            if((book_depth<1 && infos>0) ||
               (book_depth>0 && trades>0))
              {
               Print(cnt_ticks," ticks between ",prev_date," and ",cur_date," (",absent," M1 bars absent)");
               if(InpFullLogs)
                  for(j=0; j<cnt_ticks; j++)
                    {
                     Print(ticks[j].time,".",IntegerToString(ticks[j].time_msc%1000,3,'0'),
                           " Bid=",DoubleToString(ticks[j].bid,_Digits),
                           " Ask=",DoubleToString(ticks[j].ask,_Digits),
                           " Last=",DoubleToString(ticks[j].last,_Digits),
                           " Flags=",ticks[j].flags,
                           " Volume=",ticks[j].volume);
                    }
               //--- счётчик отсутствующих баров
               bars_absent_wrong+=absent;
              }
            else
              {
               if(InpFullLogs)
                  Print(cnt_ticks,str_ticks," ticks between ",prev_date," and ",cur_date," (",absent," M1 bars)");
               //--- счётчик отсутствующих баров
               bars_absent+=absent;
              }
           }
        }
      cnt_ticks=CopyTicksRange(_Symbol,ticks,COPY_TICKS_ALL,cur_date*1000,(cur_date+60)*1000-1);
      if(cnt_ticks<=0 && !IsStopped())
        {
         if(InpFullLogs)
            Print("Ticks absent for M1 ",cur_date," last_error=",GetLastError());
         tickminutes_absent++;
        }
      //--- проверим качество тиков
      if(cnt_ticks>0)
        {
         double high_trades=0.0,low_trades=0.0;
         double high_infos=0.0,low_infos=0.0;
         int    trades=0,infos=0;
         //--- сначала соберём статистику
         for(j=0; j<cnt_ticks; j++)
           {
            if((ticks[j].flags&(TICK_FLAG_BID|TICK_FLAG_ASK))!=0)
              {
               if(ticks[j].bid>0.0)
                 {
                  if(high_infos==0.0)
                     high_infos=ticks[j].bid;
                  else
                    {
                     if(high_infos<ticks[j].bid)
                        high_infos=ticks[j].bid;
                    }
                  if(low_infos==0.0)
                     low_infos=ticks[j].bid;
                  else
                    {
                     if(low_infos>ticks[j].bid)
                        low_infos=ticks[j].bid;
                    }
                 }
               infos++;
              }
            if((ticks[j].flags&(TICK_FLAG_LAST|TICK_FLAG_VOLUME))!=0)
              {
               if(ticks[j].last>0.0)
                 {
                  if(high_trades==0.0)
                     high_trades=ticks[j].last;
                  else
                    {
                     if(high_trades<ticks[j].last)
                        high_trades=ticks[j].last;
                    }
                  if(low_trades==0.0)
                     low_trades=ticks[j].last;
                  else
                    {
                     if(low_trades>ticks[j].last)
                        low_trades=ticks[j].last;
                    }
                 }
               trades++;
              }
           }
         //--- потом сверим с минутным баром
         double point=pow(10.0,-_Digits);
         double high,low;
         int    volume;
         bool   error=false;
         //--- это биржевой инструмент?
         if(book_depth>0)
           {
            high=high_trades;
            low=low_trades;
            volume=trades;
           }
          else
           {
            high=high_infos;
            low=low_infos;
            volume=infos;
           }
         if(MathAbs(low-rates[i].low)>=point)
           {
            error=true;
            bars_highlow++;
           }
         else
           {
            if(MathAbs(high-rates[i].high)>=point)
              {
               error=true;
               bars_highlow++;
              }
            else
              {
               if(volume!=rates[i].tick_volume)
                 {
                  error=true;
                  bars_volume++;
                 }
              }
           }
         //--- надо вывести сообщение об ошибке
         if(error && InpFullLogs)
            Print(rates[i].time," ticks (",DoubleToString(high,_Digits)," ",DoubleToString(low,_Digits)," ",volume,
                  ") mismatch with M1 bar (",DoubleToString(rates[i].high,_Digits)," ",DoubleToString(rates[i].low,_Digits)," ",rates[i].tick_volume,")");
        }
     }
//---
   if(tickminutes_absent>0)
      Print("real ticks absent for ",tickminutes_absent," M1 bars");
   if(bars_volume>0)
      Print("tick volumes not matched for ",bars_volume," M1 bars");
   else
      Print("all the tick volumes matched for all M1 bars");
   if(bars_highlow>0)
      Print("tick prices not matched for ",bars_volume," M1 bars");
   else
      Print("all the tick prices matched for all M1 bars");
   if(bars_absent_wrong>0)
      Print(bars_absent_wrong," M1 bars absent in total while real ticks present");
//--- тут всё нормально, есть тики, которые не формируют бары, поэтому баров и не должно быть
   if(bars_absent>0 && InpFullLogs)
      Print(bars_absent," M1 bars absent while",str_ticks," ticks present");
//--- очистим коммент
   Comment("");
  }
//+------------------------------------------------------------------+
Arquivos anexados:
TestTicks.mq5  17 kb
 
Slawa:

Aqui está um roteiro de verificação, por exemplo. Ele verifica a correspondência entre carrapatos e barras de minutos. Ainda não está optimizado. Pode ser acelerado solicitando carrapatos em uma faixa mais ampla. Mas é mais claro nesta forma, porque pede carrapatos para cada minuto separadamente.

Obrigado. Uma pequena observação.
book_depth=(int)SymbolInfoInteger(_Symbol,SYMBOL_TICKS_BOOKDEPTH);
Esta não é a maneira de definir a afiliação forex/exchange - muitos forex stacks de transmissão.


Eu obtive o seguinte resultado em Metaquotes-Demo

Test2 (Si-6.17,M1)      6 M1 bars from 2017.04.17 00:00:00 to 2017.04.17 10:05:59
Test2 (Si-6.17,M1)      9 bid/ask ticks between 2017.04.17 00:00:00 and 2017.04.17 10:00:00 (9 M1 bars)
Test2 (Si-6.17,M1)      all the tick volumes matched for all M1 bars
Test2 (Si-6.17,M1)      all the tick prices matched for all M1 bars
Test2 (Si-6.17,M1)      9 M1 bars absent while bid/ask ticks present

Está tudo bem?

 
Slawa:

O departamento de serviço disse-lhe que o problema foi resolvido? A última resposta foi "está a ser investigado".

O problema ainda não foi resolvido. Infelizmente, nem tudo depende dos desenvolvedores, parte do problema depende da qualidade dos ticks carregados para o servidor de troca.

A descobrir. Por favor, espere, por favor.


Eu não me estou a queixar.

No SD, a queixa era sobre outra coisa - carrapatos inconsistentes.

e aqui mostrou um novo bug - execução no testador a 0 na primeira corrida fria, que apareceu depois de usar todos os ticks no testador.

 
kaus_bonus:


Eu não me estou a queixar.

a aplicação em SD é por outro motivo - carrapatos inconsistentes.

e aqui mostrou um novo bug - execução no testador ao preço 0 na primeira corrida fria, que apareceu depois de usar todos os ticks no testador.

Isto é do mesmo lugar. O problema com as carraças é o mesmo.

O caso que você descreve não aconteceu antes? Não.

De onde é que ele veio? No processo de resolver o problema das carraças de correspondência

 
fxsaber:
Obrigado. Uma pequena notaNão é maneira de definir a afiliação de forex/exchange - muitos transmitem forex stack.



O que tem isto a ver com o facto de a troca não ser uma troca?

se uma pilha de divisas está sendo transmitida, significa que as barras são construídas por barbatanas.

 
Slawa:

O que tem a bolsa de valores a ver com isso?

se um tumblr está a ser transmitido, significa que as barras são construídas em barbatanas.

Que flippers sobre o forex? Abra aqui a demonstração do Servidor FIBOGroup-MT5.
 
fxsaber:
O que são as flippers em forex? Abra aqui a demonstração do Servidor FIBOGroup-MT5.

Se a profundidade do mercado for transmitida, as barras são construídas com base em barbatanas, caso contrário, são construídas com base em lances

Eu entendo a sua pergunta. Ultimamente, devido à expansão da funcionalidade do tick, existem configurações - "sempre construir por barbatanas", "sempre construir por lances", "construir dependendo da tradução da pilha".

As duas primeiras configurações não são levadas em conta neste script. É calculado da "maneira antiga".