English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
MQL5 Tarif Defteri: Uzman Danışmanlarda Alım Satım Koşullarını Belirlemek için Göstergeleri Kullanma

MQL5 Tarif Defteri: Uzman Danışmanlarda Alım Satım Koşullarını Belirlemek için Göstergeleri Kullanma

MetaTrader 5Örnekler | 13 Ocak 2022, 09:34
75 0
Anatoli Kazharski
Anatoli Kazharski

Giriş

Bu makalede, Uzman Danışman göstergeler ile güçlendirilecektir, bu göstergelerin değerleri pozisyon açma koşullarını kontrol etmek için kullanılacaktır. Renk katmak için, üç alım satım göstergesinden birini seçebilmek için harici parametrelerde bir açılır liste oluşturacağız.

Unutursanız diye bir hatırlatma: MQL5 Tarif Defteri serisinin önceki makalelerinde üzerinde çalıştığımız Uzman Danışmanı değiştirmeye devam edeceğiz. Uzman Danışmanın son sürümü, "MQL5 Tarif Defteri: Pozisyon Özelliklerini Elde Etmek için İşlemler Geçmişi ve Fonksiyon Kitaplığı" adı makaleden indirilebilir.

Ayrıca bu makalede, alım satım işlemlerinin yapılıp yapılamayacağını kontrol etmek için oluşturacağımız bir fonksiyon da yer alacaktır. Pozisyon açma fonksiyonu, Uzman Danışmanın alım satım modunu belirlemesini sağlayacak şekilde değiştirilecektir (Anında Yürütme ve Piyasa Yürütmesi).

Uzman Danışman kodu, önceki makalelerde yapılan tüm geliştirmeler ve iyileştirmeleri takiben zaten 1.500 satırı aştığından, eklenen her yeni özellik ile daha az kullanışlı hale gelecektir. Bu yüzden mantıklı bir çözüm, bunu ayrı kitaplık dosyaları olarak birkaç kategoriye bölmektir. Artık hedefler belirlendiğine göre hadi başlayalım.

 

Uzman Danışman Geliştirme

Bir önceki makaledeki Uzman Danışman (*.mq5) kaynak kodunu ayrı bir klasör olan TestIndicatorConditions içine yerleştiriyoruz, burada Include alt klasörünü oluşturmamız gerekiyor. Bu, içerik dosyaları (*.mqh) oluşturacağımız klasördür. Bunlar, MQL5 Sihirbazını (Ctrl+N) kullanılarak oluşturulabilir veya standart metin dosyaları (*.txt) olarak gerekli dizinde manuel olarak oluşturarak daha sonra *.mqh olarak yeniden adlandırılabilir.

Aşağıda, oluşturulan tüm içerik dosyalarının adları ve yorumları yer almaktadır:

  • Enums.mqh tüm numaralandırmaları içerecektir;
  • InfoPanel.mqh bilgi panelinin ayarlanması, grafik nesnelerin oluşturulması ve silinmesi için özellikleri içerecektir;
  • Errors.mqh hata kodları ve sonlandırma sebeplerini döndüren tüm fonksiyonları içerecektir;
  • TradeSignals.mqh, dizileri fiyatlar ve gösterge değerleriyle ve ayrıca sinyal bloğuyla dolduran fonksiyonları içerecektir;
  • Tradefonksiyonus.mqh alım satım fonksiyonlarını içerecektir;
  • ToString.mqh sayısal değerleri dize değerlerine dönüştüren fonksiyonları içerecektir;
  • Auxiliary.mqh diğer yardımcı fonksiyonlar için kullanılacaktır.

Bu kitaplıkları ana dosyaya dahil etmek için #include direktifini kullanırız. Uzman Danışmanın ana dosyası ve içerik dosya klasörü (Include) aynı klasörde bulunduğundan, dosya ekleme kodu aşağıdaki gibi olacaktır:

//--- Include custom libraries
#include "Include\Enums.mqh"
#include "Include\InfoPanel.mqh"
#include "Include\Errors.mqh"
#include "Include\TradeSignals.mqh"
#include "Include\TradeFunctions.mqh"
#include "Include\ToString.mqh"
#include "Include\Auxiliary.mqh"

Ardından, bunları açıp değiştirebileceğiz ve Uzman Danışmanın ana dosyasından kaynak kodun bir kısmını taşıyabileceğiz.

Kodda doğru şekilde gezinmek için, bitişik başlık dosyalarına eklenecektir ve Uzman Danışmanın ana dosyasına yapılan referanslar her başlık dosyasına eklenecektir. Örneğin, alım satım fonksiyonları kitaplığımız TradeFunctions.mqh için şu şekilde görünecektir:

//--- Connection with the main file of the Expert Advisor
#include "..\TestIndicatorConditions.mq5"
//--- Include custom libraries
#include "Enums.mqh"
#include "InfoPanel.mqh"
#include "Errors.mqh"
#include "TradeSignals.mqh"
#include "ToString.mqh"
#include "Auxiliary.mqh"

Aynı yerleşim düzeyindeki dosyalar için sadece adı belirtmek yeterlidir. Bir seviye yukarı çıkmak için, yoldaki ters eğik çizgiden önce iki adet nokta koymanız gerekir.

Enums.mqh dosyasındaki göstergeler için numaralandırma ekleyelim. Örnekleme amacıyla, bu Uzman Danışmanda, iki standart gösterge (Hareketli Ortalama ve Emtia Kanalı İndisi) ve bir özel gösterge (MultiRange_PCH) kullanacağız. Numaralandırma aşağıdaki gibi olacaktır:

//--- Indicators
enum ENUM_INDICATORS
  {
   MA       = 0, // Moving Average
   CCI      = 1, // CCI
   PCH      = 2  // Price Channel
  };

Harici parametreler aşağıdaki şekilde değiştirilir:

//--- External parameters of the Expert Advisor
sinput   long              MagicNumber=777;        // Magic number
sinput   int               Deviation=10;           // Slippage
input    ENUM_INDICATORS   Indicator=MA;           // Indicator
input    int               IndicatorPeriod=5;      // Indicator period
input    int               IndicatorSegments=2;    // Number of one direction indicator segments
input    double            Lot=0.1;                // Lot
input    double            VolumeIncrease=0.1;     // Position volume increase
input    double            VolumeIncreaseStep=10;  // Step for volume increase
input    double            StopLoss=50;            // Stop Loss
input    double            TakeProfit=100;         // Take Profit
input    double            TrailingStop=10;        // Trailing Stop
input    bool              Reverse=true;           // Position reversal
sinput   bool              ShowInfoPanel=true;     // Display of the info panel

Yukarıda belirtildiği gibi, Gösterge parametresinin açılır listesindeki üç göstergeden birini seçebileceksiniz.

Gösterge döneminin ayarlanabileceği tüm göstergeler için geçerli olan tek bir parametre vardır: IndicatorPeriod. Uzman Danışmanın önceki sürümündeki NumberOfBars parametresi IndicatorSegments olarak yeniden adlandırılmıştır ve şimdi pozisyon açma koşulunu karşılamak için belirli bir göstergenin yukarı/aşağı gitmesi gereken çubuk sayısını göstermektedir.

Puan cinsinden hacim artışına yönelik adımı ayarlamak için kullanılabilen VolumeIncreaseStep adlı başka bir harici parametre daha ekledik.

AllowedNumberOfBars değişkeninin değeri (artık AllowedNumberOfSegments) önceden GetBarsData() özel fonksiyonunda ayarlanırdı. Şimdi ise bu, ayrı bir fonksiyona yerleştirilerek yalnızca başlatma sırasında çağrılacaktır.

Pozisyon açma koşulu artık gösterge değerleri kullanılarak kontrol edileceğinden, atanacak değer her zaman ikiden büyük olacaktır. Diğer bir deyişle, IndicatorSegments harici değişkenine 1 değeri atanırsa, tamamlanan çubuktaki gösterge değerinin önceki çubuktakinden daha büyük olması gerektiği koşulunu sağlamak için (örneğin ALIŞ için) AllowedNumberOfSegments değişkenine 3 değeri atanacaktır. Bunun için son üç gösterge değerini elde etmemiz gerekiyor.

Aşağıda, CorrectInputParameters() fonksiyon kodu yer almaktadır:

//+------------------------------------------------------------------+
//| Adjusting input parameters                                       |
//+------------------------------------------------------------------+
void CorrectInputParameters()
  {
//--- Adjust the number of bars for the position opening condition
   if(AllowedNumberOfSegments<=0)
     {
      if(IndicatorSegments<=1)
         AllowedNumberOfSegments=3;                     // At least three bars are required
      if(IndicatorSegments>=5)
         AllowedNumberOfSegments=5;                     // but no more than 7
      else
         AllowedNumberOfSegments=IndicatorSegments+1;   // and always greater by two
     }
  }

Göstergelerle ilgilenmeye başlamadan önce, alım satıma izin verilip verilmediğini kontrol edecek bir fonksiyon oluşturalım: CheckTradingPermission(). Fonksiyonda listelenen nedenlerden herhangi biri nedeniyle alım satıma izin verilmezse, sıfır değeri döndürülür. Bu, bir sonraki denemenin bir sonraki çubukta yapılması gerektiği anlamına gelir.

//+------------------------------------------------------------------+
//| Checking if trading is allowed                                   |
//+------------------------------------------------------------------+
bool CheckTradingPermission()
  {
//--- For real-time mode
   if(IsRealtime())
     {
      //--- Checking server connection
      if(!TerminalInfoInteger(TERMINAL_CONNECTED))
         return(1);
      //--- Permission to trade at the running program level
      if(!MQL5InfoInteger(MQL5_TRADE_ALLOWED))
         return(2);
      //--- Permission to trade at the terminal level
      if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
         return(3);
      //--- Permission to trade for the current account
      if(!AccountInfoInteger(ACCOUNT_TRADE_ALLOWED))
         return(4);
      //--- Permission to trade automatically for the current account
      if(!AccountInfoInteger(ACCOUNT_TRADE_EXPERT))
         return(5);
     }
//---
   return(0);
  }

Şimdi makalenin ana konusuna gelelim. Göstergenin değerlerine erişmek için ilk olarak işleyiciyi elde etmemiz gerekir. Bu da, adları göstergenin kısa adından ve önündeki "i" sembolünden oluşan özel fonksiyonlar kullanılarak yapılır.

Örneğin, Moving Average (Hareketli Ortalama) göstergesinde buna karşılık gelen iMA() fonksiyonu vardır. MetaTrader 5 terminalindeki tüm standart gösterge kolları bu fonksiyonlar kullanılarak elde edilebilir. Tam liste, Teknik Göstergeler adlı MQL5 Referansı bölümünde mevcuttur. Özel bir göstergenin bir işleyicisini elde etmek için, iCustom() fonksiyonunu kullanın.

GetIndicatorHandle() fonksiyonunu uygulayacağız, burada Indicator parametresinde seçilen göstergeye göre ilgili göstergenin işleyici değeri indicator_handle global değişkenine atanacaktır. Fonksiyon kodu, alım satım sinyali fonksiyonları kitaplığımızda (\Include\TradeSignals.mqh dosyası) bulunabilir, gösterge işleyicisine sahip değişken ise Uzman Danışmanın ana dosyasında bulunur.

//+------------------------------------------------------------------+
//| Getting the indicator handle                                     |
//+------------------------------------------------------------------+
void GetIndicatorHandle()
  {
//--- If the Moving Average indicator is selected
   if(Indicator==MA)
      indicator_handle=iMA(_Symbol,Period(),IndicatorPeriod,0,MODE_SMA,PRICE_CLOSE);
//--- If the CCI indicator is selected
   if(Indicator==CCI)
      indicator_handle=iCCI(_Symbol,Period(),IndicatorPeriod,PRICE_CLOSE);
//--- If the MultiRange_PCH indicator is selected
   if(Indicator==PCH)
      indicator_handle=iCustom(_Symbol,Period(),"MultiRange_PCH",IndicatorPeriod);
//--- If the indicator handle could not be obtained
   if(indicator_handle==INVALID_HANDLE)
      Print("Failed to get the indicator handle!");
  }

Ayrıca, elde edilen gösterge işleyicilerini kullanarak değerlerini elde edebileceğimizGetDataIndicators() fonksiyonunu oluştururuz. Bu ise, aşağıdaki makalede değerlendirilen CopyTime(), CopyClose(), CopyOpen(), CopyHigh() ve CopyLow() fonksiyonlar kullanılarak elde çubuk değerlerinin elde edilmesine benzer bir şekilde CopyBuffer() fonksiyonu kullanılarak yapılır: "MQL5 Tarif Defteri: Pozisyon Parametrelerini MetaTrader 5 Strateji Test Cihazında Analiz Etme".

Gösterge birkaç tampona (değer satırları) sahip olabileceğinden, tampon indisi ikinci parametre olarak CopyBuffer() fonksiyonuna aktarılır. Standart göstergeler için tampon indisleri MQL5 Referansında bulunabilir. Özel göstergeler için, kaynak kodun mevcut olması koşuluyla, kodda tampon indisleri bulunabilir. Kod yoksa, Strateji Test Cihazının, görselleştirme modunda koşulların nasıl karşılandığını gözlemleyerek deneme yoluyla indisi bulmanız gerekecektir.

Ama bundan önce, Uzman Danışmanın ana dosyasındaki gösterge tampon değerleri için dinamik diziler oluşturmamız gerekiyor:

//--- Arrays for indicator values
double indicator_buffer1[];
double indicator_buffer2[];

GetIndicatorsData() kodu aşağıda verilmektedir:

//+------------------------------------------------------------------+
//| Getting indicator values                                         |
//+------------------------------------------------------------------+
bool GetIndicatorsData()
  {
//--- If the indicator handle has been obtained
   if(indicator_handle!=INVALID_HANDLE)
     {
      //--- For the Moving Average or CCI indicator
      if(Indicator==MA || Indicator==CCI)
        {
         //--- Reverse the indexing order (... 3 2 1 0)
         ArraySetAsSeries(indicator_buffer1,true);
         //--- Get indicator values
         if(CopyBuffer(indicator_handle,0,0,AllowedNumberOfSegments,indicator_buffer1)<AllowedNumberOfSegments)
           {
            Print("Failed to copy the values ("+
                  _Symbol+"; "+TimeframeToString(Period())+") to the indicator_buffer1 array! Error ("+
                  IntegerToString(GetLastError())+"): "+ErrorDescription(GetLastError()));
            return(false);
           }
        }
      //--- For the MultiRange_PCH indicator
      if(Indicator==PCH)
        {
         //--- Reverse the indexing order (... 3 2 1 0)
         ArraySetAsSeries(indicator_buffer1,true);
         ArraySetAsSeries(indicator_buffer2,true);
         //--- Get indicator values
         if(CopyBuffer(indicator_handle,0,0,AllowedNumberOfSegments,indicator_buffer1)<AllowedNumberOfSegments || 
            CopyBuffer(indicator_handle,1,0,AllowedNumberOfSegments,indicator_buffer2)<AllowedNumberOfSegments)
           {
            Print("Failed to copy the values ("+
                  _Symbol+"; "+TimeframeToString(Period())+") to the indicator_buffer1 or indicator_buffer2 array! Error ("+
                  IntegerToString(GetLastError())+"): "+ErrorDescription(GetLastError()));
            return(false);
           }
        }
      //---
      return(true);
     }
//--- If the indicator handle has not been obtained, retry
   else
      GetIndicatorHandle();
//---
   return(false);
  }

GetTradingSignal() fonksiyonu büyük ölçüde değiştirilmiştir. Pozisyonun yokluğunda ve pozisyonun mevcut olduğu durumlarda koşullar farklıdır. Hareketli Ortalama ve CCI göstergeleri için koşullar aynıdır. MultiRange_PCH için bunlar ayrı bir blokta düzenlenir. Kodu daha okunabilir hale getirmek ve tekrarlardan kaçınmak için, böyle bir pozisyonun mevcut olması ve harici parametre tarafından ilgili eyleme izin verilmesi koşuluyla, pozisyon açma veya ters çevirme için bir sinyal döndüren GetSignal() adlı yardımcı bir fonksiyon oluşturuyoruz.

Aşağıda GetSignal() fonksiyon kodu yer almaktadır:

//+------------------------------------------------------------------+
//| Checking the condition and returning a signal                    |
//+------------------------------------------------------------------+
ENUM_ORDER_TYPE GetSignal()
  {
//--- Check conditions for the Moving Average and CCI indicators
   if(Indicator==MA || Indicator==CCI)
     {
      //--- A Sell signal
      if(AllowedNumberOfSegments==3 && 
         indicator_buffer1[1]<indicator_buffer1[2])
         return(ORDER_TYPE_SELL);
      //---
      if(AllowedNumberOfSegments==4 && 
         indicator_buffer1[1]<indicator_buffer1[2] && 
         indicator_buffer1[2]<indicator_buffer1[3])
         return(ORDER_TYPE_SELL);
      //---
      if(AllowedNumberOfSegments==5 && 
         indicator_buffer1[1]<indicator_buffer1[2] && 
         indicator_buffer1[2]<indicator_buffer1[3] && 
         indicator_buffer1[3]<indicator_buffer1[4])
         return(ORDER_TYPE_SELL);
      //---
      if(AllowedNumberOfSegments==6 && 
         indicator_buffer1[1]<indicator_buffer1[2] && 
         indicator_buffer1[2]<indicator_buffer1[3] && 
         indicator_buffer1[3]<indicator_buffer1[4] && 
         indicator_buffer1[4]<indicator_buffer1[5])
         return(ORDER_TYPE_SELL);
      //---
      if(AllowedNumberOfSegments>=7 && 
         indicator_buffer1[1]<indicator_buffer1[2] && 
         indicator_buffer1[2]<indicator_buffer1[3] && 
         indicator_buffer1[3]<indicator_buffer1[4] && 
         indicator_buffer1[4]<indicator_buffer1[5] && 
         indicator_buffer1[5]<indicator_buffer1[6])
         return(ORDER_TYPE_SELL);

      //--- A Buy signal
      if(AllowedNumberOfSegments==3 && 
         indicator_buffer1[1]>indicator_buffer1[2])
         return(ORDER_TYPE_BUY);
      //---
      if(AllowedNumberOfSegments==4 && 
         indicator_buffer1[1]>indicator_buffer1[2] && 
         indicator_buffer1[2]>indicator_buffer1[3])
         return(ORDER_TYPE_BUY);
      //---
      if(AllowedNumberOfSegments==5 && 
         indicator_buffer1[1]>indicator_buffer1[2] && 
         indicator_buffer1[2]>indicator_buffer1[3] && 
         indicator_buffer1[3]>indicator_buffer1[4])
         return(ORDER_TYPE_BUY);
      //---
      if(AllowedNumberOfSegments==6 && 
         indicator_buffer1[1]>indicator_buffer1[2] && 
         indicator_buffer1[2]>indicator_buffer1[3] && 
         indicator_buffer1[3]>indicator_buffer1[4] && 
         indicator_buffer1[4]>indicator_buffer1[5])
         return(ORDER_TYPE_BUY);
      //---
      if(AllowedNumberOfSegments>=7 && 
         indicator_buffer1[1]>indicator_buffer1[2] && 
         indicator_buffer1[2]>indicator_buffer1[3] && 
         indicator_buffer1[3]>indicator_buffer1[4] && 
         indicator_buffer1[4]>indicator_buffer1[5] && 
         indicator_buffer1[5]>indicator_buffer1[6])
         return(ORDER_TYPE_BUY);
     }
//--- Block that checks conditions for the MultiRange_PCH indicator
   if(Indicator==PCH)
     {
      //--- A Sell signal
      if(close_price[1]<indicator_buffer2[1] && 
         open_price[1]>indicator_buffer2[1])
         return(ORDER_TYPE_SELL);
      //--- A Buy signal
      if(close_price[1]>indicator_buffer1[1] && 
         open_price[1]<indicator_buffer1[1])
         return(ORDER_TYPE_BUY);
     }
//--- No signal
   return(WRONG_VALUE);
  }

GetTradingSignal() fonksiyon kodu şimdi şu şekildedir:

//+------------------------------------------------------------------+
//| Determining trading signals                                      |
//+------------------------------------------------------------------+
ENUM_ORDER_TYPE GetTradingSignal()
  {
//--- If there is no position
   if(!pos.exists)
     {
      //--- A Sell signal
      if(GetSignal()==ORDER_TYPE_SELL)
         return(ORDER_TYPE_SELL);
      //--- A Buy signal
      if(GetSignal()==ORDER_TYPE_BUY)
         return(ORDER_TYPE_BUY);
     }
//--- If the position exists
   if(pos.exists)
     {
      //--- Get the position type
      GetPositionProperties(P_TYPE);
      //--- Get the last deal price
      GetPositionProperties(P_PRICE_LAST_DEAL);
      //--- Block that checks conditions for the Moving Average and CCI indicators
      if(Indicator==MA || Indicator==CCI)
        {
         //--- A Sell signal
         if(pos.type==POSITION_TYPE_BUY && 
            GetSignal()==ORDER_TYPE_SELL)
            return(ORDER_TYPE_SELL);
         //---
         if(pos.type==POSITION_TYPE_SELL && 
            GetSignal()==ORDER_TYPE_SELL && 
            close_price[1]<pos.last_deal_price-CorrectValueBySymbolDigits(VolumeIncreaseStep*_Point))
            return(ORDER_TYPE_SELL);
         //--- A Buy signal
         if(pos.type==POSITION_TYPE_SELL && 
            GetSignal()==ORDER_TYPE_BUY)
            return(ORDER_TYPE_BUY);
         //---
         if(pos.type==POSITION_TYPE_BUY && 
            GetSignal()==ORDER_TYPE_BUY && 
            close_price[1]>pos.last_deal_price+CorrectValueBySymbolDigits(VolumeIncreaseStep*_Point))
            return(ORDER_TYPE_BUY);
        }
      //--- Block that checks conditions for the MultiRange_PCH indicator
      if(Indicator==PCH)
        {
         //--- A Sell signal
         if(pos.type==POSITION_TYPE_BUY && 
            close_price[1]<indicator_buffer2[1] && 
            open_price[1]>indicator_buffer2[1])
            return(ORDER_TYPE_SELL);
         //---
         if(pos.type==POSITION_TYPE_SELL && 

            close_price[1]<pos.last_deal_price-CorrectValueBySymbolDigits(VolumeIncreaseStep*_Point))
            return(ORDER_TYPE_SELL);
         //--- A Buy signal
         if(pos.type==POSITION_TYPE_SELL && 
            close_price[1]>indicator_buffer1[1] && 
            open_price[1]<indicator_buffer1[1])
            return(ORDER_TYPE_BUY);
         //---
         if(pos.type==POSITION_TYPE_BUY && 
            close_price[1]>pos.last_deal_price+CorrectValueBySymbolDigits(VolumeIncreaseStep*_Point))
            return(ORDER_TYPE_BUY);
        }
     }
//--- No signal
   return(WRONG_VALUE);
  }

Şimdi, sadece sembol özelliklerinin parçası olan Anında Yürütme ve Piyasa Yürütmesi modlarını görmemiz ve OpenPosition() pozisyon açma fonksiyonunun kodunu buna göre değiştirmemiz gerekiyor. Adları kendilerini açıklayan modlar MQL5 Referansı içinde de bulunabilir:

  • Anında Yürütme
  • Piyasa Yürütmesi

Piyasa Yürütmesi modu ile uğraşırken, ayarlanmış Zarar Durdur ve Kâr Al seviyelerinde bir pozisyon açamayacağınızı lütfen unutmayın: İlk olarak bir pozisyon açmanız ve ardından seviyeleri ayarlayarak bunu değiştirmeniz gerekir.

Yapı 803'den başlayarak, Zarar Durdur ve Kâr Al seviyeleri, Piyasa Yürütmesi ve Döviz Yürütme modları için bir pozisyon açarken ayarlanabilir.

Sembol özelliklerinin yapısına yürütme modunu ekleyelim:

//--- Symbol properties
struct symbol_properties
  {
   int               digits;           // Number of decimal places in the price
   int               spread;           // Spread in points
   int               stops_level;      // Stops level
   double            point;            // Point value
   double            ask;              // Ask price
   double            bid;              // Bid price
   double            volume_min;       // Minimum volume for a deal
   double            volume_max;       // Maximum volume for a deal
   double            volume_limit;     // Maximum permissible volume for a position and orders in one direction
   double            volume_step;      // Minimum volume change step for a deal
   double            offset;           // Offset from the maximum possible price for a transaction
   double            up_level;         // Upper Stop level price
   double            down_level;       // Lower Stop level price
   ENUM_SYMBOL_TRADE_EXECUTION execution_mode; // Execution mode
  };

Buna göre, ENUM_SYMBOL_PROPERTIES numaralandırmasını

//--- Enumeration of position properties
enum ENUM_SYMBOL_PROPERTIES
  {
   S_DIGITS          = 0,
   S_SPREAD          = 1,
   S_STOPSLEVEL      = 2,
   S_POINT           = 3,
   S_ASK             = 4,
   S_BID             = 5,
   S_VOLUME_MIN      = 6,
   S_VOLUME_MAX      = 7,
   S_VOLUME_LIMIT    = 8,
   S_VOLUME_STEP     = 9,
   S_FILTER          = 10,
   S_UP_LEVEL        = 11,
   S_DOWN_LEVEL      = 12,
   S_EXECUTION_MODE  = 13,
   S_ALL             = 14
  };

ve GetSymbolProperties() fonksiyonunu değiştirmemiz gerekir:

case S_EXECUTION_MODE: symb.execution_mode=(ENUM_SYMBOL_TRADE_EXECUTION)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_EXEMODE);   break;
      //---
      case S_ALL           :
         symb.digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);
         symb.spread=(int)SymbolInfoInteger(_Symbol,SYMBOL_SPREAD);
         symb.stops_level=(int)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL);
         symb.point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);
         symb.ask=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),symb.digits);
         symb.bid=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),symb.digits);
         symb.volume_min=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
         symb.volume_max=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
         symb.volume_limit=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_LIMIT);
         symb.volume_step=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
         symb.offset=NormalizeDouble(CorrectValueBySymbolDigits(lot_offset*symb.point),symb.digits);
         symb.up_level=NormalizeDouble(symb.ask+symb.stops_level*symb.point,symb.digits);
         symb.down_level=NormalizeDouble(symb.bid-symb.stops_level*symb.point,symb.digits);
         symb.execution_mode=(ENUM_SYMBOL_TRADE_EXECUTION)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_EXEMODE);                       break;
         //---

Bunun sonucunda, OpenPosition() fonksiyon kodu şimdi şu şekildedir:

//+------------------------------------------------------------------+
//| Opening a position                                               |
//+------------------------------------------------------------------+
void OpenPosition(double lot,
                  ENUM_ORDER_TYPE order_type,
                  double price,
                  double sl,
                  double tp,
                  string comment)
  {
//--- Set the magic number in the trading structure
   trade.SetExpertMagicNumber(MagicNumber);
//--- Set the slippage in points
   trade.SetDeviationInPoints(CorrectValueBySymbolDigits(Deviation));
//--- The Instant Execution mode
//    A position can be opened with the Stop Loss and Take Profit levels set
   if(symb.execution_mode==SYMBOL_TRADE_EXECUTION_INSTANT)
     {
      //--- If the position failed to open, print the relevant message
      if(!trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,comment))
         Print("Error opening the position: ",GetLastError()," - ",ErrorDescription(GetLastError()));
     }
//--- The Market Execution mode 
//    First open a position and only then set the Stop Loss and Take Profit levels
//    *** Starting with build 803, Stop Loss and Take Profit can be set upon position opening ***
   if(symb.execution_mode==SYMBOL_TRADE_EXECUTION_MARKET)
     {
      //--- If there is no position, first open a position and then set Stop Loss and Take Profit
      if(!pos.exists)
        {
         //--- If the position failed to open, print the relevant message
         if(!trade.PositionOpen(_Symbol,order_type,lot,price,0,0,comment))
            Print("Error opening the position: ",GetLastError()," - ",ErrorDescription(GetLastError()));
         //--- Get the flag of presence/absence of the position
         pos.exists=PositionSelect(_Symbol);
         //--- If the position exists
         if(pos.exists)
           {
            //--- Set Stop Loss and Take Profit
            if(!trade.PositionModify(_Symbol,sl,tp))
               Print("Error modifying the position: ",GetLastError()," - ",ErrorDescription(GetLastError()));
           }
        }
      //--- If the position exists, increase its volume and leave the Stop Loss and Take Profit levels unchanged
      else
        {
         //--- If the position failed to open, print the relevant message
         if(!trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,comment))
            Print("Error opening the position: ",GetLastError()," - ",ErrorDescription(GetLastError()));
        }
     }
  }

Hala olay işleme fonksiyonlarına nihai, çok önemli bir dokunuş eklememiz gerekiyor:

  • OnInit
    //+------------------------------------------------------------------+
    //| Expert initialization function                                   |
    //+------------------------------------------------------------------+
    int OnInit()
      {
    //--- Adjust the input parameters
       CorrectInputParameters();
    //--- Get indicator handles
       GetIndicatorHandle();
    //--- Initialize the new bar
       CheckNewBar();
    //--- Get the properties
       GetPositionProperties(P_ALL);
    //--- Set the info panel
       SetInfoPanel();
    //---
       return(0);
      }
  • OnDeinit
    //+------------------------------------------------------------------+
    //| Expert deinitialization function                                 |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
      {
    //--- Print the deinitialization reason to the journal
       Print(GetDeinitReasonText(reason));
    //--- When deleting from the chart
       if(reason==REASON_REMOVE)
         {
          //--- Delete all objects relating to the info panel from the chart
          DeleteInfoPanel();
          //--- Delete the indicator handle
          IndicatorRelease(indicator_handle);
         }
      }
  • OnTick
    //+------------------------------------------------------------------+
    //| Expert tick function                                             |
    //+------------------------------------------------------------------+
    void OnTick()
      {
    //--- If the bar is not new, exit
       if(!CheckNewBar())
         {
          if(IsVisualMode() || IsRealtime())
            {
             //--- Get the properties and update the values on the panel
             GetPositionProperties(P_ALL);
             //--- Set/update the info panel
             SetInfoPanel();
            }
          return;
         }
    
    //--- If there is a new bar
       else
         {
          //--- If trading is allowed
          if(CheckTradingPermission()==0)
            {
             if(!GetIndicatorsData())
                return;
             GetBarsData();          // Get bar data
             TradingBlock();         // Check the conditions and trade
             ModifyTrailingStop();   // Modify the Trailing Stop level
            }
         }
    //--- Get the properties
       GetPositionProperties(P_ALL);
    //--- Update the info panel
       SetInfoPanel();
      }

Artık tüm fonksiyonlar hazır olduğuna göre parametreleri optimize edebiliriz. Kodu ana program dosyasından derlemeniz gerektiğini unutmayın.

 

Parametreleri Optimize Etme ve Uzman Danışmanı Test Etme

Strateji Test Cihazı aşağıda gösterildiği gibi ayarlanmalıdır:

Şekil 1. Strateji Test Cihazı ayarları.

Şekil 1. Strateji Test Cihazı ayarları.

Ayrıca, Optimizasyon için Uzman Danışmanın parametrelerini ayarlıyoruz (ayrıca ayarları içeren ekteki *.set dosyasına bakın):

Şekil 2. Uzman Danışman Ayarları.

Şekil 2. Uzman Danışmanın Ayarları.

Optimizasyon, çift çekirdekli bir işlemcide yaklaşık 40 dakika sürmüştür. Optimizasyon grafiği, kâr bölgesindeki sonuçlara dayalı olarak bir alım satım sisteminin kalitesini kısmen değerlendirmenize olanak sağlar:

Şekil 3. Optimizasyon grafiği.

Şekil 3. Optimizasyon grafiği.

Maksimum kurtarma faktörü test sonuçları aşağıdaki gibidir:

Şekil 4. Maksimum kurtarma faktörü test sonuçları.

Şekil 4. Maksimum kurtarma faktörü test sonuçları

 

Sonuç

Uzman Danışmanın kaynak kodlarını içeren indirilebilir arşiv makaleye eklenmiştir. Çıkarıldıktan sonra \TestIndicatorConditions dosya klasörünü <Metatrader 5 terminal>\MQL5\Experts içine yerleştirmelisiniz. Uzman Danışmanın doğru çalışmasını sağlamak için MultiRange_PCH göstergesi indirilmeli ve <Metatrader 5 terminal>\MQL5\Indicators içine yerleştirilmelidir.

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

ZigZag Göstergesi: Yeni Yaklaşım ve Yeni Çözümler ZigZag Göstergesi: Yeni Yaklaşım ve Yeni Çözümler
Makale, gelişmiş bir ZigZag göstergesi oluşturma imkanını incelemektedir. Düğümleri tanımlama fikri, Zarflar göstergesinin kullanımına dayanmaktadır. Tüm ZigZag düğümlerinin Zarf bantlarının sınırları içinde yer aldığı bir Zarflar serisi için belirli bir giriş parametresi kombinasyonu bulabileceğimizi varsayarız. Bunun sonucunda, yeni düğümün koordinatlarını tahmin etmeye çalışabiliriz.
MQL5 Tarif Defteri: Pozisyon Özelliklerini Elde Etmek için İşlemler Geçmişi ve Fonksiyon Kitaplığı MQL5 Tarif Defteri: Pozisyon Özelliklerini Elde Etmek için İşlemler Geçmişi ve Fonksiyon Kitaplığı
Pozisyon özellikleri ile ilgili önceki makalelerde verilen bilgileri kısaca özetlemenin zamanı geldi. Bu makalemizde, işlemler geçmişine erişimin ardından edinilebilecek özellikleri elde etmek için birkaç ek fonksiyon oluşturacağız. Ayrıca pozisyon ve sembol özelliklerine daha rahat erişmemizi sağlayacak veri yapılarını da öğreneceğiz.
MQL5 Tarif Defteri: Üçlü Ekran Stratejisine Dayalı Bir Alım Satım Sistemi Çerçevesi Geliştirme MQL5 Tarif Defteri: Üçlü Ekran Stratejisine Dayalı Bir Alım Satım Sistemi Çerçevesi Geliştirme
Bu makalede, MQL5'te Üçlü Ekran stratejisine dayalı bir alım satım sistemi için bir çerçeve geliştireceğiz. Uzman Danışman sıfırdan geliştirilmeyecektir. Bunun yerine, halihazırda büyük ölçüde amacımıza hizmet eden "MQL5 Tarif Defteri: Uzman Danışmanlarda Alım Satım Koşullarını Belirlemek için Göstergeleri Kullanma" önceki makalesinden programı değiştireceğiz. Böylelikle makale aynı zamanda hazır programların modellerini nasıl kolay bir şekilde değiştirebileceğinizi gösterecektir.
MQL5 Tarif Defteri Alım Satım Seviyelerini Ayarlarken/Değiştirirken Hatalardan Nasıl Kaçınılır? MQL5 Tarif Defteri Alım Satım Seviyelerini Ayarlarken/Değiştirirken Hatalardan Nasıl Kaçınılır?
"MQL5 Tarif Defteri: MetaTrader 5 Strateji Test Cihazındaki Pozisyon Parametrelerini Analiz Etme" isimli serinin önceki makalesinden Uzman Danışman üzerindeki çalışmamızın devamında, bunu birçok faydalı fonksiyon ile geliştirecek ve mevcut olanları iyileştirip optimize edeceğiz. Uzman Danışman, bu sefer MetaTrader 5 Strateji Test Cihazında optimize edilebilecek harici parametrelere sahip olacak ve bazı yönlerden basit bir alım sistemine benzeyecektir.