股票量化軟件:赫茲量化中峰谷指標(biāo)和 ATR 指標(biāo)作為類來實(shí)施指標(biāo)
歷史數(shù)據(jù)同步的算法
對于我自己而言,我已經(jīng)選擇并實(shí)施了歷史副本(本地歷史)與客戶端中的歷史進(jìn)行同步的三種算法模式:
CPCHSM_NotSynch – 對于已經(jīng)形成的柱,不執(zhí)行本地歷史的同步(風(fēng)險(xiǎn)和責(zé)任由您承擔(dān))。實(shí)際上,此模式可任意用于較小的價(jià)格偏差對計(jì)算的精確度沒有嚴(yán)重影響的指標(biāo)(MA、ADX 等)。然而,舉例而言,此模式對峰谷指標(biāo)是致命的,其中一個(gè)峰值超過另一個(gè)峰值很多。
CPCHSM_Normal – 每次新的柱出現(xiàn)時(shí),都通過以下說明的算法同步本地歷史數(shù)據(jù)。
CPCHSM_Paranoid – 在每次調(diào)用以下說明的數(shù)據(jù)同步函數(shù)時(shí)同步本地歷史數(shù)據(jù)。
同步機(jī)制本身取決于程序員設(shè)置的另一個(gè)參數(shù) - HSMinute(存儲為 HistorySynchSecond)。我們假定 Dealer Center(交易中心)只能糾正最后 HSMinute 分鐘的歷史。如果在該時(shí)間范圍內(nèi)的同步期間沒有找到差異,則將歷史數(shù)據(jù)視為是相同的并停止比較。如果找到差異,則檢查并糾正整個(gè)歷史數(shù)據(jù)。
此外,該算法允許在初始化時(shí)從指定的結(jié)構(gòu) MqlRates 僅檢查價(jià)格/點(diǎn)差/量。例如,要繪制峰谷指標(biāo),我們只需要最高價(jià)和最低價(jià)。
CCustPrevCalculated 類的實(shí)際使用
要對 CCustPrevCalculated 類進(jìn)行初始化,我們需要調(diào)用函數(shù) InitData(),該函數(shù)在成功時(shí)返回 'true':
CCustPrevCalculated CustPrevCalculated; CustPrevCalculated.InitData(_Symbol, _Period, 150, CPCHSM_Normal, CPCH_high|CPCH_low, 15);
要同步歷史數(shù)據(jù),我們需要調(diào)用函數(shù) PrepareData():
CPCPrepareDataResultCode resData; resData = CustPrevCalculated.PrepareData();
函數(shù) PrepareData() 能夠返回的值的類型:
enum CPCPrepareDataResultCode ?{ ? CPCPDRC_NoData, ? ? ? ? ? ? ? ? ? ? // Returned when there is no data for calculation (not prepared by the server) ? CPCPDRC_FullInitialization, ? ? ? ? // Full initialization of the array has been performed ? CPCPDRC_Synch, ? ? ? ? ? ? ? ? ? ? ?// Synchronization with adding new bars has been performed ? CPCPDRC_SynchOnlyLastBar, ? ? ? ? ? // Synchronization of only the last bar has been performed (possible cutting of the history) ? CPCPDRC_NoRecountNotRequired ? ? ? ?// Recalculation has not been performed, since the data was not changed ?};
用于數(shù)據(jù)存取的 CCustPrevCalculated 類的函數(shù)
注:為了加快計(jì)算,不包括對數(shù)組溢出的檢查。為了更加精確,如果索引不正確,則會(huì)返回錯(cuò)誤的值。
名稱
用途
uint GetDataBarsCount()
返回可用柱的數(shù)量
uint GetDataBarsCalculated()
返回未改變的柱的數(shù)量
uint GetDataStartInd()
返回用于環(huán)繞存取的索引(對于自定義指標(biāo))
bool GetDataBarsCuttingLeft()
返回從左側(cè)裁切柱的結(jié)果
double GetDataOpen(int shift, bool AsSeries)
為偏移柱返回 'Open'(開盤價(jià))
double GetDataHigh(int shift, bool AsSeries)
為偏移柱返回 'High'(最高價(jià))
double GetDataLow(int shift, bool AsSeries)
為偏移柱返回 "Low"(最低價(jià))
double GetDataClose(int shift, bool AsSeries)
為偏移柱返回 'Close'(收盤價(jià))
datetime GetDataTime(int shift, bool AsSeries)
為偏移柱返回 'Time'(時(shí)間)
long GetDataTick_volume(int shift, bool AsSeries)
為偏移柱返回 'Tick_volume'(交易量)
long GetDataReal_volume(int shift, bool AsSeries)
為偏移柱返回 'Real_volume'(實(shí)際交易量)
int GetDataSpread(int shift, bool AsSeries)
為偏移柱返回 'Spread'(點(diǎn)差)
進(jìn)一步優(yōu)化 CCustPrevCalculated 類的例子
通過切換到(根據(jù)某種目的所確定)幾個(gè)數(shù)組來拒絕 MqlRates,并(降低內(nèi)存要求,但是增大在數(shù)組復(fù)制的調(diào)用次數(shù)方面的載入)。
將每個(gè)存取函數(shù)分為兩個(gè)獨(dú)立的函數(shù),以便明確的使用某類數(shù)組索引(拒絕 ?bool AsSeries? 參數(shù))。優(yōu)點(diǎn)在于僅在邏輯條件 ?if (AsSeries)? 中。
依據(jù) CCustPrevCalculated 類的數(shù)據(jù)創(chuàng)建用于計(jì)算自定義峰谷指標(biāo)的 CCustZigZagPPC
此算法依據(jù)自定義指標(biāo)專業(yè)峰谷指標(biāo)。類的源代碼位于 ZigZags.mqh 文件中;此外,庫 OutsideBar.mqh 用于處理額外的柱。
為了說明我們的指標(biāo)的一個(gè)柱,讓我們創(chuàng)建一個(gè)單獨(dú)的結(jié)構(gòu):
struct ZZBar ?{ ? double UP, DN; ? ? ? ? ? ? ? ? ? ? ?// Buffers of the ZigZag indicator ? OrderFormationBarHighLow OB; ? ? ? // Buffer for caching of an external bar ?};
也讓我們確定類的計(jì)算返回的結(jié)果:
enum CPCZZResultCode ?{ ? CPCZZRC_NotInitialized, ? ? ? ? ? ? // Class is no initialized ? CPCZZRC_NoData, ? ? ? ? ? ? ? ? ? ? // Faield to receive data (including the external bar) ? CPCZZRC_NotChanged, ? ? ? ? ? ? ? ? // No changes of ZZ rays ? CPCZZRC_Changed ? ? ? ? ? ? ? ? ? ? // ZZ rays changed ?};
要對 CCustZigZagPPC 類進(jìn)行初始化,我們需要調(diào)用一次 Init() 函數(shù);該函數(shù)在成功時(shí)返回 'true':
CCustZigZagPPC ZZ1; ZZ1.Init(CustPrevCalculated, _Symbol, _Period, 150, CPCHSM_Normal, CPCH_high|CPCH_low, 15, 0, true, 12, 10);
要計(jì)算指標(biāo),我們需要依據(jù)先前計(jì)算出來的 CCustPrevCalculated 類的數(shù)據(jù)開始更新數(shù)據(jù):
CPCPrepareDataResultCode resZZ1; resZZ1 = ZZ1.PrepareData(resData);
然后調(diào)用程序 Calculate():
if ( (resZZ1 != CPCPDRC_NoData) && (resZZ1 != CPCPDRC_NoRecountNotRequired) ) ? ZZ1.Calculate();
在文件 ScriptSample_CustZigZagPPC.mq5 中提供了一起使用一個(gè) CCustPrevCalculated 類和幾個(gè) CCustZigZagPPC 類的完整例子。
CCustZigZagPPC 類的數(shù)據(jù)存取函數(shù)
名稱
用途
uint GetBarsCount()
返回可用柱的數(shù)量
uint GetBarsCalculated()
返回計(jì)算出來的柱的數(shù)量
double GetUP(uint shift, bool AsSeries)
返回柱的峰谷指標(biāo)的峰值
double GetDN(uint shift, bool AsSeries)
返回柱的峰谷指標(biāo)的谷值
OrderFormationBarHighLow GetOB(uint shift, bool AsSeries)
返回柱的 'Outside'(外部)值
圖形和程序檢查
為了進(jìn)行圖形檢查,讓我們將原來的指標(biāo)附加到一個(gè)圖表,并且在其上附加專門編寫的具有相同輸入?yún)?shù)的測試指標(biāo) Indicator_CustZigZag.mq5(但是您應(yīng)選擇其他顏色以查看兩個(gè)指標(biāo));以下是運(yùn)行結(jié)果:

編輯
紅色 - 原來的指標(biāo),藍(lán)色 - 我們自己的指標(biāo),使用最后 100 根柱計(jì)算。
我們可以在 EA 交易中以同樣的方式比較它們;這樣會(huì)有區(qū)別嗎?在測試 EA 交易 Expert_CustZigZagPPC_test.mq5 中,每一次價(jià)格變動(dòng)都會(huì)比較從 iCustom("AlexSTAL_ZigZagProf") 獲得的結(jié)果以及從 CCustZigZagPPC 類獲得的結(jié)果。計(jì)算信息顯示在日志中(在第一根柱上可能沒有計(jì)算,因此缺乏算法需要的歷史數(shù)據(jù)):
(EURUSD,M1) ? ? ? ? ? ? ? ?1.35797; 1.35644; 1.35844; 1.35761; 1.35901; 1.35760; 1.35959; 1.35791; 1.36038; 1.35806; 1.36042; 1.35976; 1.36116; 1.35971; // it is normal (EURUSD,M1) Tick processed: 1.35797; 1.35644; 1.35844; 1.35761; 1.35901; 1.35760; 1.35959; 1.35791; 1.36038; 1.35806; 1.36042; 1.35976; 1.36116; (EURUSD,M1) Divergence on the bar: 7