MQL5のフォーラムにて公開されている記事を参考にまとめていきます。
MQL5 FOR NEWBIES: GUIDE TO USING TECHNICAL INDICATORS IN EXPERT ADVISORS
標準テクニカル指標に組み込まれた関数の使い方を学ぶことが本稿の目的です。
標準テクニカル指標の関数を利用するための基礎知識
テクニカル指標の各関数が呼び出されると、指定された入力パラメータとともに作成されたオブジェクトのハンドルを作成します。オブジェクトとはテクニカル指標のインスタンス(実物、実体)のことで、ハンドルとは引換券みたいなものです。テクニカル指標の「バッファ」からデータを取得して、自分の計算に使用します。
double MA[]; // 指標となるiMAの配列
int MA_handle; // 指標となるiMAのハンドル
//+------------------------------------------------------------------+
//| EA:エキスパートアドバイザーの初期化関数
//+------------------------------------------------------------------+
int OnInit()
{
//--- 指標iMAの作成
MA_handle=iMA(NULL,0,21,0,MODE_EMA,PRICE_CLOSE);
return(0);
}
//+------------------------------------------------------------------+
//| EA:エキスパートアドバイザーのティック関数
//+------------------------------------------------------------------+
void OnTick()
{
//--- iMAの現在の値で配列MA[]を埋める
//--- 100個の要素をコピー
CopyBuffer(MA_handle,0,0,100,MA);
//--- 要素のインデックスを時系列としてセットする
ArraySetAsSeries(MA,true);
//---ここでは、MA[]のデータを自由に使うことができます。
if(MA[0]>MA[1])
{
//--- いくつかの操作
}
}
指標のハンドルは、関数OnInit()の中で作成する必要があります。
- 要素のインデックスを時系列として使用します。形成途中の現在のバーは常にインデックス[0]を持ち、インデックス[0]の前のバーはインデックス[1]となります。
- インデックスを設定する理由は、アルゴリズムの利便性と最適な実装です。
- 通常、指標は実行中にパラメータを変更しないので、起動時に一度だけ呼び出されるOnInit()関数内で指標を作成した方が効率がよいです。
プログラム講座
- ポインタを利用したオブジェクト作成は初期化関数OnInit()で宣言されます。初期化関数OnInit()に、ポインタの有効性をチェックする機能を書き込みます。ポインタが作成されていない場合、標準定数INVALID_HANDLE = -1を返します。
- 指標からデータを取得する際には、その値を指標の「バッファ」にコピーし、計算に使用します。コピーに失敗した場合、トレーディングシステムは間違ったトレードシグナルを生成する可能性がありますので、コピーされた要素の数をすぐに確認できる機能を提供しています。エラーが発生した場合、コピーされた要素の数は-1になります。
//---- 指標のための配列
double MA[]; // 指標となるiMAの配列
//---- 指標用のハンドル
int MA_handle; // 指標となるiMAのハンドル
//+------------------------------------------------------------------+
//| EA:エキスパートアドバイザーの初期化関数
//+------------------------------------------------------------------+
int OnInit()
{
//--- 指標iMAの作成
MA_handle=iMA(NULL,0,21,0,MODE_EMA,PRICE_CLOSE);
//--- オブジェクトの作成時にエラーがあった場合に報告する
if(MA_handle<0)
{
Print("iMAの作成に失敗しました。MA_handle=",INVALID_HANDLE);
Print("ランタイムエラー = ",GetLastError());
//--- プログラムの強制終了
return(-1);
}
return(0);
}
//+------------------------------------------------------------------+
//| EA:エキスパートアドバイザーのティック関数
//+------------------------------------------------------------------+
void OnTick()
{
//--- iMAの現在の値で配列MA[]を埋める
//--- 100個の要素をコピー
//--- エラーがあった場合は、プログラムの実行を終了します。
if(CopyBuffer(MA_handle,0,0,100,MA)<=0) return;
//--- 配列MA[]のインデックスを時系列にする
ArraySetAsSeries(MA,true);
//--- ここでは、MA[]のデータを自由に使うことができます。
if(MA[0]>MA[1])
{
//--- いくつかの操作
}
}
インジケータの値を配列にコピーする手順を少し改善したいと思います。コードを少し変えるだけで、安全性と信頼性が高まります。
//+------------------------------------------------------------------------------+
//| 指標の値をコピーし,要素は入力パラメータ asSeries の値に応じてインデックス化されます
//+------------------------------------------------------------------------------+
bool CopyBufferAsSeries(
int handle, // 指標のハンドル
int bufer, // バッファのインデックス
int start, // インデックスのスタート
int number, // コピーする要素数
bool asSeries, // 真であれば、要素は時系列としてインデックス化
double &M[] // ターゲットとなる配列
)
{
//--- 指標の現在の値で配列Mを埋めていきます
if(CopyBuffer(handle,bufer,start,number,M)<=0) return(false);
//--- asSeriesがtrueの場合は、timeseriesとしてインデックス化されます
//--- asSeriesがfalseの場合は、defaultとしてインデックス化されます
ArraySetAsSeries(M,asSeries);
//---
return(true);
}
上記の関数CopyBufferAsSeriesは、別途インクルードファイルとしてGetIndicatorBuffers.mqhというファイルで保存します。CopyBufferAsSeriesは汎用性の高い関数なので、毎回この部分を追加するのは冗長だからです。MQL5\Include\というフォルダにファイルを配置します。を追加する必要があります。
#include <GetIndicatorBuffers.mqh>を冒頭に追加して、CopyBuffer関数をCopyBufferAsSeries関数に置き換えます。
#include <GetIndicatorBuffers.mqh>
//---- 指標のための配列
double MA[]; // 指標となるiMAの配列
//---- 指標用のハンドル
int MA_handle; // 指標となるiMAのハンドル
//+------------------------------------------------------------------+
//| EA:エキスパートアドバイザーの初期化関数
//+------------------------------------------------------------------+
int OnInit() {
//--- 指標iMAの作成
MA_handle=iMA(NULL,0,21,0,MODE_EMA,PRICE_CLOSE);
//--- オブジェクトの作成時にエラーがあった場合に報告する
if(MA_handle<0) {
Print("iMAの作成に失敗しました。ランタイムエラー = ",GetLastError());
//--- プログラムの強制終了
return(-1);
}
return(0);
}
//+------------------------------------------------------------------+
//| EA:エキスパートアドバイザーのティック関数
//+------------------------------------------------------------------+
void OnTick() {
//--- iMAの現在の値で配列MA[]を埋める
//--- 100個の要素をコピー
//--- エラーがあった場合は、プログラムの実行を終了します。
if(!CopyBufferAsSeries(MA_handle,0,0,100,true,MA)) return;
//--- ここでは、MA[]のデータを自由に使うことができます。
if(MA[0]>MA[1])
{
//--- いくつかの操作
}
}
マルチバッファ指標の特徴
例えば、iAlligatorという指標は、3つの指標バッファを持っています。
- 0番目のバッファ – GATORJAW_LINE
- 1番目のバッファ – GATORTEETH_LINE
- 2番目のバッファ – GATORLIPS_LINE
指標バッファからのデータ受信を1回の呼び出しで済ますため、インクルードファイル(GetIndicatorBuffers.mqh)に以下の関数を記載します。
//+------------------------------------------------------------------------------+
//| この関数は,Alligator指標の値を3つの配列Jaws[]、Teeth[]、Lips[]にコピーします。要素は 時系列としてインデックス化されます
//+------------------------------------------------------------------------------
+bool GetAlligatorBuffers(int Alligator_handle,
int start,
int number,
double &Jaws[],
double &Teeth[],
double &Lips[],
bool asSeries=true
)
{
//--- 配列JawsにGATORJAW_LINEの現在の値を入力します。
if(!CopyBufferAsSeries(Alligator_handle,0,start,number,asSeries,Jaws)) return(false);
//--- 配列TeethにGATORTEETH_LINEの現在の値を入力します。
if(!CopyBufferAsSeries(Alligator_handle,1,start,number,asSeries,Teeth)) return(false);
//--- 配列LipsにGATORLIPS_LINEの現在のの値を入力します。
if(!CopyBufferAsSeries(Alligator_handle,2,start,number,asSeries,Lips)) return(false);
//---
return(true);
}
EA:エキスパートアドバイザーでの記載にてiAlligatorという指標を使う場合は、CopyBufferAsSeries関数を使う代わりにGetAlligatorBuffers関数を使います。
あとは、基本的には配列とハンドルの宣言と、CopyBufferAsSeries関数を変えるだけで多くの標準指標を使うことができます。
#include <GetIndicatorBuffers.mqh>
//---- 指標のための配列
double ●●;
//---- 指標用のハンドル
int ●●;
//+------------------------------------------------------------------+
//| EA:エキスパートアドバイザーの初期化関数
//+------------------------------------------------------------------+
int OnInit()
{
//--- 指標の作成
●●=●●(NULL,0,21,0,MODE_EMA,PRICE_CLOSE);
//--- オブジェクトの作成時にエラーがあった場合に報告する
if(●●<0)
{
Print("●●の作成に失敗しました。ランタイムエラー = ",GetLastError());
//--- プログラムの強制終了
return(-1);
}
return(0);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
if(!CopyBufferAsSeries(●●,0,0,100,true,●●)) return;
}
関数早見表(サンプル)
|
コメントを残す