
MQL5 Sihirbazı: Alım Satım Sinyalleri Modülü Nasıl Oluşturulur
Tanıtım
MetaTrader 5 alım satım fikirlerinin hızlı bir şekilde kontrol edilmesi için güçlü bir araç sunar. Bu, MQL5 Sihirbazının alım satım stratejileri üreticisidir. Uzman Danışman kodlarının otomatik olarak oluşturulması için MQL5 Sihirbazının kullanımı “ MQL5 Sihirbazı: Programlamadan Uzman Danışmanlar Oluşturma” makalesinde açıklanmıştır. Kod oluşturma sisteminin açıklığı standart olanlara kendi alım satım sinyalleri sınıflarınızı, para yönetim sistemlerinizi ve takip modüllerinizi eklemenize olanak tanır.
Bu makale MQL5 Sihirbazı ile Uzman Danışmanlar oluştururken kullanılacak alım satım sinyalleri modüllerini yazma ilkelerini açıklar.
MQL5 Sihirbazı ile oluşturulan Uzman Danışman dört temel sınıfa dayanır:
Şekil 1. CExpert temel sınıfının yapısı
CExpert sınıfı (veya alt sınıfı) bir alım satım robotunun ana “motorudur”. Bir CExpert örneği her sınıfın bir kopyasını içerir: CExpertSignal, CExpertMoney veCExpertTrailing (veya alt sınıfları):
- CExpertSignal alım satım sinyalleri üretiminin temelidir. CExpert'te bulunan CExpertSignal'den türetilen sınıfın bir örneği yerleşik algoritmalara dayalı olarak piyasaya girme olasılığı, giriş seviyeleri ve koruyucu emirlerin verilmesi hakkında bir Uzman Danışmana bilgi sağlar. Alım satım işlemlerinin yürütülmesine ilişkin nihai karar EA tarafından verilir.
- CExpertMoney para ve risk yönetim sistemlerinin temelidir. CExpertMoney'den türetilen sınıfın bir örneği pozisyon açma ve bekleyen emirler verme hacimlerini hesaplar. Hacimle ilgili nihai karar EA tarafından verilir.
- CExpertTrailing açık pozisyon desteği modülünün temelidir. CExpertTrailing'den türetilen sınıfın bir örneği bir pozisyonun koruyucu emirlerini değiştirme gerekliliği hakkında bir EA'yı bilgilendirir. Emir değişikliğine ilişkin nihai karar EA tarafından verilir.
Ayrıca CExpert sınıfının üyeleri aşağıdaki sınıfların örnekleridir:
- CExpertTrade (alım satım için)
- CIndicators (EA'nın çalışmasına dâhil olan göstergeleri ve zaman dizilerini kontrol etmek için).
- CSymbolInfo (araç hakkında bilgi almak için)
- CAccountInfo (alım satım hesabının durumu hakkında bilgi almak için)
- CPositionInfo (pozisyonlar hakkında bilgi almak için)
- COorderInfo (bekleyen emirler hakkında bilgi almak için)
Sonraki kısımda “uzman” derken CExpert'in bir örneğini veya alt sınıfını kastediyoruz.
CExpert ile ilgili daha fazla ayrıntı ve onunla yapılan çalışmalar ayrı bir makalede anlatılacaktır.
1. Temel Sınıf CExpertSignal
CExpertSignal alım satım sinyalleri üretiminin temelidir. “Dış dünya” ile iletişim için CExpertSignal bir dizi genel sanal yönteme sahiptir:
Başlatma | Tanım |
sanal Init | Sınıf örneğinin başlatılması modül verilerinin EA verileriyle senkronizasyonunu sağlar |
sanal ValidationSettings | Ayar parametrelerinin doğrulanması |
sanal InitIndicators | Alım satım sinyalleri üreticisinin çalışması için gereken tüm göstergelerin ve zaman serilerinin oluşturulması ve başlatılması |
Pozisyon açma/ters çevirme/kapanış sinyalleri |
|
sanal CheckOpenLong | Uzun pozisyon açma sinyalinin üretilmesi, giriş seviyelerinin tanımlanması ve koruyucu emirlerin verilmesi |
sanal CheckOpenShort | Kısa pozisyon açma sinyalinin üretilmesi, giriş seviyelerinin tanımlanması ve koruyucu emirlerin verilmesi |
sanal CheckCloseLong | Çıkış seviyesini tanımlayan uzun pozisyon kapatma sinyalinin üretilmesi |
sanal CheckCloseShort | Kısa pozisyon kapatma sinyalinin oluşturulması, çıkış seviyesinin tanımlanması |
sanal CheckReverseLong | Uzun pozisyon dönüş sinyalinin oluşturulması, ters çevirme seviyelerinin tanımlanması ve koruyucu emirlerin verilmesi |
sanal CheckReverseShort | Kısa pozisyon dönüş sinyalinin oluşturulması, ters çevirme seviyelerinin tanımlanması ve koruyucu emirlerin verilmesi |
Bekleyen emirleri yönetme |
|
sanal CheckTrailingOrderLong | Bekleyen bir Alış emrinin değişiklik sinyalinin oluşturulması, yeni emir fiyatının tanımlanması |
sanal CheckTrailingOrderShort | Bekleyen bir Satış emrinin değişiklik sinyalinin oluşturulması, yeni emir fiyatının tanımlanması |
Yöntemlerin Tanımı
1.1. Başlatma yöntemleri:
1.1.1 Init
Init() yöntemi uzmana bir sınıf örneği eklendikten hemen sonra otomatik olarak çağrılır. Yöntemi geçersiz kılma gerekli değildir.
virtual bool Init(CSymbolInfo* symbol, ENUM_TIMEFRAMES period, double adjusted_point);
1.1.2 ValidationSettings
ValidationSettings() yöntemi tüm parametreler ayarlandıktan hemen sonra uzmandan çağrılır. Herhangi bir kurulum parametresi varsa yöntemi geçersiz kılmalısınız.
virtual bool ValidationSettings();
Tüm seçenekler geçerliyse (kullanılabilirse) geçersiz kılınan yöntem true değerini döndürmelidir. Parametrelerden en az biri yanlışsa false değerini döndürmelidir (daha fazla çalışma mümkün değildir).
Temel sınıf CExpertSignal'in ayarlanabilir parametresi yoktur, bu nedenle temel sınıf yöntemi herhangi bir kontrol gerçekleştirmeden her zaman true değerini döndürür.
1.1.3 InitIndicators
InitIndicators() yöntemi gerekli tüm göstergelerin ve zaman serilerinin oluşturulmasını ve başlatılmasını yürütür. Tüm parametreler ayarlandıktan ve doğruluğu başarılı bir şekilde onaylandıktan sonra uzmandan çağrılır. Alım satım sinyali üreticisi en az bir gösterge veya zaman serisi kullanıyorsa yöntem geçersiz kılınmalıdır.
virtual bool InitIndicators(CIndicators* indicators);
Göstergeler veya zaman serileri Standart Kütüphanenin uygun sınıfları aracılığıyla kullanılmalıdır. Tüm göstergelerin veya zaman serilerinin işaretçileri bir uzmanın gösterge koleksiyonuna eklenmelidir (parametre olarak geçirilen bir işaretçi).
Göstergeler veya zaman serileri ile yapılan tüm manipülasyonlar başarılı olursa (kullanım için uygunsa) geçersiz kılınan yöntem true değerini döndürmelidir. Göstergeler veya zaman serileri ile en az bir işlem başarısız olursa yöntem false değerini döndürmelidir (daha fazla çalışma mümkün değildir).
Temel sınıf CExpertSignal göstergeleri veya zaman serilerini kullanmaz; bu nedenle temel sınıf yöntemi herhangi bir eylem gerçekleştirmeden her zaman true değerini döndürür.
1.2. Pozisyon açma sinyalini kontrol etme yöntemleri:
1.2.1 CheckOpenLong
CheckOpenLong() yöntemi giriş seviyesini ve koruyucu emir verme seviyelerini tanımlayarak uzun bir pozisyonun açılış sinyalini üretir. Uzun bir pozisyon açmanın gerekli olup olmadığını belirlemek için bir uzman tarafından çağrılır. Uzun bir pozisyon açma sinyalinin üretilmesi bekleniyorsa yöntem geçersiz kılınmalıdır.
virtual bool CheckOpenLong(double& price, double& sl, double& tp, datetime& expiration);
Yöntem uzun pozisyon açılışının durumunu kontrol etme algoritmasını uygulamalıdır. Koşul yerine getirilirse fiyat, sl, tp ve vade bitimi (parametre olarak geçirilen referanslar) değişkenlerine uygun değerler atanmalı ve yöntem true değerini döndürmelidir. Koşul yerine getirilmezse yöntem false değerini döndürmelidir.
Temel sınıf CExpertSignal uzun bir pozisyon açma sinyali oluşturmak için yerleşik bir algoritmaya sahip değildir; bu nedenle temel sınıf yöntemi her zaman false değerini döndürür.
1.2.2 CheckOpenShort
CheckOpenShort() yöntemi giriş seviyesini ve koruyucu emir verme seviyelerini tanımlayarak kısa bir pozisyonun açılış sinyalini üretir. Kısa bir pozisyon açmanın gerekli olup olmadığını belirlemek için bir uzman tarafından çağrılır. Kısa bir pozisyon açma sinyalinin üretilmesi bekleniyorsa yöntem geçersiz kılınmalıdır.
virtual bool CheckOpenShort(double& price, double& sl, double& tp, datetime& expiration);
Yöntem kısa pozisyon açılışının durumunu kontrol etme algoritmasını uygulamalıdır. Koşul yerine getirilirse fiyat, sl, tp ve vade bitimi (parametre olarak geçirilen referanslar) değişkenlerine uygun değerler atanmalı ve yöntem true değerini döndürmelidir. Koşul yerine getirilmezse yöntem false değerini döndürmelidir.
Temel sınıf CExpertSignal kısa bir pozisyon açma sinyali oluşturmak için yerleşik bir algoritmaya sahip değildir; bu nedenle temel sınıf yöntemi her zaman false değerini döndürür.
1.3. Pozisyon kapatma sinyalini kontrol etme yöntemleri:
1.3.1 CheckCloseLong
CheckCloseLong() yöntemi çıkış seviyesini tanımlayarak uzun bir pozisyonun kapanış sinyalini üretir. Uzun bir pozisyonu kapatmanın gerekli olup olmadığını belirlemek için bir uzman tarafından çağrılır. Uzun bir pozisyonu kapatma sinyalinin üretilmesi bekleniyorsa yöntem geçersiz kılınmalıdır.
virtual bool CheckCloseLong(double& price);
Yöntem uzun pozisyonun kapanış durumunu kontrol etme algoritmasını uygulamalıdır. Koşul yerine getirilirse fiyat (parametre olarak geçirilen referanslar) değişkenine uygun değer atanmalı ve yöntem true değerini döndürmelidir. Koşul yerine getirilmezse yöntem false değerini döndürmelidir.
Temel sınıf CExpertSignal uzun bir pozisyon kapatma sinyali oluşturmak için yerleşik bir algoritmaya sahip değildir; bu nedenle temel sınıf yöntemi her zaman false değerini döndürür.
1.3.2 CheckCloseShort
CheckCloseShort() yöntemi çıkış seviyesini tanımlayarak kısa bir pozisyonun kapanma sinyalini üretir. Kısa bir pozisyonu kapatmanın gerekli olup olmadığını belirlemek için bir uzman tarafından çağrılır. Kısa bir pozisyonu kapatma sinyalinin üretilmesi bekleniyorsa yöntem geçersiz kılınmalıdır.
virtual bool CheckCloseShort(double& price);
Yöntem kısa pozisyon kapanışının durumunu kontrol etme algoritmasını uygulamalıdır. Koşul yerine getirilirse fiyat (parametre olarak geçirilen referanslar) değişkenine uygun değer atanmalı ve yöntem true değerini döndürmelidir. Koşul yerine getirilmezse yöntem false değerini döndürmelidir.
Temel sınıf CExpertSignal kısa bir pozisyonu kapatma sinyali oluşturmak için yerleşik bir algoritmaya sahip değildir; bu nedenle temel sınıf yöntemi her zaman false değerini döndürür.
1.4. Pozisyonu tersine çevirme sinyalini kontrol etme yöntemleri:
1.4.1 CheckReverseLong
CheckReverseLong yöntemi, tersine çevirme seviyesini ve koruyucu emir verme seviyelerini tanımlayarak uzun bir pozisyonu tersine çevirme sinyalini üretir. Uzun bir pozisyonu tersine çevirmenin gerekli olup olmadığını belirlemek için bir uzman tarafından çağrılır. Uzun bir pozisyonu tersine çevirme sinyalinin üretilmesi bekleniyorsa yöntem geçersiz kılınmalıdır.
virtual bool CheckReverseLong(double& price, double& sl, double& tp, datetime& expiration);
Yöntem uzun bir pozisyonu tersine çevirme durumunu kontrol etme algoritmasını uygulamalıdır. Koşul yerine getirilirse fiyat, sl, tp ve vade bitimi (parametre olarak geçirilen referanslar) değişkenlerine uygun değerler atanmalı ve yöntem true değerini döndürmelidir. Koşul yerine getirilmezse yöntem false değerini döndürmelidir.
CExpertSignal temel sınıfında uzun bir pozisyonu tersine çevirme sinyali oluşturmak için aşağıdaki algoritma uygulanır:
- Uzun bir pozisyonu kapatma sinyali kontrol edilir.
- Kısa bir pozisyonu açma sinyali kontrol edilir.
- Her iki sinyal de etkinse (koşullar yerine getirildiyse) ve kapanış ve açılış fiyatları eşleşirse fiyat, sl, tp ve vade bitimi (parametre olarak geçirilen referanslar) değişkenlerine uygun değerler atanır ve yöntem true değerini döndürür.
1.4.2 CheckReverseShort
CheckReverseShort yöntemi tersine çevirme seviyesini ve koruyucu emir verme seviyelerini tanımlayan, kısa bir pozisyonu tersine çevirme sinyali üretir. Kısa bir pozisyonu tersine çevirmenin gerekli olup olmadığını belirlemek için bir uzman tarafından çağrılır. Temel sınıfta uygulanandan farklı olan algoritmaya göre bir uzun bir pozisyonu tersine çevirme sinyalinin üretilmesi bekleniyorsa yöntem geçersiz kılınmalıdır.
virtual bool CheckReverseShort(double& price, double& sl, double& tp, datetime& expiration);
Yöntem kısa bir pozisyonu tersine çevirme durumunu kontrol etme algoritmasını uygulamalıdır. Koşul yerine getirilirse fiyat, sl, tp ve vade bitimi (parametre olarak geçirilen referanslar) değişkenlerine uygun değerler atanmalı ve yöntem true değerini döndürmelidir. Koşul yerine getirilmezse yöntem false değerini döndürmelidir.
CExpertSignal temel sınıfında kısa bir pozisyonu tersine çevirme sinyali oluşturmak için aşağıdaki algoritma uygulanır:
- Kısa bir pozisyonu kapatma sinyali kontrol edilir.
- Uzun bir pozisyonu açma sinyali kontrol edilir.
- Her iki sinyal de etkinse (koşullar yerine getirildiyse) ve kapanış ve açılış fiyatları eşleşirse fiyat, sl, tp ve vade bitimi (parametre olarak geçirilen referanslar) değişkenlerine uygun değerler atanır ve yöntem true değerini döndürür.
Koşul yerine getirilmezse yöntem false değerini döndürür.
1.5. Bekleyen emir değişikliği sinyalini kontrol etme yöntemleri:
1.5.1 CheckTrailingOrderLong
CheckTrailingOrderLong() yöntemi yeni bir emir fiyatı tanımlayarak bekleyen bir Satın Alma emrinin değişiklik sinyalini üretir. Bekleyen bir Satın Alma emrini değiştirmenin gerekli olup olmadığını belirlemek için bir uzman tarafından çağrılır. Bekleyen bir Satın Alma emrinin değişiklik sinyalinin üretilmesi bekleniyorsa yöntem geçersiz kılınmalıdır.
virtual bool CheckTrailingOrderLong(COrderInfo* order, double& price)
Yöntem bekleyen bir Satın Alma emrinin değişiklik durumunu kontrol etme algoritmasını uygulamalıdır. Koşul yerine getirilirse fiyat (parametre olarak geçirilen referanslar) değişkenine uygun değer atanmalı ve yöntem true değerini döndürmelidir. Koşul yerine getirilmezse yöntem false değerini döndürmelidir.
Temel sınıf CExpertSignal bekleyen bir Satın Alma emrinin değişiklik sinyalini oluşturmak için yerleşik bir algoritmaya sahip değildir; bu nedenle temel sınıf yöntemi her zaman false değerini döndürür.
1.5.2 CheckTrailingOrderShort
CheckTrailingOrderShort() yöntemi yeni bir emir fiyatı tanımlayarak bekleyen bir Satış emrinin değişiklik sinyalini üretir. Bekleyen bir Satış emrini değiştirmenin gerekli olup olmadığını belirlemek için bir uzman tarafından çağrılır. Bekleyen bir Satış emrinin değişiklik sinyalinin üretilmesi bekleniyorsa yöntem geçersiz kılınmalıdır.
virtual bool CheckTrailingOrderShort(COrderInfo* order, double& price)
Yöntem bekleyen bir Satış emrinin değişiklik durumunu kontrol etme algoritmasını uygulamalıdır. Koşul yerine getirilirse fiyat (parametre olarak geçirilen referanslar) değişkenine uygun değer atanmalı ve yöntem true değerini döndürmelidir. Koşul yerine getirilmezse yöntem false değerini döndürmelidir.
Temel sınıf CExpertSignal bekleyen bir Satış emrinin değişiklik sinyalini oluşturmak için yerleşik bir algoritmaya sahip değildir; bu nedenle temel sınıf yöntemi her zaman false değerini döndürür.
2. Kendi Alım Satım Sinyalleri Üreticinizi Oluşturun
ArtıkCExpertSignal temel sınıfının yapısını incelediğinize göre kendi alım satım sinyali üreticinizi oluşturmaya başlayabilirsiniz.
Yukarıda bahsedildiği üzere CExpertSignal sınıfı bir dizi genel sanal “usul”dür; uzmanın, alım satım sinyali üreticisinin piyasaya hangi yönde girileceği konusundaki görüşünü bilebileceği yöntemlerdir.
Bu nedenle birincil hedefimiz, CExpertSignal sınıfından türeterek uygun sanal yöntemleri geçersiz kılarak ve gerekli algoritmaları uygulayarak kendi alım satım sinyali üretici sınıfımızı oluşturmaktır.
İkinci problemimiz de (ki bu da önemlidir), MQL5 Sihirbazında sınıfımızı “görünür” hale getirmektir Fakat her şey sırayla.
2.1. Alım satım sinyalleri üreticinin sınıfını oluşturma
Hadi başlayalım.
İlk olarak, (örneğin, aynı MQL5 Sihirbazını kullanarak) mqh uzantılı bir ekleme dosyası oluşturuyoruz.
Dosya menüsünde “Oluştur”u seçin (veya Ctrl+N basın) ve eklenen bir dosyanın oluşturulmasını belirtin:
Şekil 2. MQL5 Sihirbazını kullanarak bir ekleme dosyası oluşturma
Dosyanın daha sonra MQL5 Sihirbazı tarafından sinyal üretici olarak “algılanması” için dosya Include\Expert\Signal\ klasöründe oluşturulmalıdır.
Standart Kütüphane'ye gereksiz dosya atmamak için MQL5 Sihirbazında ilgili parametreleri belirterek SampleSignal.mqh dosyasını oluşturduğumuz Include\Expert\Signal\MySignals klasörünü oluşturun:
Şekil 3. Eklenen dosyanın konumunu ayarlama
MQL5 Sihirbazı işleminin bir sonucu olarak aşağıdaki düzeni oluşturmuş oluruz:
//+------------------------------------------------------------------+ //| SampleSignal.mqh | //| Copyright 2010, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2010, MetaQuotes Software Corp." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| defines | //+------------------------------------------------------------------+ // #define MacrosHello "Hello, world!" // #define MacrosYear 2010 //+------------------------------------------------------------------+ //| DLL imports | //+------------------------------------------------------------------+ // #import "user32.dll" // int SendMessageA(int hWnd,int Msg,int wParam,int lParam); // #import "my_expert.dll" // int ExpertRecalculate(int wParam,int lParam); // #import //+------------------------------------------------------------------+ //| EX5 imports | //+------------------------------------------------------------------+ // #import "stdlib.ex5" // string ErrorDescription(int error_code); // #import //+------------------------------------------------------------------+
Aşağıdakiler sadece “manuel” olarak yapılmalıdır. Gereksiz bölümleri kaldırın ve gerekli olanı ekleyin (Standart Kütüphanenin ExpertSignal.mqh dosyasını ve şu anda boş olan bir sınıf tanımını ekleyin).
//+------------------------------------------------------------------+ //| SampleSignal.mqh | //| Copyright 2010, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2010, MetaQuotes Software Corp." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| include files | //+------------------------------------------------------------------+ #include <Expert\ExpertSignal.mqh> //+------------------------------------------------------------------+ //| The CSampleSignal class. | //| Purpose: Class of trading signal generator. | //| It is derived from the CExpertSignal class. | //+------------------------------------------------------------------+ class CSampleSignal : public CExpertSignal { }; //+------------------------------------------------------------------+
Şimdi de algoritmaları seçmemiz gerek.
Alım satım sinyali üreticimizin temeli olarak, yaygın olarak kullanılan “fiyatın hareketli ortalamayla kesiştiği” modeli alıyoruz. Ama bir varsayım daha yapıyoruz: “Hareketli ortalamayla kesiştikten sonra fiyat geri hareket eder ve ancak o zaman doğru yöne gider.” Bunu dosyamıza ekleyelim.
Genel olarak, bir şeyler yazarken yorumları gözden kaçırmayın. Bir süre sonra dikkatli bir şekilde yorumlanmış bir kodu okumak çok rahat olacaktır.
//+------------------------------------------------------------------+ //| SampleSignal.mqh | //| Copyright 2010, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2010, MetaQuotes Software Corp." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| include files | //+------------------------------------------------------------------+ #include <Expert\ExpertSignal.mqh> //+------------------------------------------------------------------+ //| Class CSampleSignal. | //| Purpose: Class of trading signal generator when price | //| crosses moving average, | //| entering on the subsequent back movement. | //| It is derived from the CExpertSignal class. | //+------------------------------------------------------------------+ class CSampleSignal : public CExpertSignal { }; //+------------------------------------------------------------------+
Şimdi alım satım sinyallerinin oluşturulmasıyla ilgili kararlar almak için hangi verilerin gerekli olduğunu tanımlayalım. Bizim durumumuzda bu, önceki çubuğun açılış fiyatı ve kapanış fiyatı ile önceki aynı çubuktaki hareketli ortalamanın değeridir.
Bu verilere erişmek için CiOpen CiClose ve CiMA standart kütüphane sınıflarını kullanıyoruz. Göstergeleri ve zaman serilerini daha sonra tartışacağız.
Bu arada üreticimiz için bir ayar listesi tanımlayalım. İlk olarak, hareketli ortalamayı ayarlamamız gerekiyor. Bu parametreler içinde periyot, zaman ekseni boyunca kayma, ortalama alma yöntemi ve ortalama alma nesnesi yer alır. İkinci olarak, bekleyen emirlerle çalışacağımız için giriş seviyesini, koruyucu emirlerin verilme seviyelerini ve bekleyen bir emrin ömrünü ayarlamamız gerekiyor.
Üreticinin tüm ayarları sınıfın korumalı veri üyelerinde saklanacaktır. Ayarlara erişim uygun genel yöntemlerle gerçekleştirilecektir.
Bu değişiklikleri dosyamıza ekleyelim:
//+------------------------------------------------------------------+ //| SampleSignal.mqh | //| Copyright 2010, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2010, MetaQuotes Software Corp." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| include files | //+------------------------------------------------------------------+ #include <Expert\ExpertSignal.mqh> //+------------------------------------------------------------------+ //| The CSampleSignal class. | //| Purpose: Class of trading signal generator when price | //| crosses moving average, | //| entering on the subsequent back movement. | //| It is derived from the CExpertSignal class. | //+------------------------------------------------------------------+ class CSampleSignal : public CExpertSignal { protected: //--- Setup parameters int m_period_ma; // averaging period of the MA int m_shift_ma; // shift of the MA along the time axis ENUM_MA_METHOD m_method_ma; // averaging method of the MA ENUM_APPLIED_PRICE m_applied_ma; // averaging object of the MA double m_limit; // level to place a pending order relative to the MA double m_stop_loss; // level to place a stop loss order relative to the open price double m_take_profit; // level to place a take profit order relative to the open price int m_expiration; // lifetime of a pending order in bars public: //--- Methods to set the parameters void PeriodMA(int value) { m_period_ma=value; } void ShiftMA(int value) { m_shift_ma=value; } void MethodMA(ENUM_MA_METHOD value) { m_method_ma=value; } void AppliedMA(ENUM_APPLIED_PRICE value) { m_applied_ma=value; } void Limit(double value) { m_limit=value; } void StopLoss(double value) { m_stop_loss=value; } void TakeProfit(double value) { m_take_profit=value; } void Expiration(int value) { m_expiration=value; } }; //+------------------------------------------------------------------+
Korumalı veri üyeleri kullandığımız için bu verileri varsayılan değerlerle başlatacağımız bir sınıf oluşturucusu eklememiz gerekiyor.
Parametreleri kontrol etmek için temel sınıfın tanımına göre sanal ValidationSettings yöntemini geçersiz kılalım.
Sınıfın tanımı:
class CSampleSignal : public CExpertSignal { protected: //--- Setup parameters int m_period_ma; // averaging period of the MA int m_shift_ma; // shift of the MA along the time axis ENUM_MA_METHOD m_method_ma; // averaging method of the MA ENUM_APPLIED_PRICE m_applied_ma; // averaging object of the MA double m_limit; // level to place a pending order relative to the MA double m_stop_loss; // level to place a stop loss order relative to the open price double m_take_profit; // level to place a take profit order relative to the open price int m_expiration; // lifetime of a pending order in bars public: CSampleSignal(); //--- Methods to set the parameters void PeriodMA(int value) { m_period_ma=value; } void ShiftMA(int value) { m_shift_ma=value; } void MethodMA(ENUM_MA_METHOD value) { m_method_ma=value; } void AppliedMA(ENUM_APPLIED_PRICE value) { m_applied_ma=value; } void Limit(double value) { m_limit=value; } void StopLoss(double value) { m_stop_loss=value; } void TakeProfit(double value) { m_take_profit=value; } void Expiration(int value) { m_expiration=value; } //--- Methods to validate the parameters virtual bool ValidationSettings(); };
ValidationSettings() yönteminin uygulanması:
//+------------------------------------------------------------------+ //| Validation of the setup parameters. | //| INPUT: No. | //| OUTPUT: true if the settings are correct, otherwise false. | //| REMARK: No. | //+------------------------------------------------------------------+ bool CSampleSignal::ValidationSettings() { //--- Validation of parameters if(m_period_ma<=0) { printf(__FUNCTION__+": the MA period must be greater than zero"); return(false); } //--- ok return(true); } //+------------------------------------------------------------------+
Artık hazırlık çalışmalarının çoğunu bitirdiğimize göre göstergeler ve zaman serileri hakkında daha fazla konuşabiliriz.
Göstergeler ve zaman serileri karar verme sürecinde ana bilgi kaynağıdır (yazı tura atmayı veya ayın evrelerini kesinlikle kullanabilirsiniz ancak bunlara resmiyet kazandırmak oldukça zordur).
Yukarıda zaten tanımladığımız üzere, karar vermek için şu bilgilere ihtiyacımız vardır: önceki çubuğun açılış fiyatı, önceki çubuğun kapanış fiyatı ve önceki aynı çubuktaki hareketli ortalamanın değeri.
Bu verilere erişmek için Standart Kütüphanenin aşağıdaki sınıflarını kullanacağız:
- CiOpen: önceki çubuğun açık fiyatına erişmek için
- CiClose: önceki çubuğun kapanış fiyatına erişmek için
- CiMA: önceki çubuktaki hareketli ortalamanın değerine erişmek için.
Şunu sorabilirsiniz: “Tek bir sayı elde etmek için neden bir sınıfta “sarılı” olan göstergeyi veya zaman serisini kullanıyorsunuz?
Bunun birazdan ortaya çıkaracağımız gizli bir anlamı vardır.
Bir gösterge veya zaman serisinin verileri nasıl kullanılır?
İlk önce bir gösterge oluşturmamız gerekiyor.
İkinci olarak, gerekli miktarda veriyi bir ara tampona kopyalamamız gerekiyor.
Üçüncüsü, kopyalamanın tamamlanıp tamamlanmadığını kontrol etmemiz gerekiyor.
Ancak bu adımlardan sonra verileri kullanabilirsiniz.
Standart Kütüphane’nin sınıflarını kullanarak bir gösterge oluşturma gerekliliğinden, ara tamponların kullanılabilirliğiyle ve veri yükleme veya bir işleyicinin serbest bırakılmasıyla ilgilenmekten kurtulursunuz. Uygun bir sınıfın nesnesi bunu sizin için yapar. Gerekli tüm göstergeler başlatma aşamasında sinyal üreticimiz tarafından üretilecek ve tüm göstergelere gerekli geçici tampon sağlanacaktır. Ayrıca koleksiyona bir gösterge veya zaman serisi nesnesi eklediğimizde (özel bir sınıfın nesnesi) verilerin ilişki düzeyini önemsemeyi bırakabilirsiniz (veriler uzman tarafından otomatik olarak güncellenecektir).
InitIndicators sanal yöntemini geçersiz kılalım (temel sınıfın tanımına göre).
Sınıfın tanımı:
class CSampleSignal : public CExpertSignal { protected: CiMA m_MA; // object to access the values om the moving average CiOpen m_open; // object to access the bar open prices CiClose m_close; // object to access the bar close prices //--- Setup parameters int m_period_ma; // averaging period of the MA int m_shift_ma; // shift of the MA along the time axis ENUM_MA_METHOD m_method_ma; // averaging method of the MA ENUM_APPLIED_PRICE m_applied_ma; // averaging object of the MA double m_limit; // level to place a pending order relative to the MA double m_stop_loss; // level to place a stop loss order relative to the open price double m_take_profit; // level to place a take profit order relative to the open price int m_expiration; // lifetime of a pending order in bars public: CSampleSignal(); //--- Methods to set the parameters void PeriodMA(int value) { m_period_ma=value; } void ShiftMA(int value) { m_shift_ma=value; } void MethodMA(ENUM_MA_METHOD value) { m_method_ma=value; } void AppliedMA(ENUM_APPLIED_PRICE value) { m_applied_ma=value; } void Limit(double value) { m_limit=value; } void StopLoss(double value) { m_stop_loss=value; } void TakeProfit(double value) { m_take_profit=value; } void Expiration(int value) { m_expiration=value; } //--- Method to validate the parameters virtual bool ValidationSettings(); //--- Method to validate the parameters virtual bool InitIndicators(CIndicators* indicators); protected: //--- Object initialization method bool InitMA(CIndicators* indicators); bool InitOpen(CIndicators* indicators); bool InitClose(CIndicators* indicators); //--- Methods to access object data double MA(int index) { return(m_MA.Main(index)); } double Open(int index) { return(m_open.GetData(index)); } double Close(int index) { return(m_close.GetData(index)); } };
InitIndicators, InitMA, InitOpen, InitClose yöntemlerinin uygulanması:
//+------------------------------------------------------------------+ //| Initialization of indicators and timeseries. | //| INPUT: indicators - pointer to the object - collection of | //| indicators and timeseries. | //| OUTPUT: true in case of success, otherwise false. | //| REMARK: No. | //+------------------------------------------------------------------+ bool CSampleSignal::InitIndicators(CIndicators* indicators) { //--- Validation of the pointer if(indicators==NULL) return(false); //--- Initialization of the moving average if(!InitMA(indicators)) return(false); //--- Initialization of the timeseries of open prices if(!InitOpen(indicators)) return(false); //--- Initialization of the timeseries of close prices if(!InitClose(indicators)) return(false); //--- Successful completion return(true); } //+------------------------------------------------------------------+ //| Initialization of the moving average | //| INPUT: indicators - pointer to the object - collection of | //| indicators and timeseries. | //| OUTPUT: true in case of success, otherwise false. | //| REMARK: No. | //+------------------------------------------------------------------+ bool CSampleSignal::InitMA(CIndicators* indicators) { //--- Initialization of the MA object if(!m_MA.Create(m_symbol.Name(),m_period,m_period_ma,m_shift_ma,m_method_ma,m_applied_ma)) { printf(__FUNCTION__+": object initialization error"); return(false); } m_MA.BufferResize(3+m_shift_ma); //--- Adding an object to the collection if(!indicators.Add(GetPointer(m_MA))) { printf(__FUNCTION__+": object adding error"); return(false); } //--- Successful completion return(true); } //+------------------------------------------------------------------+ //| Initialization of the timeseries of open prices. | //| INPUT: indicators - pointer to the object - collection of | //| indicators and timeseries. | //| OUTPUT: true in case of success, otherwise false. | //| REMARK: No. | //+------------------------------------------------------------------+ bool CSampleSignal::InitOpen(CIndicators* indicators) { //--- Initialization of the timeseries object if(!m_open.Create(m_symbol.Name(),m_period)) { printf(__FUNCTION__+": object initialization error"); return(false); } //--- Adding an object to the collection if(!indicators.Add(GetPointer(m_open))) { printf(__FUNCTION__+": object adding error"); return(false); } //--- Successful completion return(true); } //+------------------------------------------------------------------+ //| Initialization of the timeseries of close prices. | //| INPUT: indicators - pointer to the object - collection of | //| indicators and timeseries. | //| OUTPUT: true in case of success, otherwise false. | //| REMARK: No. | //+------------------------------------------------------------------+ bool CSampleSignal::InitClose(CIndicators* indicators) { //--- Initialization of the timeseries object if(!m_close.Create(m_symbol.Name(),m_period)) { printf(__FUNCTION__+": object initialization error"); return(false); } //--- Adding an object to the collection if(!indicators.Add(GetPointer(m_close))) { printf(__FUNCTION__+": object adding error"); return(false); } //--- Successful completion return(true); } //+------------------------------------------------------------------+
Tüm hazırlık çalışmaları tamamlandı. Gördüğünüz gibi sınıfımız önemli ölçüde büyüdü.
Artık alım satım sinyalleri oluşturmaya hazırız.
Şekil 4. Hareketli ortalamayla kesişen fiyatın alım satım sinyalleri
Algoritmalarımızı daha ayrıntılı olarak tekrar ele alalım.
1. Satın alma sinyali önceki çubukta aşağıdaki koşullar yerine getirildiğinde görünür:
- çubuğun açılış fiyatı hareketli ortalamanın değerinden düşükse
- çubuğun kapanış fiyatı hareketli ortalamanın değerinden büyükse
- hareketli ortalama artıyorsa.
Bu durumda ayarlar tarafından tanımlanan parametrelerle bekleyen bir Satın Alma emri vermeyi öneriyoruz. Bu amaçla CheckOpenLong sanal yöntemini geçersiz kılıyoruz ve ilgili fonksiyonu ekliyoruz.
2. Satış sinyali önceki çubukta aşağıdaki koşullar yerine getirildiğinde görünür:
- çubuğun açılış fiyatı hareketli ortalamanın değerinden büyükse
- çubuğun kapanış fiyatı hareketli ortalamanın değerinden düşükse
- hareketli ortalama düşüyorsa.
Bu durumda ayarlar tarafından tanımlanan parametrelerle bekleyen bir Satış emri vermeyi öneriyoruz. Bu amaçla CheckOpenShort sanal yöntemini geçersiz kılıyoruz ve ilgili fonksiyonu ekliyoruz.
3. Pozisyonları kapatmak için sinyal üretmeyeceğiz. Pozisyonların Zarar Durdur/Kâr Et ордерам ile kapatılmasını sağlayacağız.
Bu doğrultuda CheckCloseLong ve CheckCloseShort sanal yöntemlerini geçersiz kılmayacağız.
4. Bekleyen bir emrin ayarlar tarafından belirtilen “mesafede” hareketli ortalama boyunca değiştirilmesini önereceğiz.
Bu amaçlaCheckTrailingOrderLong ve CheckTrailingOrderShort sanal yöntemlerini geçersiz kılıyoruz ve bunlara karşılık gelen fonksiyonları ekliyoruz.
Sınıfın tanımı:
class CSampleSignal : public CExpertSignal { protected: CiMA m_MA; // object to access the values of the moving average CiOpen m_open; // object to access the bar open prices CiClose m_close; // object to access the bar close prices //--- Setup parameters int m_period_ma; // averaging period of the MA int m_shift_ma; // shift of the MA along the time axis ENUM_MA_METHOD m_method_ma; // averaging method of the MA ENUM_APPLIED_PRICE m_applied_ma; // averaging object of the MA double m_limit; // level to place a pending order relative to the MA double m_stop_loss; // level to place a stop loss order relative to the open price double m_take_profit; // level to place a take profit order relative to the open price int m_expiration; // lifetime of a pending order in bars public: CSampleSignal(); //--- Methods to set the parameters void PeriodMA(int value) { m_period_ma=value; } void ShiftMA(int value) { m_shift_ma=value; } void MethodMA(ENUM_MA_METHOD value) { m_method_ma=value; } void AppliedMA(ENUM_APPLIED_PRICE value) { m_applied_ma=value; } void Limit(double value) { m_limit=value; } void StopLoss(double value) { m_stop_loss=value; } void TakeProfit(double value) { m_take_profit=value; } void Expiration(int value) { m_expiration=value; } //--- Method to validate the parameters virtual bool ValidationSettings(); //--- Method to validate the parameters virtual bool InitIndicators(CIndicators* indicators); //--- Methods to generate signals to enter the market virtual bool CheckOpenLong(double& price,double& sl,double& tp,datetime& expiration); virtual bool CheckOpenShort(double& price,double& sl,double& tp,datetime& expiration); //--- Methods to generate signals of pending order modification virtual bool CheckTrailingOrderLong(COrderInfo* order,double& price); virtual bool CheckTrailingOrderShort(COrderInfo* order,double& price); protected: //--- Object initialization method bool InitMA(CIndicators* indicators); bool InitOpen(CIndicators* indicators); bool InitClose(CIndicators* indicators); //--- Methods to access object data double MA(int index) { return(m_MA.Main(index)); } double Open(int index) { return(m_open.GetData(index)); } double Close(int index) { return(m_close.GetData(index)); } };
CheckOpenLong, CheckOpenShort, CheckTrailingOrderLong, CheckTrailingOrderShort yöntemlerinin uygulanması:
//+------------------------------------------------------------------+ //| Check whether a Buy condition is fulfilled | //| INPUT: price - variable for open price | //| sl - variable for stop loss price, | //| tp - variable for take profit price | //| expiration - variable for expiration time. | //| OUTPUT: true if the condition is fulfilled, otherwise false. | //| REMARK: No. | //+------------------------------------------------------------------+ bool CSampleSignal::CheckOpenLong(double& price,double& sl,double& tp,datetime& expiration) { //--- Preparing the data double spread=m_symbol.Ask()-m_symbol.Bid(); double ma =MA(1); double unit =PriceLevelUnit(); //--- Checking the condition if(Open(1)<ma && Close(1)>ma && ma>MA(2)) { price=m_symbol.NormalizePrice(ma-m_limit*unit+spread); sl =m_symbol.NormalizePrice(price-m_stop_loss*unit); tp =m_symbol.NormalizePrice(price+m_take_profit*unit); expiration+=m_expiration*PeriodSeconds(m_period); //--- Condition is fulfilled return(true); } //--- Condition is not fulfilled return(false); } //+------------------------------------------------------------------+ //| Check whether a Sell condition is fulfilled. | //| INPUT: price - variable for open price, | //| sl - variable for stop loss, | //| tp - variable for take profit | //| expiration - variable for expiration time. | //| OUTPUT: true if the condition is fulfilled, otherwise false. | //| REMARK: No. | //+------------------------------------------------------------------+ bool CSampleSignal::CheckOpenShort(double& price,double& sl,double& tp,datetime& expiration) { //--- Preparing the data double ma =MA(1); double unit=PriceLevelUnit(); //--- Checking the condition if(Open(1)>ma && Close(1)<ma && ma<MA(2)) { price=m_symbol.NormalizePrice(ma+m_limit*unit); sl =m_symbol.NormalizePrice(price+m_stop_loss*unit); tp =m_symbol.NormalizePrice(price-m_take_profit*unit); expiration+=m_expiration*PeriodSeconds(m_period); //--- Condition is fulfilled return(true); } //--- Condition is not fulfilled return(false); } //+------------------------------------------------------------------+ //| Check whether the condition of modification | //| of a Buy order is fulfilled. | //| INPUT: order - pointer at the object-order, | //| price - a variable for the new open price. | //| OUTPUT: true if the condition is fulfilled, otherwise false. | //| REMARK: No. | //+------------------------------------------------------------------+ bool CSampleSignal::CheckTrailingOrderLong(COrderInfo* order,double& price) { //--- Checking the pointer if(order==NULL) return(false); //--- Preparing the data double spread =m_symbol.Ask()-m_symbol.Bid(); double ma =MA(1); double unit =PriceLevelUnit(); double new_price=m_symbol.NormalizePrice(ma-m_limit*unit+spread); //--- Checking the condition if(order.PriceOpen()==new_price) return(false); price=new_price; //--- Condition is fulfilled return(true); } //+------------------------------------------------------------------+ //| Check whether the condition of modification | //| of a Sell order is fulfilled. | //| INPUT: order - pointer at the object-order, | //| price - a variable for the new open price. | //| OUTPUT: true if the condition is fulfilled, otherwise false. | //| REMARK: No. | //+------------------------------------------------------------------+ bool CSampleSignal::CheckTrailingOrderShort(COrderInfo* order,double& price) { //--- Checking the pointer if(order==NULL) return(false); //--- Preparing the data double ma =MA(1); double unit=PriceLevelUnit(); double new_price=m_symbol.NormalizePrice(ma+m_limit*unit); //--- Checking the condition if(order.PriceOpen()==new_price) return(false); price=new_price; //--- Condition is fulfilled return(true); } //+------------------------------------------------------------------+
Böylece ilk sorunu çözmüş olduk. Yukarıdaki kod ana görevimizi yerine getiren alım satım sinyalleri üreticisi sınıfının bir kaynak kodudur.
2.2. MQL5 Sihirbazı için oluşturulan alım satım sinyalleri sınıfının bir tanımını yapma
Şimdi ikinci sorunu çözmeye dönelim. Sinyalimiz MQL5 Sihirbazı alım satım stratejileri üreticisi tarafından “tanınmalıdır”.
İlk gerekli koşulu sağladık: dosyayı MQL5 Sihirbazı tarafından “bulunacağı” yere yerleştirdik. Ama bu yeterli değil. MQL5 Sihirbazı dosyayı yalnızca “bulmak”la kalmamalı, aynı zamanda da “tanımalıdır”. Bunu yapmak için orijinal metne MQL5 Sihirbazı için sınıf tanımlayıcısını eklemeliyiz.
Sınıf tanımlayıcısı belirli kurallara göre oluşturulmuş bir yorum grubudur.
Şimdi bu kuralları ele alalım.
1. Yorum grubu aşağıdaki satırlarla başlamalıdır:
// wizard description start //+------------------------------------------------------------------+ //| Description of the class |
2. Sonraki satır “//| Title=<Text> |” formatında olan bir metin tanımlayıcısıdır (sinyali seçerken MQL5 Sihirbazında göreceğimiz şey) Metin bir satır için çok büyükse ondan sonra bir satır daha (daha fazlasını değil) ekleyebilirsiniz.
Durumumuz aşağıdaki gibi oldu:
//| Title=Signal on the crossing of a price and the MA | //| entering on its back movement |
3. Daha sonra “//| Type=<Type> |” formatında belirtilen sınıf türüne sahip bir satır olacaktır. <Type> alanı Sinyal değerine sahip olmalıdır (sinyallere ek olarak MQL5 Sihirbazı diğer sınıf türlerini bilir).
Şunu yazın:
//| Type=Signal |
4. “//| Name=<Name> |” formatında olan aşağıdaki satır sinyalin kısa adıdır (uzmanın global değişkenlerinin adlarını oluşturmak için MQL5 Sihirbazı tarafından kullanılır).
Durum aşağıdaki gibi olacaktır:
//| Name=Sample |
5. Bir sınıfın adı tanımın önemli bir unsurudur. “//| Class=<ClassNamea> |” formatında olan satırda, <ClassName> parametresi sınıfımızın adıyla eşleşmelidir:
//| Class=CSampleSignal |
6. Bu satırı doldurmuyoruz ancak mevcut olması gerekiyor (bu, dil referansı bölümüne giden bir bağlantıdır):
//| Page= |
7. Bir de sinyal kurulum parametrelerinin tanımları vardır.
Bu bir satır kümesidir (satır sayısı parametre sayısına eşittir).
Her satırın formatı “//| Parameter=<NameOfMethod>,<TypeOfParameter>,<DefaultValue> |” şeklindedir.
İşte parametre grubumuz:
//| Parameter=PeriodMA,int,12 | //| Parameter=ShiftMA,int,0 | //| Parameter=MethodMA,ENUM_MA_METHOD,MODE_EMA | //| Parameter=AppliedMA,ENUM_APPLIED_PRICE,PRICE_CLOSE | //| Parameter=Limit,double,0.0 | //| Parameter=StopLoss,double,50.0 | //| Parameter=TakeProfit,double,50.0 | //| Parameter=Expiration,int,10 |
8. Yorum grubu aşağıdaki satırlarla bitmelidir:
//+------------------------------------------------------------------+ // wizard description end
Tanımlayıcıyı kaynak koduna ekleyelim.
//+------------------------------------------------------------------+ //| SampleSignal.mqh | //| Copyright 2010, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2010, MetaQuotes Software Corp." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| include files | //+------------------------------------------------------------------+ #include <Expert\ExpertSignal.mqh> // wizard description start //+------------------------------------------------------------------+ //| Description of the class | //| Title=Signal on crossing of the price and the MA | //| entering on the back movement | //| Type=Signal | //| Name=Sample | //| Class=CSampleSignal | //| Page= | //| Parameter=PeriodMA,int,12 | //| Parameter=ShiftMA,int,0 | //| Parameter=MethodMA,ENUM_MA_METHOD,MODE_EMA | //| Parameter=AppliedMA,ENUM_APPLIED_PRICE,PRICE_CLOSE | //| Parameter=Limit,double,0.0 | //| Parameter=StopLoss,double,50.0 | //| Parameter=TakeProfit,double,50.0 | //| Parameter=Expiration,int,10 | //+------------------------------------------------------------------+ // wizard description end //+------------------------------------------------------------------+ //| CSampleSignal class. | //| Purpose: Class of trading signal generator when price | //| crosses moving average, | //| entering on the subsequent back movement. | //| It is derived from the CExpertSignal class. | //+------------------------------------------------------------------+ class CSampleSignal : public CExpertSignal { protected: CiMA m_MA; // object to access the values of the moving average CiOpen m_open; // object to access the bar open prices CiClose m_close; // object to access the bar close prices //--- Setup parameters int m_period_ma; // averaging period of the MA int m_shift_ma; // shift of the MA along the time axis ENUM_MA_METHOD m_method_ma; // averaging method of the MA ENUM_APPLIED_PRICE m_applied_ma; // averaging object of the MA double m_limit; // level to place a pending order relative to the MA double m_stop_loss; // level to place a stop loss order relative to the open price double m_take_profit; // level to place a take profit order relative to the open price int m_expiration; // lifetime of a pending order in bars public: CSampleSignal(); //--- Methods to set the parameters void PeriodMA(int value) { m_period_ma=value; } void ShiftMA(int value) { m_shift_ma=value; } void MethodMA(ENUM_MA_METHOD value) { m_method_ma=value; } void AppliedMA(ENUM_APPLIED_PRICE value) { m_applied_ma=value; } void Limit(double value) { m_limit=value; } void StopLoss(double value) { m_stop_loss=value; } void TakeProfit(double value) { m_take_profit=value; } void Expiration(int value) { m_expiration=value; } //---Method to validate the parameters virtual bool ValidationSettings(); //--- Method to validate the parameters virtual bool InitIndicators(CIndicators* indicators); //--- Methods to generate signals to enter the market virtual bool CheckOpenLong(double& price,double& sl,double& tp,datetime& expiration); virtual bool CheckOpenShort(double& price,double& sl,double& tp,datetime& expiration); //--- Methods to generate signals of pending order modification virtual bool CheckTrailingOrderLong(COrderInfo* order,double& price); virtual bool CheckTrailingOrderShort(COrderInfo* order,double& price); protected: //--- Object initialization method bool InitMA(CIndicators* indicators); bool InitOpen(CIndicators* indicators); bool InitClose(CIndicators* indicators); //--- Methods to access object data double MA(int index) { return(m_MA.Main(index)); } double Open(int index) { return(m_open.GetData(index)); } double Close(int index) { return(m_close.GetData(index)); } }; //+------------------------------------------------------------------+ //| CSampleSignal Constructor. | //| INPUT: No. | //| OUTPUT: No. | //| REMARK: No. | //+------------------------------------------------------------------+ void CSampleSignal::CSampleSignal() { //--- Setting the default values m_period_ma =12; m_shift_ma =0; m_method_ma =MODE_EMA; m_applied_ma =PRICE_CLOSE; m_limit =0.0; m_stop_loss =50.0; m_take_profit=50.0; m_expiration =10; } //+------------------------------------------------------------------+ //| Validation of parameters. | //| INPUT: No. | //| OUTPUT: true if the settings are correct, otherwise false. | //| REMARK: No. | //+------------------------------------------------------------------+ bool CSampleSignal::ValidationSettings() { //--- Validation of parameters if(m_period_ma<=0) { printf(__FUNCTION__+": the MA period must be greater than zero"); return(false); } //--- Successful completion return(true); } //+------------------------------------------------------------------+ //| Initialization of indicators and timeseries. | //| INPUT: indicators - pointer to the object - collection of | //| indicators and timeseries. | //| OUTPUT: true in case of success, otherwise false. | //| REMARK: No. | //+------------------------------------------------------------------+ bool CSampleSignal::InitIndicators(CIndicators* indicators) { //--- Validation of the pointer if(indicators==NULL) return(false); //--- Initialization of the moving average if(!InitMA(indicators)) return(false); //--- Initialization of the timeseries of open prices if(!InitOpen(indicators)) return(false); //--- Initialization of the timeseries of close prices if(!InitClose(indicators)) return(false); //--- Successful completion return(true); } //+------------------------------------------------------------------+ //| Initialization of the moving average | //| INPUT: indicators - pointer to the object - collection of | //| indicators and timeseries. | //| OUTPUT: true in case of success, otherwise false. | //| REMARK: No. | //+------------------------------------------------------------------+ bool CSampleSignal::InitMA(CIndicators* indicators) { //--- Initialization of the MA object if(!m_MA.Create(m_symbol.Name(),m_period,m_period_ma,m_shift_ma,m_method_ma,m_applied_ma)) { printf(__FUNCTION__+": object initialization error"); return(false); } m_MA.BufferResize(3+m_shift_ma); //--- Adding an object to the collection if(!indicators.Add(GetPointer(m_MA))) { printf(__FUNCTION__+": object adding error"); return(false); } //--- Successful completion return(true); } //+------------------------------------------------------------------+ //| Initialization of the timeseries of open prices. | //| INPUT: indicators - pointer to the object - collection of | //| indicators and timeseries. | //| OUTPUT: true in case of success, otherwise false. | //| REMARK: No. | //+------------------------------------------------------------------+ bool CSampleSignal::InitOpen(CIndicators* indicators) { //--- Initialization of the timeseries object if(!m_open.Create(m_symbol.Name(),m_period)) { printf(__FUNCTION__+": object initialization error"); return(false); } //--- Adding an object to the collection if(!indicators.Add(GetPointer(m_open))) { printf(__FUNCTION__+": object adding error"); return(false); } //--- Successful completion return(true); } //+------------------------------------------------------------------+ //| Initialization of the timeseries of close prices. | //| INPUT: indicators - pointer to the object - collection of | //| indicators and timeseries. | //| OUTPUT: true in case of success, otherwise false. | //| REMARK: No. | //+------------------------------------------------------------------+ bool CSampleSignal::InitClose(CIndicators* indicators) { //--- Initialization of the timeseries object if(!m_close.Create(m_symbol.Name(),m_period)) { printf(__FUNCTION__+": object initialization error"); return(false); } //--- Adding an object to the collection if(!indicators.Add(GetPointer(m_close))) { printf(__FUNCTION__+": object adding error"); return(false); } //--- Successful completion return(true); } //+------------------------------------------------------------------+ //| Check whether a Buy condition is fulfilled | //| INPUT: price - variable for open price | //| sl - variable for stop loss price, | //| tp - variable for take profit price | //| expiration - variable for expiration time. | //| OUTPUT: true if the condition is fulfilled, otherwise false. | //| REMARK: No. | //+------------------------------------------------------------------+ bool CSampleSignal::CheckOpenLong(double& price,double& sl,double& tp,datetime& expiration) { //--- Preparing the data double spread=m_symbol.Ask()-m_symbol.Bid(); double ma =MA(1); double unit =PriceLevelUnit(); //--- Checking the condition if(Open(1)<ma && Close(1)>ma && ma>MA(2)) { price=m_symbol.NormalizePrice(ma-m_limit*unit+spread); sl =m_symbol.NormalizePrice(price-m_stop_loss*unit); tp =m_symbol.NormalizePrice(price+m_take_profit*unit); expiration+=m_expiration*PeriodSeconds(m_period); //--- Condition is fulfilled return(true); } //--- Condition is not fulfilled return(false); } //+------------------------------------------------------------------+ //| Check whether a Sell condition is fulfilled. | //| INPUT: price - variable for open price, | //| sl - variable for stop loss, | //| tp - variable for take profit | //| expiration - variable for expiration time. | //| OUTPUT: true if the condition is fulfilled, otherwise false. | //| REMARK: No. | //+------------------------------------------------------------------+ bool CSampleSignal::CheckOpenShort(double& price,double& sl,double& tp,datetime& expiration) { //--- Preparing the data double ma =MA(1); double unit=PriceLevelUnit(); //--- Checking the condition if(Open(1)>ma && Close(1)<ma && ma<MA(2)) { price=m_symbol.NormalizePrice(ma+m_limit*unit); sl =m_symbol.NormalizePrice(price+m_stop_loss*unit); tp =m_symbol.NormalizePrice(price-m_take_profit*unit); expiration+=m_expiration*PeriodSeconds(m_period); //--- Condition is fulfilled return(true); } //--- Condition is not fulfilled return(false); } //+------------------------------------------------------------------+ //| Check whether the condition of modification | //| of a Buy order is fulfilled. | //| INPUT: order - pointer at the object-order, | //| price - a variable for the new open price. | //| OUTPUT: true if the condition is fulfilled, otherwise false. | //| REMARK: No. | //+------------------------------------------------------------------+ bool CSampleSignal::CheckTrailingOrderLong(COrderInfo* order,double& price) { //--- Checking the pointer if(order==NULL) return(false); //--- Preparing the data double spread =m_symbol.Ask()-m_symbol.Bid(); double ma =MA(1); double unit =PriceLevelUnit(); double new_price=m_symbol.NormalizePrice(ma-m_limit*unit+spread); //--- Checking the condition if(order.PriceOpen()==new_price) return(false); price=new_price; //--- Condition is fulfilled return(true); } //+------------------------------------------------------------------+ //| Check whether the condition of modification | //| of a Sell order is fulfilled. | //| INPUT: order - pointer at the object-order, | //| price - a variable for the new open price. | //| OUTPUT: true if the condition is fulfilled, otherwise false. | //| REMARK: No. | //+------------------------------------------------------------------+ bool CSampleSignal::CheckTrailingOrderShort(COrderInfo* order,double& price) { //--- Checking the pointer if(order==NULL) return(false); //--- Preparing the data double ma =MA(1); double unit=PriceLevelUnit(); double new_price=m_symbol.NormalizePrice(ma+m_limit*unit); //--- Checking the condition if(order.PriceOpen()==new_price) return(false); price=new_price; //--- Condition is fulfilled return(true); } //+------------------------------------------------------------------+
Pekâlâ, hepsi bu. Sinyal artık kullanılabilir.
MQL5 Sihirbazı üretici alım satım stratejilerinin sinyalimizi kullanabilmesi için MetaEditor’u yeniden başlatmalıyız (MQL5 Sihirbazı Include\Expert klasörünü yalnızca açılışta tarar).
MetaEditor'u yeniden başlattıktan sonra, oluşturulan alım satım sinyalleri modülü MQL5 Sihirbazında kullanılabilir:
Şekil 5. MQL5 Sihirbazında oluşturulan alım satım sinyalleri üreticisi
Alım satım sinyalleri üreticisi parametrelerinin tanımı bölümünde belirtilen girdi parametreleri artık mevcuttur:
Şekil 6. Şekil 6. MQL5 Sihirbazında oluşturulan alım satım sinyalleri üreticisinin girdi parametreleri
Uygulanan alım satım stratejisinin girdi parametrelerinin en iyi değerleri MetaTrader 5 terminalindeki Strateji Test Edici kullanılarak bulunabilir.
Sonuç
MQL5 Sihirbazının alım satım stratejileri üreticisi alım satım fikirlerinin test edilmesini büyük ölçüde basitleştirir. Oluşturulan uzmanın kodu alım satım sinyali sınıflarının, para ve risk yönetimi sınıflarının ve pozisyon destek sınıflarının belirli uygulamalarını oluşturmak için kullanılan Standart Kütüphanenin alım satım stratejileri sınıflarına dayanmaktadır.
Bu makale fiyatın ve hareketli ortalamanın kesişimine ilişkin sinyallerin uygulanmasıyla kendi alım satım sinyalleri sınıfınızı nasıl yazacağınız ve bunu MQL5 Sihirbazının alım satım stratejileri oluşturucusuna nasıl ekleyeceğinizle birlikte mql5 Sihirbazı için oluşturulan sınıfın tanımının yapısını ve biçimini açıklar.
MetaQuotes Ltd tarafından Rusçadan çevrilmiştir.
Orijinal makale: https://www.mql5.com/ru/articles/226





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