English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
인디케이터의 경제적 계산 원칙

인디케이터의 경제적 계산 원칙

MetaTrader 5지표 | 5 7월 2021, 15:52
86 0
Nikolay Kositsin
Nikolay Kositsin

소개

사람들의 실제 활동의 한 부분 또는 다른 부분에서 자원을 보존한다는 아이디어는 아마도 인간 개발과 발전의 길에서 가장 중요하고 시급한 주제 중 하나 일 것입니다. 이와 관련하여 MQL5의 프로그래밍도 예외는 아닙니다. 물론 작업의 범위가 시각적 거래로만 제한된다면 프로그래밍의 많은 결함이 눈에 띄지 않을 수 있습니다.

그러나 자동화된 거래와 관련된 모든 것은 처음에는 최대한 경제적인 코드 작성이 필요합니다. 그렇지 않으면 거래 로봇의 테스트 및 최적화 프로세스가 오랜 기간에 걸쳐 확장 될 수있어 사실상 완료될 때까지 기다릴 수 없습니다. 이런 상황에서 가치있는 무언가를 창조한다는 생각은 꽤 의구심이 들어 보이죠.

따라서 거래 전략의 구현을 시작하기 전에 Expert Advisors의 최적화 및 테스트 시간에 영향을 미치는 프로그래밍 세부 사항에 더 익숙해지는 것이 좋습니다. 그리고 대부분의 Expert Advisors는 코드에 사용자 인디케이터에 대한 호출을 포함하고 있기 때문에 먼저 시작해야 합니다.

일반적으로 인디케이터를 구성 할 때 염두에 두어야 하는 관련 사항이 많지 않으므로 각 항목을 순서대로 검토하는 것이 가장 논리적입니다.

아직 계산되지 않은 각 인디케이터 눈금에 대한 재계산, 즉, 기존 인디케이터에서 새로 나타난 바 부분입니다.

RSI, ADX, ATR, CCI 등과 같은 고전적 인디케이터의 핵심은 닫힌 바에서 이러한 인디케이터의 계산을 한 번만 수행할 수 있고 그 후에는 새로 등장하는 바에서만 계산을 수행 할 수 있다는 것입니다. 유일한 예외는 현재 열린 바로, 이 바가 닫힐 때까지 각 틱에서 계산이 반복적으로 수행됩니다.

계산되지 않은 바에서 인디케이터를 계산하는 것이 합리적인지 여부를 확인하는 가장 쉬운 방법은 전략 테스터에서 이러한 (최적화 된) 인디케이터를 실행 한 결과를 모든 바에서 계산된 인디케이터와 항상 비교하는 것입니다 (최적화되지 않음).

이것은 꽤 쉽게 이루어집니다. OnInit() 및 OnTick()의 ​​빈 함수를 사용하여 Expert Advisor가 생성됩니다. 필요한 것은 최적화 또는 최적화되지 않은 인디케이터의 필수 버전에 대한 Expert Advisor에 호출을 작성하고 두 경우 모두 해당 전문가의 테스터에서 실행 한 결과에 감탄하는 것뿐입니다. 예를 들어, 내 글 "초보자를위한 MQL5의 사용자 인디케이터"에서 인디케이터 SMA.mq5를 가져 오는데 저는 여기서 라인을 바꾸겠습니다.  

   if (prev_calculated == 0) // if this is the first start, then make a recalculation of all existing bars
    first = MAPeriod - 1 + begin;
   else first = prev_calculated - 1; // on all subsequent starts, make calculations only on newly appeared bars

온 (on) 

   first = MAPeriod -  1  + Begin;  / / On all ticks the bars are being recalculated 

그 결과 최적화되지 않은 프로그래밍 코드 버전 (SMA !!!!!!. mq5)는 원본과 달리 각 틱에서 모든 값을 다시 계산합니다. 엄밀히 말해서 두 경우의 전문가 코드 버전은 거의 동일하므로 그중 하나만 제공하겠습니다 (SMA_Test.mq5).

//+------------------------------------------------------------------+
//|                                                     SMA_Test.mq5 |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
int Handle;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//----+
   //----+ Obtaining the indicator handle
   Handle = iCustom(Symbol(), 0, "SMA");
   if (Handle == INVALID_HANDLE)
     Print(" Not able to obtain the indicator handle SMA");
//----+
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//----+
    //--- Release the indicator handle
    IndicatorRelease(Handle);
//----+   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//----+
   double SMA[1];
   //----+ Using the indicator handle, copy the values of the indicator 
                   // buffer in a specially prepared for this statistical array
   CopyBuffer(Handle, 0, 0, 1, SMA);
//----+
  }
//+------------------------------------------------------------------+

이제 테스트를 시작할 수 있습니다. 이 글의 모든 테스트에서 우리는 가능한 한 현실에 가까운 바의 변경 시뮬레이션 모드를 사용할 것입니다- "모든 틱 (Every tick)"!

그림 1 Expert Advisor SMA_Test 테스트 구성 

테스터에서 최적화 된 인디케이터를 실행한 결과는 다음과 같습니다.

그림 2 Expert Advisor SMA_Test 테스트 결과 

빨간색은 테스트가 통과된 시간을 나타냅니다. 이것이 너무 많다고 말할 수 없습니다! 그러나 테스트 완료를 위해 인디케이터 SMA !!!!!!. mq5 우리는 아주 오래 기다려야했습니다!

그림 3 Expert Advisor SMA 테스트 결과 !!!!!! _ 테스트 

기본적으로 이 경우 테스트 처리 시간은 이전 테스트와 500배 이상 차이가 납니다. 그리고 이것은 충분히 짧은 테스트 기간이 선택되었다는 사실에도 불구하고 있습니다. 하지만 Expert Advisor를 테스트 하는 동안 엄청난 계산 비용을 감당할 수 있지만 매개 변수 최적화는 잊어버리는 것이 좋습니다!

따라서 이것은 경제적으로 작성된 코드가 프로그래밍 분야의 전문가를 위한 오락일 뿐만 아니라 자신의 코드를 작성하는 데 매우 시사적인 접근이라는 사실에 대한 가장 설득력 있는 증거입니다.

인터넷에는 성능을 극대화하기 위해 개인용 컴퓨터의 가속화에 전념하는 전체 웹 사이트 Overclockers.ru가 있습니다. 이 방법의 기본 방법은 훨씬 더 비싼 컴퓨터 구성 요소를 사용하여 CPU와 RAM 메모리의 클럭 속도를 높이는 것입니다.

이 작업이 완료되면 이 오버 클럭된 CPU에 더 비싼 수냉 시스템 또는 액체 질소 프로세서에 담그는 방법이 사용됩니다. 이러한 행위의 결과로 PC 성능이 2배 또는 3배 향상됩니다.

유능하고 경제적으로 코드를 작성하면 적은 노력을 기울이면서 많은 것을 달성하는 데 도움이 될 수 있습니다. 물론 이 방법은 Celleron300A를 Core 2 Quad Q6600으로 변환 할 수는 없지만, 정상 모델 컴퓨터에서만 기대할 수 있는 방식으로 일반적인 표준 예산 PC 함수를 만들 수 있습니다!

고전적이지 않은 일부 인디케이터에서 현재 닫힌 바의 반복적인 재계산

그리고 이 프로그램 코드 최적화 방법이 모든 인디케이터에 무차별적으로 적합하다면 모든 것이 훌륭할 것입니다! 그러나 안타깝게도, 이는 사실이 아니죠. 이러한 접근 방식에서는 이미 존재하는 과거 데이터에 인디케이터를 로드하는 동안 일반적으로 한 번만 계산되기 시작하는 전체 인디케이터 그룹이 있습니다.

그리고 인디케이터를 로드 한 후 나타난 모든 바에서 그 값은 완전히 잘못된 것으로 판명됩니다. 이것이 발생하는 주된 이유는 인디케이터 코드의 일부 변수가 이전 바에서 인디케이터를 계산 한 후 동일한 변수를 가진 인디케이터에 종속되기 때문입니다. 공식적으로 다음과 같이 보일 것입니다.

                                                                                                                                                                                                                           

SomeVariable(bar) = Function(SomeVariable(bar - 1))

 

어디:

  • SomeVariable() — 일부 바에 대한 일부 변수의 값입니다.
  • 바 - 계산이 수행되는 바의 번호.

명백한 이유로 실제 코드에서 이러한 종속성은 덜 명확한 함수적 형태를 갖습니다. 그러나 이것의 본질은 예를 들어 T3 이동 (최적화되지 않은 인디케이터-T3 !!!!!!. mq5) 우리와 관련된 코드 부분은 다음과 같습니다.

   e1 = w1 * series + w2 * e1;
   e2 = w1 * e1 + w2 * e2;
   e3 = w1 * e2 + w2 * e3;
   e4 = w1 * e3 + w2 * e4;
   e5 = w1 * e4 + w2 * e5;
   e6 = w1 * e5 + w2 * e6;
   //----  
   T3 = c1 * e6 + c2 * e5 + c3 * e4 + c4 * e3;

변수 e1, e2, e3, e4, e5, e6은 정확히 이러한 함수적 의존성을 가지며, 이 코드를 사용하여 각각의 새로운 바를 한 번만 계산합니다! 그러나 유사한 계산을 통해 현재 바는 닫힐 때까지 반복적으로 건너뜁니다.

그리고 현재 바의 이러한 변수 값은 항상 변경되지만 현재 바의 경우 변경하기 전에 이전 바의 계산 후 그대로 유지되어야 합니다!

따라서 이전 바에있는 이러한 변수의 값 (현재 바에 대해)은 정적 변수에 저장되어야 하며, 변수의 두 번째 값이있는 바가 다음 변경 될 때까지 재사용되도록 전송해야 합니다. e1, e2, e3, e4, e5, e6을 다시 저장해야 합니다.

값으로 유사한 조작을 수행하는 추가 코드는 매우 간단합니다. 우선, OnCalculate() 함수 안에 값을 저장하기 위한 로컬 정적 변수를 선언해야 합니다.

   //---- declare the static variables for storing the valid values of the coefficients
   static double e1_, e2_, e3_, e4_, e5_, e6_;

그 후 새로 나온 바의 수가 0보다 큰 순간에 계산 전에 현재 바의 주기에서 변수 값을 기억합니다.

     //---- memorize the values of variables before the run on the current bar
     if (rates_total != prev_calculated && bar == rates_total - 1)
      {
       e1_ = e1;
       e2_ = e2;
       e3_ = e3;
       e4_ = e4;
       e5_ = e5;
       e6_ = e6;
      }

그리고 순환 연산자의 블록 앞에 역변환을 통해 변수 값을 복원합니다.

   //---- restore the values of the variables
   e1 = e1_;
   e2 = e2_;
   e3 = e3_;
   e4 = e4_;
   e5 = e5_;
   e6 = e6_;

당연히 계산된 계수의 시작 초기화는 OnCalculate() 함수의 첫 번째 시작에서 한 번만 수행되며 이제 초기화는 계수 자체가 아니라 해당 정적 변수에서 수행됩니다.

//---- calculating the starting number first for the cycle of recalculation of bars
   if (prev_calculated == 0) // verification of the first start of the indicator calculation
    {
     first = begin; // the starting number for calculating all of the bars
     //---- the starting initialization of calculated coefficients
     e1_ = price[first];
     e2_ = price[first];
     e3_ = price[first];
     e4_ = price[first];
     e5_ = price[first];
     e6_ = price[first];
    }

결과적으로 최종 인디케이터 T3.mq5는 가장 비용 효율적인 방식으로 계산을 시작했습니다. 모든 것이 아무것도 아니지만 유사한 함수적 의존성이 항상 그렇게 쉽게 식별될 수 있는 것은 아닙니다. 이 경우 모든 인디케이터 변수의 값을 정적 변수에 기억하고 동일한 방식으로 복원할 수 있습니다.

그리고 나중에야 우리는 어떤 변수가 실제로 복구되어야 하는지, 어떤 변수가 필요하지 않은지 알아내기 시작할 수 있습니다. 이를 위해서는 최적화되지 않은 버전과 최적화된 인디케이터 버전을 차트에 표시하고 작업을 확인하여 복구 목록에서 한 번에 하나씩 변수를 점차적으로 제거해야 합니다. 결국 우리는 정말로 복구해야 할 변수들만 남게 됩니다.

당연히, 저는 현재 바와 새로 등장하는 바에 대한 재검토가 있는 정상 인디케이터의 프로그램 코드 작업을 위해 이 버전의 논리를 제공했습니다. 다시 칠해 미래를 내다 보는 인디케이터의 경우, 이러한 인디케이터의 고유한 특성으로 인해 유사하고 매우 표준적이고 간단한 코드 최적화 방법을 만들 수 없습니다. 숙련된 Expert Advisor 저자의 대다수는 이것이 실제로 필요하지 않다고 생각합니다. 따라서 여기에서 이러한 인디케이터에 대한 자세한 분석이 완료된 것으로 간주 할 수 있습니다.

MQL5 코드를 지나치게 느리게 만들 수 있는 인디케이터 호출 함수 

작업이 완료된 것처럼 보이며, 가장 경제적인 방법으로 바를 세는 최적화된 인디케이터가 있으며, 이제 코드 줄 몇 개를 작성하고 이 인디케이터를 Expert Advisor 또는 인디케이터의 코드에 불러 와서 인디케이터 버퍼에서 계산 된 값을 얻을 수 있습니다.

그러나 이것은 이 몇 줄의 코드 뒤에 어떤 유형의 작업이 있는지 파악하지 않고는 공식적인 문제로 접근하는 것처럼 쉽지 않습니다.

MQL5의 시계열에서와 마찬가지로 사용자 및 기술 인디케이터로부터 값을 얻는 세부 사항은 데이터를 사용자 변수 배열로 복사하여 수행된다는 것입니다. 이로 인해 현재 계정에 대해 완전히 불필요한 데이터가 축적될 수 있습니다.

일부 기술 인디케이터에서 특정 데이터 수신에 대해 이 모든 것을 확인하는 가장 쉬운 방법입니다. 예를 들어, iAMA 이동을 가져와 이 기술 인디케이터를 기반으로 사용자 지정 인디케이터 AMkA를 구축 할 수 있습니다.

데이터를 복사하기 위해 첫 번째 버전의 함수 호출 CopyBuffer ()를 사용하고, 시작 포지션에 대한 요청과 복사에 필요한 요소 수를 사용합니다. AMkA 인디케이터에서 현재 바의 이동 증분은 기술 인디케이터 표준 ​​편차를 사용하여 처리된 다음 거래 신호를 얻기 위해이 증분을 처리된 총 표준 편차 값과 비교합니다.

따라서 AMkA 인디케이터 구현의 가장 간단한 경우에는 먼저 인디케이터 버퍼에 이동 증가 값 (인디케이터 dAMA)이 포함 된 인디케이터를 만들어야 합니다. 그런 다음 다른 인디케이터에서 AMA 증가가 있는 인디케이터 핸들을 사용하여 표준 편차 인디케이터로 처리 된 결과 값을 얻습니다.

유사한 인디케이터의 생성 과정은 이미 이러한 주제에 대한 다양한 글에서 자세히 검토되었으므로 잠시 멈추지 않고 다른 인디케이터의 코드에서 호출 된 인디케이터의 인디케이터 버퍼에 액세스하는 세부 정보만 분석합니다.

인터넷의 방대한 자원에서 우리는 이미 MQL5 예제의 출현을 보았습니다. 여기에서 저자는 말 그대로 인디케이터 버퍼의 전체 내용을 중간 동적 배열로 복사합니다. 그런 다음 모든 값이 순환 연산자를 사용하여 이러한 중간 배열의 최종 인디케이터 버퍼로 하나씩 전송됩니다.

문제를 해결하기 위해 이 접근 방식은 최대한 간단해 보입니다.

   if (CopyBuffer(AMA_Handle, 0, 0, rates_total, Array) <= 0) return(0);
   ArrayCopy(AMA_Buffer, Array, 0, 0, WHOLE_ARRAY);

(인디케이터 dAMA !!!!!!. mq5) 또는 이와 같이 

   if (CopyBuffer(AMA_Handle, 0, 0, rates_total, Array) <= 0) return(0);
   
   for(bar = 0; bar < rates_total; bar++)
    {
     AMA_Buffer[bar] = Array[bar];
     /*
      here is the code of indicator calculations
    */     
    }

그러나 그러한 소박한 솔루션의 가격은 얼마입니까? 첫째, 최대한 합리적인 행동 방침이 무엇인지에 대해 약간의 이해를 얻는 것이 가장 좋습니다. 우선, 중간 배열 Array []를 사용할 필요가 없으며 데이터를 인디케이터 버퍼 AMA []에 직접 복사해야 합니다.

둘째, 각 인디케이터 틱에서 다음 세 가지 경우에만 값을 복사해야 합니다.

  • 새로 등장한 바에서
  • 닫힌 바에서,
  • 현재 열린 바에서.

인디케이터 버퍼의 나머지 값은 이미 존재하며 여러 번 다시 쓰는 것은 의미가 없습니다. 

//--- calculation of the required number of copied data
   int to_copy;
   if(prev_calculated > rates_total || prev_calculated <= 0)// verification for the first start of indicator calculation
        to_copy = rates_total - begin; // calculated number of all bars
   else to_copy = rates_total - prev_calculated + 1; // calculated number of only new bars

//--- copy the reappearing data into the indicator buffer AMA_Buffer[]
   if (CopyBuffer(AMA_Handle, 0, 0, to_copy, AMA_Buffer) <= 0)
    return(0); 

 이 경우 최종 코드가 다소 복잡해지는 것은 당연한 일이지만 (Indicator dAMA.mq5) 이제 이 글의 시작 부분에서 제가 제안한 방법론을 사용하여 두 경우 모두에서 테스트를 수행하고 적절한 결론을 그려낼 수 있습니다. 이번에는 테스트 기간을 1년으로 늘리겠습니다.

그림 4 Expert Advisor dAMA_Test 테스트 구성
 

마지막으로 테스터 전략 저널의 테스트를 통과 한 후 Expert Advisor dAMA_Test를 테스트하는 데 필요한 시간을 얻습니다.

그림 5 Expert Advisor dAMA_Test 테스트 결과

43,937ms 안에 테스트를 통과 한 결과 시간은 합리적인 범위 내에 있습니다. 불행히도 Expert Advisor dAMA !!!!!! _ Test로 테스트를 통과하는 유사한 결과 시간에 대해 말할 수 없습니다.

그림 6 시험 전문가 dAMA !!!!!! _ 시험 합격 결과
  

테스트 통과 시간은 960 625ms로 이전 사례보다 20배 더 깁니다. 결론은 꽤 명백해보입니다. 코드는 불필요한 계산을 수행하지 않도록 가장 경제적인 방법으로 작성되어야 합니다!
위에서 설명한 원칙에 기반한 AMkA 인디케이터는 새로운 것을 보여주지 않으므로 이 경우에는 데이터 복사에 대한 세부 정보에 대해서만 잠시 멈출 것입니다.

//---- declaring local arrays
   double dAMA_Array[], StdDev_Array[];
//---- indexation of elements in arrays just like in time series
   ArraySetAsSeries(dAMA_Array, true);
   ArraySetAsSeries(StdDev_Array, true);

//--- calculation of the number of copied data
   int to_copy;
   if(prev_calculated > rates_total || prev_calculated <= 0)// verification of the first start of indicator calculation
        to_copy = rates_total - begin; // calculated number of all bars
   else to_copy = rates_total - prev_calculated + 1; // calculated number of only new bars
   
//--- copy the newly appeared data into the indicator buffer and local dynamic arrays
   if(CopyBuffer(dAMAHandle,   1, 0, to_copy, AMABuffer   ) <= 0) return(0);
   if(CopyBuffer(dAMAHandle,   0, 0, to_copy, dAMA_Array  ) <= 0) return(0);
   if(CopyBuffer(StdDevHandle, 0, 0, to_copy, StdDev_Array) <= 0) return(0);

이제 데이터가 중간 계산을 위해 단일 인디케이터 버퍼와 두 개의 로컬로 선언된 동적 배열로 복사된다는 점을 제외하면 모든 작업이 완전히 유사한 방식으로 수행됩니다. 

최적화를 위한 방법 중 하나로 인디케이터 내의 모든 인디케이터 계산 구현 

이 모든 것이 매우 흥미롭지만 사용자 및 기술 인디케이터의 연속 호출과 같은 복잡한 구조는 너무 의심스러워 보입니다. 그리고 그것은 어떻게든 측정되어야 합니다. 그러나 이렇게 하려면 AMkA 인디케이터의 코드를 가지고 있어도 괜찮습니다. 이 코드는 사용자 인디케이터 내에 있으며 다른 인디케이터에 대한 호출을 사용하지 않습니다.

MQL5에서 인디케이터를 작성하는 프로세스를 철저히 파악한 프로그래머에게는 이 문제에 많은 노력이 필요하지 않습니다. 먼저 사용자 인디케이터 AMA.mq5의 코드가 작성된 다음 AMkA_.mq5 인디케이터 구현을 위해 필요한 코드 요소가 여기에 추가됩니다. 사용자 배열이 AMA 인디케이터의 증분과 함께 로드되는 또 다른 2초의 큰 인디케이터 계산주기를 받습니다.

   //---- the main cycle of calculating the AMkA indicator
   for(bar = first; bar < rates_total; bar++)
    {
     //---- load the increments of the AMA indicator into the array for intermediate calculations
     for(iii = 0; iii < ama_period; iii++)
      dAMA[iii] = AMABuffer[bar - iii - 0] - AMABuffer[bar - iii - 1]; 

이 배열은 dAMA.mq5 인디케이터의 데이터를 기반으로 한 기술 인디케이터 StDev의 계산과 유사한 작업을 수행하는데 사용됩니다.

     //---- find the simple average of increments of AMA
     Sum = 0.0;
     for(iii = 0; iii < ama_period; iii++)
      Sum += dAMA[iii];
     SMAdif = Sum / ama_period;
     
     //---- find the sum of the square differences of increments and the average
     Sum = 0.0;
     for(iii = 0; iii < ama_period; iii++)
      Sum += MathPow(dAMA[iii] - SMAdif, 2);
     
     //---- determine the final value of the meansquare deviation of StDev from the increment of AMA
     StDev = MathSqrt(Sum / ama_period);

나머지 코드는 AMkA.mq5 인디케이터의 코드와 절대적으로 유사하며 특별히 관심을 갖지 않습니다. 이제 Expert Advisors AMkA__Test.mq5 및 AMkA_Test.mq5의 도움으로 인디케이터 AMkA_.mq5 및 AMkA.mq5 테스트를 시작할 수 있습니다.

AMkA_.mq5 인디케이터를 테스트하는 데 어려움이 없으며 테스트 시간이 허용 가능한 프레임 워크 내에 있습니다.

그림 7 Expert Advisor AMkA__Test를 사용하여 테스트를 통과한 결과
 

하지만 인디케이터 AMkA.mq5는 엄청나게 느렸습니다

그림 8 Expert Advisor AMkA_Test를 사용한 테스트 합격 결과
 

그 결과는 "형제 (brothers)"보다 7배나 나빴습니다. 다른 코멘트가 어떤 게 있을 수 있을까요? 결론은 꽤나 명백합니다: 여러 개의 연속적인 인디케이터 호출로 구성된 복잡한 구조를 구축하는 것은 그닥 신중한 일이 아니며 예비 테스트에만 적합합니다!

분명히 이러한 결과는 클라이언트 터미널의 테스트 버전에서 얻은 것이며 지금은 모든 것이 앞으로 어떻게 될지 말하기가 어렵습니다. 그러나 다가오는 거래 로봇 챔피언십과 관련하여 이것이 관련성이 높고 효율적인 주제라고 분명히 주장할 수 있습니다.

Expert Advisors의 인디케이터 호출 함수

인디케이터의 프로그래밍 코드에서 사용자 데이터 및 기술 인디케이터에 대한 액세스 최적화와 관련된 모든 것은 Expert Advisors 프로그램 코드의 사용자 데이터 및 기술 인디케이터에 대한 액세스 최적화에도 동일하게 적용됩니다. 이미 제시된 상황 외에도 Expert Advisor 코드에는 거래 시스템의 테스트 및 최적화에 큰 영향을 미칠 수 있는 또 다른 요소가 있습니다.

많은 Expert Advisors는 일반적으로 바의 변경 시에만 인디케이터 데이터를 처리하므로 이러한 Expert Advisors에서는 CopyBuffer () 틱마다 함수를 가져올 필요가 없습니다.

이 상황에서는 바가 변경되는 동안에만 인디케이터 버퍼에서 데이터를 가져오기 위해 Expert Advisor가 필요합니다. 따라서 인디케이터의 호출은 괄호 뒤의 블록에 위치해야 하며, 인디케이터 버퍼에서 필요한 모든 데이터가 중간을 위해 어레이에 성공적으로 복사 된 경우 바가 변경 될 때마다 중간 계산을 위해 한 번만 액세스가 허용됩니다.

이러한 필터 역할을 하는 가장 좋은 것은 현재 바가 변경된 시간에 논리 단위 (logical unit)를 반환하는 사용자 함수입니다. IsNewBar.mqh 파일에는 이 함수의 보편적인 버전이 포함되어 있습니다.

bool IsNewBar
            (
             int Number, // Number of call to the function IsNewBar in the program code of the expert Advisor
             string symbol, // The chart symbol on which the data calculation is done
             ENUM_TIMEFRAMES timeframe // Timeframe of the chart on which the data calculation is done
            )

Expert Advisor 코드에서 이 함수를 사용하면 다음과 같이 보일 수 있습니다.

    //---- declaration of a static variable - array for storing the values of the AMA indicator
    static double AMA_Array[3];

    //---- calling up the AMA indicator for copying its values into the AMA_Array array
    if (IsNewBar(0, Symbol(), 0))
     {
      CopyBuffer(AMA_Handle, 0, 1, 3, AMA_Array); 
     }

그러나 이 경우 다르게 행동하는 것이 훨씬 더 합리적입니다. 사실 CopyBuffer ()를 호출 할 때 AMA_Array [] 배열의 데이터는 복사되지 않을 수 있으며, 이 경우 복사를 위한 성공적인 옵션이 있을 때까지 각 틱에 대해 이 함수를 호출해야 하며, 해당 데이터는 필터의 특정 복잡성에 의해 구현됩니다.

   //---- declaration of a static variable - array for storing values of the AMA indicator
   static double AMA_Array[3];
    
   //---- declaration of the static variable for storing the results of copying the data from the AMA indicator
   static bool Recount;

   //---- calling up the AMA indicator for copying its values into the AMA_Array array
   if (IsNewBar(0, Symbol(), 0) || Recount)
     {
      if (CopyBuffer(AMA_Handle, 0, 1, 3, AMA_Array) < 0)
       {
        Recount = true; // attempt of data copying was unsuccessful 
        return; // exit the function OnTick()
       }
      
      //---- All operations of copying from the indicator buffers are successfully completed
           // there is no need for returning to this block until the next bar change
      Recount = false;
     }

이제 Expert Advisor의 코드에서 인디케이터 값의 복사 함수에 대한 합리적인 호출의 세부 사항이 명확해졌으므로 Expert Advisors에서 IsNewBar () 함수를 적용하여 얻을 수 있는 이점을 테스트 할 수 있습니다.

따라서 전략 테스터에서 테스트 할 수 있는 두 가지 Expert Advisors 옵션이 있는데, 첫 번째 옵션은 AMA_Test.ex5입니다. 각 틱에서 인디케이터 버퍼의 데이터를 복사합니다.

그림 9 Expert Advisor AMA_Test에 합격한 결과

두 번째 - IsNewBar_AMA_Test.mq5는 바의 변경 중에만 데이터를 복사합니다.

그림 10 Expert Advisor의 테스트에 합격한 결과 IsNewBar_AMA_Test

네! 테스트 결과는 다소 실망스럽습니다. 각 틱마다 IsNewBar () 함수를 호출하는 것이 사용자 배열의 세 셀에 데이터를 복사하는 것보다 훨씬 더 비쌉니다! 

여기에서 중요하지만 눈에 띄지 않는 인디케이터의 또 다른 부분에 주의를 기울이고 싶습니다. 사실 OnInit () 함수에서 인디케이터의 핸들을 얻으면 OnTick () 함수 내에서 이 인디케이터의 데이터를 복사하는지 여부에 관계없이 아직 계산되지 않은 현재 바에 대한 계산, 틱마다 계속 수행됩니다.

따라서 Expert Advisor가 현재 열린 바에서 계산된 인디케이터 값을 필요로 하지 않는 경우 시간 절약 측면에서 이러한 값의 계산을 비활성화하는 것이 좋습니다. 이것은 매우 쉽게 수행됩니다 - 인디케이터에서 바의 리 카운팅의 기본주기의 오른쪽 경계를 하나 줄입니다. 변경하기 전에 AMA.mq5 인디케이터의 해당 주기는 다음과 같습니다.

   //---- main cycle of indicator calculation
   for(bar = first; bar < rates_total; bar++)

그리고 변경 후 다음과 같이 보일 것입니다.  

   //---- main cycle of indicator calculation
   for(bar = first; bar < rates_total - 1; bar++)

인디케이터 AMA_Ex.mq5. 이제 이 인디케이터를 테스트 할 수 있습니다 (Expert Advisor AMA_Ex_Test.mq5).

그림 11 Expert Advisor AMA_Ex_Test에 합격한 결과 

물론 이 결과는 AMA 인디케이터 테스트 보다 21%로 나쁘지 않은데, 생각해보면 그 정도가 아니라 훨씬 나은 것일 수 있습니다.

결론

궁극적으로 프로그램 코드의 효율성은 상당히 객관적인 매개 변수입니다. 효율성을 측정하고 논리적으로 분석 할 수 있으며 특정 상황에서는 크게 증가할 수 있습니다. 이것이 수행되는 방법은 그리 복잡하지 않습니다. 필요한 일이라고는 약간의 인내심과 자동화된 거래 시스템의 수익성에 직접적인 영향을 미치는 관행 이상의 일을 하는 것입니다.

MetaQuotes 소프트웨어 사를 통해 러시아어가 번역됨.
원본 기고글: https://www.mql5.com/ru/articles/109

파일 첨부됨 |
mql5.zip (23.38 KB)
ORDER_MAGIC을 사용하여 단일 상품에서 여러 Expert Advisors와의 거래 ORDER_MAGIC을 사용하여 단일 상품에서 여러 Expert Advisors와의 거래
이 글에서는 매직 식별을 사용한 정보 코딩 문제와 다양한 Expert Advisors의 자동 거래의 분할, 조립 및 동기화에 대해 설명합니다. 이 글은 Expert Advisors와 다양한 전략의 복잡한 동기화 시스템을 구현하는 데 유용할 수 있는 가상 포지션 문제를 다루기 때문에 초보자는 물론 숙련된 거래자에게도 흥미로울 것입니다.
예시를 통해 보는 MQL5 의 OOP: 프로세싱 경고와 에러 코드 예시를 통해 보는 MQL5 의 OOP: 프로세싱 경고와 에러 코드
이 문서에서는 매매 서버 리턴 코드 작업을 위한 클래스를 생성하는 예와 MQL 프로그램 실행 중에 발생하는 모든 오류에 대해 설명합니다. 이 문서를 다 읽고나면 당신은 MQL5로 클래스나 객체를 어떻게 다뤄야하는지 알게될 것입니다. 또한 이 도구는 오류를 처리하는 데 편리한 도구이며 특정 필요에 따라 이 도구를 추가로 변경할 수 있습니다.
Google Chart API를 통해 차트를 구성하는 라이브러리 Google Chart API를 통해 차트를 구성하는 라이브러리
다양한 유형의 다이어그램 구성은 시장 상황 분석 및 거래 시스템 테스트의 필수 부분입니다. 종종 멋진 다이어그램을 구성하려면 데이터 출력을 파일로 구성해야 하며 그 후에 MS Excel과 같은 응용 프로그램에서 사용됩니다. 이건 그닥 편리하지 않고 데이터를 동적으로 업데이트하는 함수를 뺏어가기까지 합니다. Google Charts API는 서버에 특별한 요청을 보내 온라인 모드에서 차트를 만드는 수단을 제공했습니다. 이 글에서는 이러한 요청을 작성하고 Google 서버에서 차트를 가져 오는 프로세스를 자동화하려고 합니다.
MQL5에서 이동 평균 계산 성능 테스트 MQL5에서 이동 평균 계산 성능 테스트
첫 번째 이동 평균 인디케이터 생성 이후 여러 많은 인디케이터가 나타났습니다. 그들 중 다수는 유사한 평활 방법을 사용하지만 다른 이동 평균 알고리즘의 성능은 연구되지 않았습니다. 이 글에서는 MQL5에서 이동 평균을 사용하는 가능한 방법을 고려하고 성능을 비교합니다.