English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
Yeni Başlayanlar için Çoklu Gösterge Arabelleği ile Bir Gösterge Oluşturma

Yeni Başlayanlar için Çoklu Gösterge Arabelleği ile Bir Gösterge Oluşturma

MetaTrader 5Örnekler | 15 Aralık 2021, 09:31
106 0
Nikolay Kositsin
Nikolay Kositsin

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

Ekli dosyalar |
sma_1.mq5 (3.92 KB)
aroon.mq5 (8.04 KB)
aroons.mq5 (6.28 KB)
zigzag.mq5 (9.17 KB)
"Yeni Başlayanlar" için MQL: Nesne Sınıfları Nasıl Tasarlanır ve Oluşturulur? "Yeni Başlayanlar" için MQL: Nesne Sınıfları Nasıl Tasarlanır ve Oluşturulur?
Örnek bir görsel tasarım programı oluşturarak, MQL5'te sınıfların nasıl tasarlanacağını ve oluşturulacağını gösteriyoruz. Makale, MT5 uygulamaları üzerinde çalışan yeni başlayan programcılara yönelik olarak yazılmıştır. Nesne yönelimli programlama teorisine derinlemesine dalmaya gerek kalmadan sınıflar oluşturmak için basit ve kolay kavranabilen bir teknoloji öneriyoruz.
MetaTrader 5 ve MATLAB Etkileşimi MetaTrader 5 ve MATLAB Etkileşimi
Bu makale MetaTrader 5 ve MatLab matematiksel paketi arasındaki etkileşime ilişkin ayrıntıları içermektedir. Ayrıca MatLab masaüstü ile etkileşimde bulunmak için evrensel bir kitaplık geliştirme süreci olan veri dönüştürme mekanizması gösterilmektedir. Bunun yanı sıra MatLab ortamı tarafından oluşturulan DLL kullanımını da kapsamaktadır. Bu makale, C++ ve MQL5 hakkında bilgi sahibi olan deneyimli okuyuculara yöneliktir.
Genetik Algoritmalar - Çok Kolay! Genetik Algoritmalar - Çok Kolay!
Bu makalede yazar, kişisel olarak geliştirilmiş bir genetik algoritmanın kullanımıyla gelişimsel hesaplamaları ele almaktadır. Algoritmanın işleyişini örnekler kullanarak göstermekte olup kullanımı için pratik öneriler sunmaktadır.
Grafik Kontrol Seçenekleri ile Gösterge Oluşturma Grafik Kontrol Seçenekleri ile Gösterge Oluşturma
Piyasa duyarlılığına aşina olanlar MACD göstergesi hakkında bilgi sahibidir (tam adı Hareketli Ortalama Yakınsama/Iraksama'dır) - Bu, yatırımcılar tarafından bilgisayar analiz yöntemlerinin ortaya çıktığı ilk anlardan itibaren kullanılan fiyat hareketini analiz etmek için güçlü bir araçtır. Bu makalede, MACD'ye ilişkin olası değişiklikleri ele alacağız ve bunları, değişiklikler arasında grafiksel olarak geçiş yapma imkanıyla tek bir göstergede uygulayacağız.