English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
MQL5'te Gelişmiş Uyarlanabilir Göstergeler Teorisi ve Uygulaması

MQL5'te Gelişmiş Uyarlanabilir Göstergeler Teorisi ve Uygulaması

MetaTrader 5Örnekler | 16 Aralık 2021, 15:54
197 0
investeo
investeo

Tanıtım

Bu makale, John F. Ehlers'in iki mükemmel kitabına dayanmaktadır: "Satıcılar için Roket Bilimi" ve "Hisse Senedi ve Vadeli İşlemler için Sibernetik Analiz". Dijital sinyal işleme yöntemlerini kullanan ve piyasa döngüsü tanıma için karmaşık sayıları benimseyen alışılmışın dışında bir piyasa analizi yaklaşımı, bu konuyu daha da derinleştirmemi ve ardından J.F.Ehlers tarafından sunulan üç uyarlanabilir göstergeyi MQL5'te uygulamamı sağladı.

Bu makale, uyarlanabilir göstergelerin arkasındaki temel teoriyi ve bunların MQL5 uygulamasını açıklayacaktır. Uyarlanabilir göstergeler, uyarlanabilir olmayan emsalleriyle karşılaştırılacaktır.


Piyasa döngülerini ölçmek için karmaşık sayılar ve fazörler

Karmaşık sayılar teorisi kavramı, mühendislik geçmişi olmayan okuyucular için oldukça kafa karıştırıcı olabilir, bu nedenle wiki’de teoriyi araştırmanızı ve bu makaleyi okumadan önce karmaşık sayılarla ilgili işlemlerle ilgili eğiticiyi izlemenizi öneririm. 

Fazör

Fazör veya Faz Vektörü, bir döngünün genliğini ve fazını gösteren bir vektördür. Euler formülüne göre bir sinüs dalgası iki karmaşık sayı bileşeninin toplamı olarak gösterilebilir. Lütfen aşağıda bir sinüs dalgası döngüsünü gösteren dönen fazörü gözlemleyin.

Fazör  


Bu animasyonu ilk kez gördüğünüzde, bir döngüyle fazör ilişkisini doğru bir şekilde nasıl okuyacağınız konusunda kafanız karışmış olabilir. Bunu anlamak için bir döngüyü animasyonun sol tarafında görünen normal bir dalga formu olarak değil, sağda dönen fazör olarak tanıyacak şekilde fikrinizi değiştirmeniz gerekir.

İlk başta bunu hayal etmek zor olabilir, ama bunu şu şekilde düşünmenin bir yolunu buldum: Bir fazörün tam dönüşü 360 derece veya radyandır, aynısı tam bir döngü içindir. Bir fazörün mevcut açısı, döngünün (fazın) hangi kısmında bulunduğumuzu gösterir. Y ekseni, belirli bir fazdaki bir döngünün genliğini temsil eder.

Fazör iki bileşene ayrılabilir: InPhase bileşeni (kosinüs) ve Dörtlü bileşen (sinüs). Bu bileşenlerin türetilmesiyle ilgili ayrıntılı açıklama, "Rocket Science for Traders" kitabının Bölüm 6 "Hilbert Transforms" bölümünde bulunabilir. İlgilenen varsa, lütfen bu bölümü dikkatlice takip etsin.

Şimdilik, uyarlanabilir gösterge hesaplaması için analitik sinyali (dalga biçimi) iki bileşenden oluşan karmaşık bir sinyale dönüştürmemiz gerektiği gerçeğine odaklanmanız yeterlidir. Bunu nasıl başaracağız? Hilbert Dönüşümünden bahsettim mi? Evet, kesinlikle. Hilbert Dönüşümü tam da bunu yapabilir.


Ölçüm döngüsü süresi

Hilbert Dönüşümü tüccarlar için pratik hale getirmek için John Ehlers, kitabında Hilbert Dönüşümü serisini dört elemente indirdi.

Dörtlü bileşen denklemi:

Dörtlü bileşen denklem 

ve InPhase bileşeninin denklemi üç çubuk gecikmeli fiyattır:

InPhase bileşen denklemi 

InPhase ve Quadrature bileşenlerini hesaplayarak, mevcut çubuk için ölçülen faz açısından ve bir çubuk önce ölçülen faz açısından diferansiyel faz hesaplamasını türetmek mümkündür. Mevcut çubuğun fazı, Mevcut çubuğun fazıdır ve önceki çubuğun fazı Arctan önceki çubuğudur. Trigonometrik özdeşliği kullanma:

Arctan deltafaz 

DeltaPhase olarak adlandırılan diferansiyel faz denklemini elde ederiz.

Bay Ehlers, DeltaPhase değişkenine ek kısıtlamalar koydu: sonuç negatif olamaz ve DeltaPhase <0,1, 1,1> radyanla sınırlıdır (6 ile 63 bar arasında bir döngü anlamına gelir). Gerçek veriler üzerinde ölçülen DeltaPhase'de bozulmalar olduğu ortaya çıktı, bu nedenle düzeltilmesi gerekiyor.

Dikenli veriler üzerinde en iyi yumuşatma yöntemi medyan filtresidir, bu nedenle beş DeltaPhase örneğinin medyanı MedianDelta değişkenini oluşturur. MedianDelta bölü , aradığımız piyasa döngüsü olan Dominant Döngüyü hesaplamak için kullanılır.

Geliştirme testleri sırasında, ölçümde kaldırılması gereken yaklaşık 0,5'lik bir sapma olduğu ortaya çıktı ve bu sapmayı ortadan kaldırmak için tazminat terimi eklendi. Son olarak, Baskın Döngü, sırasıyla 0,33 ve 0,15'e eşit alfa değerleriyle EMA tarafından iki kez düzleştirilir. Döngü süresi kademeli olarak 6'dan 40'a yükselen bir sinüs dalgasına uygulanan algoritmanın sağlamlığını görmek için gerçekten kitabı okumanızı tavsiye ederim.

Teorik bilgi ile donatılmış olduğunuz için MQL5'te CyclePeriod göstergesini uygulamaya hazırız.


Döngü Periyodu göstergesi

Gösterge iki satırdan oluşur: döngü süresini gösteren döngü çizgisi ve temel olarak bir çubuk gecikmeli döngü çizgisi olan bir tetikleme çizgisi. "Çevrim periyodu ölçümü" bölümündeki açıklamayı ve OnCalculate() fonksiyonundaki kaynak kodu takip ederseniz, çevrim periyodu ölçümünden hangi hatların sorumlu olduğunu kolayca ilişkilendirebilirsiniz.

//+------------------------------------------------------------------+
//|                                                  CyclePeriod.mq5 |
//|                                      Copyright 2011, Investeo.pl |
//|                                               http://Investeo.pl |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, Investeo.pl"
#property link      "http://Investeo.pl"
#property version   "1.00"
#property indicator_separate_window

#property description "CyclePeriod indicator - described by John F. Ehlers"
#property description "in \"Cybernetic Analysis for Stocks and Futures\""

#property indicator_buffers 2
#property indicator_plots 2
#property indicator_width1 1
#property indicator_width2 1
#property indicator_type1   DRAW_LINE
#property indicator_type2   DRAW_LINE
#property indicator_color1  Green
#property indicator_color2  Red
#property indicator_label1  "Cycle"
#property indicator_label2  "Trigger Line"

#define Price(i) ((high[i]+low[i])/2.0)

double Smooth[];
double Cycle[];
double Trigger[];
//double Price[];
double Q1[]; // Quadrature component
double I1[]; // InPhase component
double DeltaPhase[];
double InstPeriod[];
double CyclePeriod[];


input double InpAlpha=0.07; // alpha
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping 
   ArraySetAsSeries(Cycle,true);
   ArraySetAsSeries(CyclePeriod,true);
   ArraySetAsSeries(Trigger,true); 
   ArraySetAsSeries(Smooth,true);
   //ArraySetAsSeries(Price,true);
   
   SetIndexBuffer(0,CyclePeriod,INDICATOR_DATA);
   SetIndexBuffer(1,Trigger,INDICATOR_DATA);
   
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0);

   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---   
   long tickCnt[1];
   int i;
   int ticks=CopyTickVolume(Symbol(), 0, 0, 1, tickCnt);
   if(ticks!=1) return(rates_total);
   double DC, MedianDelta;

   Comment(tickCnt[0]);

   if(prev_calculated==0 || tickCnt[0]==1)
     {
      //--- last counted bar will be recounted
      int nLimit=rates_total-prev_calculated-1; // start index for calculations

      ArraySetAsSeries(high,true);
      ArraySetAsSeries(low,true);
      
      ArrayResize(Smooth,Bars(_Symbol,_Period));
      ArrayResize(Cycle,Bars(_Symbol,_Period));
      //ArrayResize(Price,Bars(_Symbol,_Period));
      ArrayResize(CyclePeriod,Bars(_Symbol,_Period));
      ArrayResize(InstPeriod,Bars(_Symbol,_Period));
      ArrayResize(Q1,Bars(_Symbol,_Period));
      ArrayResize(I1,Bars(_Symbol,_Period));
      ArrayResize(DeltaPhase,Bars(_Symbol,_Period));
      
      if (nLimit>rates_total-7) // adjust for last bars
         nLimit=rates_total-7;   
      
      for(i=nLimit;i>=0 && !IsStopped();i--)   
      {
         Smooth[i] = (Price(i)+2*Price(i+1)+2*Price(i+2)+Price(i+3))/6.0;
   
         if (i<rates_total-7)
         {
            Cycle[i] = (1.0-0.5*InpAlpha) * (1.0-0.5*InpAlpha) * (Smooth[i]-2.0*Smooth[i+1]+Smooth[i+2])
                      +2.0*(1.0-InpAlpha)*Cycle[i+1]-(1.0-InpAlpha)*(1.0-InpAlpha)*Cycle[i+2];
                   
         } else         
         {
            Cycle[i]=(Price(i)-2.0*Price(i+1)+Price(i+2))/4.0;
         }
         
         Q1[i] = (0.0962*Cycle[i]+0.5769*Cycle[i+2]-0.5769*Cycle[i+4]-0.0962*Cycle[i+6])*(0.5+0.08*InstPeriod[i+1]);
         I1[i] = Cycle[i+3];
         
         if (Q1[i]!=0.0 && Q1[i+1]!=0.0) 
            DeltaPhase[i] = (I1[i]/Q1[i]-I1[i+1]/Q1[i+1])/(1.0+I1[i]*I1[i+1]/(Q1[i]*Q1[i+1]));
         if (DeltaPhase[i] < 0.1)
            DeltaPhase[i] = 0.1;
         if (DeltaPhase[i] > 0.9)
            DeltaPhase[i] = 0.9;
        
         MedianDelta = Median(DeltaPhase, i, 5);
         
         if (MedianDelta == 0.0)
            DC = 15.0;
         else
            DC = (6.28318/MedianDelta) + 0.5;
        
         InstPeriod[i] = 0.33 * DC + 0.67 * InstPeriod[i+1];
         CyclePeriod[i] = 0.15 * InstPeriod[i] + 0.85 * CyclePeriod[i+1];
         Trigger[i] = CyclePeriod[i+1];
      }
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

double Median(double& arr[], int idx, int m_len)
{
   double MedianArr[];
   int copied;
   double result = 0.0;
   
   ArraySetAsSeries(MedianArr, true);
   ArrayResize(MedianArr, m_len);
   
   copied = ArrayCopy(MedianArr, arr, 0, idx, m_len);
   if (copied == m_len)
   {
      ArraySort(MedianArr);
      if (m_len %2 == 0) 
            result = (MedianArr[m_len/2] + MedianArr[(m_len/2)+1])/2.0;
      else
            result = MedianArr[m_len / 2];
      
   }
   else Print(__FILE__+__FUNCTION__+"median error - wrong number of elements copied."); 
   return result; 
}

Herhangi bir çizelgeye ekleyerek test edebiliriz - herhangi bir güvenlik ve herhangi bir zaman dilimi için çalışacaktır.

Lütfen aşağıdaki ekran görüntüsüne bakın.

CyclePeriod göstergesi 

Çalışma alanımızdaki bu gösterge ile, piyasanın mevcut bir döngü dönemine uyum sağlayan göstergeler olan yeni bir tür uyarlanabilir göstergeler uygulayabiliyoruz.


Siber Döngü göstergesi

Siber Döngü göstergesi, http://www.amazon.com/Cybernetic-Analysis-Stocks-Futures-Cutting-Edge/dp/0471463078 adresinden alınan yüksek geçişli bir filtredir. Bu filtre, zaman serilerinden yalnızca çevrim modu bileşenini bırakır.

Ek olarak iki çubuklu ve üç çubuklu döngü bileşenleri, sonuçtan bir sonlu dürtü yanıtı düşük geçiş filtresiyle yumuşatılarak çıkarılır.

Kitapta anlatılan EFL (Ticaret) dilinden uyarlanmış makaledeki gösterge MQL5 kodu ve diğer göstergeler. 

//+------------------------------------------------------------------+
//|                                                   CyberCycle.mq5 |
//|                                      Copyright 2011, Investeo.pl |
//|                                               http://Investeo.pl |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, Investeo.pl"
#property link      "http://Investeo.pl"
#property version   "1.00"
#property indicator_separate_window

#property description "CyberCycle indicator - described by John F. Ehlers"
#property description "in \"Cybernetic Analysis for Stocks and Futures\""
#property description "This indicator is available for free download."

#property indicator_buffers 2
#property indicator_plots 2
#property indicator_width1 1
#property indicator_width2 1
#property indicator_type1   DRAW_LINE
#property indicator_type2   DRAW_LINE
#property indicator_color1  Green
#property indicator_color2  Red
#property indicator_label1  "Cycle"
#property indicator_label2  "Trigger Line"

#define Price(i) ((high[i]+low[i])/2.0)

double Smooth[];
double Cycle[];
double Trigger[];

input double InpAlpha=0.07; // alpha
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping 
   ArraySetAsSeries(Cycle,true);
   ArraySetAsSeries(Trigger,true);
   ArraySetAsSeries(Smooth,true);

   SetIndexBuffer(0,Cycle,INDICATOR_DATA);
   SetIndexBuffer(1,Trigger,INDICATOR_DATA);

   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0);

   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---   
   long tickCnt[1];
   int i;
   int ticks=CopyTickVolume(Symbol(), 0, 0, 1, tickCnt);
   if(ticks!=1) return(rates_total);

   Comment(tickCnt[0]);

   if(prev_calculated==0 || tickCnt[0]==1)
     {
      //--- last counted bar will be recounted
      int nLimit=rates_total-prev_calculated-1; // start index for calculations

      ArraySetAsSeries(high,true);
      ArraySetAsSeries(low,true);

      ArrayResize(Smooth,Bars(_Symbol,_Period));
      ArrayResize(Cycle,Bars(_Symbol,_Period));
      
      if(nLimit>rates_total-4) // adjust for last bars
         nLimit=rates_total-4;

      for(i=nLimit;i>=0 && !IsStopped();i--)
        {
         Smooth[i]=(Price(i)+2*Price(i+1)+2*Price(i+2)+Price(i+3))/6.0;

         if(i<rates_total-5)
           {
            Cycle[i]=(1.0-0.5*InpAlpha) *(1.0-0.5*InpAlpha) *(Smooth[i]-2.0*Smooth[i+1]+Smooth[i+2])
                     +2.0*(1.0-InpAlpha)*Cycle[i+1]-(1.0-InpAlpha)*(1.0-InpAlpha)*Cycle[i+2];
           }
         else
           {
            Cycle[i]=(Price(i)-2.0*Price(i+1)+Price(i+2))/4.0;
           }

         //Print(__FILE__+__FUNCTION__+" received values: ",rCnt);
         Trigger[i]=Cycle[i+1];
        }
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

Göstergenin bir ekran görüntüsü aşağıya yapıştırılmıştır.

Fark edebileceğiniz gibi, bu makaledeki tüm göstergeler benzer bir görünüme sahip olacak, ancak çok farklı algoritmalar uyguluyorlar.

CyberCycle göstergesi 

Bu gösterge için orijinal ticaret yöntemi basittir: döngü çizgisi tetikleme çizgisinin üzerine çıktığında satın alın. Döngü çizgisi tetik çizgisinin altından geçtiğinde sat. Bu göstergeyi kullanarak kendi stratejinizi ve bir ticaret sinyalleri modülünü uygulamak isteyebilirsiniz ve teşvik edilirsiniz.


Uyarlanabilir Siber Döngü göstergesi

Bu makalenin özü, göstergeleri nasıl uyarlanabilir hale getirebiliriz, yani statik bir ayar yerine dinamik çevrim periyodu girdileri ile nasıl hesaplayabiliriz. Bunu başarmak için, mevcut dönemi okumak için CyclePeriod göstergesine bağlanmalı ve daha sonra bu okumayı OnCalculate() işlevinde kullanmalıyız.

İlk başta göstergenin işleyicisini almamız gerekiyor:

hCyclePeriod=iCustom(NULL,0,"CyclePeriod",InpAlpha);
   if(hCyclePeriod==INVALID_HANDLE)
     {
      Print("CyclePeriod indicator not available!");
      return(-1);
     }

 ve ardından OnCalculate() işlevinin içinde okuyun:

int copied=CopyBuffer(hCyclePeriod,0,i,1,CyclePeriod);
    if(copied<=0)
      {
       Print("FAILURE: Could not get values from CyclePeriod indicator.");
       return -1;
      }
alpha1 = 2.0/(CyclePeriod[0]+1.0);

Üstel hareketli alfa, alfa denklemi ile basit bir hareketli ortalamanın uzunluğu ile ilgilidir, Adaptif Siber Döngü göstergesinde Bay Ehlers, alfa1 katsayısının hesaplanmasında uzunluk olarak Baskın Döngü periyodunu kullandı.

Tam kaynak kodu aşağıda mevcuttur:

//+------------------------------------------------------------------+
//|                                           AdaptiveCyberCycle.mq5 |
//|                                      Copyright 2011, Investeo.pl |
//|                                               http://Investeo.pl |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, Investeo.pl"
#property link      "http://Investeo.pl"
#property version   "1.00"
#property indicator_separate_window

#property description "Adaptive CyberCycle indicator - described by John F. Ehlers"
#property description "in \"Cybernetic Analysis for Stocks and Futures\""
#property description "This indicator is available for free download."

#property indicator_buffers 2
#property indicator_plots 2
#property indicator_width1 1
#property indicator_width2 1
#property indicator_type1   DRAW_LINE
#property indicator_type2   DRAW_LINE
#property indicator_color1  Green
#property indicator_color2  Red
#property indicator_label1  "Cycle"
#property indicator_label2  "Trigger Line"

#define Price(i) ((high[i]+low[i])/2.0)

double Smooth[];
double Cycle[];
double Trigger[];

int hCyclePeriod;
 
input double InpAlpha=0.07; // alpha for Cycle Period
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping 
   ArraySetAsSeries(Cycle,true);
   ArraySetAsSeries(Trigger,true);
   ArraySetAsSeries(Smooth,true);

   SetIndexBuffer(0,Cycle,INDICATOR_DATA);
   SetIndexBuffer(1,Trigger,INDICATOR_DATA);

   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0);

   hCyclePeriod=iCustom(NULL,0,"CyclePeriod",InpAlpha);
   if(hCyclePeriod==INVALID_HANDLE)
     {
      Print("CyclePeriod indicator not available!");
      return(-1);
     }
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---   
   long tickCnt[1];
   int i;
   int ticks=CopyTickVolume(Symbol(), 0, 0, 1, tickCnt);
   if(ticks!=1) return(rates_total);
   double CyclePeriod[1],alpha1;

   Comment(tickCnt[0]);

   if(prev_calculated==0 || tickCnt[0]==1)
     {
      //--- last counted bar will be recounted
      int nLimit=rates_total-prev_calculated-1; // start index for calculations

      ArraySetAsSeries(high,true);
      ArraySetAsSeries(low,true);

      ArrayResize(Smooth,Bars(_Symbol,_Period));
      ArrayResize(Cycle,Bars(_Symbol,_Period));
      
      if(nLimit>rates_total-4) // adjust for last bars
         nLimit=rates_total-4;

      for(i=nLimit;i>=0 && !IsStopped();i--)
        {
         Smooth[i]=(Price(i)+2*Price(i+1)+2*Price(i+2)+Price(i+3))/6.0;
         int copied=CopyBuffer(hCyclePeriod,0,i,1,CyclePeriod);

         if(copied<=0)
           {
            Print("FAILURE: Could not get values from CyclePeriod indicator.");
            return -1;
           }
         alpha1 = 2.0/(CyclePeriod[0]+1.0);
         //Print(alpha1);
         //Print(CyclePeriod[0]);
         if(i>=0)
           {
            Cycle[i]=(1.0-0.5*alpha1) *(1.0-0.5*alpha1) *(Smooth[i]-2.0*Smooth[i+1]+Smooth[i+2])
                     +2.0*(1.0-alpha1)*Cycle[i+1]-(1.0-alpha1)*(1.0-alpha1)*Cycle[i+2];

            //Print("Smooth["+IntegerToString(i)+"]="+DoubleToString(Smooth[i])+" Cycle["+IntegerToString(i)+"]="+DoubleToString(Cycle[i]));
           }
         else
           {
            Cycle[i]=(Price(i)-2.0*Price(i+1)+Price(i+2))/4.0;
           }

         //Print(__FILE__+__FUNCTION__+" received values: ",rCnt);
         Trigger[i]=Cycle[i+1];
        }
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

 Lütfen ekteki ekran görüntüsündeki göstergeye bakın.

Uyarlanabilir CyberCycle göstergesi 

İlk uyarlanabilir göstergemiz hazır. Kitaba göre, uyarlanabilir olmayan sürümden daha duyarlı olmalıdır.

Alış ve satış sinyalleri, uyarlanabilir olmayan sürümden genellikle bir çubuk önce gerçekleşmelidir.

İki gösterge örneği daha ile devam edebiliriz, uyarlanabilir göstergeler oluşturma şemasını anlamanız yeterli olacaktır.


Ağırlık Merkezi göstergesi

Herhangi bir fiziksel nesnenin ağırlık merkezinden bahsederken, onun denge noktasını kastediyoruz. Bu kavramı ticarete sokma fikri, çeşitli filtrelerin gecikmelerinin filtrenin katsayılarıyla nasıl ilişkili olduğunu gözlemlemekten geldi.

SMA - Basit Hareketli Ortalama için tüm katsayılar eşittir, ağırlık merkezi ortadadır.

WMA - Ağırlıklı Hareketli Ortalama için son fiyatlar eskilerden daha önemlidir. Spesifik olmak gerekirse, WMA katsayıları üçgenin ana hatlarını tanımlar. Üçgenin ağırlık merkezi, üçgenin tabanının uzunluğunun üçte biri kadardır. Belirli bir gözlem penceresinde ağırlık merkezinin hesaplanması için türetilen daha genel denklem aşağıdaki gibidir:

CenterOfGravity 

Denge noktasının konumu, pencere içindeki konumun çarpımının bu konumdaki fiyatın toplamıdır (denklemde +1, çünkü 0'dan N'ye kadar ve 1'den N'ye kadar saydığımız için) toplamına bölünür. penceredeki fiyatlar.

CG'nin temel özelliği, fiyat dalgalanmaları ile birlikte azalır ve artar ve esasen sıfır gecikmeli bir osilatördür.

Lütfen aşağıdaki kaynak kodunu bulun:

//+------------------------------------------------------------------+
//|                                              CenterOfGravity.mq5 |
//|                                      Copyright 2011, Investeo.pl |
//|                                               http://Investeo.pl |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, Investeo.pl"
#property link      "http://Investeo.pl"
#property version   "1.00"
#property indicator_separate_window

#property description "CG indicator - described by John F. Ehlers"
#property description "in \"Cybernetic Analysis for Stocks and Futures\""
#property description "This indicator is available for free download."

#property indicator_buffers 2
#property indicator_plots 2
#property indicator_width1 1
#property indicator_width2 1
#property indicator_type1   DRAW_LINE
#property indicator_type2   DRAW_LINE
#property indicator_color1  Green
#property indicator_color2  Red
#property indicator_label1  "Cycle"
#property indicator_label2  "Trigger Line"

#define Price(i) ((high[i]+low[i])/2.0)

double Smooth[];
double Cycle[];
double Trigger[];

input double InpAlpha=0.07; // alpha
input int InpCGLength=10; //CG window size

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping 
   ArraySetAsSeries(Cycle,true);
   ArraySetAsSeries(Trigger,true);
   ArraySetAsSeries(Smooth,true);
   
   SetIndexBuffer(0,Cycle,INDICATOR_DATA);
   SetIndexBuffer(1,Trigger,INDICATOR_DATA);

   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0);

   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---   
   long tickCnt[1];
   int i;
   double Num, Denom; // Numerator and Denominator for CG
   int ticks=CopyTickVolume(Symbol(), 0, 0, 1, tickCnt);
   if(ticks!=1) return(rates_total);

   Comment(tickCnt[0]);

   if(prev_calculated==0 || tickCnt[0]==1)
     {
      //--- last counted bar will be recounted
      int nLimit=rates_total-prev_calculated-1; // start index for calculations

      ArraySetAsSeries(high,true);
      ArraySetAsSeries(low,true);

      ArrayResize(Smooth,Bars(_Symbol,_Period));
      ArrayResize(Cycle,Bars(_Symbol,_Period));

      if(nLimit>rates_total-InpCGLength) // adjust for last bars
         nLimit=rates_total-InpCGLength;

      for(i=nLimit;i>=0 && !IsStopped();i--)
        {
         Num = 0.0;
         Denom = 0.0;
         for (int count=0; count<InpCGLength; count++)
            {
               Num += (1.0+count)*Price(i+count);
               Denom += Price(i+count);
            }
         if (Denom != 0.0)
            Cycle[i] = -Num/Denom+(InpCGLength+1.0)/2.0;
         else
            Cycle[i] = 0.0;
         
         //Print(__FILE__+__FUNCTION__+" received values: ",rCnt);
         Trigger[i]=Cycle[i+1];
        }
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+ 

Aşağıda bir ekran görüntüsü. Lütfen küçük gecikmeye dikkat edin.

  CenterOfGravity göstergesi


Uyarlanabilir Ağırlık Merkezi göstergesi

CG osilatörü, sabit uzunluklu bir zaman penceresinde ağırlık merkezini bulur. Adaptif CG osilatörü, dinamik pencere uzunluğu olarak ölçülen Baskın Döngü süresinin yarısını kullanır. Ölçülen Baskın Döngü süresinin yarısını çıkarmak için aşağıdaki kod kullanıldı. 

copied=CopyBuffer(hCyclePeriod,0,i,1,CyclePeriod);

if(copied<=0)
  {
   Print("FAILURE: Could not get values from CyclePeriod indicator.");
   return -1;
  }
CG_len = floor(CyclePeriod[0]/2.0);

Lütfen aşağıda tam gösterge kaynak kodunu bulun ve uyarlamalı olmayan sürümüyle ve benzerlikler için Uyarlamalı Siber Döngü göstergesiyle karşılaştırın.

//+------------------------------------------------------------------+
//|                                      AdaptiveCenterOfGravity.mq5 |
//|                                      Copyright 2011, Investeo.pl |
//|                                               http://Investeo.pl |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, Investeo.pl"
#property link      "http://Investeo.pl"
#property version   "1.00"
#property indicator_separate_window

#property description "Adaptive CG indicator - described by John F. Ehlers"
#property description "in \"Cybernetic Analysis for Stocks and Futures\""
#property description "This indicator is available for free download."

#property indicator_buffers 2
#property indicator_plots 2
#property indicator_width1 1
#property indicator_width2 1
#property indicator_type1   DRAW_LINE
#property indicator_type2   DRAW_LINE
#property indicator_color1  Green
#property indicator_color2  Red
#property indicator_label1  "Cycle"
#property indicator_label2  "Trigger Line"

#define Price(i) ((high[i]+low[i])/2.0)

double Smooth[];
double Cycle[];
double Trigger[];

int hCyclePeriod;

input double InpAlpha=0.07; // alpha
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping 
   ArraySetAsSeries(Cycle,true);
   ArraySetAsSeries(Trigger,true);
   ArraySetAsSeries(Smooth,true);

   SetIndexBuffer(0,Cycle,INDICATOR_DATA);
   SetIndexBuffer(1,Trigger,INDICATOR_DATA);

   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0);

   hCyclePeriod=iCustom(NULL,0,"CyclePeriod",InpAlpha);
   if(hCyclePeriod==INVALID_HANDLE)
     {
      Print("CyclePeriod indicator not available!");
      return(-1);
     }

   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---   
   long tickCnt[1];
   int i, copied;
   double Num,Denom; // Numerator and Denominator for CG
   double CG_len;
   int ticks=CopyTickVolume(Symbol(), 0, 0, 1, tickCnt);
   if(ticks!=1) return(rates_total);
   double CyclePeriod[1];

   Comment(tickCnt[0]);

   if(prev_calculated==0 || tickCnt[0]==1)
     {
      //--- last counted bar will be recounted
      int nLimit=rates_total-prev_calculated-1; // start index for calculations

      ArraySetAsSeries(high,true);
      ArraySetAsSeries(low,true);

      ArrayResize(Smooth,Bars(_Symbol,_Period));
      ArrayResize(Cycle,Bars(_Symbol,_Period));
      
      copied=CopyBuffer(hCyclePeriod,0,0,1,CyclePeriod);

      if(copied<=0)
        {
         Print("FAILURE: Could not get values from CyclePeriod indicator.");
         return -1;
        }

      if(nLimit>rates_total-int(CyclePeriod[0])-2) // adjust for last bars
         nLimit=rates_total-int(CyclePeriod[0])-2;


      for(i=nLimit;i>=0 && !IsStopped();i--)
        {
         copied=CopyBuffer(hCyclePeriod,0,i,1,CyclePeriod);

         if(copied<=0)
           {
            Print("FAILURE: Could not get values from CyclePeriod indicator.");
            return -1;
           }
         CG_len = floor(CyclePeriod[0]/2.0);
         //Print("CG_len="+DoubleToString(CG_len));
         
         Num=0.0;
         Denom=0.0;
         for(int count=0; count<int(CG_len); count++)
           {
            Num+=(1.0+count)*Price(i+count);
            Denom+=Price(i+count);
           }
         if(Denom!=0.0)
            Cycle[i]=-Num/Denom+(CG_len+1.0)/2.0;
         else
            Cycle[i]=0.0;

         //Print(__FILE__+__FUNCTION__+" received values: ",rCnt);
         Trigger[i]=Cycle[i+1];
        }
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

Lütfen aşağıda yapıştırılan AdaptiveCG göstergesi ekran görüntüsünü inceleyin. 

 Uyarlanabilir CenterOfGravity ekran görüntüsü


RVI göstergesi

RVI kısaltması, Relative Vigor Index anlamına gelir. Bu göstergenin arkasındaki temel teori, fiyatların boğa piyasalarında kapanış fiyatının açık fiyattan daha yüksek ve ayı piyasalarında kapanış fiyatının açık fiyattan daha düşük olma eğiliminde olmasıdır.

Hareketin gücü, günlük işlem aralığına göre kapanış fiyatı ile açılış fiyatı arasındaki farkla ölçülür.

RVI 

Bu, artık MetaTrader 5 kurulumuna gömülü olduğu için birçok MetaTrader kullanıcısı için oldukça bilinen bir göstergedir.

Hala referans için kaynak kodunu yapıştırıyorum:

//+------------------------------------------------------------------+
//|                                                          RVI.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright   "2009, MetaQuotes Software Corp."
#property link        "https://www.mql5.com"
#property description "Relative Vigor Index"
//--- indicator settings
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   2
#property indicator_type1   DRAW_LINE
#property indicator_type2   DRAW_LINE
#property indicator_color1  Green
#property indicator_color2  Red
#property indicator_label1  "RVI"
#property indicator_label2  "Signal"
//--- input parameters
input int InpRVIPeriod=10; // Period
//--- indicator buffers
double    ExtRVIBuffer[];
double    ExtSignalBuffer[];
//---
#define TRIANGLE_PERIOD  3
#define AVERAGE_PERIOD   (TRIANGLE_PERIOD*2)
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,ExtRVIBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,ExtSignalBuffer,INDICATOR_DATA);
   IndicatorSetInteger(INDICATOR_DIGITS,3);
//--- sets first bar from what index will be drawn
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,(InpRVIPeriod-1)+TRIANGLE_PERIOD);
   PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,(InpRVIPeriod-1)+AVERAGE_PERIOD);
//--- name for DataWindow and indicator subwindow label
   IndicatorSetString(INDICATOR_SHORTNAME,"RVI("+string(InpRVIPeriod)+")");
   PlotIndexSetString(0,PLOT_LABEL,"RVI("+string(InpRVIPeriod)+")");
   PlotIndexSetString(1,PLOT_LABEL,"Signal("+string(InpRVIPeriod)+")");
//--- initialization done
  }
//+------------------------------------------------------------------+
//| Relative Vigor Index                                             |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,const int prev_calculated,
                const datetime &Time[],
                const double &Open[],
                const double &High[],
                const double &Low[],
                const double &Close[],
                const long &TickVolume[],
                const long &Volume[],
                const int &Spread[])
  {
   int    i,j,nLimit;
   double dValueUp,dValueDown,dNum,dDeNum;
//--- check for bars count
   if(rates_total<=InpRVIPeriod+AVERAGE_PERIOD+2) return(0); // exit with zero result
//--- check for possible errors
   if(prev_calculated<0) return(0); // exit with zero result
//--- last counted bar will be recounted
   nLimit=InpRVIPeriod+2;
   if(prev_calculated>InpRVIPeriod+TRIANGLE_PERIOD+2)
      nLimit=prev_calculated-1;
//--- set empty value for uncalculated bars
   if(prev_calculated==0)
     {
      for(i=0;i<InpRVIPeriod+TRIANGLE_PERIOD;i++) ExtRVIBuffer[i]=0.0;
      for(i=0;i<InpRVIPeriod+AVERAGE_PERIOD;i++)  ExtSignalBuffer[i]=0.0;
     }
//--- RVI counted in the 1-st buffer
   for(i=nLimit;i<rates_total && !IsStopped();i++)
     {
      dNum=0.0;
      dDeNum=0.0;
      for(j=i;j>i-InpRVIPeriod;j--)
        {
         dValueUp=Close[j]-Open[j]+2*(Close[j-1]-Open[j-1])+2*(Close[j-2]-Open[j-2])+Close[j-3]-Open[j-3];
         dValueDown=High[j]-Low[j]+2*(High[j-1]-Low[j-1])+2*(High[j-2]-Low[j-2])+High[j-3]-Low[j-3];
         dNum+=dValueUp;
         dDeNum+=dValueDown;
        }
      if(dDeNum!=0.0)
         ExtRVIBuffer[i]=dNum/dDeNum;
      else
         ExtRVIBuffer[i]=dNum;
     }
//--- signal line counted in the 2-nd buffer
   nLimit=InpRVIPeriod+TRIANGLE_PERIOD+2;
   if(prev_calculated>InpRVIPeriod+AVERAGE_PERIOD+2)
      nLimit=prev_calculated-1;
   for(i=nLimit;i<rates_total && !IsStopped();i++) 
      ExtSignalBuffer[i]=(ExtRVIBuffer[i]+2*ExtRVIBuffer[i-1]+2*ExtRVIBuffer[i-2]+ExtRVIBuffer[i-3])/AVERAGE_PERIOD;

//--- OnCalculate done. Return new prev_calculated.
   return(rates_total);
  }
//+------------------------------------------------------------------+

Varsayılan 10'a ayarlanmış süre ile standart RVI göstergesinin ekran görüntüsü aşağıya yapıştırılmıştır.

RVI göstergesi 

 

Uyarlanabilir RVI göstergesi

Önceki iki uyarlanabilir göstergede olduğu gibi, Dominant Döngü ölçümünü CyclePeriod göstergesinden çıkarmamız ve bunu RVI dönemine uygulamamız gerekiyor. "Uzunluk" değişkeni, dönemin dört çubuk ağırlıklı hareketli ortalaması olarak hesaplanır:

copied=CopyBuffer(hCyclePeriod,0,0,4,CyclePeriod);

if(copied<=0)
  {
   Print("FAILURE: Could not get values from CyclePeriod indicator.");
   return -1;
  }
AdaptiveRVIPeriod = int(floor((4*CyclePeriod[0]+3*CyclePeriod[1]+2*CyclePeriod[2]+CyclePeriod[3])/20.0));

Lütfen aşağıda Uyarlanabilir RVI göstergesinin tam kaynak kodunu bulun. 

//+------------------------------------------------------------------+
//|                                                 Adaptive RVI.mq5 |
//|                        Based on RVI by MetaQuotes Software Corp. |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright   "2009, MetaQuotes Software Corp."
#property copyright   "2011, Adaptive version Investeo.pl"
#property link        "https://www.mql5.com"
#property description "Adaptive Relative Vigor Index"
//--- indicator settings
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   2
#property indicator_type1   DRAW_LINE
#property indicator_type2   DRAW_LINE
#property indicator_color1  Green
#property indicator_color2  Red
#property indicator_label1  "AdaptiveRVI"
#property indicator_label2  "Signal"

#define Price(i) ((high[i]+low[i])/2.0)

//--- input parameters
input int InpRVIPeriod=10; // Initial RVI Period
//--- indicator buffers
double    ExtRVIBuffer[];
double    ExtSignalBuffer[];
//---
int hCyclePeriod; 
input double InpAlpha=0.07; // alpha for Cycle Period
int AdaptiveRVIPeriod;

#define TRIANGLE_PERIOD  3
#define AVERAGE_PERIOD   (TRIANGLE_PERIOD*2)
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,ExtRVIBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,ExtSignalBuffer,INDICATOR_DATA);
   IndicatorSetInteger(INDICATOR_DIGITS,3);
   hCyclePeriod=iCustom(NULL,0,"CyclePeriod",InpAlpha);
   if(hCyclePeriod==INVALID_HANDLE)
     {
      Print("CyclePeriod indicator not available!");
      return(-1);
     }
   
//--- sets first bar from what index will be drawn
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,(InpRVIPeriod-1)+TRIANGLE_PERIOD);
   PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,(InpRVIPeriod-1)+AVERAGE_PERIOD);
//--- name for DataWindow and indicator subwindow label
   IndicatorSetString(INDICATOR_SHORTNAME,"AdaptiveRVI");
   PlotIndexSetString(0,PLOT_LABEL,"AdaptiveRVI");
   PlotIndexSetString(1,PLOT_LABEL,"Signal");
//--- initialization done
  return 0;
  }
//+------------------------------------------------------------------+
//| Relative Vigor Index                                             |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,const int prev_calculated,
                const datetime &Time[],
                const double &Open[],
                const double &High[],
                const double &Low[],
                const double &Close[],
                const long &TickVolume[],
                const long &Volume[],
                const int &Spread[])
  {
   int    i,j,nLimit;
   double dValueUp,dValueDown,dNum,dDeNum;
   double CyclePeriod[4];
   int copied;
   
   copied=CopyBuffer(hCyclePeriod,0,0,4,CyclePeriod);

         if(copied<=0)
           {
            Print("FAILURE: Could not get values from CyclePeriod indicator.");
            return -1;
           }
   AdaptiveRVIPeriod = int(floor((4*CyclePeriod[0]+3*CyclePeriod[1]+2*CyclePeriod[2]+CyclePeriod[3])/20.0));
//--- check for bars count
   if(rates_total<=AdaptiveRVIPeriod+AVERAGE_PERIOD+2) return(0); // exit with zero result
//--- check for possible errors
   if(prev_calculated<0) return(0); // exit with zero result
//--- last counted bar will be recounted
   nLimit=AdaptiveRVIPeriod+2;
   if(prev_calculated>AdaptiveRVIPeriod+TRIANGLE_PERIOD+2)
      nLimit=prev_calculated-1;
//--- set empty value for uncalculated bars
   if(prev_calculated==0)
     {
      for(i=0;i<AdaptiveRVIPeriod+TRIANGLE_PERIOD;i++) ExtRVIBuffer[i]=0.0;
      for(i=0;i<AdaptiveRVIPeriod+AVERAGE_PERIOD;i++)  ExtSignalBuffer[i]=0.0;
     }
//--- RVI counted in the 1-st buffer
   for(i=nLimit;i<rates_total && !IsStopped();i++)
     {
      copied=CopyBuffer(hCyclePeriod,0,rates_total-i-1,4,CyclePeriod);

         if(copied<=0)
           {
            Print("FAILURE: Could not get values from CyclePeriod indicator.");
            return -1;
           }
      AdaptiveRVIPeriod = int(floor((4*CyclePeriod[0]+3*CyclePeriod[1]+2*CyclePeriod[2]+CyclePeriod[3])/20.0));
      dNum=0.0;
      dDeNum=0.0;
      for(j=i;j>MathMax(i-AdaptiveRVIPeriod, 3);j--)
        {
         //Print("rates_total="+IntegerToString(rates_total)+" nLimit="+IntegerToString(nLimit)+
         //      " AdaptiveRVIPeriod="+IntegerToString(AdaptiveRVIPeriod)+" j="+IntegerToString(j));
         dValueUp=Close[j]-Open[j]+2*(Close[j-1]-Open[j-1])+2*(Close[j-2]-Open[j-2])+Close[j-3]-Open[j-3];
         dValueDown=High[j]-Low[j]+2*(High[j-1]-Low[j-1])+2*(High[j-2]-Low[j-2])+High[j-3]-Low[j-3];
         dNum+=dValueUp;
         dDeNum+=dValueDown;
        }
      if(dDeNum!=0.0)
         ExtRVIBuffer[i]=dNum/dDeNum;
      else
         ExtRVIBuffer[i]=dNum;
     }
//--- signal line counted in the 2-nd buffer
   nLimit=AdaptiveRVIPeriod+TRIANGLE_PERIOD+2;
   if(prev_calculated>AdaptiveRVIPeriod+AVERAGE_PERIOD+2)
      nLimit=prev_calculated-1;
   for(i=nLimit;i<rates_total && !IsStopped();i++)
    ExtSignalBuffer[i]=(ExtRVIBuffer[i]+2*ExtRVIBuffer[i-1]+2*ExtRVIBuffer[i-2]+ExtRVIBuffer[i-3])/AVERAGE_PERIOD;

//--- OnCalculate done. Return new prev_calculated.
   return(rates_total);
  }
//+------------------------------------------------------------------+ 

Dinamik pencere uzunluğuna sahip Uyarlanabilir RVI göstergesinin ekran görüntüsü:

AdaptiveRVI göstergesi 


Sonuç

Bu makale, üç uyarlanabilir teknik gösterge davranışını ve MQL5 uygulamasını sundu.

Uyarlanabilir göstergeleri uygulama mekanizması, makaleyi okuduktan sonra açıkça anlaşılabilir olmalıdır. Açıklanan tüm göstergeler eklerde mevcuttur.

Yazar, halihazırda mevcut olanlardan diğer uyarlanabilir göstergeleri denemeye ve oluşturmaya teşvik eder.


MetaQuotes Ltd tarafından İngilizceden çevrilmiştir.
Orijinal makale: https://www.mql5.com/en/articles/288

Ekli dosyalar |
adaptivervi.mq5 (5.63 KB)
cybercycle.mq5 (4.09 KB)
cycleperiod.mq5 (6.04 KB)
Zaman Serisinin Temel Özelliklerinin Analizi Zaman Serisinin Temel Özelliklerinin Analizi
Bu makalede, çeşitli zaman serilerinin özellikleri hakkında hızlı bir ön tahmin vermek için tasarlanmış bir sınıf tanıtmaktadır. Bu gerçekleştiğinde, istatistiksel parametreler ve otomatik ilişki fonksiyonu tahmin edilir, zaman serisinin spektral tahmini gerçekleştirilir ve bir histogram inşa edilir.
Yeni Başlayanlar için MQL5 Sihirbazı Yeni Başlayanlar için MQL5 Sihirbazı
2011'in başlarında MQL5 Sihirbazı'nın ilk sürümünü yayınladık. Bu yeni uygulama, otomatik olarak ticaret robotları oluşturmak üzere basit ve kullanışlı bir araç sağlar. Herhangi bir MetaTrader 5 kullanıcısı, MQL5'te nasıl programlama yapılacağını bile bilmeden özel bir Uzman Danışman oluşturabilir.
Üssel Düzeltme Kullanarak Zaman Serisi Tahmini Üssel Düzeltme Kullanarak Zaman Serisi Tahmini
Makale, okuyucuyu zaman serilerinin kısa vadeli tahmini için kullanılan üssel düzeltme modellerine aşina hale getirir. Buna ek olarak, tahmin sonuçlarının optimizasyonu ve tahmini ile ilgili konulara değinir ve komut dosyalarına ve göstergelere birkaç örnek sunar. Bu makale, üssel düzeltme modelleri temelinde tahmin ilkeleri ile ilk tanışma olarak yararlı olacaktır.
Uzman Danışmanlar İçin Özel Optimizasyon Kriterleri Oluşturma Uzman Danışmanlar İçin Özel Optimizasyon Kriterleri Oluşturma
MetaTrader 5 Müşteri Terminali, Expert Advisor parametrelerinin optimizasyonu için çok çeşitli fırsatlar sunar. Strateji test cihazında yer alan optimizasyon kriterlerine ek olarak, geliştiricilere kendi kriterlerini oluşturma fırsatı verilir. Bu, Uzman Danışmanların test edilmesi ve optimize edilmesi için neredeyse sınırsız sayıda olanak sağlar. Makale, bu tür kriterleri oluşturmanın hem karmaşık hem de basit olan pratik yollarını açıklar.