MQL5 Tarif Defteri: Pozisyon Özelliklerini Elde Etmek için İşlemler Geçmişi ve Fonksiyon Kitaplığı
Giriş
Pozisyon özellikleri ile ilgili önceki makalelerde verilen bilgileri kısaca özetlemenin zamanı geldi. Bu makalemizde, işlemler geçmişine erişimin ardından edinilebilecek özellikleri elde etmek için birkaç ek fonksiyon oluşturacağız. Ayrıca pozisyon ve sembol özelliklerine daha rahat erişmemizi sağlayacak veri yapılarını da öğreneceğiz.
Pozisyon hacimlerinin varlıkları boyunca aynı kaldığı alım satım sistemleri, bu makalede sağlanacak fonksiyonların kullanılmasını pek gerektirmez. Ancak daha sonraki bir aşamada bir para yönetim sistemi uygulamayı ve alım satım stratejinizde bir pozisyon lot boyutunu kontrol etmeyi planlıyorsanız, bu fonksiyonlar vazgeçilmez olacaktır.
Başlamadan önce, bu web sitesini ilk kez ziyaret ederken bu makalenin bağlantısını takip eden veya MQL5 dilini yeni öğrenmeye başlayan okuyuculara, "MQL5 Tarif Defteri" serisinin daha önceki makaleleri ile başlamaları için bir öneride bulunmak istiyorum.
Uzman Danışman Geliştirme
Aşağıdaki önceki makalede değiştirilen Uzman Danışmanda yeni fonksiyonların çalışmasını görmek için, pozisyon halihazırda buradayken tekrar açılış sinyali gelirse pozisyon hacmini artırma imkanını ekleyeceğiz: "MQL5 Tarif Defteri: Alım Satım Seviyelerini Ayarlarken/Değiştirirken Hatalardan Nasıl Kaçınılır?"
Pozisyon geçmişinde birkaç işlem olabilir; ve alım satım sırasında pozisyon hacminde değişiklikler olmuşsa, mevcut pozisyon fiyatında da değişiklikler olmuş olmalıdır. İlk giriş noktasının fiyatını bulmak için, bu belirli pozisyonla ilgili işlemlerin geçmişine erişmemiz gerekir. Aşağıdaki şekil, bir pozisyonun yalnızca bir işleminin (giriş noktası) olduğu durumun bir gösterimidir:
Şekil 1. Pozisyondaki ilk işlem.
Sonraki şekil, ikinci işlemin ardından pozisyon fiyatındaki değişikliği gösterir:
Şekil 2. Pozisyondaki ikinci işlem.
Önceki makalelerde gösterildiği gibi standart tanımlayıcılar, yalnızca mevcut pozisyon fiyatını (POSITION_PRICE_OPEN) ve bir pozisyonun açılacağı bir sembolün mevcut fiyatını (POSITION_PRICE_CURRENT) elde etmenizi sağlar.
Bununla birlikte, bazı alım satım sistemlerinde, fiyatın ilk giriş noktasından kat ettiği mesafeyi ve son işlemin fiyatını bilmemiz gerekir. Tüm bu bilgiler, hesabın işlem/emir geçmişinde mevcuttur. Aşağıda, önceki şekil ile ilişkili işlemlerin listesi yer almaktadır:
Şekil 3. Hesaptaki işlemlerin geçmişi.
Artık durumun netleştiğine ve tüm hedeflerin belirlendiğine inanıyorum. Önceki makalelerde yer alan Uzman Danışmanı değiştirmeye devam edelim. İlk olarak, pozisyon özelliklerinin numaralandırılmasına 0, 6, 9, 12 ve 16 numaralı yeni tanımlayıcıları ekleyeceğiz:
//--- Enumeration of position properties enum ENUM_POSITION_PROPERTIES { P_TOTAL_DEALS = 0, P_SYMBOL = 1, P_MAGIC = 2, P_COMMENT = 3, P_SWAP = 4, P_COMMISSION = 5, P_PRICE_FIRST_DEAL= 6, P_PRICE_OPEN = 7, P_PRICE_CURRENT = 8, P_PRICE_LAST_DEAL = 9, P_PROFIT = 10, P_VOLUME = 11, P_INITIAL_VOLUME = 12, P_SL = 13, P_TP = 14, P_TIME = 15, P_DURATION = 16, P_ID = 17, P_TYPE = 18, P_ALL = 19 };
Özelliklerin her biri için yorumlar aşağıda biraz gözden geçirilecek bir yapıda sağlanacaktır.
Harici parametrelerin sayısını artıralım. Şimdi aşağıdakileri belirtebiliriz:
- MagicNumber - Uzman Danışman için benzersiz bir kimlik (sihirli sayı);
- Sapma - kayma;
- VolumeIncrease - pozisyon hacmini artırma değeri;
- InfoPanel - bilgi panelinin görüntülenmesini etkinleştirmenizi/devre dışı bırakmanızı sağlayan bir parametre.
Şu şekilde uygulanır:
//--- External parameters of the Expert Advisor sinput long MagicNumber=777; // Magic number sinput int Deviation=10; // Slippage input int NumberOfBars=2; // Number of Bullish/Bearish bars for a Buy/Sell input double Lot=0.1; // Lot input double VolumeIncrease=0.1; // Position volume increase input double StopLoss=50; // Stop Loss input double TakeProfit=100; // Take Profit input double TrailingStop=10; // Trailing Stop input bool Reverse=true; // Position reversal sinput bool ShowInfoPanel=true; // Display of the info panel
Lütfen sinput değiştiricisi ayarlanmış olan parametrelere dikkat edin. Bu değiştirici, Strateji Test Cihazında optimizasyonu devre dışı bırakmanıza olanak sağlar. Aslında, kendi kullanımınız için bir program geliştirirken, hangi parametrelerin nihai sonucu etkileyeceğini mükemmel bir şekilde anlarsınız, bu yüzden bunları optimizasyondan çıkarmanız yeterlidir. Ancak, oldukça fazla sayıda parametre söz konusu olduğunda, bu yöntem bunlar karartıldıkça görsel olarak bunları diğerlerinden ayırt etmenize olanak sağlar:
Şekil 4. Optimizasyon için devre dışı bırakılmış parametreler karartılır.
Şimdi pozisyon ve sembol özellik değerlerini saklayan global değişkenleri veri yapıları (yapı) ile değiştirelim:
//--- Position properties struct position_properties { uint total_deals; // Number of deals bool exists; // Flag of presence/absence of an open position string symbol; // Symbol long magic; // Magic number string comment; // Comment double swap; // Swap double commission; // Commission double first_deal_price; // Price of the first deal in the position double price; // Current position price double current_price; // Current price of the position symbol double last_deal_price; // Price of the last deal in the position double profit; // Profit/Loss of the position double volume; // Current position volume double initial_volume; // Initial position volume double sl; // Stop Loss of the position double tp; // Take Profit of the position datetime time; // Position opening time ulong duration; // Position duration in seconds long id; // Position identifier ENUM_POSITION_TYPE type; // Position type };
//--- Symbol properties struct symbol_properties { int digits; // Number of decimal places in the price int spread; // Spread in points int stops_level; // Stops level double point; // Point value double ask; // Ask price double bid; // Bid price double volume_min; // Minimum volume for a deal double volume_max; // Maximum volume for a deal double volume_limit; // Maximum permissible volume for a position and orders in one direction double volume_step; // Minimum volume change step for a deal double offset; // Offset from the maximum possible price for a transaction double up_level; // Upper Stop level price double down_level; // Lower Stop level price }
Şimdi, yapının belirli bir öğesine erişmek için bu yapı türünde bir değişken oluşturmamız gerekiyor. Prosedür, aşağıdaki makalede değerlendirilen bir alım satım sınıfına yönelik bir nesne oluşturmaya benzerdir: "MQL5 Tarif Defteri: Pozisyon Parametrelerini MetaTrader 5 Strateji Test Cihazında Analiz Etme".
//--- variables for position and symbol properties
position_properties pos;
symbol_properties symb;
Öğelere, sınıf yöntemlerini ele alırken olduğu gibi erişim sağlayabilirsiniz. Diğer bir deyişle, bu özel yapıda bulunan öğelerin listesini görüntülemek için bir yapı değişkeninin adından sonra bir nokta koymak yeterlidir. Bu oldukça kullanışlıdır. Yapının alanları için tek satırlık yorumlar sağlanıyorsa (örneğimizde olduğu gibi) bunlar, sağdaki bir araç ipucunda gösterilecektir.
Şekil 5. Yapı alanlarının listesi.
Bir diğer önemli nokta. Uzman Danışmanı değiştirirken, birçok fonksiyonda kullanılan global değişkenlerinin neredeyse tamamını değiştirdik, dolayısıyla şimdi bunları sembol ve pozisyon özellikleri için ilgili yapı alanlarıyla değiştirmemiz gerekiyor. Örneğin, bir açık pozisyonun varlığı/yokluğu bayrağını saklamak için kullanılan pos_open global değişkeni, position_properties yapı türünün exists (var) alanıyla değiştirilmiştir. Dolayısıyla, pos_open değişkeninin kullanıldığı her yerde, bunun pos.exists (var) ile değiştirilmesi gerekir.
Bunu manuel olarak yaparsanız, uzun ve yorucu bir süreç olacaktır. Bu nedenle, bu görevin çözümünü MetaEditor özelliklerini kullanarak otomatikleştirmek daha iyi olacaktır: Düzenle menüsünde Bul ve Değiştir -> Değiştir veya Ctrl+H tuş kombinasyonu:
Şekil 6. Metni bulma ve değiştirme.
Dosyayı derledikten sonra bir test yapmak için pozisyon ve sembol özellikleri için tüm global değişkenleri bulmamız ve değiştirmemiz gerekir. Herhangi bir hata tespit edilmezse bu, her şeyi doğru yaptığımız anlamına gelir. Makaleyi gereksiz yere uzatmamak için kodu burada vermeyeceğim. Bununla birlikte, indirmeniz için makalenin sonunda kullanıma hazır bir kaynak kodu mevcuttur.
Artık değişkenlerle ilgili bir şeyi çözdüğümüze göre, mevcut fonksiyonları değiştirmeye ve yenilerini oluşturmaya devam edelim.
Artık, harici parametrelerde sihirli sayıyı ve nokta cinsinden kaymayı ayarlayabiliyorsunuz. Dolayısıyla ilgili değişiklikleri Uzman Danışman kodunda da yapmamız gerekiyor. Kullanıcı tanımlı bir yardımcı OpenPosition() fonksiyonu oluşturacağız, burada bu özellikler, pozisyon açma için bir emir göndermeden önce CTrade sınıfının fonksiyonları kullanılarak ayarlanacaktır.
//+------------------------------------------------------------------+ //| Opening a position | //+------------------------------------------------------------------+ void OpenPosition(double lot, ENUM_ORDER_TYPE order_type, double price, double sl, double tp, string comment) { trade.SetExpertMagicNumber(MagicNumber); // Set the magic number in the trading structure trade.SetDeviationInPoints(CorrectValueBySymbolDigits(Deviation)); // Set the slippage in points //--- If the position failed to open, print the relevant message if(!trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,comment)) { Print("Error opening the position: ",GetLastError()," - ",ErrorDescription(GetLastError())); } }
Sadece Uzman Danışman TradingBlock() ana alım satım fonksiyonunun kodunda bazı küçük değişiklikler yapmamız gerekiyor. Aşağıda, fonksiyon kodunun değişikliğe uğrayan kısmı yer almaktadır:
//--- If there is no position if(!pos.exists) { //--- Adjust the volume lot=CalculateLot(Lot); //--- Open a position OpenPosition(lot,order_type,position_open_price,sl,tp,comment); } //--- If there is a position else { //--- Get the position type GetPositionProperties(P_TYPE); //--- If the position is opposite to the signal and the position reversal is enabled if(pos.type==opposite_position_type && Reverse) { //--- Get the position volume GetPositionProperties(P_VOLUME); //--- Adjust the volume lot=pos.volume+CalculateLot(Lot); //--- Reverse the position OpenPosition(lot,order_type,position_open_price,sl,tp,comment); return; } //--- If the signal is in the direction of the position and the volume increase is enabled, increase the position volume if(!(pos.type==opposite_position_type) && VolumeIncrease>0) { //--- Get the Stop Loss of the current position GetPositionProperties(P_SL); //--- Get the Take Profit of the current position GetPositionProperties(P_TP); //--- Adjust the volume lot=CalculateLot(Increase); //--- Increase the position volume OpenPosition(lot,order_type,position_open_price,pos.sl,pos.tp,comment); return; }
Yukarıdaki kod, mevcut pozisyonun yönünün sinyal yönüne göre kontrol edildiği blok ile geliştirilmiştir. Bunların yönleri kesişiyorsa ve harici parametrelerde pozisyon hacim artışı etkinleştirilmişse (VolumeIncrease parametre değeri sıfırdan büyükse), verilen bir lotu kontrol edip/ayarlayıp ilgili emri göndeririz. Artık bir pozisyon açmak veya bunu ters çevirmek için emir göndermek veya pozisyon hacmini artırmak için yapmanız gereken tek şey bir satır kod yazmak.
İşlemler geçmişinden pozisyon özelliklerini elde etmek için fonksiyonlar oluşturalım: Mevcut pozisyonda işlemlerin sayısını döndüren CurrentPositionTotalDeals() fonksiyonu ile başlayacağız:
//+------------------------------------------------------------------+ //| Returning the number of deals in the current position | //+------------------------------------------------------------------+ uint CurrentPositionTotalDeals() { int total =0; // Total deals in the selected history list int count =0; // Counter of deals by the position symbol string deal_symbol =""; // symbol of the deal //--- If the position history is obtained if(HistorySelect(pos.time,TimeCurrent())) { //--- Get the number of deals in the obtained list total=HistoryDealsTotal(); //--- Iterate over all the deals in the obtained list for(int i=0; i<total; i++) { //--- Get the symbol of the deal deal_symbol=HistoryDealGetString(HistoryDealGetTicket(i),DEAL_SYMBOL); //--- If the symbol of the deal and the current symbol are the same, increase the counter if(deal_symbol==_Symbol) count++; } } //--- return(count); }
Yukarıdaki kodda oldukça ayrıntılı yorumlar sağlanmıştır. Ancak geçmişin nasıl seçildiğine dair birkaç şey söylemeliyiz. Bizim durumumuzda, listeyi HistorySelect() fonksiyonunu kullanarak açılış zamanı ile belirlenen mevcut pozisyonun açılma noktasından mevcut zaman noktasına kadar olan listeyi aldık. Geçmişi seçtikten sonra, HistoryDealsTotal() fonksiyonunu kullanarak listedeki işlem sayısını bulabiliriz. Gerisi yorumlardan anlaşılmalıdır.
Belirli bir pozisyonun geçmişi, HistorySelectByPosition() fonksiyonu kullanılarak bunun tanımlayıcısı tarafından da seçilebilir. Burada, Uzman Danışmanımızda bazen meydana geldiği gibi, pozisyon ters çevrildiğinde pozisyon tanımlayıcısının aynı kaldığını göz önünde bulundurmanız gerekir. Ancak pozisyon açma süresi ters çevirme üzerine değişir, bu nedenle bu varyantın uygulanması daha kolaydır. Ancak, yalnızca şu anda açık olan pozisyon için geçerli olmayan işlemlerin geçmişi ile ilgilenmeniz gerekiyorsa, tanımlayıcıları kullanmalısınız. Gelecekteki makalelerde işlemler geçmişine geri döneceğiz.
Pozisyondaki ilk işlemin fiyatını yani pozisyonun açıldığı işlemin fiyatını döndüren bir CurrentPositionFirstDealPrice() fonksiyonu oluşturarak devam edelim.
//+------------------------------------------------------------------+ //| Returning the price of the first deal in the current position | //+------------------------------------------------------------------+ double CurrentPositionFirstDealPrice() { int total =0; // Total deals in the selected history list string deal_symbol =""; // symbol of the deal double deal_price =0.0; // Price of the deal datetime deal_time =NULL; // Time of the deal //--- If the position history is obtained if(HistorySelect(pos.time,TimeCurrent())) { //--- Get the number of deals in the obtained list total=HistoryDealsTotal(); //--- Iterate over all the deals in the obtained list for(int i=0; i<total; i++) { //--- Get the price of the deal deal_price=HistoryDealGetDouble(HistoryDealGetTicket(i),DEAL_PRICE); //--- Get the symbol of the deal deal_symbol=HistoryDealGetString(HistoryDealGetTicket(i),DEAL_SYMBOL); //--- Get the time of the deal deal_time=(datetime)HistoryDealGetInteger(HistoryDealGetTicket(i),DEAL_TIME); //--- If the time of the deal equals the position opening time, // and if the symbol of the deal and the current symbol are the same, exit the loop if(deal_time==pos.time && deal_symbol==_Symbol) break; } } //--- return(deal_price); }
Buradaki prensip önceki fonksiyondaki ile aynıdır. Pozisyon açılış noktasından itibaren geçmişi alırız ve ardından her yinelemede işlemin zamanını ve pozisyon açılış zamanını kontrol ederiz. İşlemin fiyatıyla birlikte, işlemin sembol adını ve zamanını elde ederiz. İlk işlem, işlem zamanı pozisyon açılış zamanı ile kesiştiğinde belirlenir. Fiyatı zaten ilgili değişkene atanmış olduğundan, yalnızca değeri döndürmemiz gerekir.
Devam edelim. Bazen, mevcut pozisyondaki son işlemin fiyatını elde etmeniz gerekebilir. Bunun için, bir CurrentPositionLastDealPrice() fonksiyonu oluşturacağız:
//+------------------------------------------------------------------+ //| Returning the price of the last deal in the current position | //+------------------------------------------------------------------+ double CurrentPositionLastDealPrice() { int total =0; // Total deals in the selected history list string deal_symbol =""; // Symbol of the deal double deal_price =0.0; // Price //--- If the position history is obtained if(HistorySelect(pos.time,TimeCurrent())) { //--- Get the number of deals in the obtained list total=HistoryDealsTotal(); //--- Iterate over all the deals in the obtained list from the last deal in the list to the first deal for(int i=total-1; i>=0; i--) { //--- Get the price of the deal deal_price=HistoryDealGetDouble(HistoryDealGetTicket(i),DEAL_PRICE); //--- Get the symbol of the deal deal_symbol=HistoryDealGetString(HistoryDealGetTicket(i),DEAL_SYMBOL); //--- If the symbol of the deal and the current symbol are the same, exit the loop if(deal_symbol==_Symbol) break; } } //--- return(deal_price); }
Bu sefer döngü, listedeki son işlem ile başlamıştır ve bu durumda genellikle gerekli işlem ilk döngü yinelemesinde tanımlanır. Ancak birkaç sembol üzerinde alım satım yaparsanız, döngü işlemin sembolü mevcut sembolle eşleşene kadar devam eder.
Mevcut pozisyon hacmi, POSITION_VOLUME standart tanımlayıcısı kullanılarak elde edilebilir. İlk pozisyon hacmini (ilk işlemin hacmi) bulmak için bir CurrentPositionInitialVolume() fonksiyonu oluşturacağız:
//+------------------------------------------------------------------+ //| Returning the initial volume of the current position | //+------------------------------------------------------------------+ double CurrentPositionInitialVolume() { int total =0; // Total deals in the selected history list ulong ticket =0; // Ticket of the deal ENUM_DEAL_ENTRY deal_entry =WRONG_VALUE; // Position modification method bool inout =false; // Flag of position reversal double sum_volume =0.0; // Counter of the aggregate volume of all deals, except for the first one double deal_volume =0.0; // Volume of the deal string deal_symbol =""; // Symbol of the deal datetime deal_time =NULL; // Deal execution time //--- If the position history is obtained if(HistorySelect(pos.time,TimeCurrent())) { //--- Get the number of deals in the obtained list total=HistoryDealsTotal(); //--- Iterate over all the deals in the obtained list from the last deal in the list to the first deal for(int i=total-1; i>=0; i--) { //--- If the order ticket by its position is obtained, then... if((ticket=HistoryDealGetTicket(i))>0) { //--- Get the volume of the deal deal_volume=HistoryDealGetDouble(ticket,DEAL_VOLUME); //--- Get the position modification method deal_entry=(ENUM_DEAL_ENTRY)HistoryDealGetInteger(ticket,DEAL_ENTRY); //--- Get the deal execution time deal_time=(datetime)HistoryDealGetInteger(ticket,DEAL_TIME); //--- Get the symbol of the deal deal_symbol=HistoryDealGetString(ticket,DEAL_SYMBOL); //--- When the deal execution time is less than or equal to the position opening time, exit the loop if(deal_time<=pos.time) break; //--- otherwise calculate the aggregate volume of deals by the position symbol, except for the first one if(deal_symbol==_Symbol) sum_volume+=deal_volume; } } } //--- If the position modification method is a reversal if(deal_entry==DEAL_ENTRY_INOUT) { //--- If the position volume has been increased/decreased // I.e. the number of deals is more than one if(fabs(sum_volume)>0) { //--- Current volume minus the volume of all deals except for the first one double result=pos.volume-sum_volume; //--- If the resulting value is greater than zero, return the result, otherwise return the current position volume deal_volume=result>0 ? result : pos.volume; } //--- If there are no more deals, other than the entry, if(sum_volume==0) deal_volume=pos.volume; // return the current position volume } //--- Return the initial position volume return(NormalizeDouble(deal_volume,2)); }
Bu fonksiyon öncekilerden daha karmaşıktır. Yanlış değere yol açabilecek tüm olası durumları dikkate almaya çalıştım. Dikkatli bir test herhangi bir sorun ortaya koymadı. Kodda verilen ayrıntılı yorumlar konuyu anlamanıza yardımcı olacaktır.
Pozisyon süresini döndüren bir fonksiyonun olması da faydalı olacaktır. Bunu, kullanıcının döndürülen değerin uygun biçimini seçmesine olanak sağlayacak şekilde ayarlayacağız: saniye, dakika, saat veya gün. Bunun için, başka bir numaralandırma oluşturalım:
//--- Position duration enum ENUM_POSITION_DURATION { DAYS = 0, // Days HOURS = 1, // Hours MINUTES = 2, // Minutes SECONDS = 3 // Seconds };
Aşağıda, ilgili hesaplamaların tamamından sorumlu CurrentPositionDuration() fonksiyon kodu yer almaktadır:
//+------------------------------------------------------------------+ //| Returning the duration of the current position | //+------------------------------------------------------------------+ ulong CurrentPositionDuration(ENUM_POSITION_DURATION mode) { ulong result=0; // End result ulong seconds=0; // Number of seconds //--- Calculate the position duration in seconds seconds=TimeCurrent()-pos.time; //--- switch(mode) { case DAYS : result=seconds/(60*60*24); break; // Calculate the number of days case HOURS : result=seconds/(60*60); break; // Calculate the number of hours case MINUTES : result=seconds/60; break; // Calculate the number of minutes case SECONDS : result=seconds; break; // No calculations (number of seconds) //--- default : Print(__FUNCTION__,"(): Unknown duration mode passed!"); return(0); } //--- Return result return(result); }
Pozisyon özelliklerinin görüntülendiği bilgi paneli için bir CurrentPositionDurationToString() fonksiyonu oluşturalım. Fonksiyon, saniye cinsinden pozisyon süresini kullanıcının kolayca anlayabileceği bir biçime dönüştürür. Saniye sayısı fonksiyona aktarılacak ve fonksiyon sırası geldiğinde gün, saat, dakika ve saniye cinsinden pozisyon süresini içeren bir dize döndürecektir:
//+------------------------------------------------------------------+ //| Converting the position duration to a string | //+------------------------------------------------------------------+ string CurrentPositionDurationToString(ulong time) { //--- A dash if there is no position string result="-"; //--- If the position exists if(pos.exists) { //--- Variables for calculation results ulong days=0; ulong hours=0; ulong minutes=0; ulong seconds=0; //--- seconds=time%60; time/=60; //--- minutes=time%60; time/=60; //--- hours=time%24; time/=24; //--- days=time; //--- Generate a string in the specified format DD:HH:MM:SS result=StringFormat("%02u d: %02u h : %02u m : %02u s",days,hours,minutes,seconds); } //--- Return result return(result); }
Her şey ayarlandı ve şimdi hazır. Yukarıdaki değişikliklerin tamamına göre değiştirilmesi gereken GetPositionProperties() ve GetPropertyValue() fonksiyon kodlarını vermeyeceğim. Serinin önceki tüm makalelerini okursanız, bunu kendi başınıza yapmakta zorluk çekmemeniz lazım. Yine de, kaynak kod dosyası makaleye eklenmiştir.
Bunun sonucunda, bilgi paneli aşağıda gösterildiği gibi görünmelidir:
Şekil 7. Tüm pozisyon özelliklerinin bilgi panelinde gösterimi.
Dolayısıyla, şimdi pozisyon özelliklerini elde etmek için fonksiyon kitaplığımız var ve muhtemelen gelecekteki makalelerde gerektiğinde ve gerektiği şekilde bunun üzerine çalışmaya devam edeceğiz.
Parametreleri Optimize Etme ve Uzman Danışmanı Test Etme
Bir deney olarak, Uzman Danışmanın parametrelerini optimize etmeye çalışalım. Şu anda elimizdeki şey henüz tam özellikli bir alım satım sistemi olarak adlandırılamasa da, elde edeceğimiz sonuç bazı konularda gözlerimizi açacak ve alım satım sistemleri geliştiricileri olarak tecrübemizi artıracaktır.
Aşağıda gösterilen Strateji Test Cihazı ayarlarını yapacağız:
Şekil 8. Parametre optimizasyonu için Uzman Danışman ayarları
Uzman Danışmanın harici parametrelerinin ayarları aşağıdaki şekilde olmalıdır:
Şekil 9. Optimizasyon için Uzman Danışman parametre ayarları.
Optimizasyon sonrasında, elde edilen sonuçları maksimum kurtarma faktörüne göre sıralarız:
Şekil 10. Maksimum kurtarma faktörüne göre sıralanmış sonuçlar.
Şimdi Kurtarma Faktörü değeri 4,07'ye eşit olacak şekilde en üstteki parametre setini test edelim. Optimizasyon EURUSD için yapılmış olmasına rağmen, birçok sembol için olumlu sonuçlar görebiliriz:
EURUSD için sonuçlar:
Şekil 11. EURUSD için sonuçlar.
AUDUSD için sonuçlar:
Şekil 12. AUDUSD için sonuçlar.
NZDUSD için sonuçlar:
Şekil 13. NZDUSD için sonuçlar.
Sonuç
Hemen hemen her fikir geliştirilebilir ve iyileştirilebilir. Her alım satım sistemi, kusurlu diye reddedilmeden önce çok dikkatli bir şekilde test edilmelidir. Gelecek makalelerde, hemen hemen her alım satım sistemini özelleştirmede ve uyarlamada çok olumlu bir rol oynayabilecek çeşitli mekanizmalara ve şemalara göz atacağız.
MetaQuotes Ltd tarafından Rusçadan çevrilmiştir.
Orijinal makale: https://www.mql5.com/ru/articles/644
- Ü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