English Русский 中文 Español Deutsch Português 한국어 Français Italiano Türkçe
他のインジケーターをベースにインジケーターを作成する

他のインジケーターをベースにインジケーターを作成する

MetaTrader 5 | 18 9月 2015, 18:34
7 573 0
Dmitry Fedoseev
Dmitry Fedoseev

はじめに

MQL5では "MQL5: Create Your Own Indicator" の記事で説明されているようにゼロから新しいカスタムインジケーターを作成する外に、顧客の端末に組み込みのあるいはカスタムのインジケーターを基にして書くこともできる。2つの方法があり、第1はあるインジケーターを改良し、新しい計算とグラフを追加する方法(これはオープンソースコードをもつカスタムインジケーターに対して適用できる)、第2の方法は 顧客の端末に組み込みのあるいはカスタムのものを iCustom() あるいは IndicatorCreate() ファンクション経由で使うことである。


第1の方法 グラフを追加する

この方法を、記事 "Applying One Indicator to Another"に掲載の True_Strength_Index_ver3 インジケーターを改良する例でインジケーターを創作する方法を詳細に考察していこう。そのインジケーターに平滑化のタイプと期間を選択できる信号ラインを加えよう。全体のプロセスは8つの段階からなっている。

1. ファイルのコピーを作成する。

MetaEditor でTrue_Strength_Index_ver3 インジケーター を開きそして新しい名前で保存する。新しいファイルはterminal root folderのMQL5/Indicatorsのディレクトリーに保存する。

2. インジケーターの特性を変更する。

インジケーターのコードで indicator_buffersindicator_plots properties を探す。 indicator_buffers のプロパティーはインジケーターの中で使用するインジケーターバッファーの総数を決定し、indicator_plots プロパティ はチャート上に表示されるバッファーの数を決定する。現在8つのバッファーがインジケーターで使用されていて、そのうち1つがチャート上に表示されている。もう1つのチャート上に表示されるバッファーを加える必要がある。 indicator_buffersindicator_plots の値を1増やす。.

#property indicator_buffers 8 
#property indicator_plots 2

3. 新しいバッファーの表示特性を決定する。

新しいバッファーの表示特性を設定する。この インジケーターから既に準備されたコードを使う。マウスを使ってインジケーターの第1ラインの表示の特性を決定しているコードをコピーする。

//---- plot TSI
#property indicator_label1 "TSI"
#property indicator_type1 DRAW_LINE
#property indicator_color1 Blue
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1

それを第1ラインの特性の下に挿入し、それを変更する。

//---- plot TSI Signal
#property indicator_label2 "TSISignal" // Line name that is displayed in a pop up help when the mouse cursor is put over the line
#property indicator_type2 DRAW_LINE    // Type of buffer 
#property indicator_color2 Red         // Color of the line
#property indicator_style2 STYLE_SOLID // Style
#property indicator_width2 1           // Thickness of the line

まず最初に、これは第2のラインの特性なので特性の数を1から2に変更する。 indicator_label2 特性をTSISignalとする。これはラインの名称で、マウスがラインの上に来たときポップアップヘルプの中に表示され、またデータウインドウ中にも表示される。 indicator_type2特性は変更無く残されるべきであり、バッファーはラインとして表示されるべきである。indicator_color2 特性を に変える - 新しいラインは赤色となる。indicator_style2 特性は同じに残る - 信号ラインは主ラインと同様実線である。indicator_width2 特性は同じに残る - 新ラインは1画素の線幅とする

4. 外部変数を宣言する

外部変数はインジケーターを通じて変化させることができ(ラインは"input" 単語と共に始まる) それはコードのラインの特性の下にある。信号ラインはそのパラメーターを持っている - 平滑化の期間とタイプ

int タイプの外部変数の値を 5 とし名前を"sp" (smoothing period:平滑期間), そして ENUM_MA_METHODタイプの変数を"sm" (smoothing method:平滑方法) 値を MODE_EMAとする (初期設定で信号ラインは平滑期間を5そしてエクスポネンシャルタイプを持つ)。これで外部変数を含むコードの部分は次のようになる:

input int r=25;
input int s=13;
input int sp=5;
input ENUM_MA_METHOD sm=MODE_EMA;

5. 新しいバッファーのために配列を宣言する

インジケーターのバッファーのために1つの配列を宣言する。コードの中からOnInit() ファンクションを探し、そしてSetIndexBuffer() ファンクションを呼び出しているところを見つけ、インジケーターの中で既存のインジケーターの配列がどうなっているかを理解する。True_Strength_Index_ver3 indicator の中で、その配列は MTMBuffer、 AbsMTMBuffer、EMA_MTMBuffer、EMA2_MTMBuffer、 EMA_AbsMTMBuffer、 EMA2_AbsMTMBufferである。

TSIBufferのSetIndexBuffer()ファンクションを INDICATOR_DATA パラメーターをつけて呼び出す、するとそのバッファーはチャート上に表示される。他の配列は全て INDICATOR_CALCULATIONS パラメーターをつけて呼び出す。すると配列は補助的に間に嵌る計算に用いられる。

新しいバッファーはチャートの上に表示されるはずなので TSIBuffer 配列を宣言した後でプログラムを整理しインジケーターの更なる改良が容易にできるようにしておく。

こうして、まずチャートに表示されるバッファーの2つの配列を宣言し、そして中間の計算に使用されるバッファーのための配列を宣言する。

//--- indicator buffers
double TSIBuffer[];
double TSISigBuffer[]; // Array for new buffer of the signal line
double MTMBuffer[];
double AbsMTMBuffer[];
double EMA_MTMBuffer[];
double EMA2_MTMBuffer[];
double EMA_AbsMTMBuffer[];
double EMA2_AbsMTMBuffer[];

6. 配列をバッファーと結びつける。

ここで非常に注意と配慮を払うべき重要な段階にきた - 配列をインジケーターバッファーに結合する。結合は SetIndexBuffer() ファンクションを用いて行う。ファンクション呼び出しの最初のパラメーターは配列のインデックス、2番目は配列の名前、3番目はバッファーの目的を示す識別子である。バッファーはインジケーター・プロパティ・ウインドウの"Colors" タブの所に、インデックス (第1パラメーター)に従った場所にあり、チャート上に描かれるのと同じ順序に、第1は0バッファー、次に1バッファーがその上になどとなっている。

SetIndexBuffer() ファンクションはインデックス 0, 1, 2...の付いたバッファーに対して順番に呼び出されるが、 SetIndexBuffer() ファンクションの呼び出しの順序を守ろう。TSIBuffer 配列のファンクションの呼び出しの後でTSISigBuffer配列のファンクションの呼び出しを実行する。主ラインのバッファー( TSIBuffer配列) はインデックス 0 を持ち、従って次のバッファー(TSISigBuffer 配列) はインデック1を持つ。

TSISigBuffer配列のためのSetIndexBuffer() ファンクション呼び出しの第3のパラメーター INDICATOR_DATA 定数 (そのバッファーはチャートに表示される)。

SetIndexBuffer(0,TSIBuffer,INDICATOR_DATA);
SetIndexBuffer(1,TSISigBuffer,INDICATOR_DATA);

SetIndexBuffer()ファンクション のための残りのバッファーを第1パラメーターの値を順に増やして呼び出されるよう再度インデックス付けを行う。

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つのバッファーを持った。そのうち2つはチャートに表示される。 indicator_buffersindicator_plots インジケーター(第2ステップ)のプロパティに必ず同じ値が指定されるようにする。

7. 信号ラインの値を計算する

信号ラインはインジケーターの主ラインのデータから引き出される移動平均を表わす。われわれはそのための計算をする必用はない。クライアント側ターミナルが情報の配列上の移動平均の計算のためのライブラリーを提供している(ファイル MovingAverages.mqh)。それはそうと、それは既にインジケーターのコードの中に含まれている。(ライン14):

#include <MovingAverages.mqh>

唯一取れる手段は、その機能を使うことである。
OnCalculate() ファンクションはインジケーターの主ラインの計算が終わった所 (TSIBuffer 配列)を見つける。サーチファンクションを用いTSIBuffer 配列の名前を見つける、例えばそれが宣言されているコードの部分に見つかる(図 1)。"Main Menu" から"Edit" - "Find and replace" そして "Find" 命令を実行するか、 Ctrl+F キー組合せを用いる。


図. 1. 列の名前を選択する。

"Find" ウインドウで"TSIBuffer"の語は既に "Find what" のフィールドに記入されている。"Direction"部分で"Up" を選択する。ここで、"Find" ウインドウが開くと、カーソルを OnCalculate() ファンクションのすぐ右に置き、"Find Next" ボタンを一度押すと TSIBuffer配列の計算が終わる所を直ちに発見する。 計算は"for" ループで実行される。我々はこのループの直後のラインに計算のコードを加える (図. 2)。

TSIBuffer の値の計算の最後の場所 (赤の矢印)。計算が実行されるサイクルは赤のフレームで示されている。
図 2. TSIBuffer の値の計算の最後の場所 (赤の矢印)。計算が実行されるサイクルは赤のフレームで示されている。

主な4つのタイプの移動平均は 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_totalprev_calculated パラメーターはonCalculate()ファンクションの rates_total と prev_calculated パラメーター と同じであり、それらはprice[] 配列のサイズと配列の既に処理された要素の数を決定する。begin パラメーターは配列で意味のあるデータが始まる要素のインデックスである。

MovingAverages.mqh ライブラリーで移動平均の計算をするアルゴリズムの特異性を考慮して(この特徴は本論説で扱うには適切ではない)、begin パラメーターの設定を注意深く行わなければならない。

どの場合でもこのパラメーターは配列(TSIBuffer 配列)のソースデータの値が始まる要素より前の要素に設定してはならない。計算でエラーが出ない限りそれより後の要素を指定することは許される。

beginに許される値を決定するには、TSIBuffer 配列の値が計算される for cycleに注意する - サイクルはstart 変数の値から始まる。インジケーターの最初の計算の際に使うstart 変数を見つける必用がある( prev_calculated の値が 0になっているとき)。prev_calculated=0のとき"start"変数は’サイクルの直前に次の式を用いて計算される;

start=begin+r+s-1;

移動平均を計算するファンクションに渡される begin 変数はその値に等しくなければならない。

TSIBuffer 配列の計算ループの後で begin2 変数を宣言し begin+r+s-1 の値をそれに割り当てる。.

int begin2=begin+r+s-1;

外部パラメーター "sm"の値によって異なった平滑ファンクションを用いる可能性を提供するには、 switch operatorを用いる。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. インジケータTSI, 青 - 主ライン、 赤 - 新信号ライン。

8. Cutting Off theバッファーの最初の描画を切り取る

インジケーターのチャートを左端にスクロールすると、インジケーターが値を計算していない部分でもラインを描いているのを見えるが、綺麗に見えない (図 4)。



図 4. インジケーターの計算が行われ無かった部分の描画

PLOT_DRAW_BEGIN 識別子で呼び出されたPlotIndexSetInteger() ファンクションを用いると、バッファーが描かれない最初のバーの数を決定することができる。このファンクションの呼び出しはインジケーターOnInit() ファンクションの内部から実行されなければならない。このファンクションの呼び出しはOnInit()の最後で、しかし 当然のこととしてreturn(0)の呼び出しの前に加える。

PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,r+s+sp);

"Compile"ボタンをもう一度押し、インジケーターの正しい最初の描画を得る(図 5)。



図 5. インジケーターの正しい描画の始まり


第2の方法。 既存のものの上に新しいインジケーターを作成する。


TSIsインジケーターの主および信号ラインの収束と拡散した インジケーターの作成の例を用いてこの方法を考察する。そのインジケーターはあるヒストグラム として描かれ、AOAC の2つのを持ったインジケーターを得る。インジケーターの値が増加するとヒストグラムは緑色となり、減少すると赤色となる。上記の「はじめに」の章にて述べたように、他のインジケーターを引用するために、iCustom() あるいは IndicatorCreate()ファンクションを使うことができる。まず最初に、 iCustom() ファンクションを用いたインジケーターの作成を見てみよう。


iCustom() ファンクションを用いたインジケーターの作成

1. 新しいインジケーターの作成

新しいインジケーターを作成しよう。MetaEditor で新しいインジケーターを作成するために"Main Menu" から"File" - "New" を経て "Custom Indicator"コマンドを実行するか、"Ctrl+N" のキー組合せを押す。現れたウインドウで"Name" に新しいインジケーター の名前を TSIsCDiCust とし"Add" ボタンを押す。1つの外部パラメーターを加える、その名前はコード中に外部パラメーターを置く部分に比べると重要ではない。さらにTSIs インジケーターから全ての外部パラメーターをコピーすることは容易である(図 6)。


ウィザードでカスタムなインジケーターを作成する最初のステップ
図 6. ウィザードでカスタムなインジケーターを作成する最初のステップ

"Next" ボタンを押す。

次のウインドウにおいてインジケーターが別のウインドウに描かれるように指定する。最大値と最小値は定義しない。"Add" ボタンを押すとインジケーターバッファーのリストの中に新しいバッファーが現れ、その名前をTSIsCD (この名前はマウスをインジケーターラインの上の置くと吹出しヘルプの中にまたデータウインドウにも表示される) とし、そのタイプを Color Histogram とする。

その後数種類の色の例が "Color" フィールドに現れる。Green 色を最初の例で、Red 色を第2のものに指定し、その他は変更しない 。さらに2つのバッファーを加えTsi とTsiSignal と名付ける。 TSIs インジケーターの値を受け取り保存するのに用いる (図 7)。


ウイザードでカスタムのインジケーターを作成する第2のステップ
図 7. ウイザードでカスタムのインジケーターを作成する第2のステップ

"Finish" ボタンを押すと、新しいインジケーターのテンプレートがMetaEditor の中で開く。

2. インジケーターとインジケーターバッファーのプロパティを編集する

ステップ 1 で3つのバッファーを決定した。しかし #property indicator_buffersは 4である。これは色つきヒストグラムが2つのバッファー を使うからで、 1つはチャートに表示されインジケーターの値用に意図され、第2のものは第1のバッファーの表示の色を決定することを意図されている。#property indicator_buffers の値は変更無く残す。#property indicator_plots の値は 1に変更する - これは1つのバッファーのみがチャートに表示されることを意味する。

Tsi と TsiSignal のバッファーはチャートに表示されず、これが 全てのプロパティを消去する理由である(インジケーターの全てのプロパティは2か3で終わる)。

//--- plot Tsi
#property indicator_label2 "Tsi"
#property indicator_type2 DRAW_LINE
#property indicator_color2 Red
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
//--- plot TsiSignal
#property indicator_label3 "TsiSignal"
#property indicator_type3 DRAW_LINE
#property indicator_color3 Red
#property indicator_style3 STYLE_SOLID
#property indicator_width3 1
OnInit()ファンクションにおいてこれらのバッファー(配列の名前は TsiBuffer とTsiSignalBuffer)のための SetIndexBuffer() ファンクションの呼び出しを見つけ、第3パラメーターを INDICATOR_DATA から INDICATOR_CALCULATIONSに変更する。
SetIndexBuffer(2,TsiBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(3,TsiSignalBuffer,INDICATOR_CALCULATIONS);

indicator_color1 の特性を変え - 最初の2つの色のみを残す。

#property indicator_color1 Green,Red

3. 外部パラメーターの宣言

MetaEditorでTSIsインジケーターを開きそしてそこから全ての外部変数をコピーし、 現在の 外部変数 Input1 をそれらのパラメーターで置き換える。

//--- input parameters
input int r=25;
input int s=13;
input int sp=5;                 // Smoothing period
input ENUM_MA_METHOD sm=MODE_EMA; // Smoothing type

4. インジケーターハンドルの変数を宣言しインジケーターを呼び出す。

インジケーターの共通部int タイプの変数を宣言しそれをハンドルと名付ける。iCustom() ファンクションを OnInit()の一番下で呼び出す。そのファンクションは作成したインジケーターの handle を戻し、それをインジケーターの値を受け取るのに必要とする。ファンクションから戻った値をハンドル変数に割り当てる。

iCustom() ファンクションの最初の2つのパラメーターはシンボルと時間枠を決定し、そのデータはインジケーターの計算ために使われる。インジケーターが取り付けられるシンボルと時間枠を指定する - _SymbolPERIOD_CURRENT。第3のパラメーターはカスタムインジケーターの名前であり、この場合それはTSIs である。呼び出されるインジケーターの全ての外部パラメーターがさらに列挙される。

Handle=iCustom(_Symbol,PERIOD_CURRENT,"TSIs",r,s,sp,sm);

5. OnCalculate() ファンクションを準備する

OnCalculate() ファンクションに移ろう。TSIs インジケーター はデータのバッファー上に計算されるので、最初のOnCalculate() ファンクションの形式を使う。既存の OnCalculate() ファンクションのテンプレートにある第2の形式を第1のものに変更する。

int OnCalculate(const int rates_total,         // size of the price[] array
                const int prev_calculated,   // bars processed during the previous call
                const int begin,             // from where the significant data begin
                const double &price[]        // array for calculation
                )
  {
   return(rates_total);
  }

インジケーターについての作業がこのファンクションの内部で行われる。

6. インジケーターの計算の限界を決定する。

どのインジケーターの開発でも第1優先で重要なことは処理バーの範囲の限界を決定することである。インジケーターの最初には各バーについてインジケーターの計算を実行し、操作の途中では現在形成されたものにのみ実行する。インジケーターのスタートの時をprev_calculated 変数の値から検出できる。もしこの値が’ゼロであれば、それはOnCalculate()ファンクションのインジケーターのスタート以来最初の実行である。

OnCalculate()ファンクションの最初の実行では、計算を開始する最初のバーのインデックスを決定する必要がある。 その値はインジケーターの値の計算に必要なバーの数によって決定される(インデックス付けは左から右に行われる)。

インジケーターのラインの傾斜は2つのバーによって決定されるのでもう一つ前のバーを必要とする。price[]配列の重要なデータがスタートするバーのインデックスは、 begin 変数の値であり、バーの計算をstart=begin+1 番のバーから開始する。.

さらに、インジケーターの作業の間、計算をスタートするバーのインデックスはprev_calculated 変数の値によって決定され- この変数は既に処理されたバーの数も含んでいる。こうして、計算が実行された最後のバーのインデックスを見つけるためには prev_calculatedから1引かなくてはならない。

既に処理された最後のバーはバーを形成するために再度計算に取り込まれる。計算の限界は価格配列の大きさによって決定され、それは rates_total 変数である。計算が行われた最後のバーのインデックス rates_total-1 に等しい(それは配列の大きさより1少ない)。

このインジケーターはもう一つのインジケーターのデータを使うので、このデータを得なければならない。もう一つのインジケーターのデータは CopyBuffer() ファンクションを使って得ることができる。このファンクションの第1パラメーターにはデータをコピーするべきインジケーターのハンドルを指定しなければならず (handle は第4ステージで得られる); 第2の パラメーター にはコピーされるバッファーのインデックスを指定する(必要な値はコピーされるインジケーターのプロパティの"Color" タブから得られ、計数は0からスタートする)。

第3のパラメーターはコピーが始まるバーのインデックスで、この場合インデックス付けは右から左に行われ右端のバーはゼロである。第3のパラメーターはカスタムインジケーターの名前であり、この場合それはTSIs である。第4のパラメーターはコピーすべき配列要素の数である。計算に取り込まれるバーの範囲を決定するのに従ってコピーされる要素の数を注意深く決めなければならない。それはインジケーターの性能に影響する。インジケーターの計算をスタートすべきバーのインデックスは前もって決定されているので、コピーされる要素の数はrates_total-startと計算される。処理プロセスの間、インジケーターが形成するバーにだけ計算されると、配列の1要素のみがコピーされる。

もしCopyBuffer() ファンクションが情報のコピーをしようとして -1 を戻すと、それはデータがコピーできないことを意味し、計算を行うべきポイントは何もないことを意味する。 このエラーは処置されなければならない。CopyBuffer() の開始時にbool タイプのスタティックな変数を宣言しそれを"error"と名付ける。もしインジケーターの計算処理の間にエラーが起こると、特にインジケーターデータのコピーのエラーの場合、この変数に True の値を割り当てOnCalculate() ファンクションの実行を終了する。

もしこのエラーの値が 前回のOnCalculate() ファンクションの実行の間にエラーがあると言っている場合には、次の一目盛ではインジケーター全体の再計算を行う。こうして、OnCalculate() ファンクションの始まりは次のようなものになる:

static bool error=true; 
   int start;
   if(prev_calculated==0) // First execution of the OnCalculate() function after the indicator start
     {
      error=true; // Set the value True for the indicator to be calculated for all bars
     }
   if(error) // If value of error=true, then it is the first execution of the function after 
             // the start of the indicator, or there was an error of copying of data at the previous start
     {
      start=begin+1;
      error=false;
     }
   else
     {
      start=prev_calculated-1;
     }

   if(CopyBuffer(Handle,0,0,rates_total-start,TsiBuffer)==-1) // Copying data of main line of the indicator
     {
      error=true; // Failed to copy data, set the value True for the error variable to recalculate the whole 
                 // indicator at the next call of OnCalculate()
      return(0);  // End working of the function
     }
   if(CopyBuffer(Handle,1,0,rates_total-start,TsiSignalBuffer)==-1) // Copy data of the signal line of the indicator
     {
      error=true; // Failed to copy data, set the value true for the error variable to recalculate the whole
                 // indicator at the next call of the OnCalculate() function
      return(0);  // End working of the function
     }

インジケーターの計算の限界が決定され、計算のloop をこのバーの範囲内とする。

for(int i=start;i<rates_total;i++)
  {

  }

インジケーターの値を計算する (そのコードは今作成されたループの中にある)。

TsiCDBuffer[i]=TsiBuffer[i]-TsiSignalBuffer[i];

ここで最も興味深いこと - バッファーを色付けする。この前のステージ1 では colored histogram をインジケーターバッファーに用いた。このタイプの描画には2つのバッファーを必要とする - 1つはインジケーターの値のためで、もう1つは色のためである。色のリスト indicator_color1 プロパティに設定されている。0の値がバッファーの要素に入っていると、インジケーターは緑色で表示され、1の値が入っていると、インジケーターは赤色で表示される (リストの indicator_color1中の位置に従って;番号はゼロから始まる)。

インジケーターの値が2つの隣り合うバーで等しいという状況を避けることは不可能であり、この場合には、インジケーターは前の色で表示される (上向きと下向きの動きに対して2つに色しかないからである)。従って、計算の開始時には、 前のバーのTsiCDColorsバッファーの値をコピーする:

TsiCDColors[i]=TsiCDColors[i-1];

上向きに動くときにはインジケーターの色は Green 色である:

if(TsiCDBuffer[i]>TsiCDBuffer[i-1])TsiCDColors[i]=0;

下向きに動くときにインジケーターはRed 色である:

if(TsiCDBuffer[i]<TsiCDBuffer[i-1])TsiCDColors[i]=1;

このようにしてインジケーターの作業のほぼ最後まで到達する; インジケーター描画の始まりを決定することが残っている。

7. インジケーターでの作業を終了する

begin変数がインジケーター の計算を決定するのに使われるにも関わらずそれは必ずしもインジケーター データがbegin 変数と同定されるバーからスタートすることを意味しない。カスタムなインジケーターのアルゴリズムが知られていない場合には、インジケーターの計算に必要なバーの数を決定することはできない。これはこのステージが飛ばされることがあったりする理由であり、あるいは経験をベースに値を決定することも可能である。しかし、TSIs インジケーターのアルゴリズムを知っているので、インジケーターの始まりをはっきり検出できる。PlotIndexSetInteger() ファンクションを PLOT_DRAW_BEGIN識別子をOnInit()ファンクションとして呼び出しを加える。

PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,r+s+sp);

TSIsインジケーターは値を小数点以下2桁まで正確に表示し、 IndicatorSetInteger() ファンクションを INDICATOR_DIGITS 識別子で同じ精度に設定する。

IndicatorSetInteger(INDICATOR_DIGITS,2);

インジケーターをコンパイルし それをチャートに添付する (図 8)。


図 8. インジケーターTSIsCDiCust.


インジケーターを IndicatorCreate() ファンクションを用いて作成する

インジケーターの作成を IndicatorCreate()ファンクションを使用して作成するのはそれを iCustom() ファンクションを使って作成するのとステップ4(IndicatorCreate() ファンクションが iCustom()の変わりに使われる)を除いて同じである。

1. TSIsCDiCust インジケーター のコピーをTSIsCDiCreate の名前の下に保存する。

2. コードの中から iCustom() ファンクションが呼び出されている所を見つける。 これ以降 IndicatorCreate() ファンクションが iCustom()の代わりに実行される。iCustom()におけると同様に、ファンクションIndicatorCreate() の最初の2つのパラメーター がシンボルと時間枠を決定しそれがインジケーターの計算に使われる。第3のパラメーターはインジケーターのタイプの識別子であり、カスタムのインジケーターではそれは IND_CUSTOMである。作成するインジケーターのパラメーターは構造MqlParamの配列を用いてファンクションに渡される。

MqlParam は4つの変数を含んでいる - そのうち3つは値に使われる異なったタイプの変数であり:double_value、 integer_value と string_valueである; そしてもう一つはtypeであり、使われる変数のタイプを決定する。 TSIs インジケーターは4つの外部パラメーターを持つ。. この インジケーターはカスタムのものであるため、配列の第1の要素はカスタムインジケーターの名前であり、従って、配列は5つの要素を含んでいる。構造の配列を宣言する (コードは iCustom() が呼ばれた場所にある):

MqlParam Params[5];

配列に値を埋める:

Params[0].type=TYPE_STRING;
   Params[0].string_value="TSIs"; // Specify name of the called custom indicator in the first parameter
   
   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() ファンクションに渡された最初の3つのパラメータは 既に扱った。パラメーターの配列の大きさは第4パラメーターを通じて渡され、最後のものはパラメーター 自身の配列である。:

Handle=IndicatorCreate(_Symbol,PERIOD_CURRENT,IND_CUSTOM,5,Params);

後は "Compile" ボタンを押し、そしてクライアント側ターミナルでインジケータをチェックする。


結論

簡単に他のインジケーターをベースにしてカスタムなインジケーターを作成するときに注意すべき主なアイデアを繰り返そう。

インジケーターを改良するときには、バッファーの数と、描画されるバッファーの数を正しく指定しなければならない (indicator_buffers, indicator_plots properties ); また新しいバッファーのプロパティを決定しなければならない (the indicator_label, indicator_type, indicator_color, indicator_style, indicator_width プロパティ)。新しいバッファーのためにSetIndexBufer()ファンクションを呼び出すときには第3 パラメーターの値を正しく指定しなければならない (INDICATOR_DATA あるいは INDICATOR_CALCULATIONS); そして第1パラメーターの値を正しく指定しなければならない(バッファーのインデックス); 必要ならバッファーの再インデックス付けを実行する。

もう一つのカスタムインジケーターを用いて新しいインジケーターを作成するときには、正しくパラメーターを iCustom()ファンクションに渡さなければならない;そして IndicatorCreate() ファンクションを用いるときにはstructure of parameters を埋め無ければならない。SetIndexBuffer() ファンクションを呼び出すときにパラメーターを正しく指定したかをよく見る必要があり; そして最も重要なことは新しいバッファーに SetIndexBuffer() ファンクションの呼び出しを実行することを忘れないことである。

インジケーターに取り組んでいるときは常にバーの計算範囲の決定に注意を払い、 prev_calculated, rates_total, begin 変数を用いるべきである。MetaEditorはプログラミング中に現れる他のエラーに対処するのを助けてくれる。 (コンパイル中に現れるエラーメッセージ"Errors" タブに表示される)。

MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/127

添付されたファイル |
tsis.mq5 (7.59 KB)
tsiscdicreate.mq5 (3.46 KB)
tsiscdicust.mq5 (3.11 KB)
トレードシステムの評価 - 参入、退出と取引における一般の有効性 トレードシステムの評価 - 参入、退出と取引における一般の有効性
トレードシステムの有効性と利益性を決定できる多数の尺度がある。しかし、トレーダーは常にどのシステムでも試したいと考えている。この記事はどのようにして有効性の尺度に基づいた統計が MetaTrader 5 のプラットフォームに使えるかを教えるものである。 これは取引による統計の解釈を、S.V.Bulashev(ブラシェフ)による著作"Statistika dlya traderov"(トレーダーのための統計) の記述に矛盾しないものに変換するクラスを含んでいる。また最適化のためのカスタムファンクションの例も含んでいる。
独自のトレーリングストップ注文を作成する方法 独自のトレーリングストップ注文を作成する方法
トレーダーの基本原則 - 利得を増やし、損失を削る!この論説では基本技術の一つ、この原則に従うことを可能にする - 保護的停止レベル (ストップ・ロスレベル) をポジションの利得が増大した時点で動かす、すなわちトレーリングストップレベルを考察する。ここではSAR と NRTR インジケーターに基づいてトレーリングストップをするためのクラスを作成する手続きをステップを追って示す。誰でもこのトレーリングストップをそのエキスパートに挿入し、あるいは独立にそれをそのアカウントのポジションを制御するために使用することができる。
エキスパートアドバイザ作成の特徴 エキスパートアドバイザ作成の特徴
MetaTrader 4取引システムでのエキスパートアドバイザ作成の特徴
トレードロボットのプロトタイプ トレードロボットのプロトタイプ
この論説ではトレーディングシステムのアルゴリズムと要素の作成の原理を要約しシステム化する。この論説はエキスパートアルゴリズムの設計について考察する。トレーディングシステムCExpertAdvisor クラスのある例について考察する。これはトレーディングシステムを素早く簡単に開発するのに使える。