【徹底解説】MQL4ボリンジャーバンドのサインツールの作り方!FXやバイナリーを攻略

サインツール

FXやバイナリーオプション攻略に使えるボリンジャーバンドのサインツールの作り方を徹底解説しています。紹介しているサインツールでは、±3σにタッチしたらサインが表示されアラートが発生します。

【ボリンジャーバンド】サインツールのコードを紹介

ボリンジャーバンドのサインツール

今回紹介するコードは以下の特徴があります。

コードの特徴
  • ±2σのラインを表示
  • ±3σのラインを表示
  • ±3σのラインに終値がタッチしたら矢印を表示
  • 矢印が表示される際にアラートが発生

コードはコピーしてそのまま使う事が出来ます。


#property indicator_chart_window
#property indicator_buffers 7
#property indicator_color1 Red
#property indicator_color2 Blue
#property indicator_color3 Green
#property indicator_color4 Orange
#property indicator_color5 Orange
#property indicator_color6 Magenta
#property indicator_color7 Magenta

double BuyArrowBuffer[];
double SellArrowBuffer[];
double MiddleBand2[];
double UpperBand2[];
double LowerBand2[];
double UpperBand3[];
double LowerBand3[];

extern int BB_Period = 20;
extern double BB_Deviation2 = 2;
extern double BB_Deviation3 = 3;

// 基本のオフセット割合
extern double OffsetRatio = 0.1;

// 最低オフセット(ポイント)
extern int MinOffsetPoints = 20;

// -------- 関数:時間足ごとのOffsetRatioを決める --------
double GetOffsetRatio() {
    switch (Period()) {
        case PERIOD_M1:   return 0.5;
        case PERIOD_M5:   return 0.5;
        case PERIOD_M15:  return 0.5;
        case PERIOD_H1:   return 0.5;
        case PERIOD_H4:   return 0.5;
        case PERIOD_D1:   return 1.0;
        default:          return OffsetRatio;  // パラメータのデフォルト値
    }
}

int OnInit() {
    SetIndexBuffer(0, SellArrowBuffer);
    SetIndexStyle(0, DRAW_ARROW, EMPTY, 1);
    SetIndexArrow(0, 234);

    SetIndexBuffer(1, BuyArrowBuffer);
    SetIndexStyle(1, DRAW_ARROW, EMPTY, 1);
    SetIndexArrow(1, 233);

    SetIndexBuffer(2, MiddleBand2);
    SetIndexStyle(2, DRAW_LINE);
    SetIndexLabel(2, "Middle Band 2σ");

    SetIndexBuffer(3, UpperBand2);
    SetIndexStyle(3, DRAW_LINE);
    SetIndexLabel(3, "Upper Band 2σ");

    SetIndexBuffer(4, LowerBand2);
    SetIndexStyle(4, DRAW_LINE);
    SetIndexLabel(4, "Lower Band 2σ");

    SetIndexBuffer(5, UpperBand3);
    SetIndexStyle(5, DRAW_LINE);
    SetIndexLabel(5, "Upper Band 3σ");

    SetIndexBuffer(6, LowerBand3);
    SetIndexStyle(6, DRAW_LINE);
    SetIndexLabel(6, "Lower Band 3σ");

    return(INIT_SUCCEEDED);
}

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[]) {

    int limit = rates_total - prev_calculated;
    if (prev_calculated == 0)
        limit = rates_total - 1;

    bool isNewSellSignal = false;
    bool isNewBuySignal  = false;

    double ratio = GetOffsetRatio();
    double minOffset = Point * MinOffsetPoints;

    for (int i = limit; i >= 0; i--) {
        double middleBB2 = iBands(NULL, 0, BB_Period, BB_Deviation2, 0, PRICE_CLOSE, MODE_MAIN, i);
        double upperBB2  = iBands(NULL, 0, BB_Period, BB_Deviation2, 0, PRICE_CLOSE, MODE_UPPER, i);
        double lowerBB2  = iBands(NULL, 0, BB_Period, BB_Deviation2, 0, PRICE_CLOSE, MODE_LOWER, i);

        double middleBB3 = iBands(NULL, 0, BB_Period, BB_Deviation3, 0, PRICE_CLOSE, MODE_MAIN, i);
        double upperBB3  = iBands(NULL, 0, BB_Period, BB_Deviation3, 0, PRICE_CLOSE, MODE_UPPER, i);
        double lowerBB3  = iBands(NULL, 0, BB_Period, BB_Deviation3, 0, PRICE_CLOSE, MODE_LOWER, i);

        MiddleBand2[i] = middleBB2;
        UpperBand2[i]  = upperBB2;
        LowerBand2[i]  = lowerBB2;

        UpperBand3[i]  = upperBB3;
        LowerBand3[i]  = lowerBB3;

        double candleRange = High[i] - Low[i];
        double dynamicOffset = candleRange * ratio;

        // 最低オフセットを確保
        if (dynamicOffset < minOffset) {
            dynamicOffset = minOffset;
        }

        if (Close[i] >= upperBB3) {
            SellArrowBuffer[i] = Close[i] + dynamicOffset;
            if (i == 1)
                isNewSellSignal = true;
        } else {
            SellArrowBuffer[i] = EMPTY_VALUE;
        }

        if (Close[i] <= lowerBB3) {
            BuyArrowBuffer[i] = Close[i] - dynamicOffset;
            if (i == 1)
                isNewBuySignal = true;
        } else {
            BuyArrowBuffer[i] = EMPTY_VALUE;
        }
    }

    // アラート処理
    string symbolName = Symbol();
    string alertMsg;

    if (isNewSellSignal) {
        alertMsg = "SELL Signal! Symbol: " + symbolName + " | Close >= 3σ Upper Band.";
        Alert(alertMsg);
        PlaySound("alert.wav");
    }

    if (isNewBuySignal) {
        alertMsg = "BUY Signal! Symbol: " + symbolName + " | Close <= 3σ Lower Band.";
        Alert(alertMsg);
        PlaySound("alert.wav");
    }

    return(rates_total);
}

コードを詳しく解説

サインツールのコードを詳しく解説しています。

今回はボリンジャーバンドを利用したサインツールになります。ボリンジャーバンドの基礎に関しては関連記事をご確認下さい。

バイナリーやFXをボリンジャーバンドで攻略!気になる使い方を紹介
バイナリーオプションやFXの攻略で役立つボリンジャーバンドの使い方を解説しています。さらに、相性の良いインジケーターやおすすめの設定方法も分かりやすく紹介しています。

#propertyの設定を解説

#propertyの
設定を詳しく解説

#property indicator_chart_window
#property indicator_buffers 7
#property indicator_color1 Red
#property indicator_color2 Blue
#property indicator_color3 Green
#property indicator_color4 Orange
#property indicator_color5 Orange
#property indicator_color6 Magenta
#property indicator_color7 Magenta

MQL4の「#property」とは、カスタムインジケーターの動作や見た目(表示場所や色など)を指定するための重要なコマンドです。

たとえば、インジケーターをメインチャートに表示するかサブウィンドウに表示するか、ラインやサインの色を何色にするかを簡単に設定できます。

#property 意味
#property indicator_chart_window メインチャートに表示する
#property indicator_buffers 7 バッファ数を7に設定する(サイン・ラインを格納する箱)
#property indicator_color1 Red 売り矢印を赤色で表示
#property indicator_color2 Blue 買い矢印を青色で表示
#property indicator_color3 Green 2σミドルバンドを緑色で表示
#property indicator_color4 Orange 2σアッパーバンドをオレンジで表示
#property indicator_color5 Orange 2σロワーバンドをオレンジで表示
#property indicator_color6 Magenta 3σアッパーバンドをマゼンタで表示
#property indicator_color7 Magenta 3σロワーバンドをマゼンタで表示

「アッパーバンド」・「ロワーバンド」に関しては、言いなれないかもしれませんが、ボリンジャーバンドの考案者、ジョン・ボリンジャー本人も「Upper Band(アッパーバンド)」という表現を使っています。

日本語に言い換えると「2σ上限バンド」や「2σ下限バンド」になります。

バッファの定義と役割

重要!
バッファを理解しよう

double BuyArrowBuffer[];
double SellArrowBuffer[];
double MiddleBand2[];
double UpperBand2[];
double LowerBand2[];
double UpperBand3[];
double LowerBand3[];

バッファは、チャートにサインやラインを表示するために、値を一時的に保存しておく「データの箱」のようなものです。

たとえば、売りサインや買いサインをチャートに表示するには、サインを表示したい「位置」をMetaTraderに伝える必要があります。

そこで使われるのが「バッファ」になります。

バッファにサインの位置を保存しておくことで、MetaTraderがその情報を読み取り、自動でチャートにサインを描画してくれます。

まずはバッファ用の配列を作成します。

バッファ名 役割
BuyArrowBuffer[] 買いサインの矢印の位置データを格納
SellArrowBuffer[] 売りサインの矢印の位置データを格納
MiddleBand2[] ボリンジャーバンド2σのミドルラインを格納
UpperBand2[] ボリンジャーバンド2σの上限ラインを格納
LowerBand2[] ボリンジャーバンド2σの下限ラインを格納
UpperBand3[] ボリンジャーバンド3σの上限ラインを格納

ここで作成した配列は、あくまでも配列でありバッファではありません。

例えば、OnInit()の中で「SetIndexBuffer(0, SellArrowBuffer);」と書くことで、SellArrowBuffer[]をMetaTraderがサイン表示用のバッファとして認識してくれます。

ボリンジャーバンドの値を設定する

ボリンジャーバンドの
値を設定する

ボリンジャーバンド設定用の値を3つ用意します。


extern int BB_Period = 20;
extern double BB_Deviation2 = 2;
extern double BB_Deviation3 = 3;

それぞれの意味合いは以下の様になります。

パラメーター名 意味
BB_Period ボリンジャーバンドの計算に使う移動平均の期間(ローソク足の本数)
BB_Deviation2 2σライン(アッパー・ロワー)の幅を決めるための標準偏差の倍率
BB_Deviation3 3σライン(アッパー・ロワー)の幅を決めるための標準偏差の倍率

これらの値は後程出てくる「iBands()」の関数で使用されます。

iBands()とは
iBands()で
値を取得する

iBands()はボリンジャーバンドの値を得る事が出来る関数で、今回のコードでは下の様に使用されています。

iBands(NULL, 0, BB_Period, BB_Deviation2, 0, PRICE_CLOSE, MODE_MAIN, i);

iBands()には8つの引数が用意されており、引数に値を入れる事でボリンジャーバンドの値を得る事が出来ます。

引数番号と項目 設定例 説明
① シンボル名 NULL 計算対象の通貨ペアや銘柄を指定します。NULLを使うと現在のチャートのシンボルになります。
② 時間足 0 使用する時間足を指定します。0は現在の時間足、PERIOD_H1は1時間足になります。
③ 期間 20 ボリンジャーバンドの計算に使用する移動平均の期間です。過去何本のローソク足を使うかを指定します。
④ 偏差 2 / 3 バンド幅を決めるための標準偏差(シグマ)値です。
⑤ シフト 0 インジケーターラインを右にずらす本数を指定します。通常は0(シフトなし)を使用します。
⑥ 適用価格 PRICE_CLOSE 計算に使う価格を選択します。終値(PRICE_CLOSE)や始値(PRICE_OPEN)などがあります。
⑦ バンドの種類 MODE_MAIN / MODE_UPPER / MODE_LOWER 取得したいバンドの種類を指定します。ミドル(中央)、アッパー(上)、ロワー(下)があります。
⑧ インデックス 0 / 1 / i どのローソク足のデータを取得するかを指定します。0は最新バー、1は1本前のバーを示します。

iBands(NULL, 0, BB_Period, BB_Deviation2, 0, PRICE_CLOSE, MODE_MAIN, i);の引数の意味を埋め込むと以下の様になります。

iBands(① シンボル名,② 時間足,③ 期間,④ 偏差,⑤ シフト,⑥ 適用価格,⑦ バンドの種類,⑧ インデックス)

矢印の位置をOffsetで調整する

矢印(サイン)が重なる
問題を解決

extern double OffsetRatio = 0.1;
extern int MinOffsetPoints = 20;

矢印(サイン)がローソク足に重なって見づらい場合は、矢印がローソク足に重ならないように、上下にオフセット(ずらす距離)を指定しています。

パラメーター名 意味
OffsetRatio 矢印(サイン)をローソク足からどれくらい離すかを、値幅に対する割合で決める設定で、ローソク足が大きいほど矢印も遠くに表示されます。
MinOffsetPoints 矢印(サイン)をずらすための最低オフセット値(ポイント単位)を指定します。ローソク足の値幅が小さすぎる場合でも、最低限このポイント数だけ矢印をずらすようになります。

矢印の位置をOffsetで調整する

矢印(サイン)が重なる
問題を解決

extern double OffsetRatio = 0.1;
extern int MinOffsetPoints = 20;

サインがローソク足に重なって見づらい場合は、矢印がローソク足に重ならないように、上下にオフセット(ずらす距離)を指定しています。

パラメーター名 意味
OffsetRatio 矢印サインをずらすための基本の割合を指定します。ローソク足の値幅に対する割合でオフセットを決めるため、ローソク足が大きいほど矢印のオフセット距離も大きくなります。
MinOffsetPoints 矢印サインをずらすための**最低オフセット値(ポイント単位)**を指定します。ローソク足の値幅が小さすぎる場合でも、最低限このポイント数だけ矢印をずらすようになります。
GetOffsetRatio()関数について

double GetOffsetRatio() {
    switch (Period()) {
        case PERIOD_M1:   return 0.5;
        case PERIOD_M5:   return 0.5;
        case PERIOD_M15:  return 0.5;
        case PERIOD_H1:   return 0.5;
        case PERIOD_H4:   return 0.5;
        case PERIOD_D1:   return 1.0;
        default:          return OffsetRatio;  // パラメータのデフォルト値
    }
}

GetOffsetRatio()は時間足に応じて矢印のオフセット割合を決める関数です。時間足によって矢印の位置が大きく異なるので、GetOffsetRatio()によって調整します。

※Period()は、現在のチャートの時間足を取得する関数になります。

OnInit()を解説

OnInit()で
初期設定を行う


int OnInit() {
    SetIndexBuffer(0, SellArrowBuffer);
    SetIndexStyle(0, DRAW_ARROW, EMPTY, 1);
    SetIndexArrow(0, 234);

    SetIndexBuffer(1, BuyArrowBuffer);
    SetIndexStyle(1, DRAW_ARROW, EMPTY, 1);
    SetIndexArrow(1, 233);

    SetIndexBuffer(2, MiddleBand2);
    SetIndexStyle(2, DRAW_LINE);
    SetIndexLabel(2, "Middle Band 2σ");

    SetIndexBuffer(3, UpperBand2);
    SetIndexStyle(3, DRAW_LINE);
    SetIndexLabel(3, "Upper Band 2σ");

    SetIndexBuffer(4, LowerBand2);
    SetIndexStyle(4, DRAW_LINE);
    SetIndexLabel(4, "Lower Band 2σ");

    SetIndexBuffer(5, UpperBand3);
    SetIndexStyle(5, DRAW_LINE);
    SetIndexLabel(5, "Upper Band 3σ");

    SetIndexBuffer(6, LowerBand3);
    SetIndexStyle(6, DRAW_LINE);
    SetIndexLabel(6, "Lower Band 3σ");

    return(INIT_SUCCEEDED);
}


int OnInit()でインジケーターの初期化(初期設定)を行います。

OnInit()の中では「SetIndexBuffer」・「SetIndexStyle」・「SetIndexLabel」が使用されており、それぞれの意味は以下の様になります。

関数名 説明
SetIndexBuffer バッファをMetaTraderに登録し、チャートに表示するデータを管理する。
SetIndexStyle インジケーターの描画スタイル(矢印・ライン・ヒストグラムなど)を設定する。
SetIndexLabel インジケーターの名前を設定し、チャートやデータウィンドウに表示する。
【重要】SetIndexBufferについて

この中で特に重要になるのが「SetIndexBuffer」です。SetIndexBuffer(0, SellArrowBuffer);の場合、SellArrowBuffer[]の配列を配置する事でSellArrowBuffer[]をバッファとして登録します。

バッファとして登録されたSellArrowBuffer[]に値が入るとMetaTraderがその情報を読み取り、自動でチャートにサインを描画してくれます。

SetIndexStyleの代表的な種類
スタイル名 説明
DRAW_LINE 折れ線グラフを描画する(移動平均線などに使用)。
DRAW_HISTOGRAM ヒストグラム(棒グラフ)を描画
DRAW_ARROW 矢印や記号を描画
DRAW_NONE 描画しない
DRAW_SECTION 点と点を結ぶ線分を描画
DRAW_ZIGZAG ジグザグラインを描画す
DRAW_BARS バーチャート(OHLCバー)を描画
DRAW_CANDLES ローソク足を描画

OnCalculate()を解説

要注意
引数の数を確かめよう

int OnCalculate(const int rates_total,
                 const int prev_calculated,
                 const datetime &time[],
                 const double &open[],
                 const double &high[],
                 const double &low[],
                 const double &close[],
                 const long &tick_volume[],
                 const long &volume[],
                 const int &spread[])
{

OnCalculate() とは
OnCalculate() は、インジケーターの計算処理を実行する関数です。

MetaTrader(MT4)は、新しいローソク足ができたり、価格が更新されるたびに OnCalculate() を自動で実行します。

この関数の中で、RSIの計算やサインを表示する処理を行います。

OnCalculate()の中には10個の引数が入っています。

その為、OnCalculate()を記入する際は

int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{

の様に記入します。

引数の意味は以下の様になります。

引数 役割
rates_total チャート上のローソク足の本数
prev_calculated 前回計算したローソク足の本数
time[] 各ローソク足の時間(タイムスタンプ)
open[] 各ローソク足の始値
high[] 各ローソク足の高値
low[] 各ローソク足の安値
close[] 各ローソク足の終値
tick_volume[] 各ローソク足のティック(取引)回数
volume[] 各ローソク足の出来高
spread[] 各ローソク足のスプレッド(買値と売値の差)
OnCalculate()で重要な事
OnCalculate()はインジケーター起動時や新しいローソク足が表示された時に自動的に起動し、引数に値を入れます。各ローソク足の値はOnCalculate()が自動で行っている事を認識しましょう。

OnCalculate()の処理を解説

OnCalculate()の
処理を解説
int limit = rates_total - prev_calculated;

int limit = rates_total - prev_calculated;

前回の計算以降に追加されたローソク足の本数を求めています。

パーツ 説明
int 整数型の変数を作るための型。ここでは limit を整数として定義している。
limit 計算の開始位置を決めるためのカウンター。処理するローソク足の数を表す。
= 右側の計算結果を、左側の limit に代入する記号。
rates_total チャートに表示されているローソク足の合計本数。最新のバー数を表す。
prev_calculated 前回 OnCalculate() が実行されたときに、すでに計算が終わっているローソク足の数。
if (prev_calculated == 0) limit = rates_total - 1;

if (prev_calculated == 0) limit = rates_total - 1;

まだ一度も計算されていない初回は、すべてのローソク足を計算するように開始位置を設定します。

パーツ 説明
if (prev_calculated == 0) 初回の計算(まだ何も計算していない場合)かを確認する。
limit = rates_total - 1; チャート上のすべてのローソク足を最初から計算するための開始位置を設定する。
bool isNewSellSignal = false;

bool isNewSellSignal = false;
bool isNewBuySignal  = false;

新しい売りサインと買いサインが出たかを判定するためのフラグです。

毎回の計算(OnCalculate())が始まるたびに、「今回はまだサインは出ていませんよ」という状態にリセットしています。

double ratio = GetOffsetRatio();

double ratio = GetOffsetRatio();

時間足ごとに、矢印サインをローソク足からどれくらい離して表示するかを決めるための割合を取得しています。

割合はdouble GetOffsetRatio()で設定済

double minOffset = Point * MinOffsetPoints;

double minOffset = Point * MinOffsetPoints;

矢印をローソク足から最低限どれくらい離すかの距離を計算している。

MinOffsetPointsは「extern int MinOffsetPoints = 20;」で設定済

for (int i = limit; i >= 0; i--) {

for (int i = limit; i >= 0; i--) {

最新のローソク足から始めて、最も古いローソク足(0番目のバー)まで1本ずつ逆順で処理を行うループです。

iBands()関数を使って値を取得

        double middleBB2 = iBands(NULL, 0, BB_Period, BB_Deviation2, 0, PRICE_CLOSE, MODE_MAIN, i);
        double upperBB2  = iBands(NULL, 0, BB_Period, BB_Deviation2, 0, PRICE_CLOSE, MODE_UPPER, i);
        double lowerBB2  = iBands(NULL, 0, BB_Period, BB_Deviation2, 0, PRICE_CLOSE, MODE_LOWER, i);

        double middleBB3 = iBands(NULL, 0, BB_Period, BB_Deviation3, 0, PRICE_CLOSE, MODE_MAIN, i);
        double upperBB3  = iBands(NULL, 0, BB_Period, BB_Deviation3, 0, PRICE_CLOSE, MODE_UPPER, i);
        double lowerBB3  = iBands(NULL, 0, BB_Period, BB_Deviation3, 0, PRICE_CLOSE, MODE_LOWER, i);

double middleBB2 = iBands(NULL, 0, BB_Period, BB_Deviation2, 0, PRICE_CLOSE, MODE_MAIN, i);

2σの中央ラインの値を取得

double upperBB2 = iBands(NULL, 0, BB_Period, BB_Deviation2, 0, PRICE_CLOSE, MODE_UPPER, i);

2σの上側ラインの値を取得

double lowerBB2 = iBands(NULL, 0, BB_Period, BB_Deviation2, 0, PRICE_CLOSE, MODE_LOWER, i);

2σの下側ラインの値を取得

double middleBB3 = iBands(NULL, 0, BB_Period, BB_Deviation3, 0, PRICE_CLOSE, MODE_MAIN, i);

3σの中央ラインの値を取得

double upperBB3 = iBands(NULL, 0, BB_Period, BB_Deviation3, 0, PRICE_CLOSE, MODE_UPPER, i);

3σの上側ラインの値を取得

double lowerBB3 = iBands(NULL, 0, BB_Period, BB_Deviation3, 0, PRICE_CLOSE, MODE_LOWER, i);

3σの下側ラインの値を取得

iBands()の引数は以下の様になります。

iBands(① シンボル名,② 時間足,③ 期間,④ 偏差,⑤ シフト,⑥ 適用価格,⑦ バンドの種類,⑧ インデックス)

引数に入れる値は設定済


extern int BB_Period = 20;
extern double BB_Deviation2 = 2;
extern double BB_Deviation3 = 3;

引数番号と項目 設定例 説明
① シンボル名 NULL 計算対象の通貨ペアや銘柄を指定します。NULLを使うと現在のチャートのシンボルになります。
② 時間足 0 使用する時間足を指定します。0は現在の時間足、PERIOD_H1は1時間足になります。
③ 期間 20 ボリンジャーバンドの計算に使用する移動平均の期間です。過去何本のローソク足を使うかを指定します。
④ 偏差 2 / 3 バンド幅を決めるための標準偏差(シグマ)値です。
⑤ シフト 0 インジケーターラインを右にずらす本数を指定します。通常は0(シフトなし)を使用します。
⑥ 適用価格 PRICE_CLOSE 計算に使う価格を選択します。終値(PRICE_CLOSE)や始値(PRICE_OPEN)などがあります。
⑦ バンドの種類 MODE_MAIN / MODE_UPPER / MODE_LOWER 取得したいバンドの種類を指定します。ミドル(中央)、アッパー(上)、ロワー(下)があります。
⑧ インデックス 0 / 1 / i どのローソク足のデータを取得するかを指定します。0は最新バー、1は1本前のバーを示します。

引数に値を入れる事でボリンジャーバンドの値そ取得する事が出来ます。

バッファに値を入れてラインを表示させる

MiddleBand2[i] = middleBB2;
UpperBand2[i]  = upperBB2;
LowerBand2[i]  = lowerBB2;

UpperBand3[i]  = upperBB3;
LowerBand3[i]  = lowerBB3;

MiddleBand2[i] の場合、OnInit() で「SetIndexBuffer(2, MiddleBand2);」によって、チャート表示用のバッファとして登録されています。

そのため、MiddleBand2[i] に値を入れるだけで、MetaTrader が自動的にその値を読み取り、チャートにラインを表示してくれます。

OnInit()内で「SetIndexStyle(2, DRAW_LINE);」を設定しているのでラインが表示されます。

double candleRange = High[i] - Low[i];

double candleRange = High[i] - Low[i];

ローソク足の高値と安値の差を計算しています。矢印をローソク足からどれくらい離して表示するかを決めるために使っています。

double dynamicOffset = candleRange * ratio;

double dynamicOffset = candleRange * ratio;

ローソク足の大きさに合わせて、矢印サインを適切な距離に表示するために使っています。

ratio は「double ratio = GetOffsetRatio();」によって設定されます。

GetOffsetRatio() の中では、現在のチャートの時間足に応じて値が分岐し、例えば次のように設定されています:


case PERIOD_M1:   return 0.5;
case PERIOD_M5:   return 0.5;
case PERIOD_M15:  return 0.5;

このように、時間足が「1分足(M1)」の場合は 0.5 が返され、それが ratio に代入されます。

最小値を計算する

if (dynamicOffset < minOffset) {
    dynamicOffset = minOffset;
}

計算された距離(dynamicOffset)が最低値(minOffset)より小さい場合は、最低値に調整しています。

minOffsetは「extern int MinOffsetPoints = 20;」で設定済。

ローソク足が小さいと矢印が重なりやすく、大きいと離れすぎてしまうため、サインが見づらくなります。

相場の状況によってローソク足の値幅が常に変動するため、矢印の表示位置をその都度調整する必要があります。

if分の詳細

        if (Close[i] >= upperBB3) {
            SellArrowBuffer[i] = Close[i] + dynamicOffset;
            if (i == 1)
                isNewSellSignal = true;
        } else {
            SellArrowBuffer[i] = EMPTY_VALUE;
        }

        if (Close[i] <= lowerBB3) {
            BuyArrowBuffer[i] = Close[i] - dynamicOffset;
            if (i == 1)
                isNewBuySignal = true;
        } else {
            BuyArrowBuffer[i] = EMPTY_VALUE;
        }

上のIF分
パーツ 説明
if (Close[i] >= upperBB3) 終値がボリンジャーバンドの上限(3σ)以上なら売りサインを出す条件。
SellArrowBuffer[i] = Close[i] + dynamicOffset; 売りサインの矢印を終値よりも上に表示するため、dynamicOffset を加えた位置に設定。
if (i == 1) 最新のローソク足(バー)が対象の場合、以下を実行。
isNewSellSignal = true; 最新バーに新しい売りサインが出たことをフラグで記録。
else { SellArrowBuffer[i] = EMPTY_VALUE; } 条件を満たさない場合、売りサインを表示しない(非表示にする)。

ローソク足の終値がボリンジャーバンドの上限(3σ)を上回った場合に、売りサインを表示する処理です。

下のIF分
パーツ 説明
if (Close[i] <= lowerBB3) 終値がボリンジャーバンドの下限(3σ)以下なら買いサインを出す条件。
BuyArrowBuffer[i] = Close[i] - dynamicOffset; 買いサインの矢印を終値よりも下に表示するため、dynamicOffset を引いた位置に設定。
if (i == 1) 最新のローソク足(バー)が対象の場合、以下を実行。
isNewBuySignal = true; 最新バーに新しい買いサインが出たことをフラグで記録。
else { BuyArrowBuffer[i] = EMPTY_VALUE; } 条件を満たさない場合、買いサインを表示しない(非表示にする)。

ローソク足の終値がボリンジャーバンドの下限(3σ)を下回った場合に、買いサインを表示する処理です。

以下に覚えた方が良い内容をまとめています。

Close[i]は各ローソク足の終値になります。OnCalculate()の引数で、OnCalculate()が起動するたびに自動的にローソク足の終値の値が入ります。

SellArrowBuffer[i]はOnInit()内のSetIndexBuffer(0, SellArrowBuffer);でバッファとして登録されています。その為、SellArrowBuffer[i]に値が入った瞬間に値通りの場所に矢印が表示されます。

※バッファはMetaTraderに自動管理されおり、値が入ると即実行されます。

isNewSellSignal = true;はアラートの処理で使います。新しいサインが出た時だけにアラートを出さないと、チャートを開いた時に過去のサインまでアラートが反応してしまい大惨事になります。

return(rates_total);

return(rates_total);

現在のローソク足の総数(rates_total)を返し、次回の OnCalculate() 実行時に前回計算したローソク足の数として利用されます。

アラート処理を解説


    // アラート処理
    string symbolName = Symbol();
    string alertMsg;

    if (isNewSellSignal) {
        alertMsg = "SELL Signal! Symbol: " + symbolName + " | Close >= 3σ Upper Band.";
        Alert(alertMsg);
        PlaySound("alert.wav");
    }

    if (isNewBuySignal) {
        alertMsg = "BUY Signal! Symbol: " + symbolName + " | Close <= 3σ Lower Band.";
        Alert(alertMsg);
        PlaySound("alert.wav");
    }

アラートで唯一注意すべき点は「エラーメッセージの言語」になります。エラーメッセージを日本語にすると文字化けする事があるので、英数字で表示するのが一般的にとなっています。

パーツ 処理の役割
string symbolName = Symbol(); 現在の通貨ペアや銘柄の名前を取得し、symbolName に代入する。
string alertMsg; アラートメッセージ用の文字列変数を宣言。
if (isNewSellSignal) 新しい売りサインが出た場合にアラートを実行する条件。
isNewSellSignal 新しい売りサインが出た場合にアラート処理を実行。
isNewBuySignal 新しい買いサインが出た場合にアラート処理を実行。
Alert() アラートメッセージの表示。
PlaySound() アラート音の再生。
綾瀬 文也

10年以上のFXトレード経験を持ち、チャート分析と戦略構築を専門とするトレーダー。マーケットの変動を的確に捉え、リスク管理を徹底することで安定した収益を実現。現在はpokyun企画代表として活動

綾瀬 文也をフォローする
サインツール
綾瀬 文也をフォローする
タイトルとURLをコピーしました