股票量化交易軟件:如何創(chuàng)建自己的指標(biāo)
簡介
什么是指標(biāo)?指標(biāo)是赫茲股票量化交易軟件希望以便利方式在熒幕上顯示的一組計算值。這一組值在程序中以數(shù)組表示。因此,創(chuàng)建指標(biāo)意即編寫用于處理數(shù)組(價格數(shù)組)的算法并將處理結(jié)果記錄在其他數(shù)組(指標(biāo)值)中。

來百度APP暢享高清圖片
盡管已有許多已成經(jīng)典的現(xiàn)成指標(biāo),但創(chuàng)建自己的指標(biāo)的必要性始終存在。赫茲股票量化交易軟件把使用赫茲股票量化交易軟件自己的算法創(chuàng)建的這類指標(biāo)稱為自定義指標(biāo)。本文將探討如何創(chuàng)建簡單的自定義指標(biāo)。
指標(biāo)是不同的
指標(biāo)可以表現(xiàn)為帶有顏色的線條或區(qū)域,或作為指向輸入頭寸的有利時刻的特殊標(biāo)簽顯示。同時,這些類型還可以相互結(jié)合,從而提供了更多的指標(biāo)類型。赫茲股票量化交易軟件將采用 William Blau 開發(fā)的眾所周知的“真實(shí)強(qiáng)弱指數(shù)”作為指標(biāo)創(chuàng)建的示例。
真實(shí)強(qiáng)弱指數(shù)
TSI 指標(biāo)基于雙重平滑動量來確定趨勢及超賣/超買區(qū)域。指標(biāo)的數(shù)學(xué)詮釋請見?動量、方向和背離,William Blau。在這里,赫茲股票量化交易軟件僅涉及計算公式。
TSI(CLOSE,r,s) =100*EMA(EMA(mtm,r),s) / EMA(EMA(|mtm|,r),s)
其中:
mtm = CLOSEcurrent?– CLOSprev,值數(shù)組指示當(dāng)前柱的收盤價格和上一個柱的收盤價格的差值;
EMA(mtm,r) = 周期長度為 r 的 mtm 值的指數(shù)平滑;
EMA(EMA(mtm,r),s) = 時間周期為 s 的 EMA(mtm,r) 值的指數(shù)平滑;
|mtm| = mtm 絕對值;
r = 25,
s = 13。
從上述公式赫茲股票量化交易軟件可以得知,有三個參數(shù)影響指標(biāo)計算。它們是時間周期 r 和時間周期 s,以及用于計算的價格類型。在前例中,赫茲股票量化交易軟件使用收盤價。
MQL5 向?qū)?br>
赫茲股票量化交易軟件將 TSI 以藍(lán)色線條顯示 - 在這里,赫茲股票量化交易軟件需要啟動“MQL5 向?qū)А?。首先,赫茲股票量化交易軟件需要指出赫茲股票量化交易軟件希望?chuàng)建的程序的類型 - 自定義指標(biāo)。接來下,赫茲股票量化交易軟件應(yīng)設(shè)置程序名、r?和?s?參數(shù)以及它們的值。

之后,赫茲股票量化交易軟件需定義指標(biāo)在單獨(dú)的窗口中以藍(lán)色線條顯示,并為該線條設(shè)置 TSI 標(biāo)簽。

在輸入所有初始數(shù)據(jù)后,按 Done(完成)并獲得指標(biāo)的草稿。
//+------------------------------------------------------------------+//| ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?True Strength Index.mq5 |//| ? ? ? ? ? ? ? ? ? ? ? ?Copyright 2009, MetaQuotes Software Corp. |//| ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?https://www.mql5.com |//+------------------------------------------------------------------+#property copyright "2009, MetaQuotes Software Corp."#property link ? ? ?"https://www.mql5.com"#property version ? "1.00"#property indicator_separate_window#property indicator_buffers 1#property indicator_plots ? 1//---- TSI 繪圖屬性#property indicator_label1 ?"TSI"#property indicator_type1 ? DRAW_LINE#property indicator_color1 ?Blue#property indicator_style1 ?STYLE_SOLID#property indicator_width1 ?1//--- 輸入?yún)?shù)input int ? ? ?r=25;input int ? ? ?s=13;//--- 指標(biāo)緩沖區(qū)double ? ? ? ? TSIBuffer[];//+------------------------------------------------------------------+//| 自定義指標(biāo)初始化函數(shù) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|//+------------------------------------------------------------------+int OnInit() ?{//--- 指標(biāo)緩沖區(qū)映射關(guān)系 ? SetIndexBuffer(0,TSIBuffer,INDICATOR_DATA);//--- ? return(0); ?}//+------------------------------------------------------------------+//| 自定義指標(biāo)迭代函數(shù) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |//+------------------------------------------------------------------+int OnCalculate(const int rates_total, ? ? ? ? ? ? ? ?const int prev_calculated, ? ? ? ? ? ? ? ?const datetime& time[], ? ? ? ? ? ? ? ?const double& open[], ? ? ? ? ? ? ? ?const double& high[], ? ? ? ? ? ? ? ?const double& low[], ? ? ? ? ? ? ? ?const double& close[], ? ? ? ? ? ? ? ?const long& tick_volume[], ? ? ? ? ? ? ? ?const long& volume[], ? ? ? ? ? ? ? ?const int& spread[]) ?{//---//--- 返回值會作為下一次調(diào)用的 prev_calculated 參數(shù)調(diào)用 ? return(rates_total); ?}//+------------------------------------------------------------------+
“MQL5 向?qū)А眲?chuàng)建指標(biāo)頭文件,其內(nèi)規(guī)定了指標(biāo)屬性,即:
指標(biāo)在單獨(dú)窗口中顯示;
指標(biāo)緩沖區(qū)數(shù)量,?indicator_buffers=1;
繪圖數(shù)量,?indicator_buffers=1;
繪圖 1 名稱,indicator_label1="TSI";
首個繪圖樣式 - 線條,indicator_type1=DRAW_LINE;
繪圖 1 顏色,indicator_color1=Blue;
線條樣式,indicator_style1=STYLE_SOLID;
繪圖 1 線寬,indicator_width1=1。
所有準(zhǔn)備工作就緒,現(xiàn)在赫茲股票量化交易軟件可以著手改進(jìn)和完善赫茲股票量化交易軟件的代碼。
OnCalculate()
函數(shù) OnCalculate() 是Calculate事件的處理函數(shù),在需要重新計算指標(biāo)值以及在圖表上重新繪制指標(biāo)時出現(xiàn)。這是新的訂單號接收、交易品種歷史數(shù)據(jù)更新等的事件。這就是指標(biāo)值所有計算的主代碼必須位于此函數(shù)中的原因。
當(dāng)然,輔助計算可以通過其他的單獨(dú)函數(shù)實(shí)施,但這些函數(shù)必須用于 OnCalculate處理函數(shù)。
默認(rèn)情況下,“MQL5 向?qū)А眲?chuàng)建?OnCalculate() 的第二種形式,該形式提供對所有時序類型的訪問:
開盤價、最高價、最低價、收盤價;
交易量(實(shí)際量和/或跳動量);
點(diǎn)差;
周期開盤時間。
而對于赫茲股票量化交易軟件而言,赫茲股票量化交易軟件只需要一個數(shù)據(jù)數(shù)組,這就是赫茲股票量化交易軟件要改寫調(diào)用的 OnCalculate() 函數(shù)的第一種形式的原因。
int OnCalculate (const int rates_total, ? ? ?// price[]數(shù)組大小; ? ? ? ? ? ? ? ? const int prev_calculated, ?// 上次調(diào)用計算后的價格柱的數(shù)量 ? ? ? ? ? ? ? ? const int begin, ? ? ? ? ? ?// price[]數(shù)組開始計算的索引 ? ? ? ? ? ? ? ? const double& price[]) ? ? ?// 指標(biāo)計算的依據(jù)數(shù)組 ?{//---//--- 返回值會作為下一次調(diào)用的 prev_calculated 參數(shù)調(diào)用 ? return(rates_total); ?}
這就使赫茲股票量化交易軟件不僅可以進(jìn)一步將指標(biāo)應(yīng)用于價格數(shù)據(jù),同時還可以基于其他指標(biāo)的值來創(chuàng)建指標(biāo)。

如果赫茲股票量化交易軟件在 Parameters(參數(shù))選項(xiàng)卡中選擇?Close(收盤)(默認(rèn)提供),則傳遞至 OnCalculate() 的?price[]?將包含收盤價。如果赫茲股票量化交易軟件選擇,例如,Typical Price(典型價格),price[]?將在每個時間周期中包含(最高價+最低價+收盤價)/3 的價格。
rates_total?參數(shù)指示?price[]?數(shù)組的大小;該參數(shù)在循環(huán)中組織計算時十分有用。price[] 中的元素索引從零開始,方向從過去至未來,即 price[0] 元素包含最舊的值,而 price[rates_total-1] 包含最新的數(shù)組值。
組織輔助指標(biāo)緩沖區(qū)
僅有一根線會在圖表中顯示,即一個指標(biāo)數(shù)組的數(shù)據(jù)。但在此之前,赫茲股票量化交易軟件需要組織中間計算。中間數(shù)據(jù)存儲在以?INDICATOR_CALCULATIONS?屬性標(biāo)記的指標(biāo)數(shù)組中。從上述公式可以得知,赫茲股票量化交易軟件還需要以下附加數(shù)組:
用于值 mtm - 數(shù)組 MTMBuffer[];
用于值 |mtm| - 數(shù)組 AbsMTMBuffer[];
用于 EMA(mtm,r) -?數(shù)組?EMA_MTMBuffer[];
用于 EMA(EMA(mtm,r),s) -?數(shù)組?EMA2_MTMBuffer[];
用于 EMA(|mtm|,r) -?數(shù)組?EMA_AbsMTMBuffer[];
用于 EMA(EMA(|mtm|,r),s) -?數(shù)組?EMA2_AbsMTMBuffer[]。
赫茲股票量化交易軟件總共還需要添加 6 個全局級別的雙精度類型數(shù)組,并需要將這些數(shù)組和指標(biāo)緩沖區(qū)綁定至?OnInit()?函數(shù)。切勿忘記標(biāo)示新的指標(biāo)緩沖區(qū)數(shù)量;indicator_buffers?屬性必須等于 7(原有的 1 個緩沖區(qū)加上添加的 6 個緩沖區(qū))。
#property indicator_buffers 7
現(xiàn)在指標(biāo)代碼如下所示:
#property indicator_separate_window#property indicator_buffers 7#property indicator_plots ? 1//---- TSI 繪圖屬性#property indicator_label1 ?"TSI"#property indicator_type1 ? DRAW_LINE#property indicator_color1 ?Blue#property indicator_style1 ?STYLE_SOLID#property indicator_width1 ?1//--- 輸入?yún)?shù)input int ? ? ?r=25;input int ? ? ?s=13;//--- 指標(biāo)緩沖區(qū)double ? ? ? ? TSIBuffer[];double ? ? ? ? MTMBuffer[];double ? ? ? ? AbsMTMBuffer[];double ? ? ? ? EMA_MTMBuffer[];double ? ? ? ? EMA2_MTMBuffer[];double ? ? ? ? EMA_AbsMTMBuffer[];double ? ? ? ? EMA2_AbsMTMBuffer[];//+------------------------------------------------------------------+//| 自定義指標(biāo)初始化函數(shù) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |//+------------------------------------------------------------------+int OnInit() ?{//--- 指標(biāo)緩沖區(qū)映射關(guān)系 ? SetIndexBuffer(0,TSIBuffer,INDICATOR_DATA); ? SetIndexBuffer(1,MTMBuffer,INDICATOR_CALCULATIONS); ? SetIndexBuffer(2,AbsMTMBuffer,INDICATOR_CALCULATIONS); ? SetIndexBuffer(3,EMA_MTMBuffer,INDICATOR_CALCULATIONS); ? SetIndexBuffer(4,EMA2_MTMBuffer,INDICATOR_CALCULATIONS); ? SetIndexBuffer(5,EMA_AbsMTMBuffer,INDICATOR_CALCULATIONS); ? SetIndexBuffer(6,EMA2_AbsMTMBuffer,INDICATOR_CALCULATIONS);//--- ? return(0); ?}//+------------------------------------------------------------------+//| 自定義指標(biāo)迭代函數(shù) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|//+------------------------------------------------------------------+int OnCalculate (const int rates_total, ? ?// price[]數(shù)組大小; ? ? ? ? ? ? ? ? const int prev_calculated,// 次調(diào)用計算后的價格柱的數(shù)量; ? ? ? ? ? ? ? ? const int begin, ? ? ? ? ?// price[]數(shù)組開始計算的索引; ? ? ? ? ? ? ? ? ?const double& price[]) ? ?// 指標(biāo)計算的依據(jù)數(shù)組; ?{//---//--- 返回值會作為下一次調(diào)用的 prev_calculated 參數(shù)調(diào)用 ? return(rates_total); ?}
中間計算
組織緩沖區(qū)?MTMBuffer[] 和?AbsMTMBuffer[] 的值的計算是非常容易的。在循環(huán)中,從 price[1] 至 price[rates_total-1] 逐一遍歷值,將差值寫入一個數(shù)組,差值的絕對值寫入第二個數(shù)組。
//--- 計算 mtm 和 |mtm| 的數(shù)值 ? for(int i=1;i<rates_total;i++) ? ? { ? ? ?MTMBuffer[i]=price[i]-price[i-1]; ? ? ?AbsMTMBuffer[i]=fabs(MTMBuffer[i]); ? ? }
下一階段是計算這些數(shù)組的指數(shù)平均線。赫茲股票量化交易軟件有兩種方法可用。其一是寫入整個算法,設(shè)法不犯錯誤。其二是使用已經(jīng)調(diào)試并嚴(yán)格用于這些目的的現(xiàn)成函數(shù)。
MQL5 中沒有內(nèi)置函數(shù)用于通過數(shù)組值計算移動平均線,但有一個現(xiàn)成的函數(shù)庫 MovingAverages.mqh 可用,到該庫的完整路徑為?terminal_directory/MQL5/Include/MovingAverages.mqh,其中?terminal_directory?是 赫茲股票量化交易軟件 終端的安裝目錄。該庫是一個引用文件;它包含用于計算移動平均線的函數(shù),計算通過使用以下四個經(jīng)典方法之一在數(shù)組上完成:
簡單移動平均線;
指數(shù)移動平均線;
平滑移動平均線;
線性加權(quán)移動平均線。
要使用這些函數(shù),應(yīng)在任何 MQL5 程序的標(biāo)頭碼中添加以下代碼:
#include <MovingAverages.mqh>
赫茲股票量化交易軟件需要函數(shù) ExponentialMAOnBuffer(),該函數(shù)在值數(shù)組上計算指數(shù)移動平均線,并將平均值記錄在另一數(shù)組中。
數(shù)組平滑函數(shù)
引用文件 MovingAverages.mqh 總共包含八個函數(shù),這八個函數(shù)可以劃分為相同類型的兩組函數(shù),每組 4 個函數(shù)。第一組函數(shù)接收數(shù)組并在指定位置返回移動平均線的值:
SimpleMA() - 用于計算簡單移動平均線的值;
ExponentialMA() - 用于計算指數(shù)移動平均線的值;
SmoothedMA() - 用于計算平滑移動平均線的值;
LinearWeightedMA() - 用于計算線性加權(quán)移動平均線的值。
這些函數(shù)用于獲取平均線的值,一個數(shù)組一次,且沒有針對多重調(diào)用進(jìn)行優(yōu)化。若需要在循環(huán)中使用該組的函數(shù)(以計算平均線的值并進(jìn)一步將每個計算值寫入數(shù)組),則需要組織一個最優(yōu)算法。
第二組函數(shù)用于將基于初始值數(shù)組的移動平均線的值填入接收數(shù)組:
SimpleMAOnBuffer() - 將來自 price[] 數(shù)組的簡單移動平均線的值填入輸出數(shù)組 buffer[];
ExponentialMAOnBuffer() - 將來自 price[] 數(shù)組的指數(shù)移動平均線的值填入輸出數(shù)組 buffer[];
SmoothedMAOnBuffer() - 將來自 price[] 數(shù)組的平滑移動平均線的值填入輸出數(shù)組 buffer[];
LinearWeightedMAOnBuffer() - 將來自 price[] 數(shù)組的線性加權(quán)移動平均線的值填入輸出數(shù)組 buffer[]。
所有指定的函數(shù)除數(shù)組 buffer[]、price[] 以及?period?平均周期外,均獲得 3 個以上的參數(shù),其目的是類同于 OnCalculate() 函數(shù) rates_total、prev_calculated 和 begin 的參數(shù)。該組函數(shù)可正確處理傳遞的數(shù)組 price[] 和 buffer[],并將索引方向考慮在內(nèi)(AS_SERIES?標(biāo)志)。
begin?參數(shù)指示源數(shù)組的索引,有意義的數(shù)據(jù)(即需要處理的數(shù)據(jù))從此開始。對于 MTMBuffer[] 數(shù)組,實(shí)際數(shù)據(jù)從索引 1 開始,因?yàn)?MTMBuffer[1]=price[1]-price[0]。MTMBuffer[0] 的值未定義,這就是 begin=1 的原因。
//--- 計算數(shù)組的首要移動平均 ? ExponentialMAOnBuffer(rates_total,prev_calculated, ? ? ? ? ? ? ? ? ? ? ? ? 1, ?// 索引, 開始從哪個數(shù)據(jù)開始平滑計算 ? ? ? ? ? ? ? ? ? ? ? ? ?r, ?// 指數(shù)平均的周期 ? ? ? ? ? ? ? ? ? ? ? ? MTMBuffer, ? ? ? // 計算平均的緩沖區(qū) ? ? ? ? ? ? ? ? ? ? ? ? EMA_MTMBuffer); ?// 存儲計算結(jié)果的緩沖區(qū) ? ExponentialMAOnBuffer(rates_total,prev_calculated, ? ? ? ? ? ? ? ? ? ? ? ? 1,r,AbsMTMBuffer,EMA_AbsMTMBuffer);
取平均線時,應(yīng)考慮時間周期值,因?yàn)樵谳敵鰯?shù)組中,計算值的填入帶有遲滯,較大的平均周期則該遲滯也較大。例如,如果 period=10,結(jié)果數(shù)組中的值將起始于 begin+period-1=begin+10-1。在 buffer[] 的進(jìn)一步調(diào)用中,應(yīng)將其考慮在內(nèi),且處理應(yīng)從索引 begin+period-1 開始。
因此,赫茲股票量化交易軟件可以從數(shù)組 MTMBuffer[] 和?AbsMTMBuffer?輕松獲得次要指數(shù)平均線。
//--- 計算數(shù)組的次要移動平均 ? ExponentialMAOnBuffer(rates_total,prev_calculated, ? ? ? ? ? ? ? ? ? ? ? ? r,s,EMA_MTMBuffer,EMA2_MTMBuffer); ? ExponentialMAOnBuffer(rates_total,prev_calculated, ? ? ? ? ? ? ? ? ? ? ? ? r,s,EMA_AbsMTMBuffer,EMA2_AbsMTMBuffer);
當(dāng)前的?begin?值為 r,因?yàn)?begin=1+r-1(r 是主要指數(shù)平均線的時間周期,處理從索引 1 開始)。在輸出數(shù)組 EMA2_MTMBuffer[] 和 EMA2_AbsMTMBuffer[] 中,計算值起始于索引 r+s-1,因?yàn)楹掌澒善绷炕灰总浖乃饕?r 開始處理輸入數(shù)組,且次要指數(shù)平均線的時間周期為 s。
所有預(yù)計算就緒,現(xiàn)在赫茲股票量化交易軟件可以計算將會在圖表中繪制的指標(biāo)緩沖區(qū) TSIBuffer[] 的值。
//--- 現(xiàn)在計算指標(biāo)的數(shù)值 ? for(int i=r+s-1;i<rates_total;i++) ? ? { ? ? ?TSIBuffer[i]=100*EMA2_MTMBuffer[i]/EMA2_AbsMTMBuffer[i]; ? ? }
按?F5?鍵編譯代碼,并在?赫茲股票量化交易軟件?終端中啟動代碼。運(yùn)作良好!

此時仍有一些問題待解決。
優(yōu)化計算
事實(shí)上,僅僅編寫一個可用的指標(biāo)是遠(yuǎn)遠(yuǎn)不夠的。如果赫茲股票量化交易軟件仔細(xì)檢查 OnCalculate() 的當(dāng)前實(shí)施情況,就會發(fā)現(xiàn)它不是最優(yōu)的。
int OnCalculate (const int rates_total, ? ?// price[]數(shù)組大小; ? ? ? ? ? ? ? ? const int prev_calculated,// 次調(diào)用計算后的價格柱的數(shù)量; ? ? ? ? ? ? ? ? const int begin,// price[]數(shù)組開始計算的索引; ? ? ? ? ? ? ? ? ?const double &price[]) // 指標(biāo)計算的依據(jù)數(shù)組; ?{//--- 計算 mtm 和 |mtm| 的數(shù)值 ? MTMBuffer[0]=0.0; ? AbsMTMBuffer[0]=0.0; ? for(int i=1;i<rates_total;i++) ? ? { ? ? ?MTMBuffer[i]=price[i]-price[i-1]; ? ? ?AbsMTMBuffer[i]=fabs(MTMBuffer[i]); ? ? }//--- 計算數(shù)組的首要移動平均 ? ExponentialMAOnBuffer(rates_total,prev_calculated, ? ? ? ? ? ? ? ? ? ? ? ? 1, ?// 索引, 開始從哪個數(shù)據(jù)開始平滑計算 ? ? ? ? ? ? ? ? ? ? ? ? ?r, ?// 指數(shù)平均的周期 ? ? ? ? ? ? ? ? ? ? ? ? MTMBuffer, ? ? ? // 計算平均的緩沖區(qū) ? ? ? ? ? ? ? ? ? ? ? ? EMA_MTMBuffer); ?// 存儲計算結(jié)果的緩沖區(qū) ? ExponentialMAOnBuffer(rates_total,prev_calculated, ? ? ? ? ? ? ? ? ? ? ? ? 1,r,AbsMTMBuffer,EMA_AbsMTMBuffer);//--- 計算數(shù)組的次要移動平均 ? ExponentialMAOnBuffer(rates_total,prev_calculated, ? ? ? ? ? ? ? ? ? ? ? ? r,s,EMA_MTMBuffer,EMA2_MTMBuffer); ? ExponentialMAOnBuffer(rates_total,prev_calculated, ? ? ? ? ? ? ? ? ? ? ? ? r,s,EMA_AbsMTMBuffer,EMA2_AbsMTMBuffer);//--- 現(xiàn)在計算指標(biāo)的數(shù)值 ? for(int i=r+s-1;i<rates_total;i++) ? ? { ? ? ?TSIBuffer[i]=100*EMA2_MTMBuffer[i]/EMA2_AbsMTMBuffer[i]; ? ? }//---返回值會作為下一次調(diào)用的 prev_calculated 參數(shù)調(diào)用 ? return(rates_total); ?}
在每個函數(shù)的開始,赫茲股票量化交易軟件在數(shù)組 MTMBuffer[] 和 AbsMTMBuffer[] 中計算值。在這種情況下,如果 price[] 的大小達(dá)成千上萬或甚至百萬,不必要的重復(fù)計算可能占用 CPU 的所有資源,不論該 CPU 性能如何強(qiáng)勁。
對于組織優(yōu)化計算,赫茲股票量化交易軟件使用?prev_calculated?輸入?yún)?shù),其值等于 OnCalculate() 上次調(diào)用返回的值。在函數(shù)的首次調(diào)用中,prev_calculated 的值始終為 0。在此情況下,赫茲股票量化交易軟件在指標(biāo)緩沖區(qū)中計算所有的值。在下次調(diào)用中,赫茲股票量化交易軟件不必計算整個緩沖區(qū) - 僅需計算最后的值。代碼編寫如下:
//--- 如果這是第一次調(diào)用 ? ?if(prev_calculated==0) ? ? { ? ? ?//--- 把索引0的數(shù)據(jù)設(shè)為0 ? ? ?MTMBuffer[0]=0.0; ? ? ?AbsMTMBuffer[0]=0.0; ? ? }//--- 計算 mtm 和 |mtm| 的數(shù)值 ? int start; ? if(prev_calculated==0) start=1; ?// 設(shè)置從 MTMBuffer[] 和 AbsMTMBuffer[] 的索引1開始計算填寫數(shù)據(jù) ? else start=prev_calculated-1; ? ?// 設(shè)置從上一次計算的最后一個索引開始計算填寫數(shù)據(jù) ? ?for(int i=start;i<rates_total;i++) ? ? { ? ? ?MTMBuffer[i]=price[i]-price[i-1]; ? ? ?AbsMTMBuffer[i]=fabs(MTMBuffer[i]); ? ? }
EMA_MTMBuffer[]、EMA_AbsMTMBuffer[]、EMA2_MTMBuffer[] 和 EMA2_AbsMTMBuffer[] 的運(yùn)算塊不需要優(yōu)化計算,因?yàn)?ExponentialMAOnBuffer() 已經(jīng)是以最優(yōu)方式編寫。赫茲股票量化交易軟件僅需優(yōu)化 TSIBuffer[] 數(shù)組的值的計算。赫茲股票量化交易軟件使用用于 MTMBuffer[] 的同樣方法。
//--- 現(xiàn)在計算指標(biāo)的數(shù)值 ? if(prev_calculated==0) start=r+s-1; // 第一次計算的開始位置 ? for(int i=start;i<rates_total;i++) ? ? { ? ? ?TSIBuffer[i]=100*EMA2_MTMBuffer[i]/EMA2_AbsMTMBuffer[i]; ? ? }//--- 返回值會作為下一次調(diào)用的 prev_calculated 參數(shù)調(diào)用 ? return(rates_total);
關(guān)于優(yōu)化程序還有最后一點(diǎn):OnCalculate() 返回?rates_total?的值。這表示 price[] 輸入數(shù)組的元素數(shù)量,該數(shù)量用于指標(biāo)計算。
OnCalculate() 返回值保存在終端內(nèi)存中,并在下次調(diào)用 OnCalculate() 時作為輸入?yún)?shù) prev_calculated 的值傳遞給函數(shù)。
這讓赫茲股票量化交易軟件始終知曉 OnCalculate() 的上次調(diào)用中輸入數(shù)組的大小,并從正確的索引開始指標(biāo)緩沖區(qū)的計算而無需不必要的重復(fù)計算。
檢查輸入數(shù)據(jù)
要使 OnCalculate() 完美運(yùn)行,赫茲股票量化交易軟件還需進(jìn)行以下操作。我們需要檢查在其上計算指標(biāo)值的 price[] 數(shù)組。如果數(shù)組的大小 (rates_total) 過小,則無需計算 -?赫茲股票量化交易軟件需要等待,直至下次調(diào)用 OnCalculate() 時有足夠的數(shù)據(jù)。
//--- 如果price[]數(shù)組太小 ?if(rates_total<r+s) return(0); // 不進(jìn)行計算或者繪圖,直接退出//--- 如果這是第一次調(diào)用 ? ?if(prev_calculated==0) ? ? { ? ? ?//--- 把索引0的數(shù)據(jù)設(shè)為0 ? ? ?MTMBuffer[0]=0.0; ? ? ?AbsMTMBuffer[0]=0.0; ? ? }
由于指數(shù)平滑相繼兩次用于計算“真實(shí)強(qiáng)弱指數(shù)”,則 price[] 的大小須至少等于或大于時間周期 r 和 s 的和;否則執(zhí)行將終止,OnCalculate() 返回 0。返回零值意味著指標(biāo)將不會在圖表上繪制,因?yàn)椴⑽从嬎阒笜?biāo)的值。
設(shè)置表示法
若計算正確,則指標(biāo)可就緒待用。但如果赫茲股票量化交易軟件從其他 MQL5 程序調(diào)用該指標(biāo),則其默認(rèn)使用 Close(收盤)價格建立。我們也可以使用其他默認(rèn)價格類型 - 從指標(biāo)的?indicator_applied_price?屬性的?ENUM_APPLIED_PRICE?枚舉中指定一個值。
例如,若要設(shè)置典型價格((最高價+最低價+收盤價)/3)作為價格,則編碼如下:
#property?indicator_applied_price?PRICE_TYPICAL
如果赫茲股票量化交易軟件僅使用利用?iCustom()?或?IndicatorCreate()?函數(shù)的值,則無需進(jìn)一步的改進(jìn)。但如果是直接使用,例如在圖表上繪制,赫茲股票量化交易軟件推薦以下額外設(shè)置:
柱號,起始于繪制的指標(biāo);
TSIBuffer[] 中值的標(biāo)簽,將在 DataWindow 中反映;
將鼠標(biāo)光標(biāo)停留在指標(biāo)線上時將會在單獨(dú)窗口和幫助彈出窗口中顯示的指標(biāo)的短名稱。
指標(biāo)值中小數(shù)點(diǎn)后顯示的位數(shù)(這不會影響精確性)。
這些設(shè)置可使用來自自定義指標(biāo)組中的函數(shù)在 OnInit()處理函數(shù)中調(diào)整。添加新的線條并將指標(biāo)另存為 True_Strength_Index_ver2.mq5。
//+------------------------------------------------------------------+//| 自定義指標(biāo)初始函數(shù) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|//+------------------------------------------------------------------+int OnInit() ?{//--- 指標(biāo)緩沖區(qū)映射關(guān)系 ? SetIndexBuffer(0,TSIBuffer,INDICATOR_DATA); ? SetIndexBuffer(1,MTMBuffer,INDICATOR_CALCULATIONS); ? SetIndexBuffer(2,AbsMTMBuffer,INDICATOR_CALCULATIONS); ? SetIndexBuffer(3,EMA_MTMBuffer,INDICATOR_CALCULATIONS); ? SetIndexBuffer(4,EMA2_MTMBuffer,INDICATOR_CALCULATIONS); ? SetIndexBuffer(5,EMA_AbsMTMBuffer,INDICATOR_CALCULATIONS); ? SetIndexBuffer(6,EMA2_AbsMTMBuffer,INDICATOR_CALCULATIONS);//--- 設(shè)定從哪一個柱開始畫指標(biāo) ? PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,r+s-1); ? string shortname; ? StringConcatenate(shortname,"TSI(",r,",",s,")");//--- 設(shè)置在數(shù)據(jù)窗口(DataWindow)中的顯示標(biāo)簽 ? PlotIndexSetString(0,PLOT_LABEL,shortname); ? //--- 設(shè)置單獨(dú)子窗口或者彈出幫助時候的顯示名稱 ? IndicatorSetString(INDICATOR_SHORTNAME,shortname);//--- 設(shè)置指標(biāo)數(shù)值顯示的精確度 ? IndicatorSetInteger(INDICATOR_DIGITS,2);//--- ? return(0); ?}
如果赫茲股票量化交易軟件啟動兩種版本的指標(biāo),然后將圖表滾動至開始處,赫茲股票量化交易軟件會看到所有的差異。

小結(jié)
以創(chuàng)建“真實(shí)強(qiáng)弱指數(shù)”指標(biāo)為例,赫茲股票量化交易軟件可以歸納出在 MQL5 中編寫任何指標(biāo)的基本要點(diǎn):
要創(chuàng)建自己的自定義指標(biāo),使用“MQL5 向?qū)А?,它將幫助您?zhí)行指標(biāo)設(shè)置的基本例行操作。為 OnCalculate() 函數(shù)選擇必要的變量。
如必要,添加更多的數(shù)組用于中間計算,并使用?SetIndexBuffer()?函數(shù)將這些數(shù)組與相應(yīng)的指標(biāo)緩沖區(qū)綁定。為這些緩沖區(qū)指示?INDICATOR_CALCULATIONS 類型。
優(yōu)化 OnCalculate() 中的計算,因?yàn)樵摵瘮?shù)將會在每次價格數(shù)據(jù)改變時調(diào)用。使用現(xiàn)成的已調(diào)試函數(shù)讓代碼的編寫更加容易,并獲得更好的代碼可讀性。
對指標(biāo)進(jìn)行額外的視覺調(diào)整,使程序?qū)τ谄渌?MQL5 程序和用戶而言更易于使用。