量化軟件下載:赫茲量化直方圖形式的統(tǒng)計分布無需指標緩沖區(qū)和數(shù)組
直方圖繪制基礎
直方圖是頻率的柱線圖。其中一根數(shù)軸代表變量值, 另一根數(shù)軸代表這些值出現(xiàn)的頻率。每根柱線的高度代表那些間隔等于列寬的數(shù)值的頻率 (數(shù)量)。這些示意圖通常水平顯示, 即, 變量值位于水平軸上, 而頻率 — 坐落于垂直軸。使用直方圖來表示研究的數(shù)據(jù), 使得統(tǒng)計數(shù)據(jù)更直觀, 并且更容易理解和分析。
在本文中, 我們將關注變化序列的垂直直方圖: 分析參數(shù)的價格值將按照升序位于垂直軸上, 而頻率位于水平軸上 (圖例. 1)。傳入的價格數(shù)據(jù)在當前柱線上分布并分組, 并且可以從左側、右側或兩側同時相對于其數(shù)軸顯示。

編輯切換為居中
圖例. 1. 買賣價格分布的垂直直方圖
讓我們來研究一個具體的任務:
繪制買賣價格分布直方圖;
將采購價數(shù)據(jù)定位在當前柱線的右側, 而供給價 — 位于左側;
當新的即時報價抵達, 計算每筆入價值的頻率, 即, 直方圖間隔等于當前品種的最小點數(shù)大小。
現(xiàn)在, 我們令條件更復雜: 無指標緩沖區(qū), 數(shù)組或結構。
如何解決這個問題?
首先, 我們要確定在哪里保存每個直方圖列的累積頻率。即便在圖例. 1 上, 我們可以看到, 可能存在不確定數(shù)量的直方圖條。首先進入腦海的是使用動態(tài)數(shù)組, 因為在價格圖表的選定時間間隔上, 可能的價格范圍 (柱線數(shù)量) 不可預知。但數(shù)組不允許這種問題條件。
其次, 我們應該解決搜索和排序任務: 何處以及如何搜索重新計算和重繪直方圖的數(shù)據(jù)。
結果是 MQL5 語言開發(fā)人員已經(jīng)創(chuàng)建了必要的 (和相當強大的) 功能。它基于使用圖形對象功能組的 "隱藏" (非顯性) 特征。每個對象都有自己的 屬性 — 此變量與對象一起創(chuàng)建, 并用于存儲各類多個參數(shù)。一些屬性在使用時可以完全不同于它們的設計用途, 同時保持功能完整。我們將這些屬性稱之為 "圖形" 內存。換言之, 如果您需要保存一個變量并接收其數(shù)值, 創(chuàng)建一個圖形對象并將變量值賦給一個特定的屬性。
所以, 圖形對象屬性 實際上可作為更有效的終端全局變量。全局變量自其最后訪問以來可在客戶終端中存在四個星期, 且隨后被自動刪除。圖形內存在圖形對象被移除之前會一直存在, 從而為我們提供了大量的機會。
我們可以在圖形內存中使用哪些圖形對象屬性
當創(chuàng)建圖形對象時, 我們應為它分配一個獨有的名稱。該名稱是可以由子串組成的文本字符串,而子字符串可以包含格式化的基本數(shù)據(jù)類型:整數(shù),布爾值,浮點數(shù),顏色,日期和時間。因此, OBJPROP_NAME 可保存主要用來讀取數(shù)據(jù)的變量。
另外其它可用的屬性是 OBJPROP_TEXT 對象描述。這是一個文本字符串, 與前一個屬性相比具有更大可能性的。在屬性字段中可以讀取和寫入變量。
任何圖形對象均有其自己的坐標: 價格 OBJPROP_PRICE 和時間 OBJPROP_TIME。它們也可以用在圖形內存中。
讓我們回到我們的目標。頻率將存儲在 OBJPROP_TEXT 屬性, 而供給價和采購價 — 在 OBJPROP_NAME 中。創(chuàng)建對象和收集頻率的函數(shù)代碼如下:
void DrawHistogram(bool draw, ? ? // 向左側或右側繪制直方圖 ? ? ? ? ? ? ? ? ? string h_name, // 對象名稱的獨有前綴 ? ? ? ? ? ? ? ? ? double price, ?// 價格 (分析參數(shù)) ? ? ? ? ? ? ? ? ? datetime time, // 將直方圖綁定到當前柱線 ? ? ? ? ? ? ? ? ? int span, ? ? ?// 已分析參數(shù)的數(shù)位容量 ? ? ? ? ? ? ? ? ? int swin=0) ? ?// 直方圖窗口 ?{ ? double y=NormalizeDouble(price,span); ? string pfx=DoubleToString(y,span); // 如果 draw=true, 向右側繪制直方圖 ? if(draw) ? ? { ? ? ?string name="+ "+h_name+pfx; ? ? ? ? ? ? ? ? ? // 對象名稱: 前綴+價格 ? ? ?ObjectCreate(0,name,OBJ_TREND,swin,time,y); ? ?// 創(chuàng)建對象 ? ? ?ObjectSetInteger(0,name,OBJPROP_COLOR,color_R_active); // 設置對象顏色 ? ? ?ObjSet; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 宏代碼縮寫 ? ? ?if(StringFind(ObjectGetString(0,name,OBJPROP_TEXT),"*",0)<0) ? ? ? ?{// 如果結果價格首次進入樣本 ? ? ? ? ObjectSetString(0,name,OBJPROP_TEXT,"*1"); ? ? ? ? ?// 價格頻率為 1 ? ? ? ? ObjectSetInteger(0,name,OBJPROP_TIME,1,time+hsize); // 定義時間坐標 ? ? ? ?} ? ? ?else ? ? ? ?{// 如果結果價格并非首次進入樣本 ? ? ? ? string str=ObjectGetString(0,name,OBJPROP_TEXT); ? ?// 獲取屬性值 ? ? ? ? string strint=StringSubstr(str,1); ? ? ? ? ? ? ? ? ?// 獲得子字符串 ? ? ? ? long n=StringToInteger(strint); ? ? ? ? ? ? ? ? ? ? // 獲取頻率用于進一步計算 ? ? ? ? n++; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 數(shù)值遞增 1 ? ? ? ? ObjectSetString(0,name,OBJPROP_TEXT,"*"+(string)n); // 新數(shù)值寫入到屬性 ? ? ? ? ObjectSetInteger(0,name,OBJPROP_TIME,1,time+hsize*n);//定義時間坐標 ? ? ? ?} ? ? } // 如果 draw=false, 向左側寫入直方圖 ? if(!draw) ? ? { ? ? ?string name="- "+h_name+pfx; ? ? ?ObjectCreate(0,name,OBJ_TREND,swin,time,y); ? ? ?ObjectSetInteger(0,name,OBJPROP_COLOR,color_L_active); ? ? ?ObjSet; ? ? ?if(StringFind(ObjectGetString(0,name,OBJPROP_TEXT),"*",0)<0) ? ? ? ?{ ? ? ? ? ObjectSetString(0,name,OBJPROP_TEXT,"*1"); ? ? ? ? ObjectSetInteger(0,name,OBJPROP_TIME,1,time-hsize); ? ? ? ?} ? ? ?else ? ? ? ?{ ? ? ? ? string str=ObjectGetString(0,name,OBJPROP_TEXT); ? ? ? ? string strint=StringSubstr(str,1); ? ? ? ? long n=StringToInteger(strint); ? ? ? ? n++; ? ? ? ? ObjectSetString(0,name,OBJPROP_TEXT,"*"+(string)n); ? ? ? ? ObjectSetInteger(0,name,OBJPROP_TIME,1,time-hsize*n); ? ? ? ?} ? ? } ? ChartRedraw();