
Yeni Başlayanlar için Çoklu Gösterge Arabelleği ile Bir Gösterge Oluşturma
Giriş
"Yeni Başlayanlar için MQL5'te Özel Göstergeler" ve "Yeni Başlayanlar için MQL5'te Dijital Dosyaların Pratik Uygulaması" adlı önceki makalelerimde tek bir gösterge arabelleğine sahip göstergenin yapısına odaklandım.
Açıkçası, bu tip bir yöntem özel göstergeler yazmak için yaygın olarak uygulanabilir, ancak gerçek hayat onların kullanımıyla pek sınırlı olamaz ve bu nedenle gösterge kodunu oluşturmak için daha karmaşık yöntemlere başvurmanın zamanı geldi. Neyse ki, MQL5'in özellikleri gerçekten de bitip tükenmezdir ve yalnızca bilgisayarlarımızın RAM'i ile sınırlıdır.
Kod ikiye katlama örneği olarak Aroon Göstergesi
Bu göstergenin formülü iki bileşen içerir: Ayrı bir grafik penceresinde çizilen yükseliş ve düşüş göstergeleri:
BOĞALAR = (1 - (çubuk - SHIFT(MAX(HIGH(), AroonPeriod)))/AroonPeriod) * 100
AYILAR = (1 - (çubuk - SHIFT(MIN (LOW (), AroonPeriod)))/AroonPeriod) * 100
Burada:
- BOĞALAR - Boğanın gücü,
- AYILAR - Ayının gücü,
- SHIFT() - Çubuğun indeks pozisyonunu belirleme işlevi,
- MAX() - AroonPeriod dönemi boyunca maksimum düzeyi arama işlevi,
- MIN() - AroonPeriod dönemi boyunca minimum düzeyi arama işlevi,
- HIGH() ve LOW() - İlgili fiyat dizileri,
Gösterge formüllerinden, bir gösterge oluşturmak için yalnızca iki gösterge arabelleğine sahip olmamız gerektiği sonucuna varabiliriz; gösterge yapısı önceki makalede ele alınan SMA_1.mq5'in yapısından çok az farklı olacaktır.
Pratik olarak, bu, farklı sayıda gösterge arabelleği ile aynı yinelenmiş koddur. O halde bu göstergenin kodunu MetaEditor'da açalım ve Aroon.mq5 olarak kaydedelim. Şimdi, kodun telif hakkı ve sürüm numarası ile ilgili ilk 11 satırında yalnızca göstergenin adını değiştireceğiz:
//+------------------------------------------------------------------+ //| Aroon.mq5 | //| Copyright 2010, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ //---- copyright #property copyright "2010, MetaQuotes Software Corp." //---- link to the author's site #property link "http://www.mql5.com" //---- version number #property version "1.00"
Daha sonra, 12. kod satırında, göstergenin çizimini temel grafik penceresinden ayrı pencereye değiştirmemiz gerekiyor:
//---- plot indicator in the separate window #property indicator_separate_window
Bu gösterge tamamen farklı bir değer aralığına sahip olduğu için çizimi ayrı bir pencerede yapılacaktır.
Bundan sonra, kodun aşağıdaki 4 satırında (genel gösterge özellikleri), kullanılan gösterge tamponlarının sayısını iki olarak değiştiriyoruz:
//---- two buffers are used #property indicator_buffers 2 //---- two plots are used #property indicator_plots 2
Sonraki 10 kod satırı, belirli bir gösterge arabelleğinden göstergenin çizilmesiyle ilgilidir; bunun etiketinin yinelenmesi gerekir, bunun ardından tüm indeksleri 1'den 2'ye değiştirmeliyiz. Ayrıca gösterge arabelleklerine ait etiketlerin tamamını da değiştirmeliyiz:
//+----------------------------------------------+ //| bullish strength indicator parameters | //+----------------------------------------------+ //---- drawing style = line #property indicator_type1 DRAW_LINE //---- drawing color = Lime #property indicator_color1 Lime //---- line style = solid line #property indicator_style1 STYLE_SOLID //---- line width = 1 #property indicator_width1 1 //---- label of the BullsAroon indicator #property indicator_label1 "BullsAroon" //+----------------------------------------------+ //| bearish strength indicator parameters | //+----------------------------------------------+ //---- drawing style = line #property indicator_type2 DRAW_LINE //---- drawing color = Red #property indicator_color2 Red //---- line style = solid line #property indicator_style2 STYLE_SOLID //---- line width = 1 #property indicator_width2 1 //---- label of the BearsAroon indicator #property indicator_label2 "BearsAroon"
Bu gösterge, 30, 50 ve 70 değerleriyle üç yatay düzey kullanır.
Bu düzeyleri çizmek için göstergenin koduna beş kod satırı daha eklememiz gerekir.
//+----------------------------------------------+ //| Horizontal levels | //+----------------------------------------------+ #property indicator_level1 70.0 #property indicator_level2 50.0 #property indicator_level3 30.0 #property indicator_levelcolor Gray #property indicator_levelstyle STYLE_DASHDOTDOT
Gösterge giriş parametreleri için, önceki göstergeye kıyasla, başlıklardaki küçük değişiklikler dışında her şey aynı kalır:
//+----------------------------------------------+ //| Indicator input parameters | //+----------------------------------------------+ input int AroonPeriod = 9; // Period input int AroonShift = 0; // Horizontal shift of the indicator in bars
Ancak şimdi, gösterge arabellekleri olarak kullanılacak iki dizi olacak ve bunlar, uygun adlara sahip olacaklar:
//--- declare the dynamic arrays used further as indicator buffers double BullsAroonBuffer[]; double BearsAroonBuffer[];
OnInit() işlevinin kodu ile tamamen aynı durumda ilerliyoruz.
İlk olarak, sıfırıncı arabelleğin kod satırlarını değiştiriyoruz:
//--- set BullsAroonBuffer dynamic array as indicator buffer SetIndexBuffer(0, BullsAroonBuffer, INDICATOR_DATA); //--- horizontal shift (AroonShift) of the indicator 1 PlotIndexSetInteger(0, PLOT_SHIFT, AroonShift); //--- plot draw begin (AroonPeriod) of the indicator 1 PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, AroonPeriod); //--- label shown in DataWindow PlotIndexSetString(0, PLOT_LABEL, "BearsAroon");
Bundan sonra, kodun tamamını Windows panosuna kopyalayarak aynı kodun hemen arkasına yapıştırıyoruz.
Ardından yapıştırılan kodda, gösterge arabelleğinin numarasını 0'dan 1'e değiştiriyoruz, gösterge dizisinin adını ve göstergenin etiketini değiştiriyoruz:
//--- set BearsAroonBuffer dynamic array as indicator buffer SetIndexBuffer(1, BearsAroonBuffer, INDICATOR_DATA); //--- horizontal shift (AroonShift) of the indicator 2 PlotIndexSetInteger(1, PLOT_SHIFT, AroonShift); //--- plot draw begin (AroonPeriod) of the indicator 2 PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, AroonPeriod); //--- label shown in DataWindow PlotIndexSetString(1, PLOT_LABEL, "BullsAroon");
Gösterge kısa adı da küçük değişikliklere uğradı:
//--- initialization of the variable for a short indicator name string shortname; StringConcatenate(shortname, "Aroon(", AroonPeriod, ", ", AroonShift, ")");
Şimdi, gösterge çiziminin doğruluğunu değerlendirelim. Göstergenin gerçek aralığı 0 ila 100 aralığındadır ve bu aralık her zaman gösterilir.
Bu durumda, yalnızca grafikte çizilen göstergenin tamsayı değerlerini kullanmak oldukça mümkündür. Bu nedenle, gösterge çizimi için ondalık noktadan sonraki sayılar için 0'ı kullanıyoruz:
//--- set accuracy of drawing of indicator values IndicatorSetInteger(INDICATOR_DIGITS, 0);
SMA_1.mq5 göstergesinde, OnCalculate() işlev çağrısının ilk biçimini kullandık.
High[] ve low[] fiyat dizilerinin olmaması nedeniyle bu, Aroon göstergesi için uygun değildir. Bu diziler, bu işlevin ikinci çağrı biçiminde mevcuttur. Bu nedenle, işlevin üstbilgisinin değiştirilmesi gerekir:
int OnCalculate( const int rates_total, // total bars on the current tick const int prev_calculated,// total bars on the previous tick const datetime& time[], const double& open[], const double& high[], // price array of the maximum prices for the indicator calculations const double& low[], // price array of the minimum prices for the indicator calculations const double& close[], const long& tick_volume[], const long& volume[], const int& spread[] )
Bu değişiklikten sonra başlangıç parametresinin kullanımı anlamını yitirdiği için koddan kaldırılması gerekir!
İşlem döngüsünün değişken değişikliklerinin sınırlarını hesaplama kodu, hesaplama yeterliliği için veri doğrulaması pratikte değişmeden kalmıştır.
//--- checking the number of bars if (rates_total < AroonPeriod - 1) return(0); //--- declare the local variables int first, bar; double BULLS, BEARS; //--- calculation of the first (staring index) for the main loop if (prev_calculated == 0) // checking for the first call of the OnCalculate function first = AroonPeriod - 1; // starting index for calculating all of the bars else first = prev_calculated - 1; // starting index for calculating new bars
Ancak, gösterge değerlerini hesaplamak için kullanılan algoritmalarda bazı sorunlar ortaya çıkmaktadır. Sorun, MQL5'in, mevcut çubuktan itibaren dönem boyunca azalan indeks yönünde maksimum ve minimum düzeylerin indekslerini belirlemek için yerleşik işlevlere sahip olmamasıdır.
Bu durumun bir çözümü, bu işlevleri kendimiz yazmaktır. Neyse ki, bu tür işlevler, "MetaTrader5\MQL5\Indicators\Examples" klasöründe bulunan özel göstergelerin ZigZag.mq5 göstergesinde zaten mevcuttur.
En kolay çözüm ZigZag.mq5 göstergesinde bu işlevlerin kodunu seçmek, bunları Windows panosuna kopyalamak ve örneğin OnInit() işlevini genel düzeyde açıkladıktan hemen sonra bunları kodumuza yapıştırmaktır:
//+------------------------------------------------------------------+ //| searching index of the highest bar | //+------------------------------------------------------------------+ int iHighest(const double &array[], // array for searching for the index of the maximum element int count, // number of the elements in the array (in the decreasing order), int startPos // starting index ) { //---+ int index = startPos; //---- checking the starting index if (startPos < 0) { Print("Incorrect value in the function iHighest, startPos = ", startPos); return (0); } //---- checking the startPos values if (startPos - count < 0) count = startPos; double max = array[startPos]; //---- index search for(int i = startPos; i > startPos - count; i--) { if(array[i] > max) { index = i; max = array[i]; } } //---+ return of the index of the largest bar return(index); } //+------------------------------------------------------------------+ //| searching index of the lowest bar | //+------------------------------------------------------------------+ int iLowest( const double &array[], // array for searching for the index of the maximum element int count, // number of the elements in the array (in the decreasing order), int startPos // starting index ) { //---+ int index = startPos; //--- checking the stating index if (startPos < 0) { Print("Incorrect value in the iLowest function, startPos = ",startPos); return(0); } //--- checking the startPos value if (startPos - count < 0) count = startPos; double min = array[startPos]; //--- index search for(int i = startPos; i > startPos - count; i--) { if (array[i] < min) { index = i; min = array[i]; } } //---+ return of the index of the smallest bar return(index); }
Bundan sonra, OnCalculate() işlevinin kodu aşağıdaki şekilde görünecektir:
//+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate( const int rates_total, // total number of bars on the current tick const int prev_calculated,// number of calculated bars on the previous tick const datetime& time[], const double& open[], const double& high[], // price array for the maximum price for the indicator calculation const double& low[], // price array for the minimum price for the indicator calculation const double& close[], const long& tick_volume[], const long& volume[], const int& spread[] ) { //---+ //--- checking the number of bars if (rates_total < AroonPeriod - 1) return(0); //--- declare the local variables int first, bar; double BULLS, BEARS; //--- calculation of the starting bar number if (prev_calculated == 0) // checking for the first start of the indicator calculation first = AroonPeriod - 1; // starting number for the calculation of all of the bars else first = prev_calculated - 1; // starting number for the calculation of new bars //--- main loop for(bar = first; bar < rates_total; bar++) { //--- calculation of values BULLS = 100 - (bar - iHighest(high, AroonPeriod, bar) + 0.5) * 100 / AroonPeriod; BEARS = 100 - (bar - iLowest (low, AroonPeriod, bar) + 0.5) * 100 / AroonPeriod; //--- filling the indicator buffers with the calculated values BullsAroonBuffer[bar] = BULLS; BearsAroonBuffer[bar] = BEARS; } //---+ return(rates_total); } //+------------------------------------------------------------------+
Eksenlerin simetrisi için, 0,5 değerini kullanarak göstergenin orijinaline kıyasla dikey kaymasını ekleyerek kodda biraz düzelttim.
Burada grafikte bu göstergenin çalışmasının sonuçları verilmiştir:
Geçerli çubuktan AroonPeriod'dan daha uzak olmayan bir mesafede maksimum veya minimum değerlere sahip öğenin pozisyonunu bulmak için MQL5'in aynı zamanda uçdeğerleri de arayan yerleşik ArrayMaximum() ve ArrayMinimum() işlevlerini kullanabiliriz ancak bu işlevler aramayı artan sırada gerçekleştirir.
Ancak, arama azalan indeks sırasına göre yapılmalıdır. Bu durumda en basit çözüm, ArraySetAsSeries() işlevini kullanarak gösterge ve fiyat arabelleklerindeki indeksleme yönünü değiştirmektir.
Fakat aynı zamanda hesaplama döngüsündeki çubuk sıralamasının yönünü ve ilk değişken hesaplamasının algoritmasını değiştirmemiz gerekiyor.
Bu durumda ortaya çıkan OnCalculate() işlevi şu şekilde görünecektir:
//+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate( const int rates_total, // total number of bars on the current tick const int prev_calculated,// number of calculated bars on the previous tick const datetime& time[], const double& open[], const double& high[], // price array for the maximum price for the indicator calculation const double& low[], // price array for the minimum price for the indicator calculation const double& close[], const long& tick_volume[], const long& volume[], const int& spread[] ) { //---+ //--- checking the number of bars if (rates_total < AroonPeriod - 1) return(0); //--- set indexation as timeseries ArraySetAsSeries(high, true); ArraySetAsSeries(low, true); ArraySetAsSeries(BullsAroonBuffer, true); ArraySetAsSeries(BearsAroonBuffer, true); //--- declare the local variables int limit, bar; double BULLS, BEARS; //--- calculation of the starting bar index if (prev_calculated == 0) // check for the first call of OnCalculate function limit = rates_total - AroonPeriod - 1; // starting index for the calculation of all of the bars else limit = rates_total - prev_calculated; // starting index for the calculation of new bars //--- main loop for(bar = limit; bar >= 0; bar--) { //--- calculation of the indicator values BULLS = 100 + (bar - ArrayMaximum(high, bar, AroonPeriod) - 0.5) * 100 / AroonPeriod; BEARS = 100 + (bar - ArrayMinimum(low, bar, AroonPeriod) - 0.5) * 100 / AroonPeriod; //--- filling the indicator buffers with the calculated values BullsAroonBuffer[bar] = BULLS; BearsAroonBuffer[bar] = BEARS; } //----+ return(rates_total); } //+------------------------------------------------------------------+
"First" değişkeninin adını "limit" olarak değiştirdim; bu durumda bu daha uygun.
Bu durumda, ana döngünün kodu, MQL4'te yapıldığına benzer şekilde yapılır. Dolayısıyla, OnCalculate() işlevinin bu yazım stili, minimum kod değişikliği ile göstergelerin MQL4'ten MQL5'e dönüştürülmesi için kullanılabilir.
Sonuç
Bunu gerçekleştirdik! Gösterge yazıldı; hatta iki sürümünde birden..
Bu tür sorunları doğru, ölçülü ve akıllıca çözmenin bir örneğinde çözümler, çocukların Lego kurucusunu kullanarak bir oyuncak yapmalarından biraz daha karmaşık olduğu ortaya çıkıyor.
MetaQuotes Ltd tarafından Rusçadan çevrilmiştir.
Orijinal makale: https://www.mql5.com/ru/articles/48





- Ü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