English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
Kagi Grafik Göstergesi

Kagi Grafik Göstergesi

MetaTrader 5Örnekler | 13 Ocak 2022, 16:59
245 0
Dmitriy Zabudskiy
Dmitriy Zabudskiy

Giriş

"Nokta ve Şekil Grafik Oluşturma Göstergesi" makalesi, Nokta ve şekil grafiğioluşturmanın programlama yollarından biri açıklamaktadır. Bu grafik 19. yüzyıldan beri bilinmektedir. Ancak, uzak geçmişten gelen tek grafik bu değildir. Finansal piyasa temsilinin ilk türlerinin bir başka kayda değer temsilcisi Kagi grafiğidir. Bu grafik bu makalede tartışılacaktır.

Menkul kıymetler borsası - 19. yüzyıl Japonya'sına aşina olmayan finans kurumu - Mayıs 1878'de kurulmuştur. Günümüzde Tokyo Menkul Kıymetler Borsası olarak bilinmektedir. Bu olay, Kagi grafiklerinin oluşturulmasında ve daha sonra geliştirilmesinde hayati bir rol oynamıştır. Avrupa ve ABD, 1994'te Steve Nison'ın aşağıdaki yayınının ardından Kagi grafiklerini öğrenmeye başlamıştır: "Beyond Candlesticks: New Japanese Charting Techniques Revealed".

Japonca "Kagi" kelimesi, grafik geliştirildiği sırada kullanılan L şeklinde bir anahtar anlamına gelir. Ayrıca, adın değiştirilmiş bir versiyonu var: "anahtar grafik". Steve Nison'ın "Beyond Candlesticks" isimli makalesinde, grafiğin alternatif adlarını da bulabilirsiniz: fiyat aralığı grafiği, kanca grafiği, delta veya zincir grafiği.

Bu grafikte bu kadar özel olan nedir? Başlıca özelliği, zaman ölçeğini yok sayarak yalnızca fiyatınkini bırakmasıdır (Japon mumlar, çubuklar ve çizgilerin aksine). Böylece, grafik, yalnızca en önemlilerini bırakarak önemsiz fiyat dalgalanmalarını gizler.

Grafik, piyasa durumuna göre birbirinin yerini alan bir dizi kalın Yang ve ince Yin çizgisini temsil eder. Piyasanın aynı yönde hareket etmesi durumunda çizgi genişletilerek yeni bir fiyat aralığına ulaşılır. Ancak piyasa geri döner ve önceden belirlenmiş bir miktara ulaşırsa, yeni sütunda Kagi çizgisi ters yönde çizilir. Önceden tanımlanmış miktar, nokta olarak (genellikle döviz çiftleri için kullanılır) veya mevcut fiyatın yüzde değeri olarak (genellikle hisse senetleri için kullanılır) belirlenir. Çizgi kalınlığı, en yakın Yüksek veya Düşük fiyat rekorlarına göre değişir.


1. Grafik oluşturma örneği

8 ila 11 Ekim tarihleri ​​arasında EURUSD, H1'e dair geçmiş verilerini kullanalım.

15 noktalık bir ters eşiği olan standart bir görüntüleme örneği Şekil 1'de gösterilmektedir:

Kagi grafiği, EURUSD H1

Şekil 1. Kagi grafiği, EURUSD H1

Gördüğümüz gibi fiyat 17:00'da düşmeye başladı. Aşağı yönlü hareket 21:00'a kadar devam etti. Saat 22:00'de fiyat 1,3566'dan yukarı doğru hareket ediyor ve 1,3574'te kapanıyor. Yani fiyat 11 noktadan geçiyor. Bu bir geri dönüş için yeterli değil, ancak yeni Düşük değerine de ulaşılamamış. Sonraki iki saat fiyat yatay seyrediyor ve son olarak 01:00'da (9 Ekim), 25 nokta (1,3591-1,3566) içeren 1,3591'de kapanan güçlü bir yukarı yönlü hareket görüyoruz. Bu, fiyatın yukarı ters çevrildiği anlamına gelir.

Yükseliş trendi takip eden saatte de devam ediyor. Fiyat, kalın Yang çizgisini güçlendirerek 1,3599'a ulaşıyor. Saat 03:00'da fiyat, önceki Yüksek Değerden (1,3599-1,3578) itibaren 21 nokta olan 1,3578'de keskin bir şekilde kapanıyor. Bu geri dönüş için fazlasıyla yeterli. Çizgi aşağı doğru hareket ediyor, ancak biçimini (kalın Yang çizgisi) koruyor.

Saat 16:00'ya kadar fiyat aşağı doğru hareket ediyor ve sonunda en yakın minimum değerini kırıyor ve kalın Yang'dan ince Yin çizgisine dönüyor. Daha önce bahsedilen 1,3566'lık Düşük değer burada bir rekor fiyat görevi görmüştür. Fiyat bir Yin çizgisi olarak hareket etmeye devam ediyor ve 23:00'da (9 Ekim) oluşan en yakın Yüksek değer 1,3524'ü kırarak 10 Ekim saat 14:00'da Yang olarak değişiyor. Bu küçük örnek, Kagi grafiğinin nasıl oluşturulduğunu gösterir.


2. Kagi Gösterge Grafik Oluşturma İlkesi

Göstergenin mevcut zaman aralığından bağımsız hale getirilmesi için göstergenin oluşturulması gereken zaman aralığına ait verilerin ayrı ayrı kopyalanması ve ardından elde edilen veriler kullanılarak göstergenin oluşturulmasına karar verilmiştir.

Bu, Kagi grafiklerinde teknik analizin sınırlarını genişleten tek bir grafik üzerinde aynı anda birkaç zaman aralığının incelenmesine olanak sağlar. Göstergenin kendisi ayrı bir pencerede bulunur, ancak verileri ana grafikte görüntülemek de mümkündür. Diğer bir deyişle, temel oluşum (standart veya değiştirilmiş görünüm) gösterge penceresinde gerçekleştirilir. Gösterge ana grafiğe kopyalanır, ayrıca fiyat ve zaman işaretleri (ayarlara bağlı olarak) çizilir.

Daha önce de belirtildiği gibi, gösterge, grafiği hem standart hem de değiştirilmiş versiyonda çizer. Standart olanı yukarıda açıklanmıştır. Şimdi, değiştirilmiş versiyonu ele alalım.

Yeni bir fikir mi bilmiyorum, ama böyle bir versiyonunu duymadım. Ek filtre fikri, yalnızca noktaların ters çevrilmesi değil, aynı zamanda grafiğin her hareketinin filtrelenmesidir. Diğer bir deyişle, yeni Yüksek veya Düşük değerlerin (omuz/bel ile karıştırılmamalıdır) oluşması için fiyatın belirli bir mesafe boyunca hareket etmesi gerekir. Genel olarak, fiyat nereye giderse gitsin, önce belirli bir mesafeyi kat etmelidir. Bundan sonra, bunun, trendin devamı mı yoksa tersi mi olduğu belirlenir.

Şekil 2, ilkenin nasıl çalıştığını göstermektedir. Değiştirilmiş grafik görünümü mavi, standart görünüm ise kırmızı renkte gösterilir. Gördüğümüz gibi, değiştirilmiş görünüm, küçük sinyallerin çoğunu filtreleyerek fiyat hareketi değişikliklerine daha yavaş yanıt veriyor.

Kagi grafiği oluşturmanın standart ve değiştirilmiş versiyonları

Şekil 2. Kagi grafiği oluşturmanın değiştirilmiş (mavi çizgi) ve standart (kırmızı çizgi) versiyonları

Kagi grafiği dışında, gösterge hem gösterge penceresinde hem de ana grafikte bazı ek öğeler sağlar.

Ayarlara bağlı olarak, işaretler gösterge penceresinde ayarlanabilir. Bu işaretler ters fiyatlar hakkında veri sağlar. Aynı fonksiyon, (ayarlara bağlı olarak) göstergeyi oluşturmak için kullanılan tüm fiyat aralığında veya her bir grafiğin tersinde pencere boyunca eşit olarak dağıtılabilen fiyat seviyeleri kullanılarak uygulanır. Renkler üç versiyonda ayarlanabilir: ters çevirme türüne (yukarı - aşağı), çizgi türüne (Yin - Yang) göre veya renk değişikliği yokluğuna göre.

Geçici olanlar dahil olmak üzere ters fiyat işaretleri ana grafikte verilmiştir. Bu işaretler (ayarlara bağlı olarak) tek renk olabilir veya Yin veya Yang çizgi renklerine göre renk değiştirebilir.

Gösterge kodunun tamamı, global değişkenler aracılığıyla birbirleriyle iletişim kuran fonksiyonlar kullanılarak uygulanır.

Kod, üç ana fonksiyona ve on bir ek fonksiyona ayrılabilir. Temel grafik yapıların ve ek tampon dizilerinin hesaplamaları ve tampon doldurmalarının ana yükü, gösterge penceresindeki Kagi grafiği oluşturma fonksiyonuna dayanmaktadır. Diğer iki fonksiyon verilerin sağlanmasından sorumludur: İlki, zaman verilerini kopyalarken, diğeri seçilen zaman aralığındaki her bir çubuğun fiyatlarına ilişkin verileri kopyalar.

Geri kalan yardımcı fonksiyonlar, tüm oluşumların gerçekleştirilmesi, nesnelerin silinmesi, tüm gösterge nesnelerinin silinmesi ile birlikte göstergenin boşaltılması, ters çevirme parametre hesaplaması, ana grafik ve gösterge penceresine işaretlerin çizilmesi, "Trend çizgisi" türünde grafik nesnelerinin oluşturulması, ana grafik üzerine Kagi çizilmesi ve gösterge oluşumunu başlatmak için yeni çubuğun varışının tanımlanmasından sorumludur.


3. Gösterge Kodu ve Algoritma

Şimdi gösterge kodunu ve oluşumunun algoritmasını detaylı olarak inceleyelim. Kod oldukça büyüktür ve acemi programcıların bunu anlaması epey zor olabilir. Global değişkenler aracılığıyla birbirleriyle iletişim kuran fonksiyonlar, kodu oldukça kafa karıştırıcı hale getirir. Makalenin bu bölümünde, her bir fonksiyonu ve kodun bir bölümünü ayrı ayrı açıklayacağım. İlk olarak gösterge ayarlarını anlatacağım, ardından veri kopyalama başlangıç ​​fonksiyonları, ters çevirme parametre hesaplama, Kagi grafiği oluşturma ve hesaplama ana fonksiyonu ve diğer yardımcı fonksiyonlar hakkında açıklamalar yapacağım.

3.1. Gösterge Giriş Parametreleri

Kod, 12 tampon ve 8 gösterge grafik yapısının yanı sıra ayrı bir pencerede göstergenin bildirilmesi ile başlar. İlk olarak, iki "histogram" ve altı "çizgi" dahil olmak üzere 8 grafik yapısının neden kullanıldığını açıklayalım. Her "histogram" kendi dikey çizgisini oluşturur. Çizgilerden biri Yin çizgisinden, diğeri Yang çizgisinden sorumludur.

Her çizgi için üç tane olduğundan, durum "çizgiler" ile biraz daha karmaşıktır. Bunun yapılma nedeni, birincinin yakınında çizilen başka bir nokta varsa çizginin çizilmesidir. Diğer bir deyişle, birbirine bitişik iki çizgi çizmek için döndürülecek sadece iki "çizgi" türünde grafik yapısına ihtiyacımız var. Ancak, bu çizgilerin gerekli noktaları atlamasına ihtiyacımız varsa, üçüncü yapının diğer ikisiyle birlikte döndürülmesi gerekir.

Bu, yalnızca iki "çizgi" türünde grafik yapısı kullanıldığında ne olduğunu görebileceğiniz Şekil 3'te açıklanmıştır:


 Şekil 3. Omuz ve bel çizgilerini görüntülemek için iki ve üç grafik "çizgi" türünde yapının kullanıldığı örnek

Ardından ayarlar menüsü oluşturulur. Burada beş numaralandırma vardır (bunları giriş parametrelerinde inceleyelim).

İlk giriş parametresi "dönem", oluşumun gerçekleştirildiği dönemdir; bunu "period_to_redraw" grafik oluşumun güncelleme periyodu takip eder; ve son zaman parametresi "start_data" oluşumun başladığı zamandır.

Bu parametreleri, grafik oluşumu ve ek etiketleme parametreleri takip eder:

  • kagi_type – kullanıcı tarafından tanımlanan, standart veya değiştirilmiş grafik oluşumu türü;
  • price_type – oluşum için kullanılan fiyat türü: Close, Open, High ve Low;
  • type_doorstep – kullanılan ters çevirme türü: nokta ve yüzde;
  • doorstep – ters çevirme değeri (yukarıdaki parametreye göre nokta veya yüzde değeri olarak belirtilir);
  • color_yin – gösterge penceresindeki Yin çizgi rengi;
  • color_yang – gösterge penceresindeki Yang çizgi rengi;
  • width_yin – gösterge penceresindeki Yin çizgi genişliği;
  • width_yang – gösterge penceresindeki Yang çizgi genişliği;
  • level_on_off – gösterge penceresinde fiyat seviyelerinin çizilmesi gerekip gerekmediği;
  • level_type – gösterge penceresindeki fiyat seviyeleri türleri. Aralarından seçebileceğiniz iki değer vardır: her bir ters çevirmede veya fiyat aralığı boyunca eşit olarak;
  • level_number – gösterge penceresindeki fiyat seviyelerinin sayısı;
  • level_change_color – fiyat seviyesi çizgilerinin renginin değiştirilmesine olanak sağlar; seçenekler yukarı ve aşağı ters çevirmeler, Yin ve Yang çizgileri veya değişiklik yok;
  • level_first_color – bir fiyat seviyesinin ilk rengi;
  • level_second_color – bir fiyat seviyesinin ikinci rengi;
  • label_1 - gösterge penceresine grafik ters fiyat etiketleri çizme;
  • label_1_number – gösterge penceresinde görüntülenen etiket sayısı;
  • label_1_color - gösterge penceresindeki fiyat etiketlerinin rengi;
  • label_2 - ana grafiğe fiyat etiketleri çizme;
  • label_2_color – ana grafikteki etiket rengi;
  • time_line_draw – ana grafiğe ters zaman çizgileri çizme;
  • time_separate_windows – ana grafikten ters zaman çizgilerinin devamını çizme;
  • time_line_change_color – Yin veya Yang çizgisindeki ters etikete göre zaman çizgisinin rengini değiştirme;
  • time_first_color – ana grafikteki zaman çizgisinin ilk rengi;
  • time_second_color – ana grafikteki zaman çizgisinin ikinci rengi;
  • kagi_main_chart – Kagi'nin ana grafikte çizilmesi gerekip gerekmediği;
  • color_yin_main – ana grafikteki Yin çizgi rengi;
  • color_yang_main – ana grafikteki Yang çizgi rengi;
  • width_yin_main – ana grafikteki Yin çizgi genişliği;
  • width_yang_main – ana grafikteki Yang çizgi genişliği;
  • magic_numb - nesneleri oluşturmak ve silmek için kullanılan ve ayrıca tek bir grafikte birkaç gösterge başlatmak için gösterge adında sihirli sayı.

Bu parametreleri sırasıyla, gösterge tamponlarının bildirimleri, fiyat ve zaman değerlerini saklamak için yardımcı tamponlar, yardımcı değişkenler (stop_data, bars_copied, bars_copied_time, copy_history, copy_time), grafik hareketi değişikliğinin hangi Yin veya Yang çizgisinde meydana geldiğine dair verilerin saklanması için diziler, bu değişikliğin zamanı ve fiyatı, merkezi fiyat (çubukta Yin Yang ile değiştirilmişse veya tam tersi olmuşsa) izler. Son olarak, "а" grafiği hareket değişikliklerinin sayısı hakkında veri içeren en çok kullanılan global değişkenlerden biri bildirilir.

//+------------------------------------------------------------------+
//|                                                         BKCV.mq5 |
//|                                   Azotskiy Aktiniy ICQ:695710750 |
//|                          https://www.mql5.com/ru/users/Aktiniy |
//+------------------------------------------------------------------+
//--- Build Kagi Chart Variable
#property copyright "Azotskiy Aktiniy ICQ:695710750"
#property link      "https://www.mql5.com/en/users/Aktiniy"
#property version   "1.00"
#property description "Build Kagi Chart Variable"
#property description " "
#property description "This indicator makes drawing a chart Kagi as a matter of indicator window, and in the main chart window"
#property indicator_separate_window
#property indicator_buffers 12
#property indicator_plots   8
//--- plot Yin
#property indicator_label1  "Yin"
#property indicator_type1   DRAW_HISTOGRAM2
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot Yin1
#property indicator_label2  "Yin1"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- plot Yin2
#property indicator_label3  "Yin2"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrRed
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1
//--- plot Yin3
#property indicator_label4  "Yin3"
#property indicator_type4   DRAW_LINE
#property indicator_color4  clrRed
#property indicator_style4  STYLE_SOLID
#property indicator_width4  1
//--- plot Yang
#property indicator_label5  "Yang"
#property indicator_type5   DRAW_HISTOGRAM2
#property indicator_color5  clrRed
#property indicator_style5  STYLE_SOLID
#property indicator_width5  2
//--- plot Yang1
#property indicator_label6  "Yang1"
#property indicator_type6   DRAW_LINE
#property indicator_color6  clrRed
#property indicator_style6  STYLE_SOLID
#property indicator_width6  2
//--- plot Yang2
#property indicator_label7  "Yang2"
#property indicator_type7   DRAW_LINE
#property indicator_color7  clrRed
#property indicator_style7  STYLE_SOLID
#property indicator_width7  2
//--- plot Yang3
#property indicator_label8  "Yang3"
#property indicator_type8   DRAW_LINE
#property indicator_color8  clrRed
#property indicator_style8  STYLE_SOLID
#property indicator_width8  2
//--- Enumerations as input data (for more attractive setting)
//--- Kagi charting type
enum kagi_type_enum
  {
   classic=0,  // Classic
   modified=1, // Modified
  };
//--- Type of the price used for construction
enum price_type_enum
  {
   c=0, // Close
   o=1, // Open
   h=2, // High
   l=3, // Low
  };
//--- Type of the used reversal
enum type_doorstep_enum
  {
   point=0,   // Point
   procent=1, // Percent
  };
//--- Type of levels location
enum levels_type_enum
  {
   cor=0, // Cornering
   equ=1, // Equal distance
  };
//--- Level colors change type (works when "Type of levels location"="Cornering")
enum levels_change_color_enum
  {
   up_down=0,  // Up & Down
   yin_yang=1, // Yin & Yang
   no=2,       // Don't change
  };
//--- input parameters
input ENUM_TIMEFRAMES period=PERIOD_CURRENT;                // Calculation period to build the chart
input ENUM_TIMEFRAMES period_to_redraw=PERIOD_M1;           // Refresh period chart
input datetime start_data=D'2013.07.10 00:00:00';           // Start time to build the chart
input kagi_type_enum kagi_type=classic;                     // The type to build Kagi chart
input price_type_enum price_type=c;                         // Price used to build chart
input type_doorstep_enum type_doorstep=point;               // Type calculate doorstep
input double   doorstep=25;                                 // Doorstep reversal
input color    color_yin=clrRed;                            // Color Yin line (indicator window)
input color    color_yang=clrRed;                           // Color Yang line (indicator window)
input char     width_yin=1;                                 // Width Yin line (indicator window)
input char     width_yang=2;                                // Width Yang line (indicator window)
input bool     levels_on_off=false;                         // Draw level (indicator window)
input levels_type_enum levels_type=cor;                     // Type of drawing levels (indicator window)
input uint     levels_number=6;                             // Number of levels  (indicator window)
input levels_change_color_enum levels_change_color=up_down; // Type change color of levels (indicator window)
input color    levels_first_color=clrBeige;                 // The first color of level (indicator window)
input color    levels_second_color=clrCoral;                // The second color of level (indicator window)
input bool     label_1=true;                                // Draw price label on (indicator window)
input uint     label_1_number=10;                           // The number of labels (indicator window)
input color    label_1_color=clrGreenYellow;                // The color of labels (indicator window)
input bool     label_2=true;                                // Draw price label on (main chart)
input color    label_2_color=clrGreenYellow;                // The color of labels (main chart)
input bool     time_line_draw=true;                         // Draw a timeline reversal (main chart)
input bool     time_separate_windows=false;                 // Draw a timeline reversal on indicator window
input bool     time_line_change_color=true;                 // Different color timeline on the Yin and Yang lines (main chart)
input color    time_first_color=clrRed;                     // The first color of timeline (main chart)
input color    time_second_color=clrGreenYellow;            // The second color of timeline (main chart)
input bool     kagi_main_chart=true;                        // Draw Kagi on main chart (main chart)
input color    color_yin_main=clrRed;                       // Color Yin line (main chart)
input color    color_yang_main=clrRed;                      // Color Yang line (main chart)
input char     width_yin_main=1;                            // Width Yin line (main chart)
input char     width_yang_main=2;                           // Width Yang line (main chart)
input long     magic_numb=65758473787389;                   // The magic number for drawing objects
//--- indicator buffers
double         YinBuffer1[];
double         YinBuffer2[];
double         Yin1Buffer[];
double         Yin2Buffer[];
double         Yin3Buffer[];
double         YangBuffer1[];
double         YangBuffer2[];
double         Yang1Buffer[];
double         Yang2Buffer[];
double         Yang3Buffer[];
//--- additional variables
double Price[]; // Buffer for storing the copied price data
double Time[];  // Buffer for storing the copied time data
//---
datetime stop_data;      // Current time
int bars_copied=0;       // Number of the already copied bars from the initial date
int bars_copied_time;    // Number of the already copied bars having the initial date
bool copy_history=false; // Price history copying result
bool copy_time=false;    // Time history copying result
//---
datetime time_change[];      // Array for writing the time when the chart movement started changing (up or down)
char time_line[];            // Array for storing the data on what line (Yin=0 or Yang=1) direction has changed
double time_change_price[];  // Array for writing the chart movement change price
double time_central_price[]; // Array for writing the average price during the chart movement change

uint a=0; // Variable for building the chart, number of chart reversals is fixed
 

3.2. Gösterge Başlatma Fonksiyonu

Bir sonraki gösterge başlatma fonksiyonudur. Gösterge tamponları ve bunların indislenmesi (esas olarak zaman serisi olarak; Kagi grafiği ana grafikten daha kısa olduğu için bunu geriye doğru çizmek daha iyidir) burada belirtilir. Ayrıca ekranda görüntülenmeyecek değerler de ayarlanır (EMPTY_VALUE=-1).

Şimdi, gösterge adını ve ekran doğruluğunu atıyoruz. Daha önce de belirtildiği gibi, sihirli sayı ada eklenir. Bu, ChartWindowFind() fonksiyonunun doğru çalışmasını sağlamak için yapılır. Aksi takdirde, gösterge penceresine çizilen grafik nesnesi yalnızca ilk başlatılan göstergede görüntülenir (tek bir grafik üzerinde birden fazla gösterge kullanılıyorsa).

Daha sonra, yapı çizgilerine adlar atarız, gösterge penceresinde mevcut sayısal değerlerin gösterilmesini engelleriz, Yin ve Yang çizgilerinin rengini ve genişliğini belirleriz, gösterge penceresinde görüntülenen fiyat seviyelerinin sayısını belirleriz.

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,YinBuffer1,INDICATOR_DATA);
   ArraySetAsSeries(YinBuffer1,true);
   SetIndexBuffer(1,YinBuffer2,INDICATOR_DATA);
   ArraySetAsSeries(YinBuffer2,true);
   SetIndexBuffer(2,Yin1Buffer,INDICATOR_DATA);
   ArraySetAsSeries(Yin1Buffer,true);
   SetIndexBuffer(3,Yin2Buffer,INDICATOR_DATA);
   ArraySetAsSeries(Yin2Buffer,true);
   SetIndexBuffer(4,Yin3Buffer,INDICATOR_DATA);
   ArraySetAsSeries(Yin3Buffer,true);
//---
   SetIndexBuffer(5,YangBuffer1,INDICATOR_DATA);
   ArraySetAsSeries(YangBuffer1,true);
   SetIndexBuffer(6,YangBuffer2,INDICATOR_DATA);
   ArraySetAsSeries(YangBuffer2,true);
   SetIndexBuffer(7,Yang1Buffer,INDICATOR_DATA);
   ArraySetAsSeries(Yang1Buffer,true);
   SetIndexBuffer(8,Yang2Buffer,INDICATOR_DATA);
   ArraySetAsSeries(Yang2Buffer,true);
   SetIndexBuffer(9,Yang3Buffer,INDICATOR_DATA);
   ArraySetAsSeries(Yang3Buffer,true);
//--- add the buffer for copying data on prices for calculation
   SetIndexBuffer(10,Price,INDICATOR_CALCULATIONS);
//--- add the buffer for copying data on bar open time for construction
   SetIndexBuffer(11,Time,INDICATOR_CALCULATIONS);

//--- set what values are not to be drawn
   for(char x=0; x<8; x++)
     {
      PlotIndexSetDouble(x,PLOT_EMPTY_VALUE,-1);
     }
//--- set the indicator's look
   IndicatorSetString(INDICATOR_SHORTNAME,"BKCV "+IntegerToString(magic_numb)); // Indicator name
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits); // Display accuracy
//--- assign names to graphical constructions
   PlotIndexSetString(0,PLOT_LABEL,"Yin");
   PlotIndexSetString(1,PLOT_LABEL,"Yin");
   PlotIndexSetString(2,PLOT_LABEL,"Yin");
   PlotIndexSetString(3,PLOT_LABEL,"Yin");
   PlotIndexSetString(4,PLOT_LABEL,"Yang");
   PlotIndexSetString(5,PLOT_LABEL,"Yang");
   PlotIndexSetString(6,PLOT_LABEL,"Yang");
   PlotIndexSetString(7,PLOT_LABEL,"Yang");
//--- prohibit display of the results of the current values for graphical constructions
   PlotIndexSetInteger(0,PLOT_SHOW_DATA,false);
   PlotIndexSetInteger(1,PLOT_SHOW_DATA,false);
   PlotIndexSetInteger(2,PLOT_SHOW_DATA,false);
   PlotIndexSetInteger(3,PLOT_SHOW_DATA,false);
   PlotIndexSetInteger(4,PLOT_SHOW_DATA,false);
   PlotIndexSetInteger(5,PLOT_SHOW_DATA,false);
   PlotIndexSetInteger(6,PLOT_SHOW_DATA,false);
   PlotIndexSetInteger(7,PLOT_SHOW_DATA,false);
//--- set color for Yin line
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,color_yin);
   PlotIndexSetInteger(1,PLOT_LINE_COLOR,color_yin);
   PlotIndexSetInteger(2,PLOT_LINE_COLOR,color_yin);
   PlotIndexSetInteger(3,PLOT_LINE_COLOR,color_yin);
//--- set color for Yang line
   PlotIndexSetInteger(4,PLOT_LINE_COLOR,color_yang);
   PlotIndexSetInteger(5,PLOT_LINE_COLOR,color_yang);
   PlotIndexSetInteger(6,PLOT_LINE_COLOR,color_yang);
   PlotIndexSetInteger(7,PLOT_LINE_COLOR,color_yang);
//--- set Yin line width
   PlotIndexSetInteger(0,PLOT_LINE_WIDTH,width_yin);
   PlotIndexSetInteger(1,PLOT_LINE_WIDTH,width_yin);
   PlotIndexSetInteger(2,PLOT_LINE_WIDTH,width_yin);
   PlotIndexSetInteger(3,PLOT_LINE_WIDTH,width_yin);
//--- set Yang line width
   PlotIndexSetInteger(4,PLOT_LINE_WIDTH,width_yang);
   PlotIndexSetInteger(5,PLOT_LINE_WIDTH,width_yang);
   PlotIndexSetInteger(6,PLOT_LINE_WIDTH,width_yang);
   PlotIndexSetInteger(7,PLOT_LINE_WIDTH,width_yang);
//--- set the number of levels in the indicator window
   IndicatorSetInteger(INDICATOR_LEVELS,levels_number);
//---
   return(INIT_SUCCEEDED);
  }


3.3. Veri Kopyalama Fonksiyonu

Şimdi veri kopyalama fonksiyonlarını inceleyelim.

İki tane vardır. Birincisi fiyatları kopyalamak içindir, ikincisi ise her bir çubuğun açık zamanını kopyalamak içindir. Her iki fonksiyon da değerlerini önceden bildirilen göstergenin hesaplama tamponlarında tutar.

İlk olarak, fiyatları kopyalama fonksiyonunu ele alalım. Fonksiyon giriş parametreleri: veri saklama dizisi, veri kopyalama başlangıç ​​ve bitiş zamanı (mevcut zaman). Fonksiyonun gövdesi, fonksiyona cevap verecek değişkenleri, ara diziye kopyalanan veri (çubuk) sayısını, ara dinamik dizinin kendisini ve ara diziye kopyalanması gereken çubuk sayısını içerir. Çubuk sayısı, verilen zaman aralığındaki toplam çubuk sayısı ve önceki fonksiyon çağrısında kopyalanan çubuk sayısı (genel değişken) temel alınarak hesaplanır.

Veriler ilk kez kopyalanmıyorsa, son kopyalanan çubuktaki veriler güncellenmelidir. Bunu yapmak için kopyalanan çubukların sayısını bir sayı azaltıp yeni kopyalanan çubukların sayısını bir sayı artırırız. Ayrıca, çubukları kopyalamak için bunu hazırlayan ara dizinin boyutunu da değiştiririz.

Ayarlara bağlı olarak fiyatları ara diziye kopyalarız. Kopyalama başarılı olursa, veriler ara diziden tampon dizisinin (fonksiyon yanıt dizisi) sonuna kopyalanır, fonksiyona olumlu yanıt atanır ve kopyalanan çubukların sayısına dair verileri saklayan global değişken güncellenir. Böyle bir kopyalama, yalnızca son birkaç çubuğun kopyalanmasına olanak sağlayarak kopyalama süresini azaltır.

//+------------------------------------------------------------------+
//| Func Copy History                                                |
//+------------------------------------------------------------------+
bool func_copy_history(double &result_array[],
                       datetime data_start,
                       datetime data_stop)
  {
//---
   int x=false; // Variable for answer

   int result_copy=-1; // Number of copied data

   static double price_interim[]; // Temporary dynamic array for storing copied data
   static int bars_to_copy;       // Number of bars for copying

   bars_to_copy=Bars(_Symbol,period,data_start,data_stop); // Find out the current number of bars on the time interval
   bars_to_copy-=bars_copied; // Calculate the number of bars to be copied

   if(bars_copied!=0) // If it is not the first time the data has been copied
     {
      bars_copied--;
      bars_to_copy++;
     }

   ArrayResize(price_interim,bars_to_copy); // Change the size of the receiving array

   switch(price_type)
     {
      case 0:
         result_copy=CopyClose(_Symbol,period,0,bars_to_copy,price_interim);
         break;
      case 1:
         result_copy=CopyOpen(_Symbol,period,0,bars_to_copy,price_interim);
         break;
      case 2:
         result_copy=CopyHigh(_Symbol,period,0,bars_to_copy,price_interim);
         break;
      case 3:
         result_copy=CopyLow(_Symbol,period,0,bars_to_copy,price_interim);
         break;
     }

   if(result_copy!=-1) // If copying to the intermediate array is successful
     {
      ArrayCopy(result_array,price_interim,bars_copied,0,WHOLE_ARRAY); // Copy the data from the temporary array to the main one
      x=true; // assign the positive answer to the function
      bars_copied+=result_copy; // Increase the value of the processed data
     }
//---
   return(x);
  }

Bir sonraki fonksiyon, zaman verilerini kopyalamak içindir. Bir öncekinden farklıdır, çünkü başka bir değişken türüyle ilgilidir - datetime (bu, Zaman tamponu dizisine - fonksiyon yanıt dizisine - kopyalandığında double olarak dönüştürülür). Diğer bir fark ise, kopyalanan verilerin seçilmesine gerek olmadığı için switch() ifadesinin kullanılmamasıdır.

//+------------------------------------------------------------------+
//| Func Copy Time                                                   |
//+------------------------------------------------------------------+
bool func_copy_time(double &result_array[],
                    datetime data_start,
                    datetime data_stop)
  {
//---
   int x=false; // Variable for answer
   int result_copy=-1; // Number of copied data

   static datetime time_interim[]; // Temporary dynamic array for storing copied data
   static int bars_to_copy_time; // Number of bars for copying

   bars_to_copy_time=Bars(_Symbol,period,data_start,data_stop); // Find out the current number of bars on the time interval
   bars_to_copy_time-=bars_copied_time; // Calculate the number of bars to be copied

   if(bars_copied_time!=0) // If it is not the first time the data has been copied
     {
      bars_copied_time--;
      bars_to_copy_time++;
     }
   ArrayResize(time_interim,bars_to_copy_time); // Change the size of the receiving array
   result_copy=CopyTime(_Symbol,period,0,bars_to_copy_time,time_interim);

   if(result_copy!=-1) // If copying to the intermediate array is successful
     {
      ArrayCopy(result_array,time_interim,bars_copied_time,0,WHOLE_ARRAY); // Copy the data from the temporary array to the main one
      x=true; // assign the positive answer to the function
      bars_copied_time+=result_copy; // Increase the value of the processed data
     }
//---
   return(x);
  }

3.4. Ters Çevirme Parametre Hesaplama Fonksiyonu

Ters çevirme parametresi bir nokta veya yüzde olabileceğinden, gösterge ayarlarına bağlı olarak ters çevirme parametresini hesaplayacak fonksiyona ihtiyacımız vardır. Fonksiyonun yalnızca bir parametresi vardır – yüzde ters çevirmeyi hesaplamak için fiyat. Cevap için değişken ilk olarak double türü ile başlatılır ve hesaplamalardan sonra cevap için dolaylı olarak int türüne dönüştürülür.

Bunun nedeni, hesaplamalarda floating (kayan) nokta sayılarının kullanılması ve cevabın tamsayı olarak sunulmasının gerekmesidir. Seçim, fonksiyonda if-else koşullu ifadesi ile uygulanır. Karşılaştırma doğrudan harici giriş değişkeni (gösterge parametreleri) ile yapılır. Noktaların hesaplanması basit bir denklem kullanılarak yapılır. İlk olarak, fiyatın geçtiği toplam nokta sayısı tanımlanır. Daha sonra bu sayıya göre belirlenen yüzde hesaplanır ve döndürülen değişkene atanır.

//+------------------------------------------------------------------+
//| Func Calculate Doorstep                                          |
//+------------------------------------------------------------------+
int func_calc_dorstep(double price)
  {
   double x=0; // Variable for answer
   if(type_doorstep==0) // If the calculation is to be performed in points
     {
      x=doorstep;
     }
   if(type_doorstep==1) // If the calculation is to be performed in percentage
     {
      x=price/_Point*doorstep/100;
     }
   return((int)x);
  }

3.5. Ana Fonksiyon - Kagi Grafiği Çizme

Ana fonksiyonun - gösterge penceresinde Kagi grafiği çizme (yani gösterge tamponlarını doldurma) - çalışması için gerekli olan tüm fonksiyonları zaten inceledik. Fonksiyonun giriş parametreleri veri dizilerinden oluşur. Bunlardan ikisi yukarıda açıklanan hesaplama tamponlarıdır (önceden kopyalanan Fiyat ve Zaman), geri kalanı gösterge grafik oluşum tamponlarının dizileridir.

Verileri grafik oluşumunda saklamak için gerekli olan değişkenler fonksiyonun içinde bildirilir. Grafik for döngü ifadesi kullanılarak oluşturulduğundan, önceki geçişin bittiği aşamadaki verilere sahip olmalıyız. Bu ise, altı değişken ile gerçekleştirilebilir: line_move - fiyatın önceki geçişte hareket ettiği yer; line_gauge - çizgi ölçüsü (çizgi genişliği) - Yin veya Yang, price_1 ve price_2 - dikkate alınan önceki ve mevcut fiyat, price_down ve price_up - bir omuz ve belin önceki fiyatı. Gördüğümüz gibi, price_1, bu değişkenin döngünün en başından karşılaştırmadan önce hesaplamalarda yer alması nedeniyle, kopyalanan fiyatlar dizisinin hemen ilk öğesine eşitlenir.

Gösterge grafik oluşumunun tampon dizileri AS_SERIES indisleme bayrağına sahip olduğundan, ters sırada doldurulmaları gerekir. Bunu başarmak için uygun boyuta sahip zaman dizileri uygulanır. Verileri zaman, çizgi türleri, "omuz" ve "bel" olarak saklamak için global değişkenler ve ayrıca ters fiyatlar daha sonra aynı şekilde dönüştürülür.

Ardından, tüm diziler "boş" değerler (-1) ile doldurulmalıdır. Bu, iki küçük döngü kullanılarak yapılır. Her şeyi tek bir döngüde birleştirmek mümkündür. Ancak ikisini kullanmak, gerçekleştirilen tüm eylemleri çok daha net hale getirirken, yürütme süresi çok fazla değişmez. Diğer bir deyişle, grafik tamponları ve hesaplama zamanı dizileri ayrı ayrı doldurulur.

Artık tüm değişkenler bildirilir, dönüştürülür ve doldurulur, böylece ana döngü başlatılabilir. Bu oldukça büyüktür (hesaplama yeterince hızlı yapılsa da) ve önceden kopyalanmış tüm çubukların taranmasını içerir.

Döngü, kopyalanan tüm çubuklardan geçer ve bunlarla daha fazla çalışmak için önceden bildirilmiş gerekli dizileri doldurur. İlk olarak döngüde kullanılan tüm dizileri tanımlayalım:

  • yin_int_1 - dikey Yin çizgisi fiyatının birincil değeri (dikey Yin çizgisi çizilirse ve grafik aşağı doğru hareket ederse bu, fiyatın üst değeridir; grafik yukarı doğru hareket ederse, bunun tersi olur);
  • yin_int_2 - dikey Yin çizgisi fiyatının ikincil değeri (yukarı yönlü çizgi çizilirse bu, üst değerdir; çizgi aşağı yönlü ise, tersi durumumuz olur);
  • yang_int_1 - dikey Yang çizgisi fiyatının birincil değeri;
  • yang_int_2 - dikey Yang çizgisi fiyatının ikincil değeri;
  • lin_yin - yatay Yin çizgisi değeri (Yin çizgisinde ters çevirme fiyatı);
  • lin_yang - yatay Yang çizgisi değeri (Yang çizgisinde ters çevirme fiyatı);
  • time_change - grafiğin ters çevrilme zamanı (omuz veya bel oluşumu);
  • time_line - ters çevirme Yin = 0 veya Yang = 1 sırasındaki çizgi;
  • time_central_price - merkezi fiyatın değeri, Yin çizgisinin Yang çizgisine dönüştüğü andaki fiyat veya bunun tam tersi;
  • time_change_price - ters çevirme (omuz veya bel) fiyatının değeri, değişken Yin veya Yang çizgi türlerine bağlı olmayan yaygın bir değişkendir.

Fiyat tamponundan mevcut analiz edilen fiyatın değeri, if-else koşullu ifadelerde daha fazla karşılaştırma için her döngü geçişinden önce price_2 değişkenine atanır. Daha sonra kopyalanan verinin tampon dizisi adım adım analiz edilir ve yukarıda bahsedilen diziler doldurulur. Her if-else koşullu ifadesi, belirli eylemleri koşullara göre gerçekleştirir: grafik çizgilerinin önceki yönü (yukarı veya aşağı) ve çizgilerin önceki görünümü (Yin veya Yang). Daha sonra oluşum türüne (standart veya değiştirilmiş) göre hareket koşulları (fiyatın belirli bir noktayı geçip geçmediği) kontrol edilir.

Her şey yolundaysa, yeni değişkenler (dizi öğeleri) yeniden atanır veya tanımlanır. Çizgi türü (Yin veya Yang) en başta tanımlanır. Harekete ve önceki eylemlere göre, daha fazla dağıtım gerçekleştirilir.

İki olası fiyat hareketi vardır:

  1. Fiyat yukarı hareket eder;
  2. Fiyat aşağı hareket eder.

Ayrıca her yönde önceki eylemlerin dört türü vardır:

  1. Önceki çizgi Yin'dir ve yukarı hareket etmiştir;
  2. Önceki çizgi Yang'dır ve yukarı hareket etmiştir;
  3. Önceki çizgi Yin'dir ve aşağı hareket etmiştir;
  4. Önceki çizgi Yang'dır ve aşağı hareket etmiştir.

Böylece, grafiğin ilk hareketinin (ilk çizgi görünümü) ilk iki tanımı dışında sekiz durumumuz vardır.

Bundan sonra, ana döngü tamamlanmıştır. Tamponların yeniden atanması (ters çevrilmesi) ve doldurulması, grafiği, daha önce ana döngüde tanımlanan ve "a" değişkeninde yazılan Kagi grafiği ters çevrilme sayısından oluşan daha küçük bir döngüde oluşturmak için gerçekleştirilir. Alt ve üst fiyat değerlerinin ve dikey çizgilerin dağılımına gelince, her şey oldukça basittir: Basit bir tersine çevirme gerçekleştirilir. Diğer bir deyişle, önceden elde edilen birincil değerler (0,1,2,3... indislerine sahip diziler) tamponların son değerlerine ("а" indisli öğe, yani, а,а-1,а-2,a-3... bir son değer olarak kullanılır) atanır. Ters (yatay) çizgilerin birbirine yapışmasını önlemek için yukarıda belirtildiği gibi switch (değiştir) ifadesi kullanılarak döndürme yapılır.

Böylece, Kagi haritasının ana fonksiyonunun çalışması tamamlanmış olur.

//+------------------------------------------------------------------+
//| Func Draw Kagi                                                   |
//+------------------------------------------------------------------+
void func_draw_kagi(double &array_input[],
                    double &arr_yin_1[],
                    double &arr_yin_2[],
                    double &arr_yin_lin1[],
                    double &arr_yin_lin2[],
                    double &arr_yin_lin3[],
                    double &arr_yang_1[],
                    double &arr_yang_2[],
                    double &arr_yang_lin1[],
                    double &arr_yang_lin2[],
                    double &arr_yang_lin3[],
                    double &arr_time[])
  {
//---
   a=0; // Variable for the chart construction fixing the number of chart reversals
   char line_move=0; // Previous price direction 1-up, -1-down
   char line_gauge=0; // Previous look of the line 1-thick yang, -1-thin yin
   double price_1=0,price_2=0; // Auxiliary variables for defining the price movement
   double price_down=-99999,price_up=99999; // Auxiliary variables for storing the reversal price values
   price_1=array_input[0];
//--- auxiliary arrays for the initial data storing before the reversal (transferring to the buffers)
   double yin_int_1[];
   double yin_int_2[];
   double lin_yin[];
   double yang_int_1[];
   double yang_int_2[];
   double lin_yang[];
//--- change the sizes of dynamic arrays
   ArrayResize(yin_int_1,bars_copied);
   ArrayResize(yin_int_2,bars_copied);
   ArrayResize(yang_int_1,bars_copied);
   ArrayResize(yang_int_2,bars_copied);
   ArrayResize(lin_yin,bars_copied);
   ArrayResize(lin_yang,bars_copied);
//--- time data storing arrays
   ArrayResize(time_change,bars_copied_time);
   ArrayResize(time_line,bars_copied_time); // Look of the line Yin = 0 or Yang = 1
   ArrayResize(time_change_price,bars_copied_time);
   ArrayResize(time_central_price,bars_copied_time);
//--- assign -1 (not displayed) value to the transferred buffers
   for(int z=0; z<bars_copied; z++)
     {
      arr_yin_1[z]=-1;
      arr_yin_2[z]=-1;
      arr_yin_lin1[z]=-1;
      arr_yin_lin2[z]=-1;
      arr_yin_lin3[z]=-1;
      arr_yang_1[z]=-1;
      arr_yang_2[z]=-1;
      arr_yang_lin1[z]=-1;
      arr_yang_lin2[z]=-1;
      arr_yang_lin3[z]=-1;
     }
//--- equate -1 (not displayed) value to the arrays
   for(int z=0; z<bars_copied; z++)
     {
      yin_int_1[z]=-1;
      yin_int_2[z]=-1;
      lin_yin[z]=-1;
      yang_int_1[z]=-1;
      yang_int_2[z]=-1;
      lin_yang[z]=-1;
      time_change[z]=-1;
      time_line[z]=-1;
      time_change_price[z]=-1;
      time_central_price[z]=-1;
     }
//--- function's main loop
   for(int z=0; z<bars_copied; z++)
     {
      price_2=array_input[z];
      //--- first, let's define the initial market direction
      //--- first THIN DESCENDING line
      if(((price_1-price_2)/_Point>func_calc_dorstep(price_2)) && line_move==0)
        {
         yin_int_1[a]=price_1;
         yin_int_2[a]=price_2;

         line_move=-1;
         line_gauge=-1;

         price_1=price_2;

         time_change[a]=(datetime)arr_time[z];
         time_line[a]=0;
        }
      //--- first THICK ASCENDING line
      if(((price_1-price_2)/_Point<-func_calc_dorstep(price_2)) && line_move==0)
        {
         yang_int_1[a]=price_1;
         yang_int_2[a]=price_2;

         line_move=1;
         line_gauge=1;

         price_1=price_2;

         time_change[a]=(datetime)arr_time[z];
         time_line[a]=1;
        }
      //--- price moves DOWN
      //--- if the price moved DOWN before that, the line is THIN
      if(line_move==-1 && line_gauge==-1)
        {
         if(((price_1-price_2)/_Point>func_calc_dorstep(price_2)) || (kagi_type==0 && (price_1-price_2)/_Point>0))
           {
            yin_int_2[a]=price_2;

            line_move=-1;
            line_gauge=-1;

            price_1=price_2;

            time_change[a]=(datetime)arr_time[z];
            time_line[a]=0;
           }
        }
      //--- if the price moved DOWN before that, the line is THICK
      if(line_move==-1 && line_gauge==1)
        {
         if(((price_1-price_2)/_Point>func_calc_dorstep(price_2)) || (kagi_type==0 && (price_1-price_2)/_Point>0))
           {
            if(price_2<price_down) // If the thick line crossed the lower shoulder when moving downwards
              {
               yin_int_1[a]=price_down;
               yin_int_2[a]=price_2;

               yang_int_2[a]=price_down;

               line_move=-1;
               line_gauge=-1;

               price_1=price_2;

               time_change[a]=(datetime)arr_time[z];
               time_central_price[a]=price_down;
               time_line[a]=0;
              }
            else //if(price_2>=price_down) // If the thick line has not crossed the lower shoulder when moving downwards
              {
               yang_int_2[a]=price_2;

               line_move=-1;
               line_gauge=1;

               price_1=price_2;

               time_change[a]=(datetime)arr_time[z];
               time_line[a]=1;
              }
           }
        }
      //--- if the price has moved UPWARDS before that, the line is THIN
      if(line_move==1 && line_gauge==-1)
        {
         if((price_1-price_2)/_Point>func_calc_dorstep(price_2))
           {
            a++;
            yin_int_1[a]=price_1;
            yin_int_2[a]=price_2;

            lin_yin[a]=price_1;

            line_move=-1;
            line_gauge=-1;

            price_up=price_1;

            price_1=price_2;

            time_change[a]=(datetime)arr_time[z];
            time_line[a]=0;
            time_change_price[a]=lin_yin[a];
           }
        }
      //--- if the price has moved UPWARDS before that, the line is THICK
      if(line_move==1 && line_gauge==1)
        {
         if((price_1-price_2)/_Point>func_calc_dorstep(price_2))
           {
            a++;
            if(price_2<price_down) // If the thick line has crossed the lower shoulder when moving downwards
              {
               yin_int_1[a]=price_down;
               yin_int_2[a]=price_2;

               yang_int_1[a]=price_1;
               yang_int_2[a]=price_down;

               lin_yang[a]=price_1;

               line_move=-1;
               line_gauge=-1;

               price_up=price_1;

               price_1=price_2;

               time_change[a]=(datetime)arr_time[z];
               time_line[a]=0;
               time_change_price[a]=lin_yang[a];
               time_central_price[a]=price_down;
              }
            else//if(price_2>=price_down) // If the thick line has not crossed the lower shoulder when moving downwards
              {
               yang_int_1[a]=price_1;
               yang_int_2[a]=price_2;

               lin_yang[a]=price_1;

               line_move=-1;
               line_gauge=1;

               price_up=price_1;

               price_1=price_2;

               time_change[a]=(datetime)arr_time[z];
               time_line[a]=1;
               time_change_price[a]=lin_yang[a];
              }
           }
        }
      //--- the price moves UP
      //--- if the price has moved UPWARDS before that, the line is THICK
      if(line_move==1 && line_gauge==1)
        {
         if(((price_1-price_2)/_Point<-func_calc_dorstep(price_2)) || (kagi_type==0 && (price_1-price_2)/_Point<0))
           {
            yang_int_2[a]=price_2;

            line_move=1;
            line_gauge=1;

            price_1=price_2;

            time_change[a]=(datetime)arr_time[z];
            time_line[a]=1;
           }
        }

      //--- if the price has moved UPWARDS before that, the line is THIN
      if(line_move==1 && line_gauge==-1)
        {
         if(((price_1-price_2)/_Point<-func_calc_dorstep(price_2)) || (kagi_type==0 && (price_1-price_2)/_Point<0))
           {
            if(price_2>price_up) // If the thin line has not crossed the upper shoulder when moving upwards
              {
               yin_int_2[a]=price_up;

               yang_int_1[a]=price_up;
               yang_int_2[a]=price_2;

               line_move=1;
               line_gauge=1;

               price_1=price_2;

               time_change[a]=(datetime)arr_time[z];
               time_central_price[a]=price_up;
               time_line[a]=1;
              }
            else//if(price_2<=price_up) // If the thin line has not crossed the upper shoulder when moving upwards
              {
               yin_int_2[a]=price_2;

               line_move=1;
               line_gauge=-1;

               price_1=price_2;

               time_change[a]=(datetime)arr_time[z];
               time_line[a]=0;
              }
           }
        }

      //--- if the price has moved DOWNWARDS before that, the line is THICK
      if(line_move==-1 && line_gauge==1)
        {
         if((price_1-price_2)/_Point<-func_calc_dorstep(price_2))
           {
            a++;

            yang_int_1[a]=price_1;
            yang_int_2[a]=price_2;

            lin_yang[a]=price_1;

            line_move=1;
            line_gauge=1;

            price_down=price_1;
            price_1=price_2;

            time_change[a]=(datetime)arr_time[z];
            time_line[a]=1;
            time_change_price[a]=lin_yang[a];
           }
        }

      //--- if the price has moved DOWNWARDS before that, the line is THIN
      if(line_move==-1 && line_gauge==-1)
        {
         if((price_1-price_2)/_Point<-func_calc_dorstep(price_2))
           {
            a++;
            if(price_2>price_up) // If the thin line has crossed the upper shoulder when moving upwards
              {
               yin_int_1[a]=price_1;
               yin_int_2[a]=price_up;

               yang_int_1[a]=price_up;
               yang_int_2[a]=price_2;

               lin_yin[a]=price_1;

               line_move=1;
               line_gauge=1;

               price_down=price_1;
               price_1=price_2;

               time_change[a]=(datetime)arr_time[z];
               time_line[a]=1;
               time_change_price[a]=lin_yin[a];
               time_central_price[a]=price_up;
              }
            else //if(price_2<=price_up) // If the thin line has not crossed the upper shoulder when moving upwards
              {
               yin_int_1[a]=price_1;
               yin_int_2[a]=price_2;

               lin_yin[a]=price_1;

               line_move=1;
               line_gauge=-1;

               price_down=price_1;
               price_1=price_2;

               time_change[a]=(datetime)arr_time[z];
               time_line[a]=0;
               time_change_price[a]=lin_yin[a];
              }
           }
        }

     }
//--- function's main loop
//--- assign actual values to drawing buffers
   uint y=a;
//--- auxiliary variables for storing data on filling the current buffer
   char yin=1;
   char yang=1;
   for(uint z=0; z<=a; z++)
     {
      arr_yin_1[z]=yin_int_1[y];
      arr_yin_2[z]=yin_int_2[y];

      switch(yin)
        {
         case 1:
           {
            arr_yin_lin1[z]=lin_yin[y];
            arr_yin_lin1[z+1]=lin_yin[y];
            yin++;
           }
         break;
         case 2:
           {
            arr_yin_lin2[z]=lin_yin[y];
            arr_yin_lin2[z+1]=lin_yin[y];
            yin++;
           }
         break;
         case 3:
           {
            arr_yin_lin3[z]=lin_yin[y];
            arr_yin_lin3[z+1]=lin_yin[y];
            yin=1;
           }
         break;
        }

      arr_yang_1[z]=yang_int_1[y];
      arr_yang_2[z]=yang_int_2[y];

      switch(yang)
        {
         case 1:
           {
            arr_yang_lin1[z]=lin_yang[y];
            arr_yang_lin1[z+1]=lin_yang[y];
            yang++;
           }
         break;
         case 2:
           {
            arr_yang_lin2[z]=lin_yang[y];
            arr_yang_lin2[z+1]=lin_yang[y];
            yang++;
           }
         break;
         case 3:
           {
            arr_yang_lin3[z]=lin_yang[y];
            arr_yang_lin3[z+1]=lin_yang[y];
            yang=1;
           }
         break;
        }
      y--;
     }
//---
  }


3.6. "Trend Çizgisi" Grafik Nesnesi Oluşturma Fonksiyonu

Şimdi, "trend çizgisi" grafik nesnesi oluşturma fonksiyonunu inceleyelim. Kagi'yi ana grafiğe çizmek için bu fonksiyona ihtiyaç vardır.

Fonksiyon çok basittir. "Trend çizgisi" grafik nesnesini oluşturmak için gerekli giriş parametrelerini içerir: nesne adı, birinci ve ikinci fiyat ve zaman noktalarının yanı sıra çizgi genişliği ve rengi. Fonksiyon gövdesi, grafik nesnesi oluşturma fonksiyonunu ve grafik nesnesinin özelliklerini değiştirmenin altı fonksiyonunu içerir.

//+------------------------------------------------------------------+
//| Func Object Create Trend Line                                    |
//+------------------------------------------------------------------+
void func_create_trend_line(string name,
                            double price1,
                            double price2,
                            datetime time1,
                            datetime time2,
                            int width,
                            color color_line)
  {
   ObjectCreate(0,name,OBJ_TREND,0,time1,price1,time2,price2);
//--- set the line color
   ObjectSetInteger(0,name,OBJPROP_COLOR,color_line);
//--- set the line display style
   ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID);
//--- set the line width
   ObjectSetInteger(0,name,OBJPROP_WIDTH,width);
//--- display in the foreground (false) or background (true)
   ObjectSetInteger(0,name,OBJPROP_BACK,false);
//--- enable (true) or disable (false) the mode of continuing the line display to the left
   ObjectSetInteger(0,name,OBJPROP_RAY_LEFT,false);
//--- enable (true) or disable (false) the mode of continuing the line display to the right
   ObjectSetInteger(0,name,OBJPROP_RAY_RIGHT,false);
  }

3.7. Ana Grafiğe Kagi Çizme

Bir önceki için birden çok kez geçerli olan bir sonraki fonksiyon, Kagi oluşumunun ana grafikteki fonksiyonudur. Kagi grafik oluşumunun daha önce incelenen ana fonksiyonunda doldurulan global değişkenler giriş değişkenleri olarak kullanılır: ters fiyatların dizisi ("omuzlar" ve "beller"), değişim dizisi ve merkezi fiyatlar (Yin çizgisinin Yang'a dönüştüğü fiyat veya bunun tam tersi), ters çevirme zaman dizisi (gerçek zamanlı olarak bulunur, [z-1] dizi indisi ters çevirme başlangıcı işaretlemek için kullanılır), ters çevirmenin gerçekleştiği çizgi türünün dizisi (aynı zamanda zaman dizisi gibi ileriye dönük bir öğedir).

Fonksiyon gövdesi bir döngüden oluşur. Döngü iki bölüme ayrılır: dikey ve yatay çizgiler çizme. İlki de ikiye ayrılır: çizgi değişikliği (merkezi fiyatı değiştirir) göz önünde bulundurularak dikey çizgileri çizme ve değişiklik olmaması. "Trend çizgisi" nesne oluşturma fonksiyonunun aktarılan parametrelerine dikkat edin.

Adlandırma tekrarlı bir şekilde gerçekleştirilir. Nesne adı sihirli bir sayıyla başlar (belirli bir göstergenin nesnelerini silmek için gereklidir), sonra bunun türü sabitlenir ve son olarak indis atanır. İndis, döngünün her geçişinde güncellenir.

//+------------------------------------------------------------------+
//| Func Kagi Main Chart                                             |
//+------------------------------------------------------------------+
void func_kagi_main_chart(double &price[],         // Shoulder prices array
                          double &central_price[], // Array of the prices of passing through the shoulders
                          datetime &time[],        // Current location time array ([-1] - start of shoulder)
                          char &type_line_end[])   // Line type by the start of shoulder formation
  {
//--- start of the loop
   for(uint z=1; z<=a; z++)
     {
      //--- check for the pass conditions (no pass)
      if(central_price[z]==-1)
        {
         if(type_line_end[z-1]==0 && price[z+1]!=-1)
           {
            func_create_trend_line(IntegerToString(magic_numb)+"_trend_yin_v"+IntegerToString(z),
                                   price[z],price[z+1],time[z],time[z],width_yin_main,color_yin_main);
           }
         if(type_line_end[z-1]==1 && price[z+1]!=-1)
           {
            func_create_trend_line(IntegerToString(magic_numb)+"_trend_yang_v"+IntegerToString(z),
                                   price[z],price[z+1],time[z],time[z],width_yang_main,color_yang_main);
           }
        }
      else //--- check for the pass conditions (pass is present)
        {
         if(type_line_end[z-1]==0 && price[z+1]!=-1)
           {
            func_create_trend_line(IntegerToString(magic_numb)+"_trend_yin_v"+IntegerToString(z),
                                   central_price[z],price[z],time[z],time[z],width_yin_main,color_yin_main);
            func_create_trend_line(IntegerToString(magic_numb)+"_trend_yang_v"+IntegerToString(z),
                                   central_price[z],price[z+1],time[z],time[z],width_yang_main,color_yang_main);
           }
         if(type_line_end[z-1]==1 && price[z+1]!=-1)
           {
            func_create_trend_line(IntegerToString(magic_numb)+"_trend_yin_v"+IntegerToString(z),
                                   central_price[z],price[z+1],time[z],time[z],width_yin_main,color_yin_main);
            func_create_trend_line(IntegerToString(magic_numb)+"_trend_yang_v"+IntegerToString(z),
                                   central_price[z],price[z],time[z],time[z],width_yang_main,color_yang_main);
           }
        }
      //--- check for the pass conditions (pass is present)
      //--- draw the horizontals
      if(type_line_end[z-1]==0)
        {
         func_create_trend_line(IntegerToString(magic_numb)+"_trend_h"+IntegerToString(z),
                                price[z],price[z],time[z-1],time[z],width_yin_main,color_yin_main);
        }
      if(type_line_end[z-1]==1)
        {
         func_create_trend_line(IntegerToString(magic_numb)+"_trend_h"+IntegerToString(z),
                                price[z],price[z],time[z-1],time[z],width_yang_main,color_yang_main);
        }
      //--- draw the horizontals
     }
  }

3.8. Ek Etiketler Uygulama

Yukarıda daha önce de belirttiğim gibi, gösterge ek etiketler uygular. Ana grafikte bu etiketleri sağlayan fonksiyonu inceleyelim. Burada iki etiket türü vardır: ters çevirme fiyatı ve "fiyat etiketi" ve "dikey etiket" aracılığıyla gösterilen ters çevirme zaman etiketleri. Aşağıdaki parametreler giriş parametreleri olarak aktarılır: ters fiyat etiketi çiziminin ve etiketin renginin öznitelikleri, ters çevirme zaman etiketi çiziminin ve etiketin renk değişiminin, ters çevirme süresinin birinci ve ikinci renklerinin öznitelikleri.

Tüm fonksiyon iki kısma ayrılmıştır: ilk kısım zaman etiketlerinden, ikincisi ise fiyat etiketlerinden sorumludur. Fonksiyonun her iki parçası da grafik ters çevirme sayısıyla ("a" değişkeni) sınırlandırılan döngülerden oluşur. if-else koşullu ifadesi döngüden önce ayarlanır. İfade, gösterge ayarlarına göre çizimlerinin gerekliliğini kontrol eder.

İlk döngü zaman etiketleri oluşturur, nesne adı tanımı döngünün başında gerçekleştirilir (ad oluşturma ilkesi yukarıda açıklanmıştır). Daha sonra, renk genel olarak bildirilen çizgi türü dizisindeki çizgiye göre seçilir (parametre ayarlanmışsa) ve diğer parametreler çizgiye uygulanır.

İkinci döngü ters fiyat etiketleri oluşturmaktan sorumludur. İlk olarak, nesne adı oluşturulur. Daha sonra, Kagi'nin ana grafik üzerinde oluşturulup oluşturulmayacağına göre zaman dizisi indis seçimi belirlenir. Bu yapılmazsa, etiketler "havada" yer alacak ve ters çevirmenin hangi yerden gerçekleştiği yeterince net olmayacaktır. Ardından, "fiyat etiketi" türü nesne oluşturulur ve yapılandırılır.

//+------------------------------------------------------------------+
//| Func Label Main Chart                                            |
//+------------------------------------------------------------------+
void func_label_main_chart(bool label_print,
                           color label_color,
                           bool time_change_print,
                           bool time_change_color,
                           color time_color_first,
                           color time_color_second)
  {
   if(time_change_print==true)
     {
      for(uint z=1; z<=a; z++)
        {
         string name=IntegerToString(magic_numb)+"_time_2_"+IntegerToString(z);
         //--- create an object of a vertical line type
         ObjectCreate(0,name,OBJ_VLINE,0,time_change[z],0);
         //--- set the line color
         color color_line=clrBlack;
         if(time_change_color==true)
           {
            if(time_line[z]==0)color_line=time_color_first;
            if(time_line[z]==1)color_line=time_color_second;
           }
         else color_line=time_color_first;
         ObjectSetInteger(0,name,OBJPROP_COLOR,color_line);
         //--- set the line display style
         ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID);
         //--- set the line width
         ObjectSetInteger(0,name,OBJPROP_WIDTH,1);
         //--- display on the foreground (false) or background (true)
         ObjectSetInteger(0,name,OBJPROP_BACK,false);
         //--- enable (true) or disable (false) the line display mode in the chart subwindows
         ObjectSetInteger(0,name,OBJPROP_RAY,time_separate_windows);
        }
     }
   if(label_print==true)
     {
      for(uint z=1; z<=a; z++)
        {
         string name=IntegerToString(magic_numb)+"_label_2_"+IntegerToString(z);
         uint numb_time;
         if(kagi_main_chart==true)numb_time=z;
         else numb_time=z-1;
         //--- create a label type object
         ObjectCreate(0,name,OBJ_ARROW_RIGHT_PRICE,0,time_change[numb_time],time_change_price[z]);
         //--- set the label color
         ObjectSetInteger(0,name,OBJPROP_COLOR,label_color);
         //--- set the edging line style
         ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID);
         //--- set the label size
         ObjectSetInteger(0,name,OBJPROP_WIDTH,1);
         //--- display on the foreground (false) or background (true)
         ObjectSetInteger(0,name,OBJPROP_BACK,false);
        }
     }
  }

Şimdi, etiketleri gösterge penceresinde nasıl ayarlayabileceğimizi görelim.

Gösterge penceresindeki tüm etiketler çoğunlukla fiyattır ve bunların sadece iki türü vardır: ters çevirme fiyat etiketleri ve fiyat seviyeleri. Fiyat seviyelerini çizmenin iki türü vardır: grafik ters çevirmelerinde ve tüm grafik fiyat aralığının eşit bir mesafesinde. İlk tür seviyelerin rengini iki şekilde değiştirebilir: çizgi türüne (Yin veya Yang) göre ve ters çevirmeye (yukarı veya aşağı) göre.

Bu nedenle, fonksiyonun kendisi iki döngüye ayrılır: birincisi ters çevirme fiyat etiketlerini oluşturmaktan sorumludur, ikincisi ise fiyat seviyelerinin belirlenmesi ile ilgilidir. İkincisi iki türe daha ayrılır: her ters çevirmede etiket veya eşit seviyede fiyat aralığının her yerinde etiketler.

Bu fonksiyon, büyük sayılarda bunların grafiğin anlaşılmasını zorlaştıran şekilde aşırı yüklenmesi nedeniyle fiyat etiketlerinin ve seviyelerinin sayısında sınırlamalar olmasından dolayı öncekinden farklıdır.

Bu özellik nedeniyle, her iki döngü de gösterge ayarlarında belirtilen geçiş sayısıyla (fiyat etiketlerinin ve seviyelerinin sayısı) sınırlıdır. Böyle bir yaklaşım tehlikelidir, çünkü ters çevirme sayısı ayarlarda ayarlanan fiyat etiketlerinin sayısından çok daha küçük olabilir. Bu nedenle, her döngü geçişi sırasında ters çevirme varlığı bir fiyat etiketi veya seviyesi çizimi için kontrol edilir.

Tek istisna, tüm fiyat aralığı boyunca eşit mesafede fiyat seviyeleri çizilmesidir. "Fiyat etiketi" türü grafik nesnelerinin oluşturulması, koordinatlarda ters sırada gerçekleştirilir, yani etiketler mevcut tarihten geçmişe doğru yerleştirilir. Aynı şey fiyat seviyeleri için de geçerlidir: mevcut fiyat seviyeleri önce, daha öncekiler ise sonra oluşturulur. İstisnalar, grafik ters çevirmelerine bağlı olmayan fiyat seviyeleridir.

Fiyat seviyesi renk değişiklikleri ayarlara göre if-else koşullu ifadeleri kullanılarak yapılır.

//+------------------------------------------------------------------+
//| Func Label Indicator Window                                      |
//+------------------------------------------------------------------+
void func_label_indicator_window(bool label_print,         // Draw price labels
                                 bool levels_print,        // Draw levels
                                 char levels_type_draw,    // Type of drawing the levels by reversals or at an equal distance of the entire price range
                                 char levels_color_change) // Change line color
  {
   uint number=a;
   if(label_print==true)
     {
      for(uint z=0; z<=label_1_number; z++)
        {
         if(z<number)
           {
            string name=IntegerToString(magic_numb)+"_label_1_"+IntegerToString(z);
            //--- create label type object
            ObjectCreate(0,name,OBJ_ARROW_RIGHT_PRICE,ChartWindowFind(),(datetime)Time[(bars_copied_time-z-2)],time_change_price[number-z]);
            //--- set the label color
            ObjectSetInteger(0,name,OBJPROP_COLOR,label_1_color);
            //--- set the style of the edging line
            ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID);
            //--- set the label size
            ObjectSetInteger(0,name,OBJPROP_WIDTH,1);
            //--- display on the foreground (false) or background (true)
            ObjectSetInteger(0,name,OBJPROP_BACK,false);
           }
        }
     }
   if(levels_print==true)
     {
      if(levels_type_draw==0)
        {
         for(uint z=0; z<=levels_number; z++)
           {
            if(z<number)
              {
               IndicatorSetDouble(INDICATOR_LEVELVALUE,z,time_change_price[number-z]);
               if(levels_change_color==0)
                 {
                  double numb_even=z;
                  if(MathMod(numb_even,2)==0)
                    {
                     IndicatorSetInteger(INDICATOR_LEVELCOLOR,z,levels_first_color);
                    }
                  if(MathMod(numb_even,2)!=0)
                    {
                     IndicatorSetInteger(INDICATOR_LEVELCOLOR,z,levels_second_color);
                    }
                 }
               if(levels_change_color==1)
                 {
                  if(time_line[number-z]==0)IndicatorSetInteger(INDICATOR_LEVELCOLOR,z,levels_first_color);
                  if(time_line[number-z]==1)IndicatorSetInteger(INDICATOR_LEVELCOLOR,z,levels_second_color);
                 }
               if(levels_change_color==2)
                 {
                  IndicatorSetInteger(INDICATOR_LEVELCOLOR,z,levels_first_color);
                 }
              }
           }
        }
      if(levels_type_draw==1)
        {
         double max_price=Price[ArrayMaximum(Price)];
         double min_price=Price[ArrayMinimum(Price,1,ArrayMinimum(Price)-1)];
         double number_difference=(max_price-min_price)/levels_number;
         NormalizeDouble(number_difference,_Digits);
         for(uint z=0; z<=levels_number; z++)
           {
            IndicatorSetDouble(INDICATOR_LEVELVALUE,z,(min_price+(z*number_difference)));
            IndicatorSetInteger(INDICATOR_LEVELCOLOR,z,levels_first_color);
           }
        }
     }
  }

3.9. Önceden Oluşturulmuş Grafik Nesnelerini Silme

Bu göstergenin grafik nesneleri açısından zengin olduğunu zaten biliyoruz. Bunları hızlı ve verimli bir şekilde nasıl silebileceğimizi düşünmenin zamanı geldi.

Bu görev, grafik nesnelerini silme fonksiyonu tarafından yürütülür. Fonksiyon parametreleri olarak başlangıç adı ve nesne sayısı kullanılır. Oluşturma sırasında olduğu gibi, nesne adı sihirli sayıyı ve nesne türünün adını içermelidir. Programdaki fonksiyon çağrısı, bunların olası varlıklarını aşan nesne sayısı ile sınırlıdır. Ancak bu, göstergenin fonksiyonelliğini etkilemez.

//+------------------------------------------------------------------+
//| Func Delete Objects                                              |
//+------------------------------------------------------------------+
void func_delete_objects(string name,
                         int number)
  {
   string name_del;
   for(int x=0; x<=number; x++)
     {
      name_del=name+IntegerToString(x);
      ObjectDelete(0,name_del);
     }
  }

3.10. Grafik Oluşumunu Başlatma Fonksiyonu

Şimdi, Kagi grafiğinin hesaplanması ve oluşumunun yanı sıra nesnelerin oluşturulması ve silinmesi için tüm fonksiyonları inceledikten sonra, yeni çubuğun varışını kontrol etmek için başka bir küçük fonksiyon düşünmeliyiz. Fonksiyon oldukça basittir ve bir giriş parametresine sahiptir: analiz edilen dönem. Fonksiyonun cevabı da çok basittir. Bu, bool türündedir ve yeni bir çubuğun bulunup bulunmadığının cevabını içerir. Fonksiyon gövdesinin temeli, kontrolü döneme bağlı olarak farklı ifadelerine geçiren switch ifadesidir.

Örnekte, fonksiyon tüm dönem aralığını kapsar, ancak yalnızca bir dönem de kullanılabilir.

Fonksiyon algoritması IsNewBar kodundan alınmıştır: son çubuğun açılma zamanı önceden tanımlanmış zaman değeri ile karşılaştırılır. Değerler farklıysa yeni bir çubuk vardır. Yeni değer daha önce tanımlanmış olarak atanır ve fonksiyonun cevabı pozitif olarak kabul edilir. Son çubuk açılış saati önceden belirlenmiş zaman değeriyle çakışıyorsa, yeni çubuk henüz görünmemiştir ve fonksiyonun cevabı negatiftir.

//+------------------------------------------------------------------+
//| Func New Bar                                                     |
//+------------------------------------------------------------------+
bool func_new_bar(ENUM_TIMEFRAMES period_time)
  {
//----
   static datetime old_Times[22];// array for storing old values
   bool res=false;               // analysis result variable  
   int  i=0;                     // old_Times[] array cell index    
   datetime new_Time[1];         // new bar time

   switch(period_time)
     {
      case PERIOD_M1:  i= 0; break;
      case PERIOD_M2:  i= 1; break;
      case PERIOD_M3:  i= 2; break;
      case PERIOD_M4:  i= 3; break;
      case PERIOD_M5:  i= 4; break;
      case PERIOD_M6:  i= 5; break;
      case PERIOD_M10: i= 6; break;
      case PERIOD_M12: i= 7; break;
      case PERIOD_M15: i= 8; break;
      case PERIOD_M20: i= 9; break;
      case PERIOD_M30: i=10; break;
      case PERIOD_H1:  i=11; break;
      case PERIOD_H2:  i=12; break;
      case PERIOD_H3:  i=13; break;
      case PERIOD_H4:  i=14; break;
      case PERIOD_H6:  i=15; break;
      case PERIOD_H8:  i=16; break;
      case PERIOD_H12: i=17; break;
      case PERIOD_D1:  i=18; break;
      case PERIOD_W1:  i=19; break;
      case PERIOD_MN1: i=20; break;
      case PERIOD_CURRENT: i=21; break;
     }
   // copy the time of the last bar to new_Time[0] cell  
   int copied=CopyTime(_Symbol,period_time,0,1,new_Time);
  
   if(copied>0) // all is well. Data has been copied
      {
      if(old_Times[i]!=new_Time[0])       // if the bar's old time is not equal to new one
         {
         if(old_Times[i]!=0) res=true;    // if it is not the first launch, true = new bar
         old_Times[i]=new_Time[0];        // store the bar's time
         }
      }
//----
   return(res);
  }

 

3.11. OnCalculate() ve OnChartEvent() Fonksiyonları

Yukarıda açıklanan tüm fonksiyonlar aynı adı taşıyan fonksiyonda birleştirilir: Func (Fonksiyon) Birleştirme. Bu fonksiyon, OnCalculate() fonksiyonunda her yeni çubuk göründüğünde ve OnChartEvent() fonksiyonundan "R" tuşuna basıldığında başlatılır. 

Grafik oluşturulmadan veya güncellenmeden önce, tüm grafik nesneleri silme fonksiyonu birleştirme fonksiyonunda (Fonksiyon Birleştirme) çağrılır. Oldukça fazla nesne olduğundan ve bunlar ana grafik ve gösterge penceresinin fiyat etiketlerine, ters çevirme zamanını gösteren dikey çizgilere ve Yin ve Yang dikey ve yatay trend çizgilerine ayrıldığından, fonksiyon çağrılarının genel sayısı 7'dir.

Daha sonra geçmiş verileri fiyat ve zamana göre kopyalanır. Kagi grafiği oluşturmak için ana fonksiyon daha sonra başlatılır. Bundan sonra, tüm fiyat etiketlerini ana grafiğe ve gösterge penceresine yerleştirme fonksiyonu çağrılır. Son olarak, Kagi ana grafikte oluşturulur ve nesneleri yeniden çizme fonksiyonu başlatılır.

//+------------------------------------------------------------------+
//| Func Consolidation                                               |
//+------------------------------------------------------------------+
void func_consolidation()
  {
//--- date of construction end
   stop_data=TimeCurrent();

//--- deleting all graphical objects belonging to the indicator
   func_delete_objects(IntegerToString(magic_numb)+"_label_2_",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_label_1_",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_time_2_",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_trend_yin_v",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_trend_yang_v",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_trend_h",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_trend_h",ObjectsTotal(0,-1,-1));

//--- copy price data to the main buffer
   copy_history=func_copy_history(Price,start_data,stop_data);

//--- display information about the error when copying price data
   if(copy_history==false)Alert("Error of copy history Price");

//--- copy time data to the main buffer
   copy_time=func_copy_time(Time,start_data,stop_data);

//--- display a notification of the error occurred while copying time data
   if(copy_time==false)Alert("Error of copy history Time");

//--- construct Kagi chart in the indicator window
   func_draw_kagi(Price,YinBuffer1,YinBuffer2,Yin1Buffer,Yin2Buffer,Yin3Buffer,
                  YangBuffer1,YangBuffer2,Yang1Buffer,Yang2Buffer,Yang3Buffer,Time);

//--- draw labels on the main chart
   func_label_main_chart(label_2,label_2_color,time_line_draw,time_line_change_color,time_first_color,time_second_color);

//--- draw labels on the indicator chart
   func_label_indicator_window(label_1,levels_on_off,levels_type,levels_change_color);

//--- construct Kagi chart in the main window
   if(kagi_main_chart==true)func_kagi_main_chart(time_change_price,time_central_price,time_change,time_line);

//--- redraw the chart
   ChartRedraw(0);
//---
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
//---
   if(func_new_bar(period_to_redraw)==true)
     {
      func_consolidation();
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| OnChartEvent                                                     |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,         // event ID  
                  const long& lparam,   // long type event parameter
                  const double& dparam, // double type event parameter
                  const string& sparam) // string type event parameter
  {
   if(id==CHARTEVENT_KEYDOWN) // Keyboard button pressing event
     {
      if(lparam==82) // "R" key has been pressed
        {
         func_consolidation();
        }
     }
  }

 

3.12. OnDeinit() Fonksiyonu

Tüm nesnelerin silinmesi gösterge sonlandırma fonksiyonunda gerçekleştirilir.

//+------------------------------------------------------------------+
//| OnDeinit                                                         |
//+------------------------------------------------------------------+ 
void OnDeinit(const int reason)
  {
//--- delete all graphical objects belonging to the indicator
   func_delete_objects(IntegerToString(magic_numb)+"_label_2_",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_label_1_",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_time_2_",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_trend_yin_v",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_trend_yang_v",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_trend_h",ObjectsTotal(0,-1,-1));
   func_delete_objects(IntegerToString(magic_numb)+"_trend_h",ObjectsTotal(0,-1,-1));
//--- redraw the chart
   ChartRedraw(0);
  }

Şimdi, göstergeyi pratikte kullanmaya geçelim.


4. Pratikte Kagi Grafiğini Kullanma

Kagi grafiğine dayalı birçok alım satım stratejisi vardır. Bazılarını inceleyeceğiz.

En popüler strateji ile başlayalım: Yang Yin'e dönüştüğünde sat ve tam tersi durumda satın al. Bu Şekil 4'te gösterilmektedir:

Çizgi geçişleri sırasında satın alma ve satma stratejisi

Şekil 4. Yang, Yin'e dönüştüğünde satmak ve tersi durumda satın almak

Şekil 4'te görüldüğü gibi (EURUSD M30, 5 nokta), bu strateji iyi sonuçlar göstermektedir. Şekil 4 sinyal için 8 nokta gösterir, ilki (1) uzun pozisyonun 1,3518'de açılması gerektiğini gösterir, bu da fiyat daha sonra günde 42 noktayı içine alarak yaklaşık 1,3560'a ulaştığı için doğru görünüyor. Bu iyi bir sonuç.

Bir sonraki nokta (2) 1,3519'dan satışı önerir. Gördüğümüz gibi, fiyat aslında yaklaşık iki saat boyunca 1,3485 seviyesini (ve 34 noktayı kapsayan) geçerek aşağı doğru hareket ediyor.

Noktaya (3) geçelim. Uzun pozisyon 1,3538'den açılır ve fiyat 1,3695'e kadar yükselir. Böylece, kâr zaten bir buçuk gün için 157 noktayı içerir. Tabii ki, bunlar mümkün olan en yüksek karlardır, ancak sonuç hala yeterince iyidir.

Bir sonraki alım satım stratejisi, Şekil 5'te (EURUSD M30, 5 puan), 7-18 Ekim'de gösterilen trend çizgisinden geri dönüyor:

Trend çizgisinden geri dönüş

Şekil 5. Trend çizgisinden geri dönüş

Daha da ilerleyebilir ve kanalları takip ederek alım satım yapabiliriz. Bir kanal arama örneği Şekil 6'da (EURUSD H1, 5 puan), kabaca aynı dönemde incelenebilir:

Kanallar ile alım satım

Şekil 6. Kanallar ile alım satım

7-10 ardışık olarak artan "omuzlar" veya azalan "beller" sonrasında, kesinlikle bir ters çevirme olacağı (düşüş veya yükseliş) gerçeğine dayanan daha az popüler strateji.

Bu, Şekil 7'de (GBPUSD H4, 25 nokta), 10 Temmuz - 18 Ekim'de gösterilir:

7-10 ardışık olarak artan "omuzlar" veya azalan "beller"

Şekil 7. 7-10 ardışık olarak artan "omuzlar" veya azalan "beller"

Görüntüde de görülebileceği gibi, yedi yükselen omuzu, kabaca önceki yükselişin yarısına (yaklaşık 300 nokta) eşit olarak oldukça önemli bir düşüş izler.

Ek gösterge parametrelerinin kullanılmasının gerekliliğini göstermek için "Fiyat etiketi üzerinden alım satım" stratejisini inceleyelim. Fikir, fiyat bir önceki fiyat etiketini aştığında (alış) veya altında hareket ettiğinde (satış) piyasaya girmektir.

Strateji Şekil 8'de gösterilmektedir (GBPUSD H4, 30 puan, değiştirilmiş yapı):

Bir fiyat etiketi yoluyla alım satım

Şekil 8. Bir fiyat etiketi yoluyla alım satım

Şekil 8'deki kırmızı oklar ne zaman alış veya satış yapılacağını gösterir. Oklar, önceki fiyat etiketlerinin kırıldığı konumları görüntüleyen önceki fiyat etiketinden hareket etmektedir.

Zaman etiketleri esas olarak trend yönü işaretçileri olarak hizmet eder. Zaman etiketlerinin rengi çizgi türüne göre değiştirilebildiğinden ve Yin veya Yang çizgi türü trend yönünü veya tersine çevirmeyi gösterdiğinden, renk mevcut piyasa havasını tanımlamamıza yardımcı olabilir.

Örneğin, Şekil 9'da gösterilen #IBM hisse senedi grafiğini (H4, %1, standart yapı) alalım:

Zaman etiketlerini kullanarak trend yönünü tanımlama

Şekil 9. Zaman etiketlerini kullanarak trend yönünü tanımlama

Grafik, mavi çizgilerin çoğunlukla grafiğin üst kısımlarında, kırmızı çizgilerin ise alt kısımlarda bulunduğunu gösterir.


Sonuç

Kagi grafiği, strateji temeli olarak veya daha hassas analiz için yardımcı bir araç olarak piyasa alım satımı için başarıyla kullanılabilir.

Bu makalede, kodun kendisini ve göstergeyi oluşturmanın bazı özelliklerini inceledim. Ana amaç, devre dışı bırakılabilen bazı ekstra özelliklere sahip gerekli tüm unsurları içeren çok fonksiyonu göstergenin oluşturulması olmuştur.

Gösterge için yeni fikirleri ve iyileştirmeleri düşünmeyi ve belki de gelecekte uygulamayı memnuniyetle karşılarım. Ayrıca, lütfen bana geri bildiriminizi sağlayın. Göstergeyle ilgili sorularınızı yanıtlamaktan mutluluk duyarım.

Bu makale, geçmişten grafikleri oluşturmak için göstergeler geliştirmeye adanmış serinin devamıdır. Önceki makale burada bulunabilir. Seri devam edecek ve umarım yakında tekrar karşılaşırız. İlginiz için teşekkür ederiz! Size başarılı alım satım ile optimize edilmiş ve istikrarlı kodlar diliyorum.


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

Ekli dosyalar |
bkcv.mq5 (44.19 KB)
Ekonometrik EURUSD Bir Adım İlerisi Tahmini Ekonometrik EURUSD Bir Adım İlerisi Tahmini
Makale, EViews yazılımının kullanılması ile, EURUSD için bir adım ilerisi tahminine ve EViews'teki programları kullanarak tahmin sonuçlarının daha fazla değerlendirilmesine odaklanır. Tahmin, regresyon modellerini içerir ve MetaTrader 4 için geliştirilmiş bir Uzman Danışman aracılığıyla değerlendirilir.
Çok Para Birimli, Çok Sistemli bir Uzman Danışman Oluşturma Çok Para Birimli, Çok Sistemli bir Uzman Danışman Oluşturma
Makale, eş zamanlı olarak birçok sembolün alım satımını yapan veya birkaç alım satım sistemini kullanan bir Uzman Danışman yapısını tanıtmaktadır. Tüm EA'larınız için optimum giriş parametrelerini zaten tanımladıysanız ve ayrı olarak bunlardan her biri için iyi geri dönük test sonuçları elde ettiyseniz, kendinize sorun: Tüm stratejilerinizin bir araya getirildiği tüm EA'larınız eş zamanlı olarak test edilseydi sonuçları ne olurdu?
MQL5 Programlama Temelleri: Listeler MQL5 Programlama Temelleri: Listeler
Alım satım stratejisi geliştirme için programlama dilinin yeni sürümü olan MQL [MQL5], önceki versiyona [MQL4] kıyasla daha güçlü ve etkili özellikler sunar. Avantaj, esasen nesne yönelimli programlama özelliklerinde yatmaktadır. Bu makale, düğümler ve listeler gibi karmaşık özel veri türleri kullanma olasılığını inceler. Ayrıca MQL5'te pratik programlamada listelerin kullanımına bir örnek sağlar.
MQL5 Tarif Defteri MQL5'te Çok Sembollü Volatilite Göstergesi Geliştirme MQL5 Tarif Defteri MQL5'te Çok Sembollü Volatilite Göstergesi Geliştirme
Bu makalede, çok sembollü bir volatilite göstergesinin geliştirilmesini ele alacağız. Çok sembollü göstergelerin geliştirilmesi, acemi MQL5 geliştiricileri için bazı zorluklar ortaya çıkabilir, bu makale de bunun açıklığa kavuşturulmasına yardımcı olur. Çok sembollü bir göstergenin geliştirilmesi sırasında ortaya çıkan önemli sorunlar, diğer sembollerin verilerinin mevcut sembole göre senkronize edilmesi, bazı gösterge verilerinin olmaması ve belirli bir zaman aralığının "true" çubuklarının başlangıcının tanımlanması ile ilgilidir. Bu konuların tamamı makalede yakından ele alınacaktır.