Bir grafikte birden fazla gösterge (Bölüm 04): Uzman Danışmanla çalışma
Giriş
Önceki makalelerimde, özel gösterge kullanarak birden fazla göstergenin nasıl oluşturulacağından bahsetmiştim. Bunu yapması oldukça kolaydı. Ancak aynısını Uzman Danışmanda uygulamaya çalıştığımızda, özel göstergede kullandığımız araçlara sahip olmadığımız için işler biraz daha karmaşıklaşıyor. Bu noktada programlama gerekli hale gelmektedir: alt pencere oluşturmak için doğru kodu yazabilmek çok önemlidir. Bu görev o kadar kolay olmasa da, bir Uzman Danışmana nasıl alt pencere yerleştirileceğini bilmek çok da fazla kodlama gerektirmez, sadece MQL5'in nasıl çalıştığı hakkında biraz bilgiye ihtiyaç vardır.
Planlama
Zaten çalışan bir özel göstergemiz var, yani nesne sınıfımız zaten çalışıyor ve bu bir nesne sınıfı olduğu için onu başka modellere de kolayca aktarabiliriz. Ancak, basitçe sınıfı Uzman Danışmanda bildirmek ve kullanmaya çalışmak, işlerin özel göstergemizdekiyle aynı şekilde çalışmasını sağlamayacaktır. Bunun nedeni, Uzman Danışmanda alt pencere yeteneğinin olmamasıdır. Ama sonra şunu düşündüm: “Peki önceden derlenmiş ve çalışan özel göstergeyi iCustom komutunu kullanarak Uzman Danışmandan çağırırsak?” Bu aslında işe yarayabilir çünkü alt pencereye gerek kalmayacaktır. Komut şu şekilde görünür:
#property copyright "Daniel Jose" //+------------------------------------------------------------------+ input string user01 = ""; //Used indicators input string user02 = ""; //Assets to follow //+------------------------------------------------------------------+ int OnInit() { int m_handleSub; //... Expert Advisor code ... if ((m_handleSub = iCustom(NULL, 0, "Chart In SubWindows\\Chart In SubWindow.ex5", user01, user02)) == INVALID_HANDLE) return INIT_FAILED; if (!ChartIndicatorAdd(ChartID(), 0, m_handleSub)) return INIT_FAILED; //... Expert Advisor code ... ChartRedraw(); return(INIT_SUCCEEDED); } //...The rest of the Expert Advisor code ...
Bu basit kod parçası, özel göstergemizi yükleyebilir, ancak alt pencere olmadığı için düzgün çalışmayacaktır. Burada, kod Uzman Danışmanda yürütüldüğünde, Uzman Danışman göstergemizi doğrudan ana pencereye uygulayacaktır, bu da grafiğin gösterge tarafından yüklenen şablonlarla gizleneceği anlamına gelir, ki bu kesinlikle istediğimiz şey değildir.
Bu nedenle gerçek ve asıl sorunumuz, halihazırda çalışan göstergemizi kullanabilmemiz için bir alt pencere oluşturmaktır. Ancak, göstergemizin sonraki çalıştırılması için neden bir alt pencere oluşturalım? Mantıklı değil; doğrudan Uzman Danışmana işlevsellik eklemek ve böylece ortaya çıkabilecek sınırlamaların üstesinden gelmek daha iyidir.
Dolayısıyla, birkaç görevi yerine getirmemiz gerekiyor:
Görev | Amaç |
---|---|
1 => Genel amaçlı bir gösterge oluştur. | Grafiği kirletmeden iCustom komutunun oluşturulmasına ve kullanılmasına olanak sağlar. |
2 => Bu göstergeyi bir şekilde Uzman Danışmana dahil et. | Uzman Danışmanın tam işlevsellik ile sorunsuz bir şekilde aktarılmasına olanak tanır. |
3 => Alt pencere için genel bir nesne sınıfı oluştur. | Uzman Danışman aracılığıyla alt pencere eklemeye izin verir. |
4 => C_TemplateChart sınıfını pencere sınıfına bağla. | Halihazırda çalışan kodda hiçbir şeyin değiştirilmeden alt pencerenin içeriğinin yönetilmesini mümkün kılar. |
Bu süreç çok uğraştırıcı gibi gözükse de, zorluklar oldukça basit bir şekilde çözülebilmektedir. Öyleyse, noktaların her biriyle ilgilenmeye başlayalım.
Uygulama: Genel amaçlı bir gösterge oluşturma
Bu kısım, tamamen temiz ancak işlevsel bir özel gösterge kodu oluşturularak çözülebilir. Bu amaçla kod şu şekilde görünecektir:
#property copyright "Daniel Jose" #property version "1.00" #property description "This file only enables support of indicators in SubWin." #property indicator_chart_window #property indicator_plots 0 //+------------------------------------------------------------------+ int OnInit() { return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) { return rates_total; } //+------------------------------------------------------------------+
Sadece bu kadar, daha fazlası değil. Bu dosyayı SubSupport.mq5 olarak kaydedelim. Ancak bu gösterge diğer göstergelerin bulunduğu klasörde bulunmayacak - onu Uzman Danışmanın Resources klasörüne taşıyalım. Böylece, dosya yapısı şu şekilde görünecektir:
Uygulama: Uzman Danışmana genel göstergeyi dahil etme
Bunu yapmak için, Uzman Danışmanın en üstüne aşağıdaki kodu eklememiz gerekiyor.
//+------------------------------------------------------------------+ #define def_Resource "Resources\\SubSupport.ex5" //+------------------------------------------------------------------+ #resource def_Resource //+------------------------------------------------------------------+
Bu, genel göstergenin derlenmiş kodunu Uzman Danışmana dahil edecektir. Sonrasında genel gösterge, artık gerekmeyeceğinden .ex5 dosyasının silinmesini sağlayacaktır. Burada şu ayrıntıya dikkat etmelisiniz: Uzman Danışman derlenirken SubSupport.ex5 dosyası bulunamazsa, derleyici SubSupport.mq5 genel göstergesini otomatik olarak derleyecek ve ilgili yeni derlenmiş yürütülebilir dosyayı Uzman Danışmana ekleyecektir. Yani, SubSupport.mq5 dosyasında düzenleme yapar ve değişiklikleri Uzman Danışmana eklemeniz gerekirse, öncesinde SubSupport.ex5 dosyasını silmeniz gerekecektir; aksi takdirde değişiklikler Uzman Danışmana eklenmeyecektir.
Bu ayrıntı önemlidir, çünkü bazı durumlarda kaynağa yeni değişiklikleri nasıl ekleyeceğinizi bilmeniz gerekir.
Genel gösterge artık Uzman Danışmanın bir parçası, şimdi bir sonraki göreve geçelim.
Uygulama: Alt pencere için genel bir nesne sınıfı oluşturma
Bu kısım da basittir. Burada kodlamadan önce bazı noktaları tanımlamamız gerekiyor, yani: bu sınıfta gerçekten hangi özelliklere ihtiyacımız var? Başlangıçta, şunları kullanmaya karar verdim:
Fonksiyon | Açıklama |
---|---|
Init | Uzman Danışman aracılığıyla alt pencere eklemeye izin verir. |
Close | Uzman Danışman aracılığıyla alt pencere eklemeye izin verir. |
Bu fonksiyonlar test edilmeyecek ve onların Uzman Danışmanın ömrü boyunca yalnızca bir kez çağrılacaklarını varsayıyorum. Ancak Uzman Danışman geliştikçe, gelecekte daha da pratik hale getirmek mantıklı. Bu nedenle, C_Terminal adında yeni bir nesne sınıfı oluşturalım - bu sınıf, terminalle ilgili birkaç şeyi destekleyecektir. Bu konuyu daha sonra öğreneceğiz. Çözümü kısmen uygulamanın bir yolu olmadığı için son göreve geçelim.
Uygulama: C_TemplateChart sınıfı kalıtımı
OOP (Nesne Yönelimli Programlama) kullanarak yeni bir şey oluşturmaya karar verdiğimde, bunu yaptım çünkü güvenlik ve kalıtım dahil olmak üzere bu yaklaşımı kullanmanın büyük avantajları olduğunu çoktan biliyordum. Bir diğer avantajı da polimorfizmdir ancak onu daha sonra bir çapraz emir sistemi oluştururken kullanacağız. Şimdi ise OOP’nin şu avantajını kullanacağız - kalıtım. C_TemplateChart halihazırda tamamen işlevsel bir sınıftır. Dolayısıyla, onu yeniden programlamak ya da içerisine kod ekleme riskini almak istemeyiz, ki bu da sınıfın başka yerde kullanılmasını engelleyebilir. Çözüm, orijinal kodu hiçbir şekilde değiştirmeden yeni kod veya fonksiyonlar eklenmesine olanak sağlayan kalıtımı kullanmaktır.
Kalıtımı kullanmanın şunlar dahil birçok avantajı vardır: halihazırda test edilmiş olan kod test edilmiş olarak kalır; karmaşıklık, kod boyutunda eşit şekilde artış olmadan artar; yalnızca yeni özelliklerin gerçekten test edilmesi gerekir; değişmeyenler basitçe kalıtılır, bu da istikrar sağlar. Başka bir deyişle, her şey minimum çabayla, maksimum güvenlikle gelişir. Bunu anlamak için aşağıdaki şemaya bakalım.
Büyük üst sınıf (grandparent class), en düşük veri düzenleme düzeyine sahip olduğumuz en temel sınıftır, ancak üst sınıf (parent class) büyük üst sınıftan bir şey kalıttığında, büyük üst sınıfta public olarak bildirilen her şey üst sınıf tarafından görülebilir ve kullanılabilir. Ayrıca üst sınıfa yeni şeyler de ekleyebiliriz, bu, nelerin kalıtıldığını ve kalıtımla desteklendiğini etkilemez. Üst sınıf halihazırda bitmiş ve çalışıyorsa ve onu aşağıdaki sınıflarda hiçbir şeyini değiştirmeden genişletmek istiyorsak, o zaman bu amaçla alt sınıf oluştururuz, alt sınıf önceki sınıfların tüm özelliklerine sahip olacaktır. Ayrıca işlerin çalışma şeklini de değiştirebiliriz ve kalıtımla ilgili ilginç olan şey de bu, çünkü bu değişiklikler diğer sınıfları etkilemeyecektir. Ancak burada, çoklu kalıtıma izin veren C++'ın aksine bir sınırlama vardır. Bir alt sınıf, üst sınıf olarak hem baba hem de anne tarafından fonksiyonlar kalıtabiliyorsa, bu MQL5'te mümkün değildir. Ancak MQL5’te yine de kalıtımdan faydalanılır. Çoklu kalıtım örneği aşağıda görülebilir:
Tamam, peki MQL5'te kalıtım nasıl yapılır? Kullanabilmemiz için kalıtım nasıl bildirilir? Bunu anlamanın en doğru yolu, nesne yönelimli programlamanın (OOP) içeriğini okumaktır, ancak burada doğrudan konuya gireceğiz. Kalıtım aşağıdaki satırlar aracılığıyla yapılacaktır:
#include "C_TemplateChart.mqh" //+------------------------------------------------------------------+ class C_SubWindow : public C_TemplateChart { // ... Class code };
C_SubWindow sınıfının C_TemplateChart sınıfından public olarak kalıtılacağını görebilirsiniz, böylece artık C_TemplateChart sınıfının işlevselliğine erişmek için C_SubWindow sınıfını kullanabiliriz.
Yukarıdaki kod parçasında bir şeyi vurguladım. Her zamanki gibi köşeli parantez ( < > ) içerisinde değil, tırnak işareti ( " ) içerisinde olduğuna dikkat edin. Peki bunu neden yaptım? C++ dili gibi, MQL5’in de çok ilgi çekici, farklı yönleri var, ancak bazıları programlama sanatını yeni öğrenmeye başlayanların kafasını karıştırabiliyor. Köşeli parantezler ( < > ) arasına bir header dosyası yerleştirdiğimizde, mutlak bir yolu kastediyoruz - bu durumda derleyici tam olarak belirttiğimiz yolu izleyecektir. Ancak tırnak işaretleri kullandığımızda (bizim yaptığımız gibi), derleyici göreceli bir yol kullanacak veya, daha iyi anlaşılması için, önce çalışma dosyasının bulunduğu mevcut klasörden aramaya başlayacaktır. Garip görünebilir, ancak farklı içeriklere sahip dosyaların aynı ada sahip olduğu ve farklı klasörlerde oldukları zamanlar vardır, ancak bizim durumumuzda derleyiciyi mevcut klasöre yönlendiriyoruz, bu yüzden tırnak işaretlerini kullanıyoruz.
Daha önce kullanmayı planladığımız iki fonksiyon olan Init ve Close aşağıda gösterilmektedir:
//+------------------------------------------------------------------+ bool Init(void) { if (m_handleSub != INVALID_HANDLE) return true; if ((m_handleSub = iCustom(NULL, 0, "::" + def_Resource)) == INVALID_HANDLE) return false; m_IdSub = (int) ChartGetInteger(Terminal.Get_ID(), CHART_WINDOWS_TOTAL); if (!ChartIndicatorAdd(Terminal.Get_ID(), m_IdSub, m_handleSub)) return false; return true; } //+------------------------------------------------------------------+ void Close(void) { ClearTemplateChart(); if (m_handleSub == INVALID_HANDLE) return; IndicatorRelease(m_IdSub); ChartIndicatorDelete(Terminal.Get_ID(), m_IdSub, ChartIndicatorName(Terminal.Get_ID(), m_IdSub, 0)); ChartRedraw(); m_handleSub = INVALID_HANDLE; } //+------------------------------------------------------------------+
Bakın, kod çok basit ve kısa. Ama dikkat etmemiz gereken bir şey var, vurgulanan kısma dikkat edin. Bu kısmı eklerken hata yapmamaya dikkat etmelisiniz, çünkü olduğu gibi bırakmazsanız, Uzman Danışmana eklenmesini istediğimiz SubSupport.ex5 yürütülebilir dosyası Uzman Danışman içerisinde görünmeyecektir, Uzman Danışmanın dışarısında görünecektir. Daha fazla ayrıntı için Kaynakları okuyabilirsiniz. Temel olarak ( :: ) kullanırsanız, bu, Uzman Danışmanın, içerdiği dahili kaynağı kullanması gerektiğini gösterir. Ancak sadece kaynağın adı belirtilirse, Uzman Danışman onu MQL5 klasöründe arayacaktır ve dosya belirtilen konumda mevcut değilse, dosya Uzman Danışmanın kaynağı olarak eklenmiş olsa bile fonksiyon başarısız olacaktır.
Ardından, kaynak yüklendikten sonra, mevcut alt pencerelerin sayısını kontrol ederiz ve bir alt pencereye gösterge ekleriz.
Kodun gerçekte ne yaptığı aşağıda görülebilir:
input string user01 = ""; //Used indicators input string user02 = ""; //Assets to follows //+------------------------------------------------------------------+ int OnInit() { int m_handleSub; //... if ((m_handleSub = iCustom(NULL, 0, "Chart In SubWindows\\Chart In SubWindow.ex5", user01, user02)) == INVALID_HANDLE) return INIT_FAILED; if (!ChartIndicatorAdd(ChartID(), (int) ChartGetInteger(ChartID(), CHART_WINDOWS_TOTAL), m_handleSub)) return INIT_FAILED; //... ChartRedraw(); return(INIT_SUCCEEDED); } //...The rest of the Expert Advisor code ...
Her iki kod da aynı şekilde çalışacaktır, ancak yukarıda gösterilen versiyon konsolide versiyon olduğundan ve değişmeyeceğinden, nesne sınıfı versiyonu zamanla daha fazla şey eklememize izin verecektir. Her iki versiyon da aynı şeyi yapar: Uzman Danışmanda bir alt pencere oluştururlar ve hazır tüm özel göstergeleri bu alt pencereye yerleştirirler. Lütfen kodun makalenin başındaki koda kıyasla değiştiğine dikkat edin - değişiklikler renkli olarak vurgulanmaktadır.
Sonuç
Hedeflerimize ulaşma yolunda bir plan çerçevesinde hareket edip, onu takip etmemiz gerçekten önemlidir. Bazen zorluklarla karşılaşabilir ve hedeflerimize ulaşmanın zor olduğunu düşünebiliriz, ancak sabır ve özveriyle ilk başta aşılmaz görünen engelleri aşabiliriz. Bu makalede sizlere bir sınıfı düzenlemeden kalıtım yoluyla işlevselliğini nasıl genişletebileceğinizi gösterdim. Aynı zamanda, daha önce test edilmiş gibi çalışmaları için grafiklere nasıl göstergeler ekleyebileceğinizi de gösterdim. ex5 programını Uzman Danışmanın içerisine ekliyoruz ve basitçe Uzman Danışmanı yükleyerek orijinal ex5'i aktarmak zorunda kalmadan onu kullanıyoruz.
Ekli dosya, şimdiye kadarki tüm geliştirmeleri içermektedir, ancak yakında bu kodda daha da ilginç şeyler olacak. 😁👍
MetaQuotes Ltd tarafından Portekizceden çevrilmiştir.
Orijinal makale: https://www.mql5.com/pt/articles/10241
- Ü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