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% 재현성 및 표준과의 일치는 어디에 있습니까?

그들의 말에 대한 철두철미한 논증은 어디에 있습니까?


테스터를 위한 모든 검증 전문가를 공개적으로 공개할 것을 제안합니다. 테스터에 실패한 Expert Advisors를 작성하는 사람들에게 지불하는 것이 좋습니다. 그리고 테스터를 조정한 후 검증 데이터베이스에 포함시킵니다.


테스터는 원시이며 게으르지 않은 모든 사람이 그것을 증명합니다. 테스터에서 버그를 찾으려면 매우 빨리 찾는 이유는 무엇입니까? 플랫폼 작성 분야에서 16년의 경험으로 신뢰할 수 있는 결과를 가진 테스터를 작성할 수 없는 이유는 무엇입니까? 각 빌드에는 테스터의 느낌이 하나 있습니다. 당혹감입니다.

 
kaus_bonus :

빌드 1583이 출시되면 기록의 틱 수와 틱 수 사이의 불일치 문제로 돌아가서 저유동 주식 시세의 테스터로 돌아갑니다.


서비스 데스크에서 문제가 해결되었다고 말했습니까? 마지막 대답은 "이해하다"였다.

문제가 아직 해결되지 않았습니다. 불행히도 모든 것이 개발자에게 달려있는 것은 아니며 문제의 일부는 거래 서버에 게시된 틱의 품질에 달려 있습니다.

우리는 이해한다. 기다려주세요.

 

다음은 테스트 스크립트의 예입니다. 눈금과 분 막대가 일치하는지 확인합니다. 아직 최적화되지 않았습니다. 더 넓은 범위의 틱을 요청하여 가속을 달성할 수 있습니다. 하지만 이 형식에서는 1분마다 개별적으로 틱을 요청하기 때문에 더 시각적입니다.

 //+------------------------------------------------------------------+
//|                                                    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
 
슬라바 :

다음은 테스트 스크립트의 예입니다. 눈금과 분 막대가 일치하는지 확인합니다. 아직 최적화되지 않았습니다. 더 넓은 범위의 틱을 요청하여 가속을 달성할 수 있습니다. 하지만 이 형식에서는 1분마다 개별적으로 틱을 요청하기 때문에 더 시각적입니다.

고맙습니다. 작은 메모
book_depth=( int ) SymbolInfoInteger ( _Symbol , SYMBOL_TICKS_BOOKDEPTH );
이런 식으로 forex/exchange에 속하는지 확인하는 것은 불가능합니다. 많은 사람들이 forex order book을 방송합니다.


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 :
고맙습니다. 작은 비고 이런 식으로 forex/exchange에 속하는지 확인하는 것은 불가능합니다. 많은 사람들이 forex order book을 방송합니다.



증권 거래소가 증권 거래소가 아니라 증권 거래소와 무슨 관련이 있습니까?

유리가 방송되면 바가 오리발에 따라 만들어집니다.

 
슬라바 :

증권 거래소가 증권 거래소가 아니라 증권 거래소와 무슨 관련이 있습니까?

유리가 방송되면 바가 오리발에 따라 만들어집니다.

Forex에서 오리발이란 무엇입니까? 여기에서 데모를 엽니다. FIBOGroup-MT5 서버.
 
fxsaber :
Forex에서 오리발이란 무엇입니까? 여기에서 데모를 엽니다. FIBOGroup-MT5 서버.

주문서가 방송되는 경우 바는 오리발로 제작되고, 그렇지 않으면 입찰가로 제작됩니다.

귀하의 질문을 이해했습니다. 최근에는 틱 기능 확장으로 인해 "항상 오리발로 빌드", "항상 입찰에 의해 빌드", "주문서 번역에 따라 빌드" 설정이 있습니다.

제시된 스크립트에서 처음 두 설정은 어떤 식으로든 고려되지 않습니다. "오래된" 것으로 간주