
Fiyat Histogramı (Piyasa Profili) ve MQL5'te uygulanması
"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:
- Piyasa bir müzayededir ve arz ve talebin aşağı yukarı eşit olduğu fiyat aralığı yönünde hareket eder.
- 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 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.
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:
- M1 bir yana, M5 için geçmişte çok az sayıda çubuk,
- 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,
- 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:
- Göstergenin çalışma zamanı kritiktir,
- 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:
- OnTick() içindeki Init olay işleyicisi için işlem süresi kritik değildir,
- 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.
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.
//+------------------------------------------------------------------+ //| 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





- Ücretsiz alım-satım uygulamaları
- İşlem kopyalama için 8.000'den fazla sinyal
- Finansal piyasaları keşfetmek için ekonomik haberler
Gizlilik ve Veri Koruma Politikasını ve MQL5.com Kullanım Şartlarını kabul edersiniz