English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
MetaTrader 5'te Çoklu Para Birimi Modunun Uygulanması

MetaTrader 5'te Çoklu Para Birimi Modunun Uygulanması

MetaTrader 5Örnekler | 16 Aralık 2021, 15:21
80 0
Konstantin Gruzdev
Konstantin Gruzdev

Giriş

Şu anda çok sayıda gelişmiş çoklu para birimli alım satım sistemi, göstergeler ve Uzman Danışmanlar bulunmaktadır. Bununla birlikte, geliştiriciler çoklu para birimli sistem geliştirmede belirli sorunlarla karşılaşmaya devam etmektedir.

MetaTrader 5 istemci terminalinin ve MQL5 programlama dilinin piyasaya sürülmesiyle birlikte tam teşekküllü bir çoklu para birimi modunu ve bunun sonucunda daha verimli çoklu para birimi robotlarını ve göstergelerini uygulamak için yeni bir fırsat elde ettik. İşte bu yeni fırsatlar bu makalenin konusu olacaktır.


Geleneksel yaklaşıma genel bakış

Bizim durumumuzda geleneksel yaklaşım MQL4'ün start() fonksiyonunun yerini alan standart OnTick() ve OnCalculate() fonksiyonlarına dayalı bir çoklu para birimi sistemi uygulama girişimidir. Basitçe söylemek gerekirse, mevcut grafikte yeni bir tikin veya çubuğun görünmesiyle birlikte ileri analizlere ve karar vermeye yönelik olarak tüm para birimi çiftleri (çoklu para birimi sistemine katılan) sırayla istenir.

Bu yaklaşımın sorunları şunlardır:

  1. Tüm sistemin mevcut grafiğin bir alım satım sembolüne gelen tiklere bağımlı olması.

    Hızlı bir piyasada mevcut grafiğin sembolüne gelen tikler devamlı olduğunda gerçekten herhangi bir sorun yoktur. Ancak, örneğin gece saatlerinde yavaşlayan bir piyasada tikler her yarım dakikada bir veya daha nadir olacak şekilde gelebilir. Nadiren gelen tiklerin geliş aralıklarında diğer sembollerde meydana gelen değişiklikler oldukça şiddetli olabilse de çoklu para birimi sisteminin tamamı o sırada “uyuyor” olur.

    Sistem büyük zaman dilimlerinde çalışacak şekilde yapılandırılmışsa bu eksiklik çok önemli değildir. Ancak zaman dilimi ne kadar küçük olursa etkisi de o kadar fazla olur. Her geçen gün dünya hızlanıyor, bilgisayarlar birim zaman başına daha fazla bilgi işleyebiliyor ve sonuç olarak daha fazla insan küçük periyotlarda ve hatta tikler üzerinde çalışmaya istekli oluyor.

  2. Çoklu para birimi sisteminde kullanılan tüm sembollerde geçmiş veri senkronizasyonunun karmaşıklığı.

    “MetaTrader 4'te yalnızca içinde en az bir fiyat değişikliğinin gerçekleştiği çubuklar çizilir. Bir dakika içinde fiyat değişikliği olmazsa bir dakikalık periyot içinde grafikte bir çubukluk boşluk oluşacaktır.” “Free-of-Holes Charts” (Deliksiz Grafikler) makalesinin başlangıcında bunlar yazılmıştır.

    Bir grafik oluşturmaya yönelik olan bu tür bir yaklaşım MetaTrader 5'te devam etmektedir. Diğer bir deyişle, her bir sembol için grafikte aynı sayıda çubuk olması bunların zamanla senkronize olduğu anlamına gelmez. Örneğin, yüzüncü çubukta her bir sembol için farklı bir açılış zamanı olabilir. Bu nedenle, çoklu para birimi göstergesinin oluşturulması ve yeniden hesaplanması sırasında her bir sembol için tüm çubukların birbiriyle tutarlı olduğundan emin olmak önemlidir.

    Bu, sistem geniş bir zaman diliminde çalışacak şekilde yapılandırılmışsa da çok önemli değildir çünkü periyodun uzamasıyla bir çubukluk boşluk oluşma olasılığı büyük ölçüde azalır. Ancak her zaman çok dikkatli olamazsınız. Ve her şeyi hemen fark edemezsiniz.

    Mevcut tamamlanmamış çubuğun senkronizasyon zamanını ayrıca not etmeliyiz. Mevcut grafikte yeni bir çubuk göründüğünde bu diğer sembollerde de yeni çubuklar oluştuğu anlamına gelmez. Bu nedenle, CopyXXXX() fonksiyonlarını kullanarak yeni bir çubuğun fiyatını başka bir sembol aracılığıyla sorgulamaya çalışmak sembole karşılık gelen bir önceki çubuğun fiyatını elde etmenize veya sadece bir kopyalama hatasına yol açabilir. Bu arada, başka bir semboldeki yeni bir çubuk mevcut olandan çok daha erken oluşabilir. Bu durum değerlendirmesinin doğruluğunu da etkileyebilir.

    Birkaç Ara Gösterge Tamponu Kullanarak Çoklu Para Birimi Göstergesi Oluşturma makalesinde geçmiş veri senkronizasyonu sorununu az çok çözen seçenekler verilmiştir.

  3. Verilerin senkronizasyonu ile ilgili bir diğer önemli nokta da şudur: Bazı alım satım sembolleri için bir geçmiş güncellemesi olduğunu nasıl anlarız?

    Örneğin, tekli bir para birimi göstergesi oluşturduğumuzda bu sorun olmaz. OnCalculate() fonksiyonunun prev_calculated girdi değişkeni sıfırlanırsa göstergeyi yeniden hesaplarız. Ancak bir sembole yönelik olarak mevcut grafikte değil de geçmişte güncelleme varsa ne yaparız? Bu durum herhangi bir zamanda oluşabilir ve çoklu para birimi göstergesinin yeniden hesaplanması gerekebilir. Bu sorunun cevabı oldukça uygulanabilirdir.

Diğer özelliklere girmeden bile şunu görebiliriz: bu üç örnek o kadar çok soruna sebep olabilir ki çoklu para birimli EA’nın veya göstergenin kodu çok uzun olabilir. Ama sorunun tamamı çözülmüş değil...


OnTimer() fonksiyonuyla yeni bir umut

MQL programının Timer olayını ve OnTimer() standart olay işleyicisini oluşturma konusundaki yeni becerisi, yeni türdeki çoklu para birimi sistemlerinin ortaya çıkması için bir umut vermiştir. Bunun nedeni bir yandan çoklu para birimli Uzman Danışman veya göstergenin mevcut grafiğin sembolüne tiklerin gelmesine bağımlı olmaktan çıkmasıdır, diğer yandan da EA’nın çalışmalarını zamana göre izleyebilmemize olanak tanımasıdır. Fakat ...

Bu, önceki bölümün 1. paragrafında açıklanan sorunları kısmen çözer ve bunun yanında bazı avantajlar sunar. Ancak NewTick olayını aldığınızda olduğu gibi, Timer olayının alınmasıyla birlikte değişiklikleri takip etmek için tüm para birimi çiftlerini sırayla sorgulamanız gerekir. Bazen bunun oldukça sık yapılması gerekir, bu da MQL5 programlarının kaynaklarının kullanımını önemli ölçüde arttırabilir.

2. ve 3. paragraflarda tanımlanan sorunların çözülmesi Buna ek olarak OnTimer() fonksiyonuna özgü sorunları da çözmek gerekir. Örneğin zamanlayıcının başlatılması veya başlatılmaması, hafta sonları çalışması vb.

OnTimer() olay işleyicisinin bariz avantajlarını küçümsemesek de bir çoklu para birimi modunun tam olarak uygulanmasına izin vermediğine dikkat edilmelidir.


OnChartEvent() fonksiyonuyla yeni olanaklar

Yukarıdaki standart fonksiyonların sınırlamaları dar bir alanda çalışmalarından kaynaklanır; çoklu para birimi sistemlerine değil de önceden tanımlanmış olayları işlemeye yöneliktirler. 

Çoklu para birimi sisteminin geliştiricisi için kurtarma elemanı OnChartEvent() adındaki standart bir özel olay işleyicisi olabilir. Programcının kendi takdirine bağlı olarak kendi olaylarını oluşturmasını sağlar.

Örneğin, mevcut grafikteki herhangi bir sembole gelen tikler için bu fonksiyonu kullanmamızı kimse engelleyemez. Tek yapmamız gereken uygun bir sembol kullanarak tabloya bir “casus” göndermek.

Bu komik “casus” kelimesiyle şu göstergeyi kastediyorum:

//+------------------------------------------------------------------+
//|                                                         iSpy.mq5 |
//|                                            Copyright 2010, Lizar |
//|                                               lizar-2010@mail.ru |
//+------------------------------------------------------------------+
#define VERSION         "1.00 Build 2 (26 Dec 2010)"

#property copyright   "Copyright 2010, Lizar"
#property link        "https://www.mql5.com/ru/users/Lizar"
#property version     VERSION
#property description "iSpy agent-indicator. If you want to get ticks, attach it to the chart"
#property indicator_chart_window

input long            chart_id=0;        // chart id
input ushort          custom_event_id=0; // event id

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate (const int rates_total,        // size of price[] array
                 const int prev_calculated,  // bars, calculated at the previous call
                 const int begin,            // starting index of data
                 const double& price[]       // array for the calculation
   )
  {
   double price_current=price[rates_total-1];

   //--- Initialization:
   if(prev_calculated==0) 
     { // Generate and send "Initialization" event
      EventChartCustom(chart_id,0,(long)_Period,price_current,_Symbol);
      return(rates_total);
     }
   
   // When the new tick, let's generate the "New tick" custom event
   // that can be processed by Expert Advisor or indicator
   EventChartCustom(chart_id,custom_event_id+1,(long)_Period,price_current,_Symbol);
   
   //--- return value of prev_calculated for next call
   return(rates_total);
  }

Bu “casus”u istenen sembolün grafiğinde başlatabilir ve ardından mesajlarını EA'da veya OnChartEvent() fonksiyonunda kullanarak göstergede işleyebiliriz. “Casus” mesajlarının kodunu doğru bir şekilde çözmek için bu fonksiyonun parametrelerini şu şekilde yorumlamalıyız:

  • id: olay tanımlayıcısı. Eğer id-CHARTEVENT_CUSTOM = 0 ise kullandığımız “casus” prev_calculated değişkeninin sıfırlandığını ve uygun eylemlerin yapılması gerektiğini bildirir;
  • lparam: “casus” un başlatıldığı grafiğin periyodunu ifade eder;
  • dparam: tik fiyatı. Varsayılan olarak bu son kapanış fiyatıdır. Ancak “Casus”un başlatılması sırasında bu ENUM_APPLIED_PRICE dökümünden herhangi bir değere ayarlanabilir;
  • sparam: olayın alındığı alım satım sembolünün adı.

Birkaç “casus”un eşzamanlı çalışmasını göstermek için basit bir EA exSpy.mq5 yazacağız (tam sürüm arşivde mevcuttur):

//+------------------------------------------------------------------+
//|                                                        exSpy.mq5 |
//|                                            Copyright 2010, Lizar |
//|                            https://www.mql5.com/ru/users/Lizar |
//+------------------------------------------------------------------+
#define VERSION       "1.00 Build 1 (26 Dec 2010)"

#property copyright   "Copyright 2010, Lizar"
#property link        "https://www.mql5.com/ru/users/Lizar"
#property version     VERSION
#property description "The Expert Advisor shows the work of iSPY indicator"

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {   
   if(iCustom("GBPUSD",PERIOD_M1,"iSpy",ChartID(),0)==INVALID_HANDLE) 
      { Print("Error in setting of spy on GBPUSD"); return(true);}
   if(iCustom("EURUSD",PERIOD_M1,"iSpy",ChartID(),1)==INVALID_HANDLE) 
      { Print("Error in setting of spy on EURUSD"); return(true);}
   if(iCustom("USDJPY",PERIOD_M1,"iSpy",ChartID(),2)==INVALID_HANDLE) 
      { Print("Error in setting of spy on USDJPY"); return(true);}
      
   Print("Spys ok, waiting for events...");
   //---
   return(0);
  }
  
//+------------------------------------------------------------------+
//| The Standard event handler.                                      |
//| See MQL5 Reference for the details.                              |
//|                                                                  |
//| In this case it is used for decoding of spy messages, sent by    |
//| iSPY spy indicator                                               |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,         // event id:
                                     // if id-CHARTEVENT_CUSTOM=0-"initialization" event
                const long&   lparam, // chart period
                const double& dparam, // price
                const string& sparam  // symbol
               )
  {
   if(id>=CHARTEVENT_CUSTOM)      
     {
      Print(TimeToString(TimeCurrent(),TIME_SECONDS)," -> id=",
            id-CHARTEVENT_CUSTOM,":  ",sparam," ",
            EnumToString((ENUM_TIMEFRAMES)lparam)," price=",dparam);
     }
  }
//+------------------------------------------------------------------+

Uzman Danışmanı herhangi bir grafikte başlatın.

Sonuçlar şöyle:


 

Günlükten görülebileceği gibi, özellikle geçmişe ilişkin bir güncelleme veya yükleme durumunda alınacak olan “initialization” (başlatma) olayının yanı sıra istenen sembol için tüm tikleri alıyoruz.

Ara sonuçları bir özetleyelim:

  • Standart OnTick() ve OnCalculate() fonksiyonlarını kullandığımızda yaptığımız gibi, belirli bir sembolün tiklerine bağımlı değiliz.
  • OnTimer() kullanırken olduğu gibi kesin olarak tanımlanmış zaman aralıklarıyla sınırlı değiliz.
  • Değişikliklerini takip etmek için tüm sembolleri bir sırayla veya bir döngü içinde istemeye gerek yoktur. Sembolde değişiklikler meydana geldiğinde ilgili olayı elde ederiz. Olayın meydana geldiği sembolü id olay tanımlayıcısı veya sparam parametresi ile tanımlayabiliriz.
  • Her bir sembole yönelik olarak sunucu ile geçmiş verilerin senkronizasyonunu ayrı ayrı izleme sorununu çözmüş olduk.
  • Çalışmanın küçük bir kısmı ek programlara ayrılmıştır. Bu durum veri işlemenin paralel hale getirilmesiyle ilgilidir.
  • OnChartEvent() fonksiyonunun parametrelerinde sembolün periyodu, fiyatı ve adı gibi ek bilgiler elde ederiz. Bu durum EA veya gösterge kodunu büyük ölçüde basitleştirebilir çünkü bu veriler için ek sorgulama yapmaya gerek yoktur.

Bu noktada artık MetaTrader 5 terminali ve MQL5'in programlama dili aracılığıyla çoklu para birimi modunu başarıyla uyguladığımız için bu makaleyi sonlandırabiliriz. Ancak bu modun “kabaca” uygulanmış halidir. Bu nedenle anlatıma devam edeceğiz.


Çoklu para birimi modunun uygulanması

Yukarıda anlatıldığı gibi çoklu para birimi rejimini temel haliyle uygularsanız bir noktadan sonra zorluklarla karşılaşmaya başlarsınız. Sorun şu ki, böyle bir yaklaşım “casus” un çalıştığı her bir alım satım sembolüne karşılık gelen tüm tikleri almamıza izin verir.

Hızlı bir piyasada bir saniyede her sembole karşılık gelen birkaç tik olabilir. Bu durum olay sırasının “tıkanmasına” yol açabilir. Yardım bölümünden bir uyarıyı verelim:

İstemci terminali görünen olayları olaylar kuyruğuna ekler. Böylece olaylar alındıkları sıraya göre birbiri ardına işlenir. NewTick olayı için bir istisna mevcuttur. Kuyrukta zaten böyle bir olay varsa veya bu olay işleniyorsa yeni NewTick olayı sıraya alınmaz.

Olay kuyruğu boyut açısından sınırlandırılmıştır. Kuyruk taşması durumunda yeni olayların alınmasına izin vermek için eski olaylar işlenmeden kaldırılır. Bu nedenle, verimli olay işleyicileri yazılması önerilir ve sonsuz döngüler kullanılması önerilmez (yalnızca Start olayını işleyen komut dosyalarının bir istisnası mevcuttur).

Kuyruğun taşması çoklu para birimli EA veya gösterge için önemli olayların kaybolmasına neden olabilir. Bir yandan durum böyledir. Diğer yandansa tüm semboller için her zaman tiklere ihtiyacımız yoktur. Bazen herhangi bir zaman diliminde yalnızca “new bar” (yeni çubuk) olayını elde etmemiz gerekir. Veya farklı zaman dilimleri için bir dizi “yeni çubuk” olayını elde etmemiz gerekir. Temel olarak, bizim “casusumuz” bu tür gereksinimler için uygun değildir ve kullanımı çok müsait değildir.

Bunu evrensel hale getirelim ve böylece çoklu para birimli bir EA veya gösterge sembolüne dayalı bir olayın nasıl elde edileceği konusuna bir daha geri dönmek zorunda kalmayalım. Bu amaçla Çoklu Para Birimli Uzman Danışmanlar ve Göstergeler tanımı için “MCM Kontrol Paneli”nde yer alan ENUM_CHART_EVENT_SYMBOL olay dökümünü örnek olarak alalım:

enum ENUM_CHART_EVENT_SYMBOL
  {
   CHARTEVENT_INIT      =0,         // "Initialization" event
   CHARTEVENT_NO        =0,         // No events

   CHARTEVENT_NEWBAR_M1 =0x00000001, // "New bar" event on M1 chart
   CHARTEVENT_NEWBAR_M2 =0x00000002, // "New bar" event on M2 chart
   CHARTEVENT_NEWBAR_M3 =0x00000004, // "New bar" event on M3 chart
   CHARTEVENT_NEWBAR_M4 =0x00000008, // "New bar" event on M4 chart
   
   CHARTEVENT_NEWBAR_M5 =0x00000010, // "New bar" event on M5 chart
   CHARTEVENT_NEWBAR_M6 =0x00000020, // "New bar" event on M6 chart
   CHARTEVENT_NEWBAR_M10=0x00000040, // "New bar" event on M10 chart
   CHARTEVENT_NEWBAR_M12=0x00000080, // "New bar" event on M12 chart
   
   CHARTEVENT_NEWBAR_M15=0x00000100, // "New bar" event on M15 chart
   CHARTEVENT_NEWBAR_M20=0x00000200, // "New bar" event on M20 chart
   CHARTEVENT_NEWBAR_M30=0x00000400, // "New bar" event on M30 chart
   CHARTEVENT_NEWBAR_H1 =0x00000800, // "New bar" event on H1 chart
   
   CHARTEVENT_NEWBAR_H2 =0x00001000, // "New bar" event on H2 chart
   CHARTEVENT_NEWBAR_H3 =0x00002000, // "New bar" event on H3 chart
   CHARTEVENT_NEWBAR_H4 =0x00004000, // "New bar" event on H4 chart
   CHARTEVENT_NEWBAR_H6 =0x00008000, // "New bar" event on H6 chart
   
   CHARTEVENT_NEWBAR_H8 =0x00010000, // "New bar" event on H8 chart
   CHARTEVENT_NEWBAR_H12=0x00020000, // "New bar" event on H12 chart
   CHARTEVENT_NEWBAR_D1 =0x00040000, // "New bar" event on D1 chart
   CHARTEVENT_NEWBAR_W1 =0x00080000, // "New bar" event on W1 chart
     
   CHARTEVENT_NEWBAR_MN1=0x00100000, // "New bar" event on MN1 chart
   CHARTEVENT_TICK      =0x00200000, // "New tick" event
   
   CHARTEVENT_ALL       =0xFFFFFFFF, // All events
  };

Aslında bu döküm özel grafik olaylarının bir bayrağıdır. Çoklu para birimi modu için gerekli olabilecek minimum kümedir. Elbette tamamlanabilir. Bayrakların kombinasyonu “casus”tan göndereceğimiz olayları belirleyecektir.

Bayraklar “OR” bitsel işlemi kullanılarak birleştirilebilir. Örneğin, CHARTEVENT_NEWBAR_M1 | CHARTEVENT_NEWBAR_H1 kombinasyonu “casus” yardımıyla “yeni çubuk” olayların dakika ve saatlik zaman diliminden göndereceğimiz anlamına gelecektir. Bu bayraklar casus göstergemizin girdi parametresi olacaktır. Ayrıca buna “agent-indicator” (aracı gösterge) diyeceğiz.

Göstergenin kendisi yeni fikirlere göre şöyle görünür:

//+------------------------------------------------------------------+
//|                                        Spy Control panel MCM.mq5 |
//|                                            Copyright 2010, Lizar |
//|                            https://www.mql5.com/en/users/Lizar |
//+------------------------------------------------------------------+
#define VERSION       "1.00 Build 3 (26 Dec 2010)"

#property copyright   "Copyright 2010, Lizar"
#property link        "https://www.mql5.com/en/users/Lizar"
#property version     VERSION
#property description "This is the MCM Control Panel agent-indicator."
#property description "Is launched on the required symbol on any time-frame"
#property description "and generates the custom NewBar event and/or NewTick"
#property description "for the chart which receives the event"

#property indicator_chart_window
  
input long                    chart_id;                 // identifier of the chart which receives the event
input ushort                  custom_event_id;          // event identifier  
input ENUM_CHART_EVENT_SYMBOL flag_event=CHARTEVENT_NO;// indicator, which determines the event type.

MqlDateTime time, prev_time;

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate (const int rates_total,       // size of the price[] array
                 const int prev_calculated, // bars processed at the previous call
                 const int begin,           // where the data begins
                 const double& price[]      // calculations array
   )
  {  
   double price_current=price[rates_total-1];

   TimeCurrent(time);
   
   if(prev_calculated==0)
     {
      EventCustom(CHARTEVENT_INIT,price_current);
      prev_time=time; 
      return(rates_total);
     }
   
//--- new tick
   if((flag_event & CHARTEVENT_TICK)!=0) EventCustom(CHARTEVENT_TICK,price_current);       

//--- check change time
   if(time.min==prev_time.min && 
      time.hour==prev_time.hour && 
      time.day==prev_time.day &&
      time.mon==prev_time.mon) return(rates_total);

//--- new minute
   if((flag_event & CHARTEVENT_NEWBAR_M1)!=0) EventCustom(CHARTEVENT_NEWBAR_M1,price_current);     
   if(time.min%2 ==0 && (flag_event & CHARTEVENT_NEWBAR_M2)!=0)  EventCustom(CHARTEVENT_NEWBAR_M2,price_current);
   if(time.min%3 ==0 && (flag_event & CHARTEVENT_NEWBAR_M3)!=0)  EventCustom(CHARTEVENT_NEWBAR_M3,price_current); 
   if(time.min%4 ==0 && (flag_event & CHARTEVENT_NEWBAR_M4)!=0)  EventCustom(CHARTEVENT_NEWBAR_M4,price_current);      
   if(time.min%5 ==0 && (flag_event & CHARTEVENT_NEWBAR_M5)!=0)  EventCustom(CHARTEVENT_NEWBAR_M5,price_current);     
   if(time.min%6 ==0 && (flag_event & CHARTEVENT_NEWBAR_M6)!=0)  EventCustom(CHARTEVENT_NEWBAR_M6,price_current);     
   if(time.min%10==0 && (flag_event & CHARTEVENT_NEWBAR_M10)!=0) EventCustom(CHARTEVENT_NEWBAR_M10,price_current);      
   if(time.min%12==0 && (flag_event & CHARTEVENT_NEWBAR_M12)!=0) EventCustom(CHARTEVENT_NEWBAR_M12,price_current);      
   if(time.min%15==0 && (flag_event & CHARTEVENT_NEWBAR_M15)!=0) EventCustom(CHARTEVENT_NEWBAR_M15,price_current);      
   if(time.min%20==0 && (flag_event & CHARTEVENT_NEWBAR_M20)!=0) EventCustom(CHARTEVENT_NEWBAR_M20,price_current);      
   if(time.min%30==0 && (flag_event & CHARTEVENT_NEWBAR_M30)!=0) EventCustom(CHARTEVENT_NEWBAR_M30,price_current);      
   if(time.min!=0) {prev_time=time; return(rates_total);}
//--- new hour
   if((flag_event & CHARTEVENT_NEWBAR_H1)!=0) EventCustom(CHARTEVENT_NEWBAR_H1,price_current);
   if(time.hour%2 ==0 && (flag_event & CHARTEVENT_NEWBAR_H2)!=0)  EventCustom(CHARTEVENT_NEWBAR_H2,price_current);
   if(time.hour%3 ==0 && (flag_event & CHARTEVENT_NEWBAR_H3)!=0)  EventCustom(CHARTEVENT_NEWBAR_H3,price_current);      
   if(time.hour%4 ==0 && (flag_event & CHARTEVENT_NEWBAR_H4)!=0)  EventCustom(CHARTEVENT_NEWBAR_H4,price_current);      
   if(time.hour%6 ==0 && (flag_event & CHARTEVENT_NEWBAR_H6)!=0)  EventCustom(CHARTEVENT_NEWBAR_H6,price_current);      
   if(time.hour%8 ==0 && (flag_event & CHARTEVENT_NEWBAR_H8)!=0)  EventCustom(CHARTEVENT_NEWBAR_H8,price_current);      
   if(time.hour%12==0 && (flag_event & CHARTEVENT_NEWBAR_H12)!=0) EventCustom(CHARTEVENT_NEWBAR_H12,price_current);      
   if(time.hour!=0) {prev_time=time; return(rates_total);}
//--- new day
   if((flag_event & CHARTEVENT_NEWBAR_D1)!=0) EventCustom(CHARTEVENT_NEWBAR_D1,price_current);      
//--- new week
   if(time.day_of_week==1 && (flag_event & CHARTEVENT_NEWBAR_W1)!=0) EventCustom(CHARTEVENT_NEWBAR_W1,price_current);      
//--- new month
   if(time.day==1 && (flag_event & CHARTEVENT_NEWBAR_MN1)!=0) EventCustom(CHARTEVENT_NEWBAR_MN1,price_current);      
   prev_time=time;
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

void EventCustom(ENUM_CHART_EVENT_SYMBOL event,double price)
  {
   EventChartCustom(chart_id,custom_event_id,(long)event,price,_Symbol);
   return;
  } 

Bu gösterge adını değiştirmediğimiz MCM Kontrol panelinin bir parçasıdır, ekler yalnızca güncellenmiş bir sürümünü içerir (bkz. “Casus Kontrol paneli MCM.mq5”). Ancak bu, göstergenin panelden ayrı olarak kullanılamayacağı anlamına gelmez.

Bu aracı gösterge özel kullanıcı olayları oluşturur ve OnChartEvent() fonksiyonunu kullanarak bu olayların EA'da veya göstergede daha fazla işlenmesi için onları grafik alıcısına iletir. Şimdi bu fonksiyonun girdi parametreleri şu şekilde yorumlanmalıdır:

  • id: olay tanımlayıcısı,
  • lparam: panel aracısından alınan olayın göstergesi. ENUM_CHART_EVENT_SYMBOL dökümüne karşılık gelen göstergeler:
  • dparam: belirli bir zaman dilimi için yeni bir çubuğa ilişkin tik fiyatı veya açılış fiyatı,
  • sparam: olayın gerçekleştiği alım satım sembolünün adı.

 Demo EA öncekinden daha karmaşık görünmüyor (tam sürüm arşivde mevcuttur):

//+------------------------------------------------------------------+
//|                                      exSpy Control panel MCM.mq5 |
//|                                            Copyright 2010, Lizar |
//|                            https://www.mql5.com/en/users/Lizar |
//+------------------------------------------------------------------+
#define VERSION       "1.00 Build 1 (28 Dec 2010)"

#property copyright   "Copyright 2010, Lizar"
#property link        "https://www.mql5.com/en/users/Lizar"
#property version     VERSION
#property description "The EA demonstrates the work of the MCM Spy Control panel"

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {   
   if(iCustom("GBPUSD",PERIOD_M1,"Spy Control panel MCM",ChartID(),0,
             CHARTEVENT_NEWBAR_M1|CHARTEVENT_NEWBAR_M5)==INVALID_HANDLE) 
      { Print("Error in setting of spy on GBPUSD"); return(true);}
   if(iCustom("EURUSD",PERIOD_M1,"Spy Control panel MCM",ChartID(),1,
             CHARTEVENT_NEWBAR_M2)==INVALID_HANDLE) 
      { Print("Error in setting of spy on EURUSD"); return(true);}
   if(iCustom("USDJPY",PERIOD_M1,"Spy Control panel MCM",ChartID(),2,
             CHARTEVENT_NEWBAR_M6)==INVALID_HANDLE) 
      { Print("Error in setting of spy on USDJPY"); return(true);}
      
   Print("Spys ok, waiting for events...");
   //---
   return(0);
  }
  
//+------------------------------------------------------------------+
//| The Standard event handler.                                      |
//| See MQL5 Reference for the details.                              |
//|                                                                  |
//| In this case it is used for decoding of spy messages, sent by    |
//| iSPY Control panel MCM indicator.                                |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,           // event identifier
                  const long&   lparam, // the event flag.
                                       // event flag is a bit mask of ENUM_CHART_EVENT_SYMBOL enumeration.
                  const double& dparam, // price
                  const string& sparam  // symbol 
                 )
  {
   if(id>=CHARTEVENT_CUSTOM)      
     {
      Print(TimeToString(TimeCurrent(),TIME_SECONDS)," -> id=",id-CHARTEVENT_CUSTOM,
           ":  ",sparam," ",EnumToString((ENUM_CHART_EVENT_SYMBOL)lparam)," price=",dparam);
     }
  }

exSpy Kontrol paneli MCM çalışmasının sonuçları:


 

Gördüğünüz gibi, talep edilen tüm olayları düzenli olarak alıyoruz.

Ara sonucu bir kez daha özetleyelim:

  • Aracı göstergenin yeni versiyonu sayesinde önceki tüm başarılarımızı korumuş olduk.
  • Şimdi çoklu para birimli MQL programlarımızdan “new tick” (yeni tik), “new bar” (yeni çubuk) ve “initialization” (başlatma) olaylarını içeren en az 23 olay belirtebiliriz.
  • Aracıları boşaltmak için EA veya göstergeden daha da fazla çalışma aracılara verilir. 

Görünen o ki, MetaTrader 5'te tam teşekküllü bir çoklu para birimi modunu uygulamak o kadar da zor değil.

Ek olarak birkaç ince ayrıntı üzerinde durmak istiyorum.

İlki şöyle: Çoklu para birimli EA veya göstergemiz için “agents” (aracılar) tarafından oluşturulan tüm olaylar haricidir. Bununla bağlantılı olarak şu soru ortaya çıkar: “Aracıları doğrudan EA’dan veya göstergeden çalıştırmak gerekli midir?” Cevabımız “hayır”dır.

İkincisi: OnChartEvent() fonksiyonunda olay tanımlayıcı kimliğine gerek yok gibi görünüyor çünkü olayın hangi sembol için alındığını sparam parametresi, yani alım satım sembolünün adı ile bulabiliyoruz. Bu nedenle, bunu başka bir amaç için kullanabilir miyiz? Cevap: “Evet, kullanabiliriz.” 

Bu tür argümanlar, Çoklu Para Birimli Uzman Danışmanlar ve Göstergeler için “ÇMY Kontrol Paneli”nin ortaya çıkmasına neden olmuştur. Bu, terminal ve bir EA veya gösterge arasında bir tür “ara katman” olarak çalışır. Bize çoklu para birimli bir ortamı yapılandırmada daha fazla avantaj ve esneklik sağlamıştır:

  • Bu panel tablo üzerinde ayrı bir gösterge olarak kurulabilir ve ardından panel ile uyumlu çoklu para birimi göstergeleri atanabilir.
  • Panelde bileşen birimleri olarak göstergeler ve EA'lar yer alabilir. Panel bunlarla birlikte yüklenir.  
  • “Events” menüsünü kullanarak alım satım veya analiz için “Market Watch” penceresinden sembolü etkinleştirebilir veya devre dışı bırakabiliriz. OnChartEvent() fonksiyonunda “Market Watch” penceresinde olay tanımlayıcı kimliğine göre sembolün seri numarasını bulamıyoruz.
  • Alım satım modunu herhangi bir periyot veya “Market Watch”da seçilen sembol için tikler veya “yeni çubuk” olayına göre ayarlayabiliriz. Bütün bunlar normal menü kullanılarak yapılabilir.
  • Yukarıdaki konfigürasyonların hepsini boşaltmadan, durdurmadan veya EA’nın ya da göstergenin özellikler penceresine girmeden değiştirebiliriz.
  • Tüm bunlar çoklu para birimli EA'ların veya göstergelerin oluşturulmasındaki yaratıcılık potansiyelini kısıtlamaz. Buna ek olarak artık bu panelin çıktılarını kodumuza entegre etmemize gerek yoktur. Aracı göstergelerin yönetimi artık kontrol panelinde gerçekleştirilebilir.
  • Çoklu para birimi sisteminin yapısı bundan daha da basittir.


USDx dolar endeksi için çoklu para birimi göstergesi RSI

Yukarıdaki yöntemin tüm avantajlarını deneyimlemek için MCM Kontrol Panelini kullanarak USDx dolar endeksi için RSI göstergesinin çoklu para birimi varyantını uygulamayı öneriyorum.

Başlangıç olarak birkaç özel özelliğin üzerinde duracağım. Genellikle, Dolar Endeksini analiz etmeye çalışırken sadece endeksin okumalarının göstergelerini sayarız. Benim bakış açıma göre bu tamamen doğru değildir çünkü para birimi çiftleri sepetindeki her sembol kendi katkısını sunar. Bu nedenle, örneğin endeks hesaplama formülüne benzer bir formülle dolar endeksi için RSI'yı hesaplayalım:

Yani önce belirli bir para birimi çiftine ilişkin RSI'yı hesaplayacağız ve ardından katsayıların ağırlığını hesaba katarak endekse ilişkin RSI'yı okuyacağız.

Okuyucu, çoklu para birimi sisteminde kullanılan tüm sembollerin geçmiş veri senkronizasyonunda bir sorun olduğunu fark edebilir (“Geleneksel yaklaşıma genel bakış” bölümünün 2. paragrafına bakınız).

Bu sorun RSI senkronize tamponları (SynchronizedBufferRSI.mqh dosyası) oluşturmaya ilişkin sınıf fonksiyonları kullanılarak göstergede çözülmüştür. Sınıfın tüm kodunu vermenin bir anlamı yoktur, bu nedenle aşağıda yalnızca ilgili bilgiler verilmiştir. 

İlk olarak, gösterge tamponu genel erişim değiştiricisi ile sınıf içinde tanımlanır:

public:
   double   buffer[];   // indicator buffer

İkinci olarak, gösterge başlatma sınıf yöntemi kullanılarak yapılır:

//--- Initialization methods:
bool Init(int n,string symbol,int rsi_count,int rsi_period);

Üçüncü olarak da her bir çubuk için gösterge tamponunun değeri sınıfın yenileme yöntemi kullanılarak mevcut zaman dilimi ile senkronize edilir:

//+------------------------------------------------------------------+
//| The method of receiving/updating indicator data for one bar      |
//| of the indicator buffer.                                         |
//| INPUT:  bar   - bar number                                       |
//| OUTPUT: no.                                                      |
//| REMARK: no.                                                      |
//+------------------------------------------------------------------+
void CSynchronizedBufferRSI::Refresh(int bar=0)
  {
   buffer[bar]=EMPTY_VALUE; // Initialization of the bar of the indicator buffer.
     
   //--- Inquire the time of the bar for the current graph:
   datetime time[1];      
   if(CopyTime(_Symbol,_Period,bar,1,time)!=1) return; // In case of an error, we wait for the next tick/bar...

   //--- Request the value of the indicator for the symbol for the time,
   //--- consistent with that of the bar of the current graph:
   double value[1];
   if(CopyBuffer(m_handle,0,time[0],time[0],value)!=1) return; // In case of an error, wait for the next tick/bar...

   buffer[bar]=value[0];
   return;
  }

Tüm gösterge tamponlarının tam senkronizasyonu için aşağıdaki makalede açıklandığı gibi “delikler” olmadan tam bir dakikalık zaman dilimi kullanmamız gerekir. Ancak gösterge tamponlarının bu senkronizasyon yönteminde mevcut grafiğin zaman dilimini gösterge ekranı üzerinde gerçekleştiği için özel olarak seçtik.

Kendi deneyimlerime dayanarak söyleyebilirim ki, eğer sembolleri mevcut grafikteki sembolden farklıysa küçük periyotlar söz konusu olduğunda herhangi bir zaman serisi veya gösterge tamponu için böyle bir senkronizasyon yöntemi kullanmak mantıklıdır

Aşağıdaki grafik bunun neden yapmaya değer bir şey olduğunu açıkça göstermektedir:


 

Daha büyük zaman dilimleri için bu genellikle gözlenmez.

Ve son olarak: Göstergede kullanılan standart bir kullanıcı olay işleyicisinin kodu aşağıdadır:

//+------------------------------------------------------------------+
//| The Standard event handler.                                      |
//| See MQL5 Reference for the details.                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,         // event identifier or position symbol in the "Market Match"+CHARTEVENT_CUSTOM  
                const long& lparam,   // event indicator
                const double& dparam, // price
                const string& sparam  // symbol
                )
  {
   int custom_id=id-CHARTEVENT_CUSTOM-1;
   
   if(custom_id>=0)      
     {
      if(lparam!=CHARTEVENT_NEWBAR_NO)
        { 
         //--- Recalculation of the last uncompleted bar:
         if(EventToPeriod(lparam)==_Period && sparam==_Symbol)
           { // Recalculation of the indicator, if a new bar on the current chart
            iRSIUSDx_Ind[0]=EMPTY_VALUE;
            //--- Updating the value of the RSI for all of the currency pairs for the new bar
            for(int i=0;i<symbol_total;i++) buffer[i].Refresh();
            iRSIUSDx(symbol_total);   // calculation of the current incomplete bar RSI for the index
            return;
           }
         
         buffer[custom_id].Refresh(); // The value of RSI for the custom_id of the currency pair for the current bar
         iRSIUSDx(symbol_total);      // calculation of the RSI for the current(uncompleted) bar RSIx
         return;
        }
      else 
        { 
         //--- Recalculation of the indicator for the "Initialization" event 
         buffer[custom_id].RefreshBuffer();     // Update of the RSI buffer for the custom_id of the currency pair
         Init_iRSIUSDx(symbol_total,calculate); // Update of the RSI buffer for the index
         return;
        }
     }
  }

Kodun diğer özellikleri:

  • Olay tanımlayıcı kimliğinin, geçerli zaman dilimiyle senkronize edilmiş RSI gösterge tamponlarını hesaplaması amaçlanan sınıf örneklerine ilişkin işaretçileri içeren diziye başvurmak için kullanılması. Bu yaklaşım kodun yapısını büyük ölçüde basitleştirir.
  • “Başlatılıyor” olayı RSI gösterge tamponunu yalnızca alındığı para birimi çifti için yeniden hesaplamada kullanılır, altı sembolün tümü için kullanılmaz. Daha önce belirtildiği gibi bu, örneğin bir sembolün geçmişini güncellerken göstergeyi senkronize etmenize olanak tanır.
  • “Yeni çubuk” olayı mevcut grafikteki yeni bir çubuk için tüm RSI gösterge tamponlarını senkronize etmede kullanılır.
  • Son tamamlanmamış çubuktaki göstergeleri güncellemek için tüm para birimi çiftlerinde “yeni tik” olayı kullanılır. Ayrıca çubuğun yeniden sayımı yalnızca “yeni tik”in alındığı çift için yapılır. 

USDx dolar endeksi için RSI göstergesinin tam kodunu keşfettikten sonra bunun nasıl çalıştığı daha anlaşılır bir hale gelecektir.

Kurulum özellikleri:

  • Çoklu Para Birimli Uzman Danışmanlar ve Göstergeler için “MCM Kontrol Paneli”ni indirin ve “iControl panel MCM.mq5” ve “Spy Control panel MCM.mq5” dosyalarını derleyin.
  • “Market Match” penceresinde aşağıdaki sembol sırasını belirtin:
    1. EURUSD
    2. USDJPY
    3. GBPUSD
    4. USDCAD
    5. USDSEK
    6. USDCHF
    Bu gereklidir çünkü göstergeye uygun bir kontrol koymadım ve bu sıra göstergenin doğru hesaplanması için gerekli.
  • iRSIUSDx.zip arşivini /MQL5 klasörünün içine açın. /MQL5/Indicators/iRSIUSDx/ klasöründeki iRSIUSDx.ex5 dosyasını M1 periyoduyla birlikte EURUSD grafiğine ekleyin.
  • Sırayla “Kontrol paneli MCM” panelinin “Event” menüsündeki altı sembolün tümü için burada açıklandığı gibi “Yeni tik” olayını ayarlayın. Yukarıdaki görüntüye benzer bir görüntü elde etmelisiniz.
  • Ek olarak, EURUSD sembolü için dakika tablosunda “yeni çubuk” olayını ayarlayın. Göstergede bu olay mevcut zaman diliminde M1'e eşit olan yeni çubuk oluştuğunda senkronizasyon amacıyla kullanılır.
  • Daha görsel bir örnek isterseniz dolar endeksini burada anlatıldığı gibi ayarlayın.

Sonuç

MetaTrader 5'te tam teşekküllü çoklu para birimi modunun ele alınan bu uygulaması bu sorunu çözmede platformun ve MQL5 programlama dilinin avantajlarını tam olarak göstermektedir. Daha önce zorlukların çoğuna neden olan şeyin artık çözümü mevcuttur.

Bunun bu yönde bir hareketin yalnızca başlangıcı olduğu açıktır. Elbette daha da iyi olan bir veri senkronizasyonu yolu ve çoklu para birimi modları yönetimi vb. için daha fazla seçenek bulunacaktır.  Ama umarım şu anda bunun için gerekli tüm araçlara sahip olduğumuz anlaşılmıştır.


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

Ekli dosyalar |
irsiusdx_en.zip (7.54 KB)
NeuroSolutions Yapay Sinir Ağlarını Bağlama NeuroSolutions Yapay Sinir Ağlarını Bağlama
NeuroSolutions yazılım paketi, yapay sinir ağlarının oluşturulmasına ek olarak bunların DLL olarak dışa aktarılmasına da izin verir. Bu makale yapay bir sinir ağı ve bir DLL oluşturma ve bunu MetaTrader 5'te alım satım yapmak için bir Uzman Danışmana bağlama sürecini açıklar.
MQL5 Sihirbazı: Açık Pozisyonların İzlenme Modülü Nasıl Oluşturulur MQL5 Sihirbazı: Açık Pozisyonların İzlenme Modülü Nasıl Oluşturulur
MQL5 Sihirbazının alım satım stratejileri üreticisi, alım satım fikirlerinin test edilmesini büyük ölçüde basitleştirir. Bu makale MQL5 Sihirbazının alım satım stratejileri üreticisine nasıl bağlanılacağını ve alım satım yaparken kârınızı korumaya izin veren ve düşüşleri azaltan, fiyat pozisyon yönünde gittiğinde Zarar Durdur seviyesini kayıpsız bir bölgeye taşıyarak açık pozisyonları yöneten sınıfınızı nasıl yazacağınızı ele alır. Ayrıca MQL5 Sihirbazı için oluşturulan sınıfın tanımının yapısı ve formatı hakkında bilgi verir.
Hareketli Mini-Maks: Teknik Analiz için Yeni Bir Gösterge ve MQL5'te Uygulanması Hareketli Mini-Maks: Teknik Analiz için Yeni Bir Gösterge ve MQL5'te Uygulanması
Aşağıdaki makalede, Z.G. Silagadze'nin “Moving Mini-max: a new indicator for technical analysis” (Hareketli Mini-Maks: Teknik Analiz için Yeni Bir Gösterge) başlıklı makalesine dayanan Hareketli Mini-Maks göstergesini uygulama sürecini anlatıyorum. Gösterge fikri G. Gamov tarafından alfa bozunması teorisinde önerilen kuantum tünelleme olayının simülasyonuna dayanmaktadır.
HTML'de grafikler ve şemalar HTML'de grafikler ve şemalar
Günümüzde içinde ağ tarayıcısı yüklü olmayan bir bilgisayar bulmak zordur. Ağ tarayıcıları uzun zamandır evrimleşip iyileşiyorlar. Bu makale, grafik ve şemaların tarayıcılarda görüntülenmesini sağlayan bir işlem platformu olan MetaTrader 5’ten alınan bilgilere dayanarak güvenli bir şekilde nasıl grafik ve şema oluşturulabileceğini anlatır.