'CopyTicks' 테스트 - 페이지 18

 
fxsaber :
테이프만 필요한 경우(COPY_TICKS_TRADE - time_msc, 마지막, 볼륨 및 플래그) 이 솔루션은 완전히 적합하며 버그가 발견되지 않았습니다.
니크롬은 맞지 않습니다! 또 다른 버그가 발견되었습니다

거래, 자동 거래 시스템 및 거래 전략 테스트에 관한 포럼

신비한 주식 표시기

fxsaber , 2016.09.27 18:32

CopyTicks의 입력이 0이 아닐 때 모든 브레이크가 작동하는 것 같습니다.

마지막 호출 이후 틱이 요청되더라도 이 모드에서 CopyTicks의 매우 비뚤어진 구현처럼 보입니다. 날아가야 할 것 같지만 그렇지 않습니다.

 
이번 주에 틱 및 DOM 업데이트 에서 많은 개선 사항이 있는 베타를 기다리십시오.
 
Renat Fatkhullin :
이번 주에 틱 및 DOM 업데이트를 개선한 베타를 기다리십시오.
1432 - 많은 버그가 해결되었습니다. 고맙습니다!
 
fxsaber :
1432 - 많은 버그가 해결되었습니다. 고맙습니다!

하지만 전부는 아닙니다.

추가된 이력을 실제 기록과 비교하면 COPY_TICKS_ALL 모드(TRADE 및 INFO - 문제 없음)에 불일치가 있습니다. 조언자

 #include <TypeToBytes.mqh> // https://www.mql5.com/ru/code/16280

string GetTickFlag( uint tickflag )
{
   string flag = "" ;

#define TICKFLAG_MACRO(A) flag += (( bool )(tickflag & TICK_FLAG_ ##A)) ? " TICK_FLAG_" + #A : "" ;
  TICKFLAG_MACRO(BID)
  TICKFLAG_MACRO(ASK)
  TICKFLAG_MACRO(LAST)
  TICKFLAG_MACRO(VOLUME)
  TICKFLAG_MACRO(BUY)
  TICKFLAG_MACRO(SELL)
#undef TICKFLAG_MACRO

   if (flag == "" )
    flag = " FLAG_UNKNOWN (" + ( string )tickflag + ")" ;
     
   return (flag);
}

#define TOSTRING(A) " " + #A + " = " + ( string )Tick.A

string TickToString( const MqlTick &Tick )
{
   return (TOSTRING(time) + "." + ( string ) IntegerToString (Tick.time_msc % 1000 , 3 , '0' ) +
         TOSTRING(bid) + TOSTRING(ask) + TOSTRING(last)+ TOSTRING(volume) + GetTickFlag(Tick.flags));
}

// Дописывает свежие тики после предыдущего запуска
int AddFreshTicks( MqlTick &Ticks[], const string Symb = NULL , const uint flags = COPY_TICKS_ALL )
{
   int Res = 0 ;
   const int Amount = ArraySize (Ticks);
  
   MqlTick NewTicks[];  
   const int NewAmount = (Amount == 0 ) ? CopyTicks ((Symb == NULL )? Symbol () : Symb, NewTicks, flags, ( ulong )( TimeCurrent () - 100) * 1000 ) :
                                         CopyTicks ((Symb == NULL )? Symbol () : Symb, NewTicks, flags, Ticks[Amount - 1 ].time_msc);
  
   if (NewAmount > 0 )
  {
     if (Amount > 0 )
    {
       // Взяли крайнее время из предыдущей истории
       const long LastTime = Ticks[Amount - 1 ].time_msc;
      
       int Count = 1 ;
      
       // Находим (Count) в предыдушей истории количество тиков со временем LastTime
       for ( int i = Amount - 2 ; i >= 0 ; i--)
      {
         if (Ticks[i].time_msc < LastTime)
           break ;
          
        Count++;
      }

       if ((Count < Amount) && (Count < NewAmount))      
        Res = ArrayCopy (Ticks, NewTicks, Amount, Count);
    }
     else
      Res = ArrayCopy (Ticks, NewTicks);
  }
  
   return (Res);
}

#define TOSTRING2(A) #A + " = " + ( string )(A) + " "

template < typename T>
bool ArrayEqual( const T &Array1[], const T &Array2[] )
{
   const int Amount = MathMin ( ArraySize (Array1), ArraySize (Array2));
   bool Res = (Amount > 0 );

   if (Res)
     for ( int i = 0 ; i < Amount; i++)
       if (_R(Array1[i]) != Array2[i]) // https://www.mql5.com/ru/code/16280
      {
         Print (TOSTRING2(i) + TOSTRING2( ArraySize (Array1)) +TOSTRING2( ArraySize (Array2)));
         Print (TOSTRING2(TickToString(Array1[i])) + "\n" + TOSTRING2(TickToString(Array2[i])) + "\n" );
        
        Res = false ;

         break ;
      }

   return (Res);
}

void OnTick ( void )
{
 static MqlTick PrevTicks[];
  
   // Дописываем свежие тики после предыдущего вызова
  AddFreshTicks(PrevTicks, _Symbol , COPY_TICKS_ALL );
  
   MqlTick Ticks[];
  
   if ( ArraySize (PrevTicks) > 0 )
  {
     // Взяли историю тиков
     Print ( CopyTicks ( _Symbol , Ticks, COPY_TICKS_ALL , PrevTicks[ 0 ].time_msc, 100000 ));
    
     // Проверка на совпадение собираемой истории с самой историей
     Print (ArrayEqual(Ticks, PrevTicks) ? "Equal" : "Not Equal" );
  }
}

결과

 2016.09 . 29 10 : 36 : 23.722 Test10 (Si- 12.16 ,M1)    Not Equal
2016.09 . 29 10 : 36 : 23.722 Test10 (Si- 12.16 ,M1)    
2016.09 . 29 10 : 36 : 23.722 Test10 (Si- 12.16 ,M1)    TickToString(Array2[i]) =  time = 2016.09 . 29 10 : 36 : 20.547 bid = 64353.0 ask = 64354.0 last = 64353.0 volume = 4 TICK_FLAG_BID 
2016.09 . 29 10 : 36 : 23.722 Test10 (Si- 12.16 ,M1)    TickToString(Array1[i]) =  time = 2016.09 . 29 10 : 36 : 20.546 bid = 64353.0 ask = 64354.0 last = 64353.0 volume = 1 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_SELL 
2016.09 . 29 10 : 36 : 23.722 Test10 (Si- 12.16 ,M1)    i = 57 ArraySize (Array1) = 59 ArraySize (Array2) = 58 
2016.09 . 29 10 : 36 : 23.722 Test10 (Si- 12.16 ,M1)     59
 
fxsaber :

하지만 전부는 아닙니다.

추가된 이력을 실제 기록과 비교하면 COPY_TICKS_ALL 모드(TRADE 및 INFO - 문제 없음)에 불일치가 있습니다. 조언자

결과

위의 코드를 강력하게 기록하고 이유를 찾았습니다. CopyTicks(> 0부터)가 가장 최근 것보다 먼저 틱을 얻으면 일부를 건너뛸 수 있습니다.

예시.

= 2016.09.29 11:05:55.564에서 틱을 요청했습니다. 응답으로 3개의 틱을 받았습니다.

 2016.09 . 29 11 : 05 : 58.724 Test10 (Si- 12.16 ,M1)     2 :  time = 2016.09 . 29 11 : 05 : 55.580 bid = 64380.0 ask = 64382.0 last = 64381.0 volume = 4 TICK_FLAG_BID TICK_FLAG_ASK
2016.09 . 29 11 : 05 : 58.724 Test10 (Si- 12.16 ,M1)     1 :  time = 2016.09 . 29 11 : 05 : 55.576 bid = 64379.0 ask = 64381.0 last = 64381.0 volume = 4 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_BUY
2016.09 . 29 11 : 05 : 58.724 Test10 (Si- 12.16 ,M1)     0 :  time = 2016.09 . 29 11 : 05 : 55.564 bid = 64379.0 ask = 64381.0 last = 64380.0 volume = 1 TICK_FLAG_BID TICK_FLAG_ASK

잠시 후 멀리서 틱 기록 을 요청하고 CopyTicks가 이전에 놓친 틱을 봅니다.

 2016.09 . 29 11 : 05 : 58.732 Test10 (Si- 12.16 ,M1)    time = 2016.09 . 29 11 : 05 : 55.579 bid = 64380.0 ask = 64382.0 last = 64381.0 volume = 16 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_BUY 

여기에 그런 버그가 있습니다!

그것은 틱 데이터베이스에 병렬 쓰기와 읽기의 일종의 충돌처럼 보입니다.

 
또 다른 버그, 이제 모든 COPY_TICKS_* 모드

진드기 이력 을 부분적으로 수집하면 실제 이력과 일치하지 않을 수 있음이 밝혀졌습니다. 고문이 그것을 보여줍니다.

 #include <TypeToBytes.mqh> // https://www.mql5.com/ru/code/16280

long LastTime = 0 ; // time_msc-время последнего тика (самого свежего), полученного из истории
int Count = 0 ;     // Количество тиков в последенем запросе, у которых time_msc == LastTime

// Возвращает следующие тики (после предыдущего вызова)
int GetFreshTicks( MqlTick &Ticks[], const uint flags = COPY_TICKS_TRADE , const uint count = 100000 )
{
   int Res = 0 ;

   MqlTick NewTicks[];
   const int NewAmount = CopyTicks ( Symbol (), NewTicks, flags, LastTime, count);

   if ((NewAmount > 0 ) && (Count < NewAmount))
  {
    Res = ArrayCopy (Ticks, NewTicks, 0 , Count);

     // Взяли крайнее время из текущей истории
    LastTime = Ticks[Res - 1 ].time_msc;
    Count = 1 ;

     // Находим (Count) в текущей истории количество тиков со временем LastTime
     for ( int i = Res - 2 ; i >= 0 ; i--)
    {
       if (Ticks[i].time_msc < LastTime)
         break ;

      Count++;
    }
  }
  
   return ( ArrayResize (Ticks, Res));
}

// Сравнение двух массивов
template < typename T>
bool ArrayEqual( const T &Array1[], const T &Array2[] )
{
   const int Amount = MathMin ( ArraySize (Array1), ArraySize (Array2));
   bool Res = (Amount > 0 );

   if (Res)
     for ( int i = 0 ; i < Amount; i++)
       if (_R(Array1[i]) != Array2[i]) // https://www.mql5.com/ru/code/16280
      {
        Res = false ;
        
         ExpertRemove ();

         break ;
      }

   return (Res);
}

void OnTick ()
{
   // возьмем тики с начала утренней сессии
  Count = 0 ;
  LastTime = ( TimeCurrent () - ( TimeCurrent () % ( 24 * 3600 ))) * 1000 ;
  
   MqlTick Ticks[];     // История, собранная по частям
   MqlTick NewTicks[]; // массив для следующей части тиков
  
   // Собираем историю по частям  
   while (GetFreshTicks(NewTicks, COPY_TICKS_TRADE , 100000 ) > 0 )
     ArrayCopy (Ticks, NewTicks, ArraySize (Ticks));
    
   if ( ArraySize (Ticks) > 0 )    
  {
     // Взяли ВСЮ историю тиков
     Print ( CopyTicks ( _Symbol , NewTicks, COPY_TICKS_TRADE , Ticks[ 0 ].time_msc, 10000000 )); // 10000000 - большое число, чтобы все выкачать.
    
     // Проверка на совпадение собранной по частям истории с самой историей
     Print (ArrayEqual(NewTicks, Ticks) ? "Equal" : "Not Equal" );
  }    
}

결과

 2016.09 . 30 16 : 02 : 54.661 Test (Si- 12.16 ,M1)      Not Equal
2016.09 . 30 16 : 02 : 54.661 Test (Si- 12.16 ,M1)       ExpertRemove () function called
2016.09 . 30 16 : 02 : 54.621 Test (Si- 12.16 ,M1)       333740
2016.09 . 30 16 : 02 : 54.121 Test (Si- 12.16 ,M1)      Equal
2016.09 . 30 16 : 02 : 54.071 Test (Si- 12.16 ,M1)       333736
2016.09 . 30 16 : 02 : 53.791 Test (Si- 12.16 ,M1)      Equal
2016.09 . 30 16 : 02 : 53.741 Test (Si- 12.16 ,M1)       333723

이 EA는 여전히 약한 버그를 보여줍니다. 나는 부분적으로 수집 된 역사에서 조각이 누락되어 몇 분 동안 지속 될 수 있음을 알았습니다. 코드의 형태로 간결하고 이해하기 쉬운 재생산만을 생각해 낸 것이 아닙니다. 그리고 어려운 배치 - 그것은 의미가 없습니다. 왜냐하면. 아무도 쳐다보지도 않을 것이다.

일반적으로 CopyTicks 버그를 물리칠 방법은 없습니다. EA는 테이프 모드(COPY_TICKS_TRADE)에서 작동합니다. 저것들. 테이프로도 작업이 불가능합니다.


 
fxsaber :
또 다른 버그, 이제 모든 COPY_TICKS_* 모드

특정 순간부터 시작하여 특정 금액(예: 고정 금액)을 모두 받으려고 시도한 적이 있습니까?

코드에서 그것은 마지막 순간부터 일정량(100000)처럼 보입니다. 그리고 N 틱만 받으면. 통과가 될까요?

나는 지금까지 나 자신이 틱을 많이 실험하지 않았다고 즉시 말해야합니다 ...

 
Alexey Kozitsyn :

특정 순간부터 시작하여 특정 금액(예: 고정 금액)을 모두 받으려고 시도한 적이 있습니까?

코드에서 그것은 마지막 순간부터 일정량(100000)처럼 보입니다. 그리고 N 틱만 받으면. 통과가 될까요?

나는 지금까지 나 자신이 틱을 많이 실험하지 않았다고 즉시 말해야합니다 ...

시험을 마친.

오늘 그들은 데모에 대한 새로운 빌드를 약속합니다. 그래서 우리가 기다리는 동안.

 
fxsaber :

시험을 마친.

오늘 그들은 데모에 대한 새로운 빌드를 약속합니다. 그래서 우리가 기다리는 동안.

CopyTicks()가 수정되기를 바랍니다.

그건 그렇고, CopyTicks()의 출현 이후 개발자들은 개발자들에게 다른 Copy...() 함수처럼 함수 오버로드를 추가하도록 요청해 왔습니다. 추가하겠다고 밝혔습니다. 그리고 침묵...

 
Alexey Kozitsyn :

그건 그렇고, CopyTicks()의 출현 이후 개발자들은 개발자들에게 다른 Copy...() 함수처럼 함수 오버로드를 추가하도록 요청해 왔습니다. 추가하겠다고 밝혔습니다. 그리고 침묵...

오버로드는 직접 추가할 수 있습니다.