恥は/dev/nullへ by 初心者

~ PC初心者による右往左往の記録 ~

MT5でボリンジャーバンドの幅を調べるスクリプト

ボラティリティが無いとトレードしづらいので、トレード前にボリンジャーバンド(以下「BB」)の様子を見ています。しかし、手作業で主要通貨ペアのチャートを見るのは手間です。

そこで、BBの幅をエキスパートに出力するスクリプトを書いてみました。
なお、幅は(ポイント単位ではなく)pips単位で出力されます。


この記事に載っているコードは、次のようなセッティングになっています。

・計算するのは現在足時点
・計算期間は20
・BBの偏差は2
・対象は1時間足
・BBの幅が40pips以上の通貨ペアを出力


// BBの幅を調べるスクリプト
//     1時間足、期間 20、2シグマ、対象は現在足、pips数で出力
//     BBの幅が40pips以上の通貨ペアを出力

#property copyright "Copyright 2024, PHILOJUAN."
#property version   "1.00"
#property strict
#property script_show_inputs

#define NUM_SYMBOL 28        // 通貨ペアの個数

input int    InpTargetBar = 0;     // 対象とするbar (0は現在足, 1は1本前)
input int    InpPeriod    = 20;    // BBの計算期間
input double InpDeviation = 2.0;   // BBの偏差
input ENUM_TIMEFRAMES InpTimeFrame = PERIOD_H1; // 時間軸
input int    InpTargetWidth = 40;  // 基準値(BB幅 N pips以上を抽出)

// 通貨ペア名配列
string symbols[NUM_SYMBOL] = {
    "AUDCAD", "AUDCHF", "AUDJPY", "AUDNZD", "AUDUSD",
    "CADCHF", "CADJPY", "CHFJPY",
    "EURAUD", "EURCAD", "EURCHF", "EURGBP", "EURJPY", "EURNZD", "EURUSD",
    "GBPAUD", "GBPCAD", "GBPCHF", "GBPJPY", "GBPNZD", "GBPUSD",
    "NZDCAD", "NZDCHF", "NZDJPY", "NZDUSD",
    "USDCAD", "USDCHF", "USDJPY"
};

void OnStart()
{
    int count = 0;
    for(int i = 0; i < NUM_SYMBOL; i++) {
        double width = ReturnPipsOfBBWidth(symbols[i], InpTargetBar, InpPeriod, InpDeviation, InpTimeFrame);
        if(width >= InpTargetWidth) {
            count++;
            printf("[%s][%s] BBの幅(pips) = %s",
                   symbols[i], TimeFrameToString(InpTimeFrame), DoubleToString(width, 1));
        }
    }

    if(count == 0)
        printf("BB幅 %d pips以上の通貨ペアはありませんでした", InpTargetWidth);
}


//-----------------------------------------------------------------------------------
// ボリンジャーバンドの幅をPips数で返す関数(範囲は1シグマから3シグマまで)
//-----------------------------------------------------------------------------------
double ReturnPipsOfBBWidth(string symbol,        // 通貨ペア名
                           int    startPosition, // 対象(チャートの右端からN本前)
                           int    calcPeriod,    // 計算期間
                           double sigma,         // シグマ (2.0や3.0等)
                           ENUM_TIMEFRAMES tf    // 時間軸 (PERIOD_M30等)
)
{
    //----------------------
    // パラメーターチェック
    //----------------------
    int barMax      = Bars(symbol, tf) - 1;        // 最古足
    int requiredBar = startPosition + calcPeriod;  // 計算に使用するbarのうち一番古いもの

    if(startPosition < 0 || startPosition > barMax || barMax < requiredBar ||
       calcPeriod < 2    || sigma < 1.0            || sigma > 3.0) {
        Print("[ReturnPipsOfBBWidth Function] parameter is wrong.");
        return -1.0;
    }

    //----------------------
    // BBの計算
    //----------------------
    double sum         = 0.0;
    int    endPosition = startPosition + calcPeriod - 1;
    int    digits      = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
    // [memo] SYMBOL_DIGITSはintを返すのでint型にキャスト

    for(int i = startPosition; i <= endPosition; i++) {
        sum += iClose(symbol, tf, i);
    }
   
    double avg = sum / calcPeriod;
    sum = 0.0;                                // 変数をリセット

    for(int i = startPosition; i <= endPosition; i++) {
        sum += MathPow((iClose(symbol, tf, i) - avg), 2);
    }

    double variance  = sum / calcPeriod;      // 分散
    double deviation = MathSqrt(variance);    // 偏差

    double upper = avg + sigma * deviation;   // Upperバンド
    double lower = avg - sigma * deviation;   // Lowerバンド
    double diff  = upper - lower;             // バンド幅
    double multiplier = MathPow(10, digits);  // 乗数
    diff = diff * multiplier / 10;            // バンド幅(Pips単位)

    return diff;
}

//-----------------------------------------------------------------------------------
// 時間足を「H1」等の短縮表現に変換する関数
//-----------------------------------------------------------------------------------
// 例 PERIOD_H4   →   H4
string TimeFrameToString(ENUM_TIMEFRAMES intTF)
{
    if(intTF == PERIOD_CURRENT) intTF = Period();
    return StringSubstr(EnumToString(intTF), 7);
}