English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
Göstergelerin Ekonomik Hesaplanmasına İlişkin Prensipler

Göstergelerin Ekonomik Hesaplanmasına İlişkin Prensipler

MetaTrader 5Göstergeler | 15 Aralık 2021, 10:06
187 0
Nikolay Kositsin
Nikolay Kositsin

Giriş

İnsanların pratik faaliyetlerinin şu veya bu bölümünde kaynakların korunması fikri, belki de insani gelişme ve ilerleme yolundaki en önemli ve ivedi konulardan biridir. Bu bağlamda MQL5'te programlama bir istisna değildir. Elbette, görevlerin kapsamı yalnızca görsel alım satımla sınırlıysa, o zaman birçok programlama kusuru fark edilmeden kalabilir.

Ancak otomatik alım satımla ilgili her şey, başlangıçta kodun maksimum düzeyde ekonomik olarak yazılmasını gerektirir; aksi takdirde, alım satım robotlarının test edilmesi ve optimizasyonu süreci o kadar uzun bir süreye yayılabilir ki, bunlar tamamlanıncaya kadar beklemek neredeyse imkansız olur. Bu tür bir durumda değerli bir şey yaratma fikri oldukça şüpheli görünüyor.

Bu nedenle, alım satım stratejilerini uygulama işine girişmeden önce, Expert Advisor'ların optimizasyon ve test süresi üzerinde etkisi olan programlama ayrıntıları konusunda daha fazla bilgi edinmek mantıklı olacaktır. Ve Expert Advisor'ların çoğu, kodlarında kullanıcı gösterglerine çağrılar içerdiği için sanırım onlarla başlamalıyız.

Genel olarak, göstergeler oluşturulurken dikkate alınması gereken çok fazla ilgili nokta yoktur; bu nedenle her birini sırayla gözden geçirmek en mantıklısı olacaktır.

Klasik göstergelerde henüz hesaplanmamış, yeni ortaya çıkan çubukların her bir gösterge tick'ini yeniden hesaplama

RSI, ADX, ATR, CCI vb. gibi klasik göstergelerin özü, kapalı çubuklarda bu göstergelerin hesaplanmasının yalnızca bir kez yapılabilmesi ve bundan sonra hesaplamaların yalnızca yeni ortaya çıkan çubuklar üzerinde yapılabilmesidir. Tek istisna, bu çubuk kapanana kadar hesaplamanın her tick'te tekrar tekrar yapıldığı mevcut açık çubuktur.

Hesaplanmayan çubuklardaki göstergeleri hesaplamanın mantıklı olup olmadığını bulmanın en kolay yolu, strateji test cihazında, her zaman bu tür (optimize edilmiş) göstergeleri çalıştırmanın sonuçlarını tüm çubuklarda hesaplanan göstergelerle karşılaştırmaktır (optimize edilmemiş).

Bu, oldukça kolay bir şekilde yapılır. OnInit () ve OnTick ()'in boş işleviyle bir Expert Advisor oluşturulur. Yapmanız gereken tek şey, çağrıyı optimize edilmiş veya optimize edilmemiş göstergenin gerekli sürümündeki Expert Advisor'a yazmak ve her iki durumda da bu tür expert'lerin test cihazındaki çalışmalarına ilişkin sonuçları taktir etmek. Örnek olarak, "Yeni Başlayanlar için MQL5'te Kullanıcı Göstergeleri" adlı makalemden SMA.mq5 göstergesini alacağım; burada satır değişimi yapacağım.  

   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

tarih 

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

Sonuç olarak, programlama kodunun (SMA !!!!!!. mq5) optimize edilmemiş bir sürümünü alıyorum; bu, orijinalin aksine, her bir tick'te tüm değerlerini yeniden hesaplayacaktır. Açıkçası, her iki durumda da expert kodunun sürümleri pratik olarak aynıdır; bu nedenle bunlardan yalnızca birini sağlayacağım (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);
//----+
  }
//+------------------------------------------------------------------+

Şimdi testlere başlayabiliriz. Bu makaledeki tüm testlerde, çubuk değişikliklerine ilişkin gerçeğe mümkün olduğunca yakın bir simülasyon modu kullanacağımıza dikkat edilmelidir - "Her tick"!

Şek.1 Expert Advisor SMA_Test test yapılandırmaları 

Test cihazında optimize edilmiş bir gösterge çalıştırmanın sonucu şu şekildedir:

Şek.2 Expert Advisor SMA_Test testinin sonucu 

Kırmızı renk, testin geçtiği süreyi gösterir. Bunun çok fazla olduğunu söyleyemem! Fakat SMA !!!!!!. mq5 göstergesinin test edilmesinin tamamlanması için çok uzun süre beklemek zorunda kaldık!

Şek.3 Expert Advisor SMA !!!!!!_ Test testinin sonucu 

Temel olarak, bu durumda test işleme süresi, önceki testten 500 kat fazla farklılık gösterir. Ve bu, yeterince kısa bir test süresi seçilmesine rağmen meydana gelir. Ancak Expert Advisor'ın testi sırasında bu kadar büyük hesaplama maliyetlerine katlanabiliyorken, parametrelerinin optimizasyonunu unutsak iyi olur!

Bu nedenle, bu, ekonomik olarak yazılmış bir kodun yalnızca programlama alanındaki profesyoneller için bir eğlence aracı değil, daha çok kendi kodunuzu yazmak için oldukça güncel bir yaklaşım olduğu gerçeğinin en anlamlı kanıtıdır.

İnternette, performansını en üst düzeye çıkarmak için kişisel bilgisayarların hızlandırılmasına tahsis edilmiş Overclockers.ru adlı bir web sitesi vardır. Bu uygulamanın temel yolu, CPU ve RAM belleğinin saat hızını artırmak için çok daha pahalı bilgisayar bileşenlerinin kullanılmasıdır.

Bu yapıldıktan sonra, bu hız aşırtmalı CPU için daha pahalı bir su soğutma sistemleri veya hatta bir sıvı nitrojen işlemcisine daldırma kullanılır. Bu tür eylemlerin sonucu, bilgisayar performansının iki kat, hatta üç kat artmasıdır.

Kodun yetkin, ekonomik bir şekilde yazılması, genellikle çok az çaba sarf ederken çok şey elde etmemize yardımcı olabilir. Elbette, bu yöntem bir Celleron300A'yı Core 2 Quad Q6600'e dönüştüremez fakat normal, standart bütçeli bir bilgisayarı, yalnızca üst model bir bilgisayardan beklenebilecek şekilde çalışır hale getirmemizi sağlar!

Oldukça klasik olmayan bazı göstergelerde mevcut kapalı çubuğu tekrar tekrar hesaplama

Ve bu program kodu optimizasyonu yöntemi, ayrım gözetmeksizin tüm göstergeler için uygun olsaydı, her şey mükemmel olurdu! Ama ne yazık ki, bu gerçek değil. Bu tür bir yaklaşım kapsamında, göstergenin halihazırda mevcut olan geçmiş verilere yüklenmesi sırasında normal olarak yalnızca bir kez hesaplamaya başlayan bir dizi gösterge vardır.

Ve göstergeyi yükledikten sonra beliren tüm çubuklarda değerlerinin tamamen yanlış olduğu ortaya çıkıyor. Bunun olmasının ana nedeni, gösterge kodundaki bazı değişkenlerin, önceki çubuktaki göstergenin hesaplanmasından sonra aynı değişkenlere sahip olan göstergelere bağımlı olmasıdır. Bu, resmen şu şekilde görünecektir:

                                                                                                                                                                                                                           

SomeVariable(çubuk) = İşlev(SomeVariable(çubuk - 1))

 

Burada:

  • SomeVariable() — bir çubuk için bir değişkenin değeri,
  • çubuk - hesaplamanın yapıldığı çubuk numarası.

Bariz nedenlerden dolayı, gerçek kodda, bu tür bağımlılıklar daha az net bir işlevsel forma sahiptir. Ancak bunun özü değişmez; örneğin, T3'ü (optimize edilmemiş gösterge - T3 !!!!!!. mq5) taşımak için kodun bizimle ilgili kısmı şu şekilde görünür:

   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 değişkenleri tam olarak bu tip bir işlevsel bağımlılığa sahiptir; bu da her yeni çubuğun hesaplanması için bu kodun yalnızca bir kez kullanılmasını içerir! Fakat mevcut çubuk, benzer bir hesaplama yoluyla, kapatılana kadar tekrar tekrar atlanacaktır.

Ve mevcut çubuktaki bu değişkenlerin değerleri her zaman değişecektir ama mevcut çubuk için, değiştirmeden önce, önceki çubuktaki hesaplamadan sonra olduğu gibi kalmaları gerekir!

Bu nedenle, bu değişkenlerin bir önceki çubuktaki değerleri (mevcut çubukla ilgili olarak) statik değişkenlerde saklanmalı ve bunlar, değişkenlerin sondan bir önceki değerlerinin tekrar e1, e2, e3, e4, e5, e6 olarak saklanması gerektiği çubuğun bir sonraki değişikliğine kadar yeniden kullanılmak üzere aktarılmalıdır.

Değerlerle benzer işlemleri yapan ek kod oldukça basittir. Her şeyden önce, değerleri OnCalculate() işlevi içinde saklamak için yerel statik değişkenleri bildirmelisiniz.

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

Bundan sonra, yeni ortaya çıkan çubukların sayısı sıfırdan büyük olduğu anda, herhangi bir hesaplama yapmadan önce, mevcut çubuk üzerindeki döngüde bulunan değişken değerlerinin belleğe alınması gelir:

     //---- 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;
      }

Ve döngü işlecinin bloğundan önce, değişkenlerin değerlerini ters dönüşüm yoluyla geri yükleyin:

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

Oldukça doğal olarak, hesaplanan katsayıların başlangıç başlatma işlemi artık OnCalculate () işlevinin ilk başlangıcında yalnızca bir kez yapılır ve şimdi başlatma, katsayıların kendilerinden değil, karşılık gelen statik değişkenlerinden yapılır.

//---- 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];
    }

Sonuç olarak, nihai gösterge T3.mq5 en uygun maliyetli şekilde hesaplamalar yapmaya başlamış oldu. Her şey bir hiç olurdu, ancak benzer işlevsel bağımlılıklar her zaman bu kadar kolay tanımlanamaz. Bu durumda, tüm gösterge değişkenlerinin değerleri statik değişkenlerde belleğe alınabilir ve aynı şekilde geri yüklenebilir.

Ancak bundan sonra, hangi değişkenlerin gerçekten kurtarılması gerektiğini ve hangileri için böyle bir ihtiyacın söz konusu olmadığını anlamaya başlayabiliriz. Bunu yapmak için, göstergenin optimize edilmemiş ve optimize edilmiş sürümlerini grafiğe asmalı ve çalışmalarını kontrol ederek, her seferinde bir değişkeni kademeli olarak kurtarma listesinden çıkarmalıyız. Sonunda, elimizde yalnızca gerçekten kurtarılması gereken değişkenler var.

Doğal olarak, mevcut çubuğun ve yeni ortaya çıkan çubukların yeniden sayımının olduğu normal göstergelerin program koduyla çalışmak için bu mantık sürümünü sağladım. Yeniden çizilen ve geleceğe bakan göstergeler için, bu göstergelerin benzersiz özelliklerinden dolayı benzer, çok standart ve basit bir kod optimizasyonu yöntemi oluşturamayacağız. Ve deneyimli Expert Advisor yazarlarının çoğu bunu gerçek bir ihtiyaç olarak görmemektedir. Bu nedenle, bu göstergelerin ayrıntılı analizinin tamamlandığını düşünebileceğimiz yer burasıdır.

MQL5-kodunu aşırı derecede yavaşlatabilen gösterge çağrılarının özellikleri 

Görev tamamlanmış gibi görünüyor, çubukları en ekonomik şekilde sayan optimize edilmiş bir göstergemiz var; şimdi birkaç kod satırı yazmak ve gösterge arabelleğinden hesaplanan değerleri almak için bu göstergeyi Expert Advisor'ın veya göstergenin koduna çağırmak yeterli.

Ancak bu, bu birkaç kod satırının arkasında ne tür işlemlerin olduğunu anlamaya zahmet etmeden resmi bir meseleye yaklaşıldığında göründüğü kadar kolay değil.

Tıpkı MQL5'teki zaman serilerinde olduğu gibi, kullanıcı ve teknik göstergelerden değerlerin alınmasının incelikleri, bunun, verilerin kullanıcı değişken dizilerine kopyalanması yoluyla yapılmasıdır. Bu, cari hesaplar için tamamen gereksiz verilerin birikmesine yol açabilir.

Tüm bunları bazı teknik göstergelerden belirli bir veri alıcısında doğrulamanın en kolay yolu. Örnek olarak, iAMA hareketini alabilir ve bu teknik gösterge temelinde özel bir AMkA göstergesi oluşturabiliriz.

Verileri kopyalamak için, CopyBuffer () işlev çağrısının ilk sürümünü bir başlangıç pozisyonu talebi ve kopyalama için gerekli öğelerin sayısı ile kullanacağız. AMkA göstergesinde, mevcut çubuk üzerindeki Hareketli artış, teknik bir gösterge Standart Sapma kullanılarak işlenir ve ardından alım satım sinyallerini elde etmek için bu artış, işlenen toplam standart sapma değeri ile karşılaştırılır.

Bu nedenle, AMkA göstergesinin uygulanması için en basit durumda, ilk olarak gösterge arabelleğinin Hareketli artış değerini (dAMA göstergesi) içerdiği bir gösterge oluşturmalısınız. Bunun ardından, diğer göstergede, AMA artışlarıyla gösterge vasıtasını kullanarak, Standart Sapma göstergesi tarafından işlenen sonuç değerini elde ederiz.

Benzer göstergelerin oluşturulma süreci, bu konularla ilgili çeşitli makalelerde zaten ayrıntılı olarak incelenmiştir; bu nedenle bunun üzerinde durmayacağım ve yalnızca başka bir göstergenin kodunda, çağrılan göstergenin gösterge arabelleklerine erişim ayrıntılarını analiz edeceğim.

İnternetin engin kaynaklarında, yazarlarının gösterge arabelleklerinin tüm içeriğini tam anlamıyla orta, dinamik dizilere kopyaladığı MQL5 örneklerinin ortaya çıktığını halihazırda görüyoruz. Ve bundan sonra, tüm değerler bu ara dizilerden son gösterge arabelleklerine döngü işleci kullanılarak birer birer aktarılır.

Sorunumuzu çözmek için bu yaklaşım son derece basit görünüyor

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

(dAMA !!!!!!. mq5 göstergesi) veya bunun gibi 

   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
    */     
    }

Ancak böyle iddiasız bir çözümün bedeli nedir? Öncelikle, azami rasyonel hareket tarzının ne olacağı konusunda biraz bilgi sahibi olmak en iyisi olacaktır. İlk olarak, Array [] ara dizisini kullanmak için ciddi şekilde haklı bir gereksinim yoktur ve veriler doğrudan AMA [] gösterge arabelleğine kopyalanmalıdır.

İkincisi, her gösterge tick'inde, değerleri yalnızca üç durumda kopyalamak gerekir:

  • Yeni ortaya çıkan çubuklardan,
  • kapalı çubuklardan,
  • ve mevcut açık çubuklardan.

Gösterge arabelleğinde kalan değerler zaten vardır ve bunların birden fazla kez yeniden yazılması herhangi bir anlam ifade etmez. 

//--- 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); 

 Bu durumda son kodun biraz daha karmaşık olması oldukça doğaldır (dAMA.mq5 göstergesi), ancak şimdi bu makalenin başında önerdiğim metodolojiyi her iki durumda da testler yapmak ve uygun sonuçlara varmak için kullanabiliriz. Bu kez test süresini bir yıla çıkaralım.

Şek.4 Expert Advisor dAMA_Test test yapılandırmaları
 

Son olarak, test cihazı strateji günlüğündeki testi geçtikten sonra, Expert Advisor dAMA_Test'i test etmek için gerekli zamanı elde ederiz.

Şek.5 Expert Advisor dAMA_Test testinin sonucu

Ortaya çıkan test geçme süresi 43.937 ms olup makul bir aralık içindedir. Ne yazık ki, Expert Advisor dAMA !!!!!!_ Test ile benzer ortaya çıkan test geçme süresi elde edildiği söylenemez

Şek.6 dAMA !!!!!!_ Test test expert'ini geçme sonucu
  

Testi geçme süresi, önceki duruma göre yirmi kat daha uzun olan 960 625 ms'dir. Sonuç oldukça açık görünüyor. Kodun gereksiz hesaplamalar yapmaması için en ekonomik şekilde yazılması gerekir!
Yukarıda açıklanan esaslara dayanan AMkA göstergesi yeni bir şey göstermiyor; dolayısıyla bu durumda yalnızca veri kopyalamanın ayrıntıları üzerinde duracağım.

//---- 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);

Artık verilerin tek bir gösterge arabelleğine ve ara hesaplamalar için yerel olarak bildirilen iki dinamik diziye kopyalanması dışında her şey tamamen benzer bir şekilde yapılır. 

Optimizasyon yollarından biri olarak tüm gösterge hesaplamalarının gösterge içinde uygulanması 

Tüm bunlar çok ilginç fakat ardışık kullanıcı ve teknik gösterge çağrılarının bu kadar karmaşık bir yapısı olması biraz fazla şüpheli görünüyor. Ve bu, bir şekilde ölçülmelidir. Ancak bunu yapmak için, kullanıcının göstergeyi içinde yer alacak olan AMkA göstergesinin kodunun olması zarar vermez ve çağrıları diğer göstergeler için kullanmaz.

MQL5'te gösterge yazma sürecini tüm yönleriyle kavrayan bir programcı için bu sorunun çözümü fazla çaba gerektirmez. Öncelikli olarak kullanıcının AMA.mq5 göstergesinin kodu yazılır ve ardından AMkA_.mq5 göstergesinin uygulanması için kodun gerekli öğeleri buna eklenir. Kullanıcı dizisinin AMA göstergesinin artışıyla yüklendiği başka bir ikinci, büyük gösterge hesaplama döngüsü alıyoruz,

   //---- 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]; 

daha sonra bu dizi, dAMA.mq5 göstergesinin verilerine dayalı olarak StDev teknik göstergesinin hesaplanmasına benzer işlemleri gerçekleştirmek için kullanılır.

     //---- 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);

Kodun geri kalanı kesinlikle AMkA.mq5 göstergesinin koduna benzerdir ve bizim için herhangi bir özel ilgi teşkil etmez. Artık AMkA_.mq5 ve AMkA.mq5 göstergelerini AMkA__Test.mq5 ve AMkA_Test.mq5 Expert Advisor'larının yardımıyla test etmeye başlayabiliriz.

AMkA_.mq5 göstergesinin test edilmesinde ortaya çıkan herhangi bir zorluk yoktur ve test süresi kabul edilebilir çerçeve içindedir

Şek.7 Expert Advisor AMkA__Test kullanılarak testi geçmenin sonucu
 

Ancak AMkA.mq5 göstergesi inanılmaz derecede yavaştı

Şek.8 Expert Advisor AMkA_Test kullanılarak testi geçmenin sonucu
 

Sonucunun, "eşdeğerinden" yedi kat daha kötü olduğu ortaya çıktı. Başka hangi yorumlar yapılabilir? Sonuç oldukça açıktır: Birbiri ardına birkaç ardışık gösterge çağrısından oluşan bu tür karmaşık yapıların inşa edilmesi çok ihtiyatlı değildir ve yalnızca ön testler için uygundur!

Açıkçası, bu sonuçlar istemci terminalinin bir test sürümünde elde edildi ve gelecekte nasıl görüneceklerini şu anda söylemek zor. Ancak yaklaşmakta olan alım satım robotları şampiyonasıyla ilgili olarak, bunun ilgili ve verimli bir konu olduğu oldukça açık bir şekilde tartışılabilir.

Expert Advisor'lardan göstergeleri çağırmanın bazı özellikleri

Göstergelerin programlama kodundaki kullanıcı verilerine ve teknik göstergelere erişimin optimizasyonu ile ilgili her şey, Expert Advisor'ların program kodundaki kullanıcı verilerine ve teknik göstergelere erişimin optimizasyonu için eşit derecede geçerlidir. Halihazırda sunulan durumlara ek olarak, Expert Advisor kodunun alım satım sistemlerinin test edilmesini ve optimizasyonunu önemli ölçüde etkileyebilecek başka bir faktörü daha vardır.

Çok sayıda Expert Advisor genellikle gösterge verilerini yalnızca çubuk değişikliği sırasında işler ve bu nedenle bu Expert Advisor'larda her tick için CopyBuffer () işlevinin açılmasına gerek yoktur.

Bu durumda, gösterge arabelleğinden verileri yalnızca bir çubuk değişikliği sırasında almak için Expert Advisor'lara ihtiyaç vardır. Dolayısıyla, göstergelerin çağrıları, gösterge arabelleğinden gerekli tüm verilerin ara hesaplamalar için dizilere başarılı bir şekilde kopyalanması halinde, çubuktaki her değişiklik için erişime yalnızca bir kez izin verilen, parantezlerin arkasındaki blokta yer almalıdır.

Böyle bir filtre görevi gören en iyi şey, mevcut çubukta bir değişiklik olduğu zamana mantıksal bir birim döndüren bir kullanıcı işlevidir. IsNewBar.mqh dosyası, bu işlevin oldukça evrensel olan sürümünü içerir:

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
            )

Bu işlevi Expert Advisor kodunda kullanırken şöyle görünebilir:

    //---- 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); 
     }

Ancak, bu durumda farklı davranmak çok daha mantıklı. Gerçek şu ki, CopyBuffer () işlevini çağırdığınızda, AMA_Array [] dizisindeki veriler kopyalanamayabilir ve böyle bir durumda, filtrenin belirli bir karmaşıklığı yoluyla uygulanan verileri başarılı bir şekilde kopyalama seçeneği ortaya çıkana kadar her tick için bu işlevi çağırmanız gerekecektir.

   //---- 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'ın kodundaki gösterge değerlerini kopyalama işlevinin rasyonel çağrısının ayrıntıları artık netleştiğine göre, Expert Advisor'larda IsNewBar() işlevini uygulamanın faydalarını test edebilirsiniz.

Dolayısıyla, strateji test cihazında test edilmeye hazır iki Expert Advisor seçeneğimiz mevcut; bunlardan ilki AMA_Test.ex5. Her tick'te verileri gösterge arabelleğinden kopyalar.

Şek.9 Expert Advisor AMA_Test ile testi geçmenin sonucu

İkincisi IsNewBar_AMA_Test.mq5 - Verileri yalnızca bir çubuk değişikliği sırasında kopyalar.

Şek.10 Expert Advisor IsNewBar_AMA_Test ile testi geçmenin sonucu

Evet! Test sonuçları biraz hayal kırıklığı yaratıyor. Her tick'te IsNewBar () işlevini çağırmanın, verileri kullanıcı dizisinin üç hücresine kopyalamaktan çok daha pahalı olduğu ortaya çıktı! 

Burada dikkatinizi göstergenin başka bir önemli fakat görünüşte göze çarpmayan kısmına çekmek istiyorum. Gerçek şu ki, OnInit () işlevinde göstergenin vasıtasını alırsak, bu göstergeden gelen verileri OnTick () işlevi içinde kopyalayıp kopyalamamamıza bakılmaksızın, henüz hesaplanmamış ve mevcut çubuklarla ilgili hesaplamaları yine de her tick üzerinde yapılacaktır.

Bu nedenle Expert Advisor'ımız mevcut açık çubuktan elde edilen sayılan gösterge değerlerini gerektirmiyorsa bu değerlerin hesaplanmasını devre dışı bırakmak zaman tasarrufu açısından daha iyidir. Bu, oldukça kolay bir şekilde yapılır - Göstergedeki ana çubuk tekrar sayım döngüsünün sağ kenarını bir değer azaltın Değişikliklerden önce, AMA.mq5 göstergesindeki bu döngü şu şekilde görünüyordu

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

Değişiklikten sonra, bu, şu şekilde görünecek:  

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

AMA_Ex.mq5 göstergesi. Artık bu göstergeyi test edebilirsiniz (Expert Advisor AMA_Ex_Test.mq5)

Şek.11 Expert Advisor AMA_Ex_Test ile testi geçmenin sonucu 

Elbette, bu sonuç, AMA göstergesinin testinden %21 oranında daha iyi; bu çok da kötü sayılmaz ama üzerinde biraz düşünürsek bu sonuç çok daha iyi olabilir.

Sonuç

Sonuç olarak, bir program kodunun verimliliği oldukça nesnel bir parametredir. Verimlilik ölçülebilir, mantıksal olarak analiz edilebilir ve belirli durumlarda önemli ölçüde artırılabilir. Bunun yapıldığı yöntemler çok karmaşık değildir. Tek gereken biraz sabır ve otomatik alım satım sisteminin karlılığını doğrudan etkileyen uygulamalardan fazlasını yapmak.

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

Ekli dosyalar |
mql5.zip (23.38 KB)
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.
MQL5'te Hareketli Ortalamalar Hesaplamasının Test Performansı MQL5'te Hareketli Ortalamalar Hesaplamasının Test Performansı
İlk Hareketli Ortalama göstergesinin oluşturulmasından bu yana bir dizi gösterge ortaya çıktı. Birçoğu benzer yumuşatma yöntemlerini kullanır fakat farklı hareketli ortalama algoritmalarının performansları incelenmemiştir. Bu makalede, MQL5'te Hareketli Ortalamaları kullanmanın olası yollarını ele alacak ve performanslarını karşılaştıracağız.
Google Chart API ile Grafik Oluşturmak için Kitaplık Google Chart API ile Grafik Oluşturmak için Kitaplık
Çeşitli diyagram türlerinin oluşturulması, piyasa durumuna ilişkin analizlerin ve bir alım satım sisteminin test edilmesinin önemli bir parçasıdır. Sıklıkla, güzel görünümlü bir diyagram oluşturmak için, veri çıktısını bir dosyada düzenlemek ve ardından MS Excel gibi uygulamalarda kullanmak gerekir. Bu, çok elverişli değildir ve bizi verileri dinamik olarak güncelleme özelliğinden mahrum eder. Google Charts API, sunucuya özel bir istek göndererek çevrimiçi modlarda grafikler oluşturmak için araçlar sağladı. Bu makalede, böyle bir istek oluşturma ve Google sunucusundan grafik alma sürecini otomatikleştirmeye çalışıyoruz.
Ç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.