English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
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ığı

MetaTrader 5Örnekler | 13 Ocak 2022, 09:33
120 0
Anatoli Kazharski
Anatoli Kazharski

Giriş

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.

Pozisyon hacimlerinin varlıkları boyunca aynı kaldığı alım satım sistemleri, bu makalede sağlanacak fonksiyonların kullanılmasını pek gerektirmez. Ancak daha sonraki bir aşamada bir para yönetim sistemi uygulamayı ve alım satım stratejinizde bir pozisyon lot boyutunu kontrol etmeyi planlıyorsanız, bu fonksiyonlar vazgeçilmez olacaktır.

Başlamadan önce, bu web sitesini ilk kez ziyaret ederken bu makalenin bağlantısını takip eden veya MQL5 dilini yeni öğrenmeye başlayan okuyuculara, "MQL5 Tarif Defteri" serisinin daha önceki makaleleri ile başlamaları için bir öneride bulunmak istiyorum.


Uzman Danışman Geliştirme

Aşağıdaki önceki makalede değiştirilen Uzman Danışmanda yeni fonksiyonların çalışmasını görmek için, pozisyon halihazırda buradayken tekrar açılış sinyali gelirse pozisyon hacmini artırma imkanını ekleyeceğiz: "MQL5 Tarif Defteri: Alım Satım Seviyelerini Ayarlarken/Değiştirirken Hatalardan Nasıl Kaçınılır?"

Pozisyon geçmişinde birkaç işlem olabilir; ve alım satım sırasında pozisyon hacminde değişiklikler olmuşsa, mevcut pozisyon fiyatında da değişiklikler olmuş olmalıdır. İlk giriş noktasının fiyatını bulmak için, bu belirli pozisyonla ilgili işlemlerin geçmişine erişmemiz gerekir. Aşağıdaki şekil, bir pozisyonun yalnızca bir işleminin (giriş noktası) olduğu durumun bir gösterimidir:

Şekil 1. Pozisyondaki ilk işlem

Şekil 1. Pozisyondaki ilk işlem.

Sonraki şekil, ikinci işlemin ardından pozisyon fiyatındaki değişikliği gösterir:

Şekil 2. Pozisyondaki ikinci işlem

Şekil 2. Pozisyondaki ikinci işlem.

Önceki makalelerde gösterildiği gibi standart tanımlayıcılar, yalnızca mevcut pozisyon fiyatını (POSITION_PRICE_OPEN) ve bir pozisyonun açılacağı bir sembolün mevcut fiyatını (POSITION_PRICE_CURRENT) elde etmenizi sağlar.

Bununla birlikte, bazı alım satım sistemlerinde, fiyatın ilk giriş noktasından kat ettiği mesafeyi ve son işlemin fiyatını bilmemiz gerekir. Tüm bu bilgiler, hesabın işlem/emir geçmişinde mevcuttur. Aşağıda, önceki şekil ile ilişkili işlemlerin listesi yer almaktadır:

Şekil 3. Hesaptaki işlemlerin geçmişi

Şekil 3. Hesaptaki işlemlerin geçmişi.

Artık durumun netleştiğine ve tüm hedeflerin belirlendiğine inanıyorum. Önceki makalelerde yer alan Uzman Danışmanı değiştirmeye devam edelim. İlk olarak, pozisyon özelliklerinin numaralandırılmasına 0, 6, 9, 12 ve 16 numaralı yeni tanımlayıcıları ekleyeceğiz:

//--- Enumeration of position properties
enum ENUM_POSITION_PROPERTIES
  {
   P_TOTAL_DEALS     = 0,
   P_SYMBOL          = 1,
   P_MAGIC           = 2,
   P_COMMENT         = 3,
   P_SWAP            = 4,
   P_COMMISSION      = 5,
   P_PRICE_FIRST_DEAL= 6,
   P_PRICE_OPEN      = 7,
   P_PRICE_CURRENT   = 8,
   P_PRICE_LAST_DEAL = 9,
   P_PROFIT          = 10,
   P_VOLUME          = 11,
   P_INITIAL_VOLUME  = 12,
   P_SL              = 13,
   P_TP              = 14,
   P_TIME            = 15,
   P_DURATION        = 16,
   P_ID              = 17,
   P_TYPE            = 18,
   P_ALL             = 19
  };

Özelliklerin her biri için yorumlar aşağıda biraz gözden geçirilecek bir yapıda sağlanacaktır.

Harici parametrelerin sayısını artıralım. Şimdi aşağıdakileri belirtebiliriz:

  • MagicNumber - Uzman Danışman için benzersiz bir kimlik (sihirli sayı);
  • Sapma - kayma;
  • VolumeIncrease - pozisyon hacmini artırma değeri;
  • InfoPanel - bilgi panelinin görüntülenmesini etkinleştirmenizi/devre dışı bırakmanızı sağlayan bir parametre.

Şu şekilde uygulanır:

//--- External parameters of the Expert Advisor
sinput   long        MagicNumber=777;     // Magic number
sinput   int         Deviation=10;        // Slippage
input    int         NumberOfBars=2;      // Number of Bullish/Bearish bars for a Buy/Sell
input    double      Lot=0.1;             // Lot
input    double      VolumeIncrease=0.1;  // Position 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

Lütfen sinput değiştiricisi ayarlanmış olan parametrelere dikkat edin. Bu değiştirici, Strateji Test Cihazında optimizasyonu devre dışı bırakmanıza olanak sağlar. Aslında, kendi kullanımınız için bir program geliştirirken, hangi parametrelerin nihai sonucu etkileyeceğini mükemmel bir şekilde anlarsınız, bu yüzden bunları optimizasyondan çıkarmanız yeterlidir. Ancak, oldukça fazla sayıda parametre söz konusu olduğunda, bu yöntem bunlar karartıldıkça görsel olarak bunları diğerlerinden ayırt etmenize olanak sağlar:

Şekil 4. Optimizasyon için devre dışı bırakılan parametreler karartılır

Şekil 4. Optimizasyon için devre dışı bırakılmış parametreler karartılır.

Şimdi pozisyon ve sembol özellik değerlerini saklayan global değişkenleri veri yapıları (yapı) ile değiştirelim:

//--- Position properties
struct position_properties
  {
   uint              total_deals;      // Number of deals
   bool              exists;           // Flag of presence/absence of an open position
   string            symbol;           // Symbol
   long              magic;            // Magic number
   string            comment;          // Comment
   double            swap;             // Swap
   double            commission;       // Commission   
   double            first_deal_price; // Price of the first deal in the position
   double            price;            // Current position price
   double            current_price;    // Current price of the position symbol      
   double            last_deal_price;  // Price of the last deal in the position
   double            profit;           // Profit/Loss of the position
   double            volume;           // Current position volume
   double            initial_volume;   // Initial position volume
   double            sl;               // Stop Loss of the position
   double            tp;               // Take Profit of the position
   datetime          time;             // Position opening time
   ulong             duration;         // Position duration in seconds
   long              id;               // Position identifier
   ENUM_POSITION_TYPE type;            // Position type
  };
//--- 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
  }

Şimdi, yapının belirli bir öğesine erişmek için bu yapı türünde bir değişken oluşturmamız gerekiyor. Prosedür, aşağıdaki makalede değerlendirilen bir alım satım sınıfına yönelik bir nesne oluşturmaya benzerdir: "MQL5 Tarif Defteri: Pozisyon Parametrelerini MetaTrader 5 Strateji Test Cihazında Analiz Etme".

//--- variables for position and symbol properties
position_properties  pos;
symbol_properties    symb;

Öğelere, sınıf yöntemlerini ele alırken olduğu gibi erişim sağlayabilirsiniz. Diğer bir deyişle, bu özel yapıda bulunan öğelerin listesini görüntülemek için bir yapı değişkeninin adından sonra bir nokta koymak yeterlidir. Bu oldukça kullanışlıdır. Yapının alanları için tek satırlık yorumlar sağlanıyorsa (örneğimizde olduğu gibi) bunlar, sağdaki bir araç ipucunda gösterilecektir.

Şekil 5a. Pozisyon parametreleri için yapı alanlarının listesi Şekil 5b. Sembol özellikleri için yapı alanlarının listesi

Şekil 5. Yapı alanlarının listesi.

Bir diğer önemli nokta. Uzman Danışmanı değiştirirken, birçok fonksiyonda kullanılan global değişkenlerinin neredeyse tamamını değiştirdik, dolayısıyla şimdi bunları sembol ve pozisyon özellikleri için ilgili yapı alanlarıyla değiştirmemiz gerekiyor. Örneğin, bir açık pozisyonun varlığı/yokluğu bayrağını saklamak için kullanılan pos_open global değişkeni, position_properties yapı türünün exists (var) alanıyla değiştirilmiştir. Dolayısıyla, pos_open değişkeninin kullanıldığı her yerde, bunun pos.exists (var) ile değiştirilmesi gerekir.

Bunu manuel olarak yaparsanız, uzun ve yorucu bir süreç olacaktır. Bu nedenle, bu görevin çözümünü MetaEditor özelliklerini kullanarak otomatikleştirmek daha iyi olacaktır: Düzenle menüsünde Bul ve Değiştir -> Değiştir veya Ctrl+H tuş kombinasyonu:


Şekil 6. Metni bulma ve değiştirme

Şekil 6. Metni bulma ve değiştirme.

Dosyayı derledikten sonra bir test yapmak için pozisyon ve sembol özellikleri için tüm global değişkenleri bulmamız ve değiştirmemiz gerekir. Herhangi bir hata tespit edilmezse bu, her şeyi doğru yaptığımız anlamına gelir. Makaleyi gereksiz yere uzatmamak için kodu burada vermeyeceğim. Bununla birlikte, indirmeniz için makalenin sonunda kullanıma hazır bir kaynak kodu mevcuttur.

Artık değişkenlerle ilgili bir şeyi çözdüğümüze göre, mevcut fonksiyonları değiştirmeye ve yenilerini oluşturmaya devam edelim.

Artık, harici parametrelerde sihirli sayıyı ve nokta cinsinden kaymayı ayarlayabiliyorsunuz. Dolayısıyla ilgili değişiklikleri Uzman Danışman kodunda da yapmamız gerekiyor. Kullanıcı tanımlı bir yardımcı OpenPosition() fonksiyonu oluşturacağız, burada bu özellikler, pozisyon açma için bir emir göndermeden önce CTrade sınıfının fonksiyonları kullanılarak ayarlanacaktır.

//+------------------------------------------------------------------+
//| Opening a position                                               |
//+------------------------------------------------------------------+
void OpenPosition(double lot,
                  ENUM_ORDER_TYPE order_type,
                  double price,
                  double sl,
                  double tp,
                  string comment)
  {
   trade.SetExpertMagicNumber(MagicNumber); // Set the magic number in the trading structure
   trade.SetDeviationInPoints(CorrectValueBySymbolDigits(Deviation)); // Set the slippage in points
//--- 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())); }
  }

Sadece Uzman Danışman TradingBlock() ana alım satım fonksiyonunun kodunda bazı küçük değişiklikler yapmamız gerekiyor. Aşağıda, fonksiyon kodunun değişikliğe uğrayan kısmı yer almaktadır:

//--- If there is no position
   if(!pos.exists)
     {
      //--- Adjust the volume
      lot=CalculateLot(Lot);
      //--- Open a position
      OpenPosition(lot,order_type,position_open_price,sl,tp,comment);
     }
//--- If there is a position
   else
     {
      //--- Get the position type
      GetPositionProperties(P_TYPE);
      //--- If the position is opposite to the signal and the position reversal is enabled
      if(pos.type==opposite_position_type && Reverse)
        {
         //--- Get the position volume
         GetPositionProperties(P_VOLUME);
         //--- Adjust the volume
         lot=pos.volume+CalculateLot(Lot);
         //--- Reverse the position
         OpenPosition(lot,order_type,position_open_price,sl,tp,comment);
         return;
        }
      //--- If the signal is in the direction of the position and the volume increase is enabled, increase the position volume
      if(!(pos.type==opposite_position_type) && VolumeIncrease>0)
        {
         //--- Get the Stop Loss of the current position
         GetPositionProperties(P_SL);
         //--- Get the Take Profit of the current position
         GetPositionProperties(P_TP);
         //--- Adjust the volume
         lot=CalculateLot(Increase);
         //--- Increase the position volume
         OpenPosition(lot,order_type,position_open_price,pos.sl,pos.tp,comment);
         return;
        }

Yukarıdaki kod, mevcut pozisyonun yönünün sinyal yönüne göre kontrol edildiği blok ile geliştirilmiştir. Bunların yönleri kesişiyorsa ve harici parametrelerde pozisyon hacim artışı etkinleştirilmişse (VolumeIncrease parametre değeri sıfırdan büyükse), verilen bir lotu kontrol edip/ayarlayıp ilgili emri göndeririz. Artık bir pozisyon açmak veya bunu ters çevirmek için emir göndermek veya pozisyon hacmini artırmak için yapmanız gereken tek şey bir satır kod yazmak.

İşlemler geçmişinden pozisyon özelliklerini elde etmek için fonksiyonlar oluşturalım: Mevcut pozisyonda işlemlerin sayısını döndüren CurrentPositionTotalDeals() fonksiyonu ile başlayacağız:

//+------------------------------------------------------------------+
//| Returning the number of deals in the current position            |
//+------------------------------------------------------------------+
uint CurrentPositionTotalDeals()
  {
   int    total       =0;  // Total deals in the selected history list
   int    count       =0;  // Counter of deals by the position symbol
   string deal_symbol =""; // symbol of the deal
//--- If the position history is obtained
   if(HistorySelect(pos.time,TimeCurrent()))
     {
      //--- Get the number of deals in the obtained list
      total=HistoryDealsTotal();
      //--- Iterate over all the deals in the obtained list
      for(int i=0; i<total; i++)
        {
            //--- Get the symbol of the deal
            deal_symbol=HistoryDealGetString(HistoryDealGetTicket(i),DEAL_SYMBOL);
            //--- If the symbol of the deal and the current symbol are the same, increase the counter
            if(deal_symbol==_Symbol)
               count++;
        }
     }
//---
   return(count);
  }

Yukarıdaki kodda oldukça ayrıntılı yorumlar sağlanmıştır. Ancak geçmişin nasıl seçildiğine dair birkaç şey söylemeliyiz. Bizim durumumuzda, listeyi HistorySelect() fonksiyonunu kullanarak açılış zamanı ile belirlenen mevcut pozisyonun açılma noktasından mevcut zaman noktasına kadar olan listeyi aldık. Geçmişi seçtikten sonra, HistoryDealsTotal() fonksiyonunu kullanarak listedeki işlem sayısını bulabiliriz. Gerisi yorumlardan anlaşılmalıdır.

Belirli bir pozisyonun geçmişi, HistorySelectByPosition() fonksiyonu kullanılarak bunun tanımlayıcısı tarafından da seçilebilir. Burada, Uzman Danışmanımızda bazen meydana geldiği gibi, pozisyon ters çevrildiğinde pozisyon tanımlayıcısının aynı kaldığını göz önünde bulundurmanız gerekir. Ancak pozisyon açma süresi ters çevirme üzerine değişir, bu nedenle bu varyantın uygulanması daha kolaydır. Ancak, yalnızca şu anda açık olan pozisyon için geçerli olmayan işlemlerin geçmişi ile ilgilenmeniz gerekiyorsa, tanımlayıcıları kullanmalısınız. Gelecekteki makalelerde işlemler geçmişine geri döneceğiz.

Pozisyondaki ilk işlemin fiyatını yani pozisyonun açıldığı işlemin fiyatını döndüren bir CurrentPositionFirstDealPrice() fonksiyonu oluşturarak devam edelim.

//+------------------------------------------------------------------+
//| Returning the price of the first deal in the current position    |
//+------------------------------------------------------------------+
double CurrentPositionFirstDealPrice()
  {
   int      total       =0;    // Total deals in the selected history list
   string   deal_symbol ="";   // symbol of the deal
   double   deal_price  =0.0;  // Price of the deal
   datetime deal_time   =NULL; // Time of the deal
//--- If the position history is obtained
   if(HistorySelect(pos.time,TimeCurrent()))
     {
      //--- Get the number of deals in the obtained list
      total=HistoryDealsTotal();
      //--- Iterate over all the deals in the obtained list
      for(int i=0; i<total; i++)
        {
         //--- Get the price of the deal
         deal_price=HistoryDealGetDouble(HistoryDealGetTicket(i),DEAL_PRICE);
         //--- Get the symbol of the deal
         deal_symbol=HistoryDealGetString(HistoryDealGetTicket(i),DEAL_SYMBOL);
         //--- Get the time of the deal
         deal_time=(datetime)HistoryDealGetInteger(HistoryDealGetTicket(i),DEAL_TIME);
         //--- If the time of the deal equals the position opening time, 
         //    and if the symbol of the deal and the current symbol are the same, exit the loop
         if(deal_time==pos.time && deal_symbol==_Symbol)
            break;
        }
     }
//---
   return(deal_price);
  }

Buradaki prensip önceki fonksiyondaki ile aynıdır. Pozisyon açılış noktasından itibaren geçmişi alırız ve ardından her yinelemede işlemin zamanını ve pozisyon açılış zamanını kontrol ederiz. İşlemin fiyatıyla birlikte, işlemin sembol adını ve zamanını elde ederiz. İlk işlem, işlem zamanı pozisyon açılış zamanı ile kesiştiğinde belirlenir. Fiyatı zaten ilgili değişkene atanmış olduğundan, yalnızca değeri döndürmemiz gerekir.

Devam edelim. Bazen, mevcut pozisyondaki son işlemin fiyatını elde etmeniz gerekebilir. Bunun için, bir CurrentPositionLastDealPrice() fonksiyonu oluşturacağız:

//+------------------------------------------------------------------+
//| Returning the price of the last deal in the current position     |
//+------------------------------------------------------------------+
double CurrentPositionLastDealPrice()
  {
   int    total       =0;   // Total deals in the selected history list
   string deal_symbol ="";  // Symbol of the deal 
   double deal_price  =0.0; // Price
//--- If the position history is obtained
   if(HistorySelect(pos.time,TimeCurrent()))
     {
      //--- Get the number of deals in the obtained list
      total=HistoryDealsTotal();
      //--- Iterate over all the deals in the obtained list from the last deal in the list to the first deal
      for(int i=total-1; i>=0; i--)
        {
         //--- Get the price of the deal
         deal_price=HistoryDealGetDouble(HistoryDealGetTicket(i),DEAL_PRICE);
         //--- Get the symbol of the deal
         deal_symbol=HistoryDealGetString(HistoryDealGetTicket(i),DEAL_SYMBOL);
         //--- If the symbol of the deal and the current symbol are the same, exit the loop
         if(deal_symbol==_Symbol)
            break;
        }
     }
//---
   return(deal_price);
  }

Bu sefer döngü, listedeki son işlem ile başlamıştır ve bu durumda genellikle gerekli işlem ilk döngü yinelemesinde tanımlanır. Ancak birkaç sembol üzerinde alım satım yaparsanız, döngü işlemin sembolü mevcut sembolle eşleşene kadar devam eder.

Mevcut pozisyon hacmi, POSITION_VOLUME standart tanımlayıcısı kullanılarak elde edilebilir. İlk pozisyon hacmini (ilk işlemin hacmi) bulmak için bir CurrentPositionInitialVolume() fonksiyonu oluşturacağız:

//+------------------------------------------------------------------+
//| Returning the initial volume of the current position             |
//+------------------------------------------------------------------+
double CurrentPositionInitialVolume()
  {
   int             total       =0;           // Total deals in the selected history list
   ulong           ticket      =0;           // Ticket of the deal
   ENUM_DEAL_ENTRY deal_entry  =WRONG_VALUE; // Position modification method
   bool            inout       =false;       // Flag of position reversal
   double          sum_volume  =0.0;         // Counter of the aggregate volume of all deals, except for the first one
   double          deal_volume =0.0;         // Volume of the deal
   string          deal_symbol ="";          // Symbol of the deal 
   datetime        deal_time   =NULL;        // Deal execution time
//--- If the position history is obtained
   if(HistorySelect(pos.time,TimeCurrent()))
     {
      //--- Get the number of deals in the obtained list
      total=HistoryDealsTotal();
      //--- Iterate over all the deals in the obtained list from the last deal in the list to the first deal
      for(int i=total-1; i>=0; i--)
        {
         //--- If the order ticket by its position is obtained, then...
         if((ticket=HistoryDealGetTicket(i))>0)
           {
            //--- Get the volume of the deal
            deal_volume=HistoryDealGetDouble(ticket,DEAL_VOLUME);
            //--- Get the position modification method
            deal_entry=(ENUM_DEAL_ENTRY)HistoryDealGetInteger(ticket,DEAL_ENTRY);
            //--- Get the deal execution time
            deal_time=(datetime)HistoryDealGetInteger(ticket,DEAL_TIME);
            //--- Get the symbol of the deal
            deal_symbol=HistoryDealGetString(ticket,DEAL_SYMBOL);
            //--- When the deal execution time is less than or equal to the position opening time, exit the loop
            if(deal_time<=pos.time)
               break;
            //--- otherwise calculate the aggregate volume of deals by the position symbol, except for the first one
            if(deal_symbol==_Symbol)
               sum_volume+=deal_volume;
           }
        }
     }
//--- If the position modification method is a reversal
   if(deal_entry==DEAL_ENTRY_INOUT)
     {
      //--- If the position volume has been increased/decreased
      //    I.e. the number of deals is more than one
      if(fabs(sum_volume)>0)
        {
         //--- Current volume minus the volume of all deals except for the first one
         double result=pos.volume-sum_volume;
         //--- If the resulting value is greater than zero, return the result, otherwise return the current position volume         
         deal_volume=result>0 ? result : pos.volume;
        }
      //--- If there are no more deals, other than the entry,
      if(sum_volume==0)
         deal_volume=pos.volume; // return the current position volume
     }
//--- Return the initial position volume
   return(NormalizeDouble(deal_volume,2));
  }

Bu fonksiyon öncekilerden daha karmaşıktır. Yanlış değere yol açabilecek tüm olası durumları dikkate almaya çalıştım. Dikkatli bir test herhangi bir sorun ortaya koymadı. Kodda verilen ayrıntılı yorumlar konuyu anlamanıza yardımcı olacaktır.

Pozisyon süresini döndüren bir fonksiyonun olması da faydalı olacaktır. Bunu, kullanıcının döndürülen değerin uygun biçimini seçmesine olanak sağlayacak şekilde ayarlayacağız: saniye, dakika, saat veya gün. Bunun için, başka bir numaralandırma oluşturalım:

//--- Position duration
enum ENUM_POSITION_DURATION
  {
   DAYS     = 0, // Days
   HOURS    = 1, // Hours
   MINUTES  = 2, // Minutes
   SECONDS  = 3  // Seconds
  };

Aşağıda, ilgili hesaplamaların tamamından sorumlu CurrentPositionDuration() fonksiyon kodu yer almaktadır:

//+------------------------------------------------------------------+
//| Returning the duration of the current position                   |
//+------------------------------------------------------------------+
ulong CurrentPositionDuration(ENUM_POSITION_DURATION mode)
  {
   ulong     result=0;   // End result
   ulong     seconds=0;  // Number of seconds
//--- Calculate the position duration in seconds
   seconds=TimeCurrent()-pos.time;
//---
   switch(mode)
     {
      case DAYS      : result=seconds/(60*60*24);   break; // Calculate the number of days
      case HOURS     : result=seconds/(60*60);      break; // Calculate the number of hours
      case MINUTES   : result=seconds/60;           break; // Calculate the number of minutes
      case SECONDS   : result=seconds;              break; // No calculations (number of seconds)
      //---
      default        :
         Print(__FUNCTION__,"(): Unknown duration mode passed!");
         return(0);
     }
//--- Return result
   return(result);
  }

Pozisyon özelliklerinin görüntülendiği bilgi paneli için bir CurrentPositionDurationToString() fonksiyonu oluşturalım. Fonksiyon, saniye cinsinden pozisyon süresini kullanıcının kolayca anlayabileceği bir biçime dönüştürür. Saniye sayısı fonksiyona aktarılacak ve fonksiyon sırası geldiğinde gün, saat, dakika ve saniye cinsinden pozisyon süresini içeren bir dize döndürecektir:

//+------------------------------------------------------------------+
//| Converting the position duration to a string                     |
//+------------------------------------------------------------------+
string CurrentPositionDurationToString(ulong time)
  {
//--- A dash if there is no position
   string result="-";
//--- If the position exists
   if(pos.exists)
     {
      //--- Variables for calculation results
      ulong days=0;
      ulong hours=0;
      ulong minutes=0;
      ulong seconds=0;
      //--- 
      seconds=time%60;
      time/=60;
      //---
      minutes=time%60;
      time/=60;
      //---
      hours=time%24;
      time/=24;
      //---
      days=time;
      //--- Generate a string in the specified format DD:HH:MM:SS
      result=StringFormat("%02u d: %02u h : %02u m : %02u s",days,hours,minutes,seconds);
     }
//--- Return result
   return(result);
  }

Her şey ayarlandı ve şimdi hazır. Yukarıdaki değişikliklerin tamamına göre değiştirilmesi gereken GetPositionProperties() ve GetPropertyValue() fonksiyon kodlarını vermeyeceğim. Serinin önceki tüm makalelerini okursanız, bunu kendi başınıza yapmakta zorluk çekmemeniz lazım. Yine de, kaynak kod dosyası makaleye eklenmiştir.

Bunun sonucunda, bilgi paneli aşağıda gösterildiği gibi görünmelidir:

Şekil 7. Tüm pozisyon parametrelerinin bilgi panelinde gösterimi

Şekil 7. Tüm pozisyon özelliklerinin bilgi panelinde gösterimi.

Dolayısıyla, şimdi pozisyon özelliklerini elde etmek için fonksiyon kitaplığımız var ve muhtemelen gelecekteki makalelerde gerektiğinde ve gerektiği şekilde bunun üzerine çalışmaya devam edeceğiz.


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

Bir deney olarak, Uzman Danışmanın parametrelerini optimize etmeye çalışalım. Şu anda elimizdeki şey henüz tam özellikli bir alım satım sistemi olarak adlandırılamasa da, elde edeceğimiz sonuç bazı konularda gözlerimizi açacak ve alım satım sistemleri geliştiricileri olarak tecrübemizi artıracaktır.

Aşağıda gösterilen Strateji Test Cihazı ayarlarını yapacağız:

Şekil 8. Parametre optimizasyonu için Strateji Test Cihazı ayarları

Şekil 8. Parametre optimizasyonu için Uzman Danışman ayarları

Uzman Danışmanın harici parametrelerinin ayarları aşağıdaki şekilde olmalıdır:

Şekil 9. Optimizasyon için Uzman Danışman parametre ayarları

Şekil 9. Optimizasyon için Uzman Danışman parametre ayarları.

Optimizasyon sonrasında, elde edilen sonuçları maksimum kurtarma faktörüne göre sıralarız:

Şekil 10. Maksimum kurtarma faktörüne göre sıralanmış sonuçlar

Şekil 10. Maksimum kurtarma faktörüne göre sıralanmış sonuçlar.

Şimdi Kurtarma Faktörü değeri 4,07'ye eşit olacak şekilde en üstteki parametre setini test edelim. Optimizasyon EURUSD için yapılmış olmasına rağmen, birçok sembol için olumlu sonuçlar görebiliriz:

EURUSD için sonuçlar:

Şekil 11. EURUSD için sonuçlar

Şekil 11. EURUSD için sonuçlar.

AUDUSD için sonuçlar:

Şekil 12. AUDUSD için sonuçlar

Şekil 12. AUDUSD için sonuçlar.

NZDUSD için sonuçlar:

Şekil 13. NZDUSD için sonuçlar

Şekil 13. NZDUSD için sonuçlar.


Sonuç

Hemen hemen her fikir geliştirilebilir ve iyileştirilebilir. Her alım satım sistemi, kusurlu diye reddedilmeden önce çok dikkatli bir şekilde test edilmelidir. Gelecek makalelerde, hemen hemen her alım satım sistemini özelleştirmede ve uyarlamada çok olumlu bir rol oynayabilecek çeşitli mekanizmalara ve şemalara göz atacağız.

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

Ekli dosyalar |
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
Bu makalede, MQL5 Tarif Defteri serisinin önceki makalelerinde üzerinde çalıştığımız Uzman Danışmanı değiştirmeye devam edeceğiz. Bu sefer Uzman Danışman, değerleri pozisyon açma koşullarını kontrol etmek için kullanılacak göstergeler ile güçlendirilecektir. 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.
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.
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 Parametrelerini MetaTrader 5 Strateji Test Cihazında Analiz Etme MQL5 Tarif Defteri Pozisyon Parametrelerini MetaTrader 5 Strateji Test Cihazında Analiz Etme
"MQL5 Tarif Defteri: Özel Bilgi Panelindeki Pozisyon Özellikleri" adlı önceki makalesinden Uzman Danışmanın değiştirilmiş bir versiyonunu sunacağız. Ele alacağımız sorunlardan bazıları, çubuklardan veri alma, mevcut sembol üzerindeki yeni çubuk olaylarını kontrol etme, Standart Kitaplığın bir alım satım sınıfını bir dosyaya ekleme, alım satım sinyallerini aramak için bir fonksiyon ve alım satım işlemlerini yürütmek için bir fonksiyon oluşturmanın yanı sıra OnTrade() fonksiyonundaki alım satım olaylarını belirlemeyi içerir.