English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
Bir Diğer MQL5 OOP Sınıfı

Bir Diğer MQL5 OOP Sınıfı

MetaTrader 5Örnekler | 13 Ocak 2022, 16:38
183 0
laplacianlab
[Silindi]

Giriş

Gerçekten de işe yarayan tam bir nesne yönelimli EA oluşturmak, benim düşünceme göre, birçok becerinin bir araya gelmesini gerektiren zorlayıcı bir görevdir: mantıksal akıl yürütme, farklı biçimde düşünme, analiz ve sentez yeteneği, hayal gücü vb. Çözmemiz gereken otomatik alım satım sisteminin bir satranç oyunu olduğunu düşünürsek, satranç stratejisi alım satım fikridir. Satranç stratejisinin taktikler aracılığıyla yürütülmesi ise teknik göstergeler, grafik rakamları, temel ekonomik fikirler ve kavramsal aksiyomların kullanımı ile robotun programlanması olacaktır.

Raffaello Sanzio'ya ait Atina Okulu Ayrıntısı

Şekil 1. Raffaello Sanzio'ya ait Atina Okulu Ayrıntısı. Bu resimde filozof Platon ve Aristoteles'i derin bir tartışma içinde görüyoruz.
Plato burada kavramsal dünyayı ve Aristoteles ise deneysel dünyayı temsil etmektedir.

Bu alıştırmanın zor olduğunun farkındayım. Bir OO EA'nın programlanması aşırı zor değildir, ancak uygulama geliştirmede çok az deneyime sahip kişiler için belirli bir derecede zor olduğu da doğrudur. Diğer herhangi bir disiplinde olduğu gibi, bunun da sebebi tecrübe eksikliğidir, bu nedenle size bu konuyu anlayacağınızdan emin olduğum belirli bir örnek üzerinden öğretmeye çalışacağım. OOP kavramlarını ele alma konusunda kendinize güvenmiyorsanız cesaretiniz kırılmasın, söz gelimi ilk beş EA'nızı uyguladıktan sonra her şey size çok daha kolay gelecek. Şimdilik hiçbir şeyi sıfırdan oluşturmanız gerekmiyor, sadece burada anlattıklarımı iyi anlayın!

Bir alım satım sistemini tasarlama ve uygulamayı içeren bütün süreç, birkaç kişi tarafından gerçekleştirildiğinde, iletişim sorunu ortaya çıkarsa da, birçok anlamda basitleştirilebilir. Yatırım stratejisini tasarlayan kişinin, kararlar ile ilgilenen programcının ilgilendiği programlama kavramlarını ele alması gerekmediğinden bahsediyorum. Ve MQL5 geliştiricisi, ilk başta, müşterilerinin alım satım stratejisinin bazı önemli yönlerini anlamayabilir.

Bu, yazılım mühendisliğinde, Scrum, test Güdümlü Geliştirme (TDD), Ekstrem Programlama (XP) vb. gibi birçok yazılım geliştirme metodolojisinin oluşturulmasına yol açan klasik bir sorundur. Dildeki tuzakların farkında olmak çok önemlidir. Bu arada, bilginize sunmak isterim ki, Wikipedia'da belirtildiğine göre, "Yazılım mühendisliğinde yazılım geliştirme metodolojisi veya sistem geliştirme metodolojisi bir bilgi sistemi geliştirme sürecini yapılandırmak, planlamak ve kontrol etmek için kullanılan bir çerçevedir."

Başarılı alım satım fikirlerini hızlı bir şekilde tasarlayabileceğimizi ve uygulayabileceğimizi varsayacağız. Aynı zamanda, müşterimizin düşündüğü alım satım sisteminin halihazırda iyi tanımlandığı ve herkes tarafından anlaşıldığı yinelemeli bir geliştirme sürecinin sonunda olduğumuzu da varsayabiliriz. Nasıl tercih ederseniz. Bu arada, şu andan itibaren bu metinde MQL5 Programlama Makaleleri içinde mevcut bazı eğitsel makalelere referansta bulunacağım, böylece bu uygulamayı başarılı bir şekilde gerçekleştirmek için gerektiğinde bazı fikirleri hızlıca kontrol edebilecek ve hatırlayabileceksiniz. Hazır mısınız?


1. Yeni Paradigmayı Benimsemedeki İlk Adımlarınız


1.1. Forex EA'larınızı Programlarken OOP Neden İyidir?

Bu noktada neden böyle bir şey yapmak zorunda olduğunuzu merak ediyor olabilirsiniz. İlk olarak size OOP'nin mecburi olmadığını söylemek isterim. Bununla birlikte, otomatik alım satım sistemlerini programlama bilginizi ileri taşımak için bir OOP kişisi olmanız oldukça tavsiye edilir.

Uygulama geliştirmenin klasik yolu olan prosedürel programlamanın şu dezavantajları vardır:

  • Problemleri modellemeyi zorlaştırır. Bu eski paradigma altında, ana problemin çözümü, bunu fonksiyonlar ve prosedürler olmak üzere fonksiyonel modüller tarafından çözülen daha basit alt problemlere bölmek için indirgenir.
  • Kodun yeniden kullanılmasını zorlaştırır, bu ise maliyeti, güvenilirliği, esnekliği ve bakımı zorlaştırır.

Yeni nesne yönelimli stil ile kodun yeniden kullanımı daha kolaydır. Bu çok önemli! Birçok uzman, kodu yeniden kullanmanın, yazılım geliştirmenin birçok probleminin asıl çözümü olduğuna inanmaktadır.

Bu noktada, soyut veri türlerinden (ADT) bahsetmeliyiz. OOP, ADT oluşturmayı sağlar. Bir ADT, tüm programlama dillerinde bulunan klasik veri türü kavramının bir soyutlamasıdır. Ana kullanımı, uygulamaların veri etki alanlarını rahat bir şekilde tanımlamaktır. Include\Arrays\Array.mqh, Include\Arrays\List.mqh ve Include\Arrays\Tree.mqh MQL5 soyut veri türlerinin bazı örnekleridir.

Kısaca, nesne yönelimli programlama paradigması, kodu yeniden kullanımı, güvenilirliği, esnekliği ve bakım kolaylığından faydalanmanız için uygulamalarınızı kavramsal bir düzeyde tasarlamanızı ister.

1.2. Bir Kavramsal Akıl Yürütücü müsünüz? UML İmdadınıza Yetişiyor

UML kavramını hiç duydunuz mu? UML, Birleşik Modelleme Dili anlamına gelir. Nesne yönelimli sistemlerin tasarımı için bir grafik dilidir. Biz insanların sistemlerimizi önce analiz aşamasında düşünmemiz ve sonra bunları bir programlama dili ile kodlamamız gerekir. Geliştiriciler için yukarıdan aşağıya gitmek akıllıcadır. Yine de, bir analist olarak tecrübem, birkaç nedenden ötürü bazen bunun bazen mümkün olmadığını söylüyor: uygulamanın çok kısa sürede yapılmasının gerekmesi, ekipte UML bilgisini hızlıca uygulayabilecek kimsenin bulunmaması veya belki takımdaki bazı kişilerin UML'nin bazı kısımlarını bilmemesi.

Bana göre UML, kendinizi rahat hissediyorsanız ve projedeki koşullar uygunsa kullanabileceğiniz iyi bir analiz aracıdır. UML konusunu keşfetmekle ilgileniyorsanız lütfen Uzman Danışman UML Araçları Kullanılarak Nasıl Geliştirilir? makalesini okuyun. Bu makale biraz bunaltıcı olabilir, ancak profesyonel yazılım mühendislerinin analizlerini nasıl yaptıklarına dair büyük resmi elde etme görevi görür. UML'yi tamamen anlamak için birkaç haftalık bir kursu tamamlamanız gerekir! Şimdilik UML'nin ne olduğunu bilmenizde sorun yok. Tecrübelerime göre bu analiz aracı, gerçek dünyadaki çeşitli koşullar nedeniyle tüm yazılım projelerinde her zaman kullanılmıyor.

UML logosu

Şekil 2. UML logosu.


1.3. Merhaba Dünya! İlk OO Sınıfınız

Nesne yönelimli programlama konusunda tamamen acemiyseniz, ilk olarak MQL5 Referansı içinde bulunan resmi belgeleri okumanızı ve ardından temel noktaları öğrenmek için MQL5 Nesne Yönelimli Programlama Yaklaşımını Kullanarak bir Uzman Danışman Yazma belgesine bakmanızı tavsiye ederim. Lütfen diğer materyallerle birlikte bu okumaları tamamladığınızdan emin olun. Şu andan itibaren, halihazırda biraz OOP bildiğinizi varsayıyorum, bu yüzden MQL5'te aşağıdaki şekilde olan Kişi (Person) sınıfının klasik örneğini kolayca anlayacaksınız:

//+------------------------------------------------------------------+
//| CPerson Class                                                    |
//+------------------------------------------------------------------+
class CPerson
  {
protected:
   string            m_first_name;
   string            m_surname;
   datetime          m_birth;

public:
   //--- Constructor and destructor methods
                     CPerson(void);
                    ~CPerson(void);
   //--- Getter methods
   string            GetFirstName(void);
   string            GetSurname(void);
   datetime          GetBirth(void);
   //--- Setter methods
   void              SetFirstName(string first_name);
   void              SetSurname(string surname);
   void              SetBirth(datetime birth);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CPerson::CPerson(void)
  {
   Alert("Hello world! I am run when an object of type CPerson is created!");
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CPerson::~CPerson(void)
  {
   Alert("Goodbye world! I am run when the object is destroyed!");
  }
//+------------------------------------------------------------------+
//| GetFirstName                                                     |
//+------------------------------------------------------------------+
string CPerson::GetFirstName(void)
  {
   return m_first_name;
  }
//+------------------------------------------------------------------+
//| GetSurname                                                       |
//+------------------------------------------------------------------+
string CPerson::GetSurname(void)
  {
   return m_surname;
  }
//+------------------------------------------------------------------+
//| GetBirth                                                         |
//+------------------------------------------------------------------+
datetime CPerson::GetBirth(void)
  {
   return m_birth;
  }
//+------------------------------------------------------------------+
//| SetFirstName                                                     |
//+------------------------------------------------------------------+
void CPerson::SetFirstName(string first_name)
  {
   m_first_name=first_name;
  }
//+------------------------------------------------------------------+
//| SetSurname                                                       |
//+------------------------------------------------------------------+
void CPerson::SetSurname(string surname)
  {
   m_surname=surname;
  }
//+------------------------------------------------------------------+
//| SetBirth                                                         |
//+------------------------------------------------------------------+
void CPerson::SetBirth(datetime birth)
  {
   m_birth=birth;
  }
//+------------------------------------------------------------------+

Aşağıdakiler, kalite kodu yazmaya takıntılı saf geliştiriciler içindir. MQL5 Programlama Makaleleri içinde bulunan bazı örneklerin ve Code Base içinde bulunan diğer birçok yazılımın aksine, yukarıdaki sınıf, MQL5 çerçevesini kodlamak için MetaQuotes Software Corp.'un uyguladığı ile aynı programlama uygulamalarını kullanmaz. Kodunuzu aynı MetaQuotes'un yaptığı gibi yazmanızı tavsiye ederim. Bu arada, OOP MQL5 programlarındaki uygulamalar hakkında başlıklı konu başlığı bu konuyu içerir.

Özet olarak, Person.mqh yazmada uygulanan bazı önemli uygulamalar şunlardır:

  • CPerson sınıf adı C büyük harfi ile başlar.
  • Yöntem adlarında orta harf büyük harflidir ve bunlar büyük harf ile başlar; örneğin GetFirstName, SetSurname vb.
  • Korunan özelliklerden önce m_ ön eki gelir; örneğin m_first_name, m_surname ve m_birth.
  • Bu korunmuş sözcük, sınıfın kendisinin içindeki sınıf üyelerine atıfta bulunmak için kullanılmaz.

Lütfen bazı MQL5 çerçeve dosyalarına, örneğin Include\Arrays\Array.mqh, Include\Arrays\List.mqh, Include\Trade\Trade.mqh bakın ve orijinal MQL5 kodunun nasıl yazıldığını görün.


2. İlk Nesne Yönelimli EA'mızı Programlayalım


2.1. Alım Satım Sistemi Fikri

Alım satım fikrimiz basittir: "Değişken piyasaların kısa trendleri neredeyse rastgeledir". İşte bu! Bu durum, bazı koşullar altında bazı uzmanlar tarafından gözlenmiştir. Eğer bu hipotez doğruysa, Forex robotumuz zorunlu olarak çalışmalıdır. Bir grafikte rastgele bir nokta verildiğinde, bir sonraki hareket elbette yukarı da aşağı da gidebilir, bunu bilmiyoruz. Konu şu ki, yerleşik SL ve TP seviyeleri arasındaki fark yeterince küçükse, bu durumda bu fark mutlak anlamda anlamlı değildir ve dolayısıyla matematiksel beklentiye ulaşmışızdır. Bu sistem yalnızca matematiksel beklentiyi çalıştırmasına izin verecektir. Bu makaledeki EA kodunu elde ettiğinizde ve geriye dönük testi çalıştırdığınızda, bunun çok basit bir para yönetimi politikası gerektirdiğini göreceksiniz.


2.2. Robotun OOP İskeleti

Bu bölümde, yukarıdaki stratejiyi nesne yönelimli programlamanın gerektirdiği soyut akıl yürütme ile geliştiriyoruz. Bu durumda, neden EA'mızı canlı bir varlıkmış gibi düşünmekle başlamıyoruz? Bu vizyon kapsamında, Forex makinemiz üç ana bölümden oluşabilir: bir beyin, evrim olarak adlandırabileceğimiz bir şey ve bir grafik.

Beyin, robotun, çalışması için gerekli verileri içeren, salt okunur bellek (ROM) gibi bir parçasıdır. Grafik, robotun üzerinde çalıştığı grafiği öykünen bilgi parçasıdır. Son olarak, evrim ise, robotun belirli bir andaki durumu, gerçekleştirilen işlemlerin geçmişi vb. gibi geçici bilgileri içeren bir veri parçasıdır. Sağlık sektörü için bir uygulama geliştirmemiz gerektiği için bu, sanki bir insanı organları ile tasarlıyormuşuz gibi, Frankenstein gibi, bir şeydir. Bu bağlamda her bir organ, bütünün diğer parçalarıyla ilişkili benzersiz bir anlamsal kavramdır.

İlk olarak, özel öğelerimizi saklamak için MQL5\Include\Mine klasörünü oluşturalım. Bu, sadece kodunuzu organize etmek için bir fikir. Geliştirmelerinizde bunu yapabileceğinizi bilmeniz iyidir, ancak tabi ki buna mecbur değilsiniz. Daha sonra oluşturduğumuz numaralandırmaları saklamak için MQL5\Include\Mine\Enums.mqh dosyasını oluşturacağız:

//+------------------------------------------------------------------+
//| Status enumeration                                               |
//+------------------------------------------------------------------+
enum ENUM_STATUS_EA
  {
   BUY,
   SELL,
   DO_NOTHING
  };
//+------------------------------------------------------------------+
//| Lifetime enumeration                                             |
//+------------------------------------------------------------------+
enum ENUM_LIFE_EA
  {
   HOUR,
   DAY,
   WEEK,
   MONTH,
   YEAR
  };
//+------------------------------------------------------------------+

Bundan sonra, ExpertSimpleRandom.mq5 olarak adlandırılacak EA embriyomuzu oluşturmanın zamanı! Lütfen MQL5\Experts\SimpleRandom klasörünü oluşturun ve ardından bunun içinde aşağıdaki kodu içeren ExpertSimpleRandom.mq5 dosyasını oluşturun:

//+------------------------------------------------------------------+
//|                                           ExpertSimpleRandom.mq5 |
//|                               Copyright © 2013, Jordi Bassagañas |
//+------------------------------------------------------------------+

#property copyright     "Copyright © 2013, laplacianlab"
#property link          "https://www.mql5.com/tr/articles"
#property version       "1.00"

#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\PositionInfo.mqh>
#include <Indicators\Indicators.mqh>
#include <Mine\Enums.mqh>
#include <..\Experts\SimpleRandom\CSimpleRandom.mqh>

input int               StopLoss;
input int               TakeProfit;
input double            LotSize;
input ENUM_LIFE_EA      TimeLife;

MqlTick tick;
CSimpleRandom *SR=new CSimpleRandom(StopLoss,TakeProfit,LotSize,TimeLife);
//+------------------------------------------------------------------+
//| Initialization function                                          |
//+------------------------------------------------------------------+
int OnInit(void)
  {
   SR.Init();
   return(0);
  }
//+------------------------------------------------------------------+
//| Deinitialization function                                        |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   SR.Deinit();
   delete(SR);
  }
//+------------------------------------------------------------------+
//| OnTick event function                                            |
//+------------------------------------------------------------------+
void OnTick()
  {
   SymbolInfoTick(_Symbol,tick);
   SR.Go(tick.ask,tick.bid);
  }
//+------------------------------------------------------------------+

Bu, olası birçok yaklaşımdan yalnızca biridir. Tüm bunlar, temelde OOP'nin MQL5'te nasıl çalıştığını göstermek içindir. Gördüğünüz gibi, Uzman Danışmanın ana sınıfı CSimpleRandom.mqh olarak adlandırılmıştır, lütfen bunu MQL5\Experts\SimpleRandom\CSimpleRandom.mqh içine kaydedin:

//+------------------------------------------------------------------+
//|                                           ExpertSimpleRandom.mq5 |
//|                               Copyright © 2013, Jordi Bassagañas |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
#include <Mine\Enums.mqh>
#include <..\Experts\SimpleRandom\CBrain.mqh>
#include <..\Experts\SimpleRandom\CEvolution.mqh>
#include <..\Experts\SimpleRandom\CGraphic.mqh>
//+------------------------------------------------------------------+
//| CSimpleRandom Class                                              |
//+------------------------------------------------------------------+
class CSimpleRandom
  {
protected:
   CBrain           *m_brain;
   CEvolution       *m_evolution;
   CGraphic         *m_graphic;
   CTrade           *m_trade;
   CPositionInfo    *m_positionInfo;
public:
   //--- Constructor and destructor methods
                     CSimpleRandom(int stop_loss,int take_profit,double lot_size,ENUM_LIFE_EA time_life);
                    ~CSimpleRandom(void);
   //--- Getter methods
   CBrain           *GetBrain(void);
   CEvolution       *GetEvolution(void);
   CGraphic         *GetGraphic(void);
   CTrade           *GetTrade(void);
   CPositionInfo    *GetPositionInfo(void);
   //--- Specific methods of CSimpleRandom
   bool              Init();
   void              Deinit(void);
   bool              Go(double ask,double bid);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CSimpleRandom::CSimpleRandom(int stop_loss,int take_profit,double lot_size,ENUM_LIFE_EA time_life)
  {
   int lifeInSeconds;

   switch(time_life)
     {
      case HOUR:

         lifeInSeconds=3600;

         break;

      case DAY:

         lifeInSeconds=86400;

         break;

      case WEEK:

         lifeInSeconds=604800;

         break;

      case MONTH:

         lifeInSeconds=2592000;

         break;

         // One year

      default:

         lifeInSeconds=31536000;

         break;
     }

   m_brain=new CBrain(TimeLocal(),TimeLocal()+lifeInSeconds,lot_size,stop_loss,take_profit);
   m_evolution=new CEvolution(DO_NOTHING);
   m_graphic=new CGraphic(_Symbol);
   m_trade=new CTrade();
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CSimpleRandom::~CSimpleRandom(void)
  {
   delete(m_brain);
   delete(m_evolution);
   delete(m_graphic);
   delete(m_trade);
  }
//+------------------------------------------------------------------+
//| GetBrain                                                         |
//+------------------------------------------------------------------+
CBrain *CSimpleRandom::GetBrain(void)
  {
   return m_brain;
  }
//+------------------------------------------------------------------+
//| GetBrain                                                         |
//+------------------------------------------------------------------+
CEvolution *CSimpleRandom::GetEvolution(void)
  {
   return m_evolution;
  }
//+------------------------------------------------------------------+
//| GetGraphic                                                       |
//+------------------------------------------------------------------+
CGraphic *CSimpleRandom::GetGraphic(void)
  {
   return m_graphic;
  }
//+------------------------------------------------------------------+
//| GetTrade                                                         |
//+------------------------------------------------------------------+
CTrade *CSimpleRandom::GetTrade(void)
  {
   return m_trade;
  }
//+------------------------------------------------------------------+
//| GetPositionInfo                                                  |
//+------------------------------------------------------------------+
CPositionInfo *CSimpleRandom::GetPositionInfo(void)
  {
   return m_positionInfo;
  }
//+------------------------------------------------------------------+
//| CSimpleRandom initialization                                     |
//+------------------------------------------------------------------+
bool CSimpleRandom::Init(void)
  {
// Initialization logic here...
   return true;
  }
//+------------------------------------------------------------------+
//| CSimpleRandom deinitialization                                   |
//+------------------------------------------------------------------+
void CSimpleRandom::Deinit(void)
  {
// Deinitialization logic here...
   delete(m_brain);
   delete(m_evolution);
   delete(m_graphic);
   delete(m_trade);
  }
//+------------------------------------------------------------------+
//| CSimpleRandom Go                                                 |
//+------------------------------------------------------------------+
bool CSimpleRandom::Go(double ask,double bid)
  {
   double tp;
   double sl;

   int coin=m_brain.GetRandomNumber(0,1);

// Is there any open position?     

   if(!m_positionInfo.Select(_Symbol))
     {
      // If not, we open one

      if(coin==0)
        {
         GetEvolution().SetStatus(BUY);
        }
      else
        {
         GetEvolution().SetStatus(SELL);
        }
     }

// If so, let it work the mathematical expectation.

   else GetEvolution().SetStatus(DO_NOTHING);

   switch(GetEvolution().GetStatus())
     {
      case BUY:

         tp = ask + m_brain.GetTakeProfit() * _Point;
         sl = bid - m_brain.GetStopLoss() * _Point;

         GetTrade().PositionOpen(_Symbol,ORDER_TYPE_BUY,m_brain.GetSize(),ask,sl,tp);

         break;

      case SELL:

         sl = ask + m_brain.GetStopLoss() * _Point;
         tp = bid - m_brain.GetTakeProfit() * _Point;

         GetTrade().PositionOpen(_Symbol,ORDER_TYPE_SELL,m_brain.GetSize(),bid,sl,tp);

         break;

      case DO_NOTHING:

         // Nothing...

         break;
     }

// If there is some error we return false, for now we always return true  

   return(true);
  }
//+------------------------------------------------------------------+


2.3. CSimpleRandom'ı Karmaşık Türdeki Nesnelere Bağlama

CBrain, CEvolution ve CGraphic türünde özel nesnelerin CSimpleRandom'a nasıl bağlandığını unutmayın.

İlk olarak karşılık gelen korunan özellikleri tanımlıyoruz:

protected:
   CBrain           *m_brain;
   CEvolution       *m_evolution;
   CGraphic         *m_graphic; 

Ve hemen ardından bu nesneleri oluşturucu içinde örneklendiriyoruz:

m_brain=new CBrain(TimeLocal(), TimeLocal() + lifeInSeconds, lot_size, stop_loss, take_profit);         
m_evolution=new CEvolution(DO_NOTHING);      
m_graphic=new CGraphic(_Symbol);

Yaptığımız şey, resmi belgelerin Nesne İşaretçileri içinde açıkladığı gibi karmaşık türde nesneleri dinamik olarak oluşturmaktır. Bu plan ile, CBrain, CEvolution ve CGraphic fonksiyonelliğine doğrudan CSimpleRandom'dan erişebiliriz. Örneğin ExpertSimpleRandom.mq5'te aşağıdaki kodu çalıştırabiliriz:

//+------------------------------------------------------------------+
//| OnTick event function                                            |
//+------------------------------------------------------------------+
void OnTick()
   {              
      // ...
      
      int randNumber=SR.GetBrain().GetRandomNumber(4, 8);

      // ...          
  }

Bu bölümü sonlandırmak için şimdi CBrain, CEvolution ve CGraphic kodunu yazıyorum. SimpleRandom'u geriye dönük test etmek için gerekli olmadığından dolayı kodlanmamış bazı parçalar olduğunu lütfen unutmayın. Bu sınıfların eksik kısımlarını kodlamanız size alıştırma olarak bırakılmıştır, bunları dilediğiniz gibi geliştirebilirsiniz.  Örneğin, arkasındaki fikir baştan robotun faaliyetini sonlandıracağı tarihi bilmek olan m_death aslında kullanılmaz.

//+------------------------------------------------------------------+
//|                                               ExpertSimpleRandom |
//|                               Copyright © 2013, Jordi Bassagaсas |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| CBrain Class                                                     |
//+------------------------------------------------------------------+
class CBrain
  {
protected:
   ENUM_TIMEFRAMES   m_period;               // period must always be initialized to PERIOD_M1 to fit the system's idea
   datetime          m_birth;               // The datetime in which the robot is initialized for the first time
   datetime          m_death;               // The datetime in which the robot will die
   double            m_size;                // The size of the positions
   int               m_stopLoss;            // Stop loss
   int               m_takeProfit;          // Take profit

public:
   //--- Constructor and destructor methods
                     CBrain(datetime birth,datetime death,double size,int stopLoss,int takeProfit);
                    ~CBrain(void);
   //--- Getter methods
   datetime          GetBirth(void);
   datetime          GetDeath(void);
   double            GetSize(void);
   int               GetStopLoss(void);
   int               GetTakeProfit(void);
   //--- Setter methods
   void              SetBirth(datetime birth);
   void              SetDeath(datetime death);
   void              SetSize(double size);
   void              SetStopLoss(int stopLoss);
   void              SetTakeProfit(int takeProfit);
   //--- Brain specific logic
   int               GetRandomNumber(int a,int b);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CBrain::CBrain(datetime birth,datetime death,double size,int stopLoss,int takeProfit)
  {
   MathSrand(GetTickCount());

   m_period=PERIOD_M1;
   m_birth=birth;
   m_death=death;
   m_size=size;
   m_stopLoss=stopLoss;
   m_takeProfit=takeProfit;
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CBrain::~CBrain(void)
  {
  }
//+------------------------------------------------------------------+
//| GetBirth                                                         |
//+------------------------------------------------------------------+
datetime CBrain::GetBirth(void)
  {
   return m_birth;
  }
//+------------------------------------------------------------------+
//| GetDeath                                                         |
//+------------------------------------------------------------------+
datetime CBrain::GetDeath(void)
  {
   return m_death;
  }
//+------------------------------------------------------------------+
//| GetSize                                                          |
//+------------------------------------------------------------------+
double CBrain::GetSize(void)
  {
   return m_size;
  }
//+------------------------------------------------------------------+
//| GetStopLoss                                                      |
//+------------------------------------------------------------------+
int CBrain::GetStopLoss(void)
  {
   return m_stopLoss;
  }
//+------------------------------------------------------------------+
//| GetTakeProfit                                                    |
//+------------------------------------------------------------------+
int CBrain::GetTakeProfit(void)
  {
   return m_takeProfit;
  }
//+------------------------------------------------------------------+
//| SetBirth                                                         |
//+------------------------------------------------------------------+
void CBrain::SetBirth(datetime birth)
  {
   m_birth=birth;
  }
//+------------------------------------------------------------------+
//| SetDeath                                                         |
//+------------------------------------------------------------------+
void CBrain::SetDeath(datetime death)
  {
   m_death=death;
  }
//+------------------------------------------------------------------+
//| SetSize                                                          |
//+------------------------------------------------------------------+
void CBrain::SetSize(double size)
  {
   m_size=size;
  }
//+------------------------------------------------------------------+
//| SetStopLoss                                                      |
//+------------------------------------------------------------------+
void CBrain::SetStopLoss(int stopLoss)
  {
   m_stopLoss=stopLoss;
  }
//+------------------------------------------------------------------+
//| SetTakeProfit                                                    |
//+------------------------------------------------------------------+
void CBrain::SetTakeProfit(int takeProfit)
  {
   m_takeProfit=takeProfit;
  }
//+------------------------------------------------------------------+
//| GetRandomNumber                                                  |
//+------------------------------------------------------------------+
int CBrain::GetRandomNumber(int a,int b)
  {
   return(a+(MathRand()%(b-a+1)));
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//|                                               ExpertSimpleRandom |
//|                               Copyright © 2013, Jordi Bassagaсas |
//+------------------------------------------------------------------+
#include <Indicators\Indicators.mqh>
#include <Mine\Enums.mqh>
//+------------------------------------------------------------------+
//| CEvolution Class                                                 |
//+------------------------------------------------------------------+
class CEvolution
  {
protected:
   ENUM_STATUS_EA    m_status;            // The current EA's status
   CArrayObj*        m_operations;        // History of the operations performed by the EA

public:
   //--- Constructor and destructor methods
                     CEvolution(ENUM_STATUS_EA status);
                    ~CEvolution(void);
   //--- Getter methods
   ENUM_STATUS_EA    GetStatus(void);
   CArrayObj        *GetOperations(void);
   //--- Setter methods
   void              SetStatus(ENUM_STATUS_EA status);
   void              SetOperation(CObject *operation);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CEvolution::CEvolution(ENUM_STATUS_EA status)
  {
   m_status=status;
   m_operations=new CArrayObj;
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CEvolution::~CEvolution(void)
  {
   delete(m_operations);
  }
//+------------------------------------------------------------------+
//| GetStatus                                                        |
//+------------------------------------------------------------------+
ENUM_STATUS_EA CEvolution::GetStatus(void)
  {
   return m_status;
  }
//+------------------------------------------------------------------+
//| GetOperations                                                    |
//+------------------------------------------------------------------+
CArrayObj *CEvolution::GetOperations(void)
  {
   return m_operations;
  }
//+------------------------------------------------------------------+
//| SetStatus                                                        |
//+------------------------------------------------------------------+
void CEvolution::SetStatus(ENUM_STATUS_EA status)
  {
   m_status=status;
  }
//+------------------------------------------------------------------+
//| SetOperation                                                     |
//+------------------------------------------------------------------+
void CEvolution::SetOperation(CObject *operation)
  {
   m_operations.Add(operation);
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//|                                           ExpertSimpleRandom.mq5 |
//|                               Copyright © 2013, Jordi Bassagaсas |
//+------------------------------------------------------------------+
#include <Trade\SymbolInfo.mqh>
#include <Arrays\ArrayObj.mqh>
//+------------------------------------------------------------------+
//| CGrapic Class                                                    |
//+------------------------------------------------------------------+
class CGraphic
  {
protected:
   ENUM_TIMEFRAMES   m_period;            // Graphic's timeframe
   string            m_pair;              // Graphic's pair
   CSymbolInfo*      m_symbol;            // CSymbolInfo object
   CArrayObj*        m_bars;              // Array of bars

public:
   //--- Constructor and destructor methods
                     CGraphic(string pair);
                    ~CGraphic(void);
   //--- Getter methods
   string            GetPair(void);
   CSymbolInfo      *GetSymbol(void);
   CArrayObj        *GetBars(void);
   //--- Setter methods
   void              SetPair(string pair);
   void              SetSymbol(CSymbolInfo *symbol);
   void              SetBar(CObject *bar);
  };
//+------------------------------------------------------------------+
//| Constuctor                                                       |
//+------------------------------------------------------------------+
CGraphic::CGraphic(string pair)
  {
   m_period=PERIOD_M1;
   m_pair=pair;
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CGraphic::~CGraphic(void)
  {
  }
//+------------------------------------------------------------------+
//| GetPair                                                          |
//+------------------------------------------------------------------+
string CGraphic::GetPair(void)
  {
   return m_pair;
  }
//+------------------------------------------------------------------+
//| GetSymbol                                                        |
//+------------------------------------------------------------------+
CSymbolInfo *CGraphic::GetSymbol(void)
  {
   return m_symbol;
  }
//+------------------------------------------------------------------+
//| GetBars                                                          |
//+------------------------------------------------------------------+
CArrayObj *CGraphic::GetBars(void)
  {
   return m_bars;
  }
//+------------------------------------------------------------------+
//| SetPair                                                          |
//+------------------------------------------------------------------+
void CGraphic::SetPair(string pair)
  {
   m_pair=pair;
  }
//+------------------------------------------------------------------+
//| SetSymbol                                                        |
//+------------------------------------------------------------------+
void CGraphic::SetSymbol(CSymbolInfo *symbol)
  {
   m_symbol=symbol;
  }
//+------------------------------------------------------------------+
//| SetBar                                                           |
//+------------------------------------------------------------------+
void CGraphic::SetBar(CObject *bar)
  {
   m_bars.Add(bar);
  }
//+------------------------------------------------------------------+

3. ExpertSimpleRandom.mq5'in Geriye Dönük Testi

Bu rastgele alım satım sistemi, beklendiği gibi yalnızca belirli zarar durdur ve kâr al seviyeleri için geçerlilik göstermiştir. Elbette bu kazanan SL/TP aralıkları tüm semboller için aynı değildir. Bunun nedeni, her sembolün belirli bir zamanda kendi kişiliğini göstermesi veya diğer bir deyişle, tüm döviz çiftlerinin geri kalanlara göre farklı hareket etmesidir. Bu yüzden, lütfen ExpertSimpleRandom.mq5'i gerçek bir ortamda çalıştırmadan önce bu seviyeleri geriye dönük testte belirleyin.

Bu makalede ortaya konan fikrin kazanan fikir gibi göründüğü bazı örnek verileri burada paylaşıyorum. Bu sonuca, ExpertSimpleRandom.mq5'i MetaTrader 5 Strateji Test Cihazında birçok kez çalıştırdıktan sonra varılabilir.

EURUSD, Ocak 2012 için bazı kazanan girişler:

  • StopLoss: 400
  • TakeProfit: 600
  • LotSize: 0,01
  • TimeLife: AY

Çalıştırma sayısı 1:

EURUSD, Ocak 2012

Çalıştırma sayısı 2:

EURUSD, Ocak 2012

Çalıştırma sayısı 3:

EURUSD, Ocak 2012


Sonuç

Nesne yönelimli programlamayı otomatik alım satım sistemlerimize uygulamayı öğrendik. Bunun için, ilk olarak bir mekanik alım satım stratejisi tanımlamamız gerekti. Bizim alım satım fikrimiz oldukça basit olmuştur: "Değişken piyasaların kısa trendleri neredeyse rastgeledir". Bu durum, bazı koşullar altında bazı uzmanlar tarafından gözlenmiştir.

Ardından, EA'mızı gerçek dünya koşullarında, sanki canlı bir varlıkmış gibi düşündük. Bu vizyon sayesinde, Forex makinemizin, bir beyin, evrim olarak adlandırabileceğimiz bir şey ve bir grafik olmak üzere üç ana bölümden oluşabileceğini gördük.

Ve son olarak, geriye dönük testi çalıştırmak için gerekli mantığı içeren sistemin uzman danışmanını programladık, Ocak 2012'de robotu birçok kez çalıştırdık ve birçok seferde sistemin kazandığını gördük. Bu sistemin arkasındaki fikrin doğru olduğu kanıtlandı, ancak basitliği nedeniyle sistemin etkinliği çok yüksek değildir.


MetaQuotes Ltd tarafından İngilizceden çevrilmiştir.
Orijinal makale: https://www.mql5.com/en/articles/703

Ekli dosyalar |
cbrain.mqh (5.64 KB)
cevolution.mqh (2.97 KB)
cgraphic.mqh (3.55 KB)
enums.mqh (0.92 KB)
csimplerandom.mqh (12.79 KB)
MQL5 Sihirbazı ve Hlaiman EA Oluşturucu Kullanarak Sinir Ağı EA'ları Oluşturma MQL5 Sihirbazı ve Hlaiman EA Oluşturucu Kullanarak Sinir Ağı EA'ları Oluşturma
Makale, MQL5 Sihirbazı ve Hlaiman EA Oluşturucu kullanarak otomatik sinir ağı EA'ları oluşturma yöntemini açıklar. Teorik bilgilerin tamamını öğrenmek ve kendi kodunuzu yazmak zorunda kalmadan nasıl kolay bir şekilde sinir ağları ile çalışmaya başlayabileceğinizi gösterir.
Hesaplamalar için OpenCL Nasıl Yüklenir ve Kullanılır? Hesaplamalar için OpenCL Nasıl Yüklenir ve Kullanılır?
MQL5'in OpenCL için yerel destek sağlamaya başlamasının üzerinden bir yıldan fazla zaman geçti. Ancak, Uzman Danışmanlarında, göstergelerinde veya betiklerinde paralel bilgi işlem kullanmanın gerçek değerini pek de çok kullanıcı görmemiştir. Bu makale, bu teknolojiyi MetaTrader 5 alım satım terminalinde kullanmayı deneyebilmeniz için OpenCL'yi bilgisayarınıza yüklemenize ve kurmanıza yardımcı olma görevi görür.
Otomatik Haber Yatırımcısı Oluşturma Otomatik Haber Yatırımcısı Oluşturma
Bu makale, size basit bir OO EA'nın sıfırdan nasıl oluşturulacağını gösteren ve nesne yönelimli programlamaya dair bazı ipuçları sağlayan bir diğer MQL5 OOP sınıfı makalesinin devamıdır. Bugün size haberlere göre alım satım yapabileceğiniz bir EA geliştirmek için gereken teknik temelleri göstereceğim. Amacım, size OOP hakkında fikir vermeye devam etmek ve ayrıca, bu makale dizisinde dosya sistemi ile çalışan yeni bir konuyu ele almak.
MQL5 Tarif Defteri: Tipik Grafik Olaylarını İşleme MQL5 Tarif Defteri: Tipik Grafik Olaylarını İşleme
Bu makale, tipik grafik olaylarını değerlendirir ve bunların işlenme örneklerini içerir. Fare olayları, tuş vuruşları, bir grafik nesnesinin oluşturulması/değiştirilmesi/kaldırılması, bir grafik üzerinde ve bir grafik nesnesi üzerinde fare tıklaması, bir grafik nesnesinin fare ile hareket ettirilmesi, bir metin alanındaki metnin düzenlemesinin tamamlanmasının yanı sıra grafik değişiklik olaylarına odaklanacağız. Değerlendirilen her olay türü için bir MQL5 programı örneği sağlanmıştır.