English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
Çok Sayıda Enstrüman Üzerinde Alım Satım Yapan bir Expert Advisor Oluşturma

Çok Sayıda Enstrüman Üzerinde Alım Satım Yapan bir Expert Advisor Oluşturma

MetaTrader 5Örnekler | 15 Aralık 2021, 10:03
94 0
Nikolay Kositsin
Nikolay Kositsin

Giriş

Tek bir grafik üzerinde başlatılan tek bir Expert Advisor'ın aynı anda farklı finansal varlıklarla işlem yapabilmesi için program kodunu uygulamanın teknik yönü. Genel olarak, bu MQL4'te dahi herhangi bir sorun teşkil etmedi. Ancak yalnızca MetaTrader 5 istemci terminalinin ortaya çıkmasıyla birlikte, yatırımcılar nihayet strateji test cihazlarını kullanarak bu tür otomatların çalışmasına ilişkin tam bir analiz yapma fırsatına sahip oldular.

Bu nedenle, şimdi çok para birimli otomatlar her zamankinden daha popüler hale gelecek; dolayısıyla bu tür alım satım sistemlerinin oluşturulmasına ilginin artmasını tahmin edebiliriz. Fakat bu tür robotların uygulanmasındaki ana sorun, program kodundaki boyutlarının en iyi ihtimalle aritmetik bir ilerlemeyle genişlemesi gerçeğidir ve bunun tipik bir programcı tarafından benimsenmesi kolay değildir.

Bu makalede, yapı kusurlarının yok olmasa da en azından minimum düzeye indirildiği basit bir çok para birimli Expert Advisor yazacağız.


1. Basit bir trend takip sistemini uygulama

Aslında, bir Üçlü Üstel Hareketli Ortalama teknik göstergesinin yerleşik bir terminali temelindeki trendi takip ederek, maksimum düzeyde basit bir alım satım sistemi ile başlayabiliriz. Bu, özel herhangi bir yorum gerektirmeyen ve şimdi program kodunda somutlaştıracağımız çok basit bir algoritmadır.

Ancak her şeyden önce, Expert Advisor hakkında en genel çıkarımları yapmak istiyorum. Bu doğrultuda genel düzeyde bildirilen, gelen Expert Advisor parametreleri bloğuyla başlamanın mantıklı olacağını düşünüyorum.

Bu nedenle, öncelikli olarak birlikte çalışacağımız finansal varlıkları seçmeliyiz. Bu, varlık sembollerinin saklanabileceği satır giriş değişkenleri kullanılarak yapılabilir. Şimdi, her bir finansal varlık için, varlık tarafından alım satım işlemlerini devre dışı bırakmaya izin verecek bir trade ban anahtarına sahip olmak güzel olurdu.

Doğal olarak, her varlık, Zararı Durdur, Kar Al, açık pozisyonun hacmi ve kayma gibi bireysel alım satım parametreleriyle ilişkilendirilmelidir. Ve bariz nedenlerden dolayı, her alım satım çipi için Üçlü Üstel Hareketli Ortalama göstergesinin giriş parametreleri ayrı olmalıdır.

Yalnızca bir çip için giriş değişkenlerinin nihai bir bloğu, bu bağımsız değişkenlere uygun olarak gerçekleştirilir. Kalan bloklar yalnızca Expert Advisor'ın giriş parametrelerinin adlarındaki sayılarla farklılık gösterir. Bu örnekte, ideal olarak bu tür blokların sayısı için herhangi bir yazılım sınırlaması olmamasına rağmen, kendimi yalnızca on iki finansal varlıkla sınırladım.

Yalnızca alım satım yapacak bir şeye ihtiyacımız var! Ve en önemlisi bilgisayarımız bu sorunu çözmek için yeterli kaynağa sahip olmalıdır.

input string                Symb0 = "EURUSD";
input  bool                Trade0 = true; 
input int                    Per0 = 15; 
input ENUM_APPLIED_PRICE ApPrice0 = PRICE_CLOSE;
input int                 StLoss0 = 1000;
input int               TkProfit0 = 2000;
input double                Lots0 = 0.1;
input int               Slippage0 = 30;

Artık genel düzeydeki değişkenleri anladığımıza göre, kodun OnTick() işlevi içinde oluşturulması konusuna geçebiliriz. Buradaki en mantıklı seçenek, alım satım sinyallerini almak için algoritmanın ve Expert Advisor'ın gerçek alım satım bölümünün iki özel işleve ayrılması olacaktır.

Ve Expert Advisor aynı anda on iki finansal varlıkla çalıştığı için, OnTick() bloğu içinde bu işlevlerin on iki çağrısı da olmalıdır. 

Doğal olarak, bu işlevlerin ilk giriş parametresi, bu alım satım varlıklarının altında listeleneceği benzersiz bir sayı olmalıdır. Bariz nedenlerden dolayı, ikinci giriş parametresi, alım satım amaçlı finansal varlığın satır adı olacaktır.

Üçüncü parametrenin rolü için, alım satımı işlemini çözmek için mantıksal bir değişken belirleyeceğiz. Ardından, alım satım sinyallerini belirleme algoritması için giriş göstergesi sinyallerini ve alım satım işlevi için bekleyen talimatlara olan mesafeyi, pozisyon hacmini ve kaymayı (açık pozisyon fiyatının izin verilen kayması) takip edeceğiz.

Alım satım sinyallerini bir işlevden diğerine aktarmak için, statik diziler değerlerini bir referans yoluyla türeten işlevin parametreleri olarak ayarlanmalıdır. Bu, OnTick() işlevi için önerilen kodun son sürümüdür.

void OnTick()
  {
//--- declare variables arrays for trade signals 
   static bool UpSignal[12], DnSignal[12], UpStop[12], DnStop[12];
  
//--- get trade signals
   TradeSignalCounter( 0, Symb0,  Trade0,  Per0,  ApPrice0,  UpSignal, DnSignal, UpStop, DnStop);
   TradeSignalCounter( 1, Symb1,  Trade1,  Per1,  ApPrice1,  UpSignal, DnSignal, UpStop, DnStop);
   TradeSignalCounter( 2, Symb2,  Trade2,  Per2,  ApPrice2,  UpSignal, DnSignal, UpStop, DnStop);
   TradeSignalCounter( 3, Symb3,  Trade3,  Per3,  ApPrice3,  UpSignal, DnSignal, UpStop, DnStop);
   TradeSignalCounter( 4, Symb4,  Trade4,  Per4,  ApPrice4,  UpSignal, DnSignal, UpStop, DnStop);
   TradeSignalCounter( 5, Symb5,  Trade5,  Per5,  ApPrice5,  UpSignal, DnSignal, UpStop, DnStop);
   TradeSignalCounter( 6, Symb6,  Trade6,  Per6,  ApPrice6,  UpSignal, DnSignal, UpStop, DnStop);
   TradeSignalCounter( 7, Symb7,  Trade7,  Per7,  ApPrice7,  UpSignal, DnSignal, UpStop, DnStop);
   TradeSignalCounter( 8, Symb8,  Trade8,  Per8,  ApPrice8,  UpSignal, DnSignal, UpStop, DnStop);
   TradeSignalCounter( 9, Symb9,  Trade9,  Per9,  ApPrice9,  UpSignal, DnSignal, UpStop, DnStop);
   TradeSignalCounter(10, Symb10, Trade10, Per10, ApPrice10, UpSignal, DnSignal, UpStop, DnStop);
   TradeSignalCounter(11, Symb11, Trade11, Per11, ApPrice11, UpSignal, DnSignal, UpStop, DnStop);
  
//--- perform trade operations
   TradePerformer( 0, Symb0,  Trade0,  StLoss0,  TkProfit0,  Lots0,  Slippage0,  UpSignal, DnSignal, UpStop, DnStop);
   TradePerformer( 1, Symb1,  Trade1,  StLoss1,  TkProfit1,  Lots1,  Slippage1,  UpSignal, DnSignal, UpStop, DnStop);
   TradePerformer( 2, Symb2,  Trade2,  StLoss2,  TkProfit2,  Lots2,  Slippage2,  UpSignal, DnSignal, UpStop, DnStop);
   TradePerformer( 3, Symb3,  Trade3,  StLoss3,  TkProfit3,  Lots3,  Slippage3,  UpSignal, DnSignal, UpStop, DnStop);
   TradePerformer( 4, Symb4,  Trade4,  StLoss4,  TkProfit4,  Lots4,  Slippage4,  UpSignal, DnSignal, UpStop, DnStop);
   TradePerformer( 5, Symb5,  Trade5,  StLoss5,  TkProfit5,  Lots5,  Slippage5,  UpSignal, DnSignal, UpStop, DnStop);
   TradePerformer( 6, Symb6,  Trade6,  StLoss6,  TkProfit6,  Lots6,  Slippage6,  UpSignal, DnSignal, UpStop, DnStop);
   TradePerformer( 7, Symb7,  Trade7,  StLoss7,  TkProfit7,  Lots7,  Slippage7,  UpSignal, DnSignal, UpStop, DnStop);
   TradePerformer( 8, Symb8,  Trade8,  StLoss8,  TkProfit8,  Lots8,  Slippage8,  UpSignal, DnSignal, UpStop, DnStop);
   TradePerformer( 9, Symb9,  Trade9,  StLoss9,  TkProfit9,  Lots9,  Slippage9,  UpSignal, DnSignal, UpStop, DnStop);
   TradePerformer(10, Symb10, Trade10, StLoss10, TkProfit10, Lots10, Slippage10, UpSignal, DnSignal, UpStop, DnStop);
   TradePerformer(11, Symb11, Trade11, StLoss11, TkProfit11, Lots11, Slippage11, UpSignal, DnSignal, UpStop, DnStop); 
//---
  }

TradeSignalCounter() işlevinin içinde, yalnızca, alım satım sinyallerini hesaplamak için her çipin başlangıcında bir kez ve daha sonra çubuğun her değişiminde Üçlü Üstel Hareketli Ortalama teknik göstergesinin tanıtıcısını elde etmek gerekir.

Koddaki uygulama ile bu nispeten basit şema, küçük ayrıntılarla dolup taşmaya başlar.

bool TradeSignalCounter(int Number,
                        string Symbol_,
                        bool Trade,
                        int period,
                        ENUM_APPLIED_PRICE ApPrice,
                        bool &UpSignal[],
                        bool &DnSignal[],
                        bool &UpStop[],
                        bool &DnStop[])
  {
//--- check if trade is prohibited
   if(!Trade)return(true);

//--- declare variable to store final size of variables arrays
   static int Size_=0;

//--- declare array to store handles of indicators as static variable
   static int Handle[];

   static int Recount[],MinBars[];
   double TEMA[4],dtema1,dtema2;

//--- initialization
   if(Number+1>Size_) // Entering the initialization block only on first start
     {
      Size_=Number+1; // For this number entering the block is prohibited

      //--- change size of variables arrays
      ArrayResize(Handle,Size_);
      ArrayResize(Recount,Size_);
      ArrayResize(MinBars,Size_);

      //--- determine minimum number of bars, sufficient for calculation 
      MinBars[Number]=3*period;

      //--- setting array elements to 0
      DnSignal[Number] = false;
      UpSignal[Number] = false;
      DnStop  [Number] = false;
      UpStop  [Number] = false;

      //--- use array as timeseries
      ArraySetAsSeries(TEMA,true);

      //--- get indicator's handle
      Handle[Number]=iTEMA(Symbol_,0,period,0,ApPrice);
     }

//--- check if number of bars is sufficient for calculation 
   if(Bars(Symbol_,0)<MinBars[Number])return(true);
//--- get trade signals 
   if(IsNewBar(Number,Symbol_,0) || Recount[Number]) // Entering the block on bar change or on failed copying of data
     {
      DnSignal[Number] = false;
      UpSignal[Number] = false;
      DnStop  [Number] = false;
      UpStop  [Number] = false;

      //--- using indicator's handles, copy values of indicator's
      //--- buffers into static array, specially prepared for this purpose
      if(CopyBuffer(Handle[Number],0,0,4,TEMA)<0)
        {
         Recount[Number]=true; // As data were not received, we should return 
                               // into this block (where trade signals are received) on next tick!
         return(false);        // Exiting the TradeSignalCounter() function without receiving trade signals
        }

      //--- all copy operations from indicator buffer are successfully completed
      Recount[Number]=false; // We may not return to this block until next change of bar

      int Digits_ = int(SymbolInfoInteger(Symbol_,SYMBOL_DIGITS)+4);
      dtema2 = NormalizeDouble(TEMA[2] - TEMA[3], Digits_);
      dtema1 = NormalizeDouble(TEMA[1] - TEMA[2], Digits_);

      //---- determining the input signals
      if(dtema2 > 0 && dtema1 < 0) DnSignal[Number] = true;
      if(dtema2 < 0 && dtema1 > 0) UpSignal[Number] = true;

      //---- determining the output signals
      if(dtema1 > 0) DnStop[Number] = true;
      if(dtema1 < 0) UpStop[Number] = true;
     }
//----+
   return(true);
  }

Bu açıdan, TradePerformer() işlevinin kodunun oldukça basit olduğu ortaya çıkıyor:

bool TradePerformer(int    Number,
                    string Symbol_,
                    bool   Trade,
                    int    StLoss,
                    int    TkProfit,
                    double Lots,
                    int    Slippage,
                    bool  &UpSignal[],
                    bool  &DnSignal[],
                    bool  &UpStop[],
                    bool  &DnStop[])
  {
//--- check if trade is prohibited
   if(!Trade)return(true);

//--- close opened positions 
   if(UpStop[Number])BuyPositionClose(Symbol_,Slippage);
   if(DnStop[Number])SellPositionClose(Symbol_,Slippage);

//--- open new positions
   if(UpSignal[Number])
      if(BuyPositionOpen(Symbol_,Slippage,Lots,StLoss,TkProfit))
         UpSignal[Number]=false; //This trade signal will be no more on this bar!
//---
   if(DnSignal[Number])
      if(SellPositionOpen(Symbol_,Slippage,Lots,StLoss,TkProfit))
         DnSignal[Number]=false; //This trade signal will be no more on this bar!
//---
   return(true);
  }
Ancak bunun tek nedeni, alım satım işlemlerinin gerçekleştirilmesi için gerçek komutların dört ek işlevde toplanmış olmasıdır:
BuyPositionClose();
SellPositionClose();
BuyPositionOpen();
SellPositionOpen();

Dört işlevin tümü tamamen benzer şekilde çalışır; bu nedenle kendimizi bunlardan yalnızca birinin incelenmesiyle sınırlayabiliriz:

bool BuyPositionClose(const string symbol,ulong deviation)
  {
//--- declare structures of trade request and result of trade request
   MqlTradeRequest request;
   MqlTradeResult result;
   ZeroMemory(request);
   ZeroMemory(result);

//--- check if there is BUY position
   if(PositionSelect(symbol))
     {
      if(PositionGetInteger(POSITION_TYPE)!=POSITION_TYPE_BUY) return(false);
     }
   else  return(false);

//--- initializing structure of the MqlTradeRequest to close BUY position
   request.type   = ORDER_TYPE_SELL;
   request.price  = SymbolInfoDouble(symbol, SYMBOL_BID);
   request.action = TRADE_ACTION_DEAL;
   request.symbol = symbol;
   request.volume = PositionGetDouble(POSITION_VOLUME);
   request.sl = 0.0;
   request.tp = 0.0;
   request.deviation=(deviation==ULONG_MAX) ? deviation : deviation;
   request.type_filling=ORDER_FILLING_FOK;
//---
   string word="";
   StringConcatenate(word,
                     "<<< ============ BuyPositionClose():   Close Buy position at ",
                     symbol," ============ >>>");
   Print(word);

//--- send order to close position to trade server
   if(!OrderSend(request,result))
     {
      Print(ResultRetcodeDescription(result.retcode));
      return(false);
     }
//----+
   return(true);
  }

Temel olarak, bu hemen hemen tüm çok para birimli Expert Advisor'lardır (Exp_TEMA.mq5)!

Göz önünde bulundurulan işlevlerin yanı sıra, bu, iki ek kullanıcı işlevi içerir:

bool IsNewBar(int Number, string symbol, ENUM_TIMEFRAMES timeframe);
string ResultRetcodeDescription(int retcode);

Bu işlevlerden ilki, seçilen sembol ve zaman dilimine göre çubuk değişikliği anında true değerini döndürür ve ikincisi, alım satım talebi yapısının alan retcode'undan türetilen alım satım işleminin sonuç koduyla satırı döndürür MqlTradeResult

Expert Advisor hazır, şimdi teste başlama zamanı! Çok para birimli Expert Advisor testinde, diğer tek para birimli Expert Advisor'ından gözle görülür ciddi bir fark yoktur.

Strateji Test Cihazının "Parametreler" sekmesindeki yapılandırmaları belirleyin:

Şekil 1. Strateji test cihazının "Ayarlar" sekmesi

Şekil 1. Strateji test cihazının "Ayarlar" sekmesi

Gerekirse, "Giriş parametreleri" sekmesindeki giriş parametrelerinin değerlerini ayarlayın:

Şekil 2. Strateji test cihazının "Parametreler" sekmesi

Şekil 2. Strateji test cihazının "Parametreler" sekmesi

ve ardından "Ayarlar" sekmesindeki Strateji Test Cihazında "Başlat" düğmesine tıklayın:

Şekil 3. Expert Advisor testini çalıştırma

Şekil 3. Expert Advisor testini çalıştırma

Expert Advisor'ın ilk testinin geçme süresinin, on iki sembolün tümü için geçmişin yüklenmesi nedeniyle çok önemli olduğu ortaya çıkıyor. Strateji test cihazında testi tamamladıktan sonra "Sonuçlar" sekmesini açın:

Şekil 4. Test sonuçları

Şekil 4. Test sonuçları

ve "Grafik" sekmesinin içeriğini kullanarak verilerin bir analizini yapın:

Şekil 5. Denge dinamikleri ve hisse senedi tablosu

Şekil 5. Denge dinamikleri ve hisse senedi tablosu

ve "Günlük":

Şekil 6. Strateji test cihazı Günlüğü

Şekil 6. Strateji test cihazı Günlüğü

Doğal olarak, algoritmanın bu Expert Advisor piyasasına giriş ve çıkışlarının özü çok basittir ve ilk rastgele parametreleri kullanırken çok anlamlı sonuçlar beklemek saflık olur. Ancak buradaki amacımız, çok para birimli bir Expert Advisor oluşturmanın temel fikrini mümkün olan en basit şekilde göstermektir.

Bu Expert Advisor'ın optimizasyonu ile çok fazla giriş parametresi nedeniyle bazı aksaklıklar ortaya çıkabilir. Optimizasyonun genetik algoritması, bu parametrelerin çok daha küçük bir miktarını gerektirir; bu nedenle Expert Advisor, TradeN giriş parametrelerinin kalan çipleri devre dışı bırakılarak her bir çip üzerinde ayrı ayrı optimize edilmelidir.

Yaklaşımın özü özetlendiğinde, çok para birimli robot için daha ilginç karar verme algoritmasıyla çalışmaya başlayabilirsiniz.


2. Finansal piyasalardaki rezonanslar ve alım satım sistemlerindeki uygulamaları

Genel olarak, farklı finansal varlıklar arasındaki korelasyonları göz önünde bulundurma fikri yeni değildir ve tam olarak bu tür trendlerin analizine dayanan algoritmayı uygulamak ilginç olacaktır. Bu makalede, "Döviz Spekülatörü" (Rusça) 04, 05, 2001 dergisinde yayınlanan Vasily Yakimkin "Rezonanslar - Yeni Bir Teknik Göstergeler Sınıfı" makalesine dayanan çok para birimli bir otomat uygulayacağım.

Özetle bu yaklaşımın özü aşağıdaki gibidir. Örneğin, EUR / USD üzerinde araştırma yapmak için, yalnızca finansal varlığa ilişkin bazı göstergelerin sonuçlarını değil, aynı zamanda EUR/USD varlıkları - EUR/JPY ve USD/JPY ile ilgili aynı göstergenin sonuçlarını da kullanırız. Ölçümlerin ve hesaplamaların basitliği ve kolaylığı için değerleri aynı değişiklik aralığında normalize edilmiş göstergeyi kullanmak en iyisidir.

Bu gereksinimler göz önünde bulundurulduğunda, bu klasik için tamı tamına uyan stokastik göstergedir. Her ne kadar gerçekte, diğer göstergelerin kullanımında herhangi bir fark olmasa da. Trend yönü olarak, stokastik Stoka değeri ile İşaret sinyal çizgisi arasındaki fark işaretini dikkate alacağız.

Şekil 7. Trend yönünü belirleme

Şekil 7. Trend yönünü belirleme

dStoh değişken sembolü için, mevcut trendin yönü için olası kombinasyonların ve yorumlarının tam bir tablosu vardır:

Şekil 8. dStoh değişken sembolü ve trend yönü kombinasyonları

Şekil 8. dStoh değişken sembolü ve trend yönü kombinasyonları

EUR / JPY ve USD / JPY varlıklarının iki sinyalinin zıt değerlere sahip olduğu bir durumda, toplamlarını belirlemeliyiz; bu toplam sıfırdan büyükse her iki sinyali de pozitif, aksi takdirde negatif olarak kabul edin.

Bu nedenle, Uzun Pozisyonları açmak için, trendin büyüdüğü durumu kullanın ve çıkış yapmak için düşüş trendi veya ana varlık EUR / USD göstergesinin sinyallerinin negatif olduğu bir trend kullanın. Ayrıca, ana varlıkta sinyal yoksa ve kalan varlıklar için dStoh değişkeninin toplamı sıfırdan küçükse uzun pozisyondan çıkın. Kısa pozisyonlar için her şey kesinlikle benzerdir yalnızca durum tam tersidir.

En rasyonel çözüm, Expert Advisor'ın tüm analitik kısmını çoklu para birimi göstergesine yerleştirmek ve gösterge arabelleklerinden Expert Advisor için yalnızca alım satım kontrolü için hazır sinyalleri almak olacaktır. Bu gösterge türünün sürümü, piyasa koşullarının görsel bir analizini sağlayan MultiStochastic.mq5 göstergesi tarafından sunulur.

Şekil 9. Çoklu Stokastik Gösterge

Şekil 9. Çoklu Stokastik Gösterge

Yeşil çubuk, sırasıyla uzun pozisyonların ve kırmızı çubuklar kısa pozisyonların açılmasını ve tutulmasını işaret eder. Grafiğin üst kenarındaki pembe ve açık yeşil noktalar, uzun ve kısa pozisyonlardan çıkan sinyalleri temsil etmektedir.

Bu gösterge, Expert Advisor'da doğrudan sinyal almak için kullanılabilir fakat yine de işini kolaylaştırmak ve tüm gereksiz arabellekleri ve görselleştirme öğelerini kaldırmak daha iyi olacaktır; bu şekilde yalnızca alım satım sinyallerinin sağlanmasında doğrudan ilgili olanlar kalır. MultiStochastic_Exp.mq5 göstergesinde yapılan tam olarak budur.

Bu Expert Advisor'da yalnızca üç çip ile alım satım işlemi yaptım; bu nedenle OnTick() işlevinin kodu son derece basit hale geldi:

void OnTick()
  {
//--- declare variables arrays for trade signals
  static bool UpSignal[], DnSignal[], UpStop[], DnStop[];
  
//--- get trade signals
  TradeSignalCounter(0, Trade0, Kperiod0, Dperiod0, slowing0, ma_method0, price_0, SymbolA0, SymbolB0, SymbolC0, UpSignal, DnSignal, UpStop, DnStop);
  TradeSignalCounter(1, Trade1, Kperiod1, Dperiod1, slowing1, ma_method1, price_1, SymbolA1, SymbolB1, SymbolC1, UpSignal, DnSignal, UpStop, DnStop);
  TradeSignalCounter(2, Trade2, Kperiod2, Dperiod2, slowing2, ma_method2, price_2, SymbolA2, SymbolB2, SymbolC2, UpSignal, DnSignal, UpStop, DnStop);
                             
//--- perform trade operations
   TradePerformer( 0, SymbolA0,  Trade0,  StopLoss0,  0,  Lots0,  Slippage0,  UpSignal, DnSignal, UpStop, DnStop);
   TradePerformer( 1, SymbolA1,  Trade1,  StopLoss1,  0,  Lots1,  Slippage1,  UpSignal, DnSignal, UpStop, DnStop);
   TradePerformer( 2, SymbolA2,  Trade2,  StopLoss2,  0,  Lots2,  Slippage2,  UpSignal, DnSignal, UpStop, DnStop);
//---
  }

Ancak, TradeSignalCounter() işlevinin kodu biraz daha karmaşıktır: Gerçek şu ki, çok para birimli gösterge, farklı finansal varlıkların üç zaman serisiyle doğrudan çalışır; bu nedenle, Rates_Total() işlevini kullanarak üç zaman serisinden birinde minimum sayıda yeterlilikleri için çubukların daha güç algılanan bir doğrulamasını uyguluyoruz.

Ayrıca, tüm zaman serilerinde aynı anda bir çubuk değişikliğinin meydana geldiği anın belirlenmesinin doğruluğunu garanti etmek için SynchroCheck() işlevi kullanılarak zaman serilerinin senkronizasyonuna ilişkin ek bir doğrulama yapılır.

bool TradeSignalCounter(int Number,
                        bool Trade,
                        int Kperiod,
                        int Dperiod,
                        int slowing,
                        ENUM_MA_METHOD ma_method,
                        ENUM_STO_PRICE price_,
                        string SymbolA,
                        string SymbolB,
                        string SymbolC,
                        bool &UpSignal[],
                        bool &DnSignal[],
                        bool &UpStop[],
                        bool &DnStop[])
  {
//--- check if trade is prohibited
   if(!Trade)return(true);
//--- declare variable to store sizes of variables arrays
   static int Size_=0;
//--- declare arrays to store handles of indicators as static variables
   static int Handle[];
   static int Recount[],MinBars[];
//---
   double dUpSignal_[1],dDnSignal_[1],dUpStop_[1],dDnStop_[1];
//--- change size of variables arrays
   if(Number+1>Size_)
     {
      uint size=Number+1;
      //----
      if(ArrayResize(Handle,size)==-1
         || ArrayResize(Recount,size)==-1
         || ArrayResize(UpSignal, size) == -1
         || ArrayResize(DnSignal, size) == -1
         || ArrayResize(UpStop, size) == -1
         || ArrayResize(DnStop, size) == -1
         || ArrayResize(MinBars,size) == -1)
        {
         string word="";
         StringConcatenate(word,"TradeSignalCounter( ",Number,
                           " ): Error!!! Unable to change sizes of variables arrays!!!");
         int error=GetLastError();
         ResetLastError();
         //---
         if(error>4000)
           {
            StringConcatenate(word,"TradeSignalCounter( ",Number," ): Error code ",error);
            Print(word);
           }
         Size_=-2;
         return(false);
        }

      Size_=int(size);
      Recount[Number] = false;
      MinBars[Number] = Kperiod + Dperiod + slowing;

      //--- get indicator's handle
      Handle[Number]=iCustom(SymbolA,0,"MultiStochastic_Exp",
                             Kperiod,Dperiod,slowing,ma_method,price_,
                             SymbolA,SymbolB,SymbolC);
     }
//--- check if number of bars is sufficient for calculation 
   if(Rates_Total(SymbolA,SymbolB,SymbolC)<MinBars[Number])return(true);
//--- check timeseries synchronization
   if(!SynchroCheck(SymbolA,SymbolB,SymbolC))return(true);
//--- get trade signals 
   if(IsNewBar(Number,SymbolA,0) || Recount[Number])
     {
      DnSignal[Number] = false;
      UpSignal[Number] = false;
      DnStop  [Number] = false;
      UpStop  [Number] = false;

      //--- using indicators' handles, copy values of indicator's 
      //--- buffers into static arrays, specially prepared for this purpose
      if(CopyBuffer(Handle[Number], 1, 1, 1, dDnSignal_) < 0){Recount[Number] = true; return(false);}
      if(CopyBuffer(Handle[Number], 2, 1, 1, dUpSignal_) < 0){Recount[Number] = true; return(false);}
      if(CopyBuffer(Handle[Number], 3, 1, 1, dDnStop_  ) < 0){Recount[Number] = true; return(false);}
      if(CopyBuffer(Handle[Number], 4, 1, 1, dUpStop_  ) < 0){Recount[Number] = true; return(false);}

      //--- convert obtained values into values of logic variables of trade commands
      if(dDnSignal_[0] == 300)DnSignal[Number] = true;
      if(dUpSignal_[0] == 300)UpSignal[Number] = true;
      if(dDnStop_  [0] == 300)DnStop  [Number] = true;
      if(dUpStop_  [0] == 300)UpStop  [Number] = true;

      //--- all copy operations from indicator's buffers completed successfully
      //--- unnecessary to return into this block until next bar change
      Recount[Number]=false;
     }
//----+
   return(true);
  }

Bu Expert Advisor'ın (Exp_ResonanceHunter.mq5) kodunda başka hiçbir radikal ideolojik farklılık yoktur; zira aynı işlevsel bileşenler temelinde derlenmiştir. Bu nedenle iç yapısına daha fazla zaman ayırmanın gerekli olmadığını düşünüyorum.


Sonuç

Bana göre, MQL5'teki çok para birimli Expert Advisor kodu kesinlikle normal bir Expert Advisor koduna benzerdir.


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

Ekli dosyalar |
multistochastic.mq5 (17.47 KB)
exp_tema.mq5 (25.17 KB)
MQL5'te Hareketli Ortalamalar Hesaplamasının Test Performansı MQL5'te Hareketli Ortalamalar Hesaplamasının Test Performansı
İlk Hareketli Ortalama göstergesinin oluşturulmasından bu yana bir dizi gösterge ortaya çıktı. Birçoğu benzer yumuşatma yöntemlerini kullanır fakat farklı hareketli ortalama algoritmalarının performansları incelenmemiştir. Bu makalede, MQL5'te Hareketli Ortalamaları kullanmanın olası yollarını ele alacak ve performanslarını karşılaştıracağız.
Mum Grafik Formasyonlarını Analiz Etme Mum Grafik Formasyonlarını Analiz Etme
Japon mum grafiğinin oluşturulması ve mum grafik formasyonlarının analizi, teknik analizin muhteşem bir alanını teşkil eder. Mum grafiklerin avantajı, verileri, verilerin içindeki dinamikleri takip edebileceğiniz şekilde temsil etmeleridir. Bu makalede mum grafik türlerini, mum grafik formasyonlarının sınıflandırılmasını analiz edecek ve mum grafik formasyonlarını belirleyebilecek bir gösterge sunacağız.
Göstergelerin Ekonomik Hesaplanmasına İlişkin Prensipler Göstergelerin Ekonomik Hesaplanmasına İlişkin Prensipler
Kullanıcı çağrıları ve teknik göstergeler, otomatik alım satım sistemlerinin program kodunda çok az yer kaplar. Bu, genellikle yalnızca birkaç kod satırıdır. Ancak bu, çoğu zaman, Expert Advisor'ı test etmek için harcanması gereken zamanın en büyük kısmını kullanan bu birkaç kod satırı olur. Bu nedenle, bir gösterge içindeki veri hesaplamalarıyla ilgili her şeyin, ilk bakışta göründüğünden çok daha kapsamlı bir şekilde düşünülmesi gerekir. Bu makalede tam olarak bu ele alınacaktır.
Delphi'de MQL5 için DLL yazma kılavuzu Delphi'de MQL5 için DLL yazma kılavuzu
Makalede, Delphi programlama ortamında popüler ObjectPascal programlama dili kullanılarak bir DLL modülü oluşturma mekanizması incelenmektedir. Bu makalede sağlanan materyallerin, öncelikli olarak, dış DLL modüllerini bağlayarak MQL5'in gömülü programlama dilinin sınırlarını aşan problemleri çözmeye çalışan yeni başlayan programcıları hedeflemesi amaçlanmıştır.