Uyarlanabilir Alım Satım Sistemleri ve Bunların MetaTrader 5 Müşteri Terminalinde Kullanımları
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'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
Bakiye eğrileri benzer dinamiklere sahiptir (Şekil 3):
Ş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. 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:
- Uzun pozisyon açma sinyali (SIGNAL_OPEN_LONG)
- Kısa pozisyon açma sinyali (SIGNAL_OPEN_SHORT)
- Uzun bir pozisyonu kapatmak için sinyal (SIGNAL_CLOSE_LONG)
- 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 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" 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
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 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ı 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 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
- Ücretsiz ticaret uygulamaları
- İşlem kopyalama için 8.000'den fazla sinyal
- Finansal piyasaları keşfetmek için ekonomik haberler
Gizlilik ve Veri Koruma Politikasını ve MQL5.com Kullanım Şartlarını kabul edersiniz