'CopyTicks' 테스트 - 페이지 19

 

1434 - CopyTicks에서 이미 다운로드한 1000틱을 수신하는 데 평균 1ms가 걸립니다. 천천히, 일종의.

이전에 받은 마지막 틱의 from_msc에서 TRADE0tick을 요청합니다. 나는 3개의 틱을 얻었지만 0.3 - 0.9ms 후에! - 매우 느려졌습니다.

 
fxsaber :

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

Service Desk의 매우 중요한 답변

원래 문제와 관련하여 - 다음 호출의 CopyTicks는 동일한 기간 동안 더 많은 틱을 제공할 수 있습니다.

정말이야. 문제는 bid/ask 및 last/volumes의 exchange 데이터 스트림이 이미 exchange 측에서 서로 동기화되지 않은 다른 스트림이라는 것입니다.

이 때문에 처음 매수/매도가 교환 시간 12:12:12.300에 오고, 조금 늦게 마지막/호가가 12:12:12.299에 오는 상황이 발생합니다.

따라서 마지막 틱(12:12:12.300) 이후 데이터를 요청하면 12:12:12.299에 대한 새로운 마지막을 받지 못합니다.

추신. 터미널은 시간별로 정렬된 틱을 저장하고 반환합니다. 즉, CopyTicks에 주어진 틱의 시간 순서는 항상 증가합니다.

틱 수신에는 INFO와 TRADE의 두 가지 흐름이 있습니다. ALL은 합성된 유니온(터미널 쪽에 있는 것 같습니다)이므로 이러한 사건이 발생할 수 있습니다.

그런 말이 있었던 것은 합성 때문이었다.

슬라바 :

CopyTicks 호출 후 초기 틱 레코드에는 0이 포함되지 않지만 현재 입찰가, 요청 및 요청된 시점의 마지막 값

따라서 모든 틱으로 작업할 때는 처리 대상을 명확하게 이해해야 합니다. 틱 플래그도 합성될 수 있습니다. 이러한 문제에 대한 자세한 내용을 알고 싶습니다.

테이프를 사용하면 CopyTicks가 올바르게 작동하면 이러한 문제가 발생하지 않습니다.

Help가 본격적으로 보완될 것이라고 생각합니다.

 
fxsaber :
오버로드는 직접 추가할 수 있습니다.
나도 많이 할 수 있고, 당신도 많이 할 수 있고, 다른 프로그래머들도 많이 할 수 있지만 개발자들이 모든 "스터핑"을 더 잘 알고 필요한 틱을 얻기 위한 빠른 알고리즘을 만들 수 있기를 바랍니다.
 

COPY_TICKS_TRADE 플래그로 테스트된 CopyTicks

차이가 없습니다.

 2016.10 . 03 15 : 50 : 48.507 Check_ticks (RTS- 12.16 ,M1)      History ticks = 9
2016.10 . 03 15 : 50 : 48.507 Check_ticks (RTS- 12.16 ,M1)      Dynamic ticks = 9
2016.10 . 03 15 : 50 : 48.956 Check_ticks (RTS- 12.16 ,M1)      History ticks = 11
2016.10 . 03 15 : 50 : 48.956 Check_ticks (RTS- 12.16 ,M1)      Dynamic ticks = 11
2016.10 . 03 15 : 50 : 49.184 Check_ticks (RTS- 12.16 ,M1)      History ticks = 12
2016.10 . 03 15 : 50 : 49.184 Check_ticks (RTS- 12.16 ,M1)      Dynamic ticks = 12
2016.10 . 03 15 : 50 : 49.510 Check_ticks (RTS- 12.16 ,M1)      History ticks = 14
2016.10 . 03 15 : 50 : 49.511 Check_ticks (RTS- 12.16 ,M1)      Dynamic ticks = 14
2016.10 . 03 15 : 50 : 51.568 Check_ticks (RTS- 12.16 ,M1)      History ticks = 15
2016.10 . 03 15 : 50 : 51.568 Check_ticks (RTS- 12.16 ,M1)      Dynamic ticks = 15
2016.10 . 03 15 : 50 : 51.627 Check_ticks (RTS- 12.16 ,M1)      History ticks = 16
2016.10 . 03 15 : 50 : 51.627 Check_ticks (RTS- 12.16 ,M1)      Dynamic ticks = 16
2016.10 . 03 15 : 50 : 53.143 Check_ticks (RTS- 12.16 ,M1)      History ticks = 19
2016.10 . 03 15 : 50 : 53.143 Check_ticks (RTS- 12.16 ,M1)      Dynamic ticks = 19
2016.10 . 03 15 : 50 : 54.514 Check_ticks (RTS- 12.16 ,M1)      History ticks = 27
2016.10 . 03 15 : 50 : 54.514 Check_ticks (RTS- 12.16 ,M1)      Dynamic ticks = 26
2016.10 . 03 15 : 50 : 54.542 Check_ticks (RTS- 12.16 ,M1)      History ticks = 27
2016.10 . 03 15 : 50 : 54.542 Check_ticks (RTS- 12.16 ,M1)      Dynamic ticks = 27
2016.10 . 03 15 : 50 : 54.847 Check_ticks (RTS- 12.16 ,M1)      History ticks = 30
2016.10 . 03 15 : 50 : 54.847 Check_ticks (RTS- 12.16 ,M1)      Dynamic ticks = 30
2016.10 . 03 15 : 50 : 57.052 Check_ticks (RTS- 12.16 ,M1)      History ticks = 31
2016.10 . 03 15 : 50 : 57.052 Check_ticks (RTS- 12.16 ,M1)      Dynamic ticks = 31
2016.10 . 03 15 : 50 : 57.301 Check_ticks (RTS- 12.16 ,M1)      History ticks = 32
2016.10 . 03 15 : 50 : 57.301 Check_ticks (RTS- 12.16 ,M1)      Dynamic ticks = 32
2016.10 . 03 15 : 51 : 00.498 Check_ticks (RTS- 12.16 ,M1)      History ticks = 44
2016.10 . 03 15 : 51 : 00.498 Check_ticks (RTS- 12.16 ,M1)      Dynamic ticks = 44
파일:
Check_ticks.mq5  41 kb
 
prostotrader :

COPY_TICKS_TRADE 플래그로 테스트된 CopyTicks

차이가 없습니다.

 
fxsaber :

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

예시.

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

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

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

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

1434 - TRADE 틱에 대한 동일한 버그. 재현 전문가 고문
 #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 (Res);
}

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));
}

#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" );
         Print (TOSTRING2(TickToString(Array1[i - 1 ])) + "\n" + TOSTRING2(TickToString(Array2[i - 1 ])) + "\n" );
        
        Res = false ;
        
         ExpertRemove ();

         break ;
      }

   return (Res);
}

void OnTick ( void )
{
   static bool FirstRun = true ;
   static MqlTick PrevTicks[];
  
   if (FirstRun)
  {
    LastTime = TimeCurrent () * 1000 ;
    Count = 0 ;
    
    FirstRun = false ;
  }
  
   MqlTick Ticks[];

   // Взяли свеженькие тики
   const int Amount = GetFreshTicks(Ticks);

   ArrayCopy (PrevTicks, Ticks, ArraySize (PrevTicks));
  
   if ( ArraySize (PrevTicks) > 0 )    
  {
     MqlTick NewTicks[];
    
     // Взяли историю тиков
     Print ( CopyTicks ( _Symbol , NewTicks, COPY_TICKS_TRADE , PrevTicks[ 0 ].time_msc, 1000000 ));
    
     // Проверка на совпадение собираемой истории с самой историей
     Print (ArrayEqual(NewTicks, PrevTicks) ? "Equal" : "Not Equal" );
  }  
}
결과
 2016.10 . 04 10 : 36 : 17.743 Test13 (RTS- 12.16 ,M1)   Not Equal
2016.10 . 04 10 : 36 : 17.743 Test13 (RTS- 12.16 ,M1)   ExpertRemove () function called
2016.10 . 04 10 : 36 : 17.743 Test13 (RTS- 12.16 ,M1)   
2016.10 . 04 10 : 36 : 17.743 Test13 (RTS- 12.16 ,M1)   TickToString(Array2[i- 1 ]) =  time = 2016.10 . 04 10 : 37 : 07.791 bid = 99680.0 ask = 99690.0 last = 99690.0 volume = 4 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_BUY 
2016.10 . 04 10 : 36 : 17.743 Test13 (RTS- 12.16 ,M1)   TickToString(Array1[i- 1 ]) =  time = 2016.10 . 04 10 : 37 : 07.791 bid = 99680.0 ask = 99690.0 last = 99690.0 volume = 4 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_BUY 
2016.10 . 04 10 : 36 : 17.743 Test13 (RTS- 12.16 ,M1)   
2016.10 . 04 10 : 36 : 17.743 Test13 (RTS- 12.16 ,M1)   TickToString(Array2[i]) =  time = 2016.10 . 04 10 : 37 : 07.791 bid = 99680.0 ask = 99690.0 last = 99690.0 volume = 4 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_BUY 
2016.10 . 04 10 : 36 : 17.743 Test13 (RTS- 12.16 ,M1)   TickToString(Array1[i]) =  time = 2016.10 . 04 10 : 37 : 08.773 bid = 99690.0 ask = 99700.0 last = 99690.0 volume = 1 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_SELL 
2016.10 . 04 10 : 36 : 17.743 Test13 (RTS- 12.16 ,M1)   i = 144 ArraySize (Array1) = 145 ArraySize (Array2) = 146 
2016.10 . 04 10 : 36 : 17.743 Test13 (RTS- 12.16 ,M1)   145
2016.10 . 04 10 : 36 : 16.768 Test13 (RTS- 12.16 ,M1)   Equal

수집된 TRADE-flow의 실시간 틱 히스토리에는 2016.10.04 10:37:08.773 시간의 틱이 포함되지 않았으며, 이는 나중에 히스토리에 푸시되었습니다.

이것은 위의 말 과 다소 일치하지 않습니다. 문제는 합성된 ALL-flow뿐만 아니라 직접-TRADE에도 있습니다.

 
fxsaber :
1434 - TRADE 틱에 대한 동일한 버그. 재현 전문가 고문
죄송합니다. 이것은 가장 무례한 관절입니다.
 
fxsaber :

1434 - CopyTicks에서 이미 다운로드한 1000틱을 수신하는 데 평균 1ms가 걸립니다. 천천히, 일종의.

이전에 받은 마지막 틱의 from_msc에서 TRADE0tick을 요청합니다. 나는 3개의 틱을 얻었지만 0.3 - 0.9ms 후에! - 매우 느려졌습니다.

실제! 어쨌든 속도를 높인다?

 

이 기회를 빌어 CopyTicks로 작업한 개발자들에게 감사 인사를 전하고 싶습니다!

CopyTicks가 절대적으로 올바르게 작동한다고 주장하지는 않겠지만 테이프로 작업을 아주 명확하게 설정하고 CopyTicks 자체를 더 깊이 이해할 수 있었습니다.

바퀴를 재발명하지 않기 위해 여기여기 에서 테이프를 기반으로 눈금 표시기를 작성하는 디버깅된 예를 볼 수 있습니다.

 
from_time에서 to_time으로 틱을 가져오기 위한 최적(성능) 알고리즘은 무엇입니까?