English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
MQL5 Sihirbazı: Hesaplanan Fiyatlardan Talimatlar, Zarar Durdur ve Kar Al uygulama. Standart Kitaplık Uzantısı

MQL5 Sihirbazı: Hesaplanan Fiyatlardan Talimatlar, Zarar Durdur ve Kar Al uygulama. Standart Kitaplık Uzantısı

MetaTrader 5Örnekler | 14 Ocak 2022, 10:54
200 0
Andrey Shpilev
Andrey Shpilev

Giriş

MQL5 Standart Kitaplık, katı bir mimari gerektiren büyük projelerin geliştirilmesinde faydalı bir yardımcıdır. MQL5 Sihirbazı, diyalog modunda birkaç dakika içinde, fazla tahmin edilemeyecek kadar kapsamlı bir şema halinde hazır parçaların birleştirilmesine izin verir. MQL5 Sihirbazı, Expert'in tüm parçalarını bir araya getirmeyi otomatikleştirir ve modül parametrelerini, tanıtıcılara göre Expert'te otomatik olarak bildirir. Dahil edilen çok sayıda çeşitli modül olduğunda, bu tür otomasyon çok fazla zaman ve rutin işlemler tasarrufu sağlar.

Kulağa hoş geliyor, ancak bariz bir dezavantaj var; Sihirbaz ile standart sınıflara dayalı olarak oluşturulan alım satım sistemlerinin yetenekleri sınırlıdır. Bu makale, oluşturulan Uzmanların işlevselliğini önemli ölçüde genişletmeye izin veren evrensel bir yöntemi ele almaktadır. Bu yöntem uygulandığında, Sihirbaz ve standart modüllerle uyumluluk aynı kalır.

Yöntemin fikri, Nesneye Yönelik Programlama'da kalıtım ve polimorfizm mekanizmalarını kullanmak veya oluşturulan Expert'lerin kodunda standart sınıfların yerine geçecek sınıflar oluşturmaktır. Bu şekilde, Sihirbazın ve Standart Kitaplığın tüm avantajlarından yararlanılır, bu da gerekli yeteneklere sahip bir Expert'in geliştirilmesiyle sonuçlanır. Yine de buraya ulaşmak için kodun sadece dört dizeyle biraz azaltılması gerekir.

Bu makalenin pratik amacı, oluşturulan Expert'lere, yalnızca mevcut fiyattan belirtilen mesafede değil, gerekli fiyat seviyelerinde talimat verme, Zararı Durdurma ve Kar Alma yeteneği eklemektir.

Benzer fikir "MQL5 Sihirbazı: Bir EA'ya Herhangi Bir Fiyatta Bekleyen Talimatları Açmayı Öğretme" makalesinde tartışıldı. Önerilen çözümün önemli dezavantajı, alım satım sinyali modülünün parametresinin alt filtreden "zorla" değiştirilmesidir. Bu yaklaşım, çok sayıda modülle çalışmayı ve süreç optimizasyonu için Sihirbazı kullanmayı desteklemez.

Standart sınıflardan devralınan sınıflarda herhangi bir fiyattan talimat verme, Zarar Durdur ve Kar Al işlemlerinin uygulanması daha ayrıntılı olarak ele alınmaktadır. Bununla birlikte, modüller arasında herhangi bir çakışma imkansızdır. Umarım bu makale bir örnek teşkil eder ve okuyuculara standart çerçeve üzerinde kendi geliştirmelerini yazmaları için ilham verir ve ayrıca kullanıcıların geliştirilen Kitaplık uzantısını uygulamalarına izin verir.


1. Karar Vermenin Standart Algoritması

MQL5 Sihirbazında oluşturulan uzmanlar, CExpert sınıf örneğini temel alır. CExpertSignal sınıfının nesnesinin işaretçisi bu sınıfta bildirildi. Makalede ayrıca bu nesne, kısalık uğruna ana sinyal olarak adlandırılır. Ana sinyal, alt filtrelere yönelik işaretçiler içerir (sinyal modülleri, CExpertSignal sınıfının mirasçılarıdır).

Açık pozisyon ve talimat yoksa Expert, yeni bir onay işareti üzerinde bir pozisyon açma fırsatını kontrol etmek için ana sinyale başvurur. Ana sinyal, alt filtreleri tek tek sorgular ve elde edilen tahmine göre ağırlıklı ortalama tahmini (yön) hesaplar. Bunun değeri, eşiği (ana sinyaldeki m_threshold_open parametresinin değeri) aşarsa talimat parametreleri ve bool tipi koşullar için kontrol sonuçları Expert'e iletilir. Bu koşullar karşılanırsa ya piyasa fiyatında bir pozisyon açılır ya da belli bir mesafede bekleyen bir talimat açılır (bkz. Şekil 1). Zarar Durdurma yalnızca sabit bir mesafeye yerleştirilebilir. Açılış fiyatı başlangıçları, Zarar Durdur ve piyasa fiyatından Kar Al işlemleri Expert ayarlarında belirtilir ve ana sinyalde, m_price_level, m_stop_level ve m_take_level değişkenlerinde sırasıyla saklanır.

Bu nedenle, şu anda bir talimatın verilebilmesi için iki koşulun karşılanması gerekir:

  1. Mevcut sembol için açık pozisyon yok;
  2. Ağırlıklı ortalama tahminin mutlak değeri, eşik değerini aşar; bu da bir trendin oldukça güçlü olduğu anlamına gelir.

Şek. 1. Piyasaya girerken karar verme formasyonu

Şek. 1. Piyasaya girerken karar verme formasyonu

Şekil 1'deki mevcut karar verme modeli, MQL5 Sihirbazının uygulama alanını önemli ölçüde sınırlandırmaktadır. Sabit Zarar Durdur işleminin değerine sahip stratejiler, değişken volatilite nedeniyle uzun vadeli alım satımda nadiren etkilidir. Bekleyen talimatları kullanan sistemler genellikle bunları dinamik olarak hesaplanmış seviyelere yerleştirmeyi gerektirir.


2. Karar Vermenin Değiştirilmiş Algoritması

Seviyeleri hesaplama ve talimat verme perspektifinden, sinyal modülleri bir tahmin değerinden başka bir şey üretemediğinden ve ana sinyal seviyelerle çalışmak için tasarlanmadığından bu bir çıkmaz durumdur. Bu konuda tavsiye edilir:

  • Talimat parametreleri üretebilen yeni tür sinyal modülleri (bunlara fiyat modülleri diyeceğiz) tanıtmak;
  • Bu parametreleri işlemek için ana sinyali eğitin, yani en iyilerini seçin ve Expert'e iletin.

Değiştirilmiş algoritma (Şek. 2), bekleyen talimatların yanı sıra diğer taleplerle de çalışmaya izin verir. Bu algoritmanın özü, giriş noktasını (fiyatı) bir trend tanımlamadan (ağırlıklı ortalama tahmini) ayırmasıdır. Bu, bir karar vermek için filtrelerle tercih edilen alım satım yönünün tanımlandığı ve fiyat modüllerinden elde edilen uygun yöne sahip bir dizi talimat parametresinin seçildiği anlamına gelir. Kullanılabilir birkaç benzer set varsa set, en büyük ağırlığa (m_weight parametre değeri seçilir) sahip modülden alınır. Yön belirlenmişse ancak şu anda uygun giriş noktası yoksa Expert etkin değildir.

Şek. 2. Piyasaya girerken değiştirilen karar verme formasyonu

Şek. 2. Piyasaya girerken değiştirilen karar verme formasyonu

Yeni bir talimat vermek için aşağıdaki gereksinimlerin karşılanması gerekir:

  1. Mevcut sembol için açık pozisyon ve talimat yok;
  2. Ağırlıklı ortalama tahmininin mutlak değeri eşik değerini aşıyor;
  3. Talimatın en az bir açılış fiyatı bulundu.

Şekil 2'deki algoritma, birçok olası giriş noktasının ele alınmasına, yönlere göre filtrelenmesine ve bir Expert'te en iyisinin seçilmesine olanak tanır.


3. Expert ve Sinyal Modülünün Değiştirilmiş Sınıflarının Geliştirilmesi

Kitaplığın uzantısı iki sınıfa dayanmaktadır: CExpertSignalAdvanced ve CExpertAdvanced, sırasıyla CExpertSignal ve CExpert uzantısından devralınır.

Expert'in farklı blokları arasında veri alışverişi için kullanılan arayüzleri değiştirmeyi amaçlayan yeni yetenekler özellikler eklemeye yönelik tüm önlemler. Örneğin algoritmayı Şek. 2'deki kalıba göre uygulamak için ana sinyalin (sınıf CExpertSignalAdvanced) fiyat modülleri (bu sınıfın torunları) ile etkileşimini organize etmek gerekir. Veri değiştiğinde önceden verilmiş talimatların güncellenmesi, Expert'in (sınıf CExpertAdvanced) ana sinyalle etkileşimini gerektirir.

Bu aşamada, açık pozisyonlar için Şek. 2'deki modeli uygulayacağız ve parametreler değiştiğinde (örneğin daha uygun bir giriş noktası göründüğünde) halihazırda verilmiş olan talimatların güncellenmesini organize edeceğiz. CExpertSignalAdvanced sınıfını ele alalım.

3.1. CExpertSignalAdvanced

Bu sınıf, üst öğesinin sinyal modülleri için temel olduğu gibi, ana sinyal rolünde üst öğesinin yerini alacak ve fiyat modülleri için temel sınıf olacaktır.

class CExpertSignalAdvanced : public CExpertSignal
  {
protected:
   //---data members for storing parameters of the orders being placed
   double            m_order_open_long;         //opening price of the order to buy
   double            m_order_stop_long;         //Stop Loss of the order to buy
   double            m_order_take_long;         //Take Profit of the order to buy
   datetime          m_order_expiration_long;   //expiry time of the order to buy
   double            m_order_open_short;        //opening price of the order to sell
   double            m_order_stop_short;        //Stop Loss of the order to sell
   double            m_order_take_short;        //Take Profit of the order to sell
   datetime          m_order_expiration_short;  //expiry time of the order to sell
   //---             
   int               m_price_module;            //index of the first price module in the m_filters array
public:
                     CExpertSignalAdvanced();
                    ~CExpertSignalAdvanced();
   virtual void      CalcPriceModuleIndex() {m_price_module=m_filters.Total();}
   virtual bool      CheckOpenLong(double &price,double &sl,double &tp,datetime &expiration);
   virtual bool      CheckOpenShort(double &price,double &sl,double &tp,datetime &expiration);
   virtual double    Direction(void);		//calculating weighted average forecast based on the data received from signal modules
   virtual double    Prices(void);		//updating of parameters of the orders being placed according to the data received from price modules
   virtual bool      OpenLongParams(double &price,double &sl,double &tp,datetime &expiration);
   virtual bool      OpenShortParams(double &price,double &sl,double &tp,datetime &expiration);
   virtual bool      CheckUpdateOrderLong(COrderInfo *order_ptr,double &open,double &sl,double &tp,datetime &ex);
   virtual bool      CheckUpdateOrderShort(COrderInfo *order_ptr,double &open,double &sl,double &tp,datetime &ex);
   double            getOpenLong()              { return m_order_open_long;         }
   double            getOpenShort()             { return m_order_open_short;        }
   double            getStopLong()              { return m_order_stop_long;         }
   double            getStopShort()             { return m_order_stop_short;        }
   double            getTakeLong()              { return m_order_take_long;         }
   double            getTakeShort()             { return m_order_take_short;        }
   datetime          getExpLong()               { return m_order_expiration_long;   }
   datetime          getExpShort()              { return m_order_expiration_short;  }
   double            getWeight()                { return m_weight;                  }
  };

Talimat parametrelerini depolamak için veri üyeleri, CExpertSignalAdvanced sınıfında bildirildi. Bu değişkenlerin değerleri Prices() yönteminde güncellenir. Bu değişkenler arabellek olarak davranır.

Ardından, m_price_module parametresi bildirilir. İlk fiyat modülünün indeksini CExpertSignal içinde bildirilen m_filters dizisinde saklar. Bu dizi, dahil edilen sinyal modüllerinin işaretçilerini içerir. Standart modüllere (filtreler) yönelik işaretçiler, dizinin başında saklanır. Ardından m_price_module indeksinden başlayarak fiyat modülleri gelir. Göstergelerin ve zaman serilerinin başlatma yöntemlerinin değiştirilmesi gerekliliğinden kaçınmak için her şeyin tek bir dizide saklanmasına karar verildi. Ayrıca, bir dizi üzerinden 64 modül içerme olasılığı vardır ve genellikle yeterlidir.

Ayrıca, korunan veri üyelerinin değerlerini elde etmek için CExpertSignalAdvanced sınıfında yardımcı yöntemler bildirildi. Adları get ile başlar (sınıf bildirimine bakın).

3.1.1. Kurucu

kurucu CExpertSignalAdvanced, sınıf içinde bildirilen değişkenleri başlatır:

CExpertSignalAdvanced::CExpertSignalAdvanced()
  {
   m_order_open_long=EMPTY_VALUE;
   m_order_stop_long=EMPTY_VALUE;
   m_order_take_long=EMPTY_VALUE;
   m_order_expiration_long=0;
   m_order_open_short=EMPTY_VALUE;
   m_order_stop_short=EMPTY_VALUE;
   m_order_take_short=EMPTY_VALUE;
   m_order_expiration_short=0;
   m_price_module=-1;
  }

3.1.2. CalcPriceModuleIndex()

CalcPriceModuleIndex() yöntemi, m_price_module mevcut dizi öğeleri sayısını, aşağıdaki eklenen modülün dizinine eşit olarak atar. Bu yöntem, ilk fiyat modülünü eklemeden önce çağrılır. İşlev gövdesi sınıf bildirimindedir.

virtual void      CalcPriceModuleIndex() {m_price_module=m_filters.Total();}

3.1.3. CheckOpenLong(...) ve CheckOpenShort(...)

CheckOpenLong(...) yöntemi, CExpert sınıfı örneğinden çağrılır ve aşağıda açıklandığı gibi çalışır:

  1. Dahil edilen fiyat modüllerini kontrol edin. Hiçbiri yoksa üst sınıfın isimsiz yöntemini çağırın;
  2. Direction() yönteminden ağırlıklı ortalama tahmin (yön) alın;
  3. Yönü EMPTY_VALUE ile ve m_threshold_open eşik değerini karşılaştırarak giriş koşullarının karşılanıp karşılanmadığını doğrulayın;
  4. Talimat parametrelerinin değerlerini Prices() yöntemiyle yenileyin ve OpenLongParams(...) işleviyle Expert'e iletin. Bu işlevin sonucunu kaydedin;
  5. Kaydedilen sonucu döndürün.
bool CExpertSignalAdvanced::CheckOpenLong(double &price,double &sl,double &tp,datetime &expiration)
  {
//--- if price modules were not found, call the method of the basic class CExpertSignal
   if(m_price_module<0)
      return(CExpertSignal::CheckOpenLong(price,sl,tp,expiration));

   bool   result   =false;
   double direction=Direction();
//--- prohibitive signal
   if(direction==EMPTY_VALUE)
      return(false);
//--- check for exceeding the threshold
   if(direction>=m_threshold_open)
     {
      Prices();
      result=OpenLongParams(price,sl,tp,expiration);//there's a signal if m_order_open_long!=EMPTY_VALUE
     }
//--- return the result
   return(result);
  }

CheckOpenShort(...) aynı çalışma prensibine sahiptir ve aynı şekilde kullanılır, bu yüzden dikkate almayacağız.

3.1.4 Direction()

Direction() yöntemi, filtreleri sorgular ve ağırlıklı ortalama tahmini hesaplar. Bu yöntem, döngüde m_filters dizisinin tüm öğelerine değil, yalnızca 0'dan m_price_module modülüne kadar değişen bir indekse sahip olanlara atıfta bulunmamız dışında, üst sınıf CExpertSignal sinyalinin adsız yöntemine çok benzer. Geri kalan her şey CExpertSignal::Direction() yönüne benzer.

double CExpertSignalAdvanced::Direction(void)
  {
   long   mask;
   double direction;
   double result=m_weight*(LongCondition()-ShortCondition());
   int    number=(result==0.0)? 0 : 1;      // number of queried modules
//--- loop by filters
   for(int i=0;i<m_price_module;i++)
     {
      //--- mask for bitmaps (variables, containing flags)
      mask=((long)1)<<i;
      //--- checking for a flag of ignoring a filter signal
      if((m_ignore&mask)!=0)
         continue;
      CExpertSignal *filter=m_filters.At(i);
      //--- checking for a pointer
      if(filter==NULL)
         continue;
      direction=filter.Direction();
      //--- prohibitive signal
      if(direction==EMPTY_VALUE)
         return(EMPTY_VALUE);
      if((m_invert&mask)!=0)
         result-=direction;
      else
         result+=direction;
      number++;
     }
//--- averaging the sum of weighted forecasts
   if(number!=0)
      result/=number;
//--- return the result
   return(result);
  }

3.1.5. Fiyatlar()

Prices() yöntemi, m_price_module dizininden sonuna kadar m_filters dizisinin ikinci kısmı üzerinde yinelenir. Bu, fiyat modüllerini sorgular ve OpenLongParams(...) ve OpenShortParams(...) işlevleriyle sınıf değişkenlerinin değerlerini yeniler. Döngüden önce parametre değerleri temizlenir.

Döngü sırasında, mevcut fiyat modülünün (m_weight) ağırlığı, daha önce sorgulanan ve değerleri sağlayan modüllerden daha büyükse parametre değerlerinin üzerine yazılır. Sonuç olarak ya boş parametreler (hiçbir şey bulunamadıysa) ya da bir yöntem çağrıldığında mevcut en iyi ağırlığa sahip parametreler bırakılır.

double CExpertSignalAdvanced::Prices(void)
  {
   m_order_open_long=EMPTY_VALUE;
   m_order_stop_long=EMPTY_VALUE;
   m_order_take_long=EMPTY_VALUE;
   m_order_expiration_long=0;
   m_order_open_short=EMPTY_VALUE;
   m_order_stop_short=EMPTY_VALUE;
   m_order_take_short=EMPTY_VALUE;
   m_order_expiration_short=0;
   int    total=m_filters.Total();
   double last_weight_long=0;
   double last_weight_short=0;
//--- cycle for price modules
   for(int i=m_price_module;i<total;i++)
     {   
      CExpertSignalAdvanced *prm=m_filters.At(i);
      if(prm==NULL)
         continue;
//--- ignore the current module if it has returned EMPTY_VALUE
      if(prm.Prices()==EMPTY_VALUE)continue;
      double weight=prm.getWeight();
      if(weight==0.0)continue;
//--- select non-empty values from modules with the greatest weight
      if(weight>last_weight_long && prm.getExpLong()>TimeCurrent())
         if(prm.OpenLongParams(m_order_open_long,m_order_stop_long,m_order_take_long,m_order_expiration_long))
            last_weight_long=weight;
      if(weight>last_weight_short && prm.getExpShort()>TimeCurrent())
         if(prm.OpenShortParams(m_order_open_short,m_order_stop_short,m_order_take_short,m_order_expiration_short))
            last_weight_short=weight;
     }
   return(0);
  }

3.1.6. OpenLongParams(...) ve OpenShortParams(...)

CExpertSignalAdvanced sınıfı içinde, OpenLongParams(...) yöntemi, sınıf değişkenlerinden referansla satın alınacak talimatın parametre değerlerini giriş parametrelerine iletir.

Bu yöntemin üst sınıftaki rolü biraz farklıydı. Bu, piyasa fiyatına ve ana sinyalde belirtilen girintilere dayalı olarak gerekli parametreleri hesaplıyordu. Şimdi bu sadece hazır parametreleri iletir. Açılış fiyatı doğruysa (EMPTY_VALUE değerine eşit değilse) yöntem true, aksi takdirde false döndürür.

bool CExpertSignalAdvanced::OpenLongParams(double &price,double &sl,double &tp,datetime &expiration)
  {
   if(m_order_open_long!=EMPTY_VALUE)
     {
      price=m_order_open_long;
      sl=m_order_stop_long;
      tp=m_order_take_long;
      expiration=m_order_expiration_long;
      return(true);
     }
   return(false);
  }

Çalışma prensibi aynı olduğu ve benzer şekilde kullanıldığı için OpenShortParams(...) konusunu ele almayacağız.

3.1.7. CheckUpdateOrderLong(...) ve CheckUpdateOrderShort(...)

CheckUpdateOrderLong(...) ve CheckUpdateOrderShort(...) yöntemlerine CExpertAdvanced sınıfı çağrılır. Halihazırda verilmiş bekleyen talimatları son fiyat seviyelerine göre güncellemek için kullanılırlar.

CheckUpdateOrderLong(...) yöntemini daha yakından inceleyeceğiz. Fiyatlar(...) yöntemi çağrılırken ilk olarak fiyat seviyeleri güncellenir, ardından olası değişiklik hatalarını dışlamak için veri güncellemeleri için bir kontrol yapılır. Son olarak güncellenmiş verileri geçirmek ve sonucu döndürmek için OpenLongParams(...) yöntemi çağrılır.

bool CExpertSignalAdvanced::CheckUpdateOrderLong(COrderInfo *order_ptr,double &open,double &sl,double &tp,datetime &ex)
  {
   Prices();   //update prices
//--- check for changes
   double point=m_symbol.Point();
   if(   MathAbs(order_ptr.PriceOpen() - m_order_open_long)>point
      || MathAbs(order_ptr.StopLoss()  - m_order_stop_long)>point
      || MathAbs(order_ptr.TakeProfit()- m_order_take_long)>point
      || order_ptr.TimeExpiration()!=m_order_expiration_long)
      return(OpenLongParams(open,sl,tp,ex));
//--- update is not required   
   return (false);
  }

CheckUpdateOrderShort(...) benzer şekilde çalıştığı ve aynı şekilde uygulandığı için dikkate alınmayacaktır.

3.2. CExpertAdvanced

Expert sınıfındaki değişiklikler, yalnızca ana sinyaldeki fiyatlara ilişkin güncellenmiş verilere göre önceden verilmiş talimatların değiştirilmesiyle ilgilidir. CExpertAdvanced sınıf bildirimi aşağıda sunulmuştur.

class CExpertAdvanced : public CExpert
  {
protected:
   virtual bool      CheckTrailingOrderLong();
   virtual bool      CheckTrailingOrderShort();
   virtual bool      UpdateOrder(double price,double sl,double tp,datetime ex);
public:
                     CExpertAdvanced();
                    ~CExpertAdvanced();
  };

Gördüğümüz gibi yöntemler azdır, yapıcı ve oluşturucu boştur.

3.2.1. CheckTrailingOrderLong() ve CheckTrailingOrderShort()

CheckTrailingOrderLong() yöntemi, temel sınıfın adsız bir yöntemini geçersiz kılar ve sırayı değiştirme gerekliliğini anlamak için ana sinyalin CheckUpdateOrderLong(...) yöntemini çağırır. Değişiklik gerekiyorsa UpdateOrder(...) yöntemi çağrılır ve sonuç döndürülür.

bool CExpertAdvanced::CheckTrailingOrderLong(void)
  {
   CExpertSignalAdvanced *signal_ptr=m_signal;
//--- check for the opportunity to modify the order to buy
   double price,sl,tp;
   datetime ex;
   if(signal_ptr.CheckUpdateOrderLong(GetPointer(m_order),price,sl,tp,ex))
      return(UpdateOrder(price,sl,tp,ex));
//--- return with no actions taken
   return(false);
  }

CheckTrailingOrderShort() yöntemi benzerdir ve aynı şekilde kullanılır.

3.2.2. UpdateOrder()

UpdateOrder() işlevi, ilgili fiyatın kontrolüyle başlar (EMPTY_VALUE değil). Yoksa talimat silinir, aksi halde alınan parametrelere göre talimat değiştirilir.

bool CExpertAdvanced::UpdateOrder(double price,double sl,double tp,datetime ex)
  {
   ulong  ticket=m_order.Ticket();
   if(price==EMPTY_VALUE)
      return(m_trade.OrderDelete(ticket));
//--- modify the order, return the result
   return(m_trade.OrderModify(ticket,price,sl,tp,m_order.TypeTime(),ex));
  }

Standart sınıflar devralanların geliştirilmesi tamamlandı.


4. Fiyat Modüllerinin Geliştirilmesi

Hesaplanan seviyelerde talimatları ve Zararı Durdur işlemini veren Expert'ler oluşturmak için zaten temelimiz var. Kesin olmak gerekirse fiyat seviyeleri ile çalışmak için kullanıma hazır sınıflarımız mevcut. Artık sadece bu seviyeleri oluşturacak modüller yazılmaya bırakıldı.

Fiyat modülleri geliştirme süreci, alım satım sinyalleri modülleri yazmaya benzer. Aralarındaki tek fark, sinyal modüllerinde olduğu gibi LongCondition(), ShortCondition() veya Yön() değil, modül içindeki fiyat güncellemesinden sorumlu yöntem olan Fiyatlar() modülünün geçersiz kılınması gerektiğidir. İdeal olarak, okuyucunun sinyal modüllerinin gelişimi hakkında net bir fikri olmalıdır. "6 Adımda Kendi İşlem Robotunuzu Oluşturun!" ve "Özel Göstergeye Dayalı İşlem Sinyali Oluşturucu" makaleleri bu konuda faydalı olabilir.

Birkaç fiyat modülünün kodu, bu konuya bir örnek teşkil edecek.

4.1. "Delta ZigZag" Göstergesine Dayalı Fiyat Modülü

Delta ZigZag göstergesi, belirtilen sayıda en son tepe noktasına göre seviyeler çizer. Fiyat bu seviyeleri geçerse olası bir trend dönüşü anlamına gelir.

Fiyat modülünün amacı, gösterge tamponundan giriş seviyesini almak, Zararı Durdur'u vermek için en yakın yerel ekstremi bulmak, Zararı Durdur'u ayarlarda belirtilen katsayı ile çarparak Kar Al'ı hesaplamaktır.

Şek. 3. Örnek olarak satın alma talimatı kullanılarak Delta ZigZag göstergesinde fiyat modülü işleminin gösterimi

Şek. 3. Örnek olarak satın alma talimatı kullanılarak Delta ZigZag göstergesinde fiyat modülü işleminin gösterimi

Şek. 3. fiyat modülü tarafından üretilen seviyeleri temsil etmektedir. Talimat tetiklenmeden önce, Zarar Durdur ve Kar Al işlemleri, minimum güncellemelerini takiben buna göre değişir.

4.1.1. Modül Tanımlayıcı

// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=DeltaZZ Price Module                                       |
//| Type=SignalAdvanced                                              |
//| Name=DeltaZZ Price Module                                        |
//| ShortName=DeltaZZ_PM                                             |
//| Class=CPriceDeltaZZ                                              |
//| Page=not used                                                    |
//| Parameter=setAppPrice,int,1, Applied price: 0 - Close, 1 - H/L   |
//| Parameter=setRevMode,int,0, Reversal mode: 0 - Pips, 1 - Percent |
//| Parameter=setPips,int,300,Reverse in pips                        |
//| Parameter=setPercent,double,0.5,Reverse in percent               |
//| Parameter=setLevels,int,2,Peaks number                           |
//| Parameter=setTpRatio,double,1.6,TP:SL ratio                      |
//| Parameter=setExpBars,int,10,Expiration after bars number         |
//+------------------------------------------------------------------+
// wizard description end

Tanımlayıcıdaki ilk beş parametre, kullanımdaki göstergeyi ayarlamak için gereklidir. Ardından, mevcut fiyat modülünden talimatlar için çubuklardaki Zarar Durdur ve son kullanma süresine göre Kar Al hesaplama katsayısı gelir.

4.1.2. Sınıf Beyanı

class CPriceDeltaZZ : public CExpertSignalAdvanced
  {
protected:
   CiCustom          m_deltazz;           //object of the DeltaZZ indicator
   //--- module settings
   int               m_app_price;
   int               m_rev_mode;
   int               m_pips;
   double            m_percent;
   int               m_levels;
   double            m_tp_ratio;          //tp:sl ratio
   int               m_exp_bars;          //lifetime of the orders in bars
   //--- method of indicator initialization
   bool              InitDeltaZZ(CIndicators *indicators);
   //--- helper methods
   datetime          calcExpiration() { return(TimeCurrent()+m_exp_bars*PeriodSeconds(m_period)); }
   double            getBuySL();          //function for searching latest minimum of ZZ for buy SL
   double            getSellSL();         //function for searching latest maximum of ZZ for sell SL
public:
                     CPriceDeltaZZ();
                    ~CPriceDeltaZZ();
   //--- methods of changing module settings
   void              setAppPrice(int ap)           { m_app_price=ap; }
   void              setRevMode(int rm)            { m_rev_mode=rm;  }
   void              setPips(int pips)             { m_pips=pips;    }
   void              setPercent(double perc)       { m_percent=perc; }
   void              setLevels(int rnum)           { m_levels=rnum;  }
   void              setTpRatio(double tpr)        { m_tp_ratio=tpr; }
   void              setExpBars(int bars)          { m_exp_bars=bars;}
   //--- method of checking correctness of settings
   virtual bool      ValidationSettings(void);
   //--- method of creating indicators
   virtual bool      InitIndicators(CIndicators *indicators);
   //--- main method of price module updating the output data
   virtual double    Prices();
  }; 

Korumalı veri - CiCustom türünün göstergesinin nesnesi ve tanımlayıcıda belirtilen türlere göre parametreler modülde bildirilir.

4.1.3. Kurucu

Kurucu, sınıf parametrelerini varsayılan değerlerle başlatır. Daha sonra, Expert'in giriş parametrelerine göre modül ana sinyale dahil edildiğinde bu değerler bir kez daha başlatılır.

CPriceDeltaZZ::CPriceDeltaZZ() : m_app_price(1),
                                 m_rev_mode(0),
                                 m_pips(300),
                                 m_percent(0.5),
                                 m_levels(2),
                                 m_tp_ratio(1),
                                 m_exp_bars(10)
  {
  }

4.1.4. ValidationSettings()

ValidationSettings(), giriş parametrelerini kontrol etmek için önemli bir yöntemdir. Modül parametrelerinin değerleri geçersizse sonuç false döndürülür ve günlükte bir hata mesajı yazdırılır.

bool CPriceDeltaZZ::ValidationSettings(void)
  {
//--- checking for settings of additional filters
   if(!CExpertSignal::ValidationSettings())
      return(false);
//--- initial data check
   if(m_app_price<0 || m_app_price>1)
     {
      printf(__FUNCTION__+": Applied price must be 0 or 1");
      return(false);
     }
   if(m_rev_mode<0 || m_rev_mode>1)
     {
      printf(__FUNCTION__+": Reversal mode must be 0 or 1");
      return(false);
     }
   if(m_pips<10)
     {
      printf(__FUNCTION__+": Number of pips in a ray must be at least 10");
      return(false);
     }
   if(m_percent<=0)
     {
      printf(__FUNCTION__+": Percent must be greater than 0");
      return(false);
     }
   if(m_levels<1)
     {
      printf(__FUNCTION__+": Ray Number must be at least 1");
      return(false);
     }
   if(m_tp_ratio<=0)
     {
      printf(__FUNCTION__+": TP Ratio must be greater than zero");
      return(false);
     }
   if(m_exp_bars<0)
     {
      printf(__FUNCTION__+": Expiration must be zero or positive value");
      return(false);
     }
//--- parameter check passed
   return(true);
  } 

4.1.5. InitIndicators(...)

InitIndicators(...) yöntemi, temel sınıfın adsız bir yöntemini çağırır ve geçerli modülün göstergesini InitDeltaZZ(...) yöntemiyle başlatır.

bool CPriceDeltaZZ::InitIndicators(CIndicators *indicators)
  {
//--- initialization of indicator filters
   if(!CExpertSignal::InitIndicators(indicators))
      return(false);
//--- creating and initializing of custom indicator
   if(!InitDeltaZZ(indicators))
      return(false);
//--- success
   return(true);
  }

4.1.6. InitDeltaZZ(...)

InitDeltaZZ(...) yöntemi, özel gösterge nesnesini koleksiyona ekler ve yeni gösterge "Delta ZigZag" oluşturur.

bool CPriceDeltaZZ::InitDeltaZZ(CIndicators *indicators)
  {
//--- adds to collection
   if(!indicators.Add(GetPointer(m_deltazz)))
     {
      printf(__FUNCTION__+": error adding object");
      return(false);
     }
//--- specifies indicator parameters
   MqlParam parameters[6];
//---
   parameters[0].type=TYPE_STRING;
   parameters[0].string_value="deltazigzag.ex5";
   parameters[1].type=TYPE_INT;
   parameters[1].integer_value=m_app_price;
   parameters[2].type=TYPE_INT;
   parameters[2].integer_value=m_rev_mode;
   parameters[3].type=TYPE_INT;
   parameters[3].integer_value=m_pips;
   parameters[4].type=TYPE_DOUBLE;
   parameters[4].double_value=m_percent;
   parameters[5].type=TYPE_INT;
   parameters[5].integer_value=m_levels;
//--- object initialization
   if(!m_deltazz.Create(m_symbol.Name(),m_period,IND_CUSTOM,6,parameters))
     {
      printf(__FUNCTION__+": error initializing object");
      return(false);
     }
//--- number of the indicator buffers
   if(!m_deltazz.NumBuffers(5)) return(false);
//--- ок
   return(true);
  }

ValidationSettings(), InitDeltaZZ(...) ve InitIndicators(...) yöntemlerinin başarıyla tamamlanmasından sonra modül başlatılır ve kullanıma hazırdır.

4.1.7. Fiyatlar()

Bu yöntem, fiyat modülü için temeldir. Burası, talimat parametrelerinin güncellendiği yerdir. Değerleri ana sinyale iletilir. Bu yöntem, çift türünün işlem sonucunu döndürür. Bu, esas olarak gelecekteki gelişme için uygulandı. Prices() yönteminin sonucu, ana sinyalin uygun şekilde işleyebilmesi için bazı özel durumları ve olayları kodlayabilir. Şu anda yalnızca döndürülen EMPTY_VALUE değerinin işlenmesi amaçlanmaktadır. Bu sonucu aldıktan sonra, ana sinyal modül tarafından önerilen parametreleri görmezden gelecektir.

Bu modüldeki Prices() yönteminin çalışma algoritması:

  1. Sırasıyla alım ve satım için gösterge arabellekleri 3 ve 4'ten talimatların açılış fiyatlarını alın;
  2. Talimatların son parametrelerini sıfırlayın;
  3. Satın almak için fiyatı kontrol edin. Varsa GetBuySL() yöntemi ile Zararı Durdur seviyesini belirleyin, Zararı Durdur değeri ve açılış fiyatından Kar Al seviyesini hesaplayın ve talimatın sona erme süresini hesaplayın;
  4. Satmak için fiyatı kontrol edin. Tespit edilirse getSellSL() yöntemi ile Zararı Durdur seviyesini bulun, Zarar Durdur değeri ve açılış fiyatına göre Kar Al seviyesini hesaplayın ve talimatın sona erme süresini hesaplayın;
  5. Çıkış yapın.
"Delta ZigZag" göstergesinin bazı operasyonel yönleri nedeniyle alım ve satım fiyatlarının varlığı, koşulları birbirini dışlar. Arabellek 3 ve 4, varsayılan olarak noktalar olarak çizilir (bkz. Şek. 3).

double CPriceDeltaZZ::Prices(void)
  {
   double openbuy =m_deltazz.GetData(3,0);//receive the last value from buffer 3
   double opensell=m_deltazz.GetData(4,0);//receive the last value from buffer 4
//--- clear parameter values
   m_order_open_long=EMPTY_VALUE;
   m_order_stop_long=EMPTY_VALUE;
   m_order_take_long=EMPTY_VALUE;
   m_order_expiration_long=0;
   m_order_open_short=EMPTY_VALUE;
   m_order_stop_short=EMPTY_VALUE;
   m_order_take_short=EMPTY_VALUE;
   m_order_expiration_short=0;
   int digits=m_symbol.Digits();
//--- check for the prices to buy
   if(openbuy>0)//if buffer 3 is not empty
     {
      m_order_open_long=NormalizeDouble(openbuy,digits);
      m_order_stop_long=NormalizeDouble(getBuySL(),digits);
      m_order_take_long=NormalizeDouble(m_order_open_long + m_tp_ratio*(m_order_open_long - m_order_stop_long),digits);
      m_order_expiration_long=calcExpiration();
     }
//--- check for the prices to sell
   if(opensell>0)//if buffer 4 is not empty
     {
      m_order_open_short=NormalizeDouble(opensell,digits);
      m_order_stop_short=NormalizeDouble(getSellSL(),digits);
      m_order_take_short=NormalizeDouble(m_order_open_short - m_tp_ratio*(m_order_stop_short - m_order_open_short),digits);
      m_order_expiration_short=calcExpiration();
     }
   return(0);
  }

4.1.8. getBuySL() ve getSellSL()

getBuySL() ve getSellSL() yöntemleri, Zararı Durdur'u yerleştirmek için ilgili yerel minimumları ve maksimumları arar. İlgili bir arabellekte  son sıfır olmayan değer, her yöntemde son yerel ekstremin fiyat düzeyi aranır.

double CPriceDeltaZZ::getBuySL(void)
  {
   int i=0;
   double sl=0.0;
   while(sl==0.0)
     {
      sl=m_deltazz.GetData(0,i);
      i++;
     }
   return(sl);
  }
double CPriceDeltaZZ::getSellSL(void)
  {
   int i=0;
   double sl=0.0;
   while(sl==0.0)
     {
      sl=m_deltazz.GetData(1,i);
      i++;
     }
   return(sl);
  }

4.2. İç Çubuğa Dayalı Fiyat Modülü

İç çubuk, Fiyat işlemi olarak adlandırılan hiçbir gösterge içermeyen alım satımda yaygın olarak kullanılan formasyonlar veya kalıplardan biridir. Bir iç çubuk, önceki çubuğun uç noktaları içinde Yüksek ve Düşük olan bir çubuktur. Bir iç çubuk, konsolidasyonun başladığını veya fiyat hareketinin tersine çevrilme olasılığını gösterir.

Şekil 4'te iç çubuklar kırmızı elipslerin içindedir. Bir iç çubuk tespit edildiğinde, fiyat modülü, iç çubuğun önündeki çubuğun uç noktasında buystop ve sellstop talimatlarının açılış fiyatlarını üretir.

Açılış fiyatları, karşıt talimatlar için Zarar Durdur seviyeleridir. Kar Al, yukarıda tartışılan modüldekiyle aynı şekilde hesaplanır - Zarar Durdurma seviyesi ayarlarında belirtilen katsayı ile çarpılarak. Açılış fiyatları ve Zarar Durdurma kırmızı yatay çizgilerle, Kar Al yeşil olanlarla işaretlenmiştir.

Şek. 4. Fiyat modülünün iç çubuklarının ve seviyelerinin gösterimi

Şek. 4. Fiyat modülünün iç çubuklarının ve seviyelerinin gösterimi

Şek. 4'te, trend yaklaştığı için satılacak talimatlar verilmemektedir. Bununla birlikte, fiyat modülü her iki yönde de giriş seviyeleri oluşturur. Bazı Kar Al seviyeleri planın dışındadır.

Önceki modülden farklı olarak, bu modülün algoritması basittir ve göstergelerin başlatılmasını gerektirmez. Modülde çok az kod vardır; bu, aşağıda tam olarak sunulmuştur. Yine de her işlevi ayrı ayrı analiz etmeyeceğiz.

#include <Expert\ExpertSignalAdvanced.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=Inside Bar Price Module                                    |
//| Type=SignalAdvanced                                              |
//| Name=Inside Bar Price Module                                     |
//| ShortName=IB_PM                                                  |
//| Class=CPriceInsideBar                                            |
//| Page=not used                                                    |
//| Parameter=setTpRatio,double,2,TP:SL ratio                        |
//| Parameter=setExpBars,int,10,Expiration after bars number         |
//| Parameter=setOrderOffset,int,5,Offset for open and stop loss     |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CPriceInsideBar                                            |
//| Purpose: Class of the generator of price levels for orders based |
//|          on the "inside bar" pattern.                            |
//| Is derived from the CExpertSignalAdvanced class.                 |
//+------------------------------------------------------------------+
class CPriceInsideBar : public CExpertSignalAdvanced
  {
protected:
   double            m_tp_ratio;          //tp:sl ratio
   int               m_exp_bars;          //lifetime of the orders in bars
   double            m_order_offset;      //shift of the opening and Stop Loss levels
   datetime          calcExpiration()  { return(TimeCurrent()+m_exp_bars*PeriodSeconds(m_period)); }
public:
                     CPriceInsideBar();
                    ~CPriceInsideBar();
   void              setTpRatio(double ratio){ m_tp_ratio=ratio; }
   void              setExpBars(int bars)    { m_exp_bars=bars;}
   void              setOrderOffset(int pips){ m_order_offset=m_symbol.Point()*pips;}
   bool              ValidationSettings();
   double            Prices();
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CPriceInsideBar::CPriceInsideBar()
  {
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CPriceInsideBar::~CPriceInsideBar()
  {
  }
//+------------------------------------------------------------------+
//| Validation of protected settings                                 |
//+------------------------------------------------------------------+
bool CPriceInsideBar::ValidationSettings(void)
  {
//--- verification of the filter parameters
   if(!CExpertSignal::ValidationSettings())
      return(false);
//--- initial data check
  if(m_tp_ratio<=0)
     {
      printf(__FUNCTION__+": TP Ratio must be greater than zero");
      return(false);
     }
   if(m_exp_bars<0)
     {
      printf(__FUNCTION__+": Expiration must be zero or positive value");
      return(false);
     }
//--- check passed
   return(true);
  }
//+------------------------------------------------------------------+
//| Price levels refreshing                                          |
//+------------------------------------------------------------------+
double CPriceInsideBar::Prices(void)
  {
   double h[2],l[2];
   if(CopyHigh(m_symbol.Name(),m_period,1,2,h)!=2 || CopyLow(m_symbol.Name(),m_period,1,2,l)!=2)
      return(EMPTY_VALUE);
//--- check for inside bar      
   if(h[0] >= h[1] && l[0] <= l[1])
     {
      m_order_open_long=h[0]+m_order_offset;
      m_order_stop_long=l[0]-m_order_offset;
      m_order_take_long=m_order_open_long+(m_order_open_long-m_order_stop_long)*m_tp_ratio;
      m_order_expiration_long=calcExpiration();
      
      m_order_open_short=m_order_stop_long;
      m_order_stop_short=m_order_open_long;
      m_order_take_short=m_order_open_short-(m_order_stop_short-m_order_open_short)*m_tp_ratio;
      m_order_expiration_short=m_order_expiration_long;
      return(0);
     }
   return(EMPTY_VALUE);
  }  
//+------------------------------------------------------------------+

Bu modülün Prices() yönteminde, EMPTY_VALUE sonucunun dönüşü, ana sinyale uygun fiyat seviyelerinin olmadığını göstermek için kullanılır.

4.3. Dış Çubuğa Dayalı Fiyat Modülü

Dış çubuk, "emilim" olarak da adlandırılan bir başka popüler Fiyat Hareketi formasyonudur. Dış çubuğun Yüksek ve Düşük değeri bir önceki çubuğun Yüksek ve Düşük değeri ile üst üste binmesi nedeniyle çağrılır. Bir dış çubuğun ortaya çıkması, volatilite artışının ardından yönlendirilmiş bir fiyat hareketinin bir göstergesidir.

Şek. 5'te dış çubuklar kırmızı elipslerle işaretlenmiştir. Fiyat modülü, bir dış çubuğu tespit ettikten sonra, uç noktasında buystop ve sellstop talimatlarının açılış fiyatlarını üretir.

Açılış fiyatları, karşıt talimatlar için Zarar Durdur seviyeleridir. Kar Al, yukarıda tartışılan modüldekiyle aynı şekilde hesaplanır - Zarar Durdurma seviyesi ayarlarında belirtilen katsayı ile çarpılarak. Açılış fiyatları ve Zarar Durdurma kırmızı yatay çizgilerle, Kar Al yeşil olanlarla işaretlenmiştir.

Şek. 5. Dış çubukların ve fiyat modülü seviyelerinin gösterimi

Şek. 5. Dış çubukların ve fiyat modülü seviyelerinin gösterimi

Şekil 5'te dış çubuklar kırmızı elipslerle işaretlenmiştir. Yatay çizgiler, fiyat modülü tarafından oluşturulan bekleyen talimatların açılış fiyatlarını yansıtır.

Bu durumda düşüş trendi olduğu için sadece satış talimatları açılır. Bu modülün çalışması temelde bir öncekine benzer. Kodu arasındaki tek fark, yalnızca Prices() yöntemidir, diğer parçalar tamamen aynıdır ve aynı adlara sahiptir. Aşağıda Prices() kodu yer almaktadır.

double CPriceOutsideBar::Prices(void)
{
   double h[2],l[2];
   if(CopyHigh(m_symbol.Name(),m_period,1,2,h)!=2 || CopyLow(m_symbol.Name(),m_period,1,2,l)!=2)
      return(EMPTY_VALUE);
//--- check of outside bar
   if(h[0] <= h[1] && l[0] >= l[1])
   {
      m_order_open_long=h[1]+m_order_offset;
      m_order_stop_long=l[1]-m_order_offset;
      m_order_take_long=m_order_open_long+(m_order_open_long-m_order_stop_long)*m_tp_ratio;
      m_order_expiration_long=calcExpiration();
      
      m_order_open_short=m_order_stop_long;
      m_order_stop_short=m_order_open_long;
      m_order_take_short=m_order_open_short-(m_order_stop_short-m_order_open_short)*m_tp_ratio;
      m_order_expiration_short=m_order_expiration_long;
      return(0);
   }
   return(EMPTY_VALUE);
} 

4.4. Modül Performans Testi

Bir sonraki bölümde, tek bir Expert'te bireysel ve birleşik çalışmalarını kontrol etmek ve sistemin tasarlandığı gibi çalıştığından emin olmak için üç modül örneği test edilir. Sonuç olarak, dört Expert oluşturulur. H12 zaman dilimi üzerinde çalışan Awesome Oscillator göstergesine dayalı alım satım sinyali modülü, oluşturulan Expert'lerin her birinde bir filtre olarak kullanılır. Fiyat modülleri H6 üzerinde çalışıyor.

Para yönetimi: sabit lot ve Takip Eden Durdur işlemi kullanılmaz. Tüm testler, 2013.01.01'den 2014.06.01'e kadar olan süre için MetaQuotes-Demo sunucusunun demo hesabından EURUSD kotasyonları üzerinde gerçekleştirilir. Terminal sürümü: 5.00, yapı 965 (27 Haziran 2014).

Kısa tutmak için, test sonuçları yalnızca denge grafikleriyle temsil edilir. Her özel durumda Expert'in davranışını elde etmek için yeterlidir.

4.4.1. Modülü Delta ZigZag Göstergesine Dayalı Test Etme

Şek. 6. Delta ZigZag'a dayalı fiyat modülünün test edilmesinde bakiye taslağı

Şek. 6. "Delta ZigZag" göstergesine dayalı fiyat modülünün test edilmesinde bakiye taslağı

4.4.2. Modülü "İç Çubuk" Formasyonuna Dayalı Test Etme

Şek. 7. İç çubuğa dayalı fiyat modülünün test edilmesinde bakiye taslağı

Şek. 7. İç çubuğa dayalı fiyat modülünün test edilmesinde bakiye taslağı

Şekil 7'ye bakıldığında, bu aşamadaki testlerin amacının kazanan bir strateji elde etmek değil, kod performansını kontrol etmek olduğu unutulmamalıdır.

4.4.3. Modülü "Dış Çubuk" Formasyonuna Dayalı Test Etme

Şek. 8. Dış çubuğa dayalı fiyat modülünün test edilmesinde bakiye taslağı

Şek. 8. Dış çubuğa dayalı fiyat modülünün test edilmesinde bakiye taslağı

4.4.4. Geliştirilmiş Fiyat Modüllerinin Ortak Çalışmasının Test Edilmesi

Önceki test sonuçları dikkate alındığında, DeltaZigZag tabanlı fiyat modülleri, iç çubuk ve dış çubuk sırasıyla 1, 0,5 ve 0,7 ağırlık katsayıları aldı. Ağırlık katsayıları, fiyat modüllerinin önceliklerini tanımlar.

Şek. 9. Üç fiyat modülüne sahip Expert'in test edilmesinde bakiye taslağı

Şek. 9. Üç fiyat modülüne sahip Expert'in test edilmesinde bakiye taslağı

Testin her aşamasında, fiyat taslakları üzerinde gerçekleştirilen tüm işlemler dikkatlice analiz edildi. Strateji hataları ve sapmaları ortaya çıkmadı. Önerilen tüm programlar bu makaleye eklenmiştir ve bunları kendiniz test edebilirsiniz.


5. Kullanım Talimatı

Üç fiyat modülü ve bir filtre olarak Awesome Oscillator ile Expert örneğinde geliştirilen uzantıyı kullanarak Expert geliştirmenin aşamalarını ele alacağız.

Üretim başlamadan önce, "CExpertAdvanced.mqh" ve "CExpertSignalAdvanced.mqh" başlık dosyalarının MetaTrader 5 terminalinin kataloğunda MQL5/Include/Expert klasöründe ve fiyat modüllerinin dosyalarının MQL5/Include/Expert/MySignal klasöründe olduğundan emin olun. Expert'i başlatmadan önce, derlenmiş göstergelerin MQL5/Indicators klasöründe olduğundan emin olun. Bu durumda "DeltaZigZag.ex5" dosyasıdır. Ekli arşivde tüm dosyalar yerlerindedir. Tek yapmanız gereken bu arşivi MetaTrader 5 terminali ile bir klasöre açmak ve birleştirme kataloglarını onaylamaktır.

5.1. Expert Oluşturma

Expert oluşturmayı başlatmak için MetaEditor'da "Dosya"->"Yeni" öğesini seçin.

Şek. 10. MQL5 Sihirbazını kullanarak yeni bir Expert oluşturma

Şek. 10. MQL5 Sihirbazını kullanarak yeni bir Expert oluşturma

Yeni pencerede «Expert Advisor (oluştur)" seçeneğini belirleyin ve ardından "İleri" öğesine basın.


Şek. 11. MQL5 Sihirbazını Kullanarak Bir Expert Oluşturma

Şek. 11. MQL5 Sihirbazını Kullanarak Bir Uzman Oluşturma

Adı belirtebileceğiniz bir pencere açılacaktır. Bu özel örnekte, Expert'in adı "TEST_EA_AO_DZZ_IB_OB" şeklindedir, Symbol ve TimeFrame parametrelerinin varsayılan değerleri vardır. Ardından "İleri" öğesine tıklayın.

Şek. 12. Expert Advisor'ın ortak parametreleri


Şek. 12. Expert Advisor'ın genel özellikleri

Açılan pencerede "Ekle" tuşuna basarak modülleri tek tek ekleyin. Tüm süreç aşağıda sunulmuştur.

LÜTFEN UNUTMAYIN! Modülleri eklerken, önce tüm sinyal modüllerini (devralanlar CExpertSignal) ve ardından fiyat modüllerini (devralanlar CExpertSignalAdvanced) dahil edin. Bu modülleri dahil etme talimatını bozmanın sonucu tahmin edilemez olacaktır.

Bu nedenle, Awesome Oscillator'dan gelen sinyal modüllerini dahil ederek başlıyoruz. Bu örnekteki tek filtredir.

Şek. 13. Awesome Oscillator'den gelen sinyal modülünü içerir

Şek. 13. Awesome Oscillator'den gelen sinyal modülünü içerir

Tüm sinyal modülleri dahil edildikten sonra gerekli fiyat modüllerini rastgele bir sırayla dahil edin. Bu örnekte bunlardan üç tane mevcut.

Şek. 14. DeltaZZ Fiyat Modülünden gelen sinyal modülünü içerir

Şek. 14. DeltaZZ Fiyat Modülünden gelen sinyal modülünü içerir


Şek. 15. İç Çubuk Fiyat Modülünden gelen sinyal modülünü içerir

Şek. 15. İç Çubuk Fiyat Modülünden gelen sinyal modülünü içerir


Şek. 16. Dış Çubuk Fiyat Modülünden gelen sinyal modülünü içerir

Şek. 16. Dış Çubuk Fiyat Modülünden gelen sinyal modülünü içerir

Tüm modüller eklendikten sonra pencere aşağıdaki gibi görünecektir:

Şek. 17. Dahil edilen alım satım sinyalleri modüllerinin listesi

Şek. 17. Dahil edilen alım satım sinyalleri modüllerinin listesi

Fiyat modülünün "Ağırlık" parametresinin değeri önceliğini tanımlar.

"İleri" düğmesine basıldıktan sonra Sihirbaz, para yönetimi modüllerini ve İzleyen Durdurma modüllerini seçmenizi önerir. Bunlardan birini seçin veya "İleri" veya "Hazır" düğmesine basarak olduğu gibi bırakın.

"Hazır" düğmesine basıldığında, oluşturulan Advisor kodunu alacağız.

5.2. Oluşturulan Kodu Düzenleme

Böylece, kodumuzu elde ettik.

1. En başta dizeyi bulun ve

#include <Expert\Expert.mqh>

şöyle görünecek şekilde düzenleyin

#include <Expert\ExpertAdvanced.mqh>

Geliştirilen sınıfların dosyalarının eklenmesi gerekir.

2. Sonra dizeyi bulun

CExpert ExtExpert;

ve değiştirin

CExpertAdvanced ExtExpert;

Bu, gerekli işlevlere sahip alt öğe için Expert standart sınıfını değiştirecektir.

3. Şimdi dizeyi bulun

CExpertSignal *signal=new CExpertSignal;

ve değiştirin

CExpertSignalAdvanced *signal=new CExpertSignalAdvanced;

Bu, gerekli işlevlerle alt öğeden gelen ana sinyalin standart sınıfını değiştirmenin yoludur.

4. Ana sinyalin m_filters dizisine ilk fiyat modülünün eklenmesini uygulayan dizeyi bulun. Bu örnekte şöyle görünür:

signal.AddFilter(filter1);

Bundan önce dizeyi ekliyoruz

signal.CalcPriceModuleIndex();

Bu, ana sinyalin m_filters dizisinde hangi indekse kadar sinyal modülü işaretçileri olduğunu ve hangi fiyat modülü işaretçilerinin bulunduğunu tanıması için gereklidir.

Belirtilen dizeyi eklemek için doğru konumu bulmak zor olabilir. Referans noktası olarak "filtre" kelimesinden sonraki sayıyı kullanın. Aramayı basitleştirecek ve doğru pozisyonu kaçırmamayı sağlayacaktır. MQL5 Sihirbazı, modülleri otomatik olarak talimatlarına dahil etti. İlk modül filter0, ikincisi filter1, üçüncüsü – filter2 vb. olarak çağrılır. Bizim durumumuzda sadece bir sinyal modülü mevcut. Bu nedenle, ilk dahil edilen fiyat modülü iki numaradır ve kodda numaralandırma sıfır ile başladığı için filtreyi eklemek üzere "signal.AddFilter(filter1);" dizesini aramamız gerekir. Resim, Şek. 18'dedir:

Şek. 18. Dahil edilme talimatına göre koddaki modül adları

Şek. 18. Dahil edilme talimatına göre koddaki modül adları

5. Bu kısım zorunlu değildir. Yapılan değişikliklerle açılış fiyatı girintileri, Zararı Durdur, Kar Al ve talimat sona erme süresinden sorumlu Expert parametreleri, kullanımlarını kaybetti. Kodu daha kompakt hale getirmek için aşağıdaki dizeleri silebilirsiniz:

input double Signal_PriceLevel            =0.0;                    // Price level to execute a deal
input double Signal_StopLevel             =50.0;                   // Stop Loss level (in points)
input double Signal_TakeLevel             =50.0;                   // Take Profit level (in points)
input int    Signal_Expiration            =4;                      // Expiration of pending orders (in bars)

Yukarıdaki dizeleri sildikten sonra karşılaşılan derleme hatası, bizi silinecek bir sonraki dize grubuna götürür:

   signal.PriceLevel(Signal_PriceLevel);
   signal.StopLevel(Signal_StopLevel);
   signal.TakeLevel(Signal_TakeLevel);
   signal.Expiration(Signal_Expiration);

İkincisi silindikten sonra derleme başarılı olacaktır.

Düzenlemeye ilişkin yorumlar ve açıklamalar, "TEST_EA_AO_DZZ_IB_OB" Expert'inin ekteki kodunda bulunabilir. Silinebilecek kodun dizeleri, eşlik eden yorumlara sahiptir.


Sonuç

Bu yazıda MQL5 Sihirbazının uygulama alanını önemli ölçüde genişlettik. Artık mevcut fiyattan bağımsız olarak farklı fiyat seviyelerinde talimat, Zararı Durdur ve Kar Al gerektiren otomatik alım satım sistemlerinin geliştirme optimizasyonu için kullanılabilir.

Oluşturulan Expert'ler, gönderilen talimatların parametrelerini hesaplayan bir dizi fiyat modülü içerebilir. Mevcut olanlardan en uygun parametre seti seçilir. Tercihler ayarlarda belirtilmiştir. Birçok farklı giriş noktasının maksimum verimle kullanılmasına olanak sağlar. Bu yaklaşım, Expert'leri seçici kılar. Yön biliniyorsa ancak giriş noktası tanımlanmamışsa Expert bunun görünmesini bekleyecektir.

Fiyat seviyelerinin araştırılmasından sorumlu standart uyumlu modüllerin tanıtılması önemli bir avantajdır ve Expert'lerin gelişimini basitleştirmeyi amaçlamaktadır. Şu anda sadece üç modül olmasına rağmen, gelecekte sayıları şüphesiz artacaktır. Bu makaleyi faydalı bulduysanız lütfen yorumlarda fiyat modüllerinin çalışmasının algoritmalarını önerin. İlginç fikirler kodda uygulanacaktır.

Bu makale ayrıca, Sihirbazda geliştirilen Expert yeteneklerinin daha da genişletilmesi için bir yöntem sunar. Devralma, değişiklikleri başlatmanın en uygun yoludur.

Programlama becerisine sahip olmayan ancak talimatları izleyerek kodu düzenleyebilen kullanıcılar, mevcut modellere dayalı olarak daha gelişmiş Expert'ler oluşturma fırsatına sahip olur.

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

Sanal Barındırmaya Geçiş için Alım Satım Hesabı Nasıl Hazırlanır? Sanal Barındırmaya Geçiş için Alım Satım Hesabı Nasıl Hazırlanır?
MetaTrader istemci terminali, alım satım stratejilerini otomatikleştirmek için mükemmeldir. Alım satım robotu geliştiricileri için gerekli tüm araçlara sahiptir: güçlü C++ tabanlı MQL4/MQL5 programlama dili, kullanışlı MetaEditor geliştirme ortamı ve MQL5 Cloud Network'te dağıtılmış hesaplamayı destekleyen çok kanallı strateji test cihazı. Bu makalede, istemci terminalinizi tüm özel öğelerle birlikte sanal ortama nasıl taşıyacağınızı öğreneceksiniz.
MQL5'ten (MQL4) MySQL Veritabanına Nasıl Erişilir MQL5'ten (MQL4) MySQL Veritabanına Nasıl Erişilir
Makale, MQL ve MySQL veritabanı arasında bir arayüzün geliştirilmesini açıklar. Mevcut pratik çözümleri tartışır ve veritabanlarıyla çalışmak için bir kitaplık uygulamanın daha uygun bir yolunu sunar. Makale, MySQL ile çalışmanın işlevleri, arayüz yapısı, örnekleri ve bazı belirli özelliklerinin ayrıntılı bir açıklamasını içerir. Yazılım çözümlerine gelince, makale ekleri, MQL4 ve MQL5 dilleri için dinamik kitaplıkların dosyalarını, dokümantasyonu ve script dosyası örneklerini içerir.
Piyasada Etkili Bir Ürün Sunumu İçin İpuçları Piyasada Etkili Bir Ürün Sunumu İçin İpuçları
Programları yatırımcılara etkili bir şekilde satmak, yalnızca verimli ve kullanışlı bir ürün yazıp ardından piyasada yayınlamayı gerektirmez. Kapsamlı, ayrıntılı bir açıklama ve iyi çizimler sağlamak çok önemlidir. Kaliteli bir logo ve doğru ekran görüntüleri "gerçek kodlama" kadar önemlidir. Basit bir formülü aklınızda bulundurun: İndirme yok = satış yok.
Bir Sosyal Teknoloji Girişimi Kurmak, Bölüm I: MetaTrader 5 Sinyallerinizi Tweetleyin Bir Sosyal Teknoloji Girişimi Kurmak, Bölüm I: MetaTrader 5 Sinyallerinizi Tweetleyin
Bugün, EA'larınızın alım satım sinyallerini tweetleyebilmeniz için bir MetaTrader 5 terminalini Twitter ile nasıl bağlayacağınızı öğreneceğiz. PHP'de RESTful web servisine dayalı bir Sosyal Karar Destek Sistemi geliştiriyoruz. Bu fikir, bilgisayar destekli alım satım adı verilen belirli bir otomatik alım satım anlayışından gelmektedir. İnsan yatırımcılarının bilişsel yeteneklerinin, aksi takdirde Expert Advisor'lar tarafından otomatik olarak piyasaya sürülecek olan alım satım sinyallerini filtrelemesini istiyoruz.