English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
Üç Satır Kesme Grafiği Oluşturma Göstergesi

Üç Satır Kesme Grafiği Oluşturma Göstergesi

MetaTrader 5Örnekler | 14 Ocak 2022, 10:51
402 0
Dmitriy Zabudskiy
Dmitriy Zabudskiy

Giriş

Önceki makaleler Nokta ve Şekil, Kagi ve Renko tablolarını ele aldı. 20. yüzyılın grafikleri hakkındaki makaleler dizisine devam ederken, bu sefer Üç Satır Kesme grafiğinden veya daha doğrusu bir program kodu aracılığıyla uygulanmasından bahsedeceğiz. Bu grafiğin kökeni hakkında çok az bilgi var. Sanırım Japonya'da başladı. ABD'de bunu 1994'te yayınlanan "Beyond Candlesticks", Steve Nison'den öğrendiler.

Yukarıda bahsedilen grafiklerde olduğu gibi, Üç Satır Arası grafiği oluşturulurken zaman aralığı dikkate alınmaz. Bir önceki harekete göre bir fiyattaki küçük dalgalanmaları filtrelemeye izin veren, belirli bir zaman diliminde yeni oluşan kapanış fiyatlarına dayanır.

Steve Nison "Beyond Candlesticks" kitabında bu grafiği çizmenin on bir ilkesini tanımladı (s. 185). Bunları üçe topladım.

  • İlke №1: İnşaat için bir başlangıç fiyatı seçin ve ardından piyasanın yukarı veya aşağı hareket etmesine bağlı olarak artan veya azalan bir çizgi çizin. Yeni bir minimum veya maksimum işaretler.
  • İlke №2: Yeni bir fiyat minimumun altına düştüğünde veya maksimumu aştığında, azalan veya artan bir çizgi çizebiliriz.
  • İlke №3: Bir önceki harekete zıt yönde bir çizgi çizmek için minimum veya maksimumun geçilmesi gerekir. Aynı zamanda, birden fazla aynı satır varsa bunlardan iki (arka arkaya iki özdeş satır varsa) veya üç (üç veya daha fazla ardışık aynı satır varsa) baz alınarak minimum veya maksimum hesaplanır.

Geçmiş verilere dayalı klasik bir grafik oluşturma örneğine daha yakından göz atalım (şekil 1).

Şek.1 Üç Satır Kesme grafiği oluşturma örneği (EURUSD H1 27.06.2014)

Şek.1 Üç Satır Kesme grafiği oluşturma örneği (EURUSD H1 27.06.2014)

Şek. 1, sol tarafta bir Şamdan grafiğini ve sağ tarafta bir Üç Satır Kesme grafiğini temsil etmektedir. Bu, H1 zaman dilimi olan EURUSD grafiğidir. Grafiğin başlangıç tarihi 27.06.2014 fiyatı 1.3613 (mumun kapanış saati 00:00), ardından mum (01:00) 1.3614'te kapanır ve Üç Çizgi Kesme grafiğinin ilk yükselen çizgisini oluşturur. Aşağıdaki düşüş yönü mumu (02:00) yükselen bir çizgi oluşturur ve 1.3612'de kapanır (kapanış fiyatı önceki minimumdan daha düşüktür).

Ardından yükselen mum grafik, yeni bir maksimum ve bir çizgi oluşturarak fiyatı 1.3619 (03:00) işaretine doğru hareket ettirir. Saat 04:00'deki mum minimumun altına düşmedi ve yapıyı etkilemedi. Mum saat 05:00'te 1,3623'te kapanır ve yeni bir maksimuma (yeni yükselen çizgi) işaret eder.

Şimdi düşüş trendini uzatmak için iki minimumu (1.3613) geçmemiz gerekiyor, ancak boğalar pozisyonlarından vazgeçmez ve yeni bir maksimum 1.3626 (06:00) oluşturmaz. Ardından boğalar iki saat boyunca yükseliş trendini tersine çevirmeye çalışıyor, ancak aynı trend 1.3634'te (09:00) ulaşılan yeni bir maksimumla devam ediyor. Boğalar önde gidiyor. Şimdi artan bir çizgi çizmek için üç minimumun geçilmesi gerekiyor (1.3626; 1.3623 ve 1.3619).

Gördüğümüz gibi, önümüzdeki üç saat içinde ayılar piyasayı ele geçirerek 1.3612 (12:00) noktasına kadar indiriyor. Bu, yeni bir artan çizgide yansıtılır. Ancak takip eden beş saat, boğaların pozisyonlarını geri kazandığını ve piyasayı 1.3641 noktasına geri getirerek 1.3626'da bir önceki maksimumu geçip 17:00'de yeni bir yükselen çizgi oluşturduğunu gösteriyor. Ayılar saat 18:00'de bir önceki minimumu geçemez ve takip eden beş saat boyunca boğalar piyasayı 1.3649'a getirerek her saat yeni bir yükselen çizgi oluşturur.


Grafik oluşturmanın temelleri

Koda geçmeden önce, göstergenin kendisi hakkında konuşacağız ve bunu diğerlerinden nasıl farklı kıldığını anlayacağız. Üç Satır Kesme grafiğinin de diğer göstergeler gibi etkin piyasa analizi ve yeni strateji arayışlarını kolaylaştırmak için tasarlandığı açıktır. Eminim herhangi bir yenilik olup olmadığını bilmek istersiniz. Aslında bunlardan birkaçı var. Gösterge, hesaplama için fiyat türünü değiştirmeye izin verir. Dört standart çubuk fiyatının tümünü kapsar. Klasik tip, modernize edilmiş olan dört fiyat tipinin (açık, yüksek, düşük ve yakın) kullanımına hitap ettiğinde, yalnızca bir fiyat türü için çizelgeler oluşturmak üzere tasarlanmıştır. Çizgilere "gölgeler" ekleyerek ve çizgilerin Japon şamdanları gibi görünmesini sağlayarak klasik grafik yapısının görünümünü değiştirir, bu da grafiğin görsel algısına katkıda bulunur.

Modernleştirilmiş sürüm ayrıca, eksik fiyatları öncelikli olanlar yerine koyarak fiyat verilerini zamanında senkronize etmek için ayarlara sahiptir.

Modernize edilmiş grafik yapı türü, şek. 2:

Şek.2 Dört fiyat türüne göre değiştirilmiş grafik

Şek.2 Dört fiyat türüne göre değiştirilmiş grafik

Modernize edilmiş yapı, farklı fiyat türlerine ait dört Üç Satır Kesme grafiğini birleştirdiğinden, fiyatlar arasında tutarsızlıklar bulmak doğaldır. Bunu önlemek için, zamanında veri senkronizasyonu gereklidir. Fiyat senkronizasyonu iki varyasyonda gerçekleştirildi: tam (sağda şek. 2) ve kısmi (solda şek. 2). Tam senkronizasyon, tüm verilerin grafikte çizildiği ve eksik verilerin ayarlarda belirtilen öncelik fiyatları ile değiştirildiği, filtrelenmiş kısmi bir senkronizasyonu temsil eder. Tam senkronizasyon modunda, eksik veriler basitçe atlanır ve yalnızca eksiksiz bir veri setine sahip mum grafikler çizilir.

Diğer bir yenilik, sinyalleri bölme kolaylığı için tanıtılan bir nokta ayırıcıdır. Bildiğiniz gibi, grafik ayarlarında nokta ayırıcı etkinleştirilebilir. Göstergede, ayarlarda belirtilen zaman dilimine bağlı olarak değişir. Noktaların dikey kesikli bir çizgiyle ayrıldığı MetaTrader 5 adresindeki grafiklerden farklı olarak, bu göstergede çizgi rengi değiştirilerek yeni bir dönem temsil edilir (mumlar, şek. 3):

Şek.3 Göstergedeki dönem ayırıcılar

Şek.3 Göstergedeki dönem ayırıcılar

Diğer bir ekleme, ana grafikteki fiyatlara dayalı olarak oluşturulan ancak zamanında gösterge verileriyle senkronize edilen teknik gösterge iMA uygulamasıdır. Böylece veriler hareketli ortalamaya göre filtrelenir (şekil 4):

Şek.4 Dahili hareketli ortalama

Şek.4 Dahili hareketli ortalama

Gösterge ayrıca bir çizgi çizmek için noktalarda minimum hareket ve bir geri dönüş için gerekli çizgi sayısı ayarlama özelliğine sahiptir. Aynı zamanda bir filtre rolü vardır.


Göstergenin kodu

Göstergenin algoritması oldukça basittir ve üç aşamalıdır: verileri kopyalama, kopyalanan verilere dayalı hesaplama ve göstergenin tamponlarını doldurma (alınan verilere dayalı bir grafik oluşturma). Kod, kendi aralarında veya giriş verileriyle birbirine bağlanan işlevlere bölünmüştür. Şimdi kodu yakından inceleyelim.

1. Göstergenin giriş parametreleri

Göstergenin önsözü, grafik yapıların bir beyanını içerir. Göstergede bunlardan ikisi vardır: "ABCTB" grafiği (DRAW_COLOR_CANDLES) ve ek hareketli ortalama "LINE_TLB" (DRAW_LINE). Buna göre, altı arabellek vardır. Ardından, arayüz ayarlarını ve ayarların kendilerini geliştirmek için enum tipindeki verileri takip eder:

  • magic_numb - Sihirli numara uzun türündedir. Göstergeyi belirtmek için benzersiz bir sayıdır. Gerektiğinde birkaç değişiklikle dize tipine dönüştürülebilir;
  • time_frame - Hesaplama zaman aralığı, ENUM_TIMEFRAMES türü, ana parametredir (göstergenin zaman çerçevesi);
  • time_redraw - Grafik güncellemelerinin periyodu, ENUM_TIMEFRAMES türü. Bir grafiğin yeniden hesaplanmasının gerçekleştiği zaman dilimidir. Grafiğin hızlı bir şekilde yeniden çizilmesi için klavyedeki "R" tuşuna basın - göstergenin entegre kontrolü;
  • first_date_start - Başlangıç tarihi, tarih saat türü. Veri kopyalama ve grafik oluşturma için başlangıç noktası olan ana parametredir;
  • chart_price - Hesaplama için fiyat türü (0-Kapanış, 1-Açılış, 2-Yüksek, 3-Düşük). Klasik bir grafik yapısı için bir fiyat türü seçilmelidir. Daha önce de belirtildiği gibi, değiştirilmiş yapı etkinleştirildiğinde bu parametre yok sayılır;
  • step_min_f - Yeni bir sütun için minimum adım (>0, int türü) veya bir çizgi çizmek için gereken atlama;
  • line_to_back_f - Bir tersine çevirme görüntülenecek satır sayısı (>0, int türü). Klasik tip, bir geri dönüşü göstermek için üç satır önerir;
  • chart_type - Grafik oluşturma türü (0-klasik, 1-değiştirilmiş), seç türü. Yapı türleri arasında bir geçiştir;
  • chart_color_period - Yeni bir döneme başlarken renk değiştirme (Boole türü). Yeni dönem başında çizgi rengini değiştirmek için kullanılır;
  • chart_synchronization - Yalnızca tam senkronizasyondan sonra bir grafik oluşturma (Boole türü, doğru ise bir grafik oluşturmadan önce tüm eksik değerleri bırakarak tam bir senkronizasyon gerçekleşir);
  • chart_priority_close - Kapanış fiyatının önceliği (seçim türünün dört varyasyonu vardır. Kısmi senkronizasyonda kapanış fiyatının önceliğine işaret eder ve tam senkronizasyonda yok sayılır;
  • chart_priority_open - Açılış fiyatının önceliği. Aynısı burada da geçerlidir;
  • chart_priority_high - Maksimum fiyatın önceliği. Aynısı burada da geçerlidir;
  • chart_priority_low - Minimum fiyatın önceliği. Aynısı burada da geçerlidir;
  • ma_draw - Ortalamayı çizin (Boole türü, doğru ise hareketli ortalama çizin);
  • ma_price - Ortalamayı oluşturmak için fiyat türü, bir ENUM_APPLIED_PRICE olabilir;
  • ma_method - Yapı türü, bir ENUM_MA_METHOD olabilir;
  • ma_period - Hareketli ortalamanın ortalama dönemi;

Ardından, hesaplama için gerekli olan arabellek dizilerini, değişkenleri ve yapıları bildiririz.

//+------------------------------------------------------------------+
//|                                                        ABCTB.mq5 |
//|                                 "Azotskiy Aktiniy ICQ:695710750" |
//|                        "" |
//+------------------------------------------------------------------+
// ABCTB - Auto Build Chart Three Line Break
#property copyright "Azotskiy Aktiniy ICQ:695710750"
#property link      ""
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 6
#property indicator_plots   2
//--- plot ABCTB
#property indicator_label1  "ABCTB"
#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1  clrBlue,clrRed,clrGreenYellow
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot LINE_TLB
#property indicator_label2  "LINE_TLB"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- Price type for calculation
enum type_price
  {
   close=0, // Close
   open=1,  // Open
   high=2,  // Hight
   low=3,   // Low
  };
//--- type of chart construction
enum type_build
  {
   classic=0,  // Classic
   modified=1, // Modified
  };
//--- priority
enum priority
  {
   highest_t=4, // Highest
   high_t=3,    // High
   medium_t=2,  // Medium
   low_t=1,     // Low
  };
//--- input parameters
input long               magic_numb=65758473787389;                // Magic number
input ENUM_TIMEFRAMES    time_frame=PERIOD_CURRENT;                // Calculation time range
input ENUM_TIMEFRAMES    time_redraw=PERIOD_M1;                    // Period of chart updates
input datetime           first_date_start=D'2013.03.13 00:00:00';  // Start date
input type_price         chart_price=close;                        // Price type for calculation (0-Close, 1-Open, 2-High, 3-Low)
input int                step_min_f=4;                             // Minimum step for a new column (>0)
input int                line_to_back_f=3;                         // Number of lines to display a reversal(>0)
input type_build         chart_type=classic;                       // Type of chart construction (0-classic, 1-modified)
input bool               chart_color_period=true;                  // Changing color for a new period
input bool               chart_synchronization=true;               // Constructing a chart only upon complete synchronization
input priority           chart_priority_close=highest_t;           // Priority of the closing price
input priority           chart_priority_open=highest_t;            // Priority of the opening price
input priority           chart_priority_high=highest_t;            // Priority of the maximum price
input priority           chart_priority_low=highest_t;             // Priority of the minimum price
input bool               ma_draw=true;                             // Draw the average
input ENUM_APPLIED_PRICE ma_price=PRICE_CLOSE;                     // Price type for constructing the average
input ENUM_MA_METHOD     ma_method=MODE_EMA;                       // Construction type
input int                ma_period=14;                             // Averaging period
//--- indicator buffers
//--- buffer of the chart
double         ABCTBBuffer1[];
double         ABCTBBuffer2[];
double         ABCTBBuffer3[];
double         ABCTBBuffer4[];
double         ABCTBColors[];
//--- buffer of the average
double         LINE_TLBBuffer[];
//--- variables
MqlRates rates_array[];// bar data array for analysis
datetime date_stop;    // current date
datetime date_start;   // start date variable for calculation
//+------------------------------------------------------------------+
//| Struct Line Price                                                |
//+------------------------------------------------------------------+
struct line_price// structure for storing information about the past lines
  {
   double            up;  // value of the high price
   double            down;// value of the low price
  };
//+------------------------------------------------------------------+
//| Struct Line Information                                          |
//+------------------------------------------------------------------+
struct line_info// structure for storing information about the shared lines
  {
   double            up;
   double            down;
   char              type;
   datetime          time;
  };
line_info line_main_open[];  // data on the opening prices chart
line_info line_main_high[];  // data on the maximum prices chart
line_info line_main_low[];   // data on the minimum prices chart
line_info line_main_close[]; // data on the closing prices chart
//+------------------------------------------------------------------+
//| Struct Buffer Info                                               |
//+------------------------------------------------------------------+
struct buffer_info// structure for storing data for filling a buffer
  {
   double            open;
   double            high;
   double            low;
   double            close;
   char              type;
   datetime          time;
  };
buffer_info data_for_buffer[];// data for filling the modified construction buffer
datetime array_datetime[];    // array for storing information of the time for every line
int time_array[3];            // array for the function func_date_color
datetime time_variable;       // variable for the function func_date_color
bool latch=false;             // variable-latch for the function func_date_color
int handle;                   // handle of the indicator iMA
int step_min;                 // variable of the minimum step
int line_to_back;             // variable of the number of lines to display a reversal

2. OnInit İşlevi 

Tüm gösterge arabellekleri, OnInit işlevinde bildirilir ve dizi göstergesi, bir zaman serisi gibi ayarlanır.

Daha sonra grafiğe yansımayacak olan gösterge değerlerini ayarlıyoruz, ad ayarlıyoruz, doğruluğu belirliyoruz ve grafiğe aşırı yüklendikçe mevcut değerleri kaldırıyoruz. Burada ayrıca iMA göstergesinin tutamağını ayarlıyoruz ve girilen verilerin doğruluğunu kontrol ediyoruz. Hata durumunda uygun mesaj yazdırılır ve minimum değer değiştirilir.

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
//--- buffers for a chart
   SetIndexBuffer(0,ABCTBBuffer1,INDICATOR_DATA);
   ArraySetAsSeries(ABCTBBuffer1,true);
   SetIndexBuffer(1,ABCTBBuffer2,INDICATOR_DATA);
   ArraySetAsSeries(ABCTBBuffer2,true);
   SetIndexBuffer(2,ABCTBBuffer3,INDICATOR_DATA);
   ArraySetAsSeries(ABCTBBuffer3,true);
   SetIndexBuffer(3,ABCTBBuffer4,INDICATOR_DATA);
   ArraySetAsSeries(ABCTBBuffer4,true);
   SetIndexBuffer(4,ABCTBColors,INDICATOR_COLOR_INDEX);
   ArraySetAsSeries(ABCTBColors,true);
//--- buffer for constructing the average
   SetIndexBuffer(5,LINE_TLBBuffer,INDICATOR_DATA);
   ArraySetAsSeries(LINE_TLBBuffer,true);
//--- set the values that are not going to be reflected on the chart
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0); // for the chart
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0); // for the average
//--- set the indicator appearance
   IndicatorSetString(INDICATOR_SHORTNAME,"ABCTB "+IntegerToString(magic_numb)); // name of the indicator
//--- accuracy of display
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
//--- prohibit displaying the results of the indicator current value
   PlotIndexSetInteger(0,PLOT_SHOW_DATA,false);
   PlotIndexSetInteger(1,PLOT_SHOW_DATA,false);
//---
   handle=iMA(_Symbol,time_frame,ma_period,0,ma_method,ma_price);
   if(step_min_f<1)
     {
      step_min=1;
      Alert("Minimum step for a new column must be greater than zero");
     }
   else step_min=step_min_f;
//---
   if(line_to_back_f<1)
     {
      line_to_back=1;
      Alert("The number of lines to display a reversal must be greater than zero");
     }
   else line_to_back=line_to_back_f;
//---
   return(INIT_SUCCEEDED);
  }

3. Veri kopyalama işlevi

Gösterge, dört fiyat türünün tamamıyla çalışmak üzere tasarlandığından, zaman dahil tüm verilerin kopyalanması esastır. MQL5 içinde MqlRates adında bir yapı var. Bir alım satım oturumunun başlama zamanı, fiyatlar, hacimler ve alış satış farkı hakkında bilgi depolamak için kullanılır.

İşlevin giriş parametreleri başlangıç ve bitiş tarihi, zaman dilimi ve MqlRates türünün hedef dizisidir. Kopyalama başarılı olursa işlev doğru değerini döndürür. Veriler bir ara diziye kopyalanır. Hesaplanan eksik veriler ve bir oturum burada kopyalanır ve veriler kalıcı olarak yenilenir. Ara diziye kopyalama başarılıysa işlevin doğru çalışmasını sağlamak için veriler diziye kopyalanır ve iletilir.

//+------------------------------------------------------------------+
//| Func All Copy                                                    |
//+------------------------------------------------------------------+
bool func_all_copy(MqlRates &result_array[],// response array
                   ENUM_TIMEFRAMES period,  // timeframe
                   datetime data_start,     // start date
                   datetime data_stop)      // end date
  {
//--- declaration of auxiliary variables
   bool x=false;       // variable for the function response
   int result_copy=-1; // copied data count
//--- adding variables and arrays for calculation
   static MqlRates interim_array[]; // temporary dynamic array for storing copied data
   static int bars_to_copy;         // number of bars for copying
   static int bars_copied;          // number of copied bars since the start date
//--- find out the current number of bars in the time range
   bars_to_copy=Bars(_Symbol,period,data_start,data_stop);
//--- count the number of bars to be copied
   bars_to_copy-=bars_copied;
//--- if it is not the first time when data is being copied
   if(bars_copied>0)
     {
      bars_copied--;
      bars_to_copy++;
     }
//--- change the size of the receiving array
   ArrayResize(interim_array,bars_to_copy);
//--- copy data to a temporary array
   result_copy=CopyRates(_Symbol,period,0,bars_to_copy,interim_array);
//--- check the result of copying data
   if(result_copy!=-1) // if copying to the temporary array was successful
     {
      ArrayCopy(result_array,interim_array,bars_copied,0,WHOLE_ARRAY); // copy the data from the temporary array to the main one
      x=true;                   // assign the positive response to the function
      bars_copied+=result_copy; // increase the value of the copied data
     }
//---
   return(x);
  }

4. Veri hesaplama işlevi

Bu işlev, Üç Satır Kesme grafiğinin klasik yapısı için veri hesaplamanın bir prototipidir. Daha önce belirtildiği gibi, işlev yalnızca verileri hesaplar ve bunları kodun başında bildirilen line_info yapı türünün özel bir dizisine dönüştürür.

Bu işlev, diğer iki işlevi içerir: func_regrouping (yeniden gruplandırma işlevi) ve func_insert (işlev ekleme). Başlangıç için onlara bir göz atacağız:

4.1. Yeniden gruplandırma işlevi

Bu işlev, aynı yöndeki ardışık çizgiler hakkındaki bilgileri yeniden gruplandırıyor. İçine geçirilen dizinin boyutuyla veya daha kesin olmak gerekirse gösterge ayarlarından line_to_back_f parametresi (bir geri dönüşü gösterecek satır sayısı) ile sınırlıdır. Bu nedenle, kontrol işleve her geçtiğinde, aynı hatlar hakkında alınan tüm veriler sona doğru bir nokta aşağı hareket eder ve 0 indeksi yeni bir değerle doldurulur.

Bir ara için gerekli olan satırlar hakkındaki bilgiler bu şekilde depolanır (klasik yapı durumunda kesmenin üç satırı vardır).

//+------------------------------------------------------------------+
// Func Regrouping                                                   |
//+------------------------------------------------------------------+
void func_regrouping(line_price &input_array[],// array for regrouping
                     double new_price,         // new price value
                     char type)                // type of movement
  {
   int x=ArraySize(input_array);// find out the size of the array for regrouping
   for(x--; x>0; x--)           // regrouping loop
     {
      input_array[x].up=input_array[x-1].up;
      input_array[x].down=input_array[x-1].down;
     }
   if(type==1)
     {
      input_array[0].up=new_price;
      input_array[0].down=input_array[1].up;
     }
   if(type==-1)
     {
      input_array[0].down=new_price;
      input_array[0].up=input_array[1].down;
     }
  }

 4.2. İşlev ekleme

 İşlev, değerlerin yanıt dizisine eklenmesini gerçekleştirir. Kod basittir ve ayrıntılı açıklama gerektirmez. 

//+------------------------------------------------------------------+
// Func Insert                                                       |
//+------------------------------------------------------------------+
void func_insert(line_info &line_m[],  // target array
                 line_price &line_i[], // source array
                 int index,            // array element being inserted
                 char type,            // type of the target column
                 datetime time)        // date
  {
   line_m[index].up=line_i[0].up;
   line_m[index].down=line_i[0].down;
   line_m[index].type=type;
   line_m[index].time=time;
  }

Verileri hesaplama işlevi geleneksel olarak üç bölüme ayrılmıştır. İlk kısım, analiz altındaki verileri anahtar operatörünün yardımıyla bir ara diziye kopyalar. Sadece ilgili fiyat kopyalanır. İkinci kısım, veri dizisindeki gerekli alanı hesaplamak için bir test çalıştırması yapar. Daha sonra, başlangıçta yanıt için işleve geçirilen line_main_array[] veri dizisi bir değişikliğe uğrar. Üçüncü kısım ise ayarlanan veri dizisini doldurur.

//+------------------------------------------------------------------+
//| Func Build Three Line Break                                      |
//+------------------------------------------------------------------+
void func_build_three_line_break(MqlRates &input_array[],      // array for analysis
                                 char price_type,              // type of the price under analysis (0-Close, 1-Open, 2-High, 3-Low)
                                 int min_step,                 // minimum step for drawing a line
                                 int line_back,                // number of lines for a reversal
                                 line_info &line_main_array[]) // array for return (response) of the function
  {
//--- calculate the size of the array for analysis
   int array_size=ArraySize(input_array);
//--- extract data required for calculation to an intermediate array
   double interim_array[];// intermediate array
   ArrayResize(interim_array,array_size);// adjust the intermediate array to the size of the data
   switch(price_type)
     {
      case 0: // Close
        {
         for(int x=0; x<array_size; x++)
           {
            interim_array[x]=input_array[x].close;
           }
        }
      break;
      case 1: // Open
        {
         for(int x=0; x<array_size; x++)
           {
            interim_array[x]=input_array[x].open;
           }
        }
      break;
      case 2: // High
        {
         for(int x=0; x<array_size; x++)
           {
            interim_array[x]=input_array[x].high;
           }
        }
      break;
      case 3: // Low
        {
         for(int x=0; x<array_size; x++)
           {
            interim_array[x]=input_array[x].low;
           }
        }
      break;
     }
//--- enter the variables for storing information about current situation
   line_price passed_line[];// array for storing information about the latest prices of the lines (type structure line_price)
   ArrayResize(passed_line,line_back+1);
   int line_calc=0;// number of lines
   int line_up=0;// number of the last ascending lines
   int line_down=0;// number of the last descending lines
   double limit_up=0;// upper limit necessary to pass
   double limit_down=0;// lower limit necessary to pass
/* Fill variables informing of the current situation with the first values */
   passed_line[0].up=interim_array[0];
   passed_line[0].down=interim_array[0];
//--- start the first loop to calculate received data for filling a buffer for drawing
   for(int x=0; x<array_size; x++)
     {
      if(line_calc==0)// no lines have been drawn
        {
         limit_up=passed_line[0].up;
         limit_down=passed_line[0].down;
         if(interim_array[x]>=limit_up+min_step*_Point)// the upper limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],1);// regroup
            line_calc++;// update the line counter
            line_up++;
           }
         if(interim_array[x]<=limit_down-min_step*_Point)// the lower limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],-1);// regroup
            line_calc++;// update the line counter
            line_down++;
           }
        }
      if(line_up>line_down)// last ascending line (lines)
        {
         limit_up=passed_line[0].up;
         limit_down=passed_line[(int)MathMin(line_up,line_back-1)].down;
         if(interim_array[x]>=limit_up+min_step*_Point)// the upper limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],1);// regroup
            line_calc++;// update the line counter
            line_up++;
           }
         if(interim_array[x]<limit_down)// the lower limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],-1);// regroup
            line_calc++;// update the line counter
            line_up=0;
            line_down++;
           }
        }
      if(line_down>line_up)// last descending line (lines)
        {
         limit_up=passed_line[(int)MathMin(line_down,line_back-1)].up;
         limit_down=passed_line[0].down;
         if(interim_array[x]>limit_up)// the upper limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],1);// regroup
            line_calc++;// update the line counter
            line_down=0;
            line_up++;
           }
         if(interim_array[x]<=limit_down-min_step*_Point)// the lower limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],-1);// regroup
            line_calc++;// update the line counter
            line_down++;
           }
        }
     }
   ArrayResize(line_main_array,line_calc);// change the size of the target array
//--- zeroise variables and fill with the the initial data
   line_calc=0;
   line_up=0;
   line_down=0;
   passed_line[0].up=interim_array[0];
   passed_line[0].down=interim_array[0];
//--- start the second loop to fill a buffer for drawing
   for(int x=0; x<array_size; x++)
     {
      if(line_calc==0)// no lines have been drawn
        {
         limit_up=passed_line[0].up;
         limit_down=passed_line[0].down;
         if(interim_array[x]>=limit_up+min_step*_Point)// the upper limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],1);// regroup
            func_insert(line_main_array,passed_line,line_calc,1,input_array[x].time);
            line_calc++;// update the line counter
            line_up++;
           }
         if(interim_array[x]<=limit_down-min_step*_Point)// the lower limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],-1);// regroup
            func_insert(line_main_array,passed_line,line_calc,-1,input_array[x].time);
            line_calc++;// update the line counter
            line_down++;
           }
        }
      if(line_up>line_down)// last ascending line (lines)
        {
         limit_up=passed_line[0].up;
         limit_down=passed_line[(int)MathMin(line_up,line_back-1)].down;
         if(interim_array[x]>=limit_up+min_step*_Point)// the upper limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],1);// regroup
            func_insert(line_main_array,passed_line,line_calc,1,input_array[x].time);
            line_calc++;// update the line counter
            line_up++;
           }
         if(interim_array[x]<limit_down)// the lower limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],-1);// regroup
            func_insert(line_main_array,passed_line,line_calc,-1,input_array[x].time);
            line_calc++;// update the line counter
            line_up=0;
            line_down++;
           }
        }
      if(line_down>line_up)// last descending line (lines)
        {
         limit_up=passed_line[(int)MathMin(line_down,line_back-1)].up;
         limit_down=passed_line[0].down;
         if(interim_array[x]>limit_up)// the upper limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],1);// regroup
            func_insert(line_main_array,passed_line,line_calc,1,input_array[x].time);
            line_calc++;// update the line counter
            line_down=0;
            line_up++;
           }
         if(interim_array[x]<=limit_down-min_step*_Point)// the lower limit has been passed
           {
            func_regrouping(passed_line,interim_array[x],-1);// regroup
            func_insert(line_main_array,passed_line,line_calc,-1,input_array[x].time);
            line_calc++;// update the line counter
            line_down++;
           }
        }
     }
  }

5. Grafik oluşturma işlevi

Bu işlevin amacı, seçilen yapı parametresine (klasik veya değiştirilmiş) dayalı bir çizelge için verileri hesaplamak ve gösterge arabelleğini görüntülenecek verilerle doldurmaktır. Önceki işlevin yanı sıra, çizelge oluşturma işlevinin üç ek işlevi vardır. Bunlar rengin işlevi, senkronizasyon işlevi ve hareketli ortalamanın işlevidir. Bunları daha ayrıntılı olarak tartışalım.

5.1. Renk işlevi

Bu işlevin yalnızca bir giriş parametresi vardır - zaman. İşlevin yanıtı bir boole değişkenidir. Geçirilen veri dönemin sınırıysa işlev doğru değerini döndürür. Dönemler, seçilen zaman çerçevesine bağlı olduğundan, işlevin koşullu işleci eğer tarafından yerleşik bir dönem ayrımı vardır. Dönem seçildikten sonra henüz yeni bir dönemin başlayıp başlamadığı kontrol edilir. Bir tarihin MqlDateTime yapısına dönüştürülmesi ve karşılaştırma yoluyla yapılır. H2'ye kadar ve H2 dahil zaman dilimi için, tarih değerindeki değişiklikler yeni bir dönemin başladığını gösterir. H12'den D1'e kadar olan zaman dilimleri, aylardaki değişiklikleri gösterir ve W1 ile MN arasındaki değişikliği yıl içinde kontrol ederiz.

Ne yazık ki MqlDateTime yapısı mevcut hafta hakkında bilgi içermiyor. Bu sorun, time_variable değişkeni tarafından temsil edilen bir başlangıç noktası yaratılarak çözüldü. Ayrıca, bu tarihten bir haftadaki birkaç saniye düşülür.

//+------------------------------------------------------------------+
// Func Date Color                                                   |
//+------------------------------------------------------------------+
bool func_date_color(datetime date_time) // input date
  {
   bool x=false;// response variable
   int seconds=PeriodSeconds(time_frame);// find out the calculation time range
   MqlDateTime date;
   TimeToStruct(date_time,date);// convert data
   if(latch==false) // check the state of the latch
     {
      MqlDateTime date_0;
      date_0=date;
      date_0.hour=0;
      date_0.min=0;
      date_0.sec=0;
      int difference=date_0.day_of_week-1;
      datetime date_d=StructToTime(date_0);
      date_d=date_d-86400*difference;
      time_variable=date_d;
      latch=true;// lock the latch
     }
   if(seconds<=7200)// period is less than or equal to H2
     {
      if(time_array[0]!=date.day)
        {
         x=true;
         time_array[0]=date.day;
        }
     }
   if(seconds>7200 && seconds<=43200)// period is greater than H2 but less than or equal to H12
     {
      if(time_variable>=date_time)
        {
         x=true;
         time_variable=time_variable-604800;
        }
     }
   if(seconds>43200 && seconds<=86400)// period is greater than H12 but less than or equal to D1
     {
      if(time_array[1]!=date.mon)
        {
         x=true;
         time_array[1]=date.mon;
        }
     }
   if(seconds>86400)// period W1 or MN
     {
      if(time_array[2]!=date.year)
        {
         x=true;
         time_array[2]=date.year;
        }
     }
   return(x);
  }

5.2. Senkronizasyon işlevi

Senkronizasyon fonksiyonunun altı giriş parametresi vardır: bunlardan dördü fiyatların önceliği, tam veya kısmi senkronizasyonun boole parametresi ve analiz edilen dizinin kendisidir. İşlev iki bölüme ayrılmıştır: tam ve kısmi senkronizasyon durumu.

Tam senkronizasyon üç aşamada gerçekleştirilir:

  1. Dört fiyat türünün tamamında veri içerme koşulunu sağlayan dizi öğelerinin hesaplanması.
  2. Öğeleri aynı koşul altında bir ara diziye kopyalama.
  3. Ara diziden parametreler tarafından geçirilen diziye kopyalama.

Kısmi senkronizasyon daha karmaşıktır.

Geçilen tek boyutlu yapı dizisi, ilk endeksin talimatı ve ikinci fiyat türünü gösterdiği iki boyutlu diziye dönüştürülür. Daha sonra tanıtılan dört öğeli tek boyutlu bir dizidir. Fiyat öncelik seviyeleri bu diziye kopyalanır ve ardından dizi, öncelik talimatını belirlemek için sıralanır. Daha sonra için döngüsünü ve eğer koşullu operatörünü kullanarak önceliklere göre dağıtım yaparız. Aynı zamanda, öncelikler eşitse fiyat sıralaması şu şekildedir: kapanış, açılış, yüksek, düşük. eğer operatörü ilk öncelikli değeri bulur bulmaz, için döngüsü önceden oluşturulmuş iki boyutlu dizideki tüm sıfır verileri öncelikli olanlar vb. ile değiştirir.

//+------------------------------------------------------------------+
// Func Synchronization                                              |
//+------------------------------------------------------------------+
void func_synchronization(buffer_info &info[],
                          bool synchronization,
                          char close,
                          char open,
                          char high,
                          char low)
  {
   if(synchronization==true)// carry out a complete synchronization
     {
      int calc=0;// count variable
      for(int x=0; x<ArraySize(info); x++)// count complete data
        {
         if(info[x].close!=0 && info[x].high!=0 && info[x].low!=0 && info[x].open!=0)calc++;
        }
      buffer_info i_info[];    // enter a temporary array for copying
      ArrayResize(i_info,calc);// change the size of the temporary array
      calc=0;
      for(int x=0; x<ArraySize(info); x++)// copy data into the temporary array
        {
         if(info[x].close!=0 && info[x].high!=0 && info[x].low!=0 && info[x].open!=0)
           {
            i_info[calc]=info[x];
            calc++;
           }
        }
      ZeroMemory(info);        // clear the target array
      ArrayResize(info,calc);  // change the size of the main array
      for(int x=0; x<calc; x++)// copy data from the temporary array to the main one
        {
         info[x]=i_info[x];
        }
     }
   if(synchronization==false)  // change zero values to priority ones
     {
      int size=ArraySize(info); // measure the size of the array
      double buffer[][4];       // create a temporary array for calculation
      ArrayResize(buffer,size); // change the size of the temporary array
      for(int x=0; x<size; x++) // copy data into the temporary array
        {
         buffer[x][0]=info[x].close;
         buffer[x][1]=info[x].open;
         buffer[x][2]=info[x].high;
         buffer[x][3]=info[x].low;
        }
      char p[4];// enter an array for sorting by the order
      p[0]=close; p[1]=open; p[2]=high; p[3]=low;// assign variables for further sorting
      ArraySort(p); // sort
      int z=0,v=0;  // initialize frequently used variables
      for(int x=0; x<4; x++)// taking into account the results of the sorting, look through all variables and substitute them according to the priority
        {
         if(p[x]==close)// priority is for the closing prices
           {
            for(z=0; z<size; z++)
              {
               for(v=1; v<4; v++)
                 {
                  if(buffer[z][v]==0)buffer[z][v]=buffer[z][0];
                 }
              }
           }
         if(p[x]==open)// priority is for the opening prices
           {
            for(z=0; z<size; z++)
              {
               for(v=0; v<4; v++)
                 {
                  if(v!=1 && buffer[z][v]==0)buffer[z][v]=buffer[z][1];
                 }
              }
           }
         if(p[x]==high)// priority is for the maximum prices
           {
            for(z=0; z<size; z++)
              {
               for(v=0; v<4; v++)
                 {
                  if(v!=2 && buffer[z][v]==0)buffer[z][v]=buffer[z][2];
                 }
              }
           }
         if(p[x]==low)// priority is for the minimum prices
           {
            for(z=0; z<size; z++)
              {
               for(v=0; v<3; v++)
                 {
                  if(buffer[z][v]==0)buffer[z][v]=buffer[z][3];
                 }
              }
           }
        }
      for(int x=0; x<size; x++)// copy data from the temporary array back
        {
         info[x].close=buffer[x][0];
         info[x].open=buffer[x][1];
         info[x].high=buffer[x][2];
         info[x].low=buffer[x][3];
        }
     }
  }

5.3. Hareketli ortalamanın işlevi

En basit fonksiyondur. OnInit işlevinde alınan gösterge tutamağını kullanarak, işlevin parametrelerinde geçirilen tarihe karşılık gelen değeri kopyalarız. Daha sonra bu değer, bu fonksiyona yanıt olarak döndürülür.

//+------------------------------------------------------------------+
// Func MA                                                           |
//+------------------------------------------------------------------+
double func_ma(datetime date)
  {
   double x[1];
   CopyBuffer(handle,0,date,1,x);
   return(x[0]);
  }

Bir grafiği çizme işlevi geleneksel olarak iki bölüme ayrılır: klasik çizim ve değiştirilmiş olan. İşlevin iki girdi parametresi vardır: yapı için fiyat türü (değiştirilmiş yapı sırasında göz ardı edilir) ve yapı tipi (klasik ve değiştirilmiş).

En başta gösterge arabellekleri temizlenir ve daha sonra yapının türüne bağlı olarak iki kısma ayrılır. İlk bölüm (değiştirilmiş yapıdan bahsediyoruz), dört fiyat türünün tümünü hesaplama işlevini çağırmakla başlar. Ardından, veri hesaplama işlevini çağırırken alınan, kullanımdaki verileri kopyaladığımız ortak bir veri dizisi oluştururuz. Daha sonra alınan veri dizisi sıralanır ve çoğaltılan verilerden temizlenir. Bundan sonra, global düzeyde bildirilen data_for_buffer[] dizisi, aşağıdaki veri senkronizasyonu ile ardışık tarihlere göre doldurulur. Doldurma göstergesi arabellekleri, değiştirilmiş yapının son aşamasıdır.

İkinci kısım (klasik yapı) çok daha basittir. İlk önce veri hesaplama işlevi çağrılır ve ardından gösterge arabellekleri doldurulur.

//+------------------------------------------------------------------+
//| Func Chart Build                                                 |
//+------------------------------------------------------------------+
void func_chart_build(char price, // price type for chart construction
                      char type)  // type of chart construction
  {
//--- Zeroise the buffers
   ZeroMemory(ABCTBBuffer1);
   ZeroMemory(ABCTBBuffer2);
   ZeroMemory(ABCTBBuffer3);
   ZeroMemory(ABCTBBuffer4);
   ZeroMemory(ABCTBColors);
   ZeroMemory(LINE_TLBBuffer);
   if(type==1)// construct a modified chart (based on all price types)
     {
      func_build_three_line_break(rates_array,0,step_min,line_to_back,line_main_close);// data on closing prices
      func_build_three_line_break(rates_array,1,step_min,line_to_back,line_main_open);// data on opening prices
      func_build_three_line_break(rates_array,2,step_min,line_to_back,line_main_high);// data on maximum prices
      func_build_three_line_break(rates_array,3,step_min,line_to_back,line_main_low);// data on minimum prices
      //--- calculate data arrays
      int line_main_calc[4];
      line_main_calc[0]=ArraySize(line_main_close);
      line_main_calc[1]=ArraySize(line_main_open);
      line_main_calc[2]=ArraySize(line_main_high);
      line_main_calc[3]=ArraySize(line_main_low);
      //--- gather the date array
      int all_elements=line_main_calc[0]+line_main_calc[1]+line_main_calc[2]+line_main_calc[3];// find out the number of all elements
      datetime datetime_array[];// enter the array for copying
      ArrayResize(datetime_array,all_elements);
      int y[4];
      ZeroMemory(y);
      for(int x=0;x<ArraySize(datetime_array);x++)// copy data into the array
        {
         if(x<line_main_calc[0])
           {
            datetime_array[x]=line_main_close[y[0]].time;
            y[0]++;
           }
         if(x<line_main_calc[0]+line_main_calc[1] && x>=line_main_calc[0])
           {
            datetime_array[x]=line_main_open[y[1]].time;
            y[1]++;
           }
         if(x<line_main_calc[0]+line_main_calc[1]+line_main_calc[2] && x>=line_main_calc[0]+line_main_calc[1])
           {
            datetime_array[x]=line_main_high[y[2]].time;
            y[2]++;
           }
         if(x>=line_main_calc[0]+line_main_calc[1]+line_main_calc[2])
           {
            datetime_array[x]=line_main_low[y[3]].time;
            y[3]++;
           }
        }
      ArraySort(datetime_array);// sort the array
      //--- delete replicated data from the array
      int good_info=1;
      for(int x=1;x<ArraySize(datetime_array);x++)// count useful information
        {
         if(datetime_array[x-1]!=datetime_array[x])good_info++;
        }
      ArrayResize(array_datetime,good_info);
      array_datetime[0]=datetime_array[0];// copy the first element as it is the pattern in the beginning of comparison
      good_info=1;
      for(int x=1;x<ArraySize(datetime_array);x++)// fill the new array with useful data
        {
         if(datetime_array[x-1]!=datetime_array[x])
           {
            array_datetime[good_info]=datetime_array[x];
            good_info++;
           }
        }
      //--- fill the buffer for drawing (colored candles)
      int end_of_calc[4];// variables of storing information about the last comparison
      ZeroMemory(end_of_calc);
      ZeroMemory(data_for_buffer);
      ArrayResize(data_for_buffer,ArraySize(array_datetime));// change the size of the declared global array for storing data before passing it to a buffer
      for(int x=0; x<ArraySize(array_datetime); x++)
        {
         data_for_buffer[x].time=array_datetime[x];
         for(int s=end_of_calc[0]; s<line_main_calc[0]; s++)
           {
            if(array_datetime[x]==line_main_close[s].time)
              {
               end_of_calc[0]=s;
               if(line_main_close[s].type==1)data_for_buffer[x].close=line_main_close[s].up;
               else data_for_buffer[x].close=line_main_close[s].down;
               break;
              }
           }
         for(int s=end_of_calc[1]; s<line_main_calc[1]; s++)
           {
            if(array_datetime[x]==line_main_open[s].time)
              {
               end_of_calc[1]=s;
               if(line_main_open[s].type==1)data_for_buffer[x].open=line_main_open[s].down;
               else data_for_buffer[x].open=line_main_open[s].up;
               break;
              }
           }
         for(int s=end_of_calc[2]; s<line_main_calc[2]; s++)
           {
            if(array_datetime[x]==line_main_high[s].time)
              {
               end_of_calc[2]=s;
               data_for_buffer[x].high=line_main_high[s].up;
               break;
              }
           }
         for(int s=end_of_calc[3]; s<line_main_calc[3]; s++)
           {
            if(array_datetime[x]==line_main_low[s].time)
              {
               end_of_calc[3]=s;
               data_for_buffer[x].low=line_main_low[s].down;
               break;
              }
           }
        }
      //--- start the function of synchronizing data
      func_synchronization(data_for_buffer,chart_synchronization,chart_priority_close,chart_priority_open,chart_priority_high,chart_priority_low);
      //--- preparatory actions before starting the function func_date_color
      ZeroMemory(time_array);
      time_variable=0;
      latch=false;
      //--- fill the buffer for drawing candles
      for(int x=ArraySize(data_for_buffer)-1,z=0; x>=0; x--)
        {
         ABCTBBuffer1[z]=data_for_buffer[x].open;
         ABCTBBuffer2[z]=data_for_buffer[x].high;
         ABCTBBuffer3[z]=data_for_buffer[x].low;
         ABCTBBuffer4[z]=data_for_buffer[x].close;
         if(ABCTBBuffer1[z]<=ABCTBBuffer4[z])ABCTBColors[z]=0;
         if(ABCTBBuffer1[z]>=ABCTBBuffer4[z])ABCTBColors[z]=1;
         if(func_date_color(data_for_buffer[x].time)==true && chart_color_period==true)ABCTBColors[z]=2;
         if(ma_draw==true)LINE_TLBBuffer[z]=func_ma(data_for_buffer[x].time);
         z++;
        }
     }
   else// construct a classic chart (based on one price type)
     {
      func_build_three_line_break(rates_array,price,step_min,line_to_back,line_main_close);// find data on selected prices
      ArrayResize(array_datetime,ArraySize(line_main_close));
      //--- preparatory actions before starting the function func_date_color
      ZeroMemory(time_array);
      time_variable=0;
      latch=false;
      //--- the buffer for drawing candles
      for(int x=ArraySize(line_main_close)-1,z=0; x>=0; x--)
        {
         ABCTBBuffer1[z]=line_main_close[x].up;
         ABCTBBuffer2[z]=line_main_close[x].up;
         ABCTBBuffer3[z]=line_main_close[x].down;
         ABCTBBuffer4[z]=line_main_close[x].down;
         if(line_main_close[x].type==1)ABCTBColors[z]=0;
         else ABCTBColors[z]=1;
         if(func_date_color(line_main_close[x].time)==true && chart_color_period==true)ABCTBColors[z]=2;
         if(ma_draw==true)LINE_TLBBuffer[z]=func_ma(line_main_close[x].time);
         z++;
        }
     }
  }

6. Konsolidasyonun işlevi

Bu işlev, tüm kontrol göstergesi öğelerini birleştirir. Önce güncel tarih tanımlanır, ardından veri kopyalama işlevi ve grafik oluşturma işlevi çağrılır.

//+------------------------------------------------------------------+
//| Func Consolidation                                               |
//+------------------------------------------------------------------+
void func_consolidation()
  {
//--- defining the current date
   date_stop=TimeCurrent();
//--- copying data for analysis
   func_all_copy(rates_array,time_frame,first_date_start,date_stop);
//--- basic construction of the chart
   func_chart_build(chart_price,chart_type);
   ChartRedraw();
  }

7. Anahtar kontrollü ve otomatik kontrollü yapı işlevi

Bu işlevler, klavyedeki "R" tuşuna (OnChartEvent) basarak veya seçilen zaman aralığına göre (OnCalculate) otomatik hale getirerek göstergeyi yeniden çizmek için tasarlanmıştır. İkincisi, IsNewBar içinde açıklanan işlevin basitleştirilmiş bir versiyonu olan yeni çubuk işlevi (func_new_bar) tarafından analiz edilir.

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
//---
   if(func_new_bar(time_redraw)==true)
     {
      func_consolidation();
     };
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//--- event of a keystroke
   if(id==CHARTEVENT_KEYDOWN)
     {
      if(lparam==82) //--- the key "R" has been pressed
        {
         func_consolidation();
        }
     }
  }
//+------------------------------------------------------------------+
//| Func New Bar                                                     |
//+------------------------------------------------------------------+
bool func_new_bar(ENUM_TIMEFRAMES period_time)
  {
//---
   static datetime old_times; // variable of storing old values
   bool res=false;            // variable of the analysis result
   datetime new_time[1];      // time of a new bar
//---
   int copied=CopyTime(_Symbol,period_time,0,1,new_time); // copy the time of the last bar to the cell new_time
//---
   if(copied>0) // everything is ок. data copied
     {
      if(old_times!=new_time[0]) // if the old time of the bar is not equal to the new one
        {
         if(old_times!=0) res=true; // if it is not the first start, then new bar = true
         old_times=new_time[0];     // remember the time of the bar
        }
     }
//---
   return(res);
  }

Bu noktada göstergenin kodunu açıklamayı bitireceğiz ve bunu kullanmanın yolları hakkında konuşacağız.


Göstergeyi ve alım satım stratejisini kullanma örnekleri

Klasik grafik yapısına dayalı ana analiz stratejileriyle başlayalım.

1. Alım ve satım sinyalleri olarak beyaz ve siyah çizgiler

Kabaca iki kuraldan bahsedebiliriz:

  1. Kural №1: Art arda üç artan çizgi olduğunda satın alın ve art arda üç azalan çizgi olduğunda satın. Ardışık üç çizgi, görünen bir eğilimi gösterir.
  2. Kural №2: Geri dönüş çizgisi art arda üç artan çizginin altına düştüğünde satın, dönüş çizgisi art arda üç azalan çizgiden daha yüksek olduğunda satın alın.

2013'ün başından itibaren EURUSD H1 için klasik bir yapıyı temsil eden şekil 6'ya bakalım (analiz edilen zaman aralığı şek.5'te gösterilmiştir).

Şek.5 Analiz edilen zaman aralığı EURUSD H1

Şek.5 Analiz edilen zaman aralığı EURUSD H1

Şek.6 EURUSD H1 için Üç Satır Kesme grafiğinin klasik yapısı, 2013 başı, kapanış fiyatları

Fig.6 Şek.6 EURUSD H1 için Üç Satır Kesme grafiğinin klasik yapısı, 2013 başı, kapanış fiyatları

Grafikte (şekil 6) satış için bir başlangıç noktası olan 1 ve 2 noktaları arasındaki sinyali (kural №1) açıkça görebiliriz. Bu durumda kazanç, dört ondalık basamak için 200 puanın üzerindedir. Aşağıdaki nokta 4, satın alma için uygun bir durumu gösterir (kural №2'de olduğu gibi). 5. noktada kapanışta kar 40 puandı ve 6. noktada kapanışta başabaş noktasındayız.

6. noktada satma sinyali görebiliriz (kural №2). 7. noktada kapanırken 10 puan değerinde kar elde ederiz ve 8. noktada kapanırken başabaş noktası elde ederiz. 8. ve 9. noktalar, ne №1 kuralına ne de №2 kuralına uymadığından sinyal olarak kabul edilemez. 10. noktada satın alabiliriz (kural №1); ayrıca 11. noktada kapanışta 20 puan veya 12. noktada başabaş noktası elde edebiliriz. Tüm sayılar yuvarlandı.

En iyi senaryoda, bu stratejiyi kullanarak 270 puanlık kar elde edebiliriz, bu etkileyici bir sonuçtur. Aynı zamanda belirlenen zaman aralığında karı etkileyen yoğun bir hareket mevcut. En kötü senaryoda, alım satım başabaş ile sonuçlanabilir ve bu da kötü değildir.

Bir durum ya kural №1 ya da kural №2 ile karşılaştığında, eğilimle aynı yönde bir çizgi ile temsil edilen bir eğilimin tersine çevrilmesini beklememiz gerektiğini belirtmekte fayda var.

2. Eşit mesafeli kanal, destek ve dayanıklı hatlar

Başka bir alım satım stratejisi, Üç Satır Kesme grafiğine teknik analiz uygulamaktır. Şek. 7'ye bir göz atalım:

Şek. 7 Eşit mesafeli kanal, destek ve direnç hatları, GBPUSD H1, 01.03.2014 ile 01.05.2014 arasındaki zaman aralığı

Şek. 7 Eşit mesafeli kanal, destek ve direnç hatları, GBPUSD H1, 01.03.2014 ile 01.05.2014 arasındaki zaman aralığı

Şekil 7'de alçalan eşit mesafeli kanalın kırmızı çizgilerle, yükselen kanalın mavi çizgilerle ve destek ve direnç çizgilerinin siyah olarak çizildiğini görebilirsiniz. Burada, ilk direnç çizgisinin destek çizgisine dönüştüğü nettir.

3. Mum Grafik Formasyonları

2013'ün başında USDCAD çifti için M30 zaman diliminde değiştirilmiş bir grafik (iki satır arası) oldukça ilginç görünüyor.

Sinyallerini doğrulayan Japon mum kalıplarını ayırt edebiliriz (şek. 8).

Şek. 8 Değiştirilmiş Üç Satır Arası grafiği, USDCAD M30, 2013 başı, iki satır sonu

Şek. 8 Değiştirilmiş Üç Satır Arası grafiği, USDCAD M30, 2013 başı, iki satır sonu

Grafiğin başında, №1'in altında "Yutma"nın dönüş formasyonunun bir modelini görebiliriz. Bu iki mumdan oluşur: kırmızı ve bir önceki mavi. Yükselen trend çizgisinden sonra piyasa, tek mumlu bir geri dönüş formasyonu "Çekiç" olan 2 numaraya iner. Bu noktada piyasa yön değiştirir. Aynısı formasyon №3'te ("Dönen Tepe") olur. Aşağıdaki ters çevirme modeli "Kharami" (№4) mum çubuğu 4 ve yanında yükselen büyük mum grafiği ile gösterilmektedir. Model №6 aynı zamanda iki mum çubuğundan oluşur ("Yutulan" deseni), ancak ilk benzer modelden farklı olarak, piyasayı ters yöne çevirir.

Dolayısıyla, bu tür bir analizde göstergenin kullanılmasının kabul edilebilir olduğu ancak sinyallerin nadiren ortaya çıkması ve önemli bir düşüş olasılığı gibi dezavantajları olduğu sonucuna varılabilir. Bu stratejinin kesinlikle daha fazla geliştirilmesi gerekiyor.

4. Hareketli ortalama

Yalnızca çizilen çizgilere hareketli ortalama eklemek gibi kısmi değişiklikler, analiz için yeni fırsatlar sunar.

Şimdi şek. 9'a bir göz atalım:

Şek.9 Hareketli ortalama analizi, EURUSD H4, Üç Satır Kesme grafiği, klasik yapı, 01.01.2014 ile 01.07.2014 arası

Şek.9 Hareketli ortalama analizi, EURUSD H4, Üç Satır Kesme grafiği, klasik yapı, 01.01.2014 ile 01.07.2014 arası

Şek. 9'un alt kısmı hareketli ortalama ile yüksek fiyatlara dayalı klasik bir yapıyı göstermektedir (ortalama dönem 90, düşük fiyat, düzleştirilmiş ortalama). Üst kısım hareketli ortalama ile düşük fiyatlara dayalı klasik bir yapıyı göstermektedir (ortalama dönem 90, yüksek fiyat, düzleştirilmiş ortalama).

Dolayısıyla, şek. 9'un üst kısmında hareketli ortalama bir destek çizgisi ve alt kısımda ise tam tersine bir direnç çizgisi olarak kabul edilebilir. Her iki grafikte de fiyat ortalamanın altına düşerse piyasada düşüş eğilimi vardır ve satmak daha iyidir. Fiyat ortalamanın üzerine çıktığında satın alma zamanı gelmiştir. Bu stratejinin bir dezavantajı, uzun vadeli bir alım satım amaçlı olmasıdır.


Sonuç

Sonuç olarak, Üç Satır Kesme'nin sürekli olarak iyi sinyaller verdiğini veya daha kötü durumda, başabaş sonucuna yol açtığını söyleyebilirim. Uygulama, bunun en iyi uzun vadeli bir trendde uygulandığını gösteriyor ve bu nedenle, bu grafiği kısa vadeli bir alım satım için kullanmanızı önermiyorum. Alım satımda nasıl kullanılacağına dair yeni fikirleri olan varsa bunu tartışmaktan memnuniyet duyarım.

Genelde olduğu gibi, kodu ayrıntılı olarak keşfetmeye çalıştım. Ayrıca nasıl genişletileceğine, yeniden çalıştırılacağına veya optimize edileceğine dair fikirler varsa lütfen makalenin yorumlarını yazın.


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

Ekli dosyalar |
abctb.mq5 (68.78 KB)
Alım Satım Robotlarının Hikayeleri: Daha Az mı Daha Fazla mı? Alım Satım Robotlarının Hikayeleri: Daha Az mı Daha Fazla mı?
İki yıl önce "Son Haçlı Seferi"nde piyasa bilgilerini görüntülemek için oldukça ilginç ancak şu anda yaygın olarak kullanılmayan bir yöntem olan nokta ve şekil grafiklerini inceledik. Şimdi nokta ve şekil grafiğinde tespit edilen formasyonlara göre bir alım satım robotu yazmaya çalışmanızı öneririm.
SQL ve MQL5: SQLite Veritabanı ile Çalışmak SQL ve MQL5: SQLite Veritabanı ile Çalışmak
Bu makale, projelerinde SQL kullanmak isteyen geliştiricilere yöneliktir. SQLite'ın işlevselliğini ve avantajlarını açıklar. Makale, SQLite işlevleri hakkında özel bilgi gerektirmez, ancak SQL'in minimum düzeyde anlaşılması faydalı olacaktır.
Bir Sosyal Teknoloji Girişimi Kurmak, Bölüm I: MetaTrader 5 Sinyallerinizi Tweetleyin Bir Sosyal Teknoloji Girişimi Kurmak, Bölüm I: MetaTrader 5 Sinyallerinizi Tweetleyin
Bugün, EA'larınızın alım satım sinyallerini tweetleyebilmeniz için bir MetaTrader 5 terminalini Twitter ile nasıl bağlayacağınızı öğreneceğiz. PHP'de RESTful web servisine dayalı bir Sosyal Karar Destek Sistemi geliştiriyoruz. Bu fikir, bilgisayar destekli alım satım adı verilen belirli bir otomatik alım satım anlayışından gelmektedir. İnsan yatırımcılarının bilişsel yeteneklerinin, aksi takdirde Expert Advisor'lar tarafından otomatik olarak piyasaya sürülecek olan alım satım sinyallerini filtrelemesini istiyoruz.
Sinir Ağları Ucuz ve Neşeli - NeuroPro'yu MetaTrader 5 ile Bağlayın Sinir Ağları Ucuz ve Neşeli - NeuroPro'yu MetaTrader 5 ile Bağlayın
Alım satım için belirli sinir ağı programları pahalı ve karmaşık görünüyorsa veya tam tersine çok basitse NeuroPro'yu deneyin. Ücretsizdir ve amatörler için en uygun işlevsellik setini içerir. Bu makale size MetaTrader 5'in nasıl kullanılacağını anlatacaktır.