Merkmale der Sprache mql5, Feinheiten und Techniken - Seite 36

 

was ein Kaltstart in einem solchen Fall zur Folge hat.

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

und genau darum geht es.

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]

Jetzt wiederholen Sie es

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

und das Testergebnis ist völlig anders


 

@Renat Fatkhullin, liefern Sie eindeutige Beweise dafür, dass das Prüfgerät genau und einsatzbereit ist.

Wo sind die klaren Kriterien für die Validierung des Prüfers? Wo ist die 100%ige Reproduzierbarkeit und Übereinstimmung mit dem Benchmark?

Wo ist die stichhaltige Argumentation Ihrer Worte?


Ich schlage vor, dass ALLE Ihre Validierungsexperten für den Prüfer öffentlich zugänglich gemacht werden. Ich schlage vor, die Leute zu bezahlen, die die EAs schreiben, die den Tester nicht bestehen. Und nehmen Sie sie in die Checker-Basis auf, nachdem Sie das Prüfgerät optimiert haben.


Der Tester ist roh und jeder beweist es. Warum wird ein Fehler, den man im Tester finden will, so schnell gefunden? Warum erlauben uns 16 Jahre Erfahrung in der Entwicklung von Plattformen nicht, einen Tester zu schreiben, dem man vertrauen kann? Bei jedem Build hat der Tester ein Gefühl - Verwirrung.

 
kaus_bonus:

mit der Veröffentlichung von Build 1583 werden wir das Problem der Nichtübereinstimmung von Ticks in der Historie mit Ticks im Tester bei Aktien-Tickern mit geringer Liquidität erneut aufgreifen


Hat Ihnen der Service Desk geantwortet, dass das Problem gelöst wurde? Die letzte Antwort lautete: "Wir arbeiten daran".

Das Problem ist noch nicht gelöst. Leider hängt nicht alles von den Entwicklern ab, ein Teil des Problems hängt von der Qualität der Ticks auf dem Handelsserver ab.

Wir sind dabei, das zu klären. Bitte warten Sie.

 

Hier ist zum Beispiel ein Prüfskript. Sie prüft die Entsprechung zwischen Ticks und Minutenbalken. Sie ist noch nicht optimiert. Sie kann durch die Anforderung von Ticks in einem größeren Bereich beschleunigt werden. Aber in dieser Form ist es klarer, weil es für jede Minute einzeln Ticks anfordert

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

Hier ist zum Beispiel ein Prüfskript. Sie prüft die Entsprechung zwischen Ticks und Minutenbalken. Sie ist noch nicht optimiert. Sie kann durch die Anforderung von Ticks in einem größeren Bereich beschleunigt werden. In dieser Form ist sie jedoch übersichtlicher, da sie die Ticks für jede Minute einzeln abfragt.

Ich danke Ihnen. Eine kleine Anmerkung.
book_depth=(int)SymbolInfoInteger(_Symbol,SYMBOL_TICKS_BOOKDEPTH);
Dies ist nicht die Art und Weise zu definieren Forex / Exchange Zugehörigkeit - viele Broadcast Forex Stacks.


Ich habe folgendes Ergebnis auf Metaquotes-Demo erhalten

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

Ist das in Ordnung?

 
Slawa:

Hat Ihnen der Kundendienst mitgeteilt, dass das Problem behoben wurde? Die letzte Antwort lautete: "Es wird untersucht".

Das Problem ist noch nicht gelöst. Leider hängt nicht alles von den Entwicklern ab, ein Teil des Problems hängt von der Qualität der Ticks ab, die auf den Handelsserver hochgeladen werden.

Es herauszufinden. Bitte warten, bitte.


Ich beschwere mich nicht.

Bei den SD ging es um etwas anderes - inkonsistente Zecken.

und hier zeigte sich ein neuer Fehler - Ausführung im Tester bei 0 beim ersten Kaltlauf, der nach Verwendung aller Ticks im Tester erschien.

 
kaus_bonus:


Ich beschwere mich nicht.

die Anwendung in SD ist aus einem anderen Grund - inkonsistente Zecken.

und hier zeigte sich ein neuer Fehler - Ausführung im Tester zum Preis 0 beim ersten Kaltlauf, der nach Verwendung aller Ticks im Tester auftrat.

Dies ist von der gleichen Stelle. Das Problem mit den Zecken ist das gleiche.

Der von Ihnen beschriebene Fall ist noch nicht vorgekommen? Nein.

Woher kommt sie? Bei der Lösung des Problems der passenden Zecken

 
fxsaber:
Ich danke Ihnen. Eine kleine AnmerkungDas ist kein Weg, um Forex/Exchange Zugehörigkeit zu definieren - viele Broadcast Forex Stack.



Was hat das damit zu tun, dass die Börse keine Börse ist?

Wenn ein Forex-Stapel ausgestrahlt wird, bedeutet dies, dass die Balken durch Flossen gebildet werden.

 
Slawa:

Was hat die Börse damit zu tun?

Wenn ein Tumblr übertragen wird, bedeutet das, dass die Bars auf Flippern gebaut sind.

Welche Flipper auf dem Devisenmarkt? Öffnen Sie die Demo hier FIBOGroup-MT5 Server.
 
fxsaber:
Was sind die Flipper im Devisenhandel? Öffnen Sie die Demo hier FIBOGroup-MT5 Server.

Wenn die Markttiefe übermittelt wird, werden die Balken auf der Grundlage von Flippern gebildet, ansonsten auf der Grundlage von Geboten.

Ich verstehe Ihre Frage. Seit kurzem gibt es aufgrund der Erweiterung der Tick-Funktionalität Einstellungen - "immer nach Flossen bauen", "immer nach Geboten bauen", "abhängig von der Übersetzung des Stapels bauen".

Die ersten beiden Einstellungen werden in diesem Skript nicht berücksichtigt. Sie wird auf die "alte Art" berechnet.