MT5 インディケータの作り方 その2

indicator

ハンドル の 利用
まず 手始め として 移動平均線 を 書い て み ましょ う。
移動平均線 は MT 5 に 標準 で 組み込ま れ て いる ので わざわざ 書く 必要 は ない の です が
MT 5 の プログラム が どの よう に なっ て いる かを 知る のに 手頃 な もの です ので、
あえて 車輪 の 再開発 を し ます。 ウィザード で 新しく インディケータ を 作成 し ます。
インディケータ 名 を「 MA 1 st」 として 説明 し ます。

property 部分

移動平均線 の パラメータ を 次 の よう に 決め ます。

・単純 移動平均線
・期間 は 20
・終値
を 適用 する 順番 に 説明 し ます

property copyright “Copyright 2020, Beleif Co., Ltd.”

ウィザード で 設定 し た 著者 名 です。

property link “https://belief-hf.com/”

ウィザード で 設定 し た リンク です。

property version “1. 00”

この プログラム の バージョン です。

#property indicator_ chart_ window
この インディケータ が チャート 上 に 描か れる こと を 表し ます

property indicator_ buffers 1

property indicator_ plots 1

この インディケータ で 使用 さ れる 配列 の 総数 と 描画 さ れる 配列 の 数 です。
ここ が MT 5 の 新しい 特徴 です。 計算 に 使わ れる けど、 描画 はさ れ ない 配列 なども 含め すべて の 数 を indicator_ buffers で 表し ます。
また、 描画 さ れる 数 は indicator_ plots で 表し ます。 今回 の 移動平均線 は、 計算 さ れる 配列 と 描画 さ れる 配列 が 1 つ なので 両方 1 と し ます。

property indicator_ type 1 DRAW_ LINE

インディケータ の 種類 を 表し ます( 省略 不可)。 DRAW_ LINE は 線 を 描画 し ます。

property indicator_ color 1 clrDeepPink

インディケータ の 色 を 表し ます( 省略 可)。 省略 する と デフォルト の Silver になり ます。

property indicator_ width 1 2 インディケータ の 太 さを 表し ます( 省略 可)。 省略 する と デフォルト の 1 になり ます。

property indicator_ style 1 STYLE_ DOT インディケータ の スタイル を 表し ます( 省略 可)。

省略 する と デフォルト の STYLE_ SOLID( 実線) になり ます。
なお、 indicator_ width が 1 以外 だ と、 ここ は 何 を 指定 し て STYLE_ SOLID が 強制的 に 描画 さ れ ます。
ここ は インディケータ の 数 を 指定 する 必要 が あり ます。
今回 は 1 本 だけなので indicator_ type 1 となり まし た が、 2 本 あれ ば indicator_ type 1、 indicator_ type 2 の よう に 指定 し ます。

input ENUM_ MA_ METHOD
InpMAMethod = MODE_ SMA;
ここ からは パラメータ の 指定 です。
input という のは、 インディケータ 設定 時 や 設定 後 に 変更 できる もの です。
MODE_ SMA は 単純 移動平均線 という こと です。
input ENUM_ APPLIED_ PRICE InpMAApply = PRICE_ CLOSE;
終値 を 適用 する
input int InpMaPeriod = 20;
移動平均 の 期間 が 20 で ある という こと です。
double MABuffer[]; 移動平均線 の データ を 格納 する 配列 です。
int hMA; 移動平均線 の ハンドル です。
ハンドル について は 後述 し ます。
input で 宣言 し た 変数 は 下図 の ところ で 変更 が でき ます。

もし、 変更 し たく ない パラメータ を 指定 する 場合 は input を 外し ます。
たとえ は InpMAMethod から input を 外し て、 この よう に する と。

ENUM_ MA_ METHOD InpMAMethod = MODE_ SMA;

この よう に 見え なく なり ます。
変数 名 は この まま でも「 値」 の 箇所 を 見る と 意味 が わから なく も ない です が、
もっと わかり やすく する ため には、 変数 の ところ に コメント を 入れ ます。
もう一度 input を 戻し て、 今度 は 移動平均線 種類 の ところ だけ コメント を 入れ て み ます

input ENUM_ MA_ METHOD
InpMAMethod = MODE_ SMA;// 移動平均線 の 種類
input ENUM_ APPLIED_ PRICE InpMAApply = PRICE_ CLOSE;
input int InpMaPeriod = 20;

この よう に わかり やすく なり ます ね。 全て に コメント を 入れ て 次 の よう に わかり やすく し ましょ う。
input の 部分 に 限ら ず、 コメント は 後 から プログラム を 見直す とき の 助け になり ます ので、 どんどん 入れ て ください。

input の 変数 は ウィザード の この 段階 でも 作れる の です が、 コメント を 入れ られ ない のと、
ENUM_ MA_ METHOD などの 型 は つくれ ない ので、 後 から 手動 で 入れれ ば いい と 思っ て い ます ので、
今後 も ウィザード で input の 値 は 設定 し ませ ん。 プログラム に 戻り ます。
ENUM_ MA_ METHOD という のは 移動平均線 の 平滑 化 の 方法 を あらわす 定数 です。
この よう に 指定 する こと によって、 ユーザー は 次 の よう に プルダウン で 選べる よう になり ます。

Simple = MODE_ SMA・・・単純 移動平均
Exponential = MODE_ EMA・・・指数 移動平均
Smoothed = MODE_ SMMA・・・平滑 平均
Linear weighted = MODE_ LWMA・・・線形 加重 移動平均

ENUM_ APPLIED_ PRICE は、 価格 定数 で やはり プルダウン で 選べる よう になり ます。
Close price = PRICE_ CLOSE・・・終値
Open Price = PRICE_ OPEN・・・始値
High price = PRICE_ HIGH・・・期間 の 高値
Low price = PRICE_ LOW・・・期間 の 安値
Median price = PRICE_ MEDIAN・・・中間 価格( 高 + 低) ÷ 2
Typical price = PRICE_ TYPICAL・・・典型的 価格( 高 + 低 + 終) ÷ 3
Weighted price = PRICE_ WEIGHTED・・・平均 価格( 高 + 低 + 終 + 終) ÷ 4

プルダウン で 選べる よう に し て おけ ば、 予期 し ない 入力( 期間 を マイナス で 入力 する など) をさ れる こと も ない ので 安心 です。
最後 の 期間 だけは 実際 の 数字 を 入れ て もらわ ない と いけ ない ので、 この 部分 は エラー 処理 を 考える 必要 が あり ます ね。

OnInit 関数

インディケータ が 適用 さ れ た とき に 呼び出さ れる 初期化 関数 です。

if( InpMaPeriod < 1)

{ Print(” Error Invalid InpMaPeriod value”); return( INIT_ FAILED); }

移動平均 の 期間 に 不適切 な 数値( マイナス の 値 など) が 入力 さ れ た とき に、 エラー を 返す 処理 です。
Print という のは エキスパート タブ に メッセージ を 表示 さ せる 命令 です。 例えば 期間 を 0 として 適用 する と、

この よう に 表示 さ れ て、 移動平均線 も 表示 さ れ ませ ん。 もし、 この エラー 処理 を 省い て、 同じ よう に 期間 を 0 と し て み ます と・・・

違う エラーメッセージ がで まし た。
今回 は ハンドル を 使っ て、 MT 5 内 の 移動平均 を 呼び出し て いる ので、 システム から エラー が ださ れ て いる の です。
もし、 プログラム 内 で すべて の 計算 を し て いる ので あれ ば、 ここ の エラー 処理 が ない と、 何 も メッセージ が 表示 さ れ ませ ん。
そして インディケータ も 表示 さ れ ない 状態 となり ます。
ハンドル を 使っ て い て、 この よう な 場合 に どんな 処理 が なさ れる か 理解 し て いる ので あれ ば、 ここ は 省略 し ても いい かも しれ ませ ん。
エラーメッセージ は、 どんな エラー がで た のか、 わかり やすい もの を 入れ ましょ う。
今後、 大規模 な プログラム や 大量 の インディケータ を 作る 場合、 エラーコード 表 を つくる のも いい かも しれ ませ ん。

SetIndexBuffer( 0, MABuffer, INDICATOR_ DATA);

指標 バッファ と 配列( 外部 変数 で 宣言 し た 配列) を 結びつけ ます。
順番 は 0 から 始まり ます。 0 番 という インデックス を MABuffer という 配列 に つける という のが、 第一 パラメータ、 第二 パラメータ の 意味 する ところ です。

第三 パラメータ の INDICATOR_ DATA は、 指標 の 値 を 表す( プロット さ れる) 配列 で ある という 意味 です。
第三 パラメータ の 他 の 値 について は 後 の 章 で 説明 し ます。
今回 は 一つ しか 配列 が ない ので 0 番 の 一つ だけ 結びつけ ます。
IndicatorSetString( INDICATOR_ SHORTNAME,” はじめて の 移動平均); インディケータ の 表示 名 です。
これ を 設定 し て 移動平均線 の ライン の 上 に マウス カーソル を もっ て くる と

この よう に インディケータ 名 が 表示 さ れ ます。 また、 移動平均線 の ライン の 上 でで 右 クリック する と、

この よう に インディケータ 名 が 表示 さ れ ます。 インディケータ 名 は 全角 文字 でも 表示 さ れ ます が、
配布 する 場合 などは 文字 化け などを 考慮 し て 半角 文字 に し て おい た ほう が 無難 でしょ う。

PlotIndexSetString( 0, PLOT_ LABEL,” MA 1 st(“+ string( InpMaPeriod)+”)”);

データ ウィンドウ に 表示 さ れる 指標 の 名称。 20 期間 の 移動平均線 で ある こと を データ ウィンドウ
( 移動平均線 の 上 に マウス カーソル を 乗せ た とき) に わかり やすく する よう に、 この 値 を 指定 し ます。
なお、 省略 する と、 インディケータ 名 が そのまま 表示 さ れ ます。

hMA = iMA( NULL, 0, InpMaPeriod, 0, InpMAMethod, InpMAApply);

移動平均線 の ハンドル を 取得 し ます。 第一 パラメータ は 銘柄 名、 NULL に する と インディケータ が 適用 さ れ た 銘柄 になり ます。
第二 パラメータ は 時間 足、 0 に する と インディケータ が 適用 さ れ た 時間 足 になり ます。
第三 パラメータ は 移動平均 の 期間。 これ は input の ところ で 指定 し た 期間 を 入れ て い ます。
第四 パラメータ は 移動平均線 を どれ だけ シフト さ せる か です。 し ない ので 0 を 入れ て い ます。 第 五 パラメータ は 移動平均 の 種類 です。
これ も input の ところ で 指定 し た もの です。 第六 パラメータ は 適用 価格 で、 これ も input の ところ で 指定 し た もの です。
MT 4( mql 4) では、 iMA 関数 で 実際 の 数値( double 型) を 取得 し、 for ループ で 配列 に コピー を し て い た と 思い ます が、
MT 5( mql 5) では ハンドル( int 型) という 概念 を 用い ます。
具体的 な 使い方 は OnCalculate 関数 の ところ で 説明 し ます。

if( hMA == INVALID_ HANDLE) { Print(” Error INVALID_ HANDLE”);
return( INIT_ FAILED); }

ハンドル が 正しく 取得 でき なかっ た とき、 エラー を 表示 し ます。

OnCalculate 関数
OnCalculate 関数 は 新しい ティック が 受け取ら れ た とき、 つまり 価格 が 変化 し た とき に 呼び出さ れ ます。

if( BarsCalculated( hMA)< rates_ total) return( 0);
BarsCalculated 関数 は、 計算 さ れ た データ の 数 を 計算 し ます。
OnInit 関数 で ハンドル を 取得 し た とき、 計算 さ れ た バー の 数 が rates_ total つまり バー の 総数 と 一致 し ない とき に 0 で OnCalculate 関数 を 抜け ます。
めった に 起こる こと では あり ませ ん が、 OnInit 関数 で エラー に なら なかっ た とき、 この 時点 で 正しく 取得 でき て い ない と、
OnCalculate は ずっと 0 で 返り ます ので、 もう一度 インディケータ を 適用 し 直す 必要 が あり ます。

int to_ copy; to_ copy = rates_ total-prev_ calculated; if( to_ copy == 0) to_ copy ++;

配列 に コピー する バー の 数 を 指定 し ます。 何 も 考え ず に、 毎回 全て の バー を コピー し ても 間違っ た 数値 にはなり ませ ん が、 値 が 変化 し ない バー を
毎回 コピー する のは 無駄 です。 値 が 変化 する のは、 現在 のバー だけ です。 それ 以前 の バー は 一度 計算 し たら 二度と 計算 する 必要 は あり ませ ん。
rates_ total は チャート で 使用 可能 な バー の 総数 を 表し ます。
prev_ calculated は 以前 の OnCalculate() 呼び出し に 返さ れ た 値 になり ます。
ちょっと 先 に 80 行 目 を 見 ます と、 OnCalculate は 正しく 終了 し た 場合 rates_ total を 返す という こと になり ます。
そこ から prev_ calculated は 3 つ の 値 を とる こと が わかり ます。

(1) 0
(2) rates_ total と 同じ
(3) rates_ total-1 と 同じ
(1) インディケータ を 適用 し た 直後 は 何 も 計算 さ れ て い ませ ん から 0 で ある こと は 理解 し やすい でしょ う。
( 2) も 適用 さ れ て 一度 でも OnCalculate が 呼ば れれ ば、 その 戻り 値 が rates_ total なので、 これ も 理解 し やすい かと 思い ます。
では( 3) は どういう こと か? と いい ます と、

新しい バー が でき た 瞬間
という こと です。 例えば 1 時間 足 で 11: 59: 59 から 12: 00: 00 に なっ た 瞬間 に 一本 足 が 増え ます( rates_ total も 1 増える)。
しかし、 この 間 に 価格 の 変動 なけれ ば OnCalculate は 呼ば れ ませ ん ので 11: 59 分 台 の prev_ calculated は rates_ total と 同じ、 つまり rates_ total-1 と なる わけ です。
試し に、 OnCalculate 内 に

Print( rates_ total,”,”, prev_ calculated);

という 式 を 書い て、 1 分 足 などで それぞれ の 変化 を 試し て み て ください。

FX の 会社 や 時間 足、 通貨 によって 数字 は 変わり ます が、 変化 は この よう になり ます。
したがい まし て、
to_ copy = rates_ total-prev_ calculated; の to_ copy は rates_ total、 1、 0 の 値 になり ます。
0 です と、 コピー がさ れ ない という こと になり ます ので、 次 の if 文 で 0 の 場合 1 に する という 処理 を し て い ます。
一見 無駄 な こと を し て いる よう です が、 prev_ calculated の 性格 上 この よう になり ます。 なお、MT 5 に 最初 から 組み込ま れ て いる インディケータ を 見 ます
と いろいろ な 処理 の 方法 を し て いる こと が わかり ます。

if( CopyBuffer( hMA, 0, 0, to_ copy, MABuffer)<= 0) return( 0)

配列 に 値 を コピー し ます。 CopyBuffer が 正しく 終了 する と、 複製 さ れ た バー の 数 が 返さ れ、 失敗 する と-1 が 返さ れ ます。
失敗 し た とき に OnCalculate が 0 で 返り ます。
CopyBuffer( hMA, 0, 0, to_ copy, MABuffer); 第一 パラメータ は 指標 ハンドル です。
第二 パラメータ は 指標 バッファ の 番号 になり ます。 今回 は 移動平均線 なので、 指標 バッファ は 一つ だけ です ので 0 となり ます。
複数 の バッファ が ある もの について は 後 の 章 で 解説 し ます。
第三 パラメータ は 複製 さ れる 値 の 開始 位置 です。 第四 パラメータ は 複製 さ れる 数 です。
第 五 パラメータ は データ を 格納 する 配列 です。 第二 パラメータ の「 開始 位置」 という のは 指標 バッファ( ハンドル で 得 られ た 移動平均線 の データ) の
開始 位置 を 示し ます。 指標 バッファ に ある データ は 常に 現在 の 足 から 古い 足 に 向かっ て 数え られ ます。
です から、 hMA の ハンドル で 取得 し た 指標 バッファ の 現在 の 足 から to_ copy 分、 配列 MABuffer に コピー を する という のが CopyBuffer の 意味 になり ます。
ちょっと ややこしい 話 になり ます が、 MABuffer の インデックス は デフォルト では 古い 足 → 現在 の 足 で つけ られ て い ます。
この こと について は 後ほど ArraySetAsSeries 関数 の ところ で 説明 し ます。

OnDeinit 関数
OnDeinit 関数 は、 時間 足 を 変更 し たり、 パラメータ を 変更 し たり、 インディケータ を 外し た とき などの 後処理 で 呼ば れ ます。
OnDeinit は ウィザード では 生成 さ れ ない ので、 自分 で 書く 必要 が あり ます。

取得 し た ハンドル を 解放 し ます コンパイル し て エラー が ない こと を 確認 し て 実際 に チャート に 当てはめ て み ましょ う。

表示 さ れ ない、 コンパイル で エラー に なる など し たら もう一度 プログラム を 見直し て ください。
データ ウィンドウ を 表示 さ せ て み ます と 下図 よう に 表示 さ れ て いる かと 思わ れ ます。

ここ で、 MT 5 標準 の 移動平均線( Moving   Average) を 同じく 単純 移動平均線、 終値、 期間 20 で 表示 さ せ て み ます。
ぴったり 重なっ て、 一本 の 移動平均線 に なっ て いれ ば 成功 です。 データ ウィンドウ でも 同じ 数字 に なっ て い ます。
今回は、 MT 5 で 指標 を 取得 し、 どの よう に コピー する かの 原則 を 学び まし た。
移動平均線 以外 にも MT 5 では たくさん の 指標 が 用意 さ れ て い ます が、 同じ 要領 で ハンドル を 取り、 CopyBuffer で コピー する こと によって 値 を 取得 でき ます。
次回は、 ハンドル の 使い方 の 応用 について解説します。

最後に全体のコードですのでご参考ください。

MQL5リファレンス - MetaTrader 5 のためのアルゴリズムの/自動化されたトレーディング言語の使い方
MQL5リファレンス - MetaTrader 5 のためのアルゴリズムの/自動化されたトレーディング言語の使い方
ブログランキング・にほんブログ村へ

コメント

タイトルとURLをコピーしました