
Uzman Danışmanlarda Sınırlamalar ve Doğrulamalar
Giriş
Otomatik alım satım için bir algoritma oluştururken, hem alım satım sinyalleri oluşturmak için fiyatları işleyebilmeli hem de Uzman Danışmanların işleyişine getirilen sınırlamalar hakkında birçok yardımcı bilgi alabilmelisiniz. Bu makale size şunları nasıl yapacağınızı söyleyecektir:
- Alım satım oturumları hakkında bilgi almak;
- Bir pozisyon açmak için yeterli varlığınız olup olmadığını kontrol etmek;
- Bir sembolle toplam işlem hacmine bir sınırlama getirmek;
- Toplam emir sayısına bir sınırlama getirmek;
- Giriş fiyatı ile Zararı Durdur arasındaki potansiyel kaybı hesaplamak;
- Yeni bir çubuk olup olmadığını kontrol etmek.
Alım Satım ve Teklif Oturumları
Alım satım oturumları hakkında bilgi almak için SymbolInfoSessionTrade() fonksiyonunu, teklif oturumları içinse ilgili SymbolInfoSessionQuote() fonksiyonunu kullanmalısınız. Her iki fonksiyon da aynı şekilde çalışır: Haftanın belirtilen günü için belirtilen indekse sahip bir oturum varsa (oturumların indekslenmesi sıfırdan başlar), fonksiyon true değerini döndürür. Bir oturumun başlama ve bitiş zamanı, linkten geçen dördüncü ve beşinci parametrelere yazılır.
//--- check if there is a quotation session with the number session_index bool session_exist=SymbolInfoSessionQuote(symbol,day,session_index,start,finish);Belirtilen günün tüm oturumlarını bulmak için, bu fonksiyonu false döndürene kadar bir döngü halinde çağırın.
//+------------------------------------------------------------------+ //| Display information about quotation sessions | //+------------------------------------------------------------------+ void PrintInfoForQuoteSessions(string symbol,ENUM_DAY_OF_WEEK day) { //--- start and end of session datetime start,finish; uint session_index=0; bool session_exist=true; //--- go over all sessions of this day while(session_exist) { //--- check if there is a quotation session with the number session_index session_exist=SymbolInfoSessionQuote(symbol,day,session_index,start,finish); //--- if there is such session if(session_exist) { //--- display the day of week, the session number and the time of start and end Print(DayToString(day),": session index=",session_index," start=", TimeToString(start,TIME_MINUTES)," finish=",TimeToString(finish-1,TIME_MINUTES|TIME_SECONDS)); } //--- increase the counter of sessions session_index++; } }
Haftanın günü, parametre olarak ENUM_DAY_OF_WEEK numaralandırmasının değerini alan DayToString() özel fonksiyonu kullanılarak dize biçiminde görüntülenir.
//+------------------------------------------------------------------+ //| Receive the string representation of a day of week | //+------------------------------------------------------------------+ string DayToString(ENUM_DAY_OF_WEEK day) { switch(day) { case SUNDAY: return "Sunday"; case MONDAY: return "Monday"; case TUESDAY: return "Tuesday"; case WEDNESDAY: return "Wednesday"; case THURSDAY: return "Thursday"; case FRIDAY: return "Friday"; case SATURDAY: return "Saturday"; default: return "Unknown day of week"; } return ""; }
SymbolInfoSession.mq5 betiğinin son kodu makalenin sonuna eklenmiştir. Burada sadece ana kısmını gösterelim.
void OnStart() { //--- the array where the days of week are stored ENUM_DAY_OF_WEEK days[]={SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY}; int size=ArraySize(days); //--- Print("Quotation sessions"); //--- go over all the days of week for(int d=0;d<size;d++) { PrintInfoForQuoteSessions(Symbol(),days[d]); } //--- Print("Trading sessions"); //--- go over all the days of week for(int d=0;d<size;d++) { PrintInfoForTradeSessions(Symbol(),days[d]); } }
Marjı Kontrol Etme
Bir pozisyonu açmak veya arttırmak için gereken marj miktarını bulmak için OrderCalcMargin() fonksiyonunu kullanabilirsiniz; ona iletilen ilk parametre, ENUM_ORDER_TYPE numaralandırmasından bir değerdir. Satın alma işlemi için bunu ORDER_TYPE_BUY parametresi ile çağırmalısınız; satmak içinORDER_TYPE_SELL parametresini kullanın. Fonksiyon, marj miktarını lot sayısına ve açılış fiyatına bağlı olarak döndürür.
void OnStart() { //--- the variable to receive the value of margin double margin; //--- to receive information about the last tick MqlTick last_tick; //--- try to receive the value from the last tick if(SymbolInfoTick(Symbol(),last_tick)) { //--- reset the last error code ResetLastError(); //--- calculate margin value bool check=OrderCalcMargin(type,Symbol(),lots,last_tick.ask,margin); if(check) { PrintFormat("For the operation %s %s %.2f lot at %G required margin is %.2f %s",OrderTypeToString(type), Symbol(),lots,last_tick.ask,margin,AccountInfoString(ACCOUNT_CURRENCY)); } } else { Print("Unsuccessful execution of the SymbolInfoTick() function, error ",GetLastError()); } }
OrderCalcMargin() fonksiyonunun, marj değerinin sadece piyasa emirleri için değil, aynı zamanda bekleyen emirler için de hesaplanmasını sağladığına dikkat edilmelidir. Check_Money.mq5 betiğini kullanarak tüm emir türleri için döndürülen değerleri kontrol edebilirsiniz.
OrderCalcMargin() fonksiyonu, bekleyen emirler için marj büyüklüğünün hesaplanması amacıyla tasarlanmıştır, çünkü bazı alım satım sistemlerinde bekleyen emirler için de bir para desteği gerekebilir. Bekleyen emirler için marj büyüklüğü, genellikle uzun ve kısa pozisyonlar için marj büyüklüğüne yönelik bir katsayı ile hesaplanır.
Tanımlayıcı | Açıklama | Özellik Türü |
SYMBOL_MARGIN_LONG | Uzun pozisyonlarda alınan marjin oranı | çift |
SYMBOL_MARGIN_SHORT | Kısa pozisyonlarda alınan marjin oranı | çift |
SYMBOL_MARGIN_LIMIT | Limit emirlerinde alınan marjin oranı | çift |
SYMBOL_MARGIN_STOP | Stop emirlerinde alınan marjin oranı | çift |
SYMBOL_MARGIN_STOPLIMIT | Stop Limit emirlerinde alınan marjin oranı | çift |
Basit bir kodu kullanarak bu katsayıların değerlerini alabilirsiniz:
//--- Calculate the rates of margin charging for different types of orders PrintFormat("Rate of margin charging on long positions is equal to %G",SymbolInfoDouble(Symbol(),SYMBOL_MARGIN_LONG)); PrintFormat("Rate of margin charging on short positions is equal to %G",SymbolInfoDouble(Symbol(),SYMBOL_MARGIN_SHORT)); PrintFormat("Rate of margin charging on Limit orders is equal to %G",SymbolInfoDouble(Symbol(),SYMBOL_MARGIN_LIMIT)); PrintFormat("Rate of margin charging on Stop orders is equal to %G",SymbolInfoDouble(Symbol(),SYMBOL_MARGIN_STOP)); PrintFormat("Rate of margin charging on Stop Limit orders is equal to %G",SymbolInfoDouble(Symbol(),SYMBOL_MARGIN_STOPLIMIT));
Forex sembollerinde, bekleyen emirler için marj yükleme oranları genellikle 0'a eşittir, yani onlar için herhangi bir marj gereksinimi yoktur.
Check_Money.mq5 betiğinin yürütme sonuçları.
Marj yükleme yöntemine bağlı olarak, para yönetimi sistemi değişebilir ve bekleyen emirler için bir marj gerekliyse alım satım sisteminin kendisi bazı sınırlamalarla karşılaşabilir. Bu nedenle, bu parametreler aynı zamanda bir Uzman Danışmanın çalışmasının doğal sınırlamaları olabilir.
Muhtemel Kâr ve Zararların Muhasebesi
Koruyucu bir durdurma seviyesi yerleştirirken, bunun tetiklenmesine hazır olmalısınız. Olası kayıp riski parasal açıdan dikkate alınmalıdır; ve OrderCalcProfit() bu amaca yöneliktir. Önceden düşünülen OrderCalcMargin() fonksiyonuna çok benzer, ancak hesaplamalar için hem açılış hem de kapanış fiyatlarını gerektirir.
İlk parametre olarak ENUM_ORDER_TYPE numaralandırmasının iki değerinden birini belirtin (ORDER_TYPE_BUY veya ORDER_TYPE_SELL); diğer emir türleri bir hataya yol açacaktır. Son parametrede, başarılı yürütme durumunda OrderCalcProfit() fonksiyonunun kar/zarar değerini yazacağı referansı kullanarak bir değişken geçirmelisiniz.
Belirtilen giriş ve çıkış seviyeleri ile uzun bir pozisyonu kapatırken kâr veya zararı hesaplayan CalculateProfitOneLot() fonksiyonunu kullanma örneği:
//+------------------------------------------------------------------+ //| Calculate potential profit/loss for buying 1 lot | //+------------------------------------------------------------------+ double CalculateProfitOneLot(double entry_price,double exit_price) { //--- receive the value of profit to this variable double profit=0; if(!OrderCalcProfit(ORDER_TYPE_BUY,Symbol(),1.0,entry_price,exit_price,profit)) { Print(__FUNCTION__," Failed to calculate OrderCalcProfit(). Error ",GetLastError()); } //--- return(profit); }
Bu fonksiyonun hesaplama sonucu şekilde gösterilmiştir.
OrderCalcProfit() fonksiyonunu kullanarak olası kaybı hesaplama ve grafikte görüntüleme örneği.
Kodun tamamı ekteki Uzman Danışman CalculateProfit_EA.mq5'te bulunabilir.
Yeni Bir Çubuk Olup Olmadığını Kontrol Etme
Birçok alım satım sisteminin geliştirilme sürecinde, alım satım sinyallerinin yalnızca yeni bir çubuk ortaya çıktığında hesaplandığı varsayılır ve tüm alım satım işlemleri yalnızca bir kez gerçekleştirilir. MetaTrader 5 müşteri terminalindeki strateji sınama aracının "Yalnızca açılış fiyatları" modu, bu tür otomatik alım satım sistemlerini kontrol etmek için iyidir.
"Yalnızca açılış fiyatları" modunda, tüm gösterge hesaplamaları ve Uzman Danışman’daki OnTick() fonksiyonunun çağrısı, sınama sırasında çubuk başına yalnızca bir kez gerçekleştirilir. Bu, en hızlı alım satım modudur ve kural olarak, önemsiz fiyat dalgalanmalarına karşı hatalara en dayanıklı alım satım sistemleri oluşturma yoludur. Aynı zamanda bir Uzman Danışmanda kullanılan göstergeler elbette doğru şekilde yazılmalı ve yeni bir çubuk geldiğinde değerleri bozulmamalıdır.
"Yalnızca açılış fiyatlar" modundaki strateji sınama aracıyla, Uzman Danışmanın çubuk başına yalnızca bir kez başlatılmasına dikkat etmenize gerek kalmaz ve bu çok kullanışlıdır. Ancak, bir demo veya gerçek bir hesap üzerinde gerçek zamanlı modda çalışan bir yatırımcı, alınan sinyal başına yalnızca bir alım satım işlemi gerçekleştirdiğinden emin olmak için Uzman Danışmanının etkinliğini kontrol etmelidir. Bunun en kolay yolu, mevcut biçimlendirilmemiş çubuğun açılışının izlenmesidir.
Son çubuğun açılış zamanını almak için, belirtilen sembol adı, zaman aralığı ve SERIES_LASTBAR_DATE özelliği ile SeriesInfoInteger() fonksiyonunu kullanmalısınız. Mevcut çubuğun açılma zamanını bir değişkende saklanan çubuklardan biriyle sürekli karşılaştırarak, yeni bir çubuğun ortaya çıktığı anı kolayca tespit edebilirsiniz. Bu, aşağıdaki gibi görünebilen isNewBar() özel fonksiyonunun oluşturulmasını mümkün kılar:
//+------------------------------------------------------------------+ //| Return true if a new bar appears for the symbol/period pair | //+------------------------------------------------------------------+ bool isNewBar() { //--- remember the time of opening of the last bar in the static variable static datetime last_time=0; //--- current time datetime lastbar_time=SeriesInfoInteger(Symbol(),Period(),SERIES_LASTBAR_DATE); //--- if it is the first call of the function if(last_time==0) { //--- set time and exit last_time=lastbar_time; return(false); } //--- if the time is different if(last_time!=lastbar_time) { //--- memorize time and return true last_time=lastbar_time; return(true); } //--- if we pass to this line then the bar is not new, return false return(false); }
Ekteki Uzman Danışman CheckLastBar.mq5'te fonksiyonun kullanımına ilişkin bir örnek verilmiştir.
CheckLastBar Uzman Danışmanının M1 zaman aralığında yeni çubukların görünmesine dair mesajları.
Bekleyen Emir Sayısını Sınırlama
Bir hesaba aynı anda yerleştirilebilecek aktif bekleyen emirlerin sayısını sınırlamanız gerekiyorsa, kendi özel fonksiyonunuzu yazabilirsiniz. Adını IsNewOrderAllowed() olarak koyalım; başka bir bekleyen emir verme izni olup olmadığını kontrol edecektir. Otomatikleştirilmiş Alım Satım Şampiyonası kurallarına uygun olacak şekilde yazalım.
//+------------------------------------------------------------------+ //| Checks if it is allowed to place another order | //+------------------------------------------------------------------+ bool IsNewOrderAllowed() { //--- get the allowed number of pending orders on an account int max_allowed_orders=(int)AccountInfoInteger(ACCOUNT_LIMIT_ORDERS); //--- if there is no limitations, return true; you can send an order if(max_allowed_orders==0) return(true); //--- if we pass to this line, then there are limitations; detect how many orders are already active int orders=OrdersTotal(); //--- return the result of comparing return(orders<max_allowed_orders); }
Fonksiyon basittir: İzin verilen emir sayısını max_allowed_orders değişkenine alın ve değeri sıfır değilse, mevcut emir sayısıyla karşılaştırın. Ancak, bu fonksiyon başka bir olası sınırlamayı dikkate almaz; yani belirli bir sembolde izin verilen toplam açık pozisyon hacmi ve bekleyen emirler üzerindeki sınırlamayı.
Belirli Bir Sembolde Lot Sayısını Sınırlama
Belirli bir sembolde açık pozisyonun büyüklüğünü elde etmek için öncelikle PositionSelect() fonksiyonunu kullanarak bir pozisyon seçmeniz gerekir. Ancak bundan sonra PositionGetDouble(); kullanarak açık pozisyonun hacmini talep edebilirsiniz; bu, çift tipte seçilen pozisyonun çeşitli özelliklerini döndürür. Verilen bir sembole göre pozisyon hacmini elde etmek için PostionVolume() fonksiyonunu yazalım.
//+------------------------------------------------------------------+ //| Returns the size of position by a specific symbol | //+------------------------------------------------------------------+ double PositionVolume(string symbol) { //--- try to select a positions by a symbol bool selected=PositionSelect(symbol); //--- the position exists if(selected) //--- return the position volume return(PositionGetDouble(POSITION_VOLUME)); else { //--- report about the unsuccessful attempt to select the position Print(__FUNCTION__," Failed to execute PositionSelect() for the symbol ", symbol," Error ",GetLastError()); return(-1); } }
Bir sembolde bekleyen emir vermek için bir alım satım talebinde bulunmadan önce, o sembole göre toplam açık pozisyon ve bekleyen emir hacmindeki sınırlamayı kontrol etmelisiniz - SYMBOL_VOLUME_LIMIT. Herhangi bir sınırlama yoksa, bekleyen bir emrin hacmi, SymbolInfoDouble() hacmi kullanılarak alınabilecek izin verilen maksimum hacmi aşamaz.
double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_LIMIT); if(max_volume==0) volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
Ancak bu yaklaşım, belirtilen sembole göre mevcut bekleyen emirlerin hacmini dikkate almaz. Bu değeri hesaplayan bir fonksiyon yazalım:
//+------------------------------------------------------------------+ //| Returns the size of position by a specified symbol | //+------------------------------------------------------------------+ double PositionVolume(string symbol) { //--- try to select a position by a symbol bool selected=PositionSelect(symbol); //--- the position exist if(selected) //--- return the position volume return(PositionGetDouble(POSITION_VOLUME)); else { //--- return zero if there is no position return(0); } }
Açık pozisyon hacmi ve bekleyen emirlerin hacmi dikkate alındığında, son kontrol aşağıdaki gibi olacaktır:
//+------------------------------------------------------------------+ //| Returns maximum allowed volume for an order by a symbol | //+------------------------------------------------------------------+ double NewOrderAllowedVolume(string symbol) { double allowed_volume=0; //--- get the limitation on the maximum volume of an order double symbol_max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX); //--- get the limitation of volume by a symbol double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_LIMIT); //--- get the volume of open position by a symbol double opened_volume=PositionVolume(symbol); if(opened_volume>=0) { //--- if we already used available volume if(max_volume-opened_volume<=0) return(0); //--- volume of the open position doen't exceed max_volume double orders_volume_on_symbol=PendingsVolume(symbol); allowed_volume=max_volume-opened_volume-orders_volume_on_symbol; if(allowed_volume>symbol_max_volume) allowed_volume=symbol_max_volume; } return(allowed_volume); }
Bu bölümde bahsedilen fonksiyonları içeren Check_Order_And_Volume_Limits.mq5 Uzman Danışmanı kodunun tamamı makaleye eklenmiştir.
2010 Otomatikleştirilmiş Alım Satım Şampiyonası katılımcısının hesabında Check_Order_And_Volume_Limits Uzman Danışmanı kullanılarak yapılan kontrol örneği.
Hacmin Doğruluğunu Kontrol Etme
Herhangi bir alım satım robotunun önemli bir parçası da bir alım satım işlemi gerçekleştirmek için doğru hacmi seçme yeteneğidir. Burada para yönetimi ve risk yönetimi sistemlerinden değil, hacmin bir sembolün karşılık gelen özelliklerine göre doğru olması hakkında konuşacağız.
Tanımlayıcı | Açıklama | Özellik Türü |
SYMBOL_VOLUME_MIN | Bir yatırım için en düşük hacim | çift |
SYMBOL_VOLUME_MAX | Bir yatırım için en yüksek hacim | çift |
SYMBOL_VOLUME_STEP | Yatırımın gerçekleştirilmesi için en düşük hacim değişim birimi | çift |
Böyle bir doğrulamayı gerçekleştirmek için, CheckVolumeValue() özel fonksiyonunu yazabiliriz:
//+------------------------------------------------------------------+ //| Check the correctness of volume of an order | //+------------------------------------------------------------------+ bool CheckVolumeValue(double volume,string &description) { //--- Minimum allowed volume for trade operations double min_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN); if(volume<min_volume) { description=StringFormat("Volume is less than the minimum allowed SYMBOL_VOLUME_MIN=%.2f",min_volume); return(false); } //--- Maximum allowed volume for trade opertations double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX); if(volume>max_volume) { description=StringFormat("Volume is greater than the maximum allowed SYMBOL_VOLUME_MAX=%.2f",max_volume); return(false); } //--- get the minimal volume change step double volume_step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP); int ratio=(int)MathRound(volume/volume_step); if(MathAbs(ratio*volume_step-volume)>0.0000001) { description=StringFormat("Volume is not a multiple of minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f", volume_step,ratio*volume_step); return(false); } description="Correct value of volume "; return(true); }
Makaleye eklenen CheckVolumeValue.mq5 betiğini kullanarak bu fonksiyonun çalışmasını kontrol edebilirsiniz.
Hacmin doğru olup olmadığını kontrol eden CheckVolumeValue.mq5 mesajları.
Sonuç
Bu makale, bir Uzman Danışmanın çalışmasıyla ilgili olarak, kendi otomatik alım sayım sisteminizi oluştururken karşılaşabileceğiniz olası sınırlamalar için temel doğrulamaları açıklamaktadır. Bu örnekler, bir alım satım hesabındaki bir Uzman Danışmanın çalışması sırasında kontrol edilmesi gereken tüm olası koşulları kapsamamaktadır. Elbette bu örneklerin, yeni başlayan kişilerin MQL5 dilinde en yaygın doğrulamaların nasıl uygulanacağını anlamalarına yardımcı olacağını umuyoruz.
MetaQuotes Ltd tarafından Rusçadan çevrilmiştir.
Orijinal makale: https://www.mql5.com/ru/articles/22





- Ücretsiz alım-satım 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