라이브러리: 온틱멀티 - 페이지 3

 
Stanislav Korotky #:

미래를 미리 내다보는 것은 불가능합니다. 왜냐하면 시간 X에 여러 심볼에 대한 틱이 존재한다면, 한 도구에서 첫 번째 이벤트가 발생할 때 나머지 심볼들(이벤트가 아직 대기열에 있는 심볼들)에는 다음 틱이 아닌 이전 틱이 표시되기 때문입니다 (예시에서처럼, 00:04는 00:05 이전이지, 이후가 아닙니다).

동기화를 위해서는 코드 내에서 알고리즘적으로 이를 보장해야 합니다. 예를 들어, OnTick 핸들러에서 거래를 시작하기 전에 관련된 모든 종목의 틱 시간을 조회해야 합니다. 하지만 원칙적으로, 틱(바나 분이 아닌)을 기반으로 한 차익거래라면, 특정 종목의 틱이 실제로 몇 초 동안 누락될 수 있기 때문에 신뢰할 수 있는 동기화를 구현하기는 어렵습니다.

모든 것은 상대적입니다. 어떤 종목에서는 지연이 발생하고, 다른 종목에서는 데이터가 미리 표시되기도 합니다.

거기서는 모든 것이 불안정하지만, 디버거에서는 거의 빈 OnTick을 사용해도 모든 것이 동기화되어 있습니다.

테스트를 위해 바를 틱 단위로 변환하여 커미션과 스프레드를 정상적으로 시뮬레이션해야만 합니다.

이 작업은 커스텀 테스터의 계산 결과가 MT와 일치하도록 하기 위해 OnTick에서 수행해야 했습니다.

   int size=ArraySize(T);
   if(size==0) return;
   datetime dt1=(datetime)SymbolInfoInteger(name1,SYMBOL_TIME);
   datetime dt2=(datetime)SymbolInfoInteger(name2,SYMBOL_TIME);
   while(sh1<size && T[sh1]<dt1) sh1++;
   while(sh2<size && T[sh2]<dt2) sh2++;
   while(sh1<size && T[sh1]==dt1)
     {if(D1[sh1]>0)  Buy(name1);
      if(D1[sh1]<0) Sell(name1);
      if(D1[sh1]==0) Close(name1);
      sh1++;
     }
   while(sh2<size && T[sh2]==dt2)
     {if(D2[sh2]>0)  Buy(name2,D2[sh2]);
      if(D2[sh2]<0) Sell(name2,fabs(D2[sh2]));
      if(D2[sh2]==0) Close(name2);
      sh2++;
     }
 
Stanislav Korotky #:

동기화를 위해서는 코드 내에서 알고리즘적으로 이를 구현해야 합니다. 예를 들어, OnTick 핸들러에서 거래를 시작하기 전에 관련된 모든 심볼에 대한 틱 시간을 조회해야 합니다.

하지만 이 방법으로는 OnTick 내에서 현재 시간을 가진 틱의 대기열이 끝났다는 것을 파악하기 어려울 것 같습니다. 아마도 밀리초 단위의 OnTimer를 사용하는 것만이 해결책이 될 것입니다.

 
Rorschach #:

모든 것은 상대적입니다. 어떤 도구에서는 뒤처지는 현상이 나타나고, 다른 도구에서는 앞서가는 현상이 나타납니다.

현재 시간(테스터의 시간)이 있어야만, 이를 기준으로 ‘미래를 내다본다’는 용어를 사용할 수 있습니다. 현재 시간이 X이고, 두 상품에 대해 각각 시점 X-1과 X-2에 해당하는 틱이 있다면, 이것이 마지막으로 알려진 최신 틱이므로 알고리즘은 이를 기반으로 계산해야 합니다. 만약 시점 X-2에서 누군가가 X-1과 X에 대한 틱을 계산하려고 시도했다면, 이는 미래를 내다보는 것이었을 것입니다. 하지만 기술적으로 테스터는 이를 허용하지 않습니다.
 
fxsaber #:

이 방법으로는 OnTick에서 현재 시간을 가진 틱의 대기열이 끝났다는 것을 파악할 수 없을 것 같습니다. 아마도 밀리초 단위의 OnTimer만이 도움이 될 것입니다.

시간에 따른 if 조건문을 어떻게 작성하느냐에 따라 달라집니다. >=가 아닌 >를 엄격하게 적용해야 하며, 조건이 트리거된 원인이 된 틱은 계산에서 제외해야 합니다. 타이머를 사용할 때도 마찬가지입니다.
 
Stanislav Korotky #:
if 문에서 시간 조건을 어떻게 작성하느냐에 따라 달라집니다. >=가 아닌 >를 엄격하게 사용해야 하며, 조건이 충족되게 한 틱은 계산에서 제외해야 합니다.
이해가 안 가네요.
 
Stanislav Korotky #:
타이머를 사용해도 같은 결과가 나올 겁니다.
그쪽이 더 간단해요.
 
fxsaber #:
이해가 안 가네요.

대략적으로 말하자면, 밀리초 단위(초 단위도 마찬가지)의 시간 식별 정확도로 보면:

// TODO: ArrayResize(lookback, <기호 수>)
MqlTick lookback[];

void OnTickMulti(const string &symbol, const uint &index)
{
   static MqlTick t[1];
   static long timeCurrentMsc;
   
   SymbolInfoTick(symbol, t[0]);
   
   if(t[0].time_msc > timeCurrentMsc)
   {
      if(!timeCurrentMsc) // 아주 처음은 아니므로, 이것은 새로운 밀리초입니다
      {
         // TODO: 분석 및 매매에 lookback[] ticks 사용
         // 현재 틱은 아직 포함되지 않았는데, 이는 다음 밀리초의 데이터이기 때문이다
         // ...
      }
      timeCurrentMsc = t[0].time_msc;
   }

   // 분석이 완료된 후에야 레지스트리를 새로운 타임스탬프로 업데이트합니다
   lookback[index] = t[0];
}

하지만 (Rorschach를 위해) 다시 한 번 강조하자면, 이처럼 미세한 간격에 따른 동기화는 환상에 불과합니다. 특정 상품의 티커가 몇 초 동안 표시되지 않을 수 있으며, 그럴 경우 해당 상품의 실시간 가격은 실제로 “구식”이 될 수 있습니다. 만약 누군가에게 모든 가격이 동일한 [밀리]초에 기록되는 것이 중요하다면, 제시된 코드 조각(주석 처리된 분석 블록)에서 틱 시간의 일치 여부를 추가로 확인하고, 이 조건이 충족될 때만 매매해야 합니다.

 
Stanislav Korotky #:

대략적으로, 밀리초 단위까지 정확한 시간 식별(초 단위의 경우도 마찬가지):

이러한 방법으로는 모든 심볼의 틱이 최신 상태임을 보장할 수 없습니다. 오직 밀리초 단위의 OnTimer를 통해서만 가능합니다.
 
fxsaber #:
이러한 방법으로는 모든 종목의 틱 데이터가 최신 상태임을 보장할 수 없습니다. 오직 밀리초 단위의 OnTimer를 통해서만 가능합니다.
‘최신성’이란 무엇을 의미하는 것입니까(이 방법은 모든 상품에 대해 마지막으로 알려진 틱을 반환하는데, 만약 그 점을 말씀하시는 것이라면 CopyTicks를 사용할 수 있습니다)? 그리고 OnTimer가 어떻게 다른 결과를 내놓을 수 있습니까?
 

Stanislav Korotky #:
Что подразумевается под актуальностью (этот метод отдает последние известные тики по всем инструментам)?

마지막으로 알려진 시간을 기준으로 한 틱이 더 이상 발생하지 않습니다.

그런데 OnTimer는 어떻게 다른 결과를 내겠습니까?

밀리초 단위의 OnTimer는 이 타이머 이벤트 이전에 모든 틱이 지나갔음을 보장합니다. 즉, 모든 심볼에 대해 틱이 최신 상태입니다.