Caratteristiche del linguaggio mql5, sottigliezze e tecniche - pagina 36

 

a cosa porta una partenza a freddo in un caso come questo.

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 questo è il punto.

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]

ora eseguilo di nuovo

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 il risultato del test è completamente diverso


 

@Renat Fatkhullin, fornire una forte prova che il tester è accurato e pronto all'uso.

Dove sono i criteri chiari per la convalida del tester? Dov'è la riproducibilità al 100% e l'accordo con il benchmark?

Dov'è l'argomentazione ferrea delle sue parole?


Propongo che TUTTI i vostri esperti di convalida per il tester siano pubblicati nel dominio pubblico. Suggerisco di pagare le persone che scrivono gli EA che falliscono il tester. E includerli nella base di controllo dopo aver modificato il tester.


Il tester è grezzo e tutti lo stanno provando. Perché se si vuole trovare un bug nel tester, lo si trova molto rapidamente? Perché 16 anni di esperienza nella scrittura di piattaforme non ci permettono di scrivere un tester affidabile? Ogni build ha una sensazione da parte del tester: lo smarrimento.

 
kaus_bonus:

con il rilascio della build 1583 torneremo al problema della mancata corrispondenza dei tick nella storia con i tick nel tester su ticker azionari a bassa liquidità


Il Service Desk ti ha risposto che il problema è stato risolto? L'ultima risposta è stata "ci stiamo lavorando".

Il problema non è stato ancora risolto. Purtroppo, non tutto dipende dagli sviluppatori, parte del problema dipende dalla qualità dei tick sul server commerciale.

Lo stiamo risolvendo. Aspettate, per favore.

 

Ecco uno script di controllo, per esempio. Controlla la corrispondenza tra tick e barre di minuti. Non è ancora ottimizzato. Può essere accelerato richiedendo zecche in una gamma più ampia. Ma in questa forma è più chiaro, perché richiede tick per ogni minuto separatamente

//+------------------------------------------------------------------+
//|                                                    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("");
  }
//+------------------------------------------------------------------+
File:
TestTicks.mq5  17 kb
 
Slawa:

Ecco uno script di controllo, per esempio. Controlla la corrispondenza tra tick e barre di minuti. Non è ancora ottimizzato. Può essere accelerato richiedendo zecche in una gamma più ampia. Ma è più chiaro in questa forma, perché richiede tick per ogni minuto separatamente.

Grazie. Una piccola osservazione.
book_depth=(int)SymbolInfoInteger(_Symbol,SYMBOL_TICKS_BOOKDEPTH);
Questo non è il modo di definire l'affiliazione al forex/scambio - molti trasmettono pile di forex.


Ho ottenuto il seguente risultato su 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

Va bene?

 
Slawa:

Il servizio di assistenza ti ha detto che il problema è stato risolto? L'ultima risposta è stata "si sta indagando".

Il problema non è ancora stato risolto. Sfortunatamente, non tutto dipende dagli sviluppatori, parte del problema dipende dalla qualità dei tick caricati sul server commerciale.

Capire cosa fare. Per favore, aspettate, per favore.


Non mi sto lamentando.

Nella SD, il reclamo riguardava qualcos'altro: zecche incoerenti.

e qui ha mostrato un nuovo bug - esecuzione nel tester a 0 sulla prima corsa a freddo, che è apparso dopo aver utilizzato tutti i tick nel tester.

 
kaus_bonus:


Non mi sto lamentando.

l'applicazione in SD è per un altro motivo - zecche incoerenti.

e qui ha mostrato un nuovo bug - esecuzione nel tester a prezzo 0 sulla prima corsa a freddo, che è apparso dopo aver utilizzato tutti i tick nel tester.

Questo viene dallo stesso posto. Il problema delle zecche è lo stesso.

Il caso che lei descrive non è mai successo prima? No.

Da dove viene? Nel processo di risoluzione del problema della corrispondenza delle zecche

 
fxsaber:
Grazie. Una piccola notaQuesto non è un modo per definire l'affiliazione al forex/exchange - molti stanno trasmettendo forex stack.



Cosa c'entra questo con il fatto che lo scambio non è uno scambio?

se viene trasmesso un forex stack, significa che le barre sono costruite da alette.

 
Slawa:

Cosa c'entra la borsa?

se un tumblr viene trasmesso, significa che le barre sono costruite su pinne.

Quali pinne sul forex? Aprite il demo qui FIBOGroup-MT5 Server.
 
fxsaber:
Cosa sono i flipper nel forex? Aprite il demo qui FIBOGroup-MT5 Server.

Se la profondità del mercato è trasmessa, le barre sono costruite in base alle pinne, altrimenti sono costruite in base alle offerte

Capisco la sua domanda. Di recente, a causa dell'espansione delle funzionalità di spunta, ci sono impostazioni - "costruisci sempre in base alle pinne", "costruisci sempre in base alle offerte", "costruisci in base alla traduzione dello stack".

Le prime due impostazioni non sono prese in considerazione in questo script. È calcolato alla "vecchia maniera".

Motivazione: