이동 평균(및 기타 지표) 값과 오류의 비교

 

안녕하세요!

저는 SMA 교차점을 기반으로 Expert Advisor를 작성하고 있습니다(더 정확하게는 모든 것이 단순해 보이기 때문에 이미 작성했다고 생각했습니다). 하지만 ... 문제가 생겼습니다. EA는 다음 원칙에 따라 기능합니다. 새 막대가 나타나면 마지막 두 막대에 대한 SMA 값이 분석되며 방금 나타난 막대(끝에서 두 번째 및 끝에서 두 번째)는 계산되지 않습니다. 여기 에 설명된 대로 올바른 값을 비교합니다. 유일한 예외는 iMA가 각각 마지막 매개변수(막대 단위 오프셋) 1과 2로 호출된다는 것입니다. 다음과 같습니다(코드가 인용된 코드와 유사하게 다시 실행되는 경우).

 // берем два соседних значения Быстрой МА
double fast0= iMA ( Symbol (), Period (), 10 , 0 , MODE_SMA , PRICE_CLOSE , 1 );
double fast1= iMA ( Symbol (), Period (), 10 , 0 , MODE_SMA , PRICE_CLOSE , 2 );
 
// берем два значения Медленной МА
double slow0= iMA ( Symbol (), Period (), 20 , 0 , MODE_SMA , PRICE_CLOSE , 1 );
double slow1= iMA ( Symbol (), Period (), 20 , 0 , MODE_SMA , PRICE_CLOSE , 2 );
 
// сравниваем значения и определяем направление пересечения
if (fast0>slow0 && fast1<slow1) Print ( "Пересечение ВВЕРХ" );
if (fast0<slow0 && fast1>slow1) Print ( "Пересечение ВНИЗ" );

Expert Advisor는 이전 거래를 닫고 새 거래를 여는 원칙에 따라 교차로에 대한 신호가 있는 상태에서 원시적 형태로 작동합니다. 이 경우 물론 모든 교차점이 결정되면 트랜잭션은 항상 차례대로 진행됩니다(SELL - BUY - SELL - BUY - ...). 즉, 고문은 언제든지 단 하나의 열린 거래만 가지고 있습니다(첫 거래에 들어가기 전의 순간을 제외하고). 이것이 문제의 본질입니다... 2015년 2월 17일 01시 24분에 바에 있는 전략 테스터의 Close에 대한 1분 시간 프레임과 SMA 기간 5 및 34에서 흥미로운 상황을 포착했습니다. 이러한 특성을 가진 무빙은 바의 닫기 지점에서 정확히 교차합니다. 사진은 다음과 같습니다.

2015년 2월 17일 01:24

디버깅을 위해 정보를 표시합니다. 로그에서 위의 코드와 비교하면 다음과 같이 대응됩니다.

SMAFastCurrent = fast0

SMASlowCurrent = 느린0

SMAFastPrevious = fast1

SMASlowPrevious = 느린1 및

SMACurDifference = SMAFastCurrent - SMASlowCurrent

SMAPrevDifference = SMAFastPrevious - SMASlowPreviousс(즉 , fast0, slow0fast1, slow1 의 차이   각기).

따라서 이러한 차이의 부호가 변경되면 이는 이동 평균의 교차에 대한 신호를 의미합니다. 그러나 사실은 이 특정 예에서 더 많거나 적은 검사가 작동하지 않는다는 것입니다. 이러한 차이의 값은 로그에 표시됩니다. 빨간색 직사각형은 문제가 있는 막대(1:25에서) 다음의 차이점을 강조 표시하고 다음 막대(1:26에서)의 주황색을 강조 표시합니다. 또한 이전 막대의 SMACurDifference 값과 현재 막대의 SMAPrevDifference 값이 같아야 함은 분명합니다(현재 막대가 이전 막대가 되고 새 막대가 현재 막대를 대신함). 따라서 이동 평균의 교차가 1:24의 문제 막대 닫기에서 직접 발생하기 때문에 다음 막대(1:25에서)에서 SMAFastCurrent와 SMASlowCurrent의 값은 (대략) 같습니다. 디버거는 일반적으로 5자리 이내로 표시합니다(SMAFastCurrent = 1.13371 SMASlowCurrent = 1.13371 그림 참조). 또한 그 차이는 무한히 작지만 0은 아닙니다(SMACurDifference = 2.220446049250313e-016). 다음 막대에서 그 차이는 정확히 동일한 값으로 정확히 0이 됩니다(빨간색의 SMACurDifference와 주황색 사각형의 SMAPrevDifference 비교). 실제로, 일반적으로 겉보기에 동일한 값이 다른 차이를 제공하더라도 이러한 오류를 차단하는 방법이 명확하지 않습니다. 따라서 두 가지 질문:

1. 인접한 두 막대가 번갈아 발생하는 순간에 단순히 계산된 동일한 이동의 차이가 다른 결과를 제공하는 이유는 무엇입니까?

2. 어떤 엡실론을 도입해서 제로가 아닌 그것과 비교할까 생각했다. 그러나 이것은 일반적으로 극소수를 0과 비교하기 위해 수행됩니다. 하지만 이 극소수의 부호 변화를 결정해야 하는 경우 어떻게 해야 합니까?

물론 인접한 3개의 막대를 분석할 수도 있지만 이론적으로 종가에서 이동 평균이 서로 무한히 작은 거리에서 접촉할 가능성이 있습니다. 예, 저는 그러한 상황이 거의 발생하지 않는다는 것을 이해하지만(특히 더 많은 시간이 소요되는 경우) 여전히 발생할 수 있습니다. 그리고 어떻게든 잡아야 하고 이 경우에도 이동평균선의 교집합이 결정됩니다.

도움을 주셔서 미리 감사드립니다!

Навигатор по форуму и ответы на часто задаваемые вопросы. Настоятельно Рекомендуется к Прочтению! - MQL4 форум
  • www.mql5.com
Навигатор по форуму и ответы на часто задаваемые вопросы. Настоятельно Рекомендуется к Прочтению! - MQL4 форум
 

정규화 및 비교를 시도하십시오.

MQL4 참조(MQL5는 동일함)는 " 실제 유형 (이중, 부동)"에서 열기를 말합니다.

"... 두 실수를 같은지 비교할 수는 없습니다. 대부분의 경우 같아 보이는 두 개의 숫자가 소수점 이하 15자리 값의 차이로 인해 같지 않을 수 있습니다. 두 개의 실수를 올바르게 비교하려면 숫자,이 숫자의 정규화 된 차이를 null 값과 비교할 필요가 있습니다 .... "

"... 두 실수를 동등하게 비교하는 것은 절대적으로 권장되지 않습니다. 왜냐하면 그러한 비교는 올바르지 않기 때문입니다.

..............


같음을 위해 두 개의 실수를 비교해야 하는 경우 두 가지 다른 방법으로 이를 수행할 수 있습니다. 첫 번째 방법은 두 숫자의 차이를 비교 정확도를 지정하는 작은 값과 비교하는 것입니다.

..............


두 번째 방법은 두 실수의 정규화된 차이를 0과 비교하는 것입니다. 정규화된 숫자의 차이를 0과 비교하는 것은 쓸모가 없습니다. 정규화된 숫자를 사용한 수학 연산의 결과로 결과가 비정규화되기 때문입니다.

. ... "

 
rosomah :

정규화 및 비교를 시도하십시오.

MQL4 참조(MQL5는 동일함)는 " 실제 유형 (이중, 부동)"에서 열기를 말합니다.

"... 두 실수를 같은지 비교할 수는 없습니다. 대부분의 경우 같아 보이는 두 개의 숫자가 소수점 이하 15자리 값의 차이로 인해 같지 않을 수 있습니다. 두 개의 실수를 올바르게 비교하려면 숫자,이 숫자의 정규화 된 차이를 null 값과 비교할 필요가 있습니다 .... "

"... 그러한 비교가 올바르지 않기 때문에 서로 평등을 위해 두 개의 실수를 비교하는 것은 절대적으로 권장되지 않습니다.

..............


같음을 위해 두 개의 실수를 비교해야 하는 경우 두 가지 다른 방법으로 이를 수행할 수 있습니다. 첫 번째 방법은 두 숫자의 차이를 비교 정확도를 지정하는 작은 값과 비교하는 것입니다.

..............


두 번째 방법은 두 실수의 정규화된 차이를 0과 비교하는 것입니다. 정규화된 숫자의 차이를 0과 비교하는 것은 쓸모가 없습니다. 정규화된 숫자를 사용한 수학 연산의 결과로 결과가 비정규화되기 때문입니다.

. ... "

나는 평등을 위해 실수를 비교하는 것이 불가능하다는 것을 완벽하게 이해합니다. 내가 제공한 코드에는 평등 비교가 없습니다. 예, 여기에서는 필요하지 않습니다. 다음은 분명히 0으로 떨어질 수 있는 극소수의 부호 변화를 포착해야 하는 상황입니다. 이 경우 모든 것을 0 이상으로 비교하는 것도 어리석은 일입니다. 그리고 여기서 정규화는 훨씬 더 위험할 수 있습니다... 초기 MA 값을 어떤 수치로 정규화하는지는 명확하지 않습니다(시간 프레임이 작을수록 MA 값이 작음). 소수점 이하 상수 자릿수로 정규화하면 모든 MA 값이 정확히 0이 될 수도 있습니다. 솔직히 말해서 두 MA의 차이를 정규화하는 것이 무엇인지 잘 모르겠습니다. 값은 ...

 

gammaray :

나는 평등을 위해 실수를 비교하는 것이 불가능하다는 것을 완벽하게 이해합니다. 내가 제공한 코드에는 평등 비교가 없습니다. 예, 필수 사항은 아닙니다. 다음은 분명히 0으로 떨어질 수 있는 극소수의 부호 변화를 포착해야 하는 상황입니다. 이 경우 모든 것을 0 이상으로 비교하는 것도 어리석은 일입니다. 그리고 여기서 정규화는 훨씬 더 위험할 수 있습니다... 초기 MA 값을 어떤 수치로 정규화하는지는 명확하지 않습니다(시간 프레임이 작을수록 MA 값이 작음). 소수점 이하 상수 자릿수로 정규화하면 모든 MA 값이 정확히 0이 될 수도 있습니다. 솔직히 말해서 두 MA의 차이를 정규화하는 것이 무엇인지 잘 모르겠습니다. 값은 ...

정상화가 더 위험한 이유는 무엇입니까?

하도록 하다:

...

같음을 위해 두 개의 실수를 비교해야 하는 경우 두 가지 다른 방법으로 이를 수행할 수 있습니다 . 첫 번째 방법은 두 숫자의 차이를 비교 정확도를 지정하는 작은 값과 비교하는 것입니다.

...

두 번째 방법은 두 실수의 정규화된 차이를 0과 비교하는 것입니다. 정규화된 숫자의 차이를 0과 비교하는 것은 쓸모가 없습니다. 정규화된 숫자를 사용한 수학 연산의 결과로 결과가 비정규화되기 때문입니다.

예시:

 bool CompareDoubles( double number1, double number2)
  {
   if ( NormalizeDouble (number1-number2, 8 )== 0 ) return ( true );
   else return ( false );
  }
void OnStart ()
  {
   double d_val= 0.3 ;
   float   f_val= 0.3 ;
   if (CompareDoubles(d_val,f_val)) Print (d_val, "equals" ,f_val);
   else Print ( "Different: d_val = " , DoubleToString (d_val, 16 ),
               "  f_val = " , DoubleToString (f_val, 16 ));
// Результат: Different: d_val= 0.3000000000000000   f_val= 0.3000000119209290
  }
  • 그리고 제 개인적인 실무 경험(단순히 말하면, 제가 이중수 비교를 사용하고 지금도 사용하고 있는 프로그램 작업의 세심한 조정 횟수를 기준으로 하는 트리거 조건의 정확성 측면에서 그리 적은 수는 아닙니다. 그러한 비교에서),
무해할뿐만 아니라 그러한 비교를 고려할 수 있습니다.
 if ( NormalizeDouble (number1-number2,dig)== 0 )
if ( NormalizeDouble (number1-number2,dig)> 0 )
if ( NormalizeDouble (number1-number2,dig)< 0 )

// dig=Digits();

그러나 반대로 두 가지 방법 중 하나의 다양성은 설명서에서 알 있듯이 double 유형의 숫자를 비교하는 데 사용할 수 있습니다.

때문에 :

실수 를 서로 같은지 비교할 수 없습니다. 대부분의 경우, 겉보기에 동일한 두 숫자가 소수점 이하 15자리 값의 차이로 인해 같지 않을 수 있습니다. 두 실수를 정확하게 비교하려면 이 숫자의 정규화된 차이를 0 값과 비교할 필요가 있습니다.



P./S.: 문서의 첫 번째 방법은 원칙적으로 스스로 해결한 작업을 기반으로 하는 것을 포함하여 사용하기에 덜 편리한 것으로 판명되었습니다. 따라서 나는 첫 번째 방법에 대한 축적된 경험이 많지 않습니다.

그러나 두 번째 방법을 적용할 때(즉 , 조건 연산자의 표현에서 두 실수의 정규화된 차이를 0 값과 비교할 때) 어떤 문제도 명확하게 발생하지 않았습니다.

그러나 정규화되지 않은 숫자의 비교를 수행했다면(여기서는 첫 번째 방법을 사용하지 않고 포함함을 의미합니다.) 이중 숫자의 비교를 기반으로 한 조건의 잘못된 트리거링이 드러났습니다.

 
gammaray :

다음은 문서 의 문구입니다.

두 번째 방법은 두 실수의 정규화된 차이를 0과 비교하는 것입니다. 정규화된 숫자의 차이를 0과 비교하는 것은 쓸모가 없습니다. 정규화된 숫자를 사용한 수학 연산의 결과로 결과가 비정규화되기 때문입니다.

나를 위해 단순화 된 경우 수학 연산 (다양한 변환 포함) 중에 다음과 같은 작업을 수행해서는 안됩니다.

 // dig=Digits();

double delta= NormalizeDouble (number1-number2,dig);

if (delta> 0 )


즉, 위의 이전 게시물 에서 두 실수의 정규화 차이를 0 값으로 비교하는 예를 들었습니다. 그리고 이 게시물에서는 정규화된 숫자의 차이를 0과 비교합니다(문서에서 위 문구의 텍스트에 대한 이해에서).

간단히 말해서 이런 것입니다.

 

gammaray :

...

솔직히 말해서 두 MA 값의 차이를 정규화하면 어떤 결과를 얻을 수 있는지 잘 모르겠습니다.

P./S.: 이 질문의 경우 코드에 Print()를 잠시 넣어두면 많은 양의 데이터에 무엇이 인쇄되는지 확인할 수 있습니다. 수학 연산을 기반으로 얻은 비정규화 및 정규화(실험을 수행할 차트를 포함하여 소수점 이하 자릿수 이상) 값을 인쇄합니다. 비정규화 및 정규화 iMA 값만 포함합니다. 이는 수학 연산을 기반으로 형성되기 때문입니다.

만일을 대비하여 double 유형의 비정규화 및 정규화 값을 인쇄할 때 DoubleToString 을 사용하여 숫자 값에서 텍스트 값으로 추가 변환해야 함을 분명히 밝힙니다. DoubleToString의 소수점 이하 자릿수).

 
gammaray :

P./S.: 또한 MQL4 프로그래밍을 마스터하기 위해 작성된 계획의 예에서 수학 계산 값의 정규화가 규정되지 않거나 직접 규정되지 않을 수 있다고 믿습니다.

  • 모든 조건 형성을위한 계획의 용이성을 위해;
  • 항상 그런 것은 아니거나 모든 곳에서 정규화가 필요할 수 있는 것은 아닙니다(작업에 대해 허용 가능한 오류의 다른 수준에 사용되는 것으로 가정할 수 있다는 사실 및 이에 따라 다음과 같은 수학적 연산 결과의 다양한 추가 정규화(또는 부재) 일부 개별 작업의 소수점 이하 자릿수 );
  • 그리고/또는 기본적으로 프로그래밍을 배우는 사람이 이미 문서 에 익숙하고 질문을 명확히 하는 것을 포함하여 문서를 연구할 것이라고 가정하기 때문입니다.
이 같은.
 
더 정확하게
 // сравниваем значения и определяем направление пересечения
if (fast0>slow0 && fast1<=slow1) Print ( "Пересечение ВВЕРХ" );
if (fast0<slow0 && fast1>=slow1) Print ( "Пересечение ВНИЗ" );

어떤 의미에서 ma의 값이 같을 수 있다는 점은 고려되지 않았습니다.

сравнивать вещественные числа на равенство нельзя

다른 것에 대한 몇 가지.
 
Aleksey Lebedev :
다른 것에 대한 몇 가지.

그것은 당신이 의미하는 것과 어떤 작업 / 목적에 달려 있습니다.

따라서 이 스레드에서 게시물을 작성할 때 다음과 같이 진행했습니다.

  • 첫 번째 게시물의 스크린샷 및 질문;
  • 주제 작성자의 두 번째 게시물 (정규화의 위험에 대해),

따라서 여기에서 그리고 간단히 위의 내 게시물의 의미:

정규화를 사용하여 필요한 수준의 비교(및/또는 값 출력) 및/또는 일부 작업 및 목적에 허용되는 오류를 조정/조정하는 기능 코드에서 특정 조건을 규정할 때 의도한 위치와 방법에 따라 정확히 작동합니다. 그리고 정규화된 차이를 0과 비교하면 관계 연산 "=="을 사용하여 비교할 때 뿐만 아니라 조정/조정이 가능합니다.


P./S.: 동시에 만일의 경우를 대비하여 여기에 나열된 두 가지 중 첫 번째 방법으로 실수를 비교하는 것은 숫자의 차이를 작은 값과 비교하여 비교 수준을 조정해야 할 때 정규화를 사용하는 것보다 더 나쁘다고 부릅니다(두 번째 방법이 나에게 더 편리한 것으로 판명되었기 때문에 첫 번째 방법은 실제 적용을 위해 더 자세히 고려하지 않았습니다).

 

여기서 mql은 원칙적으로 그것과 아무 관련이 없습니다. 추상 프로그래밍 언어를 사용하십시오. 내가 제공한 이 특정 예에서 주요 문제는 동일한 막대의 이동 차이 값이 동일하지 않다는 것입니다(첫 번째 계산에서는 2e-16이고 두 번째 계산에서는 정확히 0). 이 경우 일반적으로이 교차점은 어떤 식 으로든 결정할 수 없습니다. mql로 돌아가면 정규화 는 숫자를 반올림하는 것을 의미합니다(더 정확하게는 C 바닥 함수와 유사하게 특정 부호 뒤의 모든 숫자를 단순히 버리고 소수점 뒤의 특정 부호까지만). 그렇다면 정규화할 숫자를 어떻게 결정합니까? 잘못된 숫자를 선택하면 모든 값이 항상 정확히 0으로 반올림될 수 있습니다. 따라서 여기에서 정규화는 위험하며 일반적으로 문제를 해결하지 못합니다.

Alexey Lebedev가 쓴 것에 관해서. 네, 그런 맥락에서 생각했습니다. 그러나 두 차이를 0보다 크거나 같게 비교하면 잘못된 신호를 얻을 가능성이 있습니다(예: 인접 막대 사이를 이동할 때 정확히 동일한 값이 나올 때 이론적으로 가능한 상황). 그런 다음 그 차이는 기호를 변경하지 않지만(교차로가 없음) 교차로에 대한 신호는 프로그래밍 방식으로 결정됩니다. 제안한 대로 크거나 같음에 대해 하나의 비교만 할 수 있습니다. 그러나 전체 문제는이 상황에서 계산할 때 처음에는 0 (2e-16)과 같지 않고 다음 막대에서는 이미 정확히 0이지만 이미 엄격한 비교가 있다는 것입니다.

여기에서 다른 막대에서 계산할 때 동일한 차이가 동일한 결과를 제공하지 않는 이유를 이해하는 것이 중요합니다??? 결과가 같으면 하나의 비엄격한 비교를 도입하여 문제가 항상 해결되는 것처럼 보일 것입니다.

 

gammaray :

그러나 전체 문제는이 상황에서 계산할 때 처음에는 0 (2e-16)과 같지 않고 다음 막대에서는 이미 정확히 0이지만 이미 엄격한 비교가 있다는 것입니다.

여기에서 다른 막대에서 계산할 때 동일한 차이가 동일한 결과를 제공하지 않는 이유를 이해하는 것이 중요합니다??? 결과가 같으면 하나의 비엄격한 비교를 도입하여 문제가 항상 해결되는 것처럼 보일 것입니다.

아마도 iMA 기능의 계산이 최적화되었을 것입니다. 첫 번째 값 = sum(종가)/N, 두 번째 = MA+(new close-obsolete close)/N의 이전 값.

사유: