Alım-Satım Stratejilerinin Sınanması

Otomatik alım-satım fikri, bir alım-satım robotunun haftanın 7 günü 24 saat aralıksız çalışabilmesinden kaynaklanmaktadır. Robotlar yorulmaz, şüpheye düşmez ve korkmaz, tüm psikolojik problemlerden uzaktır. Sadece alım-satım kurallarının belirlenmesi ve bir algoritmada uygulanması yeterlidir; ve robot, yorulmadan çalışmak için hazırdır. Ama ilk önce, şu iki koşulun sağlandığından emin olmanız gerekir:

  • Uzman Danışman, alım-satım sisteminin kurallarına bağlı olarak alım-satım işlemleri gerçekleştirir;
  • Uzman Danışman içine uygulanan alım-satım stratejisi geçmiş veri üzerinde karlılık gösterir.

Bu iki sorunun cevabını alabilmek için, MetaTrader 5 müşteri terminaline eklenmiş olan Strateji Sınama aracına ihtiyaç duyarız.

Bu bölüm, programların Strateji Sınayıcı içinde sınanması ve optimizasyonu ile ilgili özellikleri kapsamaktadır:

 

MQL5 Bulut Ağında bellek ve disk alanı sınırları

MQL5 Bulut Ağında yürütülen optimizasyonlar için şu sınırlama mevcuttur: Uzman Danışman, diske 4 GB'tan fazla bilgi yazmamalı veya 4 GB'tan fazla RAM kullanmamalıdır. Sınır aşılırsa ağ temsilcisi hesaplamayı doğru bir şekilde tamamlayamaz ve dolayısıyla sonucu alamazsınız. Ancak yine de hesaplamalara harcanan tüm süre için ücretlendirilirsiniz.

Her optimizasyon geçişinden bilgi almanız gerekiyorsa, çerçeveleri diske yazmadan gönderin. MQL5 Bulut Ağında hesaplamalar sırasında Uzman Danışmandaki dosya işlemlerini kullanmaktan kaçınmak için aşağıdaki kontrolü kullanabilirsiniz:

   int handle=INVALID_HANDLE;
   bool file_operations_allowed=true;
   if(MQLInfoInteger(MQL_OPTIMIZATION) || MQLInfoInteger(MQL_FORWARD))
      file_operations_allowed=false;
 
   if(file_operations_allowed)
     {
      ...
      handle=FileOpen(...);
      ...
     }

 

Strateji Sınayıcı Dahilindeki Fonksiyon Kıstıtlamaları #

Müşteri terminalinin bünyesinde yer alan Strateji Sınayıcı içinde, bazı fonksiyonlar için işlem kısıtlamaları bulunur.

Comment(), Print() ve PrintFormat() Fonksiyonları #

Alım-satım robotları optimize edilirken Comment(), Print() ve PrintFormat() fonksiyonları performansı artırmak için çalıştırılmaz. Bu fonksiyonların OnInit() işleyicisinin içinde kullanılması bu ksıtlamalara bir istisna oluşturur. Böylece hataların neden kaynaklandığını kolayca bulabilirsiniz.

Alert(), MessageBox(), PlaySound(), SendFTP, SendMail(), SendNotification(), WebRequest() Fonksiyonları #

Alert(), MessageBox(), PlaySound(), SendFTP(), SendMail(), SendNotification() ve WebRequest() fonksiyonları dış dünya ile iletişim için tasarlanmıştır ve Strateji Sınayıcı içinde çalıştırılmazlar.

 

Tik Oluşturma modları #

Uzman Danışman, MQL5 dilinde yazılan ve her seferinde bazı dışsal olaylara yanıt olarak çalışan bir programdır. Uzman danışman, her ön-tanımlı olay için karşılık gelen bir fonksiyon (olay işleyici) içerir.

NewTick olayı (fiyat değişimi) bir Uzman için ana olaydır, bu nedenle, Uzman Danışmanı sınayabilmek için bir tik dizisine gereksinim duyarız. MetaTrader 5 müşteri terminalinin Strateji Sınama aracında uygulanan 3 adet tik oluşturma modu bulunmaktadır:

  • Every tick
  • 1 dakikalık çubuklarla OHLC fiyatları (1 Minute OHLC)
  • Open prices only

En temel ve en detaylı olanı "Her tik" (Every tick) modudur, diğer iki mod ise temel modun basitleştirilmiş halidir ve "Her tik" moduyla karşılaştırmalı olarak açıklanacaklardır. Aralarındaki farkı anlamak amacıyla üç modun tamamını düşünün.

"Her tik"

Finansal enstrümanlara dair geçmiş fiyat verileri, dakikalık çubuklar şeklinde paketlenmiş olarak sunucudan MetaTrader 5 müşteri terminaline aktarılır. İsteklerin yapılmasına ve istenen zaman aralığının yapımına dair detaylı bilgiyi, MQL5 Referans dosyasının Veri Erişiminin Düzenlenmesi bölümünde bulabilirsiniz.

Fiyat geçmişinin en küçük elemanı dakikalık çubuktur, bundan dört fiyat değerine dair verileri alabilirsiniz:

  • Open - dakikalık çubuğun açılış fiyatı;
  • High - dakikalık çubuk içinde gerçekleşmiş en yüksek fiyat değeri;
  • Low - dakikalık çubuk içinde gerçekleşmiş en düşük fiyat değeri;
  • Close - çubuğun kapanış fiyatı.

Yeni dakikanın çubuğu, yeni dakikanın başlamasıyla (toplam saniye sayısının 0 olmasıyla) değil, en az bir puanlık bir fiyat değişimini içeren yeni bir tikin gelmesiyle açılır. Aşağıdaki resim, yeni işlem haftasının 2011.01.10 00:00 açılış zamanına sahip ilk bir dakikalık çubuğunu göstermektedir. Cuma ve Pazartesi günleri arasındaki fiyat boşluğu, kurların gelen haberlere bağlı olarak, hafta-sonu da dalgalanmaları nedeniyle sık karşılaşılan bir durumdur.

Cuma ve Pazartesi arasındaki fiyat boşluğu

Bu çubuğun 10 ocak 2011 günü 00 saatinde ve 00 dakikasında başladığını biliyoruz ama saniye hakkında hiç bir bilgimiz yok. 00:00:12'de , 00:00:36'da (yeni günün başlangıcından 12 veya 36 saniye sonra) veya o dakika içerisindeki herhangi bir anda açılmış olabilir. Ama EURUSD Open (açılış) fiyatının, açılış anında 1.28940 olduğunu bilebiliriz.

Ayrıca söz konusu dakikalık çubuğun kapanışına karşılık gelen tik fiyatının, saniye içerisindeki geliş anını tam olarak bilmiyoruz. Sadece bir şey biliyoruz : bir dakikalık çubuğun son Close (kapanış) fiyatını. Bu dakika için fiyat 1.28958 seviyesinde. High ve Low fiyatlarının oluşma anlarını da bilmiyoruz ama maksimum ve minimum fiyatların sırasıyla 1.28958 ve 1.28940 seviyelerinde olduğunu biliyoruz.

Alım satım stratejisini sınamak amacıyla, Uzman Danışmanın çalışmasını simüle edebileceğimiz, tiklerden oluşan bir diziye ihtiyaç duyarız. Bu şekilde, her bir dakikalık çubuk için, fiyatın kesinlikle uğramış olduğu 4 kontrol noktasını biliriz. Bir çubuğun dört tik içerdiğini biliyorsak, bu bilgi bir sınama gerçekleştirmek için yeterli olacaktır, diğer taraftan tik hacmi genellikle dördün üzerindedir.

İşte bu nedenle, Open, High, Low ve Close fiyatlarının arasında, ek kontrol noktaları oluşturulması gerekir. "Her tik" tik oluşturma modunun temel ilkesi MetaTrader 5 Terminalinin Strateji Sınama Aracının Tik Oluşturma Algoritması kısmında açıklanmıştır, aşağıdaki şekilde temsil edilmektedir.

Tik oluşturma algoritması

"Her tik" modunda sınama yapılırken, Uzman Danışmanın OnTick() fonksiyou her kontrol noktasında çağrılacaktır. Her kontrol noktası oluşturulan diziden gelen bir tiktir. Uzman Danışman, simüle edilen tik zamanını ve fiyatını çevirim-içi çalışmalarda olduğu gibi alacaktır.

Önemli: "Her tik", en gerçekçi sınama modudur ama aynı zamanda en çok zaman harcayandır. Alım-satım stratejilerinin büyük çoğunluğu için, başlangıç olarak diğer iki sınama modunun kullanımı, genellikle yeterlidir.

"1 Dakikalık OHLC"

"Her tik" modu, üç sınama modu arasında en gerçekçi olandır ama aynı zamanda en yavaşıdır. OnTick() işleyicisinin çalışması her tikte gerçekleşir ve tik hacmi oldukça büyük olabilir. Çubuk içindeki minimal fiyat hareketlerinin önem taşımadığı bir strateji için, daha hızlı ve daha kaba bir simülasyon modu bulunmaktadır - "1 dakikalık OHLC".

"1 dakikalık OHLC" modunda, tik dizisi sadece dakikalık çubukların OHLC fiyatlarından oluşur; oluşturulan kontrol noktalarının sayısı - ve sınama süresi - anlamlı ölçüde azaltılmıştır. OnTick () fonksiyonu, dakikalık çubukların OHLC fiyatlarından oluşan tüm kontrol noktalarında çalıştırılır.

Open, High, Low ve Close fiyatlarının arasında ek tiklerin oluşturulmasının reddedilmesi; Open fiyatının belirlendiği andan itibaren, fiyatların geliştirilmesinde katı bir determinizm görüntüsü ortaya çıkaracaktır. Bu, test edilen bakiyenin yukarı yönlü grafiğini gösteren bir "Sınama Kasesi", oluşturulmasını mümkün kılar.

Böyle bir Kase örneği Code Base - Grr-al linkinde bulunabilir.

Grr-al Uzman Danışmanı OHLC fiyatlarının özelliklerini kullanır

Resimde bu Uzman Danışmanın etkileyici grafiği gözükmektedir. Nasıl elde edildi? Bir dakikalık çubuk için dört ayrı fiyat biliyoruz ve yine biliyoruz ki Open fiyatı bunların ilkiyken Close fiyatı ise sonuncusu. Bunların arasında High ve Low fiyatlarımız var ve bunların oluşma sıraları belirsiz ama High fiyatının Open fiyatından büyük veya ona eşit olduğunu (ve Low fiyatının Open fiyatından küçük veya ona eşit olduğunu) biliyoruz.

Open fiyatının alınma anını belirlemek, ardından o anda hangi fiyatı - High veya Low - aldığımızı belirlemek için sonraki tikleri analiz etmek yeterli olacaktır. Fiyat açılış (Open) fiyatının altındaysa, bu Low fiyatına sahip olduğumuz anlamına gelir ve bu tik üzerinde alım yaparız, bir sonraki tik High fiyatına karşılık gelir burada alış pozisyonunu kapatır ve satış için yeni pozisyon açarız. Bir sonraki (son) tik, Close fiyatıdır ve burada da satış pozisyonunu kapatırız.

Açılıştan sonra aldığımız tik açılçış fiyatından büyükse, bu işlem dizisini ters yönde uygularız. Bu "hile" modunda bir dakikalık çubuğu işleyin, ardından bir sonraki için bekleyin.

Böyle bir Uzman Danışmanı geçmiş veriyle sınarken herşey düzgün gider ama bir kez çevirim içi çalıştırdığımızda, asıl gerçek ortaya çıkar - bakiye çizgisi istikrarlıdır ama aşağı doğru yönelmiştir. Bu hileyi ortaya çıkarmak için, Uzman Danışmanı "Her Tik" modunda çalıştırmamız gerekir.

Not: Bir uzman Danışmanın test sonuçları, kaba sınama modlarında ("1 dakikalık OHLC" ve "Sadece Açılış Fiyatları") çok iyi görünüyorsa "Her Tik" modunda da Sınama gerçekleştirdiğinizden emin olun.

"Sadece Açılış Fiyatları"

Bu modda tikler, sınama için seçilen zaman aralığında OHLC fiyatlarının temelinde oluşturulur. Uzman Danışmanın OnTick() fonksiyonu, sadece çubuğun başlangıcındaki Open fiyatında çalışır. Bu özellik nedeniyle, stop (durdurma) ve bekleyen emir seviyeleri, belirtilenden farklı bir fiyat ile tetiklenebilir (özellikle test sırasında büyük periyotlar kullanılıyorsa). Bunun yerine Uzman Danışman için hızlı bir ön değerlendirme testi yapabilme olanağımız bulunmaktadır.

W1 ve MN1 periyotları, "Sadece Açılış Fiyatları" modu için birer istisnadır: bu periyotlar için tikler, haftalık veya aylık değil, günlük OHLC fiyatları ile oluşturulur.

EURUSD H1 sembolünde, "Sadece Açılış Fiyatları" modunda bir Uzman Danışmanı test ettiğimizi düşünelim. Bu durumda tiklerin (kontrol noktalarının) toplam sayısı, sınamanın yapıldığı zaman aralığındaki bir-saatlik çubukların sayısının 4 katı olacaktır. Ama OnTick() işleyicisi, sadece bir-saatlik çubuğun açılışında çağrılacaktır. Doğru sınama için istenen kontroller, tiklerin geri kalanı (Uzman Danışmandan gizlenenler) üzerinde gerçekleşir.

  • Marjin (teminat) gerekliliklerinin hesaplanması;
  • Zarar Durdur ve Kar Al seviyelerinin tetiklenmesi;
  • Bekleyen emirlerin tetiklenmesi;
  • Zaman-aşımına uğramış bekleyen emirlerin kaldırılması.

Herhangi bir açık pozisyon veya bekleyen emir yoksa, gizli tiklerin üzerinde bu kontrolleri gerçekleştirmemiz gerekmez, bu şekilde ciddi bir hız artışı sağlanabilir. "Sadece Açılış Fiyatları" modu, işlemleri sadece açılış fiyatından gerçekleştiren ve ve StopLoss, TakeProfit ve bekleyen emir kullanmayan stratejiler için oldukça uygundur. Bu tip stratejiler için gereken test geçerliliği korunur.

Standart paketteki Uzman Danışmanlardan, her modda test edilebilecek olan Moving Average Uzman Danışmanını örnek olarak alalım. Bu Uzman Danışmanın mantığı, tüm kararların çubuğun açılışında verilmesi, işlemlerin hemen uygulanması ve bekleyen emir kullanılmaması üzerine kuruludur.

Bu uzman için EURUSD H1 sembolünde, 2010.09.01 ile 2010.12.31 aralığında bir test düzenleyip sonuç grafiklerini karşılaştıralım. Aşağıdaki resim, üç modun her biri için test raporundaki bakiye grafiğini göstermektedir.

Standart paketteki Moving Average.mq5 uzmanının test grafiği test moduna bağımlı değildir

Sizin de görebileceğiniz gibi, farklı modlardaki tüm grafikler, standart paketteki Moving Average uzmanı için aynıdır.

"Sadece Açılış Fiyatları" modunda bir takım kısıtlamalar bulunmaktadır:

  • Rassal Gecikme uygulama modunu kullanamazsınız.
  • Test edilen Uzman Danışman için, sınama/optimizasyon için kullanılandan daha küçük bir zaman-aralığı verisine erişemezsiniz. Örneğin, sınamayı/optimizasyonu H1 periyodu üzerinde gerçekleştirirseniz, H2, H3, H4 vb. periyotların verilerine erişebilirsiniz ama M30, M20, M10 vb. verilerine erişemezsiniz. Ayrıca, erişilmek istenen daha yüksek zaman-aralıkları, sınama için kullanılan zaman-aralığının katı olmalıdır. Örneğin, M20 üzerinde bir sınama gerçekleştiriyorsanız, M30 verisine erişemezsiniz ama H1 verisine erişmeniz mümkündür. Bu kısıtlamalar, sınama sürecinde oluşturulan çubukların katı-olmayan veya onlardan daha düşük periyotlu çubuklardan veri alınmasının imkansızlığı ile ilişkilidir.
  • Diğer zaman-aralıklarının verilerindeki erişim kısıtlamaları, Uzman Danışman tarafından kullanılan diğer sembollere de uygulanır. Bu durumda, her bir sembol için yapılacak kısıtlama, sınama/optimizasyon sırasında erişilen ilk zaman-aralığına bağlı olacaktır. EURUSD H1 üzerinde yapılan bir sınama sırasında, Uzman Danışmanın GBPUSD M20 verisine erişim sağladığını düşünün. Bu durumda Uzman Danışman, EURUSD H1, H2, vb. verilerine de, GBPUSD M20, H1, H2, vb. verilerine eriştiği gibi erişebilecektir.

Not: "Sadece Açılış Fiyatları" modu, en kısa test süresine sahiptir fakat tüm alım-satım stratejileri için uygun değildir. İstenen sınama modunu, alım-satım stratejisinin karakteristiklerine göre seçiniz.

Tik oluşturma bölümünü sonuca bağlamak amacıyla, EURUSD sembolü ve M15 periyodu için, 2011.01.11 21:00:00 - 2011.01.11 21:30:00 aralığında, farklı tik oluşturma modlarının görsel karşılaştırmasını inceleyelim.

Tikler, WriteTicksFromTester.mq5 Uzman Danışmanı kullanılarak farklı dosyalara yazılmışlardır ve bu dosya isimlerinin sonları filenameEveryTick, filenameOHLC ve filenameOpenPrice giriş parametreleri ile belirlenmiştir.

WriteTicksFromTester Uzman Danışmanı için tiklerin başlangıç be bitiş tarihlerini belirleyebiliriz (start ve end değişkenleri)

Üç tik dizisini içeren üç dosyayı almak için, Uzman Danışman, karşılık gelen üç ayrı modda ("Her tik", "1 dakikalık OHLC" ve "Sadece Açılış Fiyatları") tekil olarak (üç defa) çalıştırılır. Ardından, bu üç dosyadaki veriler TicksFromTester.mq5 göstergesi ile çizelge üzerinde görüntülenir. Gösterge kodları bu yazıya eklenmiştir.

MetaTrader 5 terminalinin Strateji Sınama aracında, üç farklı moddaki tik dizisi

Varsayılan olarak, MQL5 dilindeki tüm dosya işlemleri, "dosya güvenlik-ortamı" (sandbox) içinde gerçekleştirilir; sınama sırasında Uzman Danışman, sadece kendi "dosya güvenlik-ortamına" erişebilir. Göstergenin ve Uzman Danışmanın sınama sırasında aynı klasördeki dosyalarla çalışabilmesi için, FILE_COMMON bayrağını kullandık. Uzman Danışmandan bir kod örneği:

//--- dosyayı aç
   file=FileOpen(filename,FILE_WRITE|FILE_CSV|FILE_COMMON,";");
//--- dosya tanıtıcı değerini kontrol et
   if(file==INVALID_HANDLE)
     {
      PrintFormat("Yazılacak %s dosyasının açılmasında hata. Hata kodu=%d",filename,GetLastError());
      return;
     }
   else
     {
      PrintFormat("Dosya, %s klasöründe oluşturulacak",TerminalInfoString(TERMINAL_COMMONDATA_PATH));
     }

Gösterge içindeki veriyi okumak için de yine FILE_COMMON bayrağını kullandık. Bu, gerekli dosyaları bir klasörden diğerine, el yordamıyla taşımaktan kaçınmamızı sağladı.

//--- dosyayı aç
   int file=FileOpen(fname,FILE_READ|FILE_CSV|FILE_COMMON,";");
//--- dosya tanıtıcı değerini kontrol et
   if(file==INVALID_HANDLE)
     {
      PrintFormat("%s dosyasının okuma amacıyla açılmasında hata. Hata kodu=%d",fname,GetLastError());
      return;
     }
   else
     {
      PrintFormat("Dosya, %s klasöründe açılacak",TerminalInfoString(TERMINAL_COMMONDATA_PATH));
     }

Makas Değerinin Simülasyonu #

Satış ve Alış fiyatları arasındaki fark, makas (spread) olarak adlandırılır. Sınama sırasında makas değeri modellenmez, geçmiş veriden veriden alınır. Geçmiş verideki makas değeri sıfıra eşit veya sıfırdan küçükse, bilinen son makas değeri sınama temsilcisi tarafından kullanılır.

Strateji Sınayıcıda makas değeri her zaman kayan noktalı şekilde düşünülür. Bu SymbolInfoInteger(symbol, SYMBOL_SPREAD_FLOAT) çağrısının her zaman true dönüşü yapmasından kaynaklanır.

Ayrıca, geçmiş veriler, tik değerlerini ve alım-satım hacimlerini de içerirler. Verileri depolamak ve almak için, özel MqlRates yapısını kullanırız:

struct MqlRates
  {
   datetime time;         // Periyot başlangıç zamanı
   double   open;         // Açılış fiyatı
   double   high;         // Periyodun en yüksek fiyatı
   double   low;          // Periyodun en düşük fiyatı
   double   close;        // Kapanış fiyatı
   long     tick_volume;  // Tik hacmi
   int      spread;       // Makas
   long     real_volume;  // Alım-satım hacmi
  };

Sınama sırasında gerçek tiklerin kullanımı #

Gerçek tiklerle yapılan sınama ve optimizasyonlar piyasa koşullarına çok yakındır. Dakikalık verilere göre oluşturulan tiklere ek olarak aracı kurumca toplanan gerçek tik verileri de kullanılabilir. Bunlar borsalardan ve likidite sağlayıcılardan gelen tiklerdir.

En tutarlı sınama sonuçlarını elde etmek için, gerçek tikler modunda dakikalık çubuklar da kullanılır. Çubuklar tik verisini kontrol etmeye ve düzeltmeye yarar. Böylece, sınayıcıda ve terminalde gösterilen çizelgelerin farklı olması önlenir.

Sınayıcı tik verilerini dakikalık çubuklarla karşılaştırır: tik değerleri çubuğun Yüksek/Düşük verileri arasında olmalıdır, ilk ve son tikler Açılış/Kapanış verileriyle örtüşmelidir. Ayrıca hacim değeri de karşılaştırılır. Uyumsuzluk tespit edilirse o dakikaya dair tüm veriler geçersiz sayılır ve bunların yerine, oluşturulan sanal tikler kullanılır ("Her Tik" modunda olduğu gibi).    

Sınayıcı, sembol geçmişinde tik verisi bulunmayan dakikalık çubuklar için "Her tik" modunda tik oluşturur. Bu sayede aracı kurum verilerinin yetersiz olması durumunda çizelge doğru çizilebilir.  

Sembol geçmişinde dakikalık veriler bulunmuyorsa ama ilgili dakika için tik verileri mevcutsa, veriler sınayıcıda kullanılabilir. Örneğin, borsalarda sembol çiftleri Son fiyatlar kullanılarak oluşturulur. Sunucudan gelen veriler Alış/Satış verilerini içeriyor ama Son fiyat bilgisini içermiyorsa çubuk oluşturulmaz. Dakikalık veriler olmadığı sürece sınayıcı bu tikleri kullanacaktır.

Bağlantı kayıpları veya kaynak ve terminal arasında veri iletimi sırasında oluşan hatalar vb. gibi sebeplerden ötürü, tik verileri dakikalık verilerle örtüşmeyebilir. Sınama sırasında dakikalık veriler daha güvenilir kabul edilir.

Gerçek tiklerle sınama yaparken şu bilgileri göz önünde bulundurun:

  • Sınama sırasında sembolün dakikalık verileri tik verileriyle eşitlenir.
  • Tikler strateji sınayıcısının sembol kasasında saklanır. Kasa boyutu 128 000 tik verisini aşamaz. Yeni tiklerin gelmesiyle, kasadaki en eski tikler silinir. Ama CopyTicks fonksiyonu ile kasa dışında kalan tik verileri alınabilir (sadece gerçek tiklerle çalışırken). Bu durumda, sınayıcının tik veri-tabanından istenen veriler terminal veri-tabanıyla tamamen aynı olur. Bu verilere dakikalık çubuklar için düzeltme uygulanmaz. Bu yüzden kullanılan tikler kasadaki tiklerden farklı olabilir.

Müşteri Terminalinin Global Değişkenleri #

Sınama sırasında, müşteri terminalinin global değişkenleri de ayrıca simüle edilir ama bunlar, (F3 tuşu kullanılarak görülebilecek) terminalin mevcut global değişkenleri ile ilişkili değildirler. Yani, sınama sırasındaki terminalin global değişkenleri ile ilgili tüm işlemler, müşteri terminalinin dışında (sınama temsilcisinde) yer alırlar.

Sınama sırasında göstergelerin hesaplanması #

Gerçek zamanlı modda, gösterge değerleri her tikte hesaplanır.

Strateji Sınayıcıda, göstergeler yalnızca verilere erişildiğinde, yani göstergenin arabellek değerleri istendiğinde hesaplanır. Tek istisna, belirtilen #property tester_everytick_calculate özelliğine sahip özel göstergelerdir. Bu durumda, her tik üzerinde yeniden hesaplama yapılır.

Görsel test modunda, görsel test grafiğinde doğru şekilde görüntülenmeleri için yeni tik geldiğinde tüm göstergeler koşulsuz olarak yeniden hesaplanır.

Gösterge, her tik için bir kez hesaplanır. Gösterge verileri için sonraki tüm talepler, yeni tik gelene kadar yeniden hesaplamaya yol açmaz. Bu nedenle, zamanlayıcı EventSetTimer() fonksiyonu aracılığıyla bir uzman danışmanda etkinleştirilirse, gösterge verileri, OnTimer() işleyicisinin her çağrısından önceki son tik ile istenir. Son tikte gösterge henüz hesaplanmadıysa, gösterge değerlerinin hesaplanmasına başlanır. Veriler önceden hazırlanmışsa, yeni bir yeniden hesaplama yapılmadan veriler sağlanır.

Bu nedenle, tüm gösterge hesaplamaları en fazla kaynak tasarrufu sağlayacak şekilde gerçekleştirilir - gösterge tik işaretinde zaten hesaplanmışsa, verileri 'olduğu gibi' sağlanır. Yeniden hesaplama yapılmaz.

Sınama sırasında Geçmiş Verinin Yüklenmesi #

Sınanacak sembolün geçmişi, sınama süreci başlamadan önce terminal tarafından, alım-satım sunucusundan indirilerek senkronize edilir. Terminal, sembolün mevcut olan bütün geçmişini bir daha istememek üzere ilk seferde yükler. Bundan sonra sadece yeni veriler yüklenir.

Sınama temsilcisi, sınanacak sembolün geçmişini sınama başladıktan hemen sonra müşteri terminalinden alır. Eğer, test sürecinde diğer enstrümanların verileri de kullanılıyorsa (çok-dövizli bir Uzman Danışman gibi), sınama temsilcisi, verinin çağrılmasıyla birlikte müşteri terminalinden gereken veriyi ister. Tarihsel veri terminalde mevcutsa, hemen sınama temsilcisine aktarılır. Eğer veriler mevcut değilse, terminal verileri sunucudan ister ve yükler, ardından sınama temsilcisine aktarır.

Ek enstrümanların verilerine, alım-satım işlemleri için çapraz-kurları hesaplamak amacıyla da ihtiyaç duyulur. Örneğin, EURCHF üzerinde USD karşıt döviz birimi ile bir sınama gerçekleştirirken, ilk alım-satım işlemini gerçekleştirmeden önce, sınama temsilcisi EURUSD ve USDCHF sembollerinin geçmişlerini müşteri terminalinden ister; ama strateji bu sembollerin doğrudan kullanımını içermez.

Çok-dövizli bir stratejiyi sınamadan önce, gereken tüm geçmiş verinin müşteri terminaline yüklenmesi önerilir. Bu, sınama sırasında, istenen verinin yüklenmesinin yol açabileceği gecikmelerin önlenmesine yardımcı olur. geçmişi, uygun çizelgeyi açıp, onu geçmiş veri başlangıcına kadar kaydırarak da yükleyebilirsiniz. Terminale zorla veri yüklemeye dair bir örnek de, MQL5 Referansının Veri Erişiminin Düzenlenmesi bölümünde yer almaktadır.

Sınama Temsilcileri, geçmişi terminalden paketlenmiş olarak alır. Bir sonraki sınama boyunca, sınayıcı veriyi terminalden yüklemez; istenen veri, sınayıcının bir önceki çalışmasından zaten mevcuttur.

  • Sınama temsilcisi sınanacak sembolün geçmişini terminalden istediğinde, terminal geçmişi sunucudan sadece bir kere yükler. geçmiş, trafiği azaltmak için paketlenmiş şekilde yüklenir.
  • Tikler ağ üzerinden gönderilmez; sınama temsilcilerinde oluşturulurlar.

Çoklu-Döviz Sınaması #

Strateji Sınama Aracı, çoklu sembollerle alım-satım yapan stratejileri sınamamıza imkan tanır. Önceki platformlarda sınama işlemi sadece tek sembol için gerçekleştirildiğinden, bunlar sıklıkla çok-dövizli Uzman Danışmanlar olarak isimlendirilir. . MetaTrader 5 terminalinin Strateji Sınama Aracı içinde, alım-satım stratejilerini mevcut tüm semboller için modelleyebiliriz.

Sınama aracı, kullanılan sembollerin geçmiş verilerini, verinin çağrılmasıyla birlikte müşteri terminalinden (alım-satım sunucusundan değil!) otomatik olarak yükler.

Sınama temsilcisi, sınama başlangıcında, sadece göstergenin hesaplanması için gereken eksik verileri indirir (geçmiş verileri sağlamak için küçük bir farkla) D1 ve daha düşük zaman-aralıkları için, indirilen minimum geçmiş veri hacmi bir yıldır.

Yani, 2010.11.01-2010.12.01 aralığında M15 periyoduyla (1 aylık aralıkta 15 dakikalık çubuklarla) bir sınama gerçekleştiriyorsak, terminal 2010 yılının tamamı için enstrümanın geçmişini isteyecektir. Haftalık zaman aralığı içinse, yaklaşık iki yıla denk gelen (bir yıl 52 hafta içerir)100 çubukluk geçmiş veri yüklenir. Aylık zaman-aralığında sınama gerçekleştirmek için, sınama temsilcisi 8 yıllık geçmiş veri isteyecektir (12 ay x 8 yıl = 96 ay).

Yeterli sayıda çubuk yoksa, sınama işleminden önce gereken çubuk rezervini sağlamak amacıyla, başlangıç tarihi otomatik olarak kaydırılacaktır (geçmişten bu güne).

Sınama sırasında, sembollerle ilgili bilgilerin alınabildiği "Piyasa Gözlemi" de ayrıca simüle edilecektir.

Ön-tanımlı olarak, sınama başlangıcında Strateji Sınama aracındaki "Piyasa Gözlemi" içinde sadece bir sembol bulunur - sınamanın yapılacağı sembol. Tüm gerekli semboller, başvurulduğunda Strateji Sınama Aracının (terminalin değil!) "Piyasa Gözlemine" bağlanırlar

Çok-dövizli bir Uzman Danışmanı sınamaya başlamadan önce, istenilen sembolün terminalin Piyasa Gözleminden seçilmesi ve istenen verinin yüklenmesi gerekir. "Yabancı" bir sembolün ilk çağrısı sırasında sembolün geçmişi, terminal ve sınama temsilcisi arasında senkronize edilir. "Yabancı" sembol, sınama işleminin yapıldığı sembolden farklı olan semboldür.

"Başka bir sembolün verilene, şu durumlarda başvuru yapılır":

  • Bir sembolün/periyodun zaman-serilerinin alınması için şu fonksiyonlarla yapılan istek:

"Başka" bir sembol ilk defa çağrıldığında, sınama süreci durdurulur ve sembolün/periyodun geçmişi terminalden sınama temsilcisine aktarılır. Bu sembol için gereken tik dizisi de aynı zamanda oluşturulur.

Seçilen tik oluşturma moduna göre, her bir sembol için ayrı tik tik dizileri oluşturulur. Ayrıca, SymbolSelect() fonksiyonunu OnInit() işleyicisi içinde kullanarak, sembolün geçmişini açık yolla isteyebilirsiniz - geçmiş verinin yüklenmesi işlemi, Uzman Danışmanın sınanmasına başlamadan hemen önce gerçekleştirilir.

Bu şekilde, MetaTrader 5 müşteri terminali içinde çok-dövizli bir sınama gerçekleştirmek için ayrı bir çabaya ihtiyaç olmaz. Sadece, uygun sembollerin çizelgelerini müşteri terminalinde açmanız yeterlidir. İstenen veriyi içeren geçmiş veri, istenen tüm semboller için, alım-satım sunucusundan otomatik olarak indirilecektir.

Strateji Sınama Aracında Zamanın Simülasyonu #

Sınama sırasında yerel zaman TimeLocal() her zaman sunucu zamanına eşittir TimeTradeServer(). Dolayısıyla, sunucu zamanı daima GMT'ye karşılık gelen zamana eşit olacaktır - TimeGMT(). Bu sebeple, tüm bu fonksiyonlar sınama sırasında aynı zamanı gösterecektir.

Strateji Sınama Aracında GMT zamanı, yerel zaman ve sunucu zamanı arasında fark olmaması, sunucu bağlantısının kurulmaması sebebiyle kasıtlı olarak yapılmıştır. Sınama sonuçları, bağlantı olup olmadığına bakılmaksızın her zaman aynı olmalıdır. Sunucu zamanı hakkındaki bilgi yerel olarak depolanmaz ve sunucudan alınır.

Sınama içinde Grafiksel Nesneler #

Sınama/optimizasyon sırasında, grafiksel nesneler çizilmez. Bu nedenle, sınama/optimizasyon sırasında oluşturulmuş grafiksel nesnelerin özelliklerine başvurulduğunda, Uzman Danışman sıfır değerlerini alacaktır.

Bu kısıtlama görsel sınama modunda uygulanmaz.

Strateji Sınayıcıda OnTimer() Fonksiyonu #

MQL5 zamanlayıcı olaylarının işlenmesine izin verir. OnTimer() işleyicisinin çağrısı, sınama modundan bağımsızdır. "Sadece açılış fiyatları" modunda H4 periyodu için bir sınama gerçekleştirildiğini ve uzman danışmanın saniyelik çağrılar yapan bir zamanlayıcıya sahip olduğunu düşünelim; bu durumda, H4 çubuğunun her açılış anında OnTick() işleyicisi bir defa, OnTimer() işleyicisi ise 14400 defa (3600 saniye * 4 saat) çağrılacaktır. Bu miktar Uzman Danışmanın sınama süresi ve çalışma mantığına bağlı olarak aratacaktır.

Sınama süresinin zamanlayıcı frekansına olan bağımlılığını ölçmek için, alım-satım işlemi içermeyen basit bir Uzman Danışman oluşturduk.

//--- giriş parametreleri
input int      timer=1;              // timer zamanlayıcı değeri, saniye
input bool     timer_switch_on=true; // zamanlayıcı devrede
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- timer_switch_on==true ise zamanlayıcıyı çalıştır
   if(timer_switch_on)
     {
      EventSetTimer(timer);
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- zamanlayıcıyı durdur
   EventKillTimer();
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
// herhangi bir eylem yok, işleyicinin gövdesi boş
  }
//+------------------------------------------------------------------+

Sınama süresi ölçümlerinde, timer parametresine bağlı olarak farklı değerler alınmıştır(Timer olayının periyodikliği). Elde edilen veriye göre, sınama süresini Timer periyodunun bir fonksiyonu olarak çizdik.

Timer periyodunun bir fonksiyonu olarak sınama süresi

Grafikten de görebileceğiniz gibi, EventSetTimer(Timer) fonksiyonunun başlatılması sırasında timer parametresi ne kadar küçükse, OnTimer() işleyicisinin çağrıları arasındaki periyot o kadar küçük ve sınama süresi T o kadar fazladır.

Strateji Sınayıcıda Sleep() Fonksiyonu #

Grafik üzerinde çalışırken Sleep() fonksiyonu, Uzman Danışmana veya betiğe, mql5-programının çalışmasını bir süreliğine durdurma imkanı sağlar. Bu, o an hazır olmayan bir veri istediğinizde, veri hazır olana kadar beklemeniz için kullanışlıdır. Sleep() fonksiyonunun detaylı kullanımına dair bir örnek Veri Erişiminin Düzenlenmesi bölümünde bulunabilir.

Sınama süreci, Sleep() çağrısıyla duraklamaz. Sleep() fonksiyonunu çağırdığınızda, oluşturulan tikler belirtilen gecikme içinde yürütülmeye devam eder - ki bu, bekleyen emirlerin ve durdurma emirlerinin tetiklenmesiyle sonuçlanabilir. Sleep() çağrısının ardından, Strateji Sınama aracında simüle edilen zaman, Sleep fonksiyonuyla belirtilen süre kadar artırılır.

Sleep() fonksiyonunun çalıştırılması sırasında, Strateji Sınama Aracındaki mevcut zaman sınama periyodunun ötesine geçiyorsa; "Sınama sırasında sonsuz Sleep döngüsü tespit edildi" şeklinde bir hata mesajı alırsınız. Bu hata mesajını almışsanız, test sonuçları reddedilmez, tüm hesaplamalar tam hacmiyle (işlemlerin sayısı) gerçekleştirilir ve test sonuçları terminale aktarılır.

Sınama süresi, sınama aralığının boyutunu aşacağından, Sleep() fonksiyonu OnDeinit() içerisinde çalışmayacaktır, .

Sleep() fonksiyonunun, MetaTrader 5 terminalinin Strateji Sınama Aracındaki kullanımına dair bir şema

Matematiksel Hesaplamalardaki Optimizasyon Problemleri için Strateji Sınama aracının Kullanılması #

MetaTrader 5 terminalindeki sınayıcı, sadece alım-satım stratejileri için değil, aynı zamanda matematiksel hesaplamalar için de kullanılabilir. Bunu kullanmak için "Matematiksel hesaplamalar" modunu seçmeniz gerekmektedir:

math_calculations

Bu durumda sadece üç fonksiyon çağrılacaktır: OnInit(), OnTester(), OnDeinit(). "Matematiksel hesaplamalar" modunda Strateji Sınama Aracı herhangi bir tik oluşturmayacak ve geçmiş veri yüklemeyecektir.

Strateji sınayıcı, başlangıç tarihini bitiş tarihinden büyük yazmış olsanız bile "Matematiksel hesaplamalar" modunda çalışır.

Sınama aracını matematiksel problemleri çözmek için kullanırken, tikler oluşturulmayacak ve geçmiş veri yüklenmeyecektir.

MetaTrader 5 Strateji Sınama Aracında çözmek için tipik bir matematiksel problem - çok değişkenli bir fonksiyonun ekstremumunun aranması.

Bunun için şu koşular sağlanmalıdır:

  • Fonksiyon değerinin hesaplama işlemleri OnTester() fonksiyonu içine yerleştirilmelidir;
  • Fonksiyonun parametreleri, Uzman Danışmanın giriş parametreleri olarak belirlenmelidir;

Uzman Danışmanı derleyin ve "Strateji Sınama Aracı" penceresini açın. "Giriş parametreleri" sekmesinde, istenen giriş parametrelerini seçin ve başlangıç, durdurma ve adım değerlerini belirleyerek, her bir fonksiyon parametresinin değerini tanımlayın.

Optimizasyon tipini seçin - "Yavaş, tam algoritma" (parametre uzayının tamamının aranması) veya "Hızlı, genetik tabanlı algoritma". Fonksiyonun ekstremum değerini basitçe aramak için, hızlı optimizasyonun seçilmesi daha iyi olacaktır; ama bütün parametre kümesi için arama gerçekleştirmek istiyorsanız, o zaman en iyisi yavaş optimizasyondur.

"Matematiksel hesaplamalar" modunu seçin ve "Başlat" düğmesine basarak optimizasyon prosedürünü çalıştırın. Optimizasyon sırasında Strateji Sınayıcının, OnTester fonksiyonunun maksimum değerini arayacağını not edin. Eğer yerel minimum değerini bulmak istiyorsanız, hesaplanan fonksiyonun değerini OnTester fonksiyonu içinde ters çevirin:

return(1/fonksiyon_değeri);

Fonksiyon değerinin sıfıra eşit olmadığı kontrol edilmelidir, aksi durumda sıfıra bölmeden kaynaklanan bir kritik hata alırız.

Bununla birlikte bir yol daha bulunmaktadır, bu yöntem daha uygundur ve optimizasyon sonuçlarında bozulmaya yol açmaz, bu makalenin okuyucuları tarafından önerilmiştir:

return(-fonksiyon_değeri);

Bu seçenekte fonksiyon değerinin sıfıra eşit olup olmadığının kontrol edilmesi gerekmez, 3-boyutlu bir temsilde optimizasyon yüzeyi aynı şekle sahiptir. Buradaki tek fark bunun orjinaline göre bir yansıma olmasıdır.

Örnek olarak sink() fonksiyonunu kullanalım:

sink_formula

Bu fonksiyonun ekstremumunu bulmak için gereken Uzman Danışman kodu OnTester() fonksiyonunun içine yerleştirilir:

//+------------------------------------------------------------------+
//|                                                         Sink.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//--- giriş parametreleri
input double   x=-3.0; // başlangıç=-3, adım=0.05, durdurma=3
input double   y=-3.0; // başlangıç=-3, adım=0.05, durduma=3
//+------------------------------------------------------------------+
//| Tester function                                                  |
//+------------------------------------------------------------------+
double OnTester()
  {
//---
   double sink=MathSin(x*x+y*y);
//---
   return(sink);
  }
//+------------------------------------------------------------------+

Bir optimizasyon gerçekleştirin ve optimizasyon sonuçlarını 2-boyutlu grafik şeklinde alın.

sink (x*x+y*y) fonksiyonunun tam optimizasyon sonuçlarının 2-boyutlu grafiği

Verilen parametre değerleri (x, y) ne kadar iyiyse, renk de o kadar canlı olacaktır. sink() formülünden umulduğu gibi, fonksiyonun değerleri (0,0) merkezinin etrafında konsantrik daireler şeklindedir. sink() fonksiyonunun tek bir global maksimuma sahip olmadığı, 3-boyutlu grafikten görülebilir:

Sink fonksiyonunun 3-boyutlu grafiği

"Sadece Açılış fiyatları" modunda Çubukların Senkronizasyonu #

MetaTrader 5 müşteri terminalindeki sınayıcı, "çok-dövizli" Uzman Danışmanları kontrol etmemizi sağlar. Çok-dövizli bir Uzman Danışman, iki veya daha çok sembol üzerinden alım-satım gerçekleştiren bir Uzman Danışmandır.

Birden çok sembol üzerinden alı-satım yapan stratejilerin sınanması, sınayıcıyaa birkaç ek teknik gereksinim yükler:

  • Bu semboller için tiklerin oluşturulması;
  • Gösterge değerlerinin bu semboller için hesaplanması;
  • Marjin (teminat) gereksinimlerinin bu sembol için hesaplanması;
  • Oluşturulan tik dizilerinin tüm alım-satım sembolleri için senkronize edilmesi.

Strateji sınayıcı, her bir enstrüman için seçilen alım-satım moduna göre bir tik dizisini oluşturur ve yürütür. Aynı zamanda, her bir sembol için yeni bir çubuk diğer sembollerden bağımsız olarak açılır. Yani, çok-dövizli Uzman Danışmanların sınanması sırasında, bir enstrüman için yeni çubuğun çoktan açıldığı, diğeri içinse henüz açılmadığı bir durumla karşılaşılabilir (bu durum sıklıkla yaşanır). Böylece, sınama içindeki her şey gerçekte olduğu gibi olur.

Sınama aracında kullanılan bu özgün simülasyon yöntemi, "Her tik" ve "1 dakikalık OHLC" modları seçildiği sürece herhangi bir sorun ortaya çıkarmaz. Bu modlarda, farklı sembollerdeki çubukların senkronizasyonunun gerçekleşmesini bekleyebilmek amacıyla, her bir çubuk için yeterli sayıda tik üretilir. Peki alım-satım enstrümanlarının senkronizasyonu bu kadar gerekliylse, çok-dövizli bir Uzman Danışmanı, "Sadece açılış fiyatları" modunda nasıl sınayabiliriz? Bu modda Uzman Danışman sadece açılış zamanına denk gelen tek bir tik üzerinde çağrılır.

Bunu bir örnek üzerinde göstereceğiz: EURUSD üzerinde bir uzmanı test ediyor olalım ve H1 çizelgesinde yeni saatin mumu açılmış olsun. Bu olayı kolayca anlayabiliriz – "Sadece açılış fiyatları" modunda NewTick olayı, sınama periyodunun üzerindeki çubuk açılış zamanına denk gelecektir. Ama yeni çubuğun Uzman Danışmanda kullanılan USDJPY sembolü üzerinde de açılacağı kesin değildir.

Normal koşullar altında, OnTick() fonksiyonunun işlemini tamamlamak ve bir sonraki tik ile birlikte USDJPY sembolü üzerindeki yeni çubuğu kontrol etmek yeterlidir. Ama "Sadece açılış fiyatları" modunda bir sınama gerçekleştirirken başka bir tik olmayacaktır; bu yüzden bu modun çok-dövizli Uzman Danışmanların sınanması için uygun olmadığı düşünülebilir. Ama öyle değildir - MetaTrader 5 içindeki sınayıcının gerçek hayattaki gibi davrandığını unutmamanız gerekir. Sleep() fonksiyonunu kullanarak, diğer semboller için yeni çubuklar açılana kadar bekleyebilirsiniz!

Synchronize_Bars_Use_Sleep.mq5 Uzman Danışmanının kodu, "Sadece açılış fiyatları" modunda çubukların senkronizasyonunun bir örneğini göstermektedir:

//+------------------------------------------------------------------+
//|                                   Synchronize_Bars_Use_Sleep.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//--- giriş parametreleri
input string   other_symbol="USDJPY";
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- sembolü kontrol et
   if(_Symbol==other_symbol)
     {
      PrintFormat("Diğer sembolü giriş parametrelerinde belirtmeli veya Strateji Sınama Aracı içerisinde seçmelisiniz!");
      //--- sınama zorla durduruldu
      return(INIT_PARAMETERS_INCORRECT);
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- son çubuğun zamanını saklaması için bir static değişken
   static datetime last_bar_time=0;
//--- senkronizasyon bayrağı
   static bool synchonized=false;
//--- Eğer statik değişken başlatılmamışsa
   if(last_bar_time==0)
     {
      //--- ilk çağrı, çubuk zamanını sakla ve çık
      last_bar_time=(datetime)SeriesInfoInteger(_Symbol,Period(),SERIES_LASTBAR_DATE);
      PrintFormat("last_bar_time değişkeni %s değeri ile başlatıldı",TimeToString(last_bar_time));
     }
//--- sembolün son çubuğunun açılış zamanını al
   datetime curr_time=(datetime)SeriesInfoInteger(Symbol(),Period(),SERIES_LASTBAR_DATE);
//--- zamanlar eşit değilse
   if(curr_time!=last_bar_time)
     {
      //--- çubuk açılış zamanını statik değişkene kaydet
      last_bar_time=curr_time;
      //--- senkronize değil
      synchonized=false;
      //--- mesajı çıktıla
      PrintFormat("%s sembolü üzerinde %s zamanında yenibir çubuk alındı",_Symbol,TimeToString(TimeCurrent()));
     }
//--- diğer sembol çubuğunun açılış zamanı
   datetime other_time;
//--- diğer sembol çubuğunun açılış zamanı curr_time değişkenine eşit olana kadar döngüye gir
   while(!(curr_time==(other_time=(datetime)SeriesInfoInteger(other_symbol,Period(),SERIES_LASTBAR_DATE)) && !synchonized))
     {
      PrintFormat("5 saniye bekleniyor..");
      //--- beş saniye bekle ve SeriesInfoInteger(other_symbol,Period(),SERIES_LASTBAR_DATE) çağrısını yap
      Sleep(5000);
     }
//--- çubuklar senkronize edildi
   synchonized=true;
   PrintFormat("%s sembolünün çubuk açılış zamanı: %s",_Symbol,TimeToString(last_bar_time));
   PrintFormat("%s sembolünün çubuk açılış zamanı: %s",other_symbol,TimeToString(other_time));
//--- TimeCurrent() kullanışsız, TimeTradeServer() çağrısını kullan
   Print("Çubukların senkronizasyon zamanı ",TimeToString(TimeTradeServer(),TIME_SECONDS));
  }
//+------------------------------------------------------------------+

Uzman Danışmanın son satırına dikkat edin - bu satırda senkrinazyonun gerçekleştirildiği mevcut zaman görüntülenmektedir:

   Print("Çubukların senkronizasyon zamanı ",TimeToString(TimeTradeServer(),TIME_SECONDS));

Mevcut zamanı görüntülemek için TimeCurrent() fonksiyonunun yerine TimeTradeServer() fonksiyonunu kullandık. TimeCurrent() fonksiyonu, Sleep() çağrısından sonra değişmeyen 'son tik zamanına' dönüş yapar. Bu Uzman Danışmanı "Sadece açılış fiyatları" modunda çalıştırdığınızda, çubukların senkronizasyonuna dair bir mesaj görürsünüz.

Synchronize_Bars_Use_Sleep_EA

Son tik zamanı yerine mevcut sunucu zamanını almanız gerekiyorsa, TimeCurrent() yerine TimeTradeServer() fonksiyonunu kullanın.

Çubukların senkronizasyonu için bir yol daha mevcuttur - zamanlayıcı kullanımı. Bu tip bir Uzman Danışman örneği (Synchronize_Bars_Use_OnTimer.mq5) bu makaleye eklenmiştir.

Sınayıcı içinde IndicatorRelease() Fonksiyonu #

Tekil bir sınama tamamladıktan sonra, otomatik olarak sembolün bir çizelgesi açılır. Bu çizelgede, tamamlanan işlemler ve Uzman Danışmanda kullanılan göstergeler yer alır. Bu, giriş-çıkış noktalarını görsel olarak analiz etmenize ve bunları gösterge değerleriyle karşılaştırmanıza olanak sağlar.  

Not: sınama işleminden sonra açılan çizelgede görüntülenen göstergeler, sınamanın tamamlanmasından sonra hesaplanır. Bu göstergeler Uzman Danışman İçerisinde kullanılmış olsa bile.

Ama bazı durumlarda, programcı hangi göstergelerin alım-satım algoritmasına dahil olduğunu gizlemek isteyebilir. Örneğin, gizlenmiş kodlarla, çalıştırılabilir bir dosya şeklinde satılan veya kiralanan bir Uzman Danışman. Bu amaç için, IndicatorRelease() fonksiyonunun kullanımı uygundur.

Eğer terminal tarafından, directory/profiles/templates konumundan tester.tpl isimli bir şablon ayarlanırsa, bu şablon açılan çizelgeye uygulanacaktır. Bu şablonun yokluğu durumunda ise, varsayılan şablon uygulanacaktır. (default.tpl).

Aslında IndicatorRelease() fonksiyonu, kullanımı tamamlanan bir göstergenin hesaplama kısmını serbest bırakmak için tasarlanmıştır. Bunun amacı bellek ve CPU kaynaklarını korumaktır, çünkü her yeni tikten sonra gösterge hesaplanması için yeniden çağrılır. İkinci bir amaç ise, tekil bir sınamadan sonra göstergenin sınama çizelgesinde görüntülenmesini engellemektir.

Sınama işleminden sonra göstergenin çizelge üzerinde görüntülenmesini engellemek için, IndicatorRelease() fonksiyonunu, gösterge tanıtıcısı ile OnDeinit() işleyicisinin içinde çağırın. OnDeinit() fonksiyonu her zaman sınama tamamlandıktan sonra ve sınama çizelgesi gösterilmeden önce çalışır.

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   bool hidden=IndicatorRelease(handle_ind);
   if(hidden) Print("IndicatorRelease() başarıyla tamamlandı");
   else Print("IndicatorRelease()'false' dönüşü yaptı Hata kodu ",GetLastError());
  }

Sınama işleminden sonra göstergenin çizelge üzerinde görüntülenmesini engellemek için IndicatorRelease() fonksiyonunu OnDeinit() işleyicisinin içerisinde çağırın.

Sınama Aracında Olay İşleme #

MetaTrader 5 sınayıcıda geçmiş veri ile sınamaya konu olması açısından OnTick() işleyicisinin Uzman Danışman içindeki varlığı zorunlu değildir. Bir Uzman Danışmanın aşağıdaki işleyicilerden en az birini içermesi yeterlidir:

  • OnTick() - gelen yeni tik olayının işleyicisi;
  • OnTrade() - Alım-satım olayının işleyicisi;
  • OnTimer() - Zamanlayıcıdan gelen sinyal olaylarının işleyicisi;
  • OnChartEvent() - Özel olaylar için bir işleyici.

Bir Uzman Danışmanı sınarken OnChartEvent() fonksiyonunu kullanarak özel olayları işleyebiliriz ama bu fonksiyon göstergelerde sınayıcı içinde çağrılamaz Gösterge OnChartEvent() içeriyorsa ve gösterge sınanan uzman Danışmanda kullanılıyor olsa bile, gösterge herhangi bir özel olay işlemeyecektir.

Sınama sırasında, göstergeler EventChartCustom() fonksiyonu ile özel olaylar oluşturabilirler ve Uzman Danışman bu olayı OnChartEvent() içerisinde işleyebilir.

Bu olaylara ilaveten, sınama sürecine ve optimizasyona dair özel olaylar da strateji sınayıcıda oluşturulurlar:

  • Tester - bu olay, Uzman Danışmanın sınama işleminin tamamlanmasından sonra oluşturulur. Tester olayı, OnTester() fonksiyonu ile işlenir. Bu olay sadece Uzman Danışmanların sınanmasında kullanabilir ve aslen giriş parametrelerinin genetik optimizasyonu için kullanılan Custom max kriterinin değerini hesaplamak amacıyla tasarlanmıştır.
  • TesterInit - bu olay, strateji sınayıcıdaki optimizasyon işleminin başlangıcında, ilk geçişin öncesinde oluşturulur. TesterInit olayı, OnTesterInit() fonksiyonu ile işlenir. Optimizasyonun başlangıcında, bu işleyiciye sahip bir uzman danışman, sınayıcıda belirtilen sembolün ve periyodun çizelgesini otomatik olarak, ayrı bir terminal penceresi üzerinde açar. Fonksiyon, optimizasyona geçilmeden önce, daha sonraki optimizasyon sonuçlarının işlenmesi aşaması için, Uzman Danışmanlarda kullanılır..
  • TesterPass - bu olay, yeni bir veri çerçevesi alındığında oluşturulur. TesterPass olayı OnTesterPass() fonksiyonu ile işlenir. Bu işleyiciye sahip bir Uzman Danışman, sınama için belirlenen sembol/zaman aralığı değerleri ile otomatik olarak ayrı bir terminal grafiğine yüklenir, optimizasyon sırasında bir çerçeve alındığında TesterPass olaylarını yakalar. Fonksiyon, optimizasyon sonuçlarının dinamik olarak tamamlanmasını beklemeksizin "anında" işlenmesi için kullanılır. Çerçeveler, OnTester() işleyicisindeki bir tekil geçişin bitmesinden sonra çağrılabilen FrameAdd() işleyicisi kullanılarak eklenirler.
  • TesterDeinit - bu olay, strateji sınayıcıda Uzman Danışman optimizasyonunun bitmesinin ardından oluşturulur.. TesterDeinit olayı, OnTesterDeinit() fonksiyonu ile işlenir. TesterDeinit() işleyicisine sahip bir Uzman Danışman, optimizasyonun başlangıcında otomatik olarak bir grafiğe yüklenir ve tamamlanmasının ardından TesterDeinit olayını teslim alır. Fonksiyon, tüm optimizasyon sonuçlarının son işlemleri için kullanılır.

Sınama Temsilcileri #

MetaTrader 5 müşteri terminalinde gerçekleştirilen sınamalar sınama temsilcileri kullanılarak uygulanır. Yerel temsilciler, otomatik olarak oluşturulup devreye sokulurlar. Yerel temsilcilerin sayısı bilgisayardaki çekirdek sayısına karşılık gelir.

Her sınama temsilcisi, müşteri terminalinden bağımsız olarak global değişkenlerin kendisine has kopyasına sahiptir. Burada terminal, görevleri yerel veya uzak temsilcilere dağıtan bir sevk merkezi gibidir. Temsilci Uzman Danışmanın sınanması görevini tamamladıktan sonra, verilen parametrelerle birlikte, sonuçları terminale verir. Tek bir sınama için tek bir temsilci kullanılır.

Temsilci, terminalden alınan geçmiş verileri enstrümanların isimlerine göre ayrı klasörlere kopyalar - EURUSD geçmişi, EURUSD isimli bir klasöre kaydedilir. Enstrümanların geçmiş verileri kaynaklarına göre de ayrılır. Geçmiş verilerin depolanma yapısı şu şekilde gözükür:

tester_catalog\Agent-IPaddress-Port\bases\kaynak_ismi\history\sembol_ismi

Örneğin, MetaQuotes-Demo sunucusundan alınan EURUSD geçmişi, tester_catalog\Agent-127.0.0.1-3000\bases\MetaQuotes-Demo\EURUSD klasörüne kaydedilebilir.

Yerel temsilci, sınamanın tamamlanmasının ardından bekleme moduna geçer ve yeni bir görev için 5 dakika boyunca bekler, böylece bir sonraki çağrıda zaman harcanmaz. Bekleme süresinin bitmesiyle Yerel temsilci kapanır ve CPU belleğinden kaldırılır.

Kullanıcı tarafından (İptal et düğmesi ile) veya müşteri terminalinin kapatılması sonucunda sınama sürecinin erken tamamlanması durumunda, Tüm temsilcler hemen işlemlerini durdurur ve bellekten kaldırılır.

Terminal ve Sınama Temsilcisi arasında Veri Değişimi #

Bir sınama gerçekleştirdiğinizde, müşteri terminali temsilciye gönderilmek üzere bir dizi parametre bloğu hazırlar:

  • Sınama için giriş parametreleri (simülasyon modu, test aralığı, enstrümanlar, optimizasyon kriteri, vb.)
  • "Piyasa Gözlemi" içinden seçilen sembollerin listesi
  • Sınanacak sembolün özellikleri (sözleşme büyüklüğü, StopLoss ve Takeprofit değerlerini ayarlamak için izin verilen teminatlar, vb.)
  • Sınanacak Uzman Danışman ve onun giriş parametrelerinin değerleri
  • Ek dosyalar hakkında bilgi (kütüphaneler, göstergeler, veri dosyaları - # property tester_ ...)

tester_indicator

string

"indicator_name.ex5" biçiminde bir özel göstergenin ismi. Sınama gerektiren özel göstergeler, iCustom() fonksiyonunun çağrısıyla otomatik olarak tanımlanırlar (karşılık gelen parametre, bir sabit dize ile ayarlanmışsa). Tüm diğer durumlar için (IndicatorCreate() fonksiyonunun kullanımı veya gösterge ismini ayarlayan parametrenin sabit-olmayan bir dize ile verilmesi) bu özellik istenir

tester_file

string

Sınayıcı için, uzantısı belirtilmiş şekilde, çift tırnak içinde (bir sabit dize olarak) dosya adı. Belirtilen dosya sınayıcıya aktarılır. Test edilecek girdi dosyaları - gerekli olanlar her zaman belirtilmelidir.

tester_library

string

Çift tırnak içinde, uzantılı olarak kütüphane adı. Bir kütüphane dll veya ex5 uzantılarına sahip olabilir. Sınama gerektiren kütüphaneler otomatik olarak tanımlanırlar. Ama, kütüphanelerden herhangi biri, bir özel gösterge tarafından kullanılıyorsa bu özellik gereklidir

Temsilciye gönderilecek her parametre bloğu için, MD5-hash biçiminde bir dijital imza oluşturulur. MD5-hash, her küme için benzersizdir; büyüklüğü hesaplandığı bilgiden kat kat daha küçüktür.

Temsilci, blokların hash değerlerini alır ve onları zaten elinde olanlarla karşılaştırır. Verilen parametrenin parmak-izi temsilcinin elinde yoksa veya alınan hash değeri temsilcide mevcut değilse, temsilci bu parametre bloğunu kabul eder. Bu, terminal ile sınama temsilcisi arasındaki trafiği azaltır.

Sınama işlemi bittikten sonra temsilci tüm sonuçları terminale döndürür. Bu sonuçlar, "Test Sonuçları" ve "Optimizasyon Sonuçları" isimli sekmelerde gösterilir: alınan kar, işlem sayısı, Sharpe katsayısı, OnTester() fonksiyonunun sonucu, vb.

Optimizasyon sırasında terminal sınama görevlerini küçük paketler halinde temsilcilere dağıtır, her paket birkaç görev içerir (her görev, bir giriş parametreleri kümesiyle tekil bir sınma anlamına gelir). Bu, terminal ve temsilci arasındaki değişim süresini azaltır.

Temsilciler, güvenlik nedeniyle, terminalden alınan EX5-dosyalarını hiçbir zaman sabit diske kaydetmez. Bu yüzden, temsilcinin çalıştığı bilgisayar gönderilen veriyi kullanamaz. Tüm diğer dosyalar - DLL dosyaları da dahil olmak üzere - güvenlik-ortamı (sandbox) içinde tutulur. DLL kullanan Uzman Danışmanları uzak temsilcilerde sınayamazsınız.

Sınama sonuçları, gerektiğinde hızlı bir şekilde ulaşabilmek amacıyla, terminal tarafından özel bir ön-bellekte toplanır (sonuç ön-belleği). Terminal her parametre kümesi için bir önceki çalışmadan gelen mevcut sonuçları, yeniden işlenmesini önlemek amacıyla sonuç ön-belleği içinde kontrol eder. Söz konusu parametre kümesine dair bir sonuç bulunamamışsa, görev, işlenmesi için temsilciye verilir.

Terminal ve sınama temsilcisi arasındaki tüm trafik şifrelenmiştir.

Tikler ağ üzerinden gönderilmez; sınama temsilcilerinde oluşturulurlar.

Tüm Müşteri Terminallerinin Ortak Klasörünün Kullanılması #

Tüm sınama temsilcileri, birbirlerinden ve terminalden izole edilmiştir: her temsilci, günlüğünün kaydedildiği kendine has bir klasöre sahiptir. Bunun yanında, tüm dosya işlemleri temsilci_ismi/MQL5/Files klasöründe gerçekleşir. Ama, tüm müşteri terminallerinin ortak klasörünü kullanarak, yerel temsilciler ve terminal arasında bir etkileşim sağlayabiliriz. Bunun için, dosya açılışı kısmında FILE_COMMON bayrağını belirtmeniz gerekir:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- tüm müşteri terminalleri için paylaşılan klasör
   common_folder=TerminalInfoString(TERMINAL_COMMONDATA_PATH);
//--- klasörün ismini çıktıla
   PrintFormat("Dosyayı, tüm müşteri terminallerinin paylaşılan klasöründe aç %s", common_folder);
//--- dosyayı paylaşılan klasörde aç (indicated by FILE_COMMON flag)
   handle=FileOpen(filename,FILE_WRITE|FILE_READ|FILE_COMMON);
  ... daha sonraki eylemler
//---
   return(INIT_SUCCEEDED);
  }

DLL Dosyalarının Kullanımı #

Optimizasyonu hızlandırmak amacıyla sadece yerel temsilcileri değil, aynı zamanda uzak temsilcileri de kullanabiliriz. Bu durumda, bazı kısıtlamalar bulunmaktadır. Öncelikle, Print() fonksiyonunun çalıştırılmasından doğan sonuçları ve pozisyon açıp kapama mesajlarını günlüklerinde göstermezler. Hatalı yazılmış Uzman Danışmanların, uzak temsilcilerin bulunduğu bilgisayarı mesajlarla çöplüğe çevirmemesi için, günlük içinde sadece gereken bilgiler görüntülenir.

İkinci bir kısıtlama - Uzman Danışmanların sınanması sırasında DLL kullanımına izin verilmez. Güvenlik nedeniyle, uzak temsilciler üzerinde DLL çağrılarına kesinlikle izin verilmez. Yerel temsilcilerde ise sınanmış Uzman Danışmanın DLL kullanmasına sadece uygun şekilde izin verilir - "DLL kullanımına izin ver"

Mql5-programları için "DLL kullanımına izin ver" seçeneği

Not: DLL kullanımı gerektiren bir 3.parti Uzman Danışman (betik, gösterge) kullanırken, terminal ayarlarından bu özelliğe izin verdiğinizde aldığınız riski iyi anlamalısınız. Bu risk Uzman Danışmanın ne için kullanılacağıyla alakalı değildir.