English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
MQL5'te Hareketli Ortalamalar Hesaplamasının Test Performansı

MQL5'te Hareketli Ortalamalar Hesaplamasının Test Performansı

MetaTrader 5Örnekler | 15 Aralık 2021, 10:05
98 0
Sergey Pavlov
Sergey Pavlov


Giriş

Hareketli Ortalamaların kullanımı, piyasa zaman serilerinin analizinde, göstergelerde ve Expert Advisor programlamasında yaygın bir uygulamadır. En popüler fiyat verisi yumuşatma yöntemidir. MQL dilinin yeni sürümünde bir düzine Hareketli Ortalama algoritması mevcuttur.

Peki bunların aralarındaki fark bu mu? Gerçekten, hesaplama hızı Hareketli Ortalamaların belirli bir algoritmasına mı bağlı? Hangi algoritma daha hızlı?

MetaTrader 5'te Hareketli Ortalamaların hesaplama hızı MetaTrader 4'e kıyasla arttı mı? Bunlara benzer bir çok soru ortaya çıkıyor. O halde, bunların büyük bir kısmını ele alalım.

Kuşkusuz ki, yeni bir platformun hızı etkileyicidir fakat bunu deneysel olarak kontrol etmek daha iyidir.


1. Test koşulları

Hesaplama hızı birçok faktöre bağlıdır. Bu nedenle, bu araştırma sonucunda elde edilen veriler, diğer test koşullarında farklı olacaktır. Başka bir deyişle, performansın mutlak değerleri farklı olacaktır fakat bağıl değerlerin benzer olması gerekir (belirli bir platform için).

MQL5'teki iMA işlevinin hesaplama sonuçlarını kendisinin döndürmemesi nedeniyle (bir göstergenin tanıtıcısını döndürür), iki işlevin hızını test edeceğiz: iMA ve CopyBuffer.

Test koşulları:
  • CPU: Core i7 965
  • Sembol: "EURUSD"
  • Fiyat veri boyutu: 10000 öğe
  • İstemci terminali: Bağımsız, grafikteki maksimum çubuk sayısı 10000 olarak ayarlanmıştır
  • Hareketli ortalama modelleri: MODE_SMA, MODE_EMA, MODE_SMMA, MODE_LWMA
  • Hesaplama hızının doğruluğu iki önemli basamakla sınırlıdır
  • Hareketli Ortalama işlevlerinin olası çağrı sayısı: 7


2. Nasıl test ettik?

Hareketli ortalama hesaplama süresini ölçmek için milisaniye cinsinden çalışan GetTickCount() işlevine sahibiz. Bu doğruluk yeterli değildir; bu nedenle ölçümlerin kalitesini iyileştirmek için bazı döngüleri düzenlememiz gerekir.

Ancak, aynı hesaplama ve aynı giriş verileri ile döngüyü birçok kez tekrarlamamız halinde sonuçlar bozulacaktır. Bu gerçeğin nedeni şudur: iMA işlevi, istemci terminalinin genel önbelleğinde karşılık gelen teknik göstergenin bir kopyasını oluşturur. Bir göstergenin kopyası (aynı parametrelere sahip) genel önbellekte zaten mevcutsa yeni kopya oluşturulmaz, gösterge kopyasının referans sayacı artırılır.

Diğer bir deyişle, tüm arabellek göstergesi ilk çağrıda yalnızca bir kez hesaplanır ve sonraki tüm çağrılarda yalnızca hazır değerleri alır ve yalnızca yeni verileri tekrar hesaplar.

Bu nedenle, döngü, göstergenin giriş parametreleri döngü sırasında benzersiz olduğunda düzenlenmelidir. Bu tür üç parametre seçtik: Ortalama alma süresi, zaman dilimi ve uygulanan fiyat.

Parametre
 Değer aralığı
 Ortalama alma süresi
 1'den 100'e kadar
 Zaman dilimi
 М1, М5, М15, М30
 Uygulanan fiyat
 PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED

Tablo 1. Giriş parametrelerinin aralıkları

Yedi farklı çağrı yöntemini kullanarak 10000 öğeli dizi için hareketli ortalama değerlerini hesaplayacağız (bölüm 4'teki ayrıntılara bakınız).


3. Çalışmanın sonuçları

Tüm sonuçları Tablo 1'de birleştirdik, hesaplama performansı saniye cinsinden hesaplama süresi (bkz. Tablo 1) kullanılarak tahmin edilmiştir. Program 100х4х7=2800 tür hareketli ortalamayı hesaplar ve 10.000 öğeli fiyat dizisi için hesaplama süresini belirleriz. Tek geçişin (döngü) hesaplama süresi yaklaşık olarak toplam sürenin 2800'e bölünmesine eşittir. Örneğin, durum 1 ve SMA modu için ~ 0,0028/2800'e eşittir.

Mod
MODE_SMAMODE_EMAMODE_SMMAMODE_LWMAPlatform
0 (bkz. bölüm 4.1)
0,0041 0,0040 0,0043 0,0041  MetaTrader 4
1   (bkz. bölüm 4.2) 0,0028 0,00023 0,00027 0,0045  MetaTrader 5
2   (bkz. bölüm 4.3) 0,0029 0,0029 0,0029 0,0029  MetaTrader 5
3   (bkz. bölüm 4.4) 0,0998 0,0997 0,0998 0,0998  MetaTrader 5
4   (bkz. bölüm 4.5) 0,0996 0,0996 0,0996 0,0996  MetaTrader 5
5   (bkz. bölüm 4.6) 0,0030 0,0029 0,0029 0,0029  MetaTrader 5
6   (bkz. bölüm 4.7) 0,000140 0,000121 0,000117 0,0035  MetaTrader 5

Tablo 2. Sonuçlar

Test durumlarının anlamı daha ayrıntılı olarak ele alınacaktır (bölüm 4.1-4.7). Hareketli Ortalamanın hesaplama performansı ile ilgili resmin tamamını tahmin edelim. 

Kolaylık sağlamak için sonuçlar grafiklerde sunulmuştur (bkz. şekil 1-5). Hareketli Ortalamanın çağrı türü X eksenlerinde sunulurken (bkz. tablo 2), Y eksenlerindeki değerler -1 ile çarpılan logaritmik ölçekte sunulmuştur; bu nedenle daha büyük değerler daha hızlı performans anlamına gelir. Hesaplama modellerinin her biri (SMA, EMA, SMMA, LWMA) grafikte bir sütuna karşılık gelir.

Şekil.1 Farklı Hareketli Ortalama algoritmaları için performans testi sonuçları

Şekil 1. Farklı Hareketli Ortalama algoritmaları için performans testi sonuçları

Hareketli Ortalama hesaplamasının farklı durumları için hesaplama hızında önemli bir fark görülebilir. Bu ne anlama gelir? MQL5 geliştiricileri tarafından sağlanan birkaç Hareketli Ortalama hesaplama algoritması farklı hesaplama performanslarına sahiptir: Hızlı bir algoritma (durum 6) ve daha yavaş yöntemler (durum 3 ve 4) vardır. Dolayısıyla, Hareketli Ortalamaları kullanan MQL5'te program yazarken doğru algoritmaları seçmek gerekir.

Her Hareketli Ortalama modelinin (0-6) hesaplama süresi aşağıdaki şekillerde ayrıntılı olarak sunulmuştur (bkz. tablo 2).

Şekil 2. MODE_SMA modunun MA hesaplama performansı

Şekil 2. MODE_SMA modunun MA hesaplama performansı

Şekil 3. MODE_EMA modunun MA hesaplama performansı

Şekil 3. MODE_EMA modunun MA hesaplama performansı

Şekil 4. MODE_SMMA modunun MA hesaplama performansı

Şekil 4. MODE_SMMA modunun MA hesaplama performansı

Şekil 5. MODE_LWMA modunun MA hesaplama performansı

Şekil 5. MODE_LWMA modunun MA hesaplama performansı

İki platformun hesaplama performansını karşılaştırmak ilginçtir: MetaTrader 4 ve MetaTrader 5. Sonuçlar Tablo 2'de, durum №0 (MQL4) ve durum №2'de (MQL5) sunulmuştur.

Kolaylık sağlamak için, iMA standart göstergesinin hesaplama sonuçlarını ayrı bir grafik ve tabloda birleştirelim (bkz. şekil 6). Testin hesaplama süresi Y eksenlerinde sunulmuştur.

Şekil 6. MetaTrader 4 и MetaTrader 5 hesaplama performansının karşılaştırmalı grafiği

Şekil 6. MetaTrader 4 и MetaTrader 5 hesaplama performansının karşılaştırmalı grafiği

Sonuçlar:

  1. Yeni MetaTrader 5 platformu, önceki MetaTrader 4'ten %40 oranında daha hızlıdır.
  2. En hızlı performans SMA, EMA ve SMMA modelleri için (durum №6), LWMA için (durum №2 ve №5) elde edilmiştir.
  3. Test durumları için, standart gösterge iMA kullanıldığında, farklı modellerin hesaplama performansı pratik olarak aynıdır. Bu, MovingAverages.mqh kitaplığı işlevleri için doğru değildir. Farklı modeller için performans neredeyse bir sıra (0,00023~0,0045) farklılık gösterir.
  4. Sunulan sonuçlar "soğuk başlatma"ya karşılık gelir, istemci terminalinin genel önbelleğinde önceden hesaplanmış herhangi bir veri yoktur.


4. Durum Çalışmaları

MQL5 geliştiricileri, standart teknik göstergelerin değerlerini almak için aşağıdaki yöntemi önerirler:

//---- indicator buffers
double      MA[];                // array for iMA indicator values
//---- handles for indicators
int         MA_handle;           // handle of the iMA indicator
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   //--- creating handle of the iMA indicator
   MA_handle=iMA(NULL,0,21,0,MODE_EMA,PRICE_CLOSE);
   //--- print message if there was an error
   if(MA_handle<0)
      {
      Print("The iMA object is not created: MA_handle= ",INVALID_HANDLE);
      Print("Runtime error = ",GetLastError());
      //--- forced termination of program
      return(-1);
      }
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   //--- filling the MA[] array with current values of the iMA indicator
   //--- we will copy 100 elements, or return if there was an error
   if(CopyBuffer(MA_handle,0,0,100,MA)<=0) return;
   //--- set ordering of MA[] as timeseries
   ArraySetAsSeries(MA,true);  
   //--- here you can do anything with these data
  }

Bu yöntem, "Yeni Başlayanlar için MQL5: Expert Advisor'larda Teknik Göstergeleri Kullanma Kılavuzu" makalesinde ayrıntılı olarak açıklanmıştır.

Hareketli ortalamaların hesaplama performansını test etmek için script dosyası kullanmak daha iyidir; zira bu, tüm hesaplamaları olayları beklemeden (örneğin, yeni tick olayı vb.) yapabilir.

Tüm test durumları için ayrı bir evrensel program oluşturmak gerekli değildir; bu nedenle her MA hesaplama durumu için ayrı bir script dosyası oluşturacağız.

Öyleyse, Hareketli Ortalama hesaplamalarının durumlarının her birini ayrıntılı olarak ele alalım.


4.1. Durum  №0

Bu durumda MQL4'ün teknik göstergesi iMA'nın hesaplama performansını ölçtük. Hesaplamalar MetaTrader4'te gerçekleştirildi ve tüm veriler üzerinde uygulandı.

ModelSonuçEn iyi sonuç
MODE_SMA 0,0041 0,000140 (durum 6)
MODE_EMA 0,0040 0,000121 (durum 6)
MODE_SMMA 0,0043 0,000117 (durum 6)
MODE_LWMA 0,0041 0,0029 (durum 2, 5)


Bu durumun kodu şu şekildedir (MQL4):

int         M[4]=
  {
   PERIOD_M1,
   PERIOD_M5,
   PERIOD_M15,
   PERIOD_M30
  };
int         P[7]=
  {
   PRICE_CLOSE,
   PRICE_OPEN,
   PRICE_HIGH,
   PRICE_LOW,
   PRICE_MEDIAN,
   PRICE_TYPICAL,
   PRICE_WEIGHTED
  };
int         periodMA;
double      buf[];
double      time;
int         count=10000;
int         startGTC,endGTC;
int         m,p;
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
   if(ArrayResize(buf,count)<0) return(-1);
   Print("START ");
   startGTC=GetTickCount();
//----
   for(m=0;m<=3;m++)
     {
      for(p=0;p<=6;p++)
        {
         for(periodMA=1;periodMA<=100;periodMA++)
           {
           Test0();
           }
        }
     }
//----
   endGTC=GetTickCount();
   time=endGTC-startGTC;
   Print("Total time [msec] ",time);
   time=time/1000/m/p/periodMA;
   Print("Performance [sec] ",DoubleToStr(time, 10));
   return(0);
  }
//+------------------------------------------------------------------+
void Test0()
  {
//--- Model: MODE_SMA; MODE_EMA; MODE_SMMA; MODE_LWMA
   for(int i=0;i<count;i++)
     {
      buf[i]=iMA(NULL,M[m],periodMA,0,MODE_SMA,P[p],i);
     }
  }

Not: Bu kod, MQL4'te yazıldığı için MetaTrader 5'te çalışmayacaktır. MetaTrader 4 istemci terminalinde yürütülmelidir.


4.2. Durum №1

Bu durumda MovingAverages.mqh kitaplık işlevlerini kullanarak 4 modelin hesaplanmasını gerçekleştirdik: №1(SMA), №2(EMA), №3(SMMA) и №4(LWMA).

Hesaplama tüm veri dizisinde gerçekleştirildi.

Model
 SonuçEn iyi sonuç
MODE_SMA
0,0028
0,000140 (durum 6)
MODE_EMA
0,00023
0,000121 (durum 6)
MODE_SMMA
0,000270,000117 (durum 6)
MODE_LWMA
0,00450,0029 (durum 2 ve 5)
#include <MovingAverages.mqh>
ENUM_TIMEFRAMES      M[4]=
  {
   PERIOD_M1,
   PERIOD_M5,
   PERIOD_M15,
   PERIOD_M30
  };
ENUM_APPLIED_PRICE   P[7]=
  {
   PRICE_CLOSE,
   PRICE_OPEN,
   PRICE_HIGH,
   PRICE_LOW,
   PRICE_MEDIAN,
   PRICE_TYPICAL,
   PRICE_WEIGHTED
  };
int         periodMA;
double      buf[],close[];
double      time;
int         count=10000;
int         startGTC,endGTC;
int         m,p;
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int OnStart()
  {
   if(ArrayResize(buf,count)<0) return(-1);
   ArraySetAsSeries(buf,false);
   ArraySetAsSeries(close,false);
   startGTC=GetTickCount();
//---
   for(m=0;m<=3;m++)
     {
      for(p=0;p<=6;p++)
        {
         CopyClose(_Symbol,M[m],0,count,close);
         for(periodMA=1;periodMA<=100;periodMA++)
           {
            Test1(); // the test is here
           }
        }
     }
//---
   endGTC=GetTickCount();
   time=endGTC-startGTC;
   time=time/1000/m/p/periodMA;
//---
   return(0);
  }
//+------------------------------------------------------------------+
void Test1()
  {
   for(int i=0;i<count;i++)
     {
      buf[i]=SimpleMA(i,periodMA,close);
     }
  }
//+------------------------------------------------------------------+
void Test2()
  {
   buf[0]=close[0];
   for(int i=1;i<count;i++)
     {
      buf[i]=ExponentialMA(i,periodMA,buf[i-1],close);
     }
  }
//+------------------------------------------------------------------+
void Test3()
  {
   buf[0]=close[0];
   for(int i=1;i<count;i++)
     {
      buf[i]=SmoothedMA(i,periodMA,buf[i-1],close);
     }
  }
//+------------------------------------------------------------------+
void Test4()
  {
   for(int i=0;i<count;i++)
     {
      buf[i]=LinearWeightedMA(i,periodMA,close);
     }
  }

Not. Dizideki çeşitli veri türlerini kullanmayı planladık ancak kolaylık sağlamak için, yalnızca kapanış fiyatı verilerini içeren bir diziyi kullandık (bu, hesaplamaların performansını etkilemez).


4.3. Durum №2

Bu durumda iMA standart teknik göstergesini ve test №5'i kullandık.

Hesaplama tüm veri dizisinde gerçekleştirildi.

ModelSonuçEn iyi sonuç
MODE_SMA 0,0029 0,000140 (durum 6)
MODE_EMA 0,0029 0,000121 (durum 6)
MODE_SMMA 0,0029 0,000117 (durum 6)
MODE_LWMA 0,0029 0,0029 (durum 2 ve 5)
ENUM_TIMEFRAMES      M[4]=
  {
   PERIOD_M1,
   PERIOD_M5,
   PERIOD_M15,
   PERIOD_M30
  };
ENUM_APPLIED_PRICE   P[7]=
  {
   PRICE_CLOSE,
   PRICE_OPEN,
   PRICE_HIGH,
   PRICE_LOW,
   PRICE_MEDIAN,
   PRICE_TYPICAL,
   PRICE_WEIGHTED
  };
int         periodMA;
double      time;
int         count=10000;
int         startGTC,endGTC;
int         m,p;
double      MA[];                // array for the iMA indicator
int         MA_handle;           // handle of the iMA indicator
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int OnStart()
  {
   startGTC=GetTickCount();
//---
   for(m=0;m<=3;m++)
     {
      for(p=0;p<=6;p++)
        {
         for(periodMA=1;periodMA<=100;periodMA++)
           {
            Test5();
           }
        }
     }
//---
   endGTC=GetTickCount();
   time=endGTC-startGTC;
   time=time/1000/m/p/periodMA;
//---
   return(0);
  }
//+------------------------------------------------------------------+
void Test5()
  {
//--- Model: MODE_SMA; MODE_EMA; MODE_SMMA; MODE_LWMA
   MA_handle=iMA(NULL,M[m],periodMA,0,MODE_SMA,P[p]);
   while(BarsCalculated(MA_handle)<count){}
   CopyBuffer(MA_handle,0,0,count,MA);
  }


4.4. Durum №3

№3 durumunda, Standart kitaplık sınıflarının göstergeleriyle çalışan sınıflar kullanıldı.

Elementwise veri kopyalama özelliği kullanıldı. Hesaplama tüm veri dizisinde gerçekleştirildi.

ModelSonuçEn iyi sonuç
MODE_SMA 0,0998 0,000140 (durum 6)
MODE_EMA 0,0997 0,000121 (durum 6)
MODE_SMMA 0,0998 0,000117 (durum 6)
MODE_LWMA 0,0998 0,0029 (durum 2 ve 5)
#include <Indicators\Trend.mqh>
ENUM_TIMEFRAMES      M[4]=
  {
   PERIOD_M1,
   PERIOD_M5,
   PERIOD_M15,
   PERIOD_M30
  };
ENUM_APPLIED_PRICE   P[7]=
  {
   PRICE_CLOSE,
   PRICE_OPEN,
   PRICE_HIGH,
   PRICE_LOW,
   PRICE_MEDIAN,
   PRICE_TYPICAL,
   PRICE_WEIGHTED
  };
int         periodMA;
double      buf[];
double      time;
int         count=10000;
int         startGTC,endGTC;
int         m,p;
CiMA        objMA;
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int OnStart()
  {
   if(ArrayResize(buf,count)<0) return(-1);
   ArraySetAsSeries(buf,false);
   startGTC=GetTickCount();
//---
   for(m=0;m<=3;m++)
     {
      for(p=0;p<=6;p++)
        {
         for(periodMA=1;periodMA<=100;periodMA++)
           {
            Test6();
           }
        }
     }
//---
   endGTC=GetTickCount();
   time=endGTC-startGTC;
   time=time/1000/m/p/periodMA;
//---
   return(0);
  }
//+------------------------------------------------------------------+
void Test6()
  {
//--- Model: MODE_SMA; MODE_EMA; MODE_SMMA; MODE_LWMA
   objMA.Create(NULL,M[m],periodMA,0,MODE_SMA,P[p]);
   objMA.BuffSize(count);
   objMA.Refresh(1);
   for(int i=0;i<count;i++)
     {
      buf[i]=objMA.Main(i);
     }
  }

4.5. Durum №4

№4 durumunda, Standart kitaplık sınıflarının göstergeleriyle çalışan sınıflar kullanıldı.

Gösterge arabelleğinin dizisi bir bütün olarak kopyalandı. Hesaplama tüm veri dizisinde gerçekleştirildi.

ModelSonuçEn iyi sonuç
MODE_SMA 0,0996 0,000140 (durum 6)
MODE_EMA 0,0996 0,000121 (durum 6)
MODE_SMMA 0,0996 0,000117 (durum 6)
MODE_LWMA 0,0996 0,0029 (durum 2, 5)
#include <Indicators\Trend.mqh>
ENUM_TIMEFRAMES      M[4]=
  {
   PERIOD_M1,
   PERIOD_M5,
   PERIOD_M15,
   PERIOD_M30
  };
ENUM_APPLIED_PRICE   P[7]=
  {
   PRICE_CLOSE,
   PRICE_OPEN,
   PRICE_HIGH,
   PRICE_LOW,
   PRICE_MEDIAN,
   PRICE_TYPICAL,
   PRICE_WEIGHTED
  };
int         periodMA;
double      buf[];
double      time;
int         count=10000;
int         startGTC,endGTC;
int         m,p;
CiMA        objMA;
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int OnStart()
  {
   if(ArrayResize(buf,count)<0) return(-1);
   ArraySetAsSeries(buf,false);
   startGTC=GetTickCount();
//---
   for(m=0;m<=3;m++)
     {
      for(p=0;p<=6;p++)
        {
         for(periodMA=1;periodMA<=100;periodMA++)
           {
            Test7();
           }
        }
     }
//---
   endGTC=GetTickCount();
   time=endGTC-startGTC;
   time=time/1000/m/p/periodMA;
//---
   return(0);
  }
//+------------------------------------------------------------------+
void Test7()
  {
//--- Models: MODE_SMA; MODE_EMA; MODE_SMMA; MODE_LWMA
   objMA.Create(NULL,M[m],periodMA,0,MODE_SMA,P[p]);
   objMA.BuffSize(count);
   objMA.Refresh(1);
   objMA.GetData(0,count,0,buf);          
  }


4.6. Durum №5

№8 testi kullanıldı: Gösterge tanıtıcısı IndicatorCreate işlevi kullanılarak oluşturuldu.

Hesaplama tüm veri dizisinde gerçekleştirildi.
ModelSonuçEn iyi sonuç
MODE_SMA 0,0030 0,000140 (durum 6)
MODE_EMA 0,0029 0,000121 (durum 6)
MODE_SMMA 0,0029 0,000117 (durum 6)
MODE_LWMA 0,0029 0,0029 (durum 2 ve 5)
ENUM_TIMEFRAMES      M[4]=
  {
   PERIOD_M1,
   PERIOD_M5,
   PERIOD_M15,
   PERIOD_M30
  };
ENUM_APPLIED_PRICE   P[7]=
  {
   PRICE_CLOSE,
   PRICE_OPEN,
   PRICE_HIGH,
   PRICE_LOW,
   PRICE_MEDIAN,
   PRICE_TYPICAL,
   PRICE_WEIGHTED
  };
int         periodMA;
double      time;
int         count=10000;
int         startGTC,endGTC;
int         m,p;
double      MA[];                // array for the iMA indicator
int         MA_handle;           // handle of the iMA indicator
MqlParam    params[];
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int OnStart()
  {
   ArrayResize(params,4);
   startGTC=GetTickCount();
//---
   for(m=0;m<=3;m++)
     {
      for(p=0;p<=6;p++)
        {
         for(periodMA=1;periodMA<=100;periodMA++)
           {
            Test8();
           }
        }
     }
//---
   endGTC=GetTickCount();
   time=endGTC-startGTC;
   time=time/1000/m/p/periodMA;
//---
   return(0);
  }
//+------------------------------------------------------------------+
void Test8()
  {
//--- Model: MODE_SMA; MODE_EMA; MODE_SMMA; MODE_LWMA
//--- set ma_period
   params[0].type         =TYPE_INT;
   params[0].integer_value=periodMA;
//--- set ma_shift
   params[1].type         =TYPE_INT;
   params[1].integer_value=0;
//--- set ma_method
   params[2].type         =TYPE_INT;
   params[2].integer_value=MODE_SMA;
//--- set applied_price
   params[3].type         =TYPE_INT;
   params[3].integer_value=P[p];
//--- create MA
   MA_handle=IndicatorCreate(NULL,M[m],IND_MA,4,params);
   while(BarsCalculated(MA_handle)<count){}
   CopyBuffer(MA_handle,0,0,count,MA);
  }


4.7. Durum №6

Bu durumda MovingAverages.mqh kitaplık işlevlerini (MQL4'ten iMAOnArray gibi arabellek işlevleri) kullanarak 4 modelin hesaplanmasını gerçekleştirdik: №9(SMA), №10(EMA), №11(SMMA) и №12(LWMA).

Hesaplama tüm veri dizisinde gerçekleştirildi.

ModelSonuçEn iyi sonuç
MODE_SMA 0,000140 0,000140 (durum 6)
MODE_EMA 0,000121 0,000121 (durum 6)
MODE_SMMA 0,000117 0,000117 (durum 6)
MODE_LWMA 0,00350 0,0029 (durum 2 ve 5)
#include <MovingAverages.mqh>
ENUM_TIMEFRAMES         M[4]=
  {
   PERIOD_M1,
   PERIOD_M5,
   PERIOD_M15,
   PERIOD_M30
  };
ENUM_APPLIED_PRICE         P[7]=
  {
   PRICE_CLOSE,
   PRICE_OPEN,
   PRICE_HIGH,
   PRICE_LOW,
   PRICE_MEDIAN,
   PRICE_TYPICAL,
   PRICE_WEIGHTED
  };
int         periodMA;
double      buf[],arr[];
double      close[];
double      time;
int         count=10000,total;
int         startGTC,endGTC;
int         m,p;
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int OnStart()
  {
   CopyClose(_Symbol,_Period,0,count,close);
   total=ArrayCopy(arr,close);
   if(ArrayResize(buf,total)<0) return(-1);
//---
   ArraySetAsSeries(close,false);
   ArraySetAsSeries(arr,false);
   ArraySetAsSeries(buf,false);
   startGTC=GetTickCount();
//---
   for(m=0;m<=3;m++)
     {
      for(p=0;p<=6;p++)
        {
         CopyClose(_Symbol,M[m],0,count,close);
         total=ArrayCopy(arr,close);
         for(periodMA=1;periodMA<=100;periodMA++)
           {
            Test9();    // the test is here
           }
        }
     }
//---
   endGTC=GetTickCount();
   time=endGTC-startGTC;
   time=time/1000/m/p/periodMA;
//---
   return(0);
  }
//+------------------------------------------------------------------+
void Test9()
  {
   SimpleMAOnBuffer(total,0,0,periodMA,arr,buf);
  }
//+------------------------------------------------------------------+
void Test10()
  {
   ExponentialMAOnBuffer(total,0,0,periodMA,arr,buf);
  }
//+------------------------------------------------------------------+
void Test11()
  {
   SmoothedMAOnBuffer(total,0,0,periodMA,arr,buf);
  }
//+------------------------------------------------------------------+
void Test12()
  {
   LinearWeightedMAOnBuffer(total,0,0,periodMA,arr,buf);
  }

Not. Dizideki çeşitli veri türlerini kullanmayı planladık fakat kolaylık sağlamak için kapanış fiyatı verileriyle yalnızca bir dizi kullandık (bu, hesaplamaların performansını etkilemez).


5. Sonuçların Çıktısı

Sonuçların çıktısı ve hareketli ortalamaların kontrolü için PrintTest işlevini kullandım:

void PrintTest(const int position, const double &price[])
{
   Print("Total time [msec] ",(endGTC-startGTC));
   Print("Performance [sec] ",time);
   Print(position," - array element = ",price[position]);
}

Bu, şu şekilde çağrılabilir (çubuk pozisyonu ve veri dizisi, işlevin parametreleridir):

//---
   ArraySetAsSeries(buf,false);
   ArraySetAsSeries(close,false);
   startGTC=GetTickCount();
//---
   for(m=0;m<=3;m++)
     {
      for(p=0;p<=6;p++)
        {
         for(periodMA=1;periodMA<=100;periodMA++)
           {
            Test();
           }
        }
     }
//---
   endGTC=GetTickCount();
   time=endGTC-startGTC;
   time=time/1000/m/p/periodMA;
//--- Output of results
   ArraySetAsSeries(buf,true);
   ArraySetAsSeries(close,true);
   PrintTest(0,buf);
   PrintTest(0,close);
//---

Dizi indekslemenin hesaplamalardan önce ve sonra farklı olduğunu unutmayın.

ÖNEMLİ. AsSeries bayrağı, hesaplamalar sırasında false olarak ayarlanır ve sonuçlar yazdırılırken true olarak ayarlanır.


6. Ek Araştırmalar

Başlangıç parametrelerinin hesaplama performansı üzerindeki etkisi ile ilgili soruyu yanıtlamak için bazı ek ölçümler yapılmıştır.

Hatırladığımız üzere, №6 durumu en iyi performansa sahiptir; bu nedenle onu kullanacağız.

Test parametreleri:

Mod
Zaman dilimi
 Ortalama alma süresi
1
М1
144
2
М5
144
3
М15
144
4
М30
144
5
М121
6
М134
7
М155
8
М189
9
М1233
10
М1377
11
М1610
12
М1987

Tablo 3. Ek araştırmalar

Testlerin kaynak kodu:

//+------------------------------------------------------------------+
//| Test_SMA                                       Model: MODE_SMA   |
//+------------------------------------------------------------------+
void Test_SMA(int periodMA,ENUM_TIMEFRAMES periodTF)
  {
   CopyClose(_Symbol,periodTF,0,count,close);
   int total=ArrayCopy(arr,close);
   SimpleMAOnBuffer(total,0,0,periodMA,arr,buf);
  }
//+------------------------------------------------------------------+
//| Test_EMA                                       Model: MODE_EMA   |
//+------------------------------------------------------------------+
void Test_EMA(int periodMA,ENUM_TIMEFRAMES periodTF)
  {
   CopyClose(_Symbol,periodTF,0,count,close);
   int total=ArrayCopy(arr,close);
   ExponentialMAOnBuffer(total,0,0,periodMA,arr,buf);
  }
//+------------------------------------------------------------------+
//| Test_SMMA                                      Model: MODE_SMMA  |
//+------------------------------------------------------------------+
void Test_SMMA(int periodMA,ENUM_TIMEFRAMES periodTF)
  {
   CopyClose(_Symbol,periodTF,0,count,close);
   int total=ArrayCopy(arr,close);
   SmoothedMAOnBuffer(total,0,0,periodMA,arr,buf);
  }
//+------------------------------------------------------------------+
//| Test_LWMA                                      Model: MODE_LWMA  |
//+------------------------------------------------------------------+
void Test_LWMA(int periodMA,ENUM_TIMEFRAMES periodTF)
  {
   CopyClose(_Symbol,periodTF,0,count,close);
   int total=ArrayCopy(arr,close);
   LinearWeightedMAOnBuffer(total,0,0,periodMA,arr,buf);
  }

Ek testler için otomatik test programını kullanacağız; buna ait grafik kullanıcı arayüzü Şekil 7'de sunulmuştur.

Şekil 7. Otomatik test için otomatik test programı

Şekil 7. Otomatik test için otomatik test programı

Sonuçlar: (X ekseninin logaritmik bir zaman ölçeği vardır)

Şekil 8. Zaman dilimi parametresi (Y) ve Hareketli Ortalamalar hesaplama performansı (X)

Şekil 8. Zaman dilimi parametresi (Y) ve Hareketli Ortalamalar hesaplama performansı (X)

Şekil 9. Dönem parametresi (Y) ve Hareketli Ortalamalar hesaplama performansı (X)

Şekil 9. Dönem parametresi (Y) ve Hareketli Ortalamalar hesaplama performansı (X)

Ek araştırmaların sonuçlarının sonuçları:

  1. Zaman dilimi parametresi önemli değildir; hesaplama performansını etkilemez (bkz. şek. 8).
  2. SMA, EMA ve SMMA modelleri için hareketli ortalamalar hesaplama performansı için dönem önemli bir parametre değildir. Ancak bunun aksine, LWMA modeli için hesaplamaları önemli ölçüde (0,00373 saniyeden 0,145 saniyeye) yavaşlatır (bkz. şek. 9).


Sonuç

Hareketli ortalamalar algoritmasının yanlış şekilde seçilmesi, programlarınızın hesaplama performansını düşürebilir.


MetaQuotes Ltd tarafından Rusçadan çevrilmiştir.
Orijinal makale: https://www.mql5.com/ru/articles/106

Ekli dosyalar |
autotest__1.zip (10.86 KB)
Göstergelerin Ekonomik Hesaplanmasına İlişkin Prensipler Göstergelerin Ekonomik Hesaplanmasına İlişkin Prensipler
Kullanıcı çağrıları ve teknik göstergeler, otomatik alım satım sistemlerinin program kodunda çok az yer kaplar. Bu, genellikle yalnızca birkaç kod satırıdır. Ancak bu, çoğu zaman, Expert Advisor'ı test etmek için harcanması gereken zamanın en büyük kısmını kullanan bu birkaç kod satırı olur. Bu nedenle, bir gösterge içindeki veri hesaplamalarıyla ilgili her şeyin, ilk bakışta göründüğünden çok daha kapsamlı bir şekilde düşünülmesi gerekir. Bu makalede tam olarak bu ele alınacaktır.
Çok Sayıda Enstrüman Üzerinde Alım Satım Yapan bir Expert Advisor Oluşturma Çok Sayıda Enstrüman Üzerinde Alım Satım Yapan bir Expert Advisor Oluşturma
Finansal piyasalarda varlıkların çeşitlendirilmesi kavramı oldukça eskiye dayanır ve her zaman yeni başlayan yatırımcıları cezbetmiştir. Bu makalede, yazar, alım satım stratejilerinin bu yönüne bir başlangıç girişi yapmak için, çok para birimli bir Expert Advisor oluşturulmasına azami ölçüde basit bir yaklaşım önermektedir.
ORDER_MAGIC'in Tek Enstrüman Üzerinde Farklı Expert Advisor'larla Alım Satım Yapmak İçin Kullanımı ORDER_MAGIC'in Tek Enstrüman Üzerinde Farklı Expert Advisor'larla Alım Satım Yapmak İçin Kullanımı
Bu makalede, sihirli tanımlama ve farklı Expert Advisor'ların otomatik alım satım işlemlerinin bölünmesi, birleştirilmesi ve senkronizasyonu kullanılarak bilgi kodlama sorunları ele alınmıştır. Söz konusu makale hem yeni başlayanlar hem de daha deneyimli yatırımcılar için ilginç olacaktır; zira Expert Advisor'ların karmaşık senkronizasyon sistemlerinin ve çeşitli stratejilerin uygulanmasında faydalı olabilecek sanal pozisyonlar sorununa değinilmiştir.
Mum Grafik Formasyonlarını Analiz Etme Mum Grafik Formasyonlarını Analiz Etme
Japon mum grafiğinin oluşturulması ve mum grafik formasyonlarının analizi, teknik analizin muhteşem bir alanını teşkil eder. Mum grafiklerin avantajı, verileri, verilerin içindeki dinamikleri takip edebileceğiniz şekilde temsil etmeleridir. Bu makalede mum grafik türlerini, mum grafik formasyonlarının sınıflandırılmasını analiz edecek ve mum grafik formasyonlarını belirleyebilecek bir gösterge sunacağız.