English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Italiano
Fiyat Histogramı (Piyasa Profili) ve MQL5'te uygulanması

Fiyat Histogramı (Piyasa Profili) ve MQL5'te uygulanması

MetaTrader 5Örnekler | 10 Aralık 2021, 17:03
188 0
Dmitry Voronkov
Dmitry Voronkov

"Piyasa Profili, bu dahili mantığı piyasa bağlamında sağlamaya çalışır.
Bu, tıpkı
sözdizimi veya bağlamı olmayan sözcüklerin
herhangi bir anlamı olmayabileceği gibi, fiyatın tek başına katılımcıya bilgi iletmediği anlayışıyla başlayan bir analiz yöntemidir. Hacim, piyasanın doğrudan ifadesinin ayrılmaz bir
parçasıdır; onu anlarsanız piyasanın dilini de kavrarsınız."
Robin Mesh

Giriş

Çok uzun zaman önce, bir dergi aboneliğine bakarken, Rus dergisi "Valutny Spekulant"ta (Şu anda "Active Trader" adıyla yayınlanıyor) "Piyasa Profili ve piyasa dilini anlama" (Ekim, 2002) adlı bir makale buldum. Orijinal makale "New Thinking in Technical Analysis: Trading Models from the Masters" adıyla yayınlandı.

Üyeler Profili, gerçekten parlak bir düşünür olan Peter Steidlmayer tarafından geliştirildi. Piyasanın doğal ifadesini (hacim) buldu ve onu okunabilir bir şekilde (çan eğrisi) düzenledi; böylece piyasa tarafından üretilen nesnel bilgiler, piyasa katılımcıları tarafından erişilebilir oldu. Steidlmayer, tamamen farklı model kümelerine yol açan "yatay" ve "dikey" piyasa hareketleri hakkındaki bilgilerin alternatif temsilini kullanmayı önerdi. Piyasanın altında yatan bir nabzın ya da denge ve dengesizlik döngüsü olarak adlandırılan temel bir modelin olduğunu varsaydı.

Piyasa Profili, dikey piyasa boyunca yatay piyasa hareketini ölçer.  Buna "dengesizlik" yoluyla "denge" diyelim. Bu ilişki, piyasanın temel teşkilatlanma prensibidir. Bir yatırımcının tüm alım satım tarzı, piyasanın denge/dengesizlik döngüsünün hangi kısmında olduğuna bağlı olarak değişebilir. Piyasa Profili, piyasanın ne zaman dengeden dengesizliğe geçeceğini ve hareketin ne kadar büyük olacağını belirleyebilir.

Piyasa Profilinin iki temel kavramı şunlardır:

  1. Piyasa bir müzayededir ve arz ve talebin aşağı yukarı eşit olduğu fiyat aralığı yönünde hareket eder.
  2. Piyasanın iki aşaması vardır: Yatay aktivite ve dikey aktivite. Piyasa arz ve talep eşit olmadığında veya dengesiz olduğunda dikey, dengede veya dengeli olduğunda yatay olarak hareket eder.

Aşağıdaki grafikte Piyasa Profili kullanılarak gösterilen denge piyasası, grafiğin oryantasyonu nedeniyle 90 derece döndürülmüş, neredeyse mükemmel bir çan eğrisi oluşturma eğilimindedir:

 

Şek. 1. Denge piyasasının Piyasa Profili

Trend, denge dışı piyasa da çan eğrisi oluşturur, ancak merkezi yukarı veya aşağı kaydırılır. Fiyat hareketine ve piyasa oyuncularının güvenine bağlı olarak iki çan tepe noktası oluşturan diğer yapılandırmalar da mümkündür.

Şek. 2. Dengesizlik (trend) piyasasının Piyasa Profili

Piyasanın denge/dengesizlik düzeyini belirlemek için günlük profil şekillerini kullanmak faydalı olabilir; zira size çeşitli piyasa katılımcıları arasındaki geçişleri anlamada bir başlangıç noktası verir.

Dengeden dengesizliğe geçiş gerçekleşmek üzereyken, en büyük faydaya sahip bir alım satım fırsatı ortaya çıkar. Ayrıca, bu alım satım fırsatını tanımlayabilir ve bu geçişin potansiyel büyüklüğünü doğru bir şekilde tahmin edebilirseniz o alım satım işleminin kalitesini ve bunun için gerekli olan süreyi öngörebilirsiniz.

Bu makalede, fiyat ve zaman arasındaki ilişkiyi temel alan Fiyat Histogramı olarak adlandırılan Piyasa Profilinin basitleştirilmiş bir sürümünü çizme kodunu ele alacağımızı belirtmek gerekir.

Bu araçla çalışma metodolojisi örneğini bir grup yatırımcının 1998'den beri Fiyat Histrogramını incelediği http://www.enthios.com/ adresinde bulabilirsiniz. Ayrıca Enthios Universal stratejisi ve bunun kullanım örneği de burada bulunabilir.

1. Fiyat Histogramı

Fiyat Histogramı çok güvenilir bir araçtır. Biraz sezgiseldir ama son derece etkilidir. Fiyat histogramı size yalnızca piyasanın "en uygun" alım satım işlemi noktalarını gösterir. Bu, önde gelen bir göstergedir; zira piyasanın yönünü önceden değiştirebileceği noktaları gösterir. Hareketli ortalamalar veya osilatörler gibi göstergeler tam direnç ve destek noktalarını belirleyemezler, yalnızca piyasanın aşırı alım ve aşırı satım durumlarını gösterebilirler.

Genellikle, Fiyat Histogramı (veya Piyasa Profili) bir gün boyunca piyasa aktivitesini incelemek için 30 dakikalık fiyat grafiklerine uygulanır. Ben borsalar için 5 dakikalık, FOREX için 15-30 dakikalık grafikleri kullanmayı tercih ederim.

2. Kontrol Noktası

Yukarıdaki şekilde, piyasanın alım satım işlemi yaptığı maksimum süre düzeyini görebilirsiniz; bu, histogramda en uzun çizgiyle özetlenmiştir. Bu, Kontrol Noktası veya POC olarak adlandırılır. Bazen, şekilde görüldüğü gibi, histogramın iki tepesi vardır; bunlardan biri biraz daha aşağıdadır. Böyle bir durumda, göstergenin yalnızca bir POC'yi gösterdiğini görürüz, ancak aslında bunlardan iki tane vardır ve göz önünde bulundurulması gerekir.

Ayrıca, histogramdaki aralığın yüzde düzeyi, İkincil POC düzeyleri olarak adlandırılan ek düzeyler de oluşturur:

Şek. 3. Kontrol noktaları

POC neyi gösterir? Yatırımcıların çoğu tarafından hatırlanan fiyatı. Piyasa bu fiyattan ne kadar uzun süre alım satım yaparsa bunu o kadar uzun süre hatırlar.

Psikolojik olarak, POC bir çekim merkezi görevi görür.

Bir sonraki grafikte, birkaç gün önce ne olduğu gösterilmektedir. Bu, Fiyat Histogramının gücünün iyi bir göstergesidir.

Şek. 4. Kontrol Noktası mutlak değildir; alım satım aralığını gösterir

Kontrol Noktası mutlak değildir; alım satım işlemi aralığını gösterir. Bu nedenle, yatırımcı, piyasa POC'ye yaklaştığında harekete geçmeye hazır olmalıdır. Geçmiş gözlemleri kullanarak talimatları optimize etmeye yardımcı olur.

Şekil 4'ü ele alalım. 29.12.2009 tarihinde POC 68,87 fiyatındadır. Histogram ve POC çizgisi olmadan dahi piyasanın neredeyse tüm gün 68,82~68,96 aralığında olduğu açıktır. Piyasa, günün sonunda POC'nin 5 puan altında kapanmıştır. Ertesi gün piyasanın aşağı yönlü bir boşlukla açılmasına neden olmuştur.

Piyasanın yukarı yönde mi yoksa aşağı yönde mi hareket edeceğini tahmin edemeyeceğimizi anlamak önemlidir. Yalnızca piyasanın POC çizgisine ve histogram çizgilerinin maksimum birikimine döneceğini varsayabiliriz. Ancak fiyat POC'ye eriştiğinde ne olacak? Yere düşen elastik bir nesneye benzer şekilde geri sıçrayacaktır.  Bu, hızlı bir şekilde gerçekleşirse bir tenis topunun raketle geri vuruşu gibi, fiyat çok hızlı bir şekilde başlangıç düzeyine geri dönecektir.

30.12.2009 tarihindeki piyasa açılışından sonra bunun bir boşluk olduğunu ve ardından piyasanın önceki günün POC'sine eriştiğini ve daha sonra hızlı bir şekilde açılış fiyatına döndüğünü ve minimumu güncellediğini görüyoruz.

POC'nin kesinlikle doğru olmadığını unutmayın (deneyimli yatırımcılar, fiyat maksimum, minimum veya konsantrasyon aralığına ulaştığında net bir direnç düzeyi olmadığını bilir). Bu noktada ne olacağı piyasa oyuncularına bağlıdır. Kolektif arzu (örneğin, haber yayını) çakışırsa piyasa POC'den geçecektir, ancak bu nadirdir ve bir alım satım sistemi geliştirmek için kullanılabilir.

31.12.2009'da piyasa davranışının aynı olduğuna dikkat edin. Fiyat POC'ye eriştiğinde alıcılar satıcılara boyun eğdi.

3. El Değmemiş Kontrol Noktası

El Değmemiş POC (El Değmemiş Kontrol Noktası), fiyatın önümüzdeki günlerde ulaşamadığı düzeydir.

Mantık basittir; yukarıda açıklandığı gibi, POC piyasa için bir çekim noktasıdır. Fiyat POC'den uzaklaştıkça çekim gücü artar. Ve fiyat El Değmemiş POC'den ne kadar uzaklaşırsa bu düzeye döndüğünde yeniden yükselişin meydana gelme ve muhtemelen bir fiyatın tersine dönme olasılığı da o kadar yüksek olur.

Şek. 5. Önceki ve şimdiki El Değmemiş POC

Şek. 5'te, destek ve direnç düzeyleri olan önceki El Değmemiş POC'ler dairelerle işaretlenmiştir. Çalışan El Değmemiş POC, fiyat değerleriyle işaretlenmiştir.

Fiyat El Değmemiş POC'ye dokunduğunda, "el değmemiş" olmaktan çıkar. Psikolojik olarak, piyasa artık bunu önemli bir destek veya direnç düzeyi olarak görmez. Yatırımcılar, başlangıçta POC'yi oluşturan fiyat düzeylerini, ancak basit bir fiyat birikimi olarak görebilirler.

Fiyat düzeyleri hakkında daha fazla ayrıntıyı Eric Naiman'ın "Master-trading: The X-Files" kitabında bulabilirsiniz (Bölüm 4, "Price Level is a base line").

4. MQL5'te Fiyat Histogramı Uygulaması

Fiyat Histogramının ilk sürümü 2006'da piyasaya çıktı, kişisel kullanım için MetaTrader4'te MQL4'te yazılmıştı. Bu göstergenin geliştirilmesi sırasında bazı sıkıntılarla karşılaştım; bunlardan bazıları şu şekildedir:

    1. M1 bir yana, M5 için geçmişte çok az sayıda çubuk,
    2. Tatilleri göz önünde bulundurarak bir gün önce geri dönmek, Cuma günü piyasa kapanış saatini kontrol etmek, CFD piyasası için açılış ve kapanış saatini kontrol etmek gibi geçmişle çalışmak için özel işlevlerin geliştirilmesi gerekliliği,
    3. Zaman dilimlerini değiştirirken göstergenin yeniden hesaplanması ve sonuç olarak terminal gecikmeleri.

    Bu nedenle, МetaТrader5 ve MQL5'in beta testi başladığında, onu MQL5'e dönüştürmeye karar verdim.

    İnsanların "ilk krep her zaman biraz ustalık ister" demesi gibi, bunu bir gösterge olarak uygulamaya çalıştım.

    İyi olanla başlayalım: Tüm semboller için uzun dakika fiyat teklifleri geçmişinin varlığı, herhangi bir zaman aralığında belirli bir zaman dilimi için tarihsel verilerin elde edilmesi olasılığı.

    Şimdi neden ortaya çıktığını açıklayacağım. MQL5 göstergelerinin özelliklerini dikkate almadım:

      1. Göstergenin çalışma zamanı kritiktir,
      2. Zaman dilimi değiştikten sonra göstergenin çalışma özellikleri.

      Calculate olay işleyicisine karşılık gelen OnCalculate() işlevinin yürütülmesi kritik bir çalışma zamanına sahiptir. Buna göre, dakika çubukları geçmişi kullanılarak 260 günün (yıllık dönem) işlenmesi, birkaç dakikaya kadar uzun bir zaman alır. Tabii ki, gösterge grafiğe eklendikten sonra hesaplamalar tek seferde yapılırsa bunu kabul edebiliriz. Ancak zaman dilimi değişiklikleri için durum böyle değildir. Gösterge farklı zaman dilimine geçtiğinde, göstergenin eski kopyası yok edilir ve yenisi oluşturulur. Bu nedenle zaman dilimi değiştikten sonra aynı düzeyleri tekrar hesaplamamız gerekiyor ve bu, çok zaman alıyor.

      Ancak ne yapacağınızı bilmiyorsanız dediğim gibi "Önce belgeleri okuyun"; bizim durumumuzda okunacak belgeler MQL5 belgeleridir. Çözüm çok basitti; bu göstergeyi alım satım işlemi yapmayan Expert Advisor olarak uygulamak.

      Expert Advisor'ın avantajları şunlardır:

        1. OnTick() içindeki Init olay işleyicisi için işlem süresi kritik değildir,
        2. OnDeinit işleyicisinin parametrelerini elde etme olasılığı (const int nedeni).

        Expert Advisor'lar göstergelerden şu açılardan farklılık gösterir: Zaman dilimi değişikliğinden sonra expert advisor REASON_CHARTCHANGE neden parametresiyle yalnızca DeInit olayını oluşturur, Expert Advisor'ı bellekten kaldırmaz ve genel değişkenler değerlerine hizmet eder. Bizim durumumuzda, yeni bir alım satım günü için Expert Advisor eklendikten, parametreleri değiştirildikten ve yeni veriler göründükten sonra tüm hesaplamaları tek seferde yapmamızı sağlar.

        Daha sonra ihtiyaç duyulacak bazı tanımları sunalım.

        Nesne yönelimli programlama (OOP), temel kavramları nesne ve sınıf kavramları olan bir programlama tarzıdır.

        Nesne, belirtilen durum ve davranışa sahip sanal alandaki bir varlıktır; bu, bazı özellik değerleri (öznitelik olarak adlandırılır) ve bunlarla ilgili işlemler (yöntem olarak adlandırılır) içerir.

        OOP'de Sınıf, yapısıyla karakterize edilen özel bir soyut veri türüdür. Sınıf, OOP'de temel bir kavramdır. Sınıf, diğer soyut veri türlerinden farklıdır. Sınıftaki veri tanımı, veri işlemenin (arayüz) sınıf yöntemlerini de içerir.

        Programlamada, algoritmalar, argümanların tanımı ve devam edilecek giriş parametrelerinin sırası ve döndürülen değerler dahil olmak üzere programın bir kısmı tarafından gerçekleştirilebilecek olası hesaplamaların bir listesi anlamına gelen bir yazılım arayüzü kavramı vardır. Soyut veri türü arayüzü, böyle bir listenin resmi bir açıklaması için geliştirilmiştir. Algoritmaların kendisi ve tüm bu hesaplamaları yapacak olan kod belirtilmez ve arayüz uygulaması olarak adlandırılır.

        Sınıf oluşturma, bazı yapıların alanlar ve yöntemlerle oluşturulmasıdır. Tüm sınıf, sınıf örnekleri olan nesnelerin oluşturulması için bir şablon olarak düşünülebilir. Sınıf örnekleri aynı şablon kullanılarak oluşturulur; bu nedenle aynı alanları ve yöntemleri içerirler.

        O halde başlayalım...

        Kaynak kodu 4 dosyada bulunur. Ana dosya PriceHistogram.mq5 olup diğer dosyalar şunlardır: ClassExpert.mqh, ClassPriceHistogram.mqh ve ClassProgressBar.mqh. .mqh uzantılı dosyalar, sınıfların açıklamalarını ve yöntemlerini içerir. Tüm dosyalar aynı dizinde yer almalıdır; Dizinim: \MQL5\ Experts\PriceHistogram.

        4.1. PriceHistogram.mq5

        Kaynak koddaki ilk ifade şudur:

        #include "ClassExpert.mqh"

        #include derleyici yönergesi, belirtilen dosyadaki metni içerir. Bizim durumumuzda bu, CExpert sınıfının tanımıdır (bu, aşağıda tartışılmıştır).

        Sonraki, Expert Advisor'ın parametreleri olan giriş değişkenleri bloğudur.

        // The block input parameters
        input int         DayTheHistogram   = 10;          // Days for histogram
        input int         DaysForCalculation= 500;         // Days for calculation(-1 all)
        input uint        RangePercent      = 70;          // Percent range
        input color       InnerRange        =Indigo;       // Inner range
        input color       OuterRange        =Magenta;      // Outer range
        input color       ControlPoint      =Orange;       // Point of Control
        input bool        ShowValue         =true;         // Show Values
        

        Bundan sonra ExtExpert değişkeni (CExpert sınıf türüne ait) bildirilir.

        Bir sonraki, MQL5 programlarında bulunan standart olay işleyicileridir. Olay işleyicileri, CExpert sınıfının karşılık gelen yöntemlerini çağırır.

        CExpert'in yürütülmesinden önce bazı işlemleri gerçekleştiren tek bir yöntem vardır; bu OnInit() yöntemidir:
        int OnInit()
          {
        //---
        // We check for symbol synchronization before the start of calculations
           int err=0;
           while(!(bool)SeriesInfoInteger(Symbol(),0,SERIES_SYNCRONIZED) && err<AMOUNT_OF_ATTEMPTS)
             {
              Sleep(500);
              err++;
             }
        // CExpert class initialization
           ExtExpert.RangePercent=RangePercent;
           ExtExpert.InnerRange=InnerRange;
           ExtExpert.OuterRange=OuterRange;
           ExtExpert.ControlPoint=ControlPoint;
           ExtExpert.ShowValue=ShowValue;
           ExtExpert.DaysForCalculation=DaysForCalculation;
           ExtExpert.DayTheHistogram=DayTheHistogram;
           ExtExpert.Init();
           return(0);
          }
        

        Expert Advisor'ın ilk sürümünü yazıp çalıştırdığımda, istemci terminali yeniden başlatıldıktan veya bir sembol değiştikten sonra neden hatayla sonlandığını anlamakta biraz sorun yaşıyorum. Bu, istemci terminalinin bağlantısı kesildiğinde veya bir sembol uzun süre kullanılmadığında ortaya çıkar.

        Geliştiricilerin hata ayıklayıcıyı MetaEditor5'e eklemesi mükemmel. MetaEditor4'te değişkenlerin değerlerini kontrol etmek için kullanılan birçok Print() ve Comment() komutunu hatırlıyorum. MetaEditor5 geliştiricilerine çok teşekkürler.

        Benim durumumda, her şey kolaydı; expert, sunucuya bağlanmadan ve geçmiş verilerin güncellenmesinden önce başlar. Bu sorunu çözmek için, verilerin senkronize olup olmadığını bildiren SeriesInfoInteger(Symbol(),0,SERIES_SYNCRONIZED) ve bağlantının olmaması durumunda err sayaç değişkenini kullanan iken () döngüsünü kullanmak zorunda kaldım.

        Veriler senkronize edildikten sonra veya bağlantı olmadığında sayaç nedeniyle döngü tamamlandığında, expert sınıfımız CExpert'in giriş parametrelerini iletir ve Init () sınıf başlatma yöntemini çağırırız.

        Gördüğünüz gibi, MQL5'teki sınıf kavramı sayesinde PriceHistogram.mq5 dosyamız basit bir şablona dönüştü; bundan sonraki tüm işlemler ClassExpert.mqh dosyasında bildirilen CExpert sınıfındadır.

        4.2. ClassExpert.mqh

        Açıklamasını göz önünde bulunduralım.

        //+------------------------------------------------------------------+
        //|   Class CExpert                                                  |
        //|   Class description                                              |
        //+------------------------------------------------------------------+
        class CExpert
          {
        public:
           int               DaysForCalculation; // Days to calculate (-1 for all)
           int               DayTheHistogram;    // Days for Histogram 
           int               RangePercent;       // Percent range
           color             InnerRange;         // Internal range color
           color             OuterRange;         // Outer range color
           color             ControlPoint;       // Point of Control (POC) Color
           bool              ShowValue;          // Show value
        

        Genel bölüm açıktır ve dış değişkenlerden erişilebilir. Değişkenlerin adlarının PriceHistogram.mq5'te açıklanan giriş parametreleri bölümünün adlarıyla uyuştuğunu fark edeceksiniz. Giriş parametreleri genel olduğu için bu, gerekli değildir. Ancak bu durumda, etik kurallara bir övgüdür, sınıf içinde harici değişkenlerin kullanılmasından kaçınılması arzu edilir.

        private:
           CList             list_object;        // The dynamic list of CObject class instances
           string            name_symbol;        // Symbol name
           int               count_bars;         // Number of daily bars
           bool              event_on;           // Flag of events processing
        

        Özel bölüm dışarıdan kapalıdır ve yalnızca sınıf içinde erişilebilir. Standart MQL5 kitaplık sınıfı olan CList türünün list_object değişkenini ana hatlarıyla belirtmek istiyorum. CList Sınıfı, CObject sınıfının ve mirasçılarının örneklerinin listesini içeren dinamik bir sınıftır. Bu listeyi, CObject sınıfının mirasçısı olan CPriceHistogram sınıfı öğelerinin referans depolaması için kullanacağım; ayrıntıları aşağıda ele alacağız. CList sınıfı açıklaması List.mqh'dedir ve #include <Arrays\List.mqh> derleyici yönergesinin kullanılmasını içerir.

        public:
           // Class constructor
                             CExpert();
           // Class destructor
                            ~CExpert(){Deinit(REASON_CHARTCLOSE);}
           // Initialization method
           bool              Init();
           // Deinitialization method
           void              Deinit(const int reason);
           // Method of OnTick processing
           void              OnTick();
           // Method of OnChartEvent() event processing
           void              OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
           // Method of OnTimer() event processing
           void              OnTimer();
        };

        Aşağıda, genel yöntemler bölümü verilmiştir. Tahmin ettiğiniz gibi bu yöntemler (işlevler) sınıfın dışında mevcuttur.

        Ve son olarak noktalı virgül içeren kaşlı ayraç, sınıf açıklamasını tamamlar.

        Sınıf yöntemlerini ayrıntılı olarak ele alalım.

        Sınıf oluşturucusu, nesne oluşturulduğunda çağrılan özel bir ifade bloğudur. Oluşturucu, yönteme benzer, ancak açıkça belirli bir döndürülen veri türüne sahip olmadığı için yöntemden farklıdır.

        MQL5 dilinde, oluşturucuların herhangi bir giriş parametresi olamaz ve her sınıf yalnızca bir oluşturucu içermelidir. Bizim durumumuzda, oluşturucu değişkenlerin birincil başlatmasıdır.

        Yıkıcı, nesne sıfırlanmasından (örneğin, boş bellek) için kullanılan özel bir sınıf yöntemidir. Bizim durumumuzda, yöntem Deinit (REASON_CHARTCLOSE) olarak çağrılır,

        Init(), sınıf başlatma için bir yöntemdir. Bu, CExpert sınıfının en önemli yöntemidir; histogram nesnelerini oluşturma işlemi orada gerçekleştirilmiştir. Ayrıntılar için lütfen açıklamalara bakınız. Ancak oradaki noktaları ele almak istiyorum.

        İlk olarak, günlük bir Fiyat Histogramı oluşturmak için ilerlemek için günlerin açık zaman verilerine ihtiyacımız var. Burada konunun dışına çıkmak ve zaman serileriyle çalışılmasına ilişkin özelliklere dikkatinizi çekmek istiyorum.  Diğer zaman dilimlerinden gelen veri talebi için bir zamana ihtiyacımız vardı; bu nedenle Bars () ve CopyTime () işlevleri ve ayrıca zaman serileriyle çalışacak diğer işlevler her zaman ilk çağrıdan istenen verileri döndürmez.

        Dolayısıyla, bu işlevi do (...) while () döngüsüne koymak zorunda kaldım, ancak onu sonlu hale getirmek için sayaç değişkenini kullandım.

         int err=0;
         do
           {
            // Calculate the number of days which available from the history
            count_bars=Bars(NULL,PERIOD_D1);
            if(DaysForCalculation+1<count_bars)
               count=DaysForCalculation+1;
            else
               count=count_bars;
            if(DaysForCalculation<=0) count=count_bars;
            rates_total=CopyTime(NULL,PERIOD_D1,0,count,day_time_open);
            Sleep(1);
            err++;
           }
         while(rates_total<=0 && err<AMOUNT_OF_ATTEMPTS);
         if(err>=AMOUNT_OF_ATTEMPTS)
           {
           Print("There is no accessible history PERIOD_D1");
           name_symbol=NULL;
           return(false);
           }

        İkincisi, MetaTrader 5'in dakika geçmişi mevcut günlere eşittir; bu nedenle ilerlemek çok zaman alabilir; dolayısıyla hesaplama sürecini görselleştirmek gerekir. CProgressBar sınıfı (#include "ClassProgressBar.mqh") bu amaç için geliştirilmiştir. Grafik penceresinde ilerleme çubuğunu oluşturur ve hesaplama işlemi sırasında bunu günceller.

         // We create the progress bar on the char to shot the loading process
         CProgressBar   *progress=new CProgressBar;
         progress.Create(0,"Loading",0,150,20);
         progress.Text("Calculation:");
         progress.Maximum=rates_total; 

        Üçüncüsü, döngüde, "new" ifadesini kullanarak, CPriceHistogram nesnesini oluşturur, yöntemlerini kullanarak yapılandırır ve Init() yöntemin çağırarak başlatırız. Başarılı olursa list_object listesine ekler; aksi taktirde delete ifadesini kullanarak hist_obj öğesini sileriz. CPriceHistogram sınıf açıklaması daha fazla sunulacaktır; koddaki yorumlara bakınız.

         // In this cycle there is creation of object CPriceHistogram
         // its initialization and addition to the list of objects
         for(int i=0;i<rates_total;i++)
           {
            CPriceHistogram  *hist_obj=new CPriceHistogram();
            //         hist_obj.StepHistigram(step);
            // We set the flag to show text labels
            hist_obj.ShowLevel(ShowValue);
            // We set POCs colour
            hist_obj.ColorPOCs(ControlPoint);
            // We set colour for inner range
            hist_obj.ColorInner(InnerRange);
            // We set colour for outer range
            hist_obj.ColorOuter(OuterRange);
            // We set the percent range
            hist_obj.RangePercent(RangePercent);
            //  hist_obj.ShowSecondaryPOCs((i>=rates_total-DayTheHistogram),PeriodSeconds(PERIOD_D1));
            if(hist_obj.Init(day_time_open[i],day_time_open[i]+PeriodSeconds(PERIOD_D1),(i>=rates_total-DayTheHistogram)))
               list_object.Add(hist_obj);
            else
               delete hist_obj; // Delete object if there was an error
            progress.Value(i);
           }; 

        OnTick(), bir sembol için yeni bir tick aldığınızda çağrılan bir yöntemdir. count_bars değişkeninde saklanan gün sayısının değerlerini Bars (Symbol (), PERIOD_D1) tarafından döndürülen günlük çubukların sayısı ile karşılaştırırız ve bunlar eşit değilse sınıf başlatmak, list_object listesini temizlemek ve değişkeni NULL name_symbol olarak değiştirmek için zorla Init () yöntemini çağırırız. Gün sayısı değişmediyse, döngü CPriceHistogram list_object sınıfında saklanan tüm nesneleri inceler ve El Değmemiş ( «el değmemiş") olanlar için bir Redraw() yöntemini yürütür.

        Deinit(), sınıfın sıfırlanması için bir yöntemdir. REASON_PARAMETERS durumunda (giriş parametreleri kullanıcı tarafından değiştirilmiştir), list_object listesini temizleriz ve name_symbol değişkenini NULL olarak ayarlarız. Diğer durumlarda, expert hiçbir şey yapmaz, ancak bir şey eklemek istiyorsanız açıklamaları okuyun.

        OnEvent(), istemci terminalinin olay işleme yöntemidir. Kullanıcı grafikle çalışırken olaylar istemci terminali tarafından oluşturulur. Ayrıntılar MQL5 dilinin belgelerinde bulunabilir. Bu Expert Advisor'da CHARTEVENT_OBJECT_CLICK grafik olayı kullanılmıştır. Histogram öğesine tıklandığında ikincil POC düzeylerini gösterir ve histogram rengini tersine çevirir.

        OnTimer(void), zamanlayıcı olaylarının işlenmesi için bir yöntemdir. Bu, programlarımda kullanılmıyor, ancak bazı zamanlayıcı eylemleri eklemek istiyorsanız (örneğin, zamanı göstermek için) buradan ulaşabilirsiniz. Kullanmadan önce, sınıf oluşturucusuna aşağıdaki satırı eklemek gerekir:

        EventSetTimer(time in seconds);

        Ve yıkıcıya aşağıdaki satırı eklemek gerekir:

        EventKillTimer(); 

        Deinit (REASON_CHARTCLOSE) yöntemini çağırmadan önce.

        CExpert sınıfını göz önünde bulundurduk; bu, CPriceHistogram sınıf yöntemlerinin gösterilmesi için oluşturuldu.

        4.3. ClassPriceHistogram.mqh
        //+------------------------------------------------------------------+
        //|   Class CPriceHistogram                                          |
        //|   Class description                                              |
        //+------------------------------------------------------------------+
        class CPriceHistogram : public CObject
          {
        private:
           // Class variables
           double            high_day,low_day;
           bool              Init_passed;      // Flag if the initialization has passed or not
           CChartObjectTrend *POCLine;
           CChartObjectTrend *SecondTopPOCLine,*SecondBottomPOCLine;
           CChartObjectText  *POCLable;
           CList             ListHistogramInner; // list for inner lines storage 
           CList             ListHistogramOuter; // list for outer lines storage
           bool              show_level;         // to show values of level
           bool              virgin;             // is it virgin
           bool              show_second_poc;    // show secondary POC levels
           double            second_poc_top;     // value of the top secondary POC level
           double            second_poc_bottom;  // value of the bottom secondary POC level
           double            poc_value;          // POC level value
           color             poc_color;          // color of POC level
           datetime          poc_start_time;
           datetime          poc_end_time;
           bool              show_histogram;     // show histogram  
           color             inner_color;        // inner color of the histogram
           color             outer_color;        // outer color of the histogram
           uint              range_percent;      // percent range
           datetime          time_start;         // start time for construction
           datetime          time_end;           // final time of construction
        public:
           // Class constructor
                             CPriceHistogram();
           // Class destructor
                            ~CPriceHistogram(){Delete();}
           // Class initialization
           bool              Init(datetime time_open,datetime time_close,bool showhistogram);
           // To level value
           void              ShowLevel(bool show){show_level=show; if(Init_passed) RefreshPOCs();}
           bool              ShowLevel(){return(show_level);}
           // To show histogram
           void              ShowHistogram(bool show);
           bool              ShowHistogram(){return(show_histogram);}
           // To show Secondary POC levels
           void              ShowSecondaryPOCs(bool show){show_second_poc=show;if(Init_passed)RefreshPOCs();}
           bool              ShowSecondaryPOCs(){return(show_second_poc);}
           // To set color of POC levels
           void              ColorPOCs(color col){poc_color=col; if(Init_passed)RefreshPOCs();}
           color             ColorPOCs(){return(poc_color);}
           // To set internal colour of histogram
           void              ColorInner(color col);
           color             ColorInner(){return(inner_color);}
           // To set outer colour of histogram
           void              ColorOuter(color col);
           color             ColorOuter(){return(outer_color);}
           // To set percent range
           void              RangePercent(uint percent){range_percent=percent; if(Init_passed)calculationPOCs();}
           uint              RangePercent(){return(range_percent);}
           // Returns value of virginity of POC level
           bool              VirginPOCs(){return(virgin);}
           // Returns starting time of histogram construction
           datetime          GetStartDateTime(){return(time_start);}
           // Updating of POC levels
           bool              RefreshPOCs();
        private:
           // Calculations of the histogram and POC levels
           bool              calculationPOCs();
           // Class delete
           void              Delete();
          }; 

        Sınıfın açıklamasında sınıf değişkenleri ve yöntemleri için açıklamalar yapmaya çalıştım. Bazılarını ayrıntılı olarak ele alalım.

        //+------------------------------------------------------------------+
        //|   Class initialization                                           |
        //+------------------------------------------------------------------+
        bool CPriceHistogram::Init(datetime time_open,datetime time_close,bool showhistogram) 

        Bu yöntem üç giriş parametresi kullanır; oluşturmanın açılışı, yapının kapanış zamanı ve histogram oluşturmayı belirten bir bayrak veya yalnızca POC düzeyleri.

        Benim örneğimde (CExpert sınıfı) giriş parametreleri, ertesi gün açılış günü ve saatinde iletilir day_time_open [i] + PeriodSeconds (PERIOD_D1). Ancak bu sınıfı kullandığınızda, hiçbir şey örneğin Avrupa, Amerika seansının saati veya hafta, ay vb. aralık boyutunun istenmesini önleyemez.

        //+---------------------------------------------------------------------------------------+
        //|   Calculations of the histogram and POCs levels                                       |
        //+---------------------------------------------------------------------------------------+
        bool CPriceHistogram::calculationPOCs() 

        Bu yöntemde, tüm düzeylerin kökeni ve yapılarının hesaplanması, dışarıdan erişilemeyen kapalı bir özel yöntemdir.

        // We get the data from time_start to time_end
           int err=0;
           do
             {
              //--- for each bar we are copying the open time
              rates_time=CopyTime(NULL,PERIOD_M1,time_start,time_end,iTime);
              if(rates_time<0)
                 PrintErrorOnCopyFunction("CopyTime",_Symbol,PERIOD_M1,GetLastError());
        
              //--- for each bar we are copying the High prices
              rates_high=CopyHigh(NULL,PERIOD_M1,time_start,time_end,iHigh);
              if(rates_high<0)
                 PrintErrorOnCopyFunction("CopyHigh",_Symbol,PERIOD_M1,GetLastError());
        
              //--- for each bar we are copying the Low prices
              rates_total=CopyLow(NULL,PERIOD_M1,time_start,time_end,iLow);
              if(rates_total<0)
                 PrintErrorOnCopyFunction("CopyLow",_Symbol,PERIOD_M1,GetLastError());
        
              err++;
             }
           while((rates_time<=0 || (rates_total!=rates_high && rates_total!=rates_time)) && err<AMOUNT_OF_ATTEMPTS&&!IsStopped());
           if(err>=AMOUNT_OF_ATTEMPTS)
             {
              return(false);
             }
           poc_start_time=iTime[0];
           high_day=iHigh[ArrayMaximum(iHigh,0,WHOLE_ARRAY)];
           low_day=iLow[ArrayMinimum(iLow,0,WHOLE_ARRAY)];
           int count=int((high_day-low_day)/_Point)+1;
        // Count of duration of a finding of the price at each level
           int ThicknessOfLevel[];    // create an array for count of ticks
           ArrayResize(ThicknessOfLevel,count);
           ArrayInitialize(ThicknessOfLevel,0);
           for(int i=0;i<rates_total;i++)
             {
              double C=iLow[i];
              while(C<iHigh[i])
                {
                 int Index=int((C-low_day)/_Point);
                 ThicknessOfLevel[Index]++;
                 C+=_Point;
                }
             }
           int MaxLevel=ArrayMaximum(ThicknessOfLevel,0,count);
           poc_value=low_day+_Point*MaxLevel;

        İlk olarak, belirli bir süre için dakika çubukları geçmiş verilerini alırız (iTime [], iHigh[], iLow[]). Ardından, iHigh[] ve Low[] öğelerinin maksimum ve minimum öğelerini buluruz. Daha sonra, minimumdan maksimuma nokta sayısını (sayım) hesaplarız ve ThicknessOfLevel dizisini ThicknessOfLevel öğeleri ile ayırırız. Döngüde, her dakika mumunu Düşük'ten Yüksek'e doğru gözden geçiririz ve bu fiyat düzeyindeki zaman dilimi varlığının verilerini ekleriz. Ardından, ThicknessOfLevel dizisinin maksimum öğesini buluruz; bu, fiyatın en uzun süre olduğu düzey olacaktır. Bu, bizim POC düzeyimizdir.

        // Search for the secondary POCs
           int range_min=ThicknessOfLevel[MaxLevel]-ThicknessOfLevel[MaxLevel]*range_percent/100;
           int DownLine=0;
           int UpLine=0;
           for(int i=0;i<count;i++)
             {
              if(ThicknessOfLevel[i]>=range_min)
                {
                 DownLine=i;
                 break;
                }
             }
           for(int i=count-1;i>0;i--)
             {
              if(ThicknessOfLevel[i]>=range_min)
                {
                 UpLine=i;
                 break;
                }
             }
           if(DownLine==0)
              DownLine=MaxLevel;
           if(UpLine==0)
              UpLine=MaxLevel;
           second_poc_top=low_day+_Point*UpLine;
           second_poc_bottom=low_day+_Point*DownLine;
        

        Bir sonraki adım, ikincil POC düzeylerini bulmaktır. Diyagramımızın bölünmüş olduğunu hatırlayın. Histogramımızın iç ve dış (farklı renklerde görüntülenen) olmak üzere iki aralığa ayrıldığını ve boyut aralığının bu düzeydeki fiyatın zaman yüzdesi olarak tanımlandığını hatırlayın. Dahili sınırların aralığı, İkincil POC düzeyleridir.

        İkincil POC - Sınır yüzde aralığını bulduktan sonra histogram oluşturma işlemine devam edin.

        // Histogram formation 
           if(show_histogram)
             {
              datetime Delta=(iTime[rates_total-1]-iTime[0]-PeriodSeconds(PERIOD_H1))/ThicknessOfLevel[MaxLevel];
              int step=1;
              
              if(count>100)
                 step=count/100// Calculate the step of the histogram (100 lines as max)
        
              ListHistogramInner.Clear();
              ListHistogramOuter.Clear();
              for(int i=0;i<count;i+=step)
                {
                 string name=TimeToString(time_start)+" "+IntegerToString(i);
                 double StartY= low_day+_Point*i;
                 datetime EndX= iTime[0]+(ThicknessOfLevel[i])*Delta;
        
                 CChartObjectTrend *obj=new CChartObjectTrend();
                 obj.Create(0,name,0,poc_start_time,StartY,EndX,StartY);
                 obj.Background(true);
                 if(i>=DownLine && i<=UpLine)
                   {
                    obj.Color(inner_color);
                    ListHistogramInner.Add(obj);
                   }
                 else
                   {
                    obj.Color(outer_color);
                    ListHistogramOuter.Add(obj);
                   }
                }
             }
        
        

        Terminal üzerindeki yükü azaltmak için her histogram için ekrana maksimum 100 satır getirdiğimi belirtmek isterim. Histogramın satırları, CList sınıfımız tarafından halihazırda bilinen nesneler olan iki listede (ListHistogramInner ve ListHistogramOuter) saklanır. Ancak bu işaretçiler, standart bir CChartObjectTrend nesneleri sınıfında saklanır. Neden iki liste olduğunu, renk histogramını değiştirebilmek için başlıktan tahmin edebileceğinizi düşünüyorum.

        // We receive data beginning from the final time of the histogram till current time
           err=0;
           do
             {
              rates_time=CopyTime(NULL,PERIOD_M1,time_end,last_tick.time,iTime);
              rates_high=CopyHigh(NULL,PERIOD_M1,time_end,last_tick.time,iHigh);
              rates_total=CopyLow(NULL,PERIOD_M1,time_end,last_tick.time,iLow);
              err++;
             }
           while((rates_time<=0 || (rates_total!=rates_high && rates_total!=rates_time)) && err<AMOUNT_OF_ATTEMPTS);
        // If there isn't history, the present day, level is virgin, we hoist the colours
           if(rates_time==0)
             {
              virgin=true;
             }
           else
        // Otherwise we check history
             {
              for(index=0;index<rates_total;index++)
                 if(poc_value<iHigh[index] && poc_value>iLow[index]) break;
        
              if(index<rates_total)   // If level has crossed
                 poc_end_time=iTime[index];
              else
                 virgin=true;
             }
           if(POCLine==NULL)
             {     
              POCLine=new CChartObjectTrend();
              POCLine.Create(0,TimeToString(time_start)+" POC ",0,poc_start_time,poc_value,0,0);
             }
           POCLine.Color(poc_color);
           RefreshPOCs();

        CPriceHistogram'ı gerekli tüm yöntemlerle tasarlamaya çalıştım; yetersizse kendiniz ekleyebilirsiniz; bu konuda size yardımcı olacağım.

        Özet

        Fiyat Histogramının güvenilir olduğunu, ancak sezgisel bir araç olduğunu bir kez daha hatırlatmak isterim; bu nedenle kullanımı için onay sinyalleri gereklidir.

        Gösterdiğiniz ilgi için teşekkürler. Tüm sorularınızı yanıtlamaya hazırım.

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

        Ekli dosyalar |
        classexpert.mqh (9.44 KB)
        pricehistogram.mq5 (3.63 KB)
        Veri Değişimi Nasıl Yapılır? 10 Dakikada MQL5 için bir DLL Veri Değişimi Nasıl Yapılır? 10 Dakikada MQL5 için bir DLL
        Artık pek çok geliştirici basit bir DLL'nin nasıl yazılacağını ve farklı sistem bağlayıcılarının özel özelliklerinin neler olduğunu hatırlamıyor. Birkaç örnek kullanarak, basit DLL oluşturma işleminin tamamını 10 dakikada göstermeye çalışacağım ve ayrıca bağlayıcı uygulamamızın bazı teknik ayrıntılarını ele alacağım. Visual Studio'da DLL oluşturma işlemini adım adım farklı değişken türlerini (sayılar, diziler, dizeler vb.) değiştirme örnekleriyle göstereceğim. Ayrıca, istemci terminalinizi özel DLL'lerdeki çökmelerden nasıl koruyacağınızı açıklayacağım.
        MQL5.community kanallarını ve grup sohbetlerini kullanın MQL5.community kanallarını ve grup sohbetlerini kullanın
        MQL5.com web sitesi dünyanın her yerinden yatırımcıları bir araya getirir. Kullanıcılar makaleler yayınlar, ücretsiz kodlar paylaşır, Mağazada ürünler satar, Freelance siparişleri gerçekleştirir ve ticaret sinyallerini kopyalar. Diğer kullanıcılarla Forumdan, yatırımcı sohbetlerinden ve MetaTrader kanallarından iletişim kurabilirsiniz.
        Göstergeler Arası Veri Değişimi: Bu Kolaydır Göstergeler Arası Veri Değişimi: Bu Kolaydır
        Bir grafiğe eklenmiş göstergelerin verilerine erişim sağlayacak ve şu özelliklere sahip olacak şöyle bir ortam oluşturmak istiyoruz: Veri kopyalama olmaması, kullanmamız gerekirse mevcut yöntemlerin kodunun minimum düzeyde değiştirilmesi, MQL kodunun tercih edilebilir olması (elbette DLL kullanmak zorundayız, ancak yalnızca bir düzine C++ kodu dizesi kullanacağız). Makalede, MetaTrader terminali için diğer MQL programlarından gösterge arabelleklerine erişmek için araçlar sağlayacak bir program ortamı geliştirmek için kolay bir yöntem açıklanmaktadır.
        Yeni Başlayanlar İçin Hızlı Başlangıç veya Kısa Kılavuz Yeni Başlayanlar İçin Hızlı Başlangıç veya Kısa Kılavuz
        Merhaba sevgili okuyucu! Bu yazıda, Uzman Danışmanlar (EA) oluşturma, göstergelerle çalışma vb. ilkeleri nasıl kolay ve hızlı bir şekilde kavrayabileceğinizi açıklamaya ve göstermeye çalışacağım. Bu, yeni başlayanlara yöneliktir ve zor veya anlaşılmaz örnekler içermeyecektir.