[SERVICE DESK] 타이머에서 시니어 TF의 시간을 가져오는 동안 오류가 발생했습니다! - 페이지 7

 
Ihor Herasko :

그렇습니다. OnInit()에서는 결과를 확인하지 않고 필요한 TF를 호출하기만 하면 되고(거기에 의존할 수 없음) 이미 OnCalculate에서 IsTFDataReady() 함수를 호출합니다. 요청된 모든 TF에 대해 true가 반환되는 즉시 표시기 알고리즘 실행을 시작할 수 있습니다.

알겠습니다. 해결되었습니다. 그러나 명시적으로 문서를 추가해야 합니다. 그렇지 않으면 빠른 타이머로 인해 개발자가 많은 질문을 하게 됩니다.

 
Ihor Herasko :

일반적으로 터미널 연결 의 존재가 중요한 어떤 종류의 작업이 해결되고 있습니까? 내가 이해하기로는 지표는 데이터 시각화 도구입니다. 사용 가능한 데이터입니다. 새로운 데이터가 들어오면 시각화를 업데이트합니다. 그것에서 데이터의 관련성 확인이 필요하지 않아야합니다. 이것은 터미널의 작업입니다.

작업은 가능한 한 빨리 이전 TF의 데이터를 가져오는 것입니다. Vitaly Gorbunov 는 IsConnected()에 대해 상기시켰습니다.

 
Alexey Kozitsyn :

글쎄, e-may ... 우리는 이미이 분석 단계를 통과했습니다. 자신의 로그 보기:

하위 시퀀스. 먼저 연결을 확인해보자. 연결이 설정되면 시간이 생깁니다. 설명해주세요 도대체 왜 에러 4066이 먼저 리턴된 다음 리턴되지 않는지!? 마지막 호출 이후 20ms 동안 무엇이 변경되었습니까?

오류 4066은 데이터가 없고 업데이트 요청이 전송되었음을 나타냅니다.

요청이 전송되면 다른 요청이 전송되지 않으므로 4066 오류가 발생하지 않습니다. 이것은 이미 여러 번 논의되었습니다.

표시기에서 타이머를 시작하는 이유는 무엇입니까? 그래서 리텔. MT4에서 표시기는 프런트 엔드 스레드에서 작동한다는 것을 이해해야 합니다. 모든 Windows 메시지는 인터페이스 스트림을 통과합니다.

 
Slava :

오류 4066은 데이터가 없고 업데이트 요청이 전송되었음을 나타냅니다.

요청이 전송되면 다른 요청이 전송되지 않으므로 오류 4066이 발생하지 않습니다. 이것은 이미 여러 번 논의되었습니다.

표시기에서 타이머를 시작하는 이유는 무엇입니까? 그래서 리텔. MT4에서 표시기는 프런트 엔드 스레드에서 작동한다는 것을 이해해야 합니다. 모든 Windows 메시지는 인터페이스 스트림을 통과합니다.

토론에 참여해주셔서 기쁩니다.

나는 포럼의 첫날이 아니며 포럼의 첫날이 아닌 여러 사람들이 여기에서 이야기했습니다. 아무도 다음과 같이 말하지 않았습니다.

요청이 전송되면 다른 요청이 전송되지 않으므로 오류 4066이 발생하지 않습니다. 이것은 이미 여러 번 논의되었습니다.

감사합니다. 매뉴얼에서 이것을 보고 싶습니다. OnTick()/OnCalculate() 이벤트가 도착할 때만 오류가 "설정"된 것으로 나타났습니까?

표시기에서 타이머를 시작하는 이유는 무엇입니까? 그래서 리텔.

여러 문자에서 데이터를 가져와야 합니다. 최대한 빨리. 불행히도 MT4와 MT5는 어떤 기호에 대한 견적 도착 이벤트 수신을 구현하지 않으므로(이러한 업데이트를 구독하는 것은 불가능합니다) 유일한 방법은 (내가 아는 한) 타이머에서 필요한 기호를 폴링하는 것입니다.

MT4에서 표시기는 프런트 엔드 스레드에서 작동한다는 것을 이해해야 합니다. 모든 Windows 메시지는 인터페이스 스트림을 통과합니다.

좋아, 가자, 그럼 어떡하지? 이것이 왜 나쁜지 / 좋은지 / 그것이 타이머 작업에 어떤 영향을 미치는지 더 자세히 설명해 주시겠습니까?
 

그것은 여러 번 논의되었습니다. "오류 4066" 쿼리당 12페이지

그리고 OnInit에서 요청을 보내고 OnCalculate에서 분석하도록 올바르게 조언되었습니다.

밀리초 타이머는 무엇 을 위한 것입니까? 당신은 당신의 행동으로 클라이언트 터미널이 정상적으로 상승하는 것을 방지하고 있습니다. 타이머를 방해하는 것은 Windows 메시지가 아니지만 타이머가 모든 사람을 방해하고 있습니다. 다시 한 번: MT4 클라이언트 터미널의 표시기는 인터페이스 스트림에서 작동합니다.

 
Slava :

그것은 여러 번 논의되었습니다. "오류 4066" 쿼리당 12페이지

알겠습니다. 감사합니다. 그러나 OnCalculate() 또는 OnTick() 작업에는 문제가 없으며 문제는 OnTimer()에 있습니다. 그리고 "오류 4066 타이머" 요청의 경우 이 분기의 결과만 떨어집니다.

그리고 OnInit에서 요청을 보내고 OnCalculate에서 분석하도록 올바르게 조언되었습니다.

나는 조언을 들었지만 이것이 문서에 기록되지 않은 타이머 작업의 기능을 무효화하지는 않습니다.

밀리초 타이머는 무엇을 위한 것입니까? 당신은 당신의 행동으로 클라이언트 터미널이 정상적으로 상승하는 것을 방지하고 있습니다. 타이머를 방해하는 것은 Windows 메시지가 아니지만 타이머가 모든 사람을 방해하고 있습니다. 다시 한 번: MT4 클라이언트 터미널의 표시기는 인터페이스 스트림에서 작동합니다.

다시 한 번, 밀리초 타이머를 사용하여 가능한 한 빨리 몇 명의 문자로부터 정보를 얻습니다! 저것들. 알고리즘은 다음과 같습니다. 표시기가 로드되고 가능한 한 빨리 더 높은 시간 프레임의 데이터를 수신한 다음 밀리초 타이머에서 필요한 기호의 입찰가를 모니터링합니다. 타이머가 아닌 모니터링 문제를 어떻게든 해결할 수 있을까요?

여기에 쓰여진 모든 것을 요약해 보겠습니다 . 내가 틀렸다면 정정해 주세요.

1. 작업: 타이머를 통해 여러 기호의 따옴표 가져오기:

구현: 고주파 타이머로 작업할 때 터미널을 로드할 때 OnCalculate() 함수에서 IsConnected()가 서버와 연결될 때까지 기다려야 합니다. 그 후에만 타이머에 액세스할 수 있습니다.

2. 작업: 표시기 시작 후 가능한 한 빨리 더 높은 기간의 데이터를 가져옵니다(표시기는 빠른 타이머를 사용함).

구현: 먼저 OnInit()에서 필요한 데이터를 요청한 다음 OnCalculate()에서 IsConnected() 연결이 설정될 때까지 기다린 다음 OnCalculate()에서도 상위 TF의 데이터를 이미 수신합니다.

3. 고주파 타이머를 실행하면 인터페이스 흐름이 느려지고 결과적으로 컴퓨터를 실행할 가치가 전혀 없습니까? 그렇다면 1번 문제를 어떻게 해결할 것인가?

4. 작업: 고위 TF의 최신 데이터를 로드합니다.

구현: 이를 위해 고주파 타이머를 사용하지 마십시오. 데이터 검색 기능은 이러한 타이머에서 작동하도록 설계되지 않았습니까? OnCalculate()만 사용합니까?

5. 오류 4066이 수신된 후 지워지면 OnCalculate()의 각 눈금에 설정됩니까?

6. MT5의 OnTimer()가 인터페이스 스레드에서 작동하지 않습니까?

@Slava 도 요점별로 답변해 주세요.

 

1. 일반적으로 OnCalculate 에 대한 두 번째 호출 에서 IsConnected 상태가 됩니다. 터미널 시작 직후 첫 번째 호출, 이력 데이터 일부 도착 시 두 번째 호출

2. 빠른 타이머를 사용하지 마십시오. 먼저, 귀하에게 허용되는 시간을 평가하십시오. 100밀리초 또는 500밀리초가 될 수 있습니다. 처음에 두 번째 타이머를 도입한 것은 우연이 아니었습니다. SetMillisecondsTimer는 3~4년 후에야 상위 5개(!)에 도입되었습니다. 그러나 상위 5개는 아키텍처가 다릅니다.

3.1. 메시지 대기열의 즉각적인 해결을 제공할 수 있는 강력한 컴퓨터를 얻으십시오.

3.2. 밀리초 타이머를 즉시 시작하지 말고 첫 번째 OnCalculate 후에만 시작하십시오. 오히려 이것은 다음과 같습니다. 첫 번째 OnCalculate에서 두 번째 타이머를 시작합니다(갑자기 연결이 끊기거나 쉬는 날). 그러면 환경을 분석할 수 있습니다. 그리고 나서야 모든 데이터가 로드되었다고 확신할 때 연결이 있고 모든 것이 정상입니다. 두 번째 타이머를 종료하고 밀리초 타이머를 시작합니다. 그런 다음 당신은 좁은 현관을 조용히 빠져나갑니다. 가장 좋은 경우(그리고 99%가 있을 것입니다) 시작 시 2초에서 5초가 손실됩니다.

4. 타이머를 가질 수 있습니다. 그러나 즉시는 아닙니다(3.2 참조). 그리고 눈에는 50밀리초면 충분하다고 생각합니다. HFT를 제공하지 않습니까?

5. 4066은 다른 사람의 기호 기간에 대한 데이터를 처음 요청할 때만 나타납니다. 같은 기간 기호 4066의 다음 요청에서 더 이상 수신하지 않습니다.

6. MT5에서 표시기는 별도의 기호 처리 스레드에서 계산됩니다. 따라서 이 기호에 둘 이상의 차트가 있는 경우(또는 이 기호에 다른 지표가 있는 경우) 속도를 늦출 수 있습니다. 그러나 여전히 이것은 인터페이스 스트림이 아닙니다.

 
Slava :

1. 일반적으로 OnCalculate 에 대한 두 번째 호출 에서 IsConnected 상태가 됩니다. 터미널 시작 직후 첫 번째 호출, 이력 데이터 일부 도착 시 두 번째 호출

2. 빠른 타이머를 사용하지 마십시오. 먼저, 귀하에게 허용되는 시간을 평가하십시오. 100밀리초 또는 500밀리초가 될 수 있습니다. 처음에 두 번째 타이머를 도입한 것은 우연이 아니었습니다. SetMillisecondsTimer는 3~4년 후에야 상위 5개(!)에 도입되었습니다. 그러나 상위 5개는 아키텍처가 다릅니다.

3.1. 메시지 대기열의 즉각적인 해결을 제공할 수 있는 강력한 컴퓨터를 얻으십시오.

3.2. 밀리초 타이머를 즉시 시작하지 말고 첫 번째 OnCalculate 후에만 시작하십시오. 오히려 이것은 다음과 같습니다. 첫 번째 OnCalculate에서 두 번째 타이머를 시작합니다(갑자기 연결이 끊기거나 쉬는 날). 그러면 환경을 분석할 수 있습니다. 그리고 나서야 모든 데이터가 로드되었다고 확신할 때 연결이 있고 모든 것이 정상입니다. 두 번째 타이머를 종료하고 밀리초 타이머를 시작합니다. 그런 다음 당신은 좁은 현관을 조용히 빠져나갑니다. 가장 좋은 경우(그리고 99%가 있을 것입니다) 시작 시 2초에서 5초가 손실됩니다.

4. 타이머를 가질 수 있습니다. 그러나 즉시는 아닙니다(3.2 참조). 그리고 눈에는 50밀리초면 충분하다고 생각합니다. HFT를 제공하지 않습니까?

5. 4066은 다른 사람의 기호 기간에 대한 데이터를 처음 요청할 때만 나타납니다. 같은 기간 기호 4066의 다음 요청에서 더 이상 수신하지 않습니다.

6. MT5에서 표시기는 별도의 기호 처리 스레드에서 계산됩니다. 따라서 이 기호에 둘 이상의 차트가 있는 경우(또는 이 기호에 다른 지표가 있는 경우) 속도를 늦출 수 있습니다. 그러나 여전히 이것은 인터페이스 스트림이 아닙니다.

1. 바로 그 일이 일어납니다.

2. 여기에 문제가 있습니다. 빠를수록 좋습니다. 그리고 평가가 이루어졌습니다. 지표는 차익 거래(보다 정확하게는 차익 거래 주제에 대한 연구)를 위해 작성되었습니다. 매 밀리초가 중요하며 견적을 빨리 받을수록 좋습니다.

3.1. 이제 시스템은 매우 강력합니다. 8600k 프로세서, SSD 터미널, 16GB DDR4 RAM;

3.2. 와... 글쎄요.

4. 중재 작업은 HFT와 관련이 있을 가능성이 큽니다.

5. 처음에는 그냥 짜증났어요. 계속해서 오류가 발생하고 데이터가 아직 준비되지 않았다는 것을 알았다면 이 분기는 존재하지 않았을 것입니다.

6. 이해했다.

자세한 답변 감사합니다.

 
Igor Makanu :

그것이 어렵지 않다면 여기에 주제의 주제가 있습니다. 이전 TF의 올바른 히스토리 로드, 여기에 표시기가 있습니다. 이전 TF의 "Masha를 가져와야 합니다." 5분 이내에 정확히 98% 올바르게 작동합니다. 이 코드에서 버그를 유발하는 2%의 "함정"이 어디 있습니까?

예, 주제에 관한 것입니다. 그리고 여기에서 결국 모든 것이 이미 분해되었습니다.

먼저, 다른 TF/심볼의 시계열에 액세스하기 전에 데이터가 사용 가능한지 확인하십시오(위의 IsTFDataReady() 함수 참조). 위의 코드에서는 CopyClose에서 얻은 결과로만 안내됩니다. 그러나 그녀는 히스토리 로딩에 대해 아무것도 모릅니다. 따라서 처음에는 데이터 가용성을 확인한 다음 요청해야 합니다.

둘째, 한 함수를 다른 함수에 대한 인수로 호출하는 것이 항상 정당화되는 것은 아닙니다. 그리고 이 경우에는 기본적으로 받아들일 수 없습니다. 결국 iBars를 호출한 결과도 확인해야 합니다. 따라서 iBars가 먼저 호출되고 결과가 캐시 및 확인된 다음 수신된 값만 CopyClose()에 전달됩니다.

셋째, CopyClose를 호출 한 후 요청된 모든 데이터가 수신되었는지 확인하지 않습니다. 결국, 이 함수는 1개 또는 2개의 막대를 반환할 수 있지만, 예를 들어 10과 같이 요청되었습니다. 저는 이러한 결과를 오류로 간주합니다.

넷째, 접근 방식 자체에 오류가 있습니다. 루프는 다른 시간 프레임의 막대로 작동한다고 가정하지만 동시에 계산은 현재 시간 프레임을 참조하는 값인 Rates_total 변수와 혼합됩니다. 한 가지 또는 다른 경우에 사용하는 두 가지 가능한 접근 방식이 있습니다.

  1. 현재 시간 프레임의 막대를 순환하고 데이터를 요청하기 전에 현재 시간 프레임의 막대 인덱스를 다른 시간 프레임의 막대 인덱스로 변환합니다(이 방법은 아래 코드에서 사용됨).
  2. 다른 TF의 막대를 순환합니다. 그러나 현재 TF가 다른 TF에 비해 더 어린 경우에 대한 추가 주기를 포함해야 합니다. 결국, 현재 시간 프레임의 여러 막대는 이전 시간 프레임의 하나의 막대에 해당합니다.

MT4에 대한 올바른 코드에 관심

나열된 4가지 사항에 비추어 보면 다음과 같습니다.

   if (!IsTFDataReady(TimeFrame))
       return 0 ;

   int i,limit;

   static int nOldBars = 0 ;
   int nBars = iBars ( _Symbol , TimeFrame);
   if (nBars == 0 )
       return 0 ;
      
   if (nOldBars == 0 || nBars - nOldBars > 1 )
   {
       if (nBars < MAPeriod)
      {
         Comment ( "Большой период МА!!!, в истории доступно " , nBars, " баров" );
         return 0 ;
      }
      
      limit = nBars - fmin (MAPeriod, nBars);
   }
   else
      limit = nBars - nOldBars;   // здесь всегда будет 0 или 1
   
   nOldBars = nBars;
   datetime dtTime = iTime ( NULL , TimeFrame, limit);
   if (dtTime == 0 )
       return 0 ;

   limit = iBarShift ( NULL , PERIOD_CURRENT , dtTime);

// основной цикл расчета индикатора
   for (i = limit; i >= 0 && ! IsStopped (); i--)
   {
       int nOtherTFBarIndex = iBarShift ( NULL , TimeFrame, time[i]);
       if (nOtherTFBarIndex < 0 || nOtherTFBarIndex >= nBars)
         continue ;
      
      BufMA[i] = iMA ( _Symbol ,TimeFrame,MAPeriod, 0 , MODE_SMA , PRICE_CLOSE ,nOtherTFBarIndex);
   }
//---
   return rates_total;

그건 그렇고, 나는 다음을 확인했습니다.


 
Ihor Herasko :

예, 주제 주제에 대해서만. 그리고 여기에서 결국 모든 것이 이미 분해되었습니다.

먼저, 다른 TF/심볼의 시계열에 액세스하기 전에 데이터가 사용 가능한지 확인하십시오(위의 IsTFDataReady() 함수 참조). 위의 코드에서는 CopyClose에서 얻은 결과로만 안내됩니다. 그러나 그녀는 히스토리 로딩에 대해 아무것도 모릅니다. 따라서 처음에는 데이터 가용성을 확인한 다음 요청해야 합니다.

둘째, 한 함수를 다른 함수에 대한 인수로 호출하는 것이 항상 정당화되는 것은 아닙니다. 그리고 이 경우에는 기본적으로 받아들일 수 없습니다. 결국 iBars를 호출한 결과도 확인해야 합니다. 따라서 iBars가 먼저 호출되고 결과가 캐시 및 확인된 다음 수신된 값만 CopyClose()에 전달됩니다.

셋째, CopyClose를 호출 한 후 요청된 모든 데이터가 수신되었는지 확인하지 않습니다. 결국, 이 함수는 1개 또는 2개의 막대를 반환할 수 있지만, 예를 들어 10과 같이 요청되었습니다. 저는 이러한 결과를 오류로 간주합니다.

넷째, 접근 방식 자체에 오류가 있습니다. 루프는 다른 시간 프레임의 막대로 작동한다고 가정하지만 동시에 계산은 현재 시간 프레임을 참조하는 값인 Rates_total 변수와 혼합됩니다. 한 가지 경우 또는 다른 경우에 사용하는 두 가지 가능한 접근 방식이 있습니다.

  1. 현재 시간 프레임의 막대를 순환하고 데이터를 요청하기 전에 현재 시간 프레임의 막대 인덱스를 다른 시간 프레임의 막대 인덱스로 변환합니다(이 방법은 아래 코드에서 사용됨).
  2. 다른 TF의 막대를 순환합니다. 그러나 현재 TF가 다른 TF에 비해 더 어린 경우에 대한 추가 주기를 포함해야 합니다. 결국, 현재 시간 프레임의 여러 막대는 이전 시간 프레임의 하나의 막대에 해당합니다.

나열된 4가지 사항에 비추어 보면 다음과 같습니다.

그건 그렇고, 나는 다음을 확인했습니다.


1. 입양! 감사하다!

2. 황금말! 예전에는 이렇게 썼는데 시간이 지나면서 간결함을 쫓는 다른 사람들의 코드를 읽다보니... "간단함은 재능의 누나"라는 말에 더 신경을 쓰게 되고.... 그리고 발생한 버그를 찾는데 시간을 보낸다.

4. "간단함은 재능의 누나"...맞아요!

3. 분석의 흥미로운 순간은 CopyClose()가 반환 하는 것입니다. 요청한 TF에 대한 .hst 파일이 없으면 CopyClose()가 2048 이상을 반환하지 않습니다. 즉, 이것이 다운로드할 수 있는 최대값입니까?

사유: