Birkaç Ara Gösterge Arabelleği Kullanarak Çok Para Birimli Gösterge Oluşturma

Alexey Klenov | 15 Aralık, 2021

Giriş

Her şey Forex için Küme Göstergeleri Oluşturmanın Teorik Temeli makalesinde küme göstergelerinden ilk kez haberdar olduğumda başladı. Bu, o zamanlar benim için çok ilginçti ve çoklu piyasa analizi açısından benzer bir şey yazmaya karar verdim. Başlangıçta, klasik göstergelerin (RSI, MACD, CCI) oranlarını hesaplamak için para birimi indekslerinin hesaplanan değerlerinin kullanıldığı MultiCurrencyIndex kod adlı göstergenin kendi sürümünü uyguladım. 

Şimdi size bu göstergeyi MQL5 ile tamamlayıcı olarak yeni bir platform olan MetaTrader 5'e nasıl aktardığımı anlatacağım, bunun dışında CCI'yi hesaplamak yerine, daha ileriye dönük olan (kanımca) Stokastik (Stokastik Osilatör) göstergeyi hesaplayacağım.

Bazı tanımlarla başlayalım.

Dolar İndeksi  - - Neutron tarafından bana sunulan formül ile hesapladığım çift değer.

USD indeksini hesaplama formülü,

Burada USD / YYY'dir - USD / CHF, XXX / USD gibi tüm doğrudan fiyat teklifleri - EUR / USD gibi tümü geriye dönük.

Diğer indeksler USD içeren Kapanış döviz çiftlerinin değerlerinden hesaplanır.

Ana çizgiler - göstergenin, doğrudan mevcut grafikle ilgili hesaplanan verileri yansıtan iki çizgisi. Örneğin, EURUSD grafiğinde bu, EUR ve USD para birimlerinin satırları olacaktır.

Ek satırlar - mevcut grafikle ilgili olmayan diğer hesaplanmış gösterge satırları. Örneğin, aynı EURUSD grafiği için bu, GBP, CHF, JPY, CAD, AUD ve NZD para birimlerinin satırları olacaktır.

Kapanış - gerekli döviz çifti için geçerli zaman diliminin (double türü) çubuğunun kapanış fiyatının değeri.

O halde başlayalım.

Sorunu belirlemek

İlk olarak sorunu belirlememiz gerekiyor.

  1. Bu zaman diliminin etkilenen döviz çiftlerini içeren grafikleri senkronize edin.
  2. Yedi döviz çiftinin Kapanış verilerine erişim sağlayın: EURUSD, GBPUSD, USDCHF, USDJPY, USDCAD, AUDUSD, NZDUSD; bunları yardımcı hesaplamalar için tasarlanmış gösterge arabelleklerine yerleştirin.
  3. Öğe (2)'de elde edilen verilere dayanarak, geçerli çubuk için dolar indeksini hesaplayın.
  4. Geçerli çubuk için dolar indeksini bilerek, kalan para birimi indekslerini hesaplayın.
  5. Seçilen geçmiş uzunluğu için gerekli sayıda veri hesaplaması (öğe 3 ve 4) gerçekleştirin.
  6. Göstergenin hedefine bağlı olarak, seçilen indekslerin her biri için para birimi değerlerini hesaplayın:
    • Göreceli Güç İndeksi (Göreceli Güç İndeksi, RSI),
    • Yakınsama / Iraksama Hareketli Ortalamaları (Hareketli Ortalama Yakınsama / Iraksama, MACD),
    • Stokastik Osilatör (Stokastik Osilatör),
    • Gelecekte, liste eklenebilir.

Bunun için şunlara ihtiyacımız olacak:

31 gösterge arabelleği:

Bir göstergenin hedefini seçmek için, numaralandırılmış bir enum türü oluşturacağız:

enum Indicator_Type
  {
   Use_RSI_on_indexes             = 1, // RSI of the index  
   Use_MACD_on_indexes            = 2, // MACD from the index  
   Use_Stochastic_Main_on_indexes = 3  // Stochastic on the index
  };
Daha sonra gösterge tercihleri penceresinde input komutunu kullanarak bu listeden kullanıcı seçimlerini türeteceğiz. 
input Indicator_Type ind_type=Use_RSI_on_indexes;  // type of the indicator from the index

"Girişler" sekmesinde giriş parametrelerinin adlarını görüntülemenin daha kolay olmasını sağlamak mümkündür. Bunu yapmak için, aynı satırda giriş parametresinin açıklamasından sonra yerleştirilmesi gereken acil açıklama hedefini kullanıyoruz. Böylece, giriş parametreleri, kullanıcı için daha kolay anlaşılır adlarla karşılaştırılabilir.

Aynı kurallar numaralandırma listeleme komutları için de geçerlidir. Yani , anımsatıcı ad örneğimizde gösterildiği gibi bir açıklamayla ilişkilendirilirse, anımsatıcı ad yerine bu açıklamanın içeriği görüntülenecektir . Bu, giriş parametrelerinin net tanımlarını içeren programlar yazmak için ek esneklik sağlar.

Geliştiriciler, son kullanıcının, kodda yazılanlar yerine anlaşılır parametre adlarını görmesini sağlayarak MQL5 programıyla çalışmanın uygun yollarını sağlamaya çalıştı. Daha fazla bilgiyi burada bulabilirsiniz.

Şekil 1. Gösterge türünü seçme

Şekil 1. Gösterge türünü seçme

Kullanıcıya, göstergeyi ve rengini oluşturmak için gerekli para birimi seçenekleri sunuyoruz:

input bool USD=true;
input bool EUR=true;
input bool GBP=true;
input bool JPY=true;
input bool CHF=true;
input bool CAD=true;
input bool AUD=true;
input bool NZD=true;

input color Color_USD = Green;            // USD line color
input color Color_EUR = DarkBlue;         // EUR line color
input color Color_GBP = Red;             // GBP line color
input color Color_CHF = Chocolate;        // CHF line color
input color Color_JPY = Maroon;           // JPY line color
input color Color_AUD = DarkOrange;       // AUD line color
input color Color_CAD = Purple;          // CAD line color
input color Color_NZD = Teal;            // NZD line color

Şekil 2. Gösterge çizgilerinin rengini seçme

Şekil 2. Gösterge çizgilerinin rengini seçme

Birkaç diğer yapılandırılabilir parametre:

input string rem000        =  ""; // depending on the type of the indicator
input string rem0000       =  ""; // requires a value :
input int rsi_period       =   9; // period RSI
input int MACD_fast        =   5; // period MACD_fast
input int MACD_slow        =  34; // period MACD_slow
input int stoch_period_k   =   8; // period Stochastic %K
input int stoch_period_sma =   5; // period of smoothing for Stochastics %K
input int shiftbars        = 500; // number of bars for calculating the indicator

Şekil 3. Gösterge parametreleri

Şekil 3. Gösterge parametreleri

Göstergenin hesaplanması için 500 çubukluk bir sınır yapaydır fakat hesaplama kavramını göstermek için yeterlidir. Ancak, her gösterge arabelleğinin bellek gerektirdiğini ve çok büyük değişken boyutlu (milyonlarca çubuk cinsinden) bir görüntünün bilgisayarın yeterli belleğe sahip olmamasına neden olabileceğini unutmamalıyız.

Gösterge arabellekleri:

double  EURUSD[], // quotes
        GBPUSD[],
        USDCHF[],
        USDJPY[],
        AUDUSD[],
        USDCAD[],
        NZDUSD[];   
               
double    USDx[], // indexes
          EURx[],
          GBPx[],
          JPYx[],
          CHFx[],
          CADx[],
          AUDx[],
          NZDx[];
                         
double USDplot[], // results of currency lines
       EURplot[],
       GBPplot[],
       JPYplot[],
       CHFplot[],
       CADplot[],
       AUDplot[],
       NZDplot[]; 

double USDStoch[], // buffers of intermediate data schotastics by the close/close type without smoothing
       EURStoch[],
       GBPStoch[],
       JPYStoch[],
       CHFStoch[],
       CADStoch[],
       AUDStoch[],
       NZDStoch[];
Ayrıca bazı genel (gösterge düzeyi) değişkenlere de ihtiyacımız olacak:
int              i,ii;
int           y_pos=0; // Y coordinate variable for the informatory objects  
datetime   arrTime[7]; // Array with the last known time of a zero valued bar (needed for synchronization)  
int        bars_tf[7]; // To check the number of available bars in different currency pairs  
int        countVal=0; // Number of executable Rates  
int           index=0;
datetime  tmp_time[1]; // Intermediate array for the time of the bar 

Ve şimdi, gösterge arabelleklerini amaçlarına göre dağıtacağımız oldukça uzun bir OnInit özelliğine geldik.

İlk hesaplamalar dolar indeksinden geçtiği için, USD için yalnızca para birimi gösterge arabelleklerinin oluşturulmasını devre dışı bırakma olasılığını belirliyoruz.

Bu, şu şekilde görünür:

if(USD)
  {
   countVal++;
   SetIndexBuffer(0,USDplot,INDICATOR_DATA);               // array for rendering
   PlotIndexSetString(0,PLOT_LABEL,"USDplot");              // name of the indicator line (when selected with a mouse)
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,shiftbars);       // from which we begin rendering
   PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_LINE);         // drawing style (line)
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,Color_USD);       // color of line rendering
   if(StringFind(Symbol(),"USD",0)!=-1)
     {PlotIndexSetInteger(0,PLOT_LINE_WIDTH,wid_main);}    // if the symbol name contains USD 
                                                       // then draw a line of appropriate width 
   else
     {PlotIndexSetInteger(0,PLOT_LINE_STYLE,style_slave);}
   ArraySetAsSeries(USDplot,true);                       // indexation of array as a timeseries   
   ArrayInitialize(USDplot,EMPTY_VALUE);                  // zero values 
   f_draw("USD",Color_USD);                            // rendering in the indicator information window 
  }
SetIndexBuffer(15,USDx,INDICATOR_CALCULATIONS);            // array of dollar index for calculations
                                                      // (is not displayed in the indicator as a line) 
ArraySetAsSeries(USDx,true);                            // indexation of an array as a time series
ArrayInitialize(USDx,EMPTY_VALUE);                       // zero values

if(ind_type==Use_Stochastic_Main_on_indexes)
  {
   SetIndexBuffer(23,USDstoch,INDICATOR_CALCULATIONS);     // if the destination of the indicator as a Use_Stochastic_Main_on_indexes,
                                                           // then this intermediate array is needed
   ArraySetAsSeries(USDstoch,true);                        // indexation of array as a time series
   ArrayInitialize(USDstoch,EMPTY_VALUE);                  // zero values
  }
EUR para birimi için işlev kodu OnInit şu şekilde görünür:
if(USD)
  {
   countVal++;
   SetIndexBuffer(0,USDplot,INDICATOR_DATA);              // array for rendering
   PlotIndexSetString(0,PLOT_LABEL,"USDplot");             // name of the indicator line (when selected with a mouse)
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,shiftbars);       // from which we begin rendering
   PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_LINE);         // drawing style (line)
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,Color_USD);       // color of line rendering
   if(StringFind(Symbol(),"USD",0)!=-1)
     {PlotIndexSetInteger(0,PLOT_LINE_WIDTH,wid_main);}    // if the symbol name contains USD 
                                                       // then draw a line of appropriate width 
   else
     {PlotIndexSetInteger(0,PLOT_LINE_STYLE,style_slave);}
   ArraySetAsSeries(USDplot,true);                       // indexation of array as a timeseries
   ArrayInitialize(USDplot,EMPTY_VALUE);                  // zero values 
   f_draw("USD",Color_USD);                             // rendering in the indicator information window 
  }
SetIndexBuffer(15,USDx,INDICATOR_CALCULATIONS);             // array of dollar index for calculations
                                                       // (is not displayed in the indicator as a line) 
ArraySetAsSeries(USDx,true);                             // indexation of an array as a time series
ArrayInitialize(USDx,EMPTY_VALUE);                        // zero values

if(ind_type==Use_Stochastic_Main_on_indexes)
  {
   SetIndexBuffer(23,USDstoch,INDICATOR_CALCULATIONS);      // if the destination of the indicator as a Use_Stochastic_Main_on_indexes,
                                                       // then this intermediate array is needed
   ArraySetAsSeries(USDstoch,true);                      // indexation of array as a time series
   ArrayInitialize(USDstoch,EMPTY_VALUE);                 // zero values
  }

if(EUR)
  {
   countVal++;
   SetIndexBuffer(1,EURplot,INDICATOR_DATA);              // array for rendering
   PlotIndexSetString(1,PLOT_LABEL,"EURplot");             // name of the indicator line (when pointed to with a mouse)
   PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,shiftbars);       // which we begin rendering from
   PlotIndexSetInteger(1,PLOT_DRAW_TYPE,DRAW_LINE);         // drawing style (lines)
   PlotIndexSetInteger(1,PLOT_LINE_COLOR,Color_EUR);       // the color of rendering lines
   if(StringFind(Symbol(),"EUR",0)!=-1)
     {PlotIndexSetInteger(1,PLOT_LINE_WIDTH,wid_main);}    // if the symbol name contains EUR
                                                       // then we draw a line of the appropriate width 
   else
     {PlotIndexSetInteger(1,PLOT_LINE_STYLE,style_slave);}  // if the symbol name does NOT contain EUR,
                                                       // then we draw a line of an appropriate style (on the crosses)
   ArraySetAsSeries(EURplot,true);                       // indexation of the array as a time series
   ArrayInitialize(EURplot,EMPTY_VALUE);                  // zero values
   SetIndexBuffer(8,EURUSD,INDICATOR_CALCULATIONS);        // data of Close currency pair EURUSD
   ArraySetAsSeries(EURUSD,true);                        // indexation of the array as a time series
   ArrayInitialize(EURUSD,EMPTY_VALUE);                   // zero values
   SetIndexBuffer(16,EURx,INDICATOR_CALCULATIONS);         // array of the EURO index for calculations
                                                      // (not displayed on the indicator as a line) 
   ArraySetAsSeries(EURx,true);
   ArrayInitialize(EURx,EMPTY_VALUE);
   if(ind_type==Use_Stochastic_Main_on_indexes)
     {
      SetIndexBuffer(24,EURstoch,INDICATOR_CALCULATIONS);   // if the indicator destination as a Use_Stochastic_Main_on_indexes,
                                                       // then this intermediate array is needed
      ArraySetAsSeries(EURstoch,true);                   // indexation of the array as a time series
      ArrayInitialize(EURstoch,EMPTY_VALUE);              // zero values
     }
   f_draw("EUR",Color_EUR);                            // rendering in the indicator information window
  }
EUR ile benzer şekilde, kod GBP, JPY, CHF, CAD, AUD ve NZD gibi para birimleri için benzer şekilde görünecek ve gösterge arabelleklerinin indekslerini değiştirecektir. Bu para birimlerinin kodu, göstergenin ekli dosyasında bulunabilir.

Bu, göstergenin başlatılmasına ilişkin açıklamayı tamamlar.

Ardından, bazı özel kullanıcı özelliklerine ihtiyacımız olacak:

Bunların her birinin kısa açıklaması:

Giriş parametreleri:

double f_RSI(double &buf_in[], int period,int shift),

burada buf_in[] - double türünde dizi (zaman serisi gibi), dönem - RSI gösterge dönemi, kayma - göstergeyi hesapladığımız indeks çubuğu. Double türünde bir değer döndürür.

Giriş parametreleri:

double f_MACD(double &buf_in[], int period_fast,int period_slow,int shift),

burada buf_in[] - double türünde bir dizi (zaman serisi gibi), period_fast - hızlı dönem МА, period_slow - dönem yavaş МА, shift } - göstergeyi hesapladığımız indeks çubuğu. Double türünde bir değer döndürür.

Giriş parametreleri:

double SimpleMA(const int position,const int period,const double &price[]),

burada pozisyon - göstergeyi hesapladığımız indeks çubuğu. dönem - gösterge SMA dönemi, price[] - çift zaman dizisi (zaman serisi gibi). Double türünde bir değer döndürür.

Giriş parametreleri:

double f_Stoch(double &price[], int period_k, int shift),

burada price[] - çift türünde dizi (zaman serisi gibi), hızlı_dönem - dönem %K gösterge çizgisi, kayma - göstergeyi hesapladığımız indeks çubuğu. Double türünde bir değer döndürür.

Giriş parametreleri:

int f_draw(string name, color _color)

burada ad - nesne adı, _color - nesne rengi. İşlev bilgi amaçlıdır. Pencere ekranının sağ üst köşesinden başlayarak ve daha aşağıya doğru bu işlev, etkilenen para birimlerinin adlarını görüntüler. Para biriminin metni, bu para birimiyle ilgili olarak gösterge çizgisiyle aynı renktedir.

Giriş parametreleri:

int f_comment(string text)

metin - Göstergenin sağ alt köşesine yerleştirilmesi gereken metin. Göstergenin çalışmasına ilişkin bir tür durum çubuğu.

Son olarak, sonuç ve en önemli işlevlerden biri:

Giriş parametresi yok.

MetaTrader 5'te geçmiş, her araç için TF'nin dakika verileri şeklinde saklanır. Bu nedenle, programı başlatmadan önce, terminal açıldığında aynı TF dakika verilerine dayanarak gerekli (etkilenen) tüm grafikler oluşturulur. Yapı ayrıca mevcut trafik TF'si değiştirilirken veya MQL5 program kodu aracılığıyla TF'nin grafiğine erişme girişimi sırasında gerçekleşir.

Dolayısıyla:

Bu görevin ilk kısmı, yerleşik Çubuklar işlevi kullanılarak gerçekleştirilir; bu, , sembole karşılık gelen döneme göre geçmişteki çubuk sayısını döndürür. Bu işlevin aşağıda gösterilen sürümünü kullanmanız yeterlidir.

int  Bars(
   string          symbol_name,   // symbol name
   ENUM_TIMEFRAMES   timeframe    // period
   );

Özel olarak bildirilen bu dizi için, etkilenen tüm para birimi çiftleri için mevcut çubukların sayısını toplarız. Her değeri minimum gerekli geçmiş miktarı için kontrol ederiz (gösterge parametrelerinde "göstergeyi hesaplamak için çubuk sayısı" değişkeni). Herhangi bir enstrümanın geçmişindeki mevcut çubuk sayısı bu değişkenin değerinden azsa, oluşturmanın başarılı olmadığını düşünürüz ve mevcut veri sayısını yeniden inceleriz. Tüm para birimi çiftleri için kullanıcı tarafından talep edilenden daha fazla kullanılabilir geçmiş olduğunda, başlatma işleminin bu kısmının başarıyla tamamlandığını düşünebiliriz.

Senkronizasyon görevinin ikinci kısmı, CopyTime işlevi kullanılarak gerçekleştirilir.

 Bu amaç için özel olarak oluşturulmuş bir diziye, etkilenen her enstrümanın sıfır çubuğunun açılışını kopyalarız. Bu dizinin tüm öğeleri aynıysa ve 0'a eşit değilse, sıfırıncı çubuğumuzun senkronize olduğunu düşünelim ve hesaplamaya başlayalım. Bunun nasıl uygulandığını daha ayrıntılı olarak anlamak için ekteki göstergenin koduna bakın.

Bu, ek işlevlerin açıklamasını özetlemektedir; OnCalculate işlevini uygulamaya geçelim. Bu çok para birimli bir gösterge olduğu için, bu işlevin talebinin ikinci sürümüne ihtiyacımız olacak.

int OnCalculate(const int     rates_total, // size of incoming time series
                const int prev_calculated, // processing of bars on the previous request
                const datetime&    time[], // Time
                const double&      open[], // Open
                const double&      high[], // High
                const double&       low[], // Low
                const double&     close[], // Close
                const long& tick_volume[], // Tick Volume
                const long&      volume[], // Real Volume
                const int&       spread[]  // Spread
   );

Hesaplama için gerekli olan çubuk miktarını belirleyin:

   int limit=shiftbars;

   if(prev_calculated>0)
     {limit=1;}
   else
     {limit=shiftbars;}

Para birimi çiftlerinin grafiklerini senkronize edin:

   init_tf();

Ardından, CopyClose işlevini kullanarak, gerekli tüm para birimi çiftlerinin Kapanış verilerini bunun için özel olarak kaydedilen gösterge arabelleklerine kopyalarız. (Mevcut aracın ve / veya diğer aracın diğer TF verilerine erişim hakkında daha fazla bilgi Yardım bölümünde bulunabilir)

İşlev herhangi bir nedenle verileri kopyalamaz ve -1 yanıtını döndürürse, açıklamada bir para birimi çifti hata mesajı görüntüler ve mevcut enstrüman için yeni bir tick'in alınmasını bekleriz.

   if (EUR){copied=CopyClose("EURUSD",PERIOD_CURRENT,0,shiftbars,EURUSD); if (copied==-1){f_comment("Wait...EURUSD");return(0);}}
   if (GBP){copied=CopyClose("GBPUSD",PERIOD_CURRENT,0,shiftbars,GBPUSD); if (copied==-1){f_comment("Wait...GBPUSD");return(0);}}
   if (CHF){copied=CopyClose("USDCHF",PERIOD_CURRENT,0,shiftbars,USDCHF); if (copied==-1){f_comment("Wait...USDCHF");return(0);}}
   if (JPY){copied=CopyClose("USDJPY",PERIOD_CURRENT,0,shiftbars,USDJPY); if (copied==-1){f_comment("Wait...USDJPY");return(0);}}
   if (AUD){copied=CopyClose("AUDUSD",PERIOD_CURRENT,0,shiftbars,AUDUSD); if (copied==-1){f_comment("Wait...AUDUSD");return(0);}}
   if (CAD){copied=CopyClose("USDCAD",PERIOD_CURRENT,0,shiftbars,USDCAD); if (copied==-1){f_comment("Wait...USDCAD");return(0);}}
   if (NZD){copied=CopyClose("NZDUSD",PERIOD_CURRENT,0,shiftbars,NZDUSD); if (copied==-1){f_comment("Wait...NZDUSD");return(0);}}  

Bir sonraki döngüde (0'dan sınıra kadar) şunları üretiriz:

for (i=limit-1;i>=0;i--)
   {
      //calculation of USD index
      USDx[i]=1.0;
      if (EUR){USDx[i]+=EURUSD[i];}         
      if (GBP){USDx[i]+=GBPUSD[i];}
      if (CHF){USDx[i]+=1/USDCHF[i];}
      if (JPY){USDx[i]+=1/USDJPY[i];}
      if (CAD){USDx[i]+=1/USDCAD[i];}
      if (AUD){USDx[i]+=AUDUSD[i];}
      if (NZD){USDx[i]+=NZDUSD[i];}
      USDx[i]=1/USDx[i];
      //calculation of other currency values
      if (EUR){EURx[i]=EURUSD[i]*USDx[i];}
      if (GBP){GBPx[i]=GBPUSD[i]*USDx[i];}
      if (CHF){CHFx[i]=USDx[i]/USDCHF[i];}
      if (JPY){JPYx[i]=USDx[i]/USDJPY[i];}
      if (CAD){CADx[i]=USDx[i]/USDCAD[i];}
      if (AUD){AUDx[i]=AUDUSD[i]*USDx[i];}
      if (NZD){NZDx[i]=NZDUSD[i]*USDx[i];}
   }

Veriler, uygun gösterge arabelleklerine yerleştirilir. Başlatma sırasında kullanıcı tarafından hangi tür göstergenin seçildiğini kontrol edin ve bu temelde ilgili hesaplamaları yapın.

İndekslerin RSI'ını gözden geçirmek istiyorsanız aşağıdaki kodu yürütün:

if (ind_type==Use_RSI_on_indexes)
   {
      if (limit>1){ii=limit - rsi_period - 1;}
      else{ii=limit - 1;}
      for(i=ii;i>=0;i--)
         {
            if (USD){USDplot[i]=f_RSI(USDx,rsi_period,i);}
            if (EUR){EURplot[i]=f_RSI(EURx,rsi_period,i);}
            if (GBP){GBPplot[i]=f_RSI(GBPx,rsi_period,i);}
            if (CHF){CHFplot[i]=f_RSI(CHFx,rsi_period,i);}
            if (JPY){JPYplot[i]=f_RSI(JPYx,rsi_period,i);}
            if (CAD){CADplot[i]=f_RSI(CADx,rsi_period,i);}
            if (AUD){AUDplot[i]=f_RSI(AUDx,rsi_period,i);}
            if (NZD){NZDplot[i]=f_RSI(NZDx,rsi_period,i);}                  
         }
   }  

MACD'yi indekslere göre görmek istiyorsak, buraya gideriz (ancak şimdiye kadar bu, yalnızca SimpleMA temelinde uygulandı ve daha sonra EMA temelinde uygulanacak):

if (ind_type==Use_MACD_on_indexes)
   {
      if (limit>1){ii=limit - MACD_slow - 1;}
      else{ii=limit - 1;}
      for(i=ii;i>=0;i--)
         {
           if (USD){USDplot[i]=f_MACD(USDx,MACD_fast,MACD_slow,i);}
           if (EUR){EURplot[i]=f_MACD(EURx,MACD_fast,MACD_slow,i);}
           if (GBP){GBPplot[i]=f_MACD(GBPx,MACD_fast,MACD_slow,i);}
           if (CHF){CHFplot[i]=f_MACD(CHFx,MACD_fast,MACD_slow,i);}
           if (JPY){JPYplot[i]=f_MACD(JPYx,MACD_fast,MACD_slow,i);}
           if (CAD){CADplot[i]=f_MACD(CADx,MACD_fast,MACD_slow,i);}
           if (AUD){AUDplot[i]=f_MACD(AUDx,MACD_fast,MACD_slow,i);}
           if (NZD){NZDplot[i]=f_MACD(NZDx,MACD_fast,MACD_slow,i);}                  
         }
   } 

Stokastik ise, önce % K çizgisini hesaplamalı ve ardından SimpleMA yöntemiyle yumuşatmalısınız. Son yumuşatılmış çizgi grafikte gösterilmelidir.

if (ind_type==Use_Stochastic_Main_on_indexes)
   {
      if (limit>1){ii=limit - stoch_period_k - 1;}
      else{ii=limit - 1;}
      for(i=ii;i>=0;i--)
         {
           if (USD){USDstoch[i]=f_Stoch(USDx,rsi_period,i);}
           if (EUR){EURstoch[i]=f_stoch(EURx,stoch_period_k,i);}
           if (GBP){GBPstoch[i]=f_stoch(GBPx,stoch_period_k,i);}
           if (CHF){CHFstoch[i]=f_stoch(CHFx,stoch_period_k,i);}
           if (JPY){JPYstoch[i]=f_stoch(JPYx,stoch_period_k,i);}
           if (CAD){CADstoch[i]=f_stoch(CADx,stoch_period_k,i);}
           if (AUD){AUDstoch[i]=f_stoch(AUDx,stoch_period_k,i);}
           if (NZD){NZDstoch[i]=f_stoch(NZDx,stoch_period_k,i);}                  
         }
      if (limit>1){ii=limit - stoch_period_sma - 1;}
      else{ii=limit - 1;}
      for(i=ii;i>=0;i--)
         {
            if (USD){USDplot[i]=SimpleMA(i,stoch_period_sma,USDstoch);}
            if (EUR){EURplot[i]=SimpleMA(i,stoch_period_sma,EURstoch);}
            if (GBP){GBPplot[i]=SimpleMA(i,stoch_period_sma,GBPstoch);}
            if (CHF){CHFplot[i]=SimpleMA(i,stoch_period_sma,CHFstoch);}
            if (JPY){JPYplot[i]=SimpleMA(i,stoch_period_sma,JPYstoch);}
            if (CAD){CADplot[i]=SimpleMA(i,stoch_period_sma,CADstoch);}
            if (AUD){AUDplot[i]=SimpleMA(i,stoch_period_sma,AUDstoch);}
            if (NZD){NZDplot[i]=SimpleMA(i,stoch_period_sma,NZDstoch);}                  
          }                     
   }       

Bu, göstergelerin hesaplanmasını tamamlar. Şekil 4-6'da, farklı gösterge türlerine ait birkaç resim gösterilmiştir.

Şekil 4. İndekslere göre RSI

Şekil 4. İndekslere göre RSI

Şekil 5. Para birimi indekslerine göre MACD

Şekil 5. Para birimi indekslerine göre MACD

Şekil 6. Para birimi indekslerine göre Stokastik

Şekil 6. Para birimi indekslerine göre Stokastik

Sonuç

MultiCurrencyIndex göstergesini uygularken, MQL5'te kodu büyük ölçüde basitleştiren sınırsız sayıda gösterge arabelleği kullandım. Bu makale bu tip bir yaklaşımın bir örneğidir. Bir göstergenin güvenilir verileri için, sıfır çubuğuna göre farklı enstrümanların senkronizasyon algoritmasını gösterdim. Ayrıca, göstergenin bağlı olduğu sembole göre verilere diğer enstrümanlardan erişmenin olası algoritmalarından birini de açıkladım.

Makalenin amacı, çok miktarda gösterge arabelleği ile çalışma olasılığını göstermek olduğu için kullanıcıların veri dizileri yoluyla göstergeleri hesaplamaya ilişkin yukarıdaki işlev, okuyucuya fazla yük olmayı önlemenin en uygun yolu değildi. Ancak gerekli hesaplamaları yapmak için yeterliydi.

Forex piyasasının küme analizinin birçok avantajı ve dezavantajı vardır. Bu yaklaşıma dayalı alım satım sistemleri serbestçe kullanılabilir ve MQL4.Community dahil olmak üzere çeşitli forumlarda bununla ilgili tartışmalar vardır. Bu nedenle, bu göstergeye göre alım satım prensipleri bu makalede dikkate alınmamıştır.