MQL4プログラミング 第3回 インジケーターを作成してみよう(処理の関数化)
今回は前回と同じ動作をするプログラムを将来的に応用が利く構造に修正していきます。
今回の大事なポイントは処理の関数化です。ある一定の処理をまとめて1つの関数にすれば見通しの良いプログラムになります。
では、早速今回のプログラムを見て頂きます。
// prg-0003.mq4
#property copyright "Copyright 2024, smile-invest-blog.com"
#property link "https://www.smile-invest-blog.com/prg-0003/"
#property strict
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Yellow
#property indicator_color2 Red
#property indicator_width1 2
#property indicator_width2 2
double Log1Up[]; // Highサイン用バッファ
double Log1Down[]; // Low サイン用バッファ
int realBars = 0;
int shortMaPeriod = 10; // 短期移動平均線の期間
int longMaPeriod = 30; // 長期移動平均線の期間
//+------------------------------------------------------------------+
//| initialization function
//+------------------------------------------------------------------+
int init() {
//---- indicators
SetIndexStyle(0, DRAW_ARROW, EMPTY);
SetIndexArrow(0, 233);
SetIndexBuffer(0, Log1Up);
SetIndexStyle(1, DRAW_ARROW, EMPTY);
SetIndexArrow(1, 234);
SetIndexBuffer(1, Log1Down);
//----
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| deinitialization function
//+------------------------------------------------------------------+
int deinit() {
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| start function
//+------------------------------------------------------------------+
int start() {
bool ret_hantei; // hantei関数の結果格納用
int counted_bars=IndicatorCounted();
int limit = Bars - counted_bars;
for(int i = limit - 1; i >= 0; i--) {
if(i == 0) {
Log1Down[i] = EMPTY_VALUE;
Log1Up[i] = EMPTY_VALUE;
ret_hantei = hantei(i); // 上下サイン表示の判定を関数化した
if (ret_hantei == true) { // hantei関数の結果がtrueの時
if (realBars < Bars) { // 1本のローソク足で1回だけ実行するための条件
realBars = Bars; // realBarsをBarsにする事で同じローソク足では1回だけ実行する
if (Log1Up[i] != EMPTY_VALUE) { // hantei関数内で上サイン表示と判定された
Alert(Symbol(), " *** High ***");
}
else if (Log1Down[i] != EMPTY_VALUE) { // hantei関数内で下サイン表示と判定された
Alert(Symbol(), " *** Low ***");
}
}
}
}
}
return(0);
}
//+------------------------------------------------------------------+
//| エントリーの条件判定関数
//| int i メイン関数からのiの値
//+------------------------------------------------------------------+
bool hantei(int i) {
double shortMaPrevious, longMaPrevious;
double shortMaCurrent, longMaCurrent;
// 前回の移動平均値を取得
shortMaPrevious = iMA(NULL, 0, shortMaPeriod, 0, MODE_SMA, PRICE_CLOSE, i+1);
longMaPrevious = iMA(NULL, 0, longMaPeriod, 0, MODE_SMA, PRICE_CLOSE, i+1);
// 現在の移動平均値を取得
shortMaCurrent = iMA(NULL, 0, shortMaPeriod, 0, MODE_SMA, PRICE_CLOSE, i);
longMaCurrent = iMA(NULL, 0, longMaPeriod, 0, MODE_SMA, PRICE_CLOSE, i);
// 移動平均線のクロスを確認
if (shortMaPrevious < longMaPrevious && shortMaCurrent > longMaCurrent) {
// ゴールデンクロス → Highサイン
Log1Up[i] = Low[i] - 10 * Point;
return true;
}
else if (shortMaPrevious > longMaPrevious && shortMaCurrent < longMaCurrent) {
// デッドクロス → Lowサイン
Log1Down[i] = High[i] + 10 * Point;
return true;
}
return false;
}
さて、前回のプログラムと比べて違いは見つけましたか?
では、今回のキモとなる処理の関数化について説明いたします。
処理の関数化
上記プログラムの54行目が処理の関数化をおこなった行です。
start()関数がかなりスッキリとした感じになりましたね。
そして新たに追加した76行目からの「bool hantei(int i)」についてです。
boolとはこのhantei関数自体がどんな戻り値(関数処理終了後に返す値)の種類を定義しています。boolとは「true(真)」、「false(偽)」のどちらかとなります。ちなみに「int i」の部分は引数と言いintつまり整数がhantei関数の引数として渡されます。
なのでゴールデンクロスの場合は92行目で、デッドクロスの場合は97行目でそれぞれ「true(真)」を返しています。他方なにも条件に該当しない場合は100行目で「false(偽)」を返しています。
今はまだhantei関数自体は単純な処理なのですが、いくつもの種類のインジケータの値を取得して複雑な条件を捉える場合などはstart()関数から分離しているほうが見通しが良くなりますね。今回のプログラムも動作確認済ですのでコピペしてコンパイルすると実際にチャートで見て頂けますので是非やってみてください。
次回はhantei関数内で判定条件を増やして少し複雑な処理をおこなってみたいと思います。