恥は/dev/nullへ by 初心者

プログラミング素人がのろのろと学んだことをつづっています♪

パラメーターで任意の時間軸を選択し、MTFの移動平均線を表示する

以前はたまにしかMTF(MultiTimeFrame)の移動平均線をチャートに表示していなかったので、必要になったら、その都度、移動平均線を描画するインディケーターを作っていました。

 

しかし、最近MTF移動平均線をチャートに入れてあれこれ調べることが増えました。こうなると、その都度作るのが面倒になってきたため、パラメーターで任意の時間軸(MTF)を選ぶ方式のコードを書きました。

 

f:id:philojuan:20200829031524p:plain

 

コード

//----------------------------------------------------------------------------
// FileName : MyMA_Multi.mq4
// Feature  : MTFのMAを表示するインディケーター
//----------------------------------------------------------------------------

#property copyright "Copyright 2020. PHILOJUAN"
#property link      "https://uhoho.hatenablog.jp/"
#property version   "1.00"
#property indicator_chart_window
#property strict

#property indicator_buffers 1

enum OnOff {OFF, ON};

input ENUM_TIMEFRAMES maTF     = PERIOD_CURRENT;  // MAの時間軸(MultiTimeFrame)
input int maPeriod             = 20;              // MAの期間
input ENUM_MA_METHOD method    = MODE_SMA;        // 計算方法(SMA, EMA等)
input ENUM_APPLIED_PRICE price = PRICE_CLOSE;     // 適用価格(デフォルトは終値)
input int maWidth              = 2;               // MAの太さ
input color maColor            = clrLightPink;    // MAの色
input OnOff repaint            = ON;              // リペイント

int chartTF = 0;             // チャートのTimeFrameを格納する変数
int BarsToRecalculate = 0;   // リペイントの対象となるローソク足の本数

// MA用バッファ
double MultiMA[];

int OnInit()
{
    // ラベル名を作成
    string label = ChangeTimeFrameExp(maTF) + "_" + IntegerToString(maPeriod)
                 + "_" + ChangeMAmodeExp(method);

    SetIndexStyle (0, DRAW_LINE, STYLE_SOLID, maWidth, maColor);
    SetIndexBuffer(0, MultiMA);
    SetIndexLabel (0, label);

    chartTF = Period();

    // MAをリペイントするーソク足の本数を計算
    //  → MAの時間軸(分) ÷ チャートの時間軸(分) = リペイント本数
    if(repaint && (maTF > chartTF))
    {
        if((maTF % chartTF) == 0)
            BarsToRecalculate = maTF / chartTF;
        else
            BarsToRecalculate = maTF / chartTF + 1;
    }

    return(0);
}

int start()
{
    int counted_bars = IndicatorCounted();

    if(!counted_bars)  // counted_barsが 0 のとき
    {
        // 計算対象から除外するローソク足の本数を計算
        if((maTF * maPeriod % chartTF) == 0)
            counted_bars = maTF * maPeriod / chartTF;
        else
            counted_bars = maTF * maPeriod / chartTF + 1;
    }
    else if(repaint) // counted_barsが 0 ではなく、かつ、repaintがONのとき
    {
        // リペイントするローソク足の本数を counted_bars から差し引く。
        counted_bars = counted_bars - BarsToRecalculate;
    }

    // limitは計算対象となるローソク足の本数
    int limit = Bars - counted_bars;

    for(int i = limit - 1; i >= 0; i--)
    {
        MultiMA[i] = EMPTY_VALUE;
        int shift_Multi = iBarShift(NULL, maTF, iTime(NULL, 0, i), false);

        MultiMA[i] = iMA(NULL, maTF, maPeriod, 0, method, price, shift_Multi);
    }

    return(0);
}

// MAの計算方法の表現を「SMA」等に変換する関数
//  → 「MODE_SMA」等は整数値。これを「SMA」等の文字列にして返す。
string ChangeMAmodeExp(ENUM_MA_METHOD original)
{
    string res = "";
    switch(original)
    {
        case 0:          // MODE_SMA
            res = "SMA";
            break;

        case 1:          // MODE_EMA
            res = "EMA";
            break;

        case 2:          // MODE_SMMA
            res = "SMMA";
            break;

        case 3:          // MODE_LWMA
            res = "LWMA";
            break;

        default:
            res = "ERROR";
            break;
    }

    return res;
}

// 時間軸の表現を「M1」等に変換する関数
//  → 「PERIOD_M5」等は整数値。これを「M5」等の文字列にして返す。
string ChangeTimeFrameExp(ENUM_TIMEFRAMES tf)
{
    string res = "";   // 戻り値を格納する変数

    // 通常は、引数で受け取った時間軸を使用
    int frame  = tf;

    // 引数が PERIOD_CURRENTの場合、チャートの時間軸を使用
    if(!tf) frame = Period();

    // 変換処理
    if(frame < 60)
        res = "M" + IntegerToString(frame);
    else if(frame < 1440)  // D1は1440分
        res = "H" + IntegerToString(frame / 60);
    else if(frame == 1440)
        res = "D1";
    else if(frame == 10080)
        res = "W1";
    else if(frame == 43200)
        res = "MN1";
    else
        res = "ERROR";

    return res;
}