【MQL5】インジケータでアラートを鳴らしたい

当ページのリンクには広告が含まれています。
目次

作るもの

チャートと別枠に表示する平均足インジケータ に、陽線(陰線)から陰線(陽線)に切替わったときにアラートを鳴らす機能を追加します。

参考サイト

実装

input string    AlertSound = "alert.wav";   // Sound

datetime prevDt = 0;

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[])
{
    (省略)

    MqlDateTime dt;
    TimeToStruct(time[rates_total - 1], dt);

    MqlDateTime pdt;
    TimeToStruct(prevDt, pdt);

    if (dt.min != pdt.min)
    {
        prevDt = time[rates_total - 1];

        if (((ExtOBuffer[rates_total - 3] > ExtCBuffer[rates_total - 3]) &&
             (ExtOBuffer[rates_total - 2] < ExtCBuffer[rates_total - 2])) ||
            ((ExtOBuffer[rates_total - 3] < ExtCBuffer[rates_total - 3]) &&
             (ExtOBuffer[rates_total - 2] > ExtCBuffer[rates_total - 2])))
        {
            PlaySound(AlertSound);
            prevDt = time[rates_total - 1];
        }
    }

    return rates_total;
}

音声ファイル

音声ファイルは、(MT5のインストール先)\Sounds フォルダ、または Soundsフォルダのサブフォルダに格納する必要があります。

私の環境では、C:\Program Files\OANDA MetaTrader 5\Sounds でした。

今回は、このフォルダにデフォルトで入っている alert.wav を使用します。

足確定の判定

OnCalculate() の引数 time の分の部分が変わったら、足が確定したと見なしています。

すみません。分足でしか機能しません。
1時間以上の時間軸で動作確認するのが面倒で、端折りました。(´-∀-`;)

音声ファイルの再生

音声ファイルは PlaySound関数で再生できます。

PlaySound関数の定義は以下のとおり。

bool PlaySound(
  string  filename      // ファイル名
);

filename には、ファイル名を指定します。
サブフォルダ内に格納している場合は、(サブフォルダ名)\\(音声ファイル名) を指定します。
今回はサブフォルダを使用しないので、alert.wav だけ指定しています。

このインジケータをチャートに追加すると、下図のタイミングでアラートが鳴ります。

これで、テンションが上がるアラートを鳴らせますね!

コード全体

//+------------------------------------------------------------------+
//|                                         Heikin-Ashi_SubFrame.mq5 |
//|                                            Copyright 2024, Hailu |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
// 参考: Heiken_Ashi.mql5

#property copyright "Copyright 2024, Hailu"
#property link      "https://www.mql5.com"
#property version   "1.01"

#property indicator_separate_window
#property indicator_minimum 0
#property indicator_maximum 1

#property indicator_buffers 9
#property indicator_plots   1
#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1  Red, DodgerBlue
#property indicator_label1  "Upper/Lower"

input string    AlertSound = "alert.wav";   // Sound

double ExtOBuffer[];
double ExtHBuffer[];
double ExtLBuffer[];
double ExtCBuffer[];
double ExtColorBuffer[];

double bufOpen[];
double bufHigh[];
double bufLow[];
double bufClose[];

int hHeiken = 0;
datetime prevDt = 0;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
    // 平均足インジケータを作成
    hHeiken = iCustom(NULL, 0, "Examples\\Heiken_Ashi");
    if (hHeiken == INVALID_HANDLE)
    {
        PrintFormat("[E] Failed to create Heiken_Ashi indicator. [%d]", GetLastError());
        return INIT_FAILED;
    }

    SetIndexBuffer(0, ExtOBuffer, INDICATOR_DATA);
    SetIndexBuffer(1, ExtHBuffer, INDICATOR_DATA);
    SetIndexBuffer(2, ExtLBuffer, INDICATOR_DATA);
    SetIndexBuffer(3, ExtCBuffer, INDICATOR_DATA);
    SetIndexBuffer(4, ExtColorBuffer, INDICATOR_COLOR_INDEX);

    IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
    IndicatorSetString(INDICATOR_SHORTNAME, "Heikin-Ashi");
    PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0);

    SetIndexBuffer(5, bufOpen, INDICATOR_CALCULATIONS);
    SetIndexBuffer(6, bufHigh, INDICATOR_CALCULATIONS);
    SetIndexBuffer(7, bufLow, INDICATOR_CALCULATIONS);
    SetIndexBuffer(8, bufClose, INDICATOR_CALCULATIONS);

    prevDt = 0;

    return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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 start = prev_calculated - 1;
    if(prev_calculated == 0)
    {
        ExtLBuffer[0] = 0;
        ExtHBuffer[0] = 0;
        ExtOBuffer[0] = 0;
        ExtCBuffer[0] = 0;
        start = 1;
    }

    // 平均足を取得
    CopyBuffer(hHeiken, 0, 0, rates_total, bufOpen);
    CopyBuffer(hHeiken, 1, 0, rates_total, bufHigh);
    CopyBuffer(hHeiken, 2, 0, rates_total, bufLow);
    CopyBuffer(hHeiken, 3, 0, rates_total, bufClose);

    // 正規化した平均足を設定
    for(int i = start; i < rates_total; i++)
    {
        // 最小値と最大値を求める
        double min = low[i];
        double max = high[i];
    
        for (int j = 1; j <= 100; j++)
        {
            int idx = i - j;
            if (idx < 0)
                break;
    
            min = MathMin(min, low[idx]);
            max = MathMax(max, high[idx]);
        }

        double pw = max - min;

        // 正規化
        ExtOBuffer[i] = (bufOpen[i] - min) / pw;
        ExtHBuffer[i] = (bufHigh[i] - min) / pw;
        ExtLBuffer[i] = MathMax((bufLow[i] - min) / pw, 0) + 0.000001;
        ExtCBuffer[i] = (bufClose[i] - min) / pw;

        // 色
        if (bufOpen[i] < bufClose[i])
            ExtColorBuffer[i] = 0.0;
        else
            ExtColorBuffer[i] = 1.0;
    }

    MqlDateTime dt;
    TimeToStruct(time[rates_total - 1], dt);

    MqlDateTime pdt;
    TimeToStruct(prevDt, pdt);

    if (dt.min != pdt.min)
    {
        prevDt = time[rates_total - 1];

        if (((ExtOBuffer[rates_total - 3] > ExtCBuffer[rates_total - 3]) &&
             (ExtOBuffer[rates_total - 2] < ExtCBuffer[rates_total - 2])) ||
            ((ExtOBuffer[rates_total - 3] < ExtCBuffer[rates_total - 3]) &&
             (ExtOBuffer[rates_total - 2] > ExtCBuffer[rates_total - 2])))
        {
            PlaySound(AlertSound);
            prevDt = time[rates_total - 1];
        }
    }

    return rates_total;
}
//+------------------------------------------------------------------+
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA



reCaptcha の認証期間が終了しました。ページを再読み込みしてください。

目次