![Başka Bir Göstergeye Dayalı Bir Gösterge Nasıl Yazılır?](https://c.mql5.com/i/articles/overlay.png)
Başka Bir Göstergeye Dayalı Bir Gösterge Nasıl Yazılır?
Giriş
MQL5'te, "MQL5: Kendi Göstergenizi Oluşturun" makalesinde açıklandığı gibi en baştan yeni bir özel gösterge oluşturmanın yanı sıra, istemci terminalinde yerleşik veya özel bir göstergeye dayalı olarak bir tane yazabilirsiniz. İki yol vardır: birincisi bir göstergeyi iyileştirmek, yeni hesaplamalar ve grafikler eklemek (bu değişken yalnızca açık kaynak koduna sahip özel göstergeler için geçerlidir), ikinci yol ise terminalde yerleşik bir gösterge veya iCustom() ya da IndicatorCreate() fonksiyonları aracılığıyla mevcut bir özel gösterge kullanmaktır.
İlk Yol. Grafik Ekleme
"Bir Göstergeyi Diğerine Uygulama" makalesinden göstergesini iyileştirme örneğinde bu şekilde bir gösterge oluşturma yöntemini ayrıntılı olarak ele alalım. Göstergeye düzleştirme türü ve dönemini seçme imkanı olan bir sinyal satırı ekleyelim. Tüm işlem 8 aşamadan oluşmaktadır.
1. Dosyanın Kopyasını Oluşturma
True_Strength_Index_ver3 göstergesini MetaEditor'da açın ve yeni bir adla, örneğin TSIs altında kaydedin. Yeni dosya, terminal kök klasörünün MQL5/Indicators dizinine kaydedilmelidir.
2. Göstergenin Değişen Özellikleri
Gösterge kodunda indicator_buffers ve indicator_plots özelliklerini arayın. indicator_buffers özelliği, göstergede kullanılan gösterge tamponlarının toplam sayısını belirler, indicator_plots özelliği de bir grafikte görüntülenen tampon sayısını belirler. Şu anda göstergede sekiz tampon kullanılmaktadır; bunlardan biri bir grafikte görüntülenir. Bir grafikte görüntülenmesi gereken başka bir tampon eklememiz gerekiyor. indicator_buffers ve indicator_plots değerlerini birer birer artırın.
#property indicator_buffers 8 #property indicator_plots 2
3. Yeni Tampon Görüntüleme Özelliklerinin Belirlenmesi
Yeni tamponun görüntülenme özelliklerini ayarlayın. Bu göstergeden önceden hazırlanmış kodu kullanın. Fareyi kullanarak, göstergenin ilk satırının görüntülenme özelliklerini belirleyen tüm kodu kopyalayın.
//---- plot TSI #property indicator_label1 "TSI" #property indicator_type1 DRAW_LINE #property indicator_color1 Blue #property indicator_style1 STYLE_SOLID #property indicator_width1 1
İlk satırın özelliklerinin altına ekleyin ve değiştirin.
//---- plot TSI Signal #property indicator_label2 "TSISignal" // Line name that is displayed in a pop up help when the mouse cursor is put over the line #property indicator_type2 DRAW_LINE // Type of buffer #property indicator_color2 Red // Color of the line #property indicator_style2 STYLE_SOLID // Style #property indicator_width2 1 // Thickness of the line
Önce ikinci tamponun özelliği olduğundan, özellik sayısını 1'den 2'ye değiştirin. indicator_label2 özelliğini TSISignal olarak değiştirin, bu fare imleci satırın üzerine getirildiğinde bir açılır pencere yardımında gösterilen satırın ve veri penceresinde görüntülenenin satırın adıdır. indicator_type2 özelliği değiştirilmeden bırakılmalı, tampon bir satır olarak görüntülenmelidir. indicator_color2 özelliğini Kırmızı olarak değiştirin - yeni satır kırmızı renge sahip olacaktır. indicator_style2 özelliği aynı kalır - sinyal hattı ana hat gibi sabittir. indicator_width2 özelliği de aynı kalmalıdır - yeni satır 1 piksel kalınlığa sahip olacaktır.
4. Dış Değişkenleri Bildirme
Gösterge aracılığıyla değiştirilebilen dış değişkenler ("input" (giriş) kelimesiyle başlayan satırlar) koddaki satırların özelliklerinin altında bulunur. Sinyal çizgisi ayrıca kendi parametrelerine sahip olmalıdır - dönem ve düzleştirme türü.
5 değerine sahip int türünde bir dış değişken ve "sp" (düzleştirme dönemi) olarak adlandırın ve MODE_EMA değerine sahip "sm" (düzleştirme yöntemi) adlı ENUM_MA_METHOD türünde bir değişken (sinyal çizgisi düzleştirme dönemi 5’e ve varsayılan olarak üssel düzleştirme türüne sahip olacaktır) bildirin. Şimdi kodun dış değişkenleri içeren bölümü aşağıdaki gibi görünür:
input int r=25; input int s=13; input int sp=5; input ENUM_MA_METHOD sm=MODE_EMA;
5. Yeni Bir Tampon için Dizi Bildirme
Gösterge tamponu tarafından kullanılacak bir dizi bildirelim. Kodda OnInit() fonksiyonunu arayın ve göstergede zaten mevcut olan gösterge tampon dizileri arasında kendinize rehberlik etmesi için SetIndexBuffer() fonksiyonu çağrılarının nerede bulunduğunu bulun. True_Strength_Index_ver3 göstergesinde bu diziler TSIBuffer, MTMBuffer, AbsMTMBuffer, EMA_MTMBuffer, EMA2_MTMBuffer, EMA_AbsMTMBuffer, EMA2_AbsMTMBuffer'dır.
TSIBuffer dizisinin SetIndexBuffer() fonksiyonu, INDICATOR_DATA parametresi ile çağrılır ve bu, tamponun bir grafikte görüntülendiği anlamına gelir. Diğer tüm diziler INDICATOR_CALCULATIONS parametresi ile çağrılır. Bu, dizilerin yardımcı olduğu ve ara hesaplamalar için kullanıldığı anlamına gelir.
Yeni tampon bir grafikte görüntülenmelidir, bu nedenle göstergenin daha da iyileştirilmesi durumunda mantık sırasını korumak ve kodda daha kolay yönlendirme için bunu TSIBuffer dizisinin bildiriminden sonra bildirelim.
Bu nedenle, önce bir grafikte görüntülenen tamponlar için iki dizi, ardından ara hesaplamalarda kullanılan tamponlar için diziler bildiririz.
//--- indicator buffers double TSIBuffer[]; double TSISigBuffer[]; // Array for new buffer of the signal line double MTMBuffer[]; double AbsMTMBuffer[]; double EMA_MTMBuffer[]; double EMA2_MTMBuffer[]; double EMA_AbsMTMBuffer[]; double EMA2_AbsMTMBuffer[];
6. Bir Diziyi Bir Tampon İle İlişkilendirme
Şimdi, daha fazla dikkat ve özen gerektiren oldukça önemli bir adım atacağız - bir dizinin bir gösterge tamponu ile ilişkilendirilmesi. İlişkilendirme, SetIndexBuffer() fonksiyonu kullanılarak gerçekleştirilir. Fonksiyon çağrısındaki ilk parametre dizi indisidir; ikincisi dizi adıdır; üçüncüsü tamponun amacını gösteren tanımlayıcıdır. Tamponlar, bir grafikte çizildikleri sırayla, önce 0 tamponu, ardından bunun üzerinde tampon 1 vs. gibi indise (ilk parametre) göre gösterge özellikleri penceresinin "Renkler" sekmesinde bulunur.
0, 1, 2... indisli tamponlar için SetIndexBuffer() fonksiyonunun sırayla çağrılması gerekli değildir, yine de SetIndexBuffer() fonksiyonlarının çağrı sırasını koruyalım. TSIBuffer dizisinin fonksiyonunu çağırdıktan sonra TSISigBuffer dizisinin çağrısını yürütün. Ana çizginin tamponu (TSIBuffer dizisi) 0 indisine sahiptir ve bu, bir sonraki tamponun (TSISigBuffer dizisi) indis 1'e sahip olması gerektiği anlamına gelir.
TSISigBuffer dizisi için SetIndexBuffer() fonksiyonunu çağırmanın üçüncü parametresi INDICATOR_DATA sabitidir (tampon bir grafikte görüntülenir).
SetIndexBuffer(0,TSIBuffer,INDICATOR_DATA); SetIndexBuffer(1,TSISigBuffer,INDICATOR_DATA);
İlk parametrenin sıralı olarak artan değeriyle çağrılacak SetIndexBuffer() fonksiyonu için tamponların geri kalanını yeniden indisleyin.
SetIndexBuffer(0,TSIBuffer,INDICATOR_DATA); SetIndexBuffer(1,TSISigBuffer,INDICATOR_DATA); SetIndexBuffer(2,MTMBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(3,AbsMTMBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(4,EMA_MTMBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(5,EMA2_MTMBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(6,EMA_AbsMTMBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(7,EMA2_AbsMTMBuffer,INDICATOR_CALCULATIONS);
Bu özel durum için SetIndexBufer() fonksiyonunun çağrılma sırasının artan indislere göre tutulması tavsiye edilir. Böylece daha fazla iyileştirme yapılması durumunda daha az dikkat ve emek harcanacaktır.
Şimdi sekiz tamponumuz var, bunlardan ikisi bir grafikte gösteriliyor. indicator_buffers ve indicator_plots göstergelerinin özelliklerinde aynı değerlerin belirtildiğinden emin olun (2. adım).
7. Sinyal Çizgisi Değerlerinin Hesaplanması
Sinyal çizgisi, göstergenin ana çizgisinin verilerine çizilen hareketli bir ortalamayı temsil eder. Bunun için herhangi bir hesaplama yapmamıza gerek yok; istemci terminalinin iletimi, bir dizi bilgi üzerindeki hareketli ortalamaların hesaplanması için bir kitaplık içerir (MovingAverages.mqh dosyası). Bu arada bu, gösterge koduna zaten dahil edilmiştir (satır 14):
#include <MovingAverages.mqh>
Yapılması gereken tek şey özelliklerini kullanmaktır.
OnCalculate() fonksiyonunda, göstergenin ana çizgisinin (TSIBuffer dizisi) hesaplamalarının bittiği bir nokta bulun. Arama fonksiyonunu kullanalım; örneğin kodun, bunun bildirildiği bölümünde TSIBuffer dizisinin adını seçin (şekil 1). Ardından "Ana Menü" - "Düzenle" - "Bul ve değiştir" - "Bul" komutunu yürütün veya Ctrl+F tuş kombinasyonunu kullanın.
Şekil 1. Dizinin seçilen adı.
Açılan "Bul" penceresinin "Bul" alanına "TSIBuffer" kelimesi zaten yazılacaktır. "Yön" bölümünde "Yukarı" öğesini seçin. Şimdi "Bul" penceresi açıldığında imleci OnCalculate() fonksiyonunun hemen arkasına getirin, "Sonrakini Bul" butonuna bir kez basın ve TSIBuffer dizisinin hesaplamalarının bittiği yeri hemen bulacaksınız. Hesaplamalar "for" döngüsünde yapılır. Bu döngüden hemen sonra sinyal çizgisi hesaplama kodunu ekleyeceğiz (şekil 2).
Şekil 2. TSIBuffer değerinin hesaplanması için son bulunan konum (kırmızı ok). Hesaplamaların yapıldığı döngü kırmızı çerçeve ile işaretlenmiştir.
Dört ana hareketli ortalama türünün tümünün hesaplanmasına yönelik fonksiyonlar, MovingAverages.mqh kitaplığına dahil edilmiştir:
- basit olanı için - SimpleMAOnBuffer(),
- üssel olan için - ExponentialMAOnBuffer(),
- doğrusal ağırlıklı olan için - LinearWeightedMAOnBuffer(),
- düzleştirilmiş olan için - SmoothedMAOnBuffer().
Tüm bu fonksiyonlar aynı parametre setine sahiptir:
const int rates_total, const int prev_calculated, const int begin, const int period, const double& price[],double& buffer[]
Fonksiyonun price[] parametresi, üzerinde hareketli ortalama hesaplamasının gerçekleştirileceği ilk verilerle bir dizi belirler. Tampon parametresi, hareketli ortalamanın değerlerini depolayacak dizidir. rates_total ve prev_calculated parametreleri, onCalculate() fonksiyonunun rates_total ve prev_calculated parametreleriyle aynıdır, bunlar price[] dizisinin boyutunu ve dizinin önceden işlenmiş öğelerinin sayısını belirler. Begin parametresi, önemli verilerin başladığı dizinin bir öğesinin indisidir.
MovingAverages.mqh kitaplığındaki hareketli ortalamaları hesaplama algoritmalarının özelliklerini göz önünde bulundurarak (bu özellikler bu makalenin konusu ile ilgili değildir), begin parametresini ayarlamak için dikkatli bir yaklaşıma ihtiyacımız var.
Bu parametre hiçbir durumda dizinin kaynak veri değerlerinin (TSIBuffer dizisi) başladığı değerden daha önceki bir öğesine ayarlanmamalıdır. Hesaplamalarda hatalara yol açmıyorsa, daha sonraki bir öğenin belirtilmesine izin verilir.
Kabul edilebilir bir begin değeri belirlemek için TSIBuffer dizisinin değerlerinin hesaplandığı for döngüsü parametrelerine dikkat edin - döngü, start değişkeninin değerinden başlar. Göstergenin ilk hesaplaması sırasında sahip olduğu start değişkeninin değerini bulmamız gerekiyor (prev_calculated değeri 0'a eşit olduğunda). "Start" değişkeninin değeri, prev_calculated=0 olduğunda döngüden hemen önce hesaplanır; hesaplama aşağıdaki formül kullanılarak yapılır:
start=begin+r+s-1;
Hareketli ortalama hesaplama fonksiyonuna iletilen begin değişkeninin değeri o değere eşit olmalıdır.
TSIBuffer dizisinin hesaplama döngüsünden sonra, begin2 değişkenini bildirin ve ona begin+r+s-1 değerini atayın.
int begin2=begin+r+s-1;
"sm" dış parametresinin değerine bağlı olarak farklı düzleştirme fonksiyonlarını kullanma imkanı sağlamak için switch operatörünü kullanın. sm değişkeninin her bir değer çeşidi için ilgili fonksiyonun çağrısını yazın.
switch(sm) { case MODE_EMA: ExponentialMAOnBuffer(rates_total,prev_calculated,begin2,sp,TSIBuffer,TSISigBuffer); break; case MODE_LWMA: LinearWeightedMAOnBuffer(rates_total,prev_calculated,begin2,sp,TSIBuffer,TSISigBuffer); break; case MODE_SMA: SimpleMAOnBuffer(rates_total,prev_calculated,begin2,sp,TSIBuffer,TSISigBuffer); break; case MODE_SMMA: SmoothedMAOnBuffer(rates_total,prev_calculated,begin2,sp,TSIBuffer,TSISigBuffer); break; }
Bundan sonra sinyal çizgisi ile göstergeyi görebiliriz. "Derle" düğmesine basın, istemci terminalini açın ve göstergeyi bir tabloya ekleyin (şekil 3).
Şekil 3. Gösterge TSIs, mavi - ana çizgi, kırmızı - yeni, sinyal çizgisi.
8. Tampon Çiziminin Başlangıcının Kesilmesi
Gösterge sol kenarına gelecek şekilde bir grafiği kaydırırsanız, değerlerin hesaplanmadığı kısımda göstergenin çizgiler çizdiğini görürsünüz. Güzel görünmez (şekil 4).
Şekil 4. Hesaplamanın yapılmadığı kısımdaki göstergenin çizimi.
PLOT_DRAW_BEGIN tanımlayıcısıyla çağrılan PlotIndexSetInteger() fonksiyonunu kullanarak, tamponun çizilmediği ilk çubukların sayısını belirleyin. Fonksiyonun çağrısı, göstergenin OnInit() fonksiyonu içinden gerçekleştirilmelidir. Fonksiyon çağrısını OnInit()'in en sonuna, ancak doğal olarak return(0) çağrısından önce ekleyin.
PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,r+s+sp);
"Derle" düğmesine tekrar basın ve gösterge çiziminin doğru başlangıcını alın (şekil 5).
Şekil 5. Gösterge çiziminin doğru başlangıcı.
İkinci Yol. Mevcut Bir Göstergeye Dayalı Yeni Bir Gösterge Oluşturma
Bu yolu, TSI göstergesinin ana çizgisi ve sinyal çizgisinin yakınsama ve uzaklaşma göstergesi oluşturma örneğini kullanarak ele alacağız. Gösterge bir histogram olarak çizilecek ve AO, AC göstergeleri gibi iki renge sahip olacaktır. Gösterge değeri artarsa, histogram yeşil renkte olacaktır; azalırsa, histogram kırmızı renkte olacaktır. Yukarıda giriş bölümünde belirtildiği gibi, başka bir göstergeye atıfta bulunmak için iCustom() veya IndicatorCreate() fonksiyonunu kullanabilirsiniz. İlk olarak, iCustom() fonksiyonunu kullanarak bir gösterge oluşturmaya bir göz atalım.
iCustom() Fonksiyonunu Kullanarak Gösterge Oluşturma
1. Yeni Gösterge Oluşturma
Yeni bir gösterge oluşturalım. MetaEditor'da yeni bir gösterge oluşturmak için "Ana Menü" - "Dosya" - "Yeni" - "Özel Gösterge" komutunu çalıştırmalı veya "Ctrl+N" tuş kombinasyonuna basmalısınız. Görüntülenen pencerenin "Ad" alanında yeni göstergenin adını belirtin - TSIsCDiCust, ardından "Ekle" düğmesine basın. Bir dış parametre ekleyin, bunun adı koddaki dış parametreler için bir parçanın belirlenmesi kadar önemli değildir; ayrıca TSI göstergesinden tüm dış parametreleri kopyalamak daha kolay olacaktır (şekil 6).
Şekil 6. Sihirbazda özel bir gösterge oluşturmanın ilk adımı.
"İleri" düğmesine basın.
Bir sonraki pencerede, göstergenin ayrı bir pencerede çizileceğini belirtin. Minimum ve maksimum tanımlamayın. "Ekle" düğmesine basın, gösterge tamponları listesinde yeni bir tampon görünecektir; adını belirtin - TSIsCD (fare imlecini gösterge çizgisinin üzerine ve veri penceresine getirirseniz bir yardım açılır penceresinde görüntülenecektir) ve türünü belirin - Renk Histogramı.
Bundan sonra "Renk" alanında birkaç renk örneği görünecektir. İlk örnek için Yeşil rengi, ikinci örnek için Kırmızı rengi belirtin ve diğerlerini değiştirmeden bırakın. Tsi ve TsiSignal adlı iki tampon daha ekleyin, bunlar TSI’ler göstergesinin değerlerini almak ve depolamak için kullanılacaktır (şekil 7).
Şekil 7. Sihirbazda özel gösterge oluşturmanın ikinci adımı.
"Son" düğmesine basın ve yeni göstergenin şablonu MetaEditor'da açılacaktır.
2. Gösterge ve Gösterge Tamponlarının Özelliklerini Düzenleme
1. adımda 3 tampon belirledik; ancak, #property indicator_buffers değeri 4'e eşittir. Mesele şu ki, renkli bir histogram iki tampon kullanır - biri bir grafikte görüntülenir ve bir göstergenin değerleri için tasarlanmıştır; ikincisi, birinci tamponun görüntülenme rengini belirlemeye yöneliktir. #property indicator_buffers değerini değişiklik yapmadan bırakın. #property indicator_plots değerini 1 olarak değiştirin - bir grafikte yalnızca bir tampon görüntülenmelidir.
Tsi ve TsiSignal tamponları bir grafikte görüntülenmemelidir, bu nedenle tüm özelliklerini silin (2 ve 3 ile biten göstergenin tüm özellikleri).
//--- plot Tsi #property indicator_label2 "Tsi" #property indicator_type2 DRAW_LINE #property indicator_color2 Red #property indicator_style2 STYLE_SOLID #property indicator_width2 1 //--- plot TsiSignal #property indicator_label3 "TsiSignal" #property indicator_type3 DRAW_LINE #property indicator_color3 Red #property indicator_style3 STYLE_SOLID #property indicator_width3 1OnInit() fonksiyonunda, bu tamponlar için SetIndexBuffer() fonksiyonunun çağrılarını bulun (dizi adları TsiBuffer ve TsiSignalBuffer'dır), üçüncü parametrenin değerini INDICATOR_DATA'dan INDICATOR_CALCULATIONS'a değiştirin.
SetIndexBuffer(2,TsiBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(3,TsiSignalBuffer,INDICATOR_CALCULATIONS);
indicator_color1 özelliğini değiştirin - yalnızca ilk iki rengi bırakın.
#property indicator_color1 Green,Red
3. Dış Parametrelerin Bildirilmesi
TSIs göstergesini MetaEditor'da açın ve ondan tüm dış değişkenleri kopyalayın, mevcut dış değişken Input1'i bu parametrelerle değiştirin.
//--- input parameters input int r=25; input int s=13; input int sp=5; // Smoothing period input ENUM_MA_METHOD sm=MODE_EMA; // Smoothing type
4. Gösterge Kolu için Değişken Bildirme ve Göstergeyi Çağırma
Göstergenin ortak bölümünde int türü bir değişken bildirin ve buna Handle adını verin. OnInit() öğesinin en altındaki iCustom() fonksiyonunu çağırın. Fonksiyon, oluşturulan göstergenin tanıtıcı değerini verir; göstergenin değerlerini almak için buna ihtiyacımız var. Fonksiyon tarafından verilen değeri Handle değişkenine atayın.
iCustom() fonksiyonunun ilk iki parametresi, göstergenin hesaplanması kullanılacak verilerin sembolünü ve zaman dilimini belirler. Göstergenin eklendiği bir sembol ve zaman çerçevesi belirleyelim - _Symbol ve PERIOD_CURRENT. Üçüncü parametre, özel bir göstergenin adıdır; bu durumda TSIs’tir. Çağrılan göstergenin tüm dış parametreleri ayrıca listelenmiştir:
Handle=iCustom(_Symbol,PERIOD_CURRENT,"TSIs",r,s,sp,sm);
5. OnCalculate() Fonksiyonunun Hazırlanması
OnCalculate() fonksiyonuna geçelim. TSIs göstergesi bir veri tamponu üzerinde hesaplanır, bu nedenle OnCalculate() fonksiyonunun ilk biçimini kullanacağız. Şablondaki OnCalculate() fonksiyonunun mevcut ikinci biçimini birincisi ile değiştirin.
int OnCalculate(const int rates_total, // size of the price[] array const int prev_calculated, // bars processed during the previous call const int begin, // from where the significant data begin const double &price[] // array for calculation ) { return(rates_total); }
Gösterge üzerinde yapılacak daha fazla çalışma bu fonksiyon dahilinde gerçekleştirilecektir.
6. Gösterge Hesaplama Limitlerinin Belirlenmesi
Herhangi bir göstergenin geliştirilmesinde en büyük öncelik ve önem, işlenmiş çubukların aralığının sınırlarının belirlenmesidir. Göstergenin başlangıcında, çalışması sırasında sadece o anda oluşturulan her bir çubuk için gösterge hesaplaması yapmalıyız. prev_calculated değişkeninin değeri aracılığıyla göstergenin başlangıç anını tespit edebilirsiniz. Bu değer sıfıra eşitse bu, göstergenin başlangıcından bu yana OnCalculate() fonksiyonunun ilk uygulamasıdır.
OnCalculate() fonksiyonunun ilk çalıştırılmasında, hesaplamaların başlaması gereken ilk çubuğun indisini belirlemelisiniz. Değeri, göstergenin değerinin hesaplanması için gerekli olan çubuk sayısı ile belirlenir (indisleme soldan sağa yapılır).
Gösterge çizgisinin eğimi iki çubuk tarafından belirlenir, bu nedenle bir önceki çubuğa ihtiyacımız var. Bir çubuğun indisi, yani price[] dizisinin başladığı önemli veri, know’dur - bu, begin değişkeninin değeridir; bu yüzden çubukları hesaplamaya start=begin+1 çubuğundan başlıyoruz.
Ayrıca, göstergenin çalışması sırasında, hesaplamanın başladığı bir çubuğun indisi, prev_calculated değişkeninin değeri tarafından belirlenir - bu değişken halihazırda işlenmiş çubukların sayısını içerir. Bu nedenle, hesaplamaların yapıldığı son çubuğun indisini bulmak için prev_calculated öğesinden 1 çıkarmanız gerekir.
Halihazırda işlenmiş çubukların sonuncusu, bir şekillendirme çubuğu olabileceği için tekrar hesaplamalara alınacaktır. Hesaplama sınırı, price[] dizisinin boyutuna göre belirlenir - rates_total değişkeni. Hesaplamaların yapıldığı son çubuğun indisi, rates_total-1'e eşittir (dizinin boyutundan bir kat küçüktür).
Gösterge, hesaplaması için başka bir göstergenin verilerini kullandığından, bu verileri almalıyız. CopyBuffer() fonksiyonunu kullanarak başka bir göstergenin verilerini alabilirsiniz. Fonksiyonun ilk parametresinde, verileri kopyalanacak olan bir göstergenin tanıtıcı değerini belirtmelisiniz (4. aşamada tanıtıcı değer elde edilir); ikinci parametrede, kopyalanan tamponun bir indisini belirtin (gerekli değer, kopyalanan göstergenin özelliklerinin "Renk" sekmesinden belirlenebilir, sayım sıfırdan başlatılır).
Üçüncü parametre, kopyalamanın başlatıldığı çubuğun indisidir; bu durumda indisleme sağdan sola yapılır, böylece en sağdaki çubuk sıfırdır. Dördüncü parametre kopyalanacak dizi elemanlarının sayısıdır. Kopyalanan eleman sayısını belirlemeye, hesaplamaya alınan çubukların aralığını belirlerken olduğu kadar dikkat etmelisiniz. Göstergenin performansını etkiler. Göstergenin hesaplanmasının başladığı bir çubuğun indisi önceden belirlenir, bu nedenle kopyalanan eleman sayısı rates_total-start olarak hesaplanır. Çalışma süreci sırasında, gösterge yalnızca oluşum çubuğu için hesaplanırken dizinin yalnızca bir elemanı kopyalanır.
CopyBuffer() fonksiyonları, bilgileri kopyalama girişiminde -1 verirse bu, verilerin kopyalanamayacağı anlamına gelir, bu nedenle hesaplama yapmanın bir anlamı yoktur. Bu hata çözülmelidir. CopyBuffer()'ın en başında bool tipinde statik bir değişken tanımlayın ve buna "error" adını verin. Gösterge hesaplama işlemi sırasında özellikle gösterge verilerinin kopyalanması gibi bir hata oluşursa, bu değişkene True değerini atayın ve OnCalculate() fonksiyonunun yürütülmesini sonlandırın.
Hata değeri, OnCalculate() fonksiyonunun önceki yürütülmesi sırasında bir hata olduğunu söylüyorsa, bir sonraki tikte tüm göstergeyi yeniden hesaplayın. Böylece, OnCalculate() fonksiyonunun başlangıcı aşağıdaki gibi görünecektir:
static bool error=true; int start; if(prev_calculated==0) // First execution of the OnCalculate() function after the indicator start { error=true; // Set the value True for the indicator to be calculated for all bars } if(error) // If value of error=true, then it is the first execution of the function after // the start of the indicator, or there was an error of copying of data at the previous start { start=begin+1; error=false; } else { start=prev_calculated-1; } if(CopyBuffer(Handle,0,0,rates_total-start,TsiBuffer)==-1) // Copying data of main line of the indicator { error=true; // Failed to copy data, set the value True for the error variable to recalculate the whole // indicator at the next call of OnCalculate() return(0); // End working of the function } if(CopyBuffer(Handle,1,0,rates_total-start,TsiSignalBuffer)==-1) // Copy data of the signal line of the indicator { error=true; // Failed to copy data, set the value true for the error variable to recalculate the whole // indicator at the next call of the OnCalculate() function return(0); // End working of the function }
Gösterge hesaplamasının sınırları belirlenir, bu çubuk aralığında bir hesaplama döngüsü yapın.
for(int i=start;i<rates_total;i++) { }
Gösterge değerini hesaplayın (kod yeni oluşturulan döngünün içinde bulunur).
TsiCDBuffer[i]=TsiBuffer[i]-TsiSignalBuffer[i];
Şimdi sıra en ilginç şeye geldi - tamponu renklendirmek. Daha önce 1. aşamada, gösterge tamponu için renkli bir histogramın kullanımını belirledik. Bu çizim türü iki tampon gerektirir - biri gösterge değeri, diğeri ise renk içindir. Renk listesi, indicator_color1 özelliğinde ayarlanır. Tampon elemanı için 0 değeri ayarlandığında gösterge yeşil renkle görüntülenir; 1 değeri ayarlandığında gösterge kırmızıdır (listedeki indicator_color1 içindeki konumlarına göre; numaralandırma sıfırdan başlar).
İki bitişik çubukta gösterge değerlerinin eşit olduğu bir durumdan kaçınmak mümkün değildir; bu durumda gösterge önceki renkle görüntülenmelidir (çünkü yukarı ve aşağı hareketler için sadece iki rengimiz var). Bu nedenle hesaplamaların başında, önceki çubuktaki TsiCDColors tamponunun değerini kopyalayacağız:
TsiCDColors[i]=TsiCDColors[i-1];
Yukarı doğru hareket ederken göstergeyi Yeşil renkle renklendirin:
if(TsiCDBuffer[i]>TsiCDBuffer[i-1])TsiCDColors[i]=0;
Aşağı hareket ederken göstergeyi Kırmızı renkle renklendirin:
if(TsiCDBuffer[i]<TsiCDBuffer[i-1])TsiCDColors[i]=1;
Bu da bizi gösterge üzerinde çalışmanın neredeyse sonuna getiriyor; gösterge çiziminin başlangıcını belirlemek için bırakılmıştır.
7. Gösterge Üzerindeki Çalışmanın Tamamlanması
Göstergenin hesaplanmasını belirlemek için begin değişkeni kullanılmasına rağmen, gösterge verilerinin begin değişkeni ile tanımlanan çubuktan başladığı anlamına gelmez. Özel bir göstergenin algoritması bilinmiyorsa, gösterge hesaplaması için gerekli olan çubuk sayısını tespit etmek neredeyse imkansızdır. Bu yüzden bu aşama atlanabilir veya deneyime dayalı bir değer tespit edebilirsiniz. Ancak TSIs göstergesinin algoritmasını biliyoruz, bu nedenle göstergenin başlangıcını tam olarak tespit edebiliyoruz. OnInit() fonksiyonuna PLOT_DRAW_BEGIN tanımlayıcısıyla PlotIndexSetInteger() fonksiyonunun çağrısını ekleyin.
PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,r+s+sp);
TSIs göstergesi, değerleri iki ondalık basamağa kadar doğru görüntüler; INDICATOR_DIGITS tanımlayıcısı ile IndicatorSetInteger() fonksiyonunu kullanarak aynı doğruluğu ayarlayın:
IndicatorSetInteger(INDICATOR_DIGITS,2);
Göstergeyi derleyin ve bir tabloya ekleyin (şekil 8).
Şekil 8. TSIsCDiCust göstergesi.
IndicatorCreate() Fonksiyonunu Kullanarak Gösterge Oluşturma
IndicatorCreate() fonksiyonu kullanılarak bir gösterge oluşturulması, iCustom() yerine IndicatorCreate() fonksiyonunun kullanıldığı 4. adım dışında, iCustom() fonksiyonu kullanılarak oluşturulmasıyla aynıdır.
1. TSIsCDiCust göstergesinin bir kopyasını TSIsCDiCreate adı altında kaydedin.
2. Kodda iCustom() fonksiyonunun nerede çağrıldığını bulun. Şu andan itibaren iCustom() yerine IndicatorCreate() fonksiyonunun çağrısı gerçekleştirilecektir. iCustom()'dakiyle aynı şekilde, IndicatorCreate() fonksiyonunun ilk iki parametresi, göstergenin hesaplanması için kullanılacak bir sembol ve zaman dilimi belirler. Üçüncü parametre, gösterge türünün bir tanımlayıcısıdır, özel bir gösterge için IND_CUSTOM'dır. Oluşturma göstergesinin parametreleri, MqlParam yapı dizisi kullanılarak fonksiyona iletilir.
MqlParam dört değişken içerir - bunlardan üçü değerler için kullanılan farklı türlerdeki değişkenlerdir: double_value, integer_value ve string_value; diğeri ise kullanılan değişkenin tipini belirleyen type’tır. TSIs göstergesinin dört dış parametresi vardır. Gösterge özel bir gösterge olduğundan, dizinin ilk öğesi özel göstergenin adını belirler, bu nedenle dizi beş eleman içermelidir. Bir yapı dizisi bildirin (kod, iCustom() öğesinin çağrıldığı yerde bulunur):
MqlParam Params[5];
Diziyi değerlerle doldurun:
Params[0].type=TYPE_STRING; Params[0].string_value="TSIs"; // Specify name of the called custom indicator in the first parameter Params[1].type=TYPE_INT; Params[1].integer_value=r; Params[2].type=TYPE_INT; Params[2].integer_value=s; Params[3].type=TYPE_INT; Params[3].integer_value=sp; Params[4].type=TYPE_INT; Params[4].integer_value=sm;
IndicatorCreate() fonksiyonuna iletilen ilk üç parametreyi ele aldık. Parametre dizisinin boyutu dördüncü parametreden geçirilir; sonuncusu, parametreleri içeren dizidir:
Handle=IndicatorCreate(_Symbol,PERIOD_CURRENT,IND_CUSTOM,5,Params);
"Derle" düğmesine basmak ve istemci terminalindeki göstergeyi kontrol etmek için bırakılmıştır.
Sonuç
Başka bir göstergeye dayanarak özel bir gösterge oluştururken dikkat etmeniz gereken ana fikirleri kısaca tekrarlayalım.
Bir göstergeyi geliştirirken, tampon sayısını ve çizilecek tampon sayısını doğru bir şekilde belirtmelisiniz (indicator_buffers, indicator_plots özellikleri); yeni tamponların özelliklerini belirlemelisiniz (indicator_label, indicator_type, indicator_color, indicator_style, indicator_width özellikleri). Yeni tamponlar için SetIndexBufer() fonksiyonunu çağırırken, üçüncü parametrenin (INDICATOR_DATA veya INDICATOR_CALCULATIONS) doğru değerini belirtmelisiniz; ve ilk parametrenin (tampon indisi) değerlerini doğru bir şekilde belirtin; gerekirse tamponların yeniden indislemesini gerçekleştirin.
Başka bir özel gösterge kullanarak yeni bir gösterge oluştururken, parametreleri doğru şekilde iCustom() fonksiyonuna iletmelisiniz; ve IndicatorCreate() fonksiyonunu kullanırken parametrelerin yapısını doldurun. Burada ayrıca SetIndexBuffer() fonksiyonunu çağırırken parametrelerin doğru belirtimini izlemelisiniz; en önemli şey, yeni tamponlar için SetIndexBuffer() fonksiyonunun çağrısını yapmayı unutmamaktır.
Göstergelerle her çalıştığınızda, bir dizi çubuk hesaplaması belirlemeye dikkat etmelisiniz - prev_calculated, rates_total, begin değişkenlerinin değerlerini kullanın. MetaEditor, programlama sırasında ortaya çıkabilecek diğer hatalarla başa çıkmanıza yardımcı olacaktır (derleme sırasında görünen hata mesajları "Hatalar" sekmesinde görüntülenir).
MetaQuotes Ltd tarafından Rusçadan çevrilmiştir.
Orijinal makale: https://www.mql5.com/ru/articles/127
![MQL5'te 20 Alım Satım Sinyali](https://c.mql5.com/2/0/20_Trading_Signals_MQL5__1.png)
![Uzman Danışmanda Para Yönetimi için fonksiyonlar](https://c.mql5.com/2/0/money_management_MQL5__1.png)
![Alım Satım Robotunun Prototipi](https://c.mql5.com/2/0/Prototype_Expert_Advisor_MQL5.png)
![Standart Kitaplık Sınıflarını ve Google Grafik API (Uygulama Programlama Arayüzü) kullanarak Bilgi Panosu oluşturmak](https://c.mql5.com/2/0/info_panel_MQL5.png)
![MQL5 - MetaTrader 5 müşteri terminalinde yerleşik ticaret stratejileri dili](https://c.mql5.com/i/registerlandings/logo-2.png)
- Ücretsiz ticaret 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