mql5语言的特点、微妙之处以及技巧 - 页 36

 

在这样的情况下,冷启动会导致什么。

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

而这正是它的意义所在。

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]

现在再次运行它

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

而测试结果却完全不同


附加的文件:
 

@Renat Fatkhullin,提供强有力的证据,证明测试器是准确的,可以使用的。

对测试员的明确验证标准在哪里?100%的可重复性和与基准的一致性在哪里?

你的话的铁证在哪里?


我建议将你们所有的测试员的验证专家都公布在公共领域。我建议向那些编写未能通过测试器的EA的人支付费用。并在调整测试器后将其纳入检查器基础。


测试器是生的,每个人都在证明它。为什么如果你想在测试器中找到一个错误,它很快就会被发现?为什么16年的编写平台的经验不允许我们编写一个可以信赖的测试器?每一个构建都有一个来自测试者的感觉--迷惑。

 
kaus_bonus:

随着Build 1583的发布,我们将回到低流动性股票的历史记录与测试器中的刻度不匹配的问题上。


服务台是否给你答复说问题已经解决了?最后的答复是 "我们正在努力"。

这个问题还没有得到解决。不幸的是,并不是一切都取决于开发人员,部分问题取决于贸易服务器上蜱虫的质量。

我们正在梳理它。请稍等。

 

例如,这里有一个检查脚本。它检查刻度线和分钟柱之间的对应关系。它还没有被优化。可以通过在更大的范围内请求蜱虫来加速它。但在这种形式下,它更清楚,因为它要求每分钟都有刻度。

//+------------------------------------------------------------------+
//|                                                    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("");
  }
//+------------------------------------------------------------------+
附加的文件:
TestTicks.mq5  17 kb
 
斯拉瓦

例如,这里有一个检查脚本。它检查刻度线和分钟柱之间的对应关系。它还没有被优化。可以通过在更大的范围内请求蜱虫来加速它。但在这种形式下,它更清楚,因为它分别要求每分钟的刻度。

谢谢你。一个小小的评论。
book_depth=(int)SymbolInfoInteger(_Symbol,SYMBOL_TICKS_BOOKDEPTH);
这不是定义外汇/交易所隶属关系的方式--许多广播外汇的堆栈。


我在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

可以吗?

 
斯拉瓦

服务部门是否告诉你,问题已经解决了?最后的回答是 "正在调查"。

这个问题还没有得到解决。不幸的是,并不是所有的事情都取决于开发人员,部分问题取决于上传到交易服务器的刻度线的质量。

想明白了。请等待,请。


我不是在抱怨。

在SD中,投诉是关于别的东西--不一致的虱子。

这里显示了一个新的错误--在第一次冷运行时,测试器中的执行值为0,这是在使用了测试器中的所有刻度后出现的。

 
kaus_bonus:


我不是在抱怨。

在SD中的应用是出于另一个原因--不一致的蜱虫。

这里显示了一个新的错误--在第一次冷运行时,在测试器中以价格0执行,这是在使用了测试器中的所有刻度后出现的。

这是来自同一个地方。蜱虫的问题也是如此。

你描述的情况以前没有发生过?没有。

它是从哪里来的?在解决蜱虫匹配问题的过程中

 
fxsaber:
谢谢你。一个小提示这不是定义外汇/交易所附属机构的方法--许多广播外汇栈。



这与交易所不是一个交易所有什么关系呢?

如果正在播放外汇堆栈,这意味着酒吧是由翅片建立的。

 
斯拉瓦

证券交易所与此有什么关系?

如果正在播放的是tumblr,这意味着酒吧是建立在flippers上的。

在外汇市场上有哪些炒家?在这里打开FIBOGroup-MT5服务器的演示。
 
fxsaber:
什么是外汇中的炒家?在这里打开FIBOGroup-MT5服务器的演示。

如果市场深度被传送,则根据炒家建立条形图,否则根据出价建立条形图。

我明白你的问题。最近,由于Tick功能的扩展,出现了一些设置--"总是按翅片构建"、"总是按出价构建 "和 "根据堆栈的翻译来构建"。

本脚本中不考虑前两项设置。它是按 "老办法 "计算的。