English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
추가 버퍼를 사용하지 않고 중간 계산을 위한 평균 가격 시리즈

추가 버퍼를 사용하지 않고 중간 계산을 위한 평균 가격 시리즈

MetaTrader 5지표 | 5 7월 2021, 17:02
113 0
Nikolay Kositsin
Nikolay Kositsin

소개

저의 글 "지표의 경제적 계산 원칙" 코드에서 사용자 지정 또는 기술 지표의 모든 단일 호출이 다음과 같은 것은 아니라는 사실을 입증하는 합리적으로 설득력 있는 테스트를 수행했습니다. 개발된 지표에서 중간 계산을 수행하는 가장 최적의 방법입니다.

최종 실행 속도는 인디케이터에 중간 계산용 코드를 배치할 경우에 비해 훨씬 느리게 보일 수 있습니다.

이러한 종류의 코드 작성 방법은 간단하다면 매우 매력적일 것입니다. 사실, 중간 계산 결과를 저장하는데 사용되는 추가 버퍼를 설명하는 코드의 심각한 복잡성으로 보입니다.

다양한 중간 계산에도 불구하고 가장 필요한 것은 평균화 알고리즘이 다릅니다. 대부분의 경우 이러한 코드 작성 작업을 상당히 단순화하는 심플하고도 유니버스한 사용자 지정 함수를 사용할 수 있습니다. 이러한 함수를 만들고 작업하는 과정은 이 글에서 설명합니다.


1. 하나의 막대로 작동하는 평균화 기능의 일반적인 개념

현재 막대의 평균화에 대한 고전적인 접근 방식은 중간 표시기 버퍼로 구성되어 필요한 정보를 채운 다음 평균화 기간과 동일한 이전 값 범위를 선택하고 평균값을 계산합니다.

이 선택을 처리하는 절차는 다음과 같습니다.

SmoothVar(bar) = Function(Var(bar - (n-1)), Var(bar - (n-2)), ......... Var(bar)) 

어디:

  • SmoothVar(bar) — 평균 매개 변수;
  • bar — 계산이 수행되는 막대의 수입니다;
  • Var(bar - (n-1)) — (n-1) 막대에서 이동 한 평균 매개 변수입니다;
  • n — 평균화를 위한 막대 수.

우리의 경우 평균화에 대한 이러한 접근 방식은 두 가지 계산주기가 나타납니다. 첫 번째 주기에서 데이터가 계산되어 중간 버퍼에 저장됩니다. 두 번째 사이클에서는 상기 제시된 공식에 기초하여 지표 버퍼의 셀 추가 검색의 또 다른 사이클을 사용한 평균화가 수행된다. 함수 자체 내에서 선택한 중간 데이터를 누적하면 이 계산이 훨씬 쉬워 보입니다. 이 경우 평균화 기능은 다음과 같습니다.

SmoothVar(bar) = Function(Var(bar), bar)

새로운 값 Var (bar)는 현재 막대의 함수 내에서 선택한 값에 기록되고 불필요한 Var (bar-n) 값은 선택 항목에서 삭제됩니다. 이 접근 방식을 사용하면 평균화 코드가 매우 사소해 보이고 추가 표시기 버퍼가 필요하지 않습니다. 함수 내에서 배열은 전체 히스토리 데이터가 아닌 하나의 막대를 계산하는 데 필요한 정확한 양의 데이터를 저장합니다.

이 경우 데이터 계산 주기도 하나 뿐 입니다. 현재 막대에서 이 평균화 기능을 호출하려면 먼저 모든 이전 막대에서 호출해야 합니다!


2. 하나의 막대로 작동하는 함수를 구현하는 예로서의 클래식 평균화

이러한 평균화 함수는 해당 함수 호출 사이에 값을 잃지 않아야 하는 변수를 포함해야 합니다. 또한 다른 매개 변수를 사용하는 단일 유형 평균화는 코드에서 여러 번 사용될 수 있습니다. 따라서 공유 메모리 리소스 사용의 충돌을 피하려면 이러한 기능을 클래스로 구현해야 합니다. 그리고 그게 내가 한 일입니다.

클래식 평균화 알고리즘은 CMoving_Average 클래스에 설명되어 있습니다.

class CMoving_Average : public CMovSeriesTools
  {
public:  
   double    MASeries  (uint begin,               // Index of start of reliable bars
                       uint prev_calculated,      // Amount of history in bars at a previous tick
                       uint rates_total,          // Amount of history in bars at a current tick
                       int Length,               // Period of averaging
                       ENUM_MA_METHOD MA_Method, // Method of averaging (MODE_SMA, MODE_EMA, MODE_SMMA, MODE_LWMA)
                       double series,              // Value of price series calculated for the bar with the 'bar' number
                       uint bar,                   // Bar index
                       bool set                  // Direction of indexing of arrays.
                      );

   double    SMASeries (uint begin,          // Index of start of reliable bars
                       uint prev_calculated,// Amount of history in bars at a previous tick
                       uint rates_total,     // Amount of history in bars at a current tick
                       int Length,            // Period of averaging
                       double series,         // Value of price series calculated for the bar with the 'bar' number
                       uint bar,              // Bar index
                       bool set              // Direction of indexing of arrays.
                      );
                        
   double    EMASeries (uint begin,            // Index of start of reliable bars
                       uint prev_calculated, // Amount of history in bars at a previous tick
                       uint rates_total,     // Amount of history in bars at a current tick
                       double Length,         // Period of averaging
                       double series,        // Value of price series calculated for the bar with the 'bar' number
                       uint bar,              // Bar index
                       bool set              // Direction of indexing of arrays.
                      );
                        
   double    SMMASeries(uint begin,              // Index of start of reliable bars
                         uint prev_calculated, // Amount of history in bars at a previous tick
                         uint rates_total,     // Amount of history in bars at a current tick
                         int Length,            // Period of averaging
                         double series,         // Value of price series calculated for the bar with the 'bar' number
                         uint bar,              // Bar index
                         bool set              // Direction of indexing of arrays.
                      );

   double    LWMASeries(uint begin,               // Index of start of reliable bars
                         uint prev_calculated, // Amount of history in bars at a previous tick
                         uint rates_total,      // Amount of history in bars at a current tick
                         int Length,             // Period of averaging
                         double series,          // Value of price series calculated the bar with the 'bar' number
                         uint bar,               // Bar index
                         bool set               // Direction of indexing of arrays.
                        );

protected:
   double            m_SeriesArray[];
   int               m_Size_, m_count, m_weight;
   double            m_Moving, m_MOVING, m_Pr;
   double            m_sum, m_SUM, m_lsum, m_LSUM;
  };

이 클래스는 추가 보호된 기능-방법 및 이동 평균 기간에 대한 정확성 검사를 포함하는 기본 클래스 CMovSeriesTools에서 파생됩니다.

기본 클래스에는 내가 제안하는 모든 클래스에서 사용되는 추가 범용 코드가 포함되어 있으며 파생 클래스에 여러 번 복사할 필요가 없습니다. 평균화를 사용하는 응용 작업에서 보호되는 클래스 멤버는 명시적인 형식으로 사용되지 않으므로 당분간 개요를 일시 중지합시다.

클래스 CMoving_Average 5 개의 단일 유형 평균화 함수로 구성되며, 이름은 그 자체로 말하며 세부적으로 설명할 필요가 없습니다.

첫 번째 함수 MASeries() 은 MA_Method 매개 변수를 사용하여 평균화 알고리즘을 선택할 수 있는 4 개의 다른 함수의 통합 모음입니다. 평균화 알고리즘의 코드는 최대 성능을 위해 최적화되어 있으며 이것이 기능의 주요 매개 변수 (길이, 시리즈, 막대) 추가 매개 변수 begin, prev_calculated, rates_total 및 set, 로 보완되며 목적은 같은 이름의 인디케이터 변수와 완전히 동일합니다.

매개 변수 'set' 은 평균화 함수에서 가격 시리즈 '시리즈' 요소의 색인 플래그를 변수 배열과 동일하게 설정합니다..

이 클래스의 모든 평균화 함수는 Length 매개 변수가 고정되어 있으며 프로그램 코드 실행시 변경할 수 없다는 점을 고려해야 합니다! CMoving_Average 클래스의 EMASeries() 함수는 이 유형의 매개 변수를 두 배로 만듭니다!

이제 CMoving_Average 클래스에 익숙해졌으므로 인디케이터에서 사용할 수 있습니다. 이를 위해 #include 지시문을 사용하여 글로벌 범위에있는 MASeries_Cls.mqh 파일의 내용을 개발하는 표시기 코드에 추가합니다.

#include <MASeries_Cls.mqh> 

그런 다음 표시기 코드에서 필요한 평균화 절차 수를 결정한 다음 OnCalculate() 부분 (루프 연산자 및 중괄호 앞)에서 CMoving_Average 의 정적 변수를 선언해야 합니다. 클래스는 필요한 평균 절차 수에 따라 다릅니다. 평균화 절차마다 클래스의 개별 변수와 클래스 배열에 별도의 셀이 있어야 합니다.

//---- declaration of variables of the class CMoving_Average из файла MASeries_Cls.mqh
static CMoving_Average MA1, MA2, MA3, MA4;

OnCalculate() 함수의 클래스 변수는이 함수 호출 사이에 값이 유지되어야 하므로 정적 변수로 선언됩니다. 이제 평균화 작업 그 자체를 시작할 수 있습니다. 예를 들어 SMA/EMA/SMMA/LWMA (지표 MAx4.mq5)의 4 가지 연속 가격 시리즈 평균화 절차를 보여 드리겠습니다.

//---- The main cycle of indicator calculation 
for(bar = first; bar < rates_total; bar++) 
 {
  //----+ Four calls of the function MASeries.  
  ma1_ = MA1.MASeries(start1, prev_calculated, rates_total, Length1, MODE_SMA,  price[bar], bar, false);
  ma2_ = MA2.MASeries(start2, prev_calculated, rates_total, Length2, MODE_EMA,  ma1_,       bar, false);
  ma3_ = MA3.MASeries(start3, prev_calculated, rates_total, Length3, MODE_SMMA, ma2_,       bar, false);
  ma4_ = MA4.MASeries(start4, prev_calculated, rates_total, Length4, MODE_LWMA, ma3_,       bar, false);
  //----       
  MAx4[bar] = ma4_ + dPriceShift;
 }

각 이전 평균 (마지막 제외)의 결과는 다음 평균화 알고리즘에 사용되며 최종 결과는 표시기 버퍼로 전달됩니다.

이 코드에서 가장 중요한 부분은 신뢰할 수 있는 막대의 시작을 표시하는 인덱스 변수의 매우 신중한 예비 초기화입니다. 이 상황에서는 다음과 같이 표시됩니다.

//---- Initialization of variables of start of reliable information
start1 = 0 + begin;
start2 = Length1 + begin;
start3 = Length1 + begin; // the previous EMA averaging doesn't change the start of reliable information
start4 = Length1 + Length3 + begin;

이 상황에서 평균화의 LWMA 알고리즘은 마지막 알고리즘이며 아무 영향도주지 않습니다. 그러나 그것이 마지막 것이 아니라면 신뢰할 수있는 정보의 시작 이동은 Length4가 아니라 Length4+1과 같습니다!

신뢰할 수 있는 정보가 어느 숫자에서 시작되는지 이전 코드에서 명확하지 않은 경우 더 큰 숫자를 취한 다음 필요에 따라 실험적으로 줄입니다.


3. 클래스를 사용하여 생성된 지표와 기술 지표 및 사용자 지정 지표를 사용하는 유사체 비교

생성된 지표 MAx4.mq5의 성능을 기술 지표 iMA()를 사용하는 동일한 아날로그(iMAx4.mq5)와 비교하는 것은 매우 흥미로울 것입니다.

음, 우리가 테스트를 하기로 결정하자마자, MAx4.mq5와 유사한 또 다른 지표(MAx3x1.mq5)를 테스트하는 것이 합리적일 것이지만, 첫 번째 평균은 기술 지표 iMA()를 사용하며, 나머지 세 가지는 클래스 CMoving_Average를 사용하여 계산됩니다. 그리고 클라이언트 터미널의 표준 표시기 세트에 Custom Moving Average.mq5 표시기가 포함되자마자 테스트 목적으로 기반에 또 다른 유사한 표시기를 만들었습니다 (cMAx4.mq5).

다가오는 분석을 위해 저는 각각 MAx4_Test.mq5, iMAx4_Test.mq5, MAx3x1_Test.mq5 및 cMAx4_Test.mq5 테스트 Expert Advisors를 준비했습니다. 이러한 테스트를 수행하는 조건은 "지표의 경제적 계산 원칙" 문서에 자세히 설명되어 있습니다. 이 기사에서는 테스트의 세부 사항을 설명하지 않을 것이지만 EURUSD Н4에서 지난 12개월 동안 전략 테스터에서 4명의 Expert Advisor를 모두 실행한 최종 결과를 모든 모델링과 함께 보여 드리겠습니다. 틱 및 모든 EA의 '기간' 입력 매개변수 값은 500입니다.

그림 1 지표 테스트 결과 

테스트에서 최악의 결과는 사용자 지정 지표를 호출하는 지표에 의해 표시됩니다. 따라서 코드 작성의 이 변형은 게으른 사람들에게만 권장될 수 있습니다! 물론 마지막에 오는 또 다른 "리더"이지만 기술 지표의 호출을 기반으로 하는 리더가 훨씬 더 나은 결과를 가져오지만 이상과는 너무 거리가 멉니다.

테스트의 진정한 리더는 클래스를 사용하여 개발된 지표입니다!

클래스와 기술 지표를 사용하는 하이브리드가 2위를 차지했지만 항상 그런 것은 아닙니다. 지표의 테스트 시간이 중요한 경우 각 상황에 대해 이러한 변형을 개인적으로 확인하는 것이 좋습니다.

구현된 평균화 클래스 개요

№  알고리즘 클래스 이름 파일 이름 신뢰할 수 있는 막대의 시작 이동
알고리즘을 적용한 후
동적 가능성
매개변수 길이 변경
   1  Classic Averaging  CMoving_Average  MASeries_Cls.mqh Length/0/Length/Length + 1 (SMA/EMA/SMMA/LWMA) no
   2  Standard Deviation   CStdDeviation  StdDevSeries_Cls.mqh Length no
   3  JMA Smoothing  CJJMA  JJMASeries_Cls.mqh 30 yes
   4  T3 Smoothing  CT3  T3Series_Cls.mqh 0 yes
   5  Ultralinear Smoothing  CJurX  JurXSeries_Cls.mqh 0 yes
   6  Tushar Chande's Smoothing   CCMO  CMOSeries_Cls.mqh Length + 1 no
   7  Kaufman's Smoothing  CAMA  AMASeries_Cls.mqh Length + 3 no
   8  Parabolic Averaging  CParMA  ParMASeries_Cls.mqh Length no
   9  Speed of Change  CMomentum  MomSeries_Cls.mqh                                             Length + 1                               no
  10  Normalized Speed of Change   CnMomentum  nMomSeries_Cls.mqh                                             Length + 1                               no
  11  Rate of Change  CROC  ROCSeries_Cls.mqh                                             Length + 1                               no

앞서 설명한 클래스 CMoving_Average에는 평균화 알고리즘이 5개 포함되어 있습니다.

CCMO 클래스에는 평균화 및 오실레이터 알고리즘이 포함되어 있습니다.

다른 클래스에는 평균화의 단일 알고리즘이 포함됩니다. 제안된 클래스를 사용하는 이념은 위에서 설명한 CMoving_Average 클래스를 사용하는 절차와 완전히 동일합니다. 모든 평균화 알고리즘의 코드(포물선 알고리즘 제외)는 최대 실행 속도에 최적화되어 있습니다. 이 프로세스의 복잡성으로 인해 포물선 평균 코드가 최적화되지 않았습니다. 마지막 세 가지 알고리즘은 평균을 나타내지 않습니다. 높은 인기와 인기 있는 기술 분석가의 작업과의 호환성 때문에 추가했습니다.

정보를 보다 쉽게 ​​이해하려면 평균 알고리즘을 별도의 .mqh 파일로 나타내는 것이 좋습니다. 실제 사용을 위해 가장 좋은 변형은 단일 파일에 저장하는 것입니다.

표시기에서 사용하기 위해 제안된 모든 클래스는 단일 파일 SmoothAlgorithms.mqh로 압축됩니다. 이 외에도 파일은 iPriceSeries.mqh 파일의 기능으로 보완됩니다. 이 문서의 예에서는 PriceSeries() 함수만 사용합니다.

double PriceSeries
 (
  uint applied_price,  // Price constant
  uint   bar,          // Index of shift for a specified number of periods back or forward
                          // relatively to a current bar.
  const double& Open [],
  const double& Low  [],
  const double& High [],
  const double& Close[]
 )

이 함수는 OnCalculate() 함수의 두 번째 호출 유형을 사용하여 표시기를 사용하기 위한 것입니다.

이 함수를 만드는 주요 아이디어는 맞춤 변형으로 열거형 ENUM_APPLIED_PRICE의 가격 시계열 집합을 확장하는 것입니다. 이 함수는 1에서 11까지 다양한 숫자로 가격 시계열의 값을 반환합니다.


4. 평균화 클래스를 사용한 프로그램 코드 구현의 실제 예

다른 클래스를 사용하는 또 다른 예를 보여주는 것으로 충분하다면 모든 것이 4중 평균화와 동일한 방식으로 수행되는지 확인하십시오. CJJMA 및 CJurX(JCCX.mq5) 클래스를 사용하여 CCI 표시기의 아날로그에서 OnCalculate() 함수 구현의 변형을 보여 드리겠습니다.

int OnCalculate(const int rates_total,       // amount of history in bars on a current tick
              const int prev_calculated,   // amount of history in bars on a previous tick
              const datetime& time[],
              const double& open[],
              const double& high[],
              const double& low[],
              const double& close[],
              const long& tick_volume[],
              const long& volume[],
              const int& spread[]
             )
  {
//----+   
   //---- Checking whether there are enough bars for calculation
   if (rates_total < 0) return(0);
    
   //---- Declaration of variables  with floating point  
   double price_, jma, up_cci, dn_cci, up_jccx, dn_jccx, jccx;
   //----+ Declaration of integer variables
   int first, bar;
   
   //---- calculation of start number 'first' for the cycle of recalculation of bars
   if (prev_calculated == 0) // checking for the first start of calculation of indicator
        first = 0;           // starting number for calculation of all bars
   else first = prev_calculated - 1; // starting number for calculation of new bars
   
   //---- declaration of variables of the class CJurX from the file SmoothAlgorithms.mqh
   static CJurX Jur1, Jur2;
   //---- declaration of variables of the class CJMA from the file SmoothAlgorithms.mqh
   static CJJMA JMA;
   
   //---- Main cycle of calculation of the indicator
   for(bar = first; bar < rates_total; bar++)
    {
     //----+ Calling the PriceSeries function to get the input price price_
     price_ = PriceSeries(IPC, bar, open, low, high, close); 

     //----+ One call of the JJMASeries function to get JMA
     jma = JMA.JJMASeries(0, prev_calculated, rates_total, 0, JMAPhase, JMALength, price_, bar, false); 

     //----+ Determine the deviation of price from the value of JMA
     up_cci = price_ - jma;         
     dn_cci = MathAbs(up_cci);

     //----+ Two calls of the JurXSeries function.  
     up_jccx = Jur1.JurXSeries(30, prev_calculated, rates_total, 0, JurXLength, up_cci, bar, false);
     dn_jccx = Jur2.JurXSeries(30, prev_calculated, rates_total, 0, JurXLength, dn_cci, bar, false); 

     //---- Preventing zero divide in empty values
     if (dn_jccx == 0) jccx = EMPTY_VALUE;
     else
      {
       jccx = up_jccx / dn_jccx;
       
       //---- Limitation of the indicator from the top and from the bottom
       if (jccx > +1)jccx = +1;
       if (jccx < -1)jccx = -1;
      }

     //---- Loading the obtained value to the indicator buffer
     JCCX[bar] = jccx;
    }
//----+     
   return(rates_total);
  }

그림 2 표시기 JCCX 

그러나 이번에는 표시기 코드의 전역 범위에 있는 다른 파일의 적절한 클래스를 추가했습니다.

#include <SmoothAlgorithms.mqh>

이제 다른 일에 주의를 기울이고 싶습니다. 문제는 수많은 지표를 하나의 막대의 기능으로 나타낼 수 있다는 것인데, 이는 클래스를 사용하여 작업하기 정말 편리합니다.

예를 들어, Tushar Chande의 이동 평균 Vidya를 기반으로 Bollinger 채널을 그리는 것은 흥미로울 것입니다. 이 경우 두 개의 클래스 CCMOCStdDeviation가 사용됩니다. 첫 번째 클래스를 사용하여 이동 평균 VIDYA의 값을 얻습니다. 두 번째 것을 사용하여 이동 평균에 대한 가격 계열의 표준 편차 값을 계산합니다.

그런 다음 채널의 위쪽 및 아래쪽 경계를 계산하기 위해 이 편차를 사용합니다.

//+------------------------------------------------------------------+
// Description of the classes CStdDeviation{}; and CCMO{};           | 
//+------------------------------------------------------------------+ 
#include <SmoothAlgorithms.mqh> 
//+==================================================================+
//|  The algorithm of getting the Bollinger channel from             |
//|  the moving average VIDYA                                        |
//+==================================================================+
class CVidyaBands
{
public:
  double VidyaBandsSeries(uint begin,                // number of the start of reliable calculation of bars
                         uint prev_calculated,      // amount of history on a previous tick in bars
                         uint rates_total,          // amount of history on a current tick in bars
                         int CMO_period,            // the period of averaging of the oscillator CMO
                         double EMA_period,         // the period of averaging of EMA
                         ENUM_MA_METHOD MA_Method, // the type of averaging
                         int BBLength,             // the period of averaging of the Bollinger channel
                         double deviation,          // Deviation
                         double series,             // Value of the price series calculated for a bar with the number 'bar'
                         uint bar,                  // Bar index
                         bool set,                  // Direction of indexing of arrays
                         double& DnMovSeries,       // Value of the lower border of the channel for a current bar
                         double& MovSeries,         // Value of the middle line of the channel for a current bar
                         double& UpMovSeries        // Value of the upper border of the channel for a current bar 
                        ) 
   {
//----+
    //----+ Calculation of the middle line    
    MovSeries = m_VIDYA.VIDYASeries(begin, prev_calculated, rates_total, 
                                    CMO_period, EMA_period, series, bar, set); 
    //----+ Calculation of the Bollinger channel
    double StdDev = m_STD.StdDevSeries(begin+CMO_period+1, prev_calculated, rates_total, 
                                      BBLength, deviation, series, MovSeries, bar, set);
    DnMovSeries = MovSeries - StdDev;
    UpMovSeries = MovSeries + StdDev;
//----+
    return(StdDev); 
   }

  protected:
    //---- declaration of variables of the classes CCMO and CStdDeviation
    CCMO           m_VIDYA;
    CStdDeviation  m_STD;
};

그래서 우리는 간단하고 작은 수업을 얻었습니다!

VidyaBandsSeries() 함수의 마지막 세 입력 매개변수는 링크를 통해 채널의 필요한 값을 전달합니다.

이 경우 VidyaBandsSeries() 함수 내에서 클래스의 변수를 선언하고 정적 변수로 만들 수 없습니다. 클래스의 정적 변수는 매우 다른 의미를 갖기 때문입니다. 그렇기 때문에 이 선언은 클래스의 전역 범위에서 이루어져야 합니다.

protected: 
  //---- declaration of variables of the classes CCMO and CStdDeviation 
  CCMO           m_VIDYA; 
  CStdDeviation  m_STD;

일반적인 볼린저 채널에서는 이동 평균의 평균 주기와 채널 자체의 평균 주기가 항상 동일합니다.

이 클래스에서는 더 많은 자유를 제공하기 위해 해당 매개변수를 분리했습니다(EMA_period 및 BBLength). 이 클래스를 기반으로 만든 표시기 자체(VidyaBBands.mq5)는 CVidyaBands 클래스를 사용하는 데 매우 간단하므로 기사에서 해당 코드를 분석할 필요가 없습니다.

이러한 표시기 기능 클래스는 별도의 mqh 파일에 배치해야 합니다. 이러한 기능을 IndicatorsAlgorithms.mqh 파일에 배치했습니다.

그림 3 VidyaBBands 표시기 


5. 클래스를 사용하는 지표와 그렇지 않은 지표의 성능 비교 

먼저 인디케이터 코드를 작성할 때 클래스를 사용하면 성능이 어떻게 저하되는지 알고 싶습니다.

이를 위해 인디케이터 JJMA.mq5 의 코드를 클래스(JMA.mq5)를 사용하지 않고 작성한 후 이전과 동일한 조건에서 테스트하였습니다. 테스트의 최종 결과는 큰 차이가 없습니다.

그림 4 지표 JMA 및 JJMA 테스트 결과 

물론 클래스 이용에 따른 추가 비용이 발생하지만, 클래스가 제공하는 이점에 비하면 큰 차이는 없습니다. 


6. 평균화 클래스 사용의 장점

정말 설득력 있는 이러한 알고리즘을 사용하는 한 가지 이점은 기술 및 사용자 지정 지표의 호출을 대체하면 위에서 설명한 개발된 코드의 성능이 크게 향상된다는 것입니다.

이러한 클래스의 또 다른 실용적인 이점은 사용이 매우 편리하다는 것입니다. 예를 들어, William Blau의 유명한 책 "Momentum, Direction and Divergence"에 설명된 모든 것은 지표 작성에 대한 이러한 종류의 접근 방식에 대한 실제 시험장으로 보입니다. 지표 코드는 최대한 압축되고 이해하기 쉬우며 종종 막대 재계산의 단일 주기로 구성됩니다.

평균화의 대체 방법을 사용하여 모든 지표(클래식 또는 기술 지표)를 쉽게 개발할 수 있습니다. 매우 다양한 평균화 알고리즘은 비전통적인 거래 시스템을 생성할 수 있는 광범위한 가능성을 제공하며, 종종 추세를 조기에 감지하고 잘못된 트리거 횟수를 줄입니다.


7. 특정 지표 코드에서 평균화 알고리즘 사용에 대한 몇 가지 권장 사항

여기에 설명된 다양한 평균화 알고리즘을 사용하여 개발된 지표를 한 번만 살펴보면 이러한 알고리즘이 얼마나 다른지 이해하기에 충분합니다.

 

 그림 5 다양한 평균 알고리즘을 사용하는 이동 평균

따라서 제안된 모든 알고리즘이 모든 상황에서 동등하게 좋은 것은 아니라고 가정하는 것이 합리적입니다. 하나 또는 다른 알고리즘의 사용에 대한 엄격한 제한을 결정하는 것은 어렵지만 사용에 대한 몇 가지 일반적인 권장 사항을 제공하는 것은 가능합니다.

예를 들어, Tushar Chande 및 Kaufman의 알고리즘은 추세 상황을 결정하기 위한 것이며 노이즈 필터링을 위한 추가 평활화에는 적합하지 않습니다. 따라서 이러한 알고리즘을 평균화하지 않고 처리되지 않은 가격 계열이나 지표 값을 입력하는 것이 좋습니다. 다음은 Kaufman 알고리즘(지표 4c_Momentum_AMA.mq5)을 사용하여 지표 모멘텀 값을 처리한 결과입니다.

그림 6 Kaufman의 알고리즘을 사용하여 측정하는 모멘텀 값을 처리한 결과 

고전적인 평균화 알고리즘은 특별한 추천이 필요하지 않다고 생각합니다. 그들의 응용 분야는 꽤 넓습니다. 이러한 알고리즘이 사용되는 모든 곳에서 4개의 왼쪽 알고리즘(JMA, T3, 초선형 및 포물선)을 성공적으로 사용할 수 있습니다. 다음은 EMA 및 SMA가 JMA 평균으로 대체된 MACD 표시기의 예입니다(표시기 JMACD.mq5).

 그림 7 JMA 평균을 이용한 MACD 그래프

그리고 다음은 현재 경향을 결정하는 더 나은 품질을 위해 평균화 알고리즘을 변경하는 대신 계산된 지표를 평활화한 결과입니다(지표 JMomentum.mq5).

그림 8 지표 모멘텀의 JMA 평활화 결과

시장의 행동이 끊임없이 변화하는 것은 놀라운 일이 아닙니다. 따라서 현재와 영원히 금융 시장의 특정 부분에 대해 유일하고 유일한 이상적인 알고리즘을 찾을 수 있다고 생각하는 것은 순진한 생각입니다! 안타깝지만요! 이 세상에 영원한 것은 없다! 그럼에도 불구하고 나는 예를 들어 이 끊임없이 변화하는 시장에서 JFATL.mq5 및 J2JMA.mq5와 같은 고속 및 중기 추세 지표를 자주 사용합니다. 나는 그것들을 근거로 한 예측에 매우 만족합니다.

추가하고 싶은 또 다른 것. 평균화 알고리즘은 재사용 가능합니다. 이미 평균을 낸 값에 반복 평균을 적용하면 좋은 결과를 얻을 수 있습니다. 사실 이 기사에서는 지표(지표 MAx4.mq5)를 그리는 과정을 분석하기 시작했습니다.


8. 평균화 알고리즘의 코드 작성에 대한 일반적인 아이디어

그리고 이제 기사의 끝에서 평균 기능의 메커니즘에 주의를 기울이고 싶습니다.

우선, 평균화 알고리즘의 대부분은 입력 매개변수 '시리즈'의 값을 저장하기 위한 m_SeriesArray[] 유형의 변수의 동적 배열을 포함합니다.

계산에 중요한 정보가 나오자 마자 이러한 배열에 대해 한 번만 메모리를 할당해야 합니다. CMovSeriesTools 클래스의 SeriesArrayResize() 함수를 사용하여 수행됩니다.

//----+ Changing the size of the array of variables
if(bar==begin && !SeriesArrayResize(__FUNCTION__, Length, m_SeriesArray, m_Size_))
   return(EMPTY_VALUE);

그런 다음 모든 막대에서 '시리즈' 가격 시리즈의 현재 값을 배열의 가장 오래된 값에 쓰고 변수 m_count에서 해당 포지션의 번호를 기억해야 합니다. CmovSeriesTools 클래스의 Recount_ArrayZeroPos() 함수를 사용하여 수행됩니다.

//----+ transposition and initialization of cells of the array m_SeriesArray 
Recount_ArrayZeroPos(m_count, Length_, prev_calculated, series, bar, m_SeriesArray);

이제 현재 요소에 대한 상대적 이동이 있는 요소를 찾아야 하는 경우 CmovSeriesTools 클래스의 Recount_ArrayNumber() 함수를 사용해야 합니다.

for(iii=1; iii<=Length; iii++, rrr--)
   {
    kkk = Recount_ArrayNumber(m_count, Length_, iii);
    m_sum += m_SeriesArray[kkk] * rrr;
    m_lsum += m_SeriesArray[kkk];
    m_weight += iii;
   }

일반적으로 이러한 상황에서 최신 요소는 0 위치에 기록되고 다른 요소(가장 오래된 요소 제외)는 차례로 다음 위치에 예비 덮어씁니다. 그러나 그것은 컴퓨터 리소스를 절약하지 않으며 위에서 설명한 더 복잡한 접근 방식이 더 합리적으로 보입니다!

평균화 알고리즘 외에도 이러한 함수의 본문에는 막대 계산 시작과 관련된 막대 포지션을 결정하는 데 사용되는 함수 호출이 포함되어 있습니다.

//----+ Checking the start of reliable calculation of bars
if(BarCheck1(begin, bar, set)) return(EMPTY_VALUE);

변수 초기화 시작에 대한 정보가 충분한 순간:

//----+ Initialization of zero
if(BarCheck2(begin, bar, set, Length))

마지막 막대가 닫힌 상황:

//----+ Saving values of the variables 
if(BarCheck4(rates_total, bar, set))

또는 닫히지 않음:

//----+ Restoring values of the variables
if(BarCheck5(rates_total, bar, set))

첫 번째 검사는 평균화 함수가 작동하기에 막대가 충분하지 않은 상황을 결정하고 빈 결과를 반환합니다. 두 번째 검사가 성공적으로 통과되고 첫 번째 계산에 충분한 데이터가 있으면 변수 초기화가 한 번 수행됩니다. 현재 닫히지 않은 막대에서 값을 올바르게 다중 처리하려면 마지막 두 가지 검사가 필요합니다. 프로그램 코드 최적화에 관한 내 문서에서 이미 설명했습니다.

이제 최대 성능을 위해 이러한 기능의 프로그램 코드를 최적화하는 방법에 대해 몇 마디 하겠습니다. 예를 들어, SMA 알고리즘은 모든 막대에서 가격 시리즈 기간의 선택된 값을 평균화하는 것을 의미합니다. 이러한 값은 문자 그대로 합산되고 각 막대의 마침표로 나뉩니다.

그러나 이전 막대의 합계와 현재 막대의 합계의 차이는 첫 번째 막대가 현재 기간에 상대적으로 한 기간의 이동으로 가격 계열의 값과 합산되고 두 번째 막대의 값이 현재 값과 합산된다는 것입니다. 따라서 함수 초기화 중에 이러한 합계를 한 번만 계산한 다음 각 막대에서 이 합계에 가격 계열의 새 값만 추가하고 가장 오래된 값을 빼는 것이 훨씬 합리적입니다. 이것은 정확히 그러한 기능에서 수행됩니다.


결론

기사에서 제안하는 클래스를 사용한 평균화 알고리즘의 구현은 단순하고 단일 유형이며 보편적이므로 이를 연구하는 데 문제가 없습니다.

기사에 첨부된 아카이브에는 지표 코드 작성에 대한 이러한 접근 방식을 더 쉽게 이해할 수 있도록 많은 예제가 포함되어 있습니다. 아카이브 Include__en.zip에서 모든 클래스는 파일로 배포됩니다. Include_en.zip 아카이브에는 Indicators.zip 아카이브의 모든 표시기를 컴파일하기에 충분한 두 개의 파일만 포함되어 있습니다. 테스트를 위한 Expert Advisors는 Experts.zip 아카이브에 있습니다.


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

파일 첨부됨 |
experts-en.zip (3.88 KB)
include__en.zip (40.84 KB)
include-en.zip (17.82 KB)
indicators_en.zip (90.93 KB)
스펙트럼 분석기 구축 스펙트럼 분석기 구축
이 글은 독자들이 MQL5 언어의 그래픽 객체를 사용하는 가능한 변형에 대해 알게 하기 위한 것입니다. 그래픽 개체를 사용하여 간단한 스펙트럼 분석기를 관리하는 패널을 구현하는 표시기를 분석합니다. 이 기사는 MQL5의 기본 사항에 대해 잘 알고 있는 독자를 대상으로 합니다.
표준 라이브러리 클래스를 사용하여 나만의 Market Watch 만들기 표준 라이브러리 클래스를 사용하여 나만의 Market Watch 만들기
새로운 MetaTrader 5 클라이언트 터미널과 MQL5 언어는 트레이더에게 시각적 정보를 제공 할 수 있는 새로운 기회를 제공합니다. 이 기사에서는 차트에 임의의 텍스트 정보를 표시하는 모든 작업을 처리하는 확장 가능한 범용 클래스 집합을 제안합니다. Market Watch 지표의 예가 표시됩니다.
MQL5 트레이딩 시스템과 윌리엄 블라우의 인디케이터. 파트 1: 인디케이터 MQL5 트레이딩 시스템과 윌리엄 블라우의 인디케이터. 파트 1: 인디케이터
이 글은 윌리엄 블라우의 저서 'Momentum, Direction, and Divergence'에서 다루어진 인디케이터에 대한 소개입니다. 윌리엄 블라우의 접근법을 이용하면 수요 곡선 상의 변동을 빠르고 정확하게 계산할 수 있으며, 가격 변동 추세와 전환점을 판단하고, 노이즈를 제거할 수 있습니다. 이와 동시에 시장의 과매수/과매도 상태와 추세의 끝과 가격 움직임의 반전을 나타내는 신호를 감지할 수도 있죠.
퍼지 로직 (Fuzzy Logic)을 이용한 인디케이터 생성의 간단한 예 퍼지 로직 (Fuzzy Logic)을 이용한 인디케이터 생성의 간단한 예
이 글은 금융 시장 분석을위한 fuzzy logic 개념의 실제 적용에 전념합니다. Envelopes 인디케이터를 기반으로 두 가지 퍼지 규칙을 기반으로 신호를 생성하는 인디케이터의 예를 제안합니다. 개발된 인디케이터는 여러 인디케이터 버퍼를 사용함: 계산용 버퍼 7 개, 차트 디스플레이 용 버퍼 5 개, 색상 버퍼 2 개.