English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
MQL5: Kendi Göstergenizi Oluşturma

MQL5: Kendi Göstergenizi Oluşturma

MetaTrader 5Örnekler | 9 Aralık 2021, 10:06
809 0
MetaQuotes
MetaQuotes

Giriş

Bir gösterge nedir? Ekranda uygun bir şekilde görüntülenmesini istediğimiz bir dizi hesaplanmış değerdir. Değer setleri programlarda bir dizi olarak gösterilir. Böylelikle, bir göstergenin oluşturulması, bazı dizileri (fiyat dizileri) idare eden ve diğer dizilere (gösterge değerleri) devretmenin sonuçlarını kaydeden bir algoritmanın yazılması anlamına gelir.

Bazıları çoktan klasikleşmiş olan çok sayıda hazır gösterge olsa bile kişinin kendi göstergelerini oluşturma ihtiyacı her zaman var olacaktır. Kendi algoritmalarımızı kullanarak oluşturduğumuz bu tür göstergeler, özel göstergeler olarak bilinir. Bu makalede, basit bir özel göstergenin nasıl oluşturulacağını inceleyeceğiz.

Göstergeler Farklıdır

Bir gösterge renkli çizgiler veya alanlar olarak sunulabilir veya pozisyonun girilmesi için tercih edilen anları gösteren özel etiketler olarak görüntülenebilir. Ayrıca bu türler birleştirilebilir, bu da daha da fazla gösterge türü olmasını sağlar. William Blau tarafından geliştirilmiş iyi bilinen Doğru Güç Endeksi örneğinde bir gösterge oluşturulmasını inceleyeceğiz.

Doğru Güç Endeksi

TSI göstergesi, trendleri ve aşırı satılan/aşırı alınan alanları tanımlamak için çift düzleştirilmiş momentuma dayanır. Bunun matematiksel açıklamasını şurada bulabilirsiniz: Momentum, Yön ve Ayrışma, William Blau. Burada sadece hesaplama formülünü ele alıyoruz.

TSI(CLOSE,r,s) =100*EMA(EMA(mtm,r),s) / EMA(EMA(|mtm|,r),s)

Burada:

  • mtm = KAPANIŞmevcut – KAPANIŞönceki, geçerli çubuğun ve öncekinin kapanış fiyatları arasındaki farkı belirten değerler dizisi;
  • EMA(mtm,r) = r’ye eşit olan dönem uzunluğu ile mtm değerlerinin üssel düzleştirmesi;
  • EMA(EMA(mtm,r),s) = s dönemi ile EMA(mtm,r) değerlerinin üssel düzleştirmesi;
  • |mtm| = mutlak değerler mtm;
  • r = 25,
  • s = 13.

Bu formülden, gösterge hesaplamasını etkileyebilecek üç parametreyi alabiliriz. Bunlar r ve s dönemleri ve hesaplamalar için kullanılan fiyat türleridir. Kendi örneğimizde KAPANIŞ fiyatını kullanacağız.

MQL5 Sihirbazı

TSI’yi mavi çizgi olarak görüntüleyelim; burada MQL5 Sihirbazını başlatmamız gereklidir. İlk aşamada oluşturmak istediğimiz program türünü belirtmeliyiz - özel gösterge. İkinci aşamada program adını, r ve s parametrelerini ve bunların değerlerini belirlemeliyiz.

MQL5 Sihirbazı: Gösterge adı ve parametresini belirleme

Ardından göstergenin mavi bir çizgi olarak ayı bir pencerede görüntülenmesini belirleyelim ve bu çizgi için TSI etiketini ayarlayalım.

MQL5 Wizard: gösterge türünü belirleme

İlk veriler girildikten sonra Bitti üzerine basarız ve göstergemizin taslağını ediniriz. 

//+------------------------------------------------------------------+
//|                                          True Strength Index.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//---- plot TSI
#property indicator_label1  "TSI"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Blue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- input parameters
input int      r=25;
input int      s=13;
//--- indicator buffers
double         TSIBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,TSIBuffer,INDICATOR_DATA);
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime& time[],
                const double& open[],
                const double& high[],
                const double& low[],
                const double& close[],
                const long& tick_volume[],
                const long& volume[],
                const int& spread[])
  {
//---
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

MQL5 Sihirbazı, gösterge başlığını oluşturur ve burada aşağıdaki gösterge özellikleri yazılır:

  • gösterge ayrı bir pencerede görüntülenir;
  • gösterge tamponlarının sayısı, indicator_buffers=1;
  • çizimlerin sayısı, indicator_plots= 1;
  • çizim No 1 adı, indicator_label1="TSI";
  • ilk çizimin stili - satır, indicator_type1=DRAW_LINE;
  • çizim No 1 rengi, indicator_color1=Blue;
  • bir çizginin stili, indicator_style1=STYLE_SOLID;
  • çizim için çizgi genişliği 1, indicator_width1=1.

Tüm hazırlıklar tamam, şimdi kodumuzu geliştirelim ve iyileştirelim.

OnCalculate()

OnCalculate() fonksiyonu, Hesapla olayının işleyicisidir, gösterge değerlerini yeniden hesaplamak ve grafikte yeniden çizmek gerektiğinde ortaya çıkar. Bu yeni bir tik alma, sembol geçmişi güncellemesi vs. olayıdır. Bu yüzden gösterge değerlerinin tüm hesaplamalarının ana kodu, bu fonksiyonda kesin olarak konumlandırılmalıdır.

Elbette yardımcı hesaplamalar diğer ayrı fonksiyonlara uygulanabilir ama bu fonksiyonlar OnCalculate işleyicisinde kullanılmalıdır.

Varsayılan olarak MQL5 Sihirbazı, tüm zaman serisi türlerine erişim sağlayan ikinci OnCalculate() formunu sunar:

  • Açılış, Yüksek, Düşük, Kapanış fiyatları;
  • hacimler (gerçek ve/veya tik);
  • spread (alım-satım farkı);
  • dönem açılış zamanı.

Bizim örneğimizde sadece bir veri dizisine ihtiyacımız var, bu yüzden OnCalculate() ilk çağrı formunu değiştirelim.

int OnCalculate (const int rates_total,      // size of the price[] array
                 const int prev_calculated,  // number of available bars at the previous call
                 const int begin,            // from what index in price[] authentic data start
                 const double& price[])      // array, on which the indicator will be calculated
  {
//---
//--- return value of prev_calculated for next call
   return(rates_total);
  }  

Bu, göstergeyi sadece fiyat verisine uygulamamızı sağlamakla kalmaz, aynı zamanda göstergeyi diğer göstergelerin değerlerine göre oluşturmamızı da sağlar.

Özel gösterge hesaplaması için veri türünü belirleme

Parametreler sekmesinde (varsayılan olarak sunuluyorsa) Kapanış öğesini seçersek OnCalculate() öğesine iletilen price[] öğesi, kapanış fiyatlarını içerecektir. Örneğin Tipik Fiyat öğesini seçersek, price[]öğesi her bir dönemin fiyatlarını (Yüksek+Düşük+Kapanış)/3 içerecektir.

rates_total parametresi, price[] dizisinin boyutunu belirtir, bir döngüdeki hesaplamaları düzenlemek için faydalı olacaktır. Price[] içindeki öğelerin indislemesi, sıfırdan başlar ve geçmişten geleceğe doğru yönlendirilir. Yani price[0] öğesi en eski değeri içerir, price[rates_total-1] ise son dizi öğesini içerir.

Yardımcı Gösterge Tamponlarının Düzenlenmesi

Bir grafikte yalnızca bir satır, yani bir gösterge dizisinin verisi gösterilecektir. Ancak bundan önce, ara hesaplamaları düzenlemeliyiz. Ara veriler, INDICATOR_CALCULATIONS özniteliği tarafından işaretlenmiş gösterge dizilerinde saklanır. Formül öğesinde ek dizilere ihtiyacımız olduğunu görürüz:

  1. mtm değerleri için - dizi MTMBuffer[];
  2. |mtm| değerleri için - dizi absMTMBuffer[];
  3. EMA(mtm,r) için - dizi EMA_MTMBuffer[];
  4. EMA(EMA(mtm,r),s) için - dizi EMA2_MTMBuffer[];
  5. EMA(|mtm|,r) için - dizi EMA_AbsMTMBuffer[];
  6. EMA(EMA(|mtm|,r),s) için - dizi EMA2_AbsMTMBuffer[].

Toplamda global düzeyde double tipli 6 dizi daha eklememiz ve bu dizileri, OnInit() fonksiyonunda gösterge tamponlarıyla birlikte bağlamamız gereklidir. Gösterge tamponlarının yeni sayısını belirtmeyi unutmayın; indicator_buffers özelliği 7’ye eşit olmalıdır (1 adet vardı ve 6 tampon daha ekledik).

#property indicator_buffers 7

Şimdi gösterge kodu şöyle görünür:

#property indicator_separate_window
#property indicator_buffers 7
#property indicator_plots   1
//---- plot TSI
#property indicator_label1  "TSI"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Blue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- input parameters
input int      r=25;
input int      s=13;
//--- indicator buffers
double         TSIBuffer[];
double         MTMBuffer[];
double         AbsMTMBuffer[];
double         EMA_MTMBuffer[];
double         EMA2_MTMBuffer[];
double         EMA_AbsMTMBuffer[];
double         EMA2_AbsMTMBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,TSIBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,MTMBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(2,AbsMTMBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(3,EMA_MTMBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(4,EMA2_MTMBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(5,EMA_AbsMTMBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(6,EMA2_AbsMTMBuffer,INDICATOR_CALCULATIONS);
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate (const int rates_total,    // size of the price[] array;
                 const int prev_calculated,// number of available bars;
                                           // during the previous call;
                 const int begin,          // from what index in  
                                           // price[] authentic data start;
                 const double& price[])    // array, on which the indicator will be calculated;
  {
//---
//--- return value of prev_calculated for next call
   return(rates_total);
  }

Ara Hesaplamalar

MTMBuffer[] ve AbsMTMBuffer[] tamponları için değerlerin hesaplamasını düzenlemek çok kolaydır. Döngüde price[1] ile price[rates_total-1] arasındaki değerlere tek tek bakın ve farkı bir diziye, farkın mutlak değerini de ikinci diziye yazın.

//--- calculate values of mtm and |mtm|
   for(int i=1;i<rates_total;i++)
     {
      MTMBuffer[i]=price[i]-price[i-1];
      AbsMTMBuffer[i]=fabs(MTMBuffer[i]);
     }

Sonraki aşama, bu dizilerin üssel ortalamasının hesaplamasıdır. Bunu yapmanın iki yolu vardır. İlkinde hiç hata yapmamaya çalışarak tüm algoritmayı yazarız. İkinci yöntemde zaten hatası ayıklanmış ve tamamen bu amaca yönelik olan hazır fonksiyonları kullanırız.

MQL5’te hareketli ortalamaları dizi değerleriyle hesaplamak için yerleşik fonksiyonlar yoktur ama MovingAverages.mqh adlı bir hazır fonksiyonlar kitaplığı vardır ve buna terminal_directory/MQL5/Include/MovingAverages.mqh yoluyla erişilebilir, burada terminal_directory, MetaTrader 5 terminalinin kurulu olduğu katalogdur. Kitaplık bir içerik dosyasıdır; dört klasik yöntemden birini kullanarak dizilerde hareketli ortalamaları hesaplamak için fonksiyonlar içerir:

  • basit ortalama;
  • üssel ortalama;
  • düzleştirilmiş ortalama;
  • doğrusal ağırlıklı ortalama.

Bu fonksiyonları kullanmak için herhangi bir MQL5 programında kod başlığına aşağıdakileri ekleyin:

#include <MovingAverages.mqh>

Değerler dizisinde üssel hareketli ortalamayı hesaplayan ve ortalamanın değerlerini başka bir diziye kaydeden ExponentialMAOnBuffer() fonksiyonuna ihtiyacımız var.

Bir Dizini Düzleştirme Fonksiyonu

Toplamda MovingAverages.mqh içerik dosyası, her birinde 4 adet olan aynı türde iki fonksiyon grubuna bölünebilen sekiz fonksiyonu içerir. İlk grupta bir diziyi alan ve belirtilen pozisyonda hareketli bir ortalamanın değerini veren fonksiyonlar yer alır:

  • SimpleMA() - basit ortalamanın değerini hesaplamak içindir;
  • ExponentialMA() - üssel ortalamanın değerini hesaplamak içindir;
  • SmoothedMA() - düzleştirilmiş ortalamanın değerini hesaplamak içindir;
  • LinearWeightedMA() - doğrusal ağırlıklı ortalamanın değerini hesaplamak içindir.

Bu fonksiyonlar, tek seferde bir dizi için bir ortalamanın değerini elde etmek içindir ve birden fazla çağrı için optimize edilmemiştir. Bu gruptaki bir fonksiyonu bir döngüde kullanmanız gerekirse (bir ortalamanın değerlerini hesaplamak ve hesaplanan her değeri bir diziye yazmak için) optimal bir algoritma düzenlemeniz gerekecektir.

İkinci fonksiyonlar grubu, ilk değerlerin dizisine dayanan bir hareketli ortalamanın değerleriyle alıcı diziyi doldurmak içindir:

  • SimpleMAOnBuffer() - price[] dizisinden basit bir ortalamanın değerleriyle buffer[] çıktı dizisini doldurur;
  • ExponentialMAOnBuffer() - price[] dizisinden basit bir ortalamanın değerleriyle buffer[] çıktı dizisini doldurur;
  • SmoothedMAOnBuffer() - price[] dizisinden düzleştirilmiş bir ortalamanın değerleriyle buffer[] çıktı dizisini doldurur;
  • LinearWeightedMAOnBuffer() - price[] dizisinden doğrusal ağırlıklı bir ortalamanın değerleriyle buffer[] çıktı dizisini doldurur.

Buffer[], price[] dizileri ve dönem ortalama dönemi hariç belirtilen tüm fonksiyonlarda 3 parametre daha bulunur ve bunun amacı, OnCalculate() fonksiyonu - rates_total, prev_calculated ve begin parametreleri ile benzeşir. Bu grubun fonksiyonları, indisleme yönünü (AS_SERIES bayrağı) dikkate alarak price[] ve buffer[] öğelerinin iletilen dizilerini doğru şekilde işler.

Begin parametresi, anlamlı verinin, yani işlenmesi gereken verinin başladığı bir kaynak dizisinin indisini belirtir. MTMBuffer[] dizisi için gerçek veri, MTMBuffer[1]=price[1]-price[0] öğesinden dolayı indis 1 ile başlar. MTMBuffer[0] değeri tanımlanmamıştır, bu yüzden begin=1 olmalıdır.

//--- calculate the first moving
   ExponentialMAOnBuffer(rates_total,prev_calculated,
                         1,  // index, starting from which data for smoothing are available 
                         r,  // period of the exponential average
                         MTMBuffer,       // buffer to calculate average
                         EMA_MTMBuffer);  // into this buffer locate value of the average
   ExponentialMAOnBuffer(rates_total,prev_calculated,
                         1,r,AbsMTMBuffer,EMA_AbsMTMBuffer);

Ortalama alırken dönem değeri dikkate alınmalıdır çünkü çıktı dizisinde hesaplanan değerler küçük bir gecikmeyle doldurulur ve bu gecikme, daha büyük ortalama dönemlerinde daha büyüktür. Örneğin period=10 ise bunun sonucundaki dizideki değerler begin+period-1=begin+10-1 ile başlayacaktır. Sonraki buffer[] çağrılarında bu durum dikkate alınmalıdır ve işleme, begin+period-1 indisi ile başlamalıdır.

Böylece ikinci üssel ortalamayı MTMBuffer[] ve AbsMTMBuffer dizilerinden kolayca elde edebiliriz:

//--- calculate the second moving average on arrays
   ExponentialMAOnBuffer(rates_total,prev_calculated,
                         r,s,EMA_MTMBuffer,EMA2_MTMBuffer);
   ExponentialMAOnBuffer(rates_total,prev_calculated,
                         r,s,EMA_AbsMTMBuffer,EMA2_AbsMTMBuffer);

Begin değeri şimdi r’ye eşittir çünkü begin=1+r-1 şeklindedir (r, birincil üssel ortalamanın dönemidir, işleme indis 1 ile başlar). EMA2_MTMBuffer[] ve EMA2_AbsMTMBuffer[] çıktı dizilerinde hesaplanan değerler r+s-1 indisi ile başlar çünkü girdi dizilerini r indisi ile işlemeye başladık ve ikincil üssel ortalama dönemi s’ye eşittir.

Ön hesaplamaların hepsi hazır olduğuna göre şimdi grafikte çizilecek olan TSIBuffer[] gösterge tamponunun değerlerini hesaplayabiliriz.

//--- now calculate values of the indicator
   for(int i=r+s-1;i<rates_total;i++)
     {
      TSIBuffer[i]=100*EMA2_MTMBuffer[i]/EMA2_AbsMTMBuffer[i];
     }
F5 tuşuna basarak kodu tamamlayın ve MetaTrader 5 terminalinde başlatın. İşe yarıyor!

Doğru Güç Endeksinin ilk versiyonu

Hala sorulacak sorular var.

Hesaplamaların Optimize Edilmesi

Aslında çalışma göstergesi yazmak için bu kadarı yeterli değil. OnCalculate() öğesinin mevcut uygulamasına dikkatli bakarsak bunun optimal olmadığını görürüz.

int OnCalculate (const int rates_total,    // size of the price[] array;
                 const int prev_calculated,// number of available bars;
                 // at the previous call;
                 const int begin,// from what index of the 
                 // price[] array true data start;
                 const double &price[]) // array, at which the indicator will be calculated;
  {
//--- calculate values of mtm and |mtm|
   MTMBuffer[0]=0.0;
   AbsMTMBuffer[0]=0.0;
   for(int i=1;i<rates_total;i++)
     {
      MTMBuffer[i]=price[i]-price[i-1];
      AbsMTMBuffer[i]=fabs(MTMBuffer[i]);
     }
//--- calculate the first moving average on arrays
   ExponentialMAOnBuffer(rates_total,prev_calculated,
                         1,  // index, starting from which data for smoothing are available 
                         r,  // period of the exponential average
                         MTMBuffer,       // buffer to calculate average
                         EMA_MTMBuffer);  // into this buffer locate value of the average
   ExponentialMAOnBuffer(rates_total,prev_calculated,
                         1,r,AbsMTMBuffer,EMA_AbsMTMBuffer);

//--- calculate the second moving average on arrays
   ExponentialMAOnBuffer(rates_total,prev_calculated,
                         r,s,EMA_MTMBuffer,EMA2_MTMBuffer);
   ExponentialMAOnBuffer(rates_total,prev_calculated,
                         r,s,EMA_AbsMTMBuffer,EMA2_AbsMTMBuffer);
//--- now calculate values of the indicator
   for(int i=r+s-1;i<rates_total;i++)
     {
      TSIBuffer[i]=100*EMA2_MTMBuffer[i]/EMA2_AbsMTMBuffer[i];
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }

Her fonksiyonun başlangıcında MTMBuffer[] ve AbsMTMBuffer[] dizilerindeki değerleri hesaplarız. Bu durumda price[] öğesinin boyutu yüz binlerce veya hatta milyonlarca değere eşitse gereksiz tekrarlanan hesaplamalar, ne kadar güçlü olursa olsun tüm CPU kaynaklarını tüketebilir.

Optimal hesaplamaları düzenlemek için önceki çağrıda OnCalculate() tarafından verilen değere eşit olan prev_calculated giriş parametresini kullanırız. Fonksiyonun ilk çağrısında prev_calculated değeri her zaman 0’a eşittir. Bu durumda gösterge tamponundaki tüm değerleri hesaplarız. Sonraki çağrıda tüm tamponu hesaplamamız gerekmez, sadece son değer hesaplanacaktır. Şöyle yazalım:

//--- if it is the first call 
   if(prev_calculated==0)
     {
      //--- set zero values to zero indexes
      MTMBuffer[0]=0.0;
      AbsMTMBuffer[0]=0.0;
     }
//--- calculate values of mtm and |mtm|
   int start;
   if(prev_calculated==0) start=1;  // start filling out MTMBuffer[] and AbsMTMBuffer[] from the 1st index 
   else start=prev_calculated-1;    // set start equal to the last index in the arrays 
   for(int i=start;i<rates_total;i++)
     {
      MTMBuffer[i]=price[i]-price[i-1];
      AbsMTMBuffer[i]=fabs(MTMBuffer[i]);
     }

EMA_MTMBuffer[], EMA_AbsMTMBuffer[], EMA2_MTMBuffer[] ve EMA2_AbsMTMBuffer[] hesaplama blokları, hesaplamaların optimizasyonunu gerektirmez çünkü ExponentialMAOnBuffer() zaten optimal şekilde yazılmıştır. Yalnızca TSIBuffer[] dizisinin değerlerinin hesaplamasını optimize etmemiz gereklidir. MTMBuffer[] için kullanılan yöntemin aynısını kullanırız.

//--- now calculate the indicator values
   if(prev_calculated==0) start=r+s-1; // set the starting index for input arrays
   for(int i=start;i<rates_total;i++)
     {
      TSIBuffer[i]=100*EMA2_MTMBuffer[i]/EMA2_AbsMTMBuffer[i];
     }
//--- return value of prev_calculated for next call
   return(rates_total);

Optimizasyon prosedürünün son bilgisi: OnCalculate(), rates_total değerini verir. Bu, gösterge hesaplamaları için kullanılan price[] girdi dizisindeki öğelerin sayısı anlamına gelir.

OnCalculate() tarafından verilen değer terminal belleğe kaydedilir ve sonraki OnCalculate() çağrısında prev_calculated giriş parametresinin değeri olarak fonksiyona iletilir.

Bu, OnCalculate() öğesinin önceki çağrısındaki girdi dizisinin boyutunun her zaman bilinmesini ve gösterge tamponlarının hesaplamasının, gereksiz yeniden hesaplamalar olmadan doğru bir indisten yapılmasını sağlar.

Girdi Verisinin Kontrol Edilmesi

OnCalculate() öğesinin doğru çalışması için yapmamız gereken bir şey daha var. Gösterge değerlerinin hesaplandığı price[] dizisinin kontrolünü ekleyelim. Dizinin boyutu (rates_total) çok küçükse hesaplama gerekmez, yeterli veri olduğunda bir sonraki OnCalculate() çağrısını beklememiz gerekir.

//--- if the size of price[] is too small
  if(rates_total<r+s) return(0); // do not calculate or draw anything
//--- if it's the first call 
   if(prev_calculated==0)
     {
      //--- set zero values for zero indexes
      MTMBuffer[0]=0.0;
      AbsMTMBuffer[0]=0.0;
     }

Doğru Güç Endeksini hesaplamak için üssel düzleştirme sırayla iki defa kullanıldığı için price[] boyutu en az r ve s dönemlerinin toplamına eşit veya bundan büyük olmalıdır; aksi takdirde yürütme sonlandırılır ve OnCalculate(), 0 değerini verir. Verilen sıfır değeri, göstergenin grafikte çizilmeyeceği anlamına gelir çünkü değerler hesaplanmamıştır.

Temsilin Ayarlanması

Hesaplamaların doğruluğu açısından gösterge kullanıma hazırdır. Ancak onu başka bir mql5 programından çağırırsak varsayılan olarak Kapanış fiyatları tarafından oluşturulacaktır. Başka bir varsayılan fiyat türü belirtebiliriz: Göstergenin indicator_applied_price özelliğinde ENUM_APPLIED_PRICE numaralandırmasından bir değer belirtin. 

Örneğin, bir fiyat için tipik bir fiyat ayarlamak amacıyla ( (yüksek+düşük+kapanış)/3) aşağıdakileri yazalım:

#property indicator_applied_price PRICE_TYPICAL


iCustom() veya IndicatorCreate() fonksiyonlarını kullanarak sadece değerlerini kullanmayı planlıyorsak daha fazla geliştirmeye gerek yoktur. Ancak doğrudan kullanılırsa, yani grafikte çizilirse ek ayarlar önerilir:

  • göstergenin çizildiği yerden başlayarak çubuk numarası;
  • DataWindow içerisinde yansıtılacak olan TSIBuffer[] içindeki değerler için etiket;
  • fare gösterge çizgisinin üzerine getirildiğinde ayrı bir pencerede ve açılır yardım penceresinde gösterilen göstergenin kısa adı;
  • gösterge değerlerinde gösterilen ondalık noktasından sonra gelen basamak sayısı (bu, doğruluğu etkilemez).

Bu ayarlar Özel Göstergeler grubundaki fonksiyonlar kullanılarak OnInit() işleyicisinde ayarlanabilir. Yeni çizgiler ekleyin ve göstergeyi True_Strength_Index_ver2.mq5 olarak kaydedin.

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,TSIBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,MTMBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(2,AbsMTMBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(3,EMA_MTMBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(4,EMA2_MTMBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(5,EMA_AbsMTMBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(6,EMA2_AbsMTMBuffer,INDICATOR_CALCULATIONS);
//--- bar, starting from which the indicator is drawn
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,r+s-1);
   string shortname;
   StringConcatenate(shortname,"TSI(",r,",",s,")");
//--- set a label do display in DataWindow
   PlotIndexSetString(0,PLOT_LABEL,shortname);   
//--- set a name to show in a separate sub-window or a pop-up help
   IndicatorSetString(INDICATOR_SHORTNAME,shortname);
//--- set accuracy of displaying the indicator values
   IndicatorSetInteger(INDICATOR_DIGITS,2);
//---
   return(0);
  }

Göstergenin her iki versiyonunu da başlatırsak ve grafiği başlangıca getirirsek tüm farkları göreceğiz.


Doğru Güç Endeksi göstergesinin ikinci versiyonu daha iyi görünüyor

Sonuç

Doğru Güç Endeksi göstergesinin oluşturulması örneğine dayanarak MQL5’te herhangi bir göstergeyi yazma sürecindeki temel anları özetleyebiliriz:

  • Kendi özel göstergenizi oluşturmak için gösterge kurulumunda ön rutin işlemleri gerçekleştirmenize yardımcı olacak MQL5 Sihirbazını kullanın. OnCalculate() fonksiyonunun gereken değişkenini seçin.
  • Gerekirse ara hesaplamalar için daha fazla dizi ekleyin ve bunları SetIndexBuffer() fonksiyonunu kullanarak ilgili gösterge tamponlarıyla bağlayın. Bu tamponlar için INDICATOR_CALCULATIONS türünü belirtin.
  • OnCalculate() içindeki hesaplamaları optimize edin çünkü fiyat verisi her değiştiğinde bu fonksiyon çağrılacaktır. Kod yazmayı kolaylaştırmak için zaten hatası ayıklanmış fonksiyonları kullanın.
  • Hem diğer mql5 programları hem de kullanıcılar için programı kolay kullanılır kılmak için göstergenin ek görsel ayarlarını yapın.

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

Bir Göstergenin Diğerine Uygulanması Bir Göstergenin Diğerine Uygulanması
OnCalculate() fonksiyon çağrısının kısa biçimini kullanan bir gösterge yazarken, bir göstergenin yalnızca fiyat verileriyle değil, aynı zamanda başka bir göstergenin verileriyle de hesaplanabileceği gerçeğini kaçırabilirsiniz. Diğer göstergelerin verilerine doğru uygulanması için bir göstergeyi geliştirmek ister misiniz? Bu makalede, bu tür bir değişiklik için gereken tüm adımları gözden geçireceğiz.
Yeni Raylara Adım Atın: MQL5'te Özel Göstergeler Yeni Raylara Adım Atın: MQL5'te Özel Göstergeler
Yeni terminalin ve dilin tüm yeni olanaklarını ve özelliklerini listelemeyeceğim. Bunlar sayısızdır ve bazı yenilikler ayrı bir makalede tartışılmaya değerdir. Ayrıca burada nesne yönelimli programlama ile yazılmış bir kod yoktur, geliştiriciler için ek avantajlar olarak bir bağlamda basitçe bahsedilemeyecek kadar ciddi bir konudur. Bu makalede, MQL4'e kıyasla göstergeleri, yapılarını, çizimlerini, türlerini ve programlama ayrıntılarını ele alacağız. Umarım bu makale hem yeni başlayanlar hem de deneyimli geliştiriciler için faydalı olacaktır, belki bazıları yeni bir şeyler bulacaktır.
Uzman Danışmanlarda Sınırlamalar ve Doğrulamalar Uzman Danışmanlarda Sınırlamalar ve Doğrulamalar
Pazartesi günü bu sembolün alım satımına izin verilir mi? Pozisyon açmak için yeterli para var mı? Zararı Durdur tetiklenirse kayıp ne kadar büyük olur? Bekleyen emirlerin sayısı nasıl sınırlandırılır? Alım satım işlemi mevcut çubukta mı yoksa önceki çubukta mı gerçekleştirildi? Bir alım satım robotu bu tür doğrulamaları gerçekleştiremezse, herhangi bir alım satım stratejisi kaybeden bir stratejiye dönüşebilir. Bu makale, herhangi bir Uzman Danışmanda yararlı olan doğrulama örneklerini gösterir.
İşte Karışınızda Yeni MetaTrader 5 ve MQL5 İşte Karışınızda Yeni MetaTrader 5 ve MQL5
Bu MetaTrader 5 ile ilgili sadece kısa bir inceleme. Sistemin tüm yeni özelliklerini bu kadar kısa sürede açıklayamam, test süreci 09.09.2009’da başladı. Bu sembolik bir tarihtir ve şanslı sayı olacağına eminim. MetaTrader 5 terminalinin ve MQL5’in beta sürümünü beş gün önce aldım. Tüm özelliklerini deneme şansım olmadı ama şimdiden etkilendim.