Características del lenguaje mql5, sutilezas y técnicas - página 36

 

a lo que conduce un arranque en frío en un caso como éste.

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

y de eso 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]

ahora ejecútelo de nuevo

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

y el resultado de la prueba es completamente diferente


Archivos adjuntos:
 

@Renat Fatkhullin, proporciona pruebas sólidas de que el probador es preciso y está listo para su uso.

¿Dónde están los criterios claros de validación del probador? ¿Dónde está la reproducibilidad del 100% y la concordancia con el punto de referencia?

¿Dónde está la férrea argumentación de tus palabras?


Propongo que TODOS sus expertos en validación para el probador sean publicados en el dominio público. Sugiero que se pague a los que escriben los EAs que fallan al probador. E incluirlos en la base de comprobación después de ajustar el comprobador.


El probador está crudo y todo el mundo lo está probando. ¿Por qué si quieres encontrar un error en el probador, se encuentra muy rápidamente? ¿Por qué 16 años de experiencia en la escritura de plataformas no nos permiten escribir un probador en el que se pueda confiar? Todas las construcciones tienen una sensación del probador: el desconcierto.

 
kaus_bonus:

con el lanzamiento de la compilación 1583 volveremos a tratar el problema de la falta de coincidencia de los ticks en el historial con los ticks en el comprobador en los valores de baja liquidez


¿Le ha respondido el Servicio de Atención al Cliente que el problema se ha resuelto? La última respuesta fue "estamos trabajando en ello".

El problema aún no se ha resuelto. Por desgracia, no todo depende de los desarrolladores, parte del problema depende de la calidad de los ticks en el servidor de comercio.

Lo estamos resolviendo. Espere, por favor.

 

Aquí hay un script de comprobación, por ejemplo. Comprueba la correspondencia entre los ticks y las barras de minutos. Todavía no está optimizado. Se puede acelerar solicitando ticks en un rango más amplio. Pero en esta forma es más claro, porque pide ticks para cada minuto por separado

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

Aquí hay un script de comprobación, por ejemplo. Comprueba la correspondencia entre los ticks y las barras de minutos. Todavía no está optimizado. Se puede acelerar solicitando ticks en un rango más amplio. Pero es más claro en esta forma, porque pide ticks para cada minuto por separado.

Gracias. Una pequeña observación.
book_depth=(int)SymbolInfoInteger(_Symbol,SYMBOL_TICKS_BOOKDEPTH);
Esta no es la forma de definir la afiliación a la bolsa de valores - muchos difunden las pilas de la bolsa de valores.


He obtenido el siguiente resultado en 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á bien?

 
Slawa:

¿Te han dicho en el servicio técnico que el problema se ha solucionado? La última respuesta fue "se está investigando".

El problema aún no se ha resuelto. Por desgracia, no todo depende de los desarrolladores, parte del problema depende de la calidad de los ticks subidos al servidor de comercio.

Lo que se está haciendo. Por favor, espere, por favor.


No me quejo.

En la SD, la queja se refería a otra cosa: garrapatas incoherentes.

y aquí se mostró un nuevo error - la ejecución en el probador a 0 en la primera ejecución en frío, que apareció después de usar todos los ticks en el probador.

 
kaus_bonus:


No me quejo.

la aplicación en SD es por otra razón: garrapatas inconsistentes.

y aquí se mostró un nuevo error - la ejecución en el probador al precio 0 en la primera ejecución en frío, que apareció después de usar todos los ticks en el probador.

Esto es del mismo lugar. El problema con las garrapatas es el mismo.

¿El caso que describe no ha ocurrido antes? No.

¿De dónde viene? En el proceso de resolver el problema de la coincidencia de las garrapatas

 
fxsaber:
Gracias. Una pequeña notaEsa no es la manera de definir la afiliación a forex/cambio - muchos transmiten la pila de forex.



¿Qué tiene que ver esto con que la bolsa no sea una bolsa?

si se emite una pila de divisas, significa que las barras están construidas por aletas.

 
Slawa:

¿Qué tiene que ver la bolsa con esto?

si se emite un tumblr, significa que los bares están construidos sobre aletas.

¿Qué flippers en el forex? Abra la demo aquí FIBOGroup-MT5 Server.
 
fxsaber:
¿Qué son los flippers en el mercado de divisas? Abra la demo aquí FIBOGroup-MT5 Server.

Si se transmite la profundidad del mercado, las barras se construyen en base a los flippers, de lo contrario se construyen en base a las ofertas

Entiendo su pregunta. Últimamente, debido a la expansión de la funcionalidad de los ticks, hay ajustes - "construir siempre por aletas", "construir siempre por ofertas", "construir dependiendo de la traducción de la pila".

Los dos primeros ajustes no se tienen en cuenta en este script. Se calcula a la "vieja usanza".