簡介
在 MQL5 中,除了如“MQL5:創建您自己的指標”文中所述那樣從頭創建一個新的自定義指標之外,您還可以根據客戶端內置或自定義的另一個指標來編寫一個。有兩種方式:第一種是對某指標做出改進,添加新的計算和標繪(此情形僅適用於擁有開源代碼的自定義指標);第二種方式是使用終端內置的某個指標,或是通過 iCustom() 或 IndicatorCreate() 函數使用某現有自定義指標。
第一種方式:添加一個標繪
我們根據“將一個指標應用到另一個指標”一文來改進 True_Strength_Index_ver3 指標的示例,仔細研究一下這種指標創建方式。我們來添加一條帶有選擇指標類型與平滑周期可能性的信號線。整個流程分 8 個階段。
1. 制作一份文件複本
於 MetaEditor 中打開 True_Strength_Index_ver3 指標並以新名稱保存,比如 TSIs。新文件必須保存到終端根文件夾的 MQL5/Indicators 目錄中。
2. 更改指標屬性
於指標代碼中搜索 indicator_buffers 和 indicator_plots 屬性。indicator_buffers 屬性決定指標中使用的指標緩衝區的總數量,而 indicator_plots 屬性則決定圖表上顯示的緩衝區數量。指標當前使用 8 個緩衝區;其中一個顯示於圖表上。我們需要再添加一個顯示於圖表上的緩衝區。將 indicator_buffers 與 indicator_plots 的值加 1。
#property indicator_buffers 8 #property indicator_plots 2
3. 確定新緩衝區的顯示屬性
設置新緩衝區的顯示屬性。采用已通過此指標準備好的代碼。利用鼠標,複制確定指標首行顯示屬性的所有代碼。
//---- TSI 繪圖 #property indicator_label1 "TSI" #property indicator_type1 DRAW_LINE #property indicator_color1 Blue #property indicator_style1 STYLE_SOLID #property indicator_width1 1
將其插入首行屬性的下方並修改。
//---- TSISignal 繪圖 #property indicator_label2 "TSISignal" // 線的名稱,當鼠標光標停留在線上有彈出幫助時會顯示 #property indicator_type2 DRAW_LINE // 緩衝區類型 #property indicator_color2 Red // 線的顏色 #property indicator_style2 STYLE_SOLID // 風格 #property indicator_width2 1 // 線粗
首先,將屬性編號從 1 改為 2,因為其為第二緩衝區的屬性。將 indicator_label2 屬性改為 TSISignal - 此行名會在鼠標指針放在此行上方時在一個彈出幫助中顯示,還會顯示於數據窗口。indicator_type2 屬性應保持不變,緩衝區應作為行顯示。將 indicator_color2 屬性改為 Red - 新行將標紅色。indicator_style2 屬性保持不變 - 信號線是與主線類似的實線。indicator_width2 屬性亦應保持不變 - 新行有 1 像素厚。
4. 聲明外部變量
可通過指標修改的外部變量(以 "input" 開頭的行)位於代碼中行屬性的下方。信號線亦應有其參數 - 平滑周期與類型。
聲明其值為 5 的 int 類型外部變量並命名為 "sp" (平滑周期),將 ENUM_MA_METHOD 類型變量命名為 "sm" (平滑方法),且值為 MODE_EMA (信號線平滑周期為 5,默認指數型平滑)。現在,包含外部變量的代碼段如下:
input int r=25; input int s=13; input int sp=5; input ENUM_MA_METHOD sm=MODE_EMA;
5. 為新緩衝區聲明一個數組
我們聲明一個將來供指標緩衝區使用的數組。於代碼中搜索 OnInit() 函數,並查找 SetIndexBuffer() 函數的調用位置,以引導自己通過指標中指標緩衝區的現有數組。True_Strength_Index_ver3 指標中的這些數組分別為 TSIBuffer、MTMBuffer、AbsMTMBuffer、EMA_MTMBuffer、EMA2_MTMBuffer、EMA_AbsMTMBuffer、EMA2_AbsMTMBuffer。
TSIBuffer 數組的 SetIndexBuffer() 函數利用 INDICATOR_DATA 參數調用,這就意味着該緩衝區顯示於圖表上方。所有其它數組均利用 INDICATOR_CALCULATIONS 參數調用。這就意味着這些數組為輔數組,用於中間計算。
新緩衝區要顯示於圖表上,所以我們在 TSIBuffer 數組的聲明之後聲明它,保持邏輯順序,以備進一步改進該指標時代碼中的定向更方便。
由此,我們首先聲明兩個顯示於圖表上的緩衝區數組,然後再是用於中間計算的緩衝區數組。
//--- 指標緩衝區 double TSIBuffer[]; double TSISigBuffer[]; // 用於信號線新緩衝區的數組 double MTMBuffer[]; double AbsMTMBuffer[]; double EMA_MTMBuffer[]; double EMA2_MTMBuffer[]; double EMA_AbsMTMBuffer[]; double EMA2_AbsMTMBuffer[];
6. 將一個數組關聯一個緩衝區
現在到了非常重要的一步,此步驟要求投以格外的注意力和謹慎度 - 將一個數組與一個指標緩衝區關聯。關聯利用 SetIndexBuffer() 函數執行。函數調用中的第一個參數為數組索引,第二個是數組名稱,第三個則是指明緩衝區用途的標識符。緩衝區均按索引(第一個參數)排列於指標屬性窗口中的 "Colors" 選項卡,順序與其於圖表上的繪制順序相同,第一個為 0 緩衝區,然後是 1 緩衝區,以此類推。
沒必要針對索引 0、1、2……順序調用 SetIndexBuffer() 函數,我們幹脆保持 theSetIndexBuffer() 函數的調用順序即可。調用 TSIBuffer 數組函數後,執行 TSISigBuffer 數組調用。主線緩衝區(TSIBuffer 數組)索引為 0,這意味着下一個緩衝區(TSISigBuffer 數組)的索引應為 1。
調用 TSISigBuffer 數組 SetIndexBuffer() 函數的第三個參數為 INDICATOR_DATA 變量(此緩衝區顯示於圖表上)。
SetIndexBuffer(0,TSIBuffer,INDICATOR_DATA); SetIndexBuffer(1,TSISigBuffer,INDICATOR_DATA);
將其餘要利用第一個參數的順序遞增值調用的 SetIndexBuffer() 函數緩衝區重新索引。
SetIndexBuffer(0,TSIBuffer,INDICATOR_DATA); SetIndexBuffer(1,TSISigBuffer,INDICATOR_DATA); SetIndexBuffer(2,MTMBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(3,AbsMTMBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(4,EMA_MTMBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(5,EMA2_MTMBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(6,EMA_AbsMTMBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(7,EMA2_AbsMTMBuffer,INDICATOR_CALCULATIONS);
針對這種特定情況,建議按照遞增索引來保持調用 SetIndexBufer() 函數的順序。由此,也會減少進一步改進時的耗時耗力。
現在我們有 8 個緩衝區,其中兩個顯示於圖表上。確保亦於 indicator_buffers 和 indicator_plots 指標的屬性中指定相同的值(步驟 2)。
7. 計算信號線的值
信號線是指根據指標主線數據繪制的一條移動平均線。我們無需為此執行任何計算;客戶端交付中包括根據一個信息數組計算移動平均線的庫(MovingAverages.mqh 文件)。順便說一下,其已包含於指標代碼中(第 14 行):
#include <MovingAverages.mqh>
只剩下使用其功能一件事了。
在 OnCalculate() 函數中找到指標主線計算完成的點(TSIBuffer 數組)。我們來使用搜索功能;選擇 TSIBuffer 數組的名稱,比如在其聲明的代碼部分中(圖 1)。然後執行 "Main Menu" - "Edit" - "Find and replace" - "Find" 命令或使用 Ctrl+F 組合鍵。
圖 1. 選取的數組名稱。
"TSIBuffer" 一詞已被鍵入到打開的 "Find" 窗口的 "Find what" 字段中。於 "Direction" 區段中選擇 "Up" 。現在,打開 "Find" 窗口後,將指針置於 OnCalculate() 函數的後面,按一次 "Find Next" 按鈕,您馬上就會找到 TSIBuffer 數組計算結束的位置。計算於 "for" 循環中執行。我們緊隨此循環之後,添加信號線計算的代碼(圖 2)。
圖 2. TSIBuffer 計算值的最後找到位置(紅色箭頭)。紅框標注為執行計算循環的位置。
全部四種主要移動平均線類型計算的函數,均被納入 MovingAverages.mqh 庫中:
- 針對簡單型 - SimpleMAOnBuffer(),
- 針對指數型 - ExponentialMAOnBuffer(),
- 針對線性加權型 - LinearWeightedMAOnBuffer(),
- 針對平滑型 - SmoothedMAOnBuffer()。
上述所有函數都擁有一個相同的參數集:
const int rates_total, const int prev_calculated, const int begin, const int period, const double& price[],double& buffer[]
此函數的 price[] 參數會確定一個數組,該數組包含待執行移動平均線計算的初始數據。buffer 參數是存儲移動平均線值的數組。rates_total 與 prev_calculated 參數與 onCalculate() 函數的 rates_total 和 prev_calculated 參數相同,它們會確定 price[] 數組的大小以及該數組已處理元素的數量。begin 參數是重要數據開頭數組某元素的索引。
鑒於 MovingAverages.mqh 庫中移動平均線計算各算法的獨特性(此功能於本文主題不相關),我們需要一種謹慎的方法來設置 begin 參數。
此參數任何情況下均不得設置到比源數據起始值(TSIBuffer 數組)更早的數組元素。如果不會導致計算錯誤,則允許其指定一個較晚的元素。
為確定一個可接受的 begin 值,要格外注意 for cycle 參數,TSIBuffer 數組值於此計算 - 周期始於 start 變量值。我們需要找到其於指標首次計算期間擁有的 start 變量值(當 prev_calculated 值為 0 時)。"start" 變量的值就在此周期之前、當 prev_calculated=0 時計算;計算利用下述公式執行:
start=begin+r+s-1;
被傳遞至移動平均線計算函數的 begin 變量值,必須等於該值。
計算循環過後,TSIBuffer 數組就會聲明 begin2 變量並將 begin+r+s-1 值分配給它。
int begin2=begin+r+s-1;
如欲根據外部參數 "sm" 的值提供使用不同平滑函數的可能性,則使用 switch 操作符。針對 sm 變量值的每一種情形,編寫相應函數的調用。
switch(sm) { case MODE_EMA: ExponentialMAOnBuffer(rates_total,prev_calculated,begin2,sp,TSIBuffer,TSISigBuffer); break; case MODE_LWMA: LinearWeightedMAOnBuffer(rates_total,prev_calculated,begin2,sp,TSIBuffer,TSISigBuffer); break; case MODE_SMA: SimpleMAOnBuffer(rates_total,prev_calculated,begin2,sp,TSIBuffer,TSISigBuffer); break; case MODE_SMMA: SmoothedMAOnBuffer(rates_total,prev_calculated,begin2,sp,TSIBuffer,TSISigBuffer); break; }
之後我們就能看到帶有信號線的指標了。按下 "Compile" 按鈕,打開客戶端並將此指標附至圖表(圖 3)。
圖 3. 指標 TSIs,藍色 - 主線,紅色 - 新的,信號線。
8. 切掉緩衝區繪圖的開頭部分
如果您將含有指標的圖表滾動至左邊緣,就會看到值未被計算的部分的指標繪線。看起來很不美觀(圖 4)。
圖 4. 未執行計算部分的指標繪圖。
采用通過 PLOT_DRAW_BEGIN 標識符調用的 PlotIndexSetInteger() 函數,確定未被繪制緩衝區區域的首柱數量。此函數的調用應於該指標的 OnInit() 函數內完成。於 OnInit() 的結尾添加此函數調用,當然,還要在 return(0) 調用之前。
PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,r+s+sp);
再次按下 "Compile" 按鈕,以獲取指標繪制的正確開頭(圖 5)。
圖 5. 指標繪制的正確開頭。
第二種方式。基於現有指標創建一個新的指標
我們會利用創建 TSIs 指標主線和信號線平滑異同指標的一個示例來研究這種方式。該指標會被繪制為一個直方圖且有兩種顏色,與 AO、AC 指標相同。如果指標值增長,則此直方圖標以綠色;如果減少,則標以紅色。前面的簡介中我們提到過,如欲引用另一個指標,您可以使用 iCustom() 或 IndicatorCreate() 函數。首先,我們來講講利用 iCustom() 函數創建一個指標。
利用 iCustom() 函數創建指標
1. 創建新指標
我們來創建一個新指標。想在 MetaEditor 中創建一個新指標,您應執行 "Main Menu" - "File" - "New" - "Custom Indicator" 命令或按下 "Ctrl+N" 組合鍵。在出現窗口的 "Name" 字段中指定新指標的名稱 - TSIsCDiCust,再按下 "Add" 按鈕。添加一個外部參數,其名稱並沒有確定代碼中外部參數某個部分那麼重要;而且它會方便由 TSIs 指標複制所有外部參數(圖 6)。
圖 6. 利用向導創建一個自定義指標的第一步。
按下 "Next" 按鈕。
在下個窗口中指定將於某個獨立窗口中繪制的指標。不要界定最小值與最大值。按下 "Add" 按鈕,指標緩衝區列表中就會出現一個新的緩衝區;指定其名稱 - TSIsCD (如果您將鼠標指針置於指標行上方和數據窗口中時,它就會於一個彈出幫助中顯示) 及其類型 - 彩色直方圖。
此後,"Color" 字段中就會出現幾種顏色示例。為第一個示例指定綠色,第二個指定紅色,其它保持不變。再添加兩個名為 Tsi 和 TsiSignal 的緩衝區,它們將用於接收和存儲 TSIs 指標的值(圖 7)。
圖 7. 利用向導創建一個自定義指標的第二步。
按下 "Finish" 按鈕,新指標的模板就會在 MetaEditor 中打開。
2. 編輯指標與指標緩衝區的屬性
我們已於步驟 1 中確定了 3 個緩衝區,但是,#property indicator_buffers 的值為 4。問題是一個彩色直方圖使用了兩個緩衝區 - 一個顯示於圖表上,打算為指標值所用;還有一個則用於確定第一緩衝區的顯示顏色。#property indicator_buffers 值保持不變。將 #property indicator_plots 值改為 1 - 圖表上只應顯示一個緩衝區。
Tsi 與 TsiSignal 緩衝區不得顯示於圖表上,所以刪除其所有屬性(以 2 和 3 結尾的所有指標屬性)。
//--- Tsi 繪圖 #property indicator_label2 "Tsi" #property indicator_type2 DRAW_LINE #property indicator_color2 Red #property indicator_style2 STYLE_SOLID #property indicator_width2 1 //--- TsiSignal 繪圖 #property indicator_label3 "TsiSignal" #property indicator_type3 DRAW_LINE #property indicator_color3 Red #property indicator_style3 STYLE_SOLID #property indicator_width3 1於 OnInit() 函數中查找上述緩衝區的 SetIndexBuffer() 函數調用(數組名稱為 TsiBuffer 與 TsiSignalBuffer),將第三參數的值由 INDICATOR_DATA 改為 INDICATOR_CALCULATIONS。
SetIndexBuffer(2,TsiBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(3,TsiSignalBuffer,INDICATOR_CALCULATIONS);
修改 indicator_color1 屬性 - 只保留前兩種顏色。
#property indicator_color1 Green,Red
3. 聲明外部參數
於 MetaEditor 中打開 TSIs 指標,並由其複制所有外部變量,利用這些參數替換當前的外部變量 Input1。
//--- 輸入參數 input int r=25; input int s=13; input int sp=5; // 平滑周期 input ENUM_MA_METHOD sm=MODE_EMA; // 平滑類型
4. 為指標句柄聲明一個變量並調用此指標
於指標的共用區段中聲明一個 int 類型變量並命名為 Handle。於 OnInit() 的最底部調用 iCustom() 函數。此函數會返回所創建指標的句柄;我們則需要用它來接收指標值。將此函數返回的值賦給 Handle 變量。
iCustom() 函數的前兩個參數會確定交易品種和時間表,這些數據會被用於計算指標。我們來指定指標所附的交易品種和時間表 - _Symbol 與 PERIOD_CURRENT。第三個參數是自定義指標的名稱,本例中是 TSIs。被調用指標的所有外部參數進一步列出如下:
Handle=iCustom(_Symbol,PERIOD_CURRENT,"TSIs",r,s,sp,sm);
5. 制備 OnCalculate() 函數
我們轉到 OnCalculate() 函數上來。TSIs 指標根據數據的一個緩衝區計算,所以我們會采用 OnCalculate() 函數的第一種形式。在模板中將 OnCalculate() 函數現有的第二種形式改為第一種。
int OnCalculate(const int rates_total, // price[] 數組的大小 const int prev_calculated, // 在前一次調用中處理的柱數 const int begin, // 大數據起點 const double &price[] // 用於計算的數組 ) { return(rates_total); }
有關指標的進一步工作均將於此函數內完成。
6. 確定指標計算的極限
任何指標開發過程中,最優先最重要的都是確定處理柱的限制範圍。指標啟動時,我們應在其運行期間履行指標每柱的計算 - 僅針對當前形成的一個。您可以通過 prev_calculated 變量的值探測到指標啟動的時機。如果此值為零,則這是自指標啟動以來首次執行 OnCalculate() 函數。
首次執行 OnCalculate() 函數時,您要確定計算起始的首柱的索引。其值由指標值計算所需的柱數確定(索引由左向右執行)。
指標線的傾斜由兩個柱確定,所以我們還需要另一個前柱。柱索引,price[] 數組起始的重要數據已知 - 即 begin 變量的值;所以我們從 start=begin+1 柱開始柱計算。
此外,指標工作期間,計算起始的柱索引是由 prev_calculated 變量的值確定的 - 此變量中包含已經處理的柱的數量。因此,想要查出已執行計算的上一個柱,您要從 prev_calculated 減 1。
上一個已經處理的柱會被再次納入計算 - 因為它可能是一個成形柱。計算的限值由 price[] 數組的大小確定 - rates_total 變量。已執行計算的上一個柱的索引為 rates_total-1 (比數組大小小 1)。
因為指標會使用另一指標的數據供其計算,所以我們要獲取該數據。您可以利用 CopyBuffer() 函數獲取另一指標的數據。您應於函數的第一個參數中指定指標的句柄,複制其相關數據(句柄已於階段 4 中獲取);於第二個參數中指定被複制緩衝區的索引(必要值可通過被複制指標屬性的 "Color" 選項卡確定,從零開始計數)。
第三個參數是複制起始柱的索引;本例中的索引是從右到左執行,所以最右邊的柱為零。第四個參數為待複制的數組元素數量。確定被複制元素數量時,應像確定納入計算的柱的範圍一樣小心謹慎。它會影響到指標的性能。指標計算起始的柱索引已初步確定,所以被複制元素數量則按 rates_total-start 計算。工作過程中,如果只計算成形柱指標,則僅複制數組的一個元素。
如在嘗試複制信息時 CopyBuffer() 函數返回 -1,則意味着此數據不得複制,所以也就無需執行計算了。此錯誤應予處理。於 CopyBuffer() 的最開頭聲明一個 bool 類型的靜態變量並命名為 "error"。如在指標計算過程中出現錯誤,尤其是複制指標數據的錯誤,則為此變量賦 True 值,並結束 OnCalculate() 函數的執行。
如果錯誤值顯示此前執行的 OnCalculate() 函數有誤,則在下一個訂單號再次重新計算整個指標。由此,OnCalculate() 函數的開頭如下:
static bool error=true; int start; if(prev_calculated==0) // 在開始指標後第一次執行OnCalculate()函數 { error=true; // 把值設為 True 用於計算所有柱 } if(error) // 如果 error=true, 說明是在開始指標後第一次執行 // 或者之前開始時複制數據出錯 { start=begin+1; error=false; } else { start=prev_calculated-1; } if(CopyBuffer(Handle,0,0,rates_total-start,TsiBuffer)==-1) // 複制指標主線的數據 { error=true; // 複制數據失敗, 把error變量的值設為 True 準備下次調用 // OnCalculate() 的時候全部重新計算指標 return(0); // 退出函數工作 } if(CopyBuffer(Handle,1,0,rates_total-start,TsiSignalBuffer)==-1) // 複制指標的信號線數據 { error=true; // 複制數據失敗, 把 error 變量的值設為 true 準備下次調用 // OnCalculate() 函數的時候全部重新計算指標 return(0); // 退出函數工作 }
指標計算的限值已經確定,再於這個柱範圍內制作一個計算循環。
for(int i=start;i<rates_total;i++) { }
計算指標值(代碼位於剛剛創建的循環中)。
TsiCDBuffer[i]=TsiBuffer[i]-TsiSignalBuffer[i];
現在到了大家最感興趣的部分了 - 緩衝區上色。在此前的階段 1 中,我們已經確定了指標緩衝區彩色直方圖的使用。該繪制類型要求有兩個緩衝區 - 一個用於指標值,另一個用於顏色。顏色列表於 indicator_color1 屬性中設置。如果緩衝區元素值設置為 0,則指標以綠色顯示;如果值設置為 1,則指標為紅色(按照它們在列表 indicator_color1 中的位置;從零開始計數)。
不可避免會產生兩個相鄰柱的指標值相等的情況,這種情況下,指標應以此前的顏色顯示(因為我們用以顯示上下動作的顏色只有兩種)。因此,計算開始時,我們會複制前柱上 TsiCDColors 緩衝區的值:
TsiCDColors[i]=TsiCDColors[i-1];
向上移動時,指標上綠色:
if(TsiCDBuffer[i]>TsiCDBuffer[i-1])TsiCDColors[i]=0;
向下移動時,指標上紅色:
if(TsiCDBuffer[i]<TsiCDBuffer[i-1])TsiCDColors[i]=1;
我們快要看到指標相關工作勝利的曙光了 - 只剩下確定指標繪制的開頭。
7. 完成指標相關工作
盡管 begin 變量用於確定指標的計算,但並不意味着指標數據從被標識為 begin 變量的柱開始。如果不清楚某自定義指標的算法,想探測到指標計算所需的柱數幾乎是不可能的。正因如此,此階段亦可跳過,或者您也可以根據經驗探測某值。但是我們知道 TSIs 指標的算法,所以可精確地探測到此指標的開頭。將帶有 PLOT_DRAW_BEGIN 標識符的 PlotIndexSetInteger() 函數調用添加到 OnInit() 函數。
PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,r+s+sp);
TSIs 指標的顯示值精確到兩位小數;利用帶有 INDICATOR_DIGITS 標識符的 IndicatorSetInteger() 函數設置同樣的精確度:
IndicatorSetInteger(INDICATOR_DIGITS,2);
對指標進行編譯,並將其附至圖表(圖 8)。
圖 8. 指標 TSIsCDiCust。
利用 IndicatorCreate() 函數創建指標
利用 IndicatorCreate() 函數與利用 iCustom() 函數創建指標基本相同,只是步驟 4 有所區別 - 是利用 IndicatorCreate() 函數,而非 iCustom()。
1. 保存 TSIsCDiCust 指標的一份複本並命名為 TSIsCDiCreate。
2. 查找 iCustom() 函數於代碼中何處被調用。自此以後,IndicatorCreate() 函數的調用將取代 iCustom() 執行。與 iCustom() 相同,IndicatorCreate() 函數的前兩個參數會確定將用於指標計算的交易品種和時間表。第三個參數是指標類型的一個標識符,對於某個自定義指標而言即 IND_CUSTOM。創建指標的參數被傳遞至采用 MqlParam 結構數組的函數。
MqlParam 包含四個變量 - 其中三個都是用於下述值的不同類型的變量:double_value、integer_value 與 string_value;另一個為 type,它會確定使用變量的類型。TSIs 指標擁有四個外部參數。因是自定義指標,所以數組的第一個元素會確定自定義指標的名稱,由此,數組應包含五個元素。聲明一個結構數組(代碼位於 iCustom() 被調用的地方):
MqlParam Params[5];
將相應值填入數組:
Params[0].type=TYPE_STRING; Params[0].string_value="TSIs"; // 在第一個參數中指定調用自定義指標的名稱 Params[1].type=TYPE_INT; Params[1].integer_value=r; Params[2].type=TYPE_INT; Params[2].integer_value=s; Params[3].type=TYPE_INT; Params[3].integer_value=sp; Params[4].type=TYPE_INT; Params[4].integer_value=sm;
傳遞至 IndicatorCreate() 函數的四個參數,我們已經處理了前三個。參數數組的大小則通過第四個參數傳遞;最後這個參數是一個帶有自身參數的數組:
Handle=IndicatorCreate(_Symbol,PERIOD_CURRENT,IND_CUSTOM,5,Params);
它被留作按下 "Compile" 按鈕並於客戶端中檢查指標用途。
總結
我們簡要回顧一下根據另一指標創建自定義指標時您應注意到的幾個主要概念。
改進某指標時,您要正確指定緩衝區的數量和待繪制緩衝區的數量(indicator_buffers、indicator_plots 屬性);您應確定新緩衝區的屬性(indicator_label、indicator_type、indicator_color、indicator_style、indicator_width 屬性)。調用新緩衝區的 SetIndexBufer() 函數時,您應指定第三個參數的正確值(INDICATOR_DATA 或 INDICATOR_CALCULATIONS);並正確指定第一個參數的值(緩衝區索引);必要時執行緩衝區的重新索引。
利用另一個自定義指標創建一個新指標時,您要將參數正確地傳遞至 iCustom() 函數;並在使用 IndicatorCreate() 函數時填寫參數結構。這里您還應注意到調用 SetIndexBuffer() 函數時參數的正確規範;而且重要的是不要忘記執行新緩衝區的 SetIndexBuffer() 函數調用。
每次使用指標,您都應重視柱計算的範圍 - 利用 prev_calculated、rates_total、begin 變量的值。MetaEditor 會幫助您處理編程過程中可能出現的其它錯誤(編譯期間出現的錯誤信息會顯示於 "Errors" 選項卡)。