English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
Uyarlanabilir Alım Satım Sistemleri ve Bunların MetaTrader 5 Müşteri Terminalinde Kullanımları

Uyarlanabilir Alım Satım Sistemleri ve Bunların MetaTrader 5 Müşteri Terminalinde Kullanımları

MetaTrader 5Ticaret sistemleri | 9 Aralık 2021, 11:16
148 0
MetaQuotes
MetaQuotes


Tanıtım

Tüm dünyada yüz binlerce yatırımcı, MetaQuotes Software Corp. tarafından geliştirilen alım satım platformlarını kullanıyor. Başarıya götüren en önemli faktör, uzun yılların getirdiği deneyim ve en iyi yazılım çözümlerine dayanan teknolojik üstünlüktür.

Pek çok kişi, yeni MQL5 diliyle kullanıma sunulan yeni fırsatları şimdiden tahmin etti. Temel özellikleri yüksek performans ve nesne yönelimli programlama kullanabilme imkanıdır. Buna ek olarak, MetaTrader 5 müşteri terminalinde çoklu para birimi strateji sınama aracının ortaya çıkmasıyla, birçok yatırımcı karmaşık alım satım sistemlerini geliştirmek, öğrenmek ve kullanmak için benzersiz araçlar elde etti.

Otomatik Alım-Satım Şampiyonası 2010 bu sonbaharda başlıyor ve MQL5'te yazılmış binlerce alım-satım robotu bu şampiyonaya katılacak. Yarışma sırasında maksimum kârı elde eden Uzman Danışman kazanacaktır. Ama en etkili görünen strateji hangisi olacak?

MetaTrader 5 terminalinin strateji sınama aracı, sistemin belirli bir süre boyunca maksimum miktarda kâr elde ettiği en iyi parametre setini bulmayı mümkün kılar. Peki bu gerçek zamanlı olarak yapılabilir mi? Bir Uzman Danışman’da çeşitli stratejiler kullanan sanal alım-satım fikri, MQL4'teki uygulamasını da içeren "Uzman Danışmanın İçinde Uzman Danışmanların Yarışması" makalesinde ele alındı. 

Bu makalede, Standart Kitaplığın nesne yönelimli programlama, verilerle çalışma sınıfları ve alım-satım sınıflarının kullanımı nedeniyle MQL5'te uyarlanabilir stratejilerin oluşturulması ve analizinin önemli ölçüde kolaylaştığını göstereceğiz.


1. Uyarlanabilir Alım Satım Stratejileri

Piyasalar sürekli olarak değişir. Alım satım stratejilerinin mevcut piyasa koşullarına uyarlanmaları gerekir.

Stratejinin maksimum kârlılığını veren parametrelerin değerleri, parametrelerin sıralı değişimi ve sınama sonuçlarının analizi yoluyla optimizasyon kullanılmadan bulunabilir. 

Şekil 1, her biri hareketli ortalama stratejisiyle fakat farklı periyotlarla işlem gerçekleştiren (3,13,..93) on Uzman Danışman (MA_3,...MA_93) için eşitlik eğrilerini göstermektedir. Sınama EURUSD H1'de gerçekleştirilmiştir, sınama aralığı 04.01.2010-20.08.2010'dur.

Şekil 1. Hesaptaki on Uzman Danışman’ın hisse senedi eğrisi diyagramları

Şekil 1. Hesaptaki on Uzman Danışman’ın hisse senedi eğrisi diyagramları

Şekil 1'de görebileceğiniz gibi, Uzman Danışmanlar, çalışmanın ilk iki haftasında hemen hemen aynı sonuçları elde ettiler, ancak kârları önemli ölçüde farklılaşmaya başladı. Sınama süresinin sonunda en iyi alım satım sonuçları Uzman Danışmanlar tarafından 63, 53 ve 43. periyotlarla gösterilmiştir.

Piyasa en iyilerini seçmiştir. Neden piyasanın seçimlerine uymayalım? On stratejinin tümünü tek bir Uzman Danışman’da birleştirirsek, her strateji için "sanal" alım satım imkanı sağlarsak ve periyodik olarak (örneğin, her yeni çubuğun başında) gerçek alım-satım ve alım-satım için en iyi stratejiyi sinyallerine göre belirlersek ne olur?

Elde edilen uyarlanabilir stratejinin sonuçları Şekil 2'de gösterilmektedir. Uyarlanabilir alım satım yapılan hesabın hisse senedi eğrisi kırmızı renkle gösterilmiştir. Dönemin yarısından fazlasında uyarlanabilir stratejinin eşitlik eğrisinin biçiminin, işin sonunda kazanan MA_63 stratejisindeki ile aynı olduğuna dikkat edin.

Şekil 2. 10 alım-satım sisteminin sinyallerini kullanan uyarlanabilir stratejili hesaptaki hisse senedi eğrileri

Şekil 2. 10 alım satım sisteminin sinyallerini kullanan uyarlanabilir stratejili hesaptaki hisse senedi eğrileri

Bakiye eğrileri benzer dinamiklere sahiptir (Şekil 3):

Şekil 3. 10 alım-satım sisteminin sinyallerini kullanan uyarlanabilir stratejinin bakiye eğrileri

Şekil 3. 10 alım-satım sisteminin sinyallerini kullanan uyarlanabilir stratejinin bakiye eğrileri

Şu anda stratejilerin hiçbiri kârlı değilse, uyarlanabilir sistemler alım satım işlemlerini gerçekleştirmemelidir. Böyle bir durumun örneği, Şekil 2'de gösterilmektedir. 4 (4-22 Ocak 2010 arasındaki periyot).

Şekil 4. Uyarlanabilir stratejinin kârlı stratejilerin olmaması nedeniyle yeni pozisyon açmayı bıraktığı zaman dilimi

Şekil 4. Kârlı stratejilerin olmaması nedeniyle uyarlanabilir stratejinin yeni pozisyonlar açmayı bıraktığı dönem

Ocak 2010'dan itibaren, en iyi etkinlik MA_3 stratejisi tarafından gösterilmektedir. MA_3 (mavi) o anda kazanılan maksimum para miktarına sahip olduğundan, uyarlanabilir strateji (kırmızı), onun sinyallerini takip etmiştir. 8-20 Ocak arasındaki dönemde düşünülen tüm stratejiler olumsuz sonuç verdi, bu nedenle uyarlanabilir strateji yeni alım-satım pozisyonu açmadı. 

Tüm stratejilerin olumsuz sonuç verdiği durumlarda alım-satımdan uzak durmak daha iyidir. Kârsız alım-satımı durdurmaya ve paranızı güvende tutmanızı mümkün kılan önemli şey budur.


2. Uyarlanabilir Alım-Satım Stratejisinin Uygulanması

Bu bölümde, birkaç alım-satım stratejisini aynı anda kullanarak "sanal" alım-satım gerçekleştiren ve sinyallere göre gerçek alım-satım için en kârlı olanı seçen uyarlanabilir stratejinin yapısını ele alacağız. Nesne yönelimli yaklaşımın kullanılmasının bu sorunun çözümünü önemli ölçüde kolaylaştırdığını unutmayın.

Öncelikle uyarlanabilir Uzman Danışman’ın kodunu inceleyeceğiz, ardından uyarlanabilir sistemin fonksiyonelliğinin uygulandığı CAdaptiveStrategy'ye detaylı bir göz atacağız ve ardından CSampleStrategy sınıfının, yani sanal alım-satımın fonksiyonelliğinin uygulandığı alım-satım stratejilerinin temel sınıfının yapısını göstereceğiz.

Ayrıca, hareketli ortalamalar ve stokastik osilatör ile alım satım stratejilerini temsil eden iki çocuğunun - CStrategyMA ve CStrategyStoch sınıflarının kodunu ele alacağız. Yapılarını analiz ettikten sonra, stratejilerinizi gerçekleştiren kendi sınıflarınızı kolayca yazabilecek ve ekleyebileceksiniz.

2.1. Uzman Danışman’ın kodu

Uzman Danışman’ın kodu çok basit görünüyor:

//+------------------------------------------------------------------+
//|                                       Adaptive_Expert_Sample.mq5 |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"

#include <CAdaptiveStrategy.mqh>

CAdaptiveStrategy Adaptive_Expert;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   return(Adaptive_Expert.Expert_OnInit());
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Adaptive_Expert.Expert_OnDeInit(reason);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   Adaptive_Expert.Expert_OnTick();
  }
//+------------------------------------------------------------------+

İlk üç satır programın özelliklerini tanımlar, ardından önişlemciye CAdaptiveStrategy.mqh dosyasını eklemesini söyleyen #include yönergesi gelir. Köşeli parantezler, dosyanın standart dizinden alınması gerektiğini belirtir (genellikle bu terminal_folder\MQL5\Include olur).

Sonraki satır, Adaptive_Expert nesnesinin (CAdaptiveStrategy sınıfının örneği) bildirimini içerir; ve Uzman Danışman'ın OnInit, OnDeinit ve OnTick fonksiyonlarının kodu, ilgili Expert_OnInit, Expert_OnDeInit ve Expert_OnTick fonksiyonlarının ve Adaptive_Expert nesnesinin çağrılarından oluşur.

2.2. CadaptiveStrategy sınıfı

Uyarlanabilir Uzman Danışman sınıfı (CAdaptiveStrategy sınıfı), CAdaptiveStrategy.mqh dosyasında bulunur. Dahil edilen dosyalarla başlayalım:

#include <Arrays\ArrayObj.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <CStrategyMA.mqh>
#include <CStrategyStoch.mqh>

ArrayObj.mqh dosyasını eklememizin nedeni, temel sınıf CObject ve alt öğeleri tarafından oluşturulan sınıf örneklerine yönelik dinamik bir işaretçi dizisini temsil eden CArrayObj sınıfının nesnesini kullanarak farklı strateji sınıflarıyla çalışmanın sunduğu rahatlıktır. Bu nesne m_all_strategies dizisi olacak ve alım-satım stratejilerinin bir "taşıyıcısı" olarak kullanılacak.

Her strateji bir sınıf olarak temsil edilir. Bu durumda, hareketli ortalamalar ve stokastik osilatör ile alım-satım stratejilerini temsil eden CStrategyMA ve CStrategyStoch sınıflarını içeren dosyaları ekledik.

Mevcut pozisyonların özelliklerini talep etmek ve alım-satım işlemlerini gerçekleştirmek için Standart kütüphanenin CPositionInfo ve CTrade sınıflarını kullanacağız, bu yüzden PositionInfo.mqh ve Trade.mqh dosyalarını dahil ediyoruz.

Şimdi CAdaptiveStrategy sınıfının yapısına bir göz atalım.

//+------------------------------------------------------------------+
//| Class CAdaptiveStrategy                                          |
//+------------------------------------------------------------------+
class CAdaptiveStrategy
  {
protected:
   CArrayObj        *m_all_strategies;   // objects of trade strategies

   void              ProceedSignalReal(int state,double trade_volume);
   int               RealPositionDirection();

public:
   // initialization of the adaptive strategy
   int               Expert_OnInit();
   // deinitialization of the adaptive strategy
   int               Expert_OnDeInit(const int reason);
   // check of trade conditions and opening of virtual positions
   void              Expert_OnTick();
  };

Farklı sınıfların nesnelerine birleşik bir yaklaşım uygulamak için, alım-satım stratejileri (veya daha doğrusu onların sınıflarının örnekleri), strateji sınıflarının bir "taşıyıcısı" olarak kullanılan m_all_strategies (CArrayObj türünde) dinamik dizisinde depolanır. SampleStrategy alım satım stratejileri sınıfının CObject sınıfından üretilmesinin nedeni budur.

ProceedSignalReal fonksiyonu, verilen yön ve hacim ile gerçek bir konumun yönünün ve hacminin "senkronizasyonunu" uygular:

//+------------------------------------------------------------------+
//| This method is intended for "synchronization" of current         |
//| real trade position with the value of the 'state' state          |
//+------------------------------------------------------------------+
void CAdaptiveStrategy::ProceedSignalReal(int state,double trade_volume)
  {
   CPositionInfo posinfo;
   CTrade trade;

   bool buy_opened=false;
   bool sell_opened=false;

   if(posinfo.Select(_Symbol)) // if there are open positions
     {
      if(posinfo.Type()==POSITION_TYPE_BUY) buy_opened=true;    // a buy position is opened
      if(posinfo.Type()==POSITION_TYPE_SELL) sell_opened=true;  // a sell position is opened

      // if state = 0, then we need to close open positions
      if((state==POSITION_NEUTRAL) && (buy_opened || sell_opened))
        {
         if(!trade.PositionClose(_Symbol,200))
            Print(trade.ResultRetcodeDescription());
        }
      //reverse: closing buy position and opening sell position
      if((state==POSITION_SHORT) && (buy_opened))
        {
         if(!trade.PositionClose(_Symbol,200))
            Print(trade.ResultRetcodeDescription());
         if(!trade.PositionOpen(_Symbol,ORDER_TYPE_SELL,trade_volume,SymbolInfoDouble(_Symbol,SYMBOL_BID),0,0))
            Print(trade.ResultRetcodeDescription());
        }
      //reverse: close sell position and open buy position
      if(((state==POSITION_LONG) && (sell_opened)))
        {
         if(!trade.PositionClose(_Symbol,200))
            Print(trade.ResultRetcodeDescription());
         if(!trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,trade_volume,SymbolInfoDouble(_Symbol,SYMBOL_ASK),0,0))
            Print(trade.ResultRetcodeDescription());
        }
     }
   else // if there are no open positions
     {
      // open a buy position
      if(state==POSITION_LONG)
        {
         if(!trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,0.1,SymbolInfoDouble(_Symbol,SYMBOL_ASK),0,0))
            Print(trade.ResultRetcodeDescription());
        }
      // open a sell position
      if(state==POSITION_SHORT)
        {
         if(!trade.PositionOpen(_Symbol,ORDER_TYPE_SELL,0.1,SymbolInfoDouble(_Symbol,SYMBOL_BID),0,0))
            Print(trade.ResultRetcodeDescription());
        }
     }
  }

Alım-satım sınıflarını kullanarak alım-satım pozisyonuyla çalışmanın daha kolay olduğunu unutmayın. Sırasıyla piyasa pozisyonunun özelliklerini talep etmek ve alım-satım işlemlerini gerçekleştirmek için CPositionInfo ve CTrade sınıflarına ait nesneleri kullandık.

RealPositionDirection fonksiyonu, gerçek açık pozisyonun parametrelerini ister ve yönünü döndürür:

//+------------------------------------------------------------------+
//| Returns direction (0,+1,-1) of the current real position         |
//+------------------------------------------------------------------+
int CAdaptiveStrategy::RealPositionDirection()
  {
   int direction=POSITION_NEUTRAL;
   CPositionInfo posinfo;

   if(posinfo.Select(_Symbol)) // if there are open positions
     {
      if(posinfo.Type()==POSITION_TYPE_BUY) direction=POSITION_LONG;    // a buy position is opened
      if(posinfo.Type()==POSITION_TYPE_SELL) direction=POSITION_SHORT;  // a short position is opened
     }
   return(direction);
  }

Şimdi СAdaptiveStrategy sınıfının ana fonksiyonlarına bir göz atacağız.

Expert_OnInit: fonksiyonuyla başlayalım

//+------------------------------------------------------------------+
//| Function of initialization of the Adaptive Expert Advisor        |
//+------------------------------------------------------------------+
int CAdaptiveStrategy::Expert_OnInit()
  {
//--- Create array of objects m_all_strategies
//--- we will put our object with strategies in it 
   m_all_strategies=new CArrayObj;
   if(m_all_strategies==NULL)
     {
      Print("Error of creation of the object m_all_strategies"); return(-1);
     }

// create 10 trading strategies CStrategyMA (trading by moving averages)
// initialize them, set parameters
// and add to the m_all_strategies container 
   for(int i=0; i<10; i++)
     {
      CStrategyMA *t_StrategyMA;
      t_StrategyMA=new CStrategyMA;
      if(t_StrategyMA==NULL)
        {
         delete m_all_strategies;
         Print("Error of creation of object of the CStrategyMA type");
         return(-1);
        }
      //set period for each strategy
      int period=3+i*10;
      // initialize strategy
      t_StrategyMA.Initialization(period,true);
      // set details of the strategy
      t_StrategyMA.SetStrategyInfo(_Symbol,"[MA_"+IntegerToString(period)+"]",period,"Moving Averages "+IntegerToString(period));
      //t_StrategyMA.Set_Stops(3500,1000);

      //add the object of the strategy to the array of objects m_all_strategies
      m_all_strategies.Add(t_StrategyMA);
     }

   for(int i=0; i<m_all_strategies.Total(); i++)
     {
      CSampleStrategy *t_SampleStrategy;
      t_SampleStrategy=m_all_strategies.At(i);
      Print(i," Strategy name:",t_SampleStrategy.StrategyName(),
              " Strategy ID:",t_SampleStrategy.StrategyID(),
              " Virtual trading:",t_SampleStrategy.IsVirtualTradeAllowed());
     }
//---
   return(0);
  }

Alım satım stratejileri seti Expert_OnInit fonksiyonunda hazırlanır. Öncelikle m_all_strategies dinamik dizisinin nesnesi oluşturulur.

Bu durumda, CStrategyMA sınıfının on örneğini oluşturduk. Her biri Başlatma fonksiyonu kullanılarak başlatıldı (bu durumda farklı süreler belirledik ve "sanal" alım-satıma izin verdik).

Ardından SetStrategyInfo fonksiyonunu kullanarak finansal enstrümanı, strateji adını ve yorumunu belirliyoruz.

Gerekirse, Set_Stops(TP,SL) fonksiyonunu kullanarak, "sanal" alım-satım sırasında yürütülecek Kâr Al ve Zarar Durdur için bir değer (puan olarak) belirtebiliriz. Bu satırı yorumladık.

Strateji sınıfı oluşturulduktan ve ayarlandıktan sonra onu m_all_strategies taşıyıcısına ekliyoruz.

Tüm alım-satım strateji sınıfları, alım-satım koşullarının kontrollerini gerçekleştiren CheckTradeConditions() fonksiyonuna sahip olmalıdır. Uyarlanabilir strateji sınıfında bu fonksiyon her yeni çubuğun başında çağrılır, böylece stratejilere göstergelerin değerlerini kontrol etme ve "sanal" alım-satım işlemlerini yapma imkanı verilir.

Belirtilen on hareketli ortalama (3, 13, 23...93) yerine yüzlerce hareketli ortalama ekleyebiliriz (CStrategyMA sınıfı ise örnekler):

  for(int i=0; i<100; i++)
     {
      CStrategyMA *t_StrategyMA;
      t_StrategyMA=new CStrategyMA;
      if(t_StrategyMA==NULL)
        {
         delete m_all_strategies;
         Print("Error of creation of object of the CStrategyMA type");
         return(-1);
        }
      //set period for each strategy
      int period=3+i*10;
      // initialization of strategy
      t_StrategyMA.Initialization(period,true);
      // set details of the strategy
      t_StrategyMA.SetStrategyInfo(_Symbol,"[MA_"+IntegerToString(period)+"]",period,"Moving Averages "+IntegerToString(period));
      //add the object of the strategy to the array of objects m_all_strategies
      m_all_strategies.Add(t_StrategyMA);
     }

Veya stokastik osilatörün sinyalleriyle çalışan strateji sınıflarını ekleyebiliriz (CStrategyStoch sınıfının örnekleri):

  for(int i=0; i<5; i++)
     {
      CStrategyStoch *t_StrategyStoch;
      t_StrategyStoch=new CStrategyStoch;
      if(t_StrategyStoch==NULL)
        {
         delete m_all_strategies;
         printf("Error of creation of object of the CStrategyStoch type");
         return(-1);
        }
      //set period for each strategy
      int Kperiod=2+i*5;
      int Dperiod=2+i*5;
      int Slowing=3+i;
      // initialization of strategy
      t_StrategyStoch.Initialization(Kperiod,Dperiod,Slowing,true);
      // set details of the strategy
      string s=IntegerToString(Kperiod)+"/"+IntegerToString(Dperiod)+"/"+IntegerToString(Slowing);
      t_StrategyStoch.SetStrategyInfo(_Symbol,"[Stoch_"+s+"]",100+i," Stochastic "+s);
      //add the object of the strategy to the array of objects m_all_strategies
      m_all_strategies.Add(t_StrategyStoch);
     }

Bu durumda taşıyıcı 10 hareketli ortalama stratejisi ve stokastik osilatörün 5 stratejisini içerir.

Alım-satım strateji sınıflarının örnekleri, CObject sınıfının alt öğeleri olmalı ve CheckTradeConditions() fonksiyonunu içermelidir. Bunları CSampleStrategy sınıfından devralmak daha iyidir. Alım-satım stratejilerini uygulayan sınıflar farklı olabilir ve sayıları sınırlı değildir.

Expert_OnInit fonksiyonu, m_all_strategies taşıyıcısında bulunan stratejilerin listesiyle sona erer. Taşıyıcıdaki tüm stratejilerin CSampleStrategy sınıfının alt öğeleri olarak kabul edildiğini unutmayın. CStrategyMA ve CStrategyStoch alım-satım strateji sınıfları da onun alt öğeleridir.

Aynı numara Expert_OnDeInit fonksiyonunda da kullanılır. Taşıyıcıda her strateji için gerçekleştirilen sanal yatırımların geçmişini depolayan SaveVirtualDeals fonksiyonunu çağırırız.

Parametre olarak iletilen dosya adı için strateji adını kullanırız. Ardından, Deinitialization() fonksiyonunu çağırarak ve m_all_strategies taşıyıcısını silerek stratejileri sonlandırırız:

//+------------------------------------------------------------------+
//| Function of deinitialization the adaptive Expert Advisor         |
//+------------------------------------------------------------------+
int CAdaptiveStrategy::Expert_OnDeInit(const int reason)
  {
   // deinitialize all strategies
   for(int i=0; i<m_all_strategies.Total(); i++)
     {
      CSampleStrategy *t_Strategy;
      t_Strategy=m_all_strategies.At(i);
      t_Strategy.SaveVirtualDeals(t_Strategy.StrategyName()+"_deals.txt");
      t_Strategy.Deinitialization();
     }
   //delete the array of object with strategies 
   delete m_all_strategies;
   return(0);
  }

Stratejiler tarafından gerçekleştirilen sanal yatırımları bilmeniz gerekmiyorsa, tStrategy.SaveVirtualDeals'ın çağrıldığı satırı kaldırın. Strateji sınama aracını kullanırken dosyaların /tester_directory/Files/ dizinine kaydedildiğini unutmayın.

Her yeni tik geldiğinde çağrılan CadaptiveStrategy sınıfının Expert_OnTick fonksiyonunu ele alalım:

//+------------------------------------------------------------------+
//| Function of processing ticks of the adaptive strategy            |
//+------------------------------------------------------------------+
void CAdaptiveStrategy::Expert_OnTick()
  {
   CSampleStrategy *t_Strategy;

   // recalculate the information about positions for all strategies
   for(int i=0; i<m_all_strategies.Total(); i++)
     {
      t_Strategy=m_all_strategies.At(i);
      t_Strategy.UpdatePositionData();
     }

   // the expert advisor should check the conditions of making trade operations only when a new bar comes
   if(IsNewBar()==false) { return; }

   // check trading conditions for all strategies 
   for(int i=0; i<m_all_strategies.Total(); i++)
     {
      t_Strategy=m_all_strategies.At(i);
      t_Strategy.CheckTradeConditions();
     }

   //search for the best position
   //prepare the array performance[] 
   double performance[];
   ArrayResize(performance,m_all_strategies.Total());
   
   //request the current effectiveness for each strategy,
   //each strategy returns it in the Strategyperformance() function
   for(int i=0; i<m_all_strategies.Total(); i++)
     {
      t_Strategy=m_all_strategies.At(i);
      performance[i]=t_Strategy.StrategyPerformance();
     }
   //find the strategy (or rather its index in the m_all_strategies container)
   //with maximum value of Strategyperformance()
   int best_strategy_index=ArrayMaximum(performance,0,WHOLE_ARRAY);

   //this strategy is - t_Strategy
   t_Strategy=m_all_strategies.At(best_strategy_index);
   //request the direction of its current position
   int best_direction=t_Strategy.PositionDirection();

   string s=s+" "+t_Strategy.StrategyName()+" "+DoubleToString(t_Strategy.GetVirtualEquity())+" "+IntegerToString(best_direction);
   Print(TimeCurrent()," TOTAL=",m_all_strategies.Total(),
                       " BEST IND=",best_strategy_index,
                       " BEST STRATEGY="," ",t_Strategy.StrategyName(),
                       " BEST=",performance[best_strategy_index],"  =",
                       " BEST DIRECTION=",best_direction,
                       " Performance=",t_Strategy.StrategyPerformance());

   //if the best strategy has a negative result and doesn't have open positions, it's better to stay away from trading
   if((performance[best_strategy_index]<0) && (RealPositionDirection()==POSITION_NEUTRAL)) {return;}

   if(best_direction!=RealPositionDirection())
     {
      ProceedSignalReal(best_direction,t_Strategy.GetCurrentLotSize());
     }
  }

Kod oldukça basit. Taşıyıcıda bulunan her strateji, mevcut fiyatları kullanarak sanal pozisyonlarının mevcut finansal sonucunu yeniden hesaplayabilmelidir. Bu da UpdatePositionData() fonksiyonu çağrılarak yapılır. Burada bir kez daha stratejileri CSampleStrategy sınıfının mirasçıları olarak adlandırıyoruz.

Tüm alım-satım işlemleri yeni bir çubuğun başlangıcında gerçekleştirilir (IsNewBar() fonksiyonu, yeni çubuğu kontrol etmenin diğer yöntemlerinin yanı sıra bunun zamanının belirlenmesini sağlar). Bu durumda bir çubuğun oluşumunun sona ermesi, bir önceki çubuğun tüm verilerinin (fiyatlar ve gösterge değerleri) artık değişmeyeceği anlamına gelir, bu nedenle alım-satım koşullarına uygunluğu üzerinden analiz edilebilir. Tüm stratejilere, CheckTradeConditions fonksiyonunu çağırarak bu kontrolü gerçekleştirme ve sanal alım-satım işlemleri gerçekleştirme fırsatı veriyoruz.

Şimdi m_all_strategies dizisindeki tüm stratejiler arasında en başarılı stratejiyi bulmalıyız. Bunu yapmak için Performance[] dizisini kullandık. Her stratejinin StrategyPerformance() fonksiyonu tarafından döndürülen değerler buraya yerleştirilir. Temel sınıf CSampleStrategy, bu fonksiyonu "sanal" Hisse Senedi ve Bakiyenin geçerli değerleri arasındaki fark olarak barındırır.

En başarılı stratejinin dizin araması ArrayMaximum fonksiyonu kullanılarak gerçekleştirilir. En iyi stratejinin negatif kârı varsa ve gerçek açık pozisyonları yoksa, işlem yapmamak daha iyidir, fonksiyondan çıkmamızın nedeni de budur (bkz. Bölüm 1).

Ayrıca, bu stratejinin (best_direction) sanal konumunun yönünü talep ediyoruz. Gerçek konumun mevcut yönünden farklıysa, gerçek konumun mevcut yönü (ProceedSignalReal fonksiyonu kullanılarak) best_direction yönüne göre düzeltilecektir.

2.3. CSampleStrategySınıfı

m_all_strategies taşıyıcısına yerleştirilen stratejiler, CSampleStrategy sınıfının mirasçıları olarak kabul edilmişti.

Bu sınıf, alım-satım stratejilerinin temelini oluşturur ve sanal alım-satımın uygulanmasını barındırır. Bu yazıda basitleştirilmiş bir sanal alım-satım uygulaması vakasını ele alacağız; takaslar dikkate alınmamıştır. Alım-satım strateji sınıfları, CSampleStrategy sınıfından devralınmalıdır.

Şimdi bu sınıfın yapısını gösterelim.

//+------------------------------------------------------------------+
//|                                              CSampleStrategy.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#include <Object.mqh>

#define POSITION_NEUTRAL   0     // no position
#define POSITION_LONG      1     // long position
#define POSITION_SHORT    -1     // short position

#define SIGNAL_OPEN_LONG    10   // signal to open a long position
#define SIGNAL_OPEN_SHORT  -10   // signal to open a short position
#define SIGNAL_CLOSE_LONG   -1   // signal to close a long position
#define SIGNAL_CLOSE_SHORT   1   // signal to close a short position
//+------------------------------------------------------------------+
//| Structure for storing the parameters of virtual position         |
//+------------------------------------------------------------------+
struct virtual_position
  {
   string            symbol;            // symbol
   int               direction;         // direction of the virtual position (0-no open position,+1 long,-1 short)
   double            volume;            // volume of the position in lots
   double            profit;            // current profit of the virtual position on points
   double            stop_loss;         // Stop Loss of the virtual position
   double            take_profit;       // Take Profit of the virtual position
   datetime          time_open;         // date and time of opening the virtual position
   datetime          time_close;        // date and time of closing the virtual position
   double            price_open;        // open price of the virtual position
   double            price_close;       // close price of the virtual position
   double            price_highest;     // maximum price during the life of the position
   double            price_lowest;      // minimal price during the lift of the position
   double            entry_eff;         // effectiveness of entering
   double            exit_eff;          // effectiveness of exiting
   double            trade_eff;         // effectiveness of deal
  };
//+------------------------------------------------------------------+
//| Class CSampleStrategy                                            |
//+------------------------------------------------------------------+
class CSampleStrategy: public CObject
  {
protected:
   int               m_strategy_id;            // Strategy ID
   string            m_strategy_symbol;        // Symbol 
   string            m_strategy_name;          // Strategy name
   string            m_strategy_comment;       // Comment

   MqlTick           m_price_last;             // Last price
   MqlRates          m_rates[];                // Array for current quotes
   bool              m_virtual_trade_allowed;  // Flag of allowing virtual trading 
   int               m_current_signal_state;   // Current state of strategy
   double            m_current_trade_volume;   // Number of lots for trading
   double            m_initial_balance;        // Initial balance (set in the constructor, default value is 10000)
   int               m_sl_points;              // Stop Loss
   int               m_tp_points;              // Take Profit

   virtual_position  m_position;               // Virtual position
   virtual_position  m_deals_history[];        // Array of deals
   int               m_virtual_deals_total;    // Total number of deals

   double            m_virtual_balance;           // "Virtual" balance
   double            m_virtual_equity;            // "Virtual" equity
   double            m_virtual_cumulative_profit; // cumulative "virtual" profit
   double            m_virtual_profit;            // profit of the current open "virtual" position

   //checks and closes the virtual position by stop levels if it is necessary
   bool              CheckVirtual_Stops(virtual_position &position);
   // recalculation of position and balance
   void              RecalcPositionProperties(virtual_position &position);
   // recalculation of open virtual position in accordance with the current prices 
   void              Position_RefreshInfo(virtual_position &position);
   // open virtual short position
   void              Position_OpenShort(virtual_position &position);
   // closes virtual short position  
   void              Position_CloseShort(virtual_position &position);
   // opens virtual long position
   void              Position_OpenLong(virtual_position &position);
   // closes the virtual long position
   void              Position_CloseLong(virtual_position &position);
   // closes open virtual position  
   void              Position_CloseOpenedPosition(virtual_position &position);
   // adds closed position to the m_deals_history[] array (history of deals)
   void              AddDealToHistory(virtual_position &position);
   //calculates and returns the recommended volume that will be used in trading
   virtual double    MoneyManagement_CalculateLots(double trade_volume);
public:
   // constructor
   void              CSampleStrategy();
   // destructor
   void             ~CSampleStrategy();

   //returns the current size of virtual balance
   double            GetVirtualBalance() { return(m_virtual_balance); }
   //returns the current size of virtual equity
   double            GetVirtualEquity() { return(m_virtual_equity); }
   //returns the current size of virtual profit of open position
   double            GetVirtualProfit() { return(m_virtual_profit); }

   //sets Stop Loss and Take Profit in points
   void              Set_Stops(int tp,int sl) {m_tp_points=tp; m_sl_points=sl;};
   //sets the current volume in lots
   void              SetLots(double trade_volume) {m_current_trade_volume=trade_volume;};
   //returns the current volume in lots
   double            GetCurrentLots() { return(m_current_trade_volume); }

   // returns strategy name
   string            StrategyName() { return(m_strategy_name); }
   // returns strategy ID
   int               StrategyID() { return(m_strategy_id); }
   // returns the comment of strategy
   string            StrategyComment() { return(m_strategy_comment); }
   // sets the details of strategy (symbol, name and ID of strategy)
   void              SetStrategyInfo(string symbol,string name,int id,string comment);

   // set the flag of virtual trading (allowed or not)
   void              SetVirtualTradeFlag(bool pFlag) { m_virtual_trade_allowed=pFlag; };
   // returns flag of allowing virtual trading
   bool              IsVirtualTradeAllowed() { return(m_virtual_trade_allowed); };

   // returns the current state of strategy
   int               GetSignalState();
   // sets the current state of strategy (changes virtual position if necessary)
   void              SetSignalState(int state);
   // changes virtual position in accordance with the current state 
   void              ProceedSignalState(virtual_position &position);

   // sets the value of cumulative "virtual" profit
   void              SetVirtualCumulativeProfit(double cumulative_profit) { m_virtual_cumulative_profit=cumulative_profit; };

   //returns the effectiveness of strategy ()
   double            StrategyPerformance();

   //updates position data
   void              UpdatePositionData();
   //closes open virtual position
   void              CloseVirtualPosition();
   //returns the direction of the current virtual position
   int               PositionDirection();
   //virtual function of initialization
   virtual int       Initialization() {return(0);};
   //virtual function of checking trade conditions
   virtual bool      CheckTradeConditions() {return(false);};
   //virtual function of deinitialization
   virtual int       Deinitialization() {return(0);};

   //saves virtual deals to a file
   void              SaveVirtualDeals(string file_name);
  };

Ayrıntılı açıklamasını analiz etmeyeceğiz, ek bilgiler CSampleStrategy.mqh dosyasında bulunabilir. Burada ayrıca yeni çubuğu kontrol etmeye yarayan IsNewBar fonksiyonunu da bulabilirsiniz.


3. Alım Satım Stratejileri Sınıfları

Bu bölüm, uyarlanabilir Uzman Danışman'da kullanılan alım-satım strateji sınıflarının yapısına ayrılmıştır.

3.1. Class CStrategyMA - Hareketli Ortalamalarla Alım-Satım Stratejisi

//+------------------------------------------------------------------+
//|                                                  CStrategyMA.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#include <CSampleStrategy.mqh>
//+------------------------------------------------------------------+
//| Class CStrategyMA for implementation of virtual trading          |
//| by the strategy based on moving average                          |
//+------------------------------------------------------------------+
class CStrategyMA : public CSampleStrategy
  {
protected:
   int               m_handle;     // handle of the Moving Average (iMA) indicator
   int               m_period;     // period of the Moving Average indicator
   double            m_values[];   // array for storing values of the indicator
public:
   // initialization of the strategy
   int               Initialization(int period,bool virtual_trade_flag);
   // deinitialization of the strategy
   int               Deinitialization();
   // checking trading conditions and opening virtual positions
   bool              CheckTradeConditions();
  };

CStrategyMA sınıfı, sanal alım-satımın tüm fonksiyonelliğinin uygulandığı CSampleStrategy sınıfının bir alt öğesidir.

Korumalı bölüm, strateji sınıfında kullanılacak dahili değişkenleri içerir. Bunlar: m_handle - iMA göstergesinin tutacağı, m_period - hareketli ortalamanın periyodu ve m_values[] - göstergenin mevcut değerlerini almak için CheckTradeConditions fonksiyonunda kullanılacak dizidir.

Herkese açık bölüm, alım-satım stratejisinin uygulanmasını sağlayan üç fonksiyonu içerir.

  • Başlatma Fonksiyonu. Strateji burada başlatılır. Göstergeler oluşturmanız gerekiyorsa, bunları burada oluşturun.
  • Sonlandırma Fonksiyonu. Strateji burada sonlanır. Göstergelerin işleyicileri burada serbest bırakılır.
  • СheckTradeConditions Fonksiyonu. Burada strateji alım-satım koşullarını kontrol eder ve sanal alım-satım için kullanılan alım-satım sinyalleri üretir. Sanal alım-satım işlemlerini gerçekleştirmek için CStrategy üst sınıfının SetSignalState fonksiyonu çağrılır ve aşağıdaki dört alım-satım sinyalinden biri kendisine iletilir:
  1. Uzun pozisyon açma sinyali (SIGNAL_OPEN_LONG)
  2. Kısa pozisyon açma sinyali (SIGNAL_OPEN_SHORT)
  3. Uzun bir pozisyonu kapatmak için sinyal (SIGNAL_CLOSE_LONG)
  4. Kısa pozisyonu kapatmak için sinyal (SIGNAL_CLOSE_SHORT)
//+------------------------------------------------------------------+
//| Strategy Initialization Method                                   |
//+------------------------------------------------------------------+
int CStrategyMA::Initialization(int period,bool virtual_trade_flag)
  {
   // set period of the moving average
   m_period=period;
   // set specified flag of virtual trading
   SetVirtualTradeFlag(virtual_trade_flag);

   //set indexation of arrays like the one of timeseries
   ArraySetAsSeries(m_rates,true);
   ArraySetAsSeries(m_values,true);
   
   //create handle of the indicator
   m_handle=iMA(_Symbol,_Period,m_period,0,MODE_EMA,PRICE_CLOSE);
   if(m_handle<0)
     {
      Alert("Error of creation of the MA indicator - error number: ",GetLastError(),"!!");
      return(-1);
     }

   return(0);
  }
//+------------------------------------------------------------------+
//| Strategy Deinitialization Method                                 |
//+------------------------------------------------------------------+
int CStrategyMA::Deinitialization()
  {
   Position_CloseOpenedPosition(m_position);
   IndicatorRelease(m_handle);
   return(0);
  };
//+------------------------------------------------------------------+
//| Checking trading conditions and opening virtual positions        |
//+------------------------------------------------------------------+
bool CStrategyMA::CheckTradeConditions()
  {
   RecalcPositionProperties(m_position);
   double p_close;

   // get history data of the last three bars
   if(CopyRates(_Symbol,_Period,0,3,m_rates)<0)
     {
      Alert("Error of copying history data - error:",GetLastError(),"!!");
      return(false);
     }
   // Copy the current price of closing of the previous bar (it is bar 1)
   p_close=m_rates[1].close;  // close price of the previous bar          

   if(CopyBuffer(m_handle,0,0,3,m_values)<0)
     {
      Alert("Error of copying buffers of the Moving Average indicator - error number:",GetLastError());
      return(false);
     }

   // buy condition 1: MA rises
   bool buy_condition_1=(m_values[0]>m_values[1]) && (m_values[1]>m_values[2]);
   // buy condition 2: previous price is greater than the MA
   bool buy_condition_2=(p_close>m_values[1]);

   // sell condition 1: // MA falls
   bool sell_condition_1=(m_values[0]<m_values[1]) && (m_values[1]<m_values[2]);
   // sell condition 2: // previous price is lower than the MA   
   bool sell_condition_2=(p_close<m_values[1]);

   int new_state=0;

   if(buy_condition_1  &&  buy_condition_2) new_state=SIGNAL_OPEN_LONG;
   if(sell_condition_1 && sell_condition_2) new_state=SIGNAL_OPEN_SHORT;

   if((GetSignalState()==SIGNAL_OPEN_SHORT) && (buy_condition_1 || buy_condition_2)) new_state=SIGNAL_CLOSE_SHORT;
   if((GetSignalState()==SIGNAL_OPEN_LONG) && (sell_condition_1 || sell_condition_2)) new_state=SIGNAL_CLOSE_LONG;

   if(GetSignalState()!=new_state)
     {
      SetSignalState(new_state);
     }

   return(true);
  };

Bu, basit bir konsepttir - gösterge durumları ve fiyatlar temelinde, sinyal tipi (new_state) belirlenir, ardından sanal alım-satımın mevcut durumu istenir (GetSignalState fonksiyonu kullanılarak) ve eğer aynı değillerse, sanal konumu "düzeltmek" için SetSignalState fonksiyonu çağrılır.

3.2. Class CStrategyStoch - Stokastik Aracılığıyla Alım-Satım Stratejisi

iStochastic osilatörün ana ve sinyal hatlarının kesişimi temelinde alım-satım yapan sınıfın kodu aşağıda verilmiştir:

//+------------------------------------------------------------------+
//|                                               CStrategyStoch.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#include <CSampleStrategy.mqh>
//+------------------------------------------------------------------+
//| Class CStrategyStoch for implementation of virtual trading by    |
//| the strategy of intersection of lines of stochastic oscillator   |
//+------------------------------------------------------------------+
class CStrategyStoch : public CSampleStrategy
  {
protected:
   int               m_handle;          // handle of the Stochastic Oscillator (iStochastic)
   int               m_period_k;        // K-period (number of bars for calculations)
   int               m_period_d;        // D-period (period of primary smoothing)
   int               m_period_slowing;  // final smoothing
   double            m_main_line[];     // array for storing indicator values
   double            m_signal_line[];   // array for storing indicator values
public:
   // initialization of strategy
   int               Initialization(int period_k,int period_d,int period_slowing,bool virtual_trade_flag);
   // deinitialization of strategy
   int               Deinitialization();
   // checking trading conditions and opening virtual positions
   bool              CheckTradeConditions();
  };
//+------------------------------------------------------------------+
//| Strategy Initialization Method                                   |
//+------------------------------------------------------------------+
int CStrategyStoch::Initialization(int period_k,int period_d,int period_slowing,bool virtual_trade_flag)
  {
   // Set period of the oscillator
   m_period_k=period_k;
   m_period_d=period_d;
   m_period_slowing=period_slowing;

   // set specified flag of the virtual trading
   SetVirtualTradeFlag(virtual_trade_flag);

   // set indexation of arrays like the one of timeseries
   ArraySetAsSeries(m_rates,true);
   ArraySetAsSeries(m_main_line,true);
   ArraySetAsSeries(m_signal_line,true);

   // create handle of the indicator
   m_handle=iStochastic(_Symbol,_Period,m_period_k,m_period_d,m_period_slowing,MODE_SMA,STO_LOWHIGH);
   if(m_handle<0)
     {
      Alert("Error of creating the Stochastic indicator - error number: ",GetLastError(),"!!");
      return(-1);
     }

   return(0);
  }
//+------------------------------------------------------------------+
//| Strategy Deinitialization Method                                 |
//+------------------------------------------------------------------+
int CStrategyStoch::Deinitialization()
  {
   // close all open positions
   Position_CloseOpenedPosition(m_position);
   // release handle of the indicator
   IndicatorRelease(m_handle);
   return(0);
  };
//+------------------------------------------------------------------+
//| Checking Trading Conditions and Opening Virtual Positions        |
//+------------------------------------------------------------------+
bool CStrategyStoch::CheckTradeConditions()
  {
   // call the functions of recalculation of position parameters
   RecalcPositionProperties(m_position);
   double p_close;

   // get history  data of the last 3 bars 
   if(CopyRates(_Symbol,_Period,0,3,m_rates)<0)
     {
      Alert("Error of copying history data - error:",GetLastError(),"!!");
      return(false);
     }
   // copy the current close price of the previous bar (it is bar 1)
   p_close=m_rates[1].close;  // close price of the previous bar          

   if((CopyBuffer(m_handle,0,0,3,m_main_line)<3) || (CopyBuffer(m_handle,1,0,3,m_signal_line)<3))
     {
      Alert("Error of copying buffers of the Stochastic indicator - error number:",GetLastError());
      return(false);
     }

   // buy condition: crossing the signal line by the main one from bottom up
   bool buy_condition=((m_signal_line[2]<m_main_line[2]) && (m_signal_line[1]>m_main_line[1]));
   // sell condition: crossing the signal line by the main one from top downwards
   bool sell_condition=((m_signal_line[2]>m_main_line[2]) && (m_signal_line[1]<m_main_line[1]));

   int new_state=0;

   if(buy_condition) new_state=SIGNAL_OPEN_LONG;
   if(sell_condition) new_state=SIGNAL_OPEN_SHORT;

   if((GetSignalState()==SIGNAL_OPEN_SHORT) && (buy_condition)) new_state=SIGNAL_CLOSE_SHORT;
   if((GetSignalState()==SIGNAL_OPEN_LONG) && (sell_condition)) new_state=SIGNAL_CLOSE_LONG;

   if(GetSignalState()!=new_state)
     {
      SetSignalState(new_state);
     }

   return(true);
  };

Gördüğünüz gibi, CStrategyStoch sınıfının yapısı ile CStrategyMA sınıfının yapısı arasındaki tek fark, başlatma fonksiyonu (farklı parametreler), kullanılan göstergenin türü ve alım-satım sinyalleridir.

Bu nedenle uyarlanabilir Uzman Danışman’da stratejilerinizi kullanmak için bunları bu tür sınıflar şeklinde yeniden yazmalı ve m_all_strategies taşıyıcısına yüklemelisiniz.


4. Uyarlanabilir Alım-Satım Stratejilerinin Analiz Sonuçları

Bu bölümde, uyarlanabilir stratejilerin pratik kullanımının çeşitli yönlerini ve bunları geliştirme yöntemlerini tartışacağız.

4.1. Sistemi Ters Sinyalleri Kullanan Stratejilerle Geliştirmek

Trend olmadığında Hareketli Ortalamalar iyi değildir. Bu tür bir durumla daha önce karşılaşmıştık - Şekil 3'te, 8-20 Ocak arasındaki dönemde herhangi bir trend olmadığını görebilirsiniz, bu nedenle alım-satımda hareketli ortalama kullanan 10 stratejinin hepsi sanal bir kayıp yaşadı. Uyarlanabilir sistem, pozitif para kazancı bulunduran bir stratejinin olmaması nedeniyle alım-satımı durdurdu. Bu tür olumsuz etkilerden kaçınmanın bir yolu var mıdır?

10 stratejimize (MA_3, MA_13, ... MA_93) alım satım sinyalleri tersine çevrilmiş (koşulları aynı ancak SIGNAL_OPEN_LONG/SIGNAL_OPEN_SHORT ve SIGNAL_CLOSE_LONG/SIGNAL_CLOSE_SHORT yer değiştirmiş) olan CStrategyMAinv 10 sınıf daha ekleyelim. Böylelikle, on trend stratejisine (CStrategyMA sınıfının örnekleri) ek olarak, on tane de karşı-trend stratejimiz (CStrategyMAinv sınıfının örnekleri) var.

Yirmi stratejiden oluşan uyarlanabilir sistemin kullanılmasının sonucu şekil 5'te gösterilmektedir.

Şekil 5. 20 alım satım sinyali kullanan uyarlanabilir strateji hesabındaki hisse senedi diyagramları: 10’u hareketli ortalama CadaptiveMA ve 10’u "yansıtılmış" CadaptiveMAinv

Şekil 5. 20 alım satım sinyali kullanan uyarlanabilir strateji hesabındaki hisse senedi diyagramları: 10 hareketli ortalama CadaptiveMA ve 10 "yansıtılmış" ortalama CadaptiveMAinv

Şekil 5'te görebileceğiniz gibi, tüm CAdaptiveMA stratejilerinin olumsuz sonuç aldığı dönemde CAdaptiveMAinv stratejilerini takip etmek, alım-satımın en başında Uzman Danışman’ın istenmeyen düşüşlerden kaçınmasını sağladı.

Şekil 6. Uyarlanabilir stratejinin "karşı-trend" CadaptiveMAinv stratejilerinin sinyallerini kullandığı zaman aralığı

Şekil 6. Uyarlanabilir stratejinin "karşı-trend" sinyallerini kullandığı zaman dilimi CAdaptiveMAinv stratejileri

Bu tür bir yaklaşım kabul edilemez görünebilir, çünkü mevduat kaybetmek, karşı-trend stratejisi kullanırken sadece bir zaman meselesidir. Ancak biz bu durumda tek bir strateji ile sınırlı değiliz. Şu anda hangi stratejilerin etkili olduğunu piyasa daha iyi biliyor.

Uyarlanabilir sistemlerin güçlü yanı, pazarın hangi stratejinin ne zaman kullanılması gerektiğini kendi kendine önermesidir.

Stratejilerin mantığından soyutlanma imkanı verir - bir strateji etkiliyse çalışma şeklinin hiçbir önemi yoktur. Uyarlanabilir yaklaşım, bir stratejinin başarısının tek ölçütü olan etkililiği kullanır.

4.2. En Kötü Stratejinin Sinyallerini Tersine Çevirmeye Değer mi?

Yukarıda gösterilen ters çevirme numarası, aklımıza en kötü stratejinin sinyallerini kullanmanın potansiyel olasılıkları ile ilgili bazı düşünceler getirir. Bir strateji kârsızsa (ve en kötüsü ise), o zaman tersine hareket ederek kâr elde edebilir miyiz?

Sinyallerinde basit bir değişiklik yaparak kaybeden bir stratejiyi kârlı bir stratejiye dönüştürebilir miyiz? Bu soruyu cevaplamak için, CAdaptiveStrategy sınıfının Expert_OnTick() fonksiyonunda ArrayMaximum'u ArrayMinimum ile değiştirmemiz ve BestDirection değişkeninin değerini -1 ile çarparak yön değişikliğini gerçekleştirmemiz gerekiyor.

Ek olarak, negatif etkililik olması durumunda sanal alım-satımın sınırlamasını yorumlamamız gerekiyor (çünkü en kötü stratejinin sonucunu analiz edeceğiz):

//if((Performance[BestStrategyIndex]<0) && (RealPositionDirection()==0)) {return;}

En kötü stratejinin tersine çevrilmiş sinyallerini kullanan uyarlanabilir Uzman Danışman’ın eşitlik diyagramı, şekil 7'de gösterilmektedir:

Şekil 7. On stratejinin hesaplarındaki hisse senedi diyagramları ve en kötü sistemin tersine çevrilmiş sinyallerini kullanan uyarlanabilir sistem

Şekil 7. On stratejinin hesaplarındaki hisse senedi diyagramları ve en kötü sistemin tersine çevrilmiş sinyallerini kullanan uyarlanabilir sistem

Bu durumda çoğu zaman en başarısız strateji, hareketli ortalamaların 3. periyotla (MA_3) kesişimine dayanan stratejiydi. Şekil 7'de görebileceğiniz gibi, MA_3 (mavi renkli) ile uyarlamalı strateji (kırmızı renkli) arasında ters korelasyon var, ancak uyarlamalı sistemin finansal sonucu pek etkileyici değil.

En kötü stratejinin sinyallerini kopyalamak (ve tersine çevirmek), alım-satın etkililiğini artırmaya yol açmaz.

4.2. Hareketli Ortalamalar Grubu Neden Göründüğü Kadar Etkili Değil?

10 hareketli ortalama yerine, m_all_strategies taşıyıcısına farklı periyotlara sahip yüz CStrategyMA stratejisi ekleyerek bunların çoğunu kullanabilirsiniz.

Bunu yapmak için CAdaptiveStrategy sınıfındaki kodu biraz değiştirin:

   for(int i=0; i<100; i++)
     {
      CStrategyMA *t_StrategyMA;
      t_StrategyMA=new CStrategyMA;
      if(t_StrategyMA==NULL)
        {
         delete m_all_strategies;
         Print("Error of creation of object of the CStrategyMA type");
         return(-1);
        }
      //set period for each strategy
      int period=3+i*10;
      // initialization of strategy
      t_StrategyMA.Initialization(period,true);
      // set details of the strategy
      t_StrategyMA.SetStrategyInfo(_Symbol,"[MA_"+IntegerToString(period)+"]",period,"Moving Averages "+IntegerToString(period));
      //add the object of the strategy to the array of objects m_all_strategies
      m_all_strategies.Add(t_StrategyMA);
     }

Ancak, birbirine yakın olan hareketli ortalamaların kaçınılmaz olarak kesişeceğini bilmelisiniz; lider sürekli değişecek ve uyarlanabilir sistem, gerekenden daha sık durumlarını değiştirecek ve pozisyonlarını açacak/kapatacaktır. Sonuç olarak, uyarlanabilir sistemin özellikleri kötüleşecektir. Sistemin istatistiksel özelliklerini karşılaştırarak bundan kendiniz de olabilirsiniz (strateji sınama aracının "Sonuçlar" sekmesi).

Yakın parametrelere sahip birden fazla stratejiye dayalı uyarlanabilir sistemler yapmamak daha iyi bir seçim.


5. Dikkat Edilmesi Gerekenler

m_all_strategies taşıyıcısında binlerce önerilen strateji örneği bulunabilir, hatta tüm stratejileri farklı parametrelerle ekleyebilirsiniz; ancak, Otomatik Alım-Satım Şampiyonası 2010'u kazanmak için gelişmiş para yönetim sistemini geliştirmeniz gerekli. Geçmiş veriler üzerinde (ve sınıfların kodunda) sınamak için 0,1 lot’a eşit işlem hacmi kullandığımızı unutmayın.

5.1 Uyarlanabilir Uzman Danışman’ın Kârlılığı Nasıl Artırılır?

CSampleStrategy sınıfı, MoneyManagement_CalculateLots sanal fonksiyonuna sahiptir:

//+------------------------------------------------------------------+
//| The function returns the recommended volume for a strategy       |
//| Current volume is passed to it as a parameter                    |
//| Volume can be set depending on:                                  |
//| current m_virtual_balance and m_virtual_equity                   |
//| current statistics of deals (located in m_deals_history)         |
//| or any other thing you want                                      |
//| If a strategy doesn't require change of volume                   |
//| you can return the passed value of volume:  return(trade_volume);|
//+------------------------------------------------------------------+ 
double CSampleStrategy::MoneyManagement_CalculateLots(double trade_volume)
  {
   //return what we've got 
   return(trade_volume);
  }

İşlem hacmini yönetmek için, m_deals_history[] dizisinde kaydedilen sanal yatırımların sonuçları ve özellikleri hakkındaki istatistiksel bilgileri kullanabilirsiniz.

Hacmi artırmanız gerekiyorsa (örneğin, m_deals_history[] içindeki son sanal yatırımlar kârlıysa iki katına çıkarmak veya azaltmak için), dönüş değerini buna uygun şekilde değiştirmelisiniz.

5.2 Strateji Performansının Hesaplanması için Yatırım İstatistiklerinin Kullanılması

CSampleStrategy sınıfında uygulanan StrategyPerformance() fonksiyonu, strateji performansının hesaplanması için tasarlanmıştır,

//+-----------------------------------------------------------------------+
//| Function StrategyPerformance - the function of strategy effectiveness |
//+-----------------------------------------------------------------------+ 
double CSampleStrategy::StrategyPerformance()
  {
   //returns effectiveness of a strategy
   //in this case it's the difference between the amount
   //of equity at the moment and the initial balance, 
   //i.e. the amount of assets earned by the strategy
   double performance=(m_virtual_equity-m_initial_balance);
   return(performance);
  }

Bir stratejinin etkililiğinin formülü daha karmaşık olabilir ve örneğin giriş, çıkış, yatırımların, kârların ve düşüşlerin vb. etkililiğini içerebilir.

Giriş, çıkış ve yatırımların etkililiğinin (m_deals_history[] dizisinin yapılarının entry_eff, exit_eff ve trade_eff alanları) hesaplanması, sanal alım-satım sırasında otomatik olarak gerçekleştirilir (CSampeStrategy sınıfına bakın). Bu istatistiksel bilgiyi, kendiniz stratejinin etkililiğinin daha karmaşık oranlarını yapmak için kullanabilirsiniz.

Örneğin, etkililiğin bir özelliği olarak son üç yatırımın kârını kullanabilirsiniz (yatırımlar arşivindeki m_deals_history[] pos_Profit alanını kullanın):

double CSampleStrategy::StrategyPerformance()
  {
  //if there are deals, multiply this value by the result of three last deals
   if(m_virtual_deals_total>0)
     {
      int avdeals=MathRound(MathMin(3,m_virtual_deals_total));
      double sumprofit=0;
      for(int j=0; j<avdeals; j++)
        {
         sumprofit+=m_deals_history[m_virtual_deals_total-1-j].profit;
        }
      double performance=sumprofit/avdeals;
     }
     return(performance);

  }

Bu fonksiyonu değiştirmek istiyorsanız sadece CSampleStrategy sınıfında değiştirin, çünkü uyarlanabilir sistemin tüm alım-satım stratejileri için bu aynı olmalıdır. Ancak, Hisse Senedi ve Bakiye arasındaki farkın iyi bir etkililik faktörü olduğunu da unutmamalısınız.

5.3 Kâr Al ve Zarar Durdur özelliğini kullanma

Sabit durdurma seviyeleri belirleyerek alım-satım sistemlerinin etkililiğini değiştirebilirsiniz (bu, Set_Stops fonksiyonu çağırarak yapılabilir ve sanal alım-satım için durdurma seviyelerinin puan olarak ayarlanmasına izin verir). Seviyeler belirtilirse, sanal pozisyonların kapatılması otomatik olarak gerçekleştirilecektir. Bu fonksiyonellik, CSampleStrategy sınıfında uygulanır.

Örneğimizde (bkz. 2.2, hareketli ortalama sınıflarının fonksiyonu), durma seviyelerini ayarlama fonksiyonu yorumlanmıştır.

5.4. Kümülatif Sanal Kârın Periyodik Olarak Sıfırlanması

Uyarlanabilir yaklaşım, ortak stratejilerle aynı dezavantaja sahiptir. Lider strateji kaybetmeye başlarsa, uyarlanabilir sistem de kaybetmeye başlar. Bu nedenle, bazen tüm stratejilerin çalışma sonuçlarını "sıfırlamanız" ve tüm sanal konumlarını kapatmanız gerekir. 

Bunu yapmak için CSampleStrategy sınıfında aşağıdaki fonksiyonlar uygulanır:

// sets a value for cumulative "virtual profit"
 void              SetVirtualCumulativeProfit(double cumulative_profit) { m_virtual_cumulative_profit=cumulative_perofit; };
//closes an open virtual position
 void              CloseVirtualPosition();

Bu tür Kontrol Noktaları zaman zaman, örneğin her N sayıda çubuktan sonra kullanılabilir.

5.5. Mucize Yok

Uyarlanabilir sistemin bir kutsal kâse olmadığını unutmamalısınız (USDJPY H1, 4.01.2010-20.08.2010):

Şekil 8. En iyi 10 stratejinin sinyallerini kullanan uyarlamalı sistemin hisse senedi ve bakiye eğrileri (USDJPY H1)

Şekil 8. En iyi 10 stratejinin sinyallerini kullanan uyarlanabilir sistemin bakiye ve hisse senedi eğrileri (USDJPY H1)

Tüm stratejilerin hisse senedi eğrileri şekil 9'da gösterilmiştir.

Şekil 9. 10 stratejiye dayalı uyarlamalı sistemli hesaptaki hisse senedi eğrileri (USDJPY H1)

Şekil 9. 10 stratejiye dayalı uyarlanabilir sistemli hesaptaki hisse senedi eğrileri (USDJPY H1)

Uyarlanabilir sistemde kârlı stratejiler yoksa, bunları kullanmak etkili değildir. Kârlı stratejiler kullanın.

Önemli ve ilginç olan başka bir şeyi de düşünmeliyiz. Alım-satımın en başında uyarlanabilir stratejinin davranışına dikkat edin:

Şekil 10. Uyarlanabilir stratejinin 10 stratejisine

Şekil 10. Uyarlanabilir stratejinin 10 stratejisine sahip hesaptaki hisse senedi eğrileri

İlk olarak tüm stratejilerin sonuçları olumsuz oldu ve uyarlanabilir strateji alım-satımı durdurdu; daha sonra olumlu sonuç veren olan stratejiler arasında geçiş yapmaya başladı ve sonra tüm stratejiler tekrar kârsız hale geldi.

Tüm stratejiler başlangıçta aynı bakiyeye sahiptir. Yalnızca bir süre sonra bir strateji lider olabilir. Bu nedenle, ilk çubuklarda işlem yapmaktan kaçınmak için uyarlamalı stratejide bir sınırlama getirilmesi önerilir. Bunu yapmak için, CAdaptiveStrategy sınıfının Expert_OnTick fonksiyonunu, her yeni çubuk geldiğinde değeri artan bir değişken ile tamamlayın.

Başlangıçta piyasa en iyi stratejiyi seçene kadar gerçek alım-satımdan uzak durmalısınız.


Sonuçlar

Bu yazımızda, her biri kendi "sanal" alım-satım işlemlerini yapan birçok stratejiden oluşan uyarlanabilir sistem örneğini ele aldık. Şu anda gerçek alım satım en kârlı stratejinin sinyallerine göre gerçekleştirilir.

Standart kitaplığın nesne yönelimli yaklaşımı, verilerle çalışmak için sınıflar ve alım-satım sınıfları sayesinde, sistemin mimarisi basit ve ölçeklenebilir görünüyordu. Artık yüzlerce alım-satım stratejisini içeren uyarlanabilir sistemleri kolayca oluşturabilir ve analiz edebilirsiniz.

NOT Uyarlanabilir sistemlerin davranışlarının kolaylı analizi için, CSampleStrategy sınıfının hata ayıklama sürümü eklenmiştir (adaptive-systems-mql5-sources-debug-en.zip arşiv dosyası). Bu sürümün farkı, çalışması sırasında metin dosyaları oluşturmasıdır. Bu dosyalar, sistemde yer alan stratejilerin sanal bakiye/hisse senedi değişim dinamiklerine ilişkin özet raporları içerirler.

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

MQL5'te Uzman Danışmanları Test Etme ve Optimize Etme Kılavuzu MQL5'te Uzman Danışmanları Test Etme ve Optimize Etme Kılavuzu
Bu makale, adım adım kod hatalarını belirleme ve çözme sürecini ve ayrıca Uzman Danışman girdi parametrelerinin sınanması ve optimize edilmesi adımlarını açıklamaktadır. Uzman Danışmanınız için en iyi sembolü ve girdi parametreleri setini bulmak için MetaTrader 5 müşteri terminalinin Strateji Sınama Aracını nasıl kullanacağınızı öğreneceksiniz.
Bill Williams'ın "Yeni Ticaret Boyutları" kitabına dayanan Uzman Danışman Bill Williams'ın "Yeni Ticaret Boyutları" kitabına dayanan Uzman Danışman
Bu makalede, Uzman Danışmanın Bill Williams tarafından yazılan "New Trading Dimensions: How to Profit from Chaos in Stocks, Bonds and Commodities” (Yeni Ticaret Boyutları: Hisse Senetleri, Tahviller ve Emtialardaki Kaostan Nasıl Kar Edilir) kitabına dayanarak geliştirilmesini ele alacağım. Stratejinin kendisi iyi bilinmektedir ve kullanımı yatırımcılar arasında hala tartışmalıdır. Makale, sistemin alım satım sinyallerini, uygulanmasının özelliklerini ve geçmiş veriler üzerinde test sonuçlarını dikkate almaktadır.
MetaTrader 5 Emirler, Pozisyonlar ve Yatırımlar MetaTrader 5 Emirler, Pozisyonlar ve Yatırımlar
Güçlü bir alım satım robotu oluşturmak, MetaTrader 5 alım satım sisteminin mekanizmalarını anlamadan yapılamaz. Müşteri terminali, alım satım sunucusundan pozisyonlar, emirler ve yatırımlar hakkında bilgi alır. Bu verileri MQL5 kullanarak düzgün bir şekilde kullanmak için MQL5 programı ve müşteri terminali arasındaki etkileşimin iyi anlaşılması gerekir.
Alım Satım Sistemlerinin Değerlendirilmesi - Genel Olarak Giriş, Çıkış ve İşlemlerin Etkililiği Alım Satım Sistemlerinin Değerlendirilmesi - Genel Olarak Giriş, Çıkış ve İşlemlerin Etkililiği
Bir alım satım sisteminin etkililiğini ve kârlılığını belirlemeye izin veren birçok önlem vardır. Ancak, yatırımcılar her zaman herhangi bir sistemi yeni bir çarpışma testine sokmaya hazırdır. Makale, etkililik ölçütlerine dayalı istatistiklerin MetaTrader 5 platformu için nasıl kullanılabileceğini anlatıyor. S.V. Bulashev’in "Statistika dlya traderov" ("Yatırımcılar için İstatistikler") kitabında verilen açıklamaya aykırı olmayan, sözleşmelere göre istatistiklerin yorumlanmasının dönüştürülmesine yönelik sınıfı içerir. Ayrıca optimizasyon için bir özel fonksiyon örneği içerir.