
Göstergelerin Ekonomik Hesaplanmasına İlişkin Prensipler
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"!
Test cihazında optimize edilmiş bir gösterge çalıştırmanın sonucu şu şekildedir:
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!
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.
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.
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
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
Ancak AMkA.mq5 göstergesi inanılmaz derecede yavaştı
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.
İkincisi IsNewBar_AMA_Test.mq5 - Verileri yalnızca bir çubuk değişikliği sırasında kopyalar.
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)
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





- Ücretsiz alım-satım uygulamaları
- İşlem kopyalama için 8.000'den fazla sinyal
- Finansal piyasaları keşfetmek için ekonomik haberler
Gizlilik ve Veri Koruma Politikasını ve MQL5.com Kullanım Şartlarını kabul edersiniz