MQL4MQL5 インジケーター 売買サイン・相場の判定
チャートに売買サイン(矢印)を出したい
結論:インジケーターのバッファを2本(買い・売り)用意し、描画を DRAW_ARROW にして、サインの足だけ価格を入れます。
考え方
売買サインの矢印は、インジケーターのバッファを矢印表示(DRAW_ARROW)にして作ります。矢印を出したい足には表示する価格(買いなら安値の少し下)を入れ、出さない足には EMPTY_VALUE を入れます。ここでは移動平均線のゴールデンクロスで上向き矢印、デッドクロスで下向き矢印を出すインジケーターを例にしています。
- バッファを2本用意し、それぞれ矢印表示にする(上向き 233・下向き 234)
- 各足について、短期 MA と長期 MA が交差したかを判定する
- 交差した足には矢印の位置(安値の下・高値の上)を、それ以外は EMPTY_VALUE を入れる
- 新しい足の分だけ計算し直すようにして、動作を軽くする
そのまま使えるコード
MetaEditor の「新規作成」で「カスタムインディケータ」を選び、できたファイルの中身をすべてこのコードに置き換えてコンパイル(F7)します。ファイルは Indicators フォルダに保存され、ナビゲーターからチャートにドラッグして使います。
MQL4(MT4)
#property strict
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 clrDodgerBlue
#property indicator_color2 clrRed
#property indicator_width1 2
#property indicator_width2 2
// 移動平均線のクロスで売買サインの矢印を出すインジケーター(MT4)
input int InpFast = 5; // 短期 MA の期間
input int InpSlow = 20; // 長期 MA の期間
double BuyBuf[], SellBuf[];
int OnInit()
{
SetIndexBuffer(0, BuyBuf);
SetIndexBuffer(1, SellBuf);
SetIndexStyle(0, DRAW_ARROW);
SetIndexStyle(1, DRAW_ARROW);
SetIndexArrow(0, 233); // 上向き矢印
SetIndexArrow(1, 234); // 下向き矢印
SetIndexLabel(0, "Buy");
SetIndexLabel(1, "Sell");
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[])
{
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
int limit = rates_total - prev_calculated; // MQL4 は 0 = 最新の足
if(prev_calculated == 0) limit = rates_total - InpSlow - 2;
double gap = 10 * _Point; // 矢印をローソク足から離す幅
for(int i = limit; i >= 1; i--) // 確定した足(1 以降)だけにサインを出す
{
BuyBuf[i] = EMPTY_VALUE;
SellBuf[i] = EMPTY_VALUE;
double f1 = iMA(_Symbol, 0, InpFast, 0, MODE_SMA, PRICE_CLOSE, i);
double f2 = iMA(_Symbol, 0, InpFast, 0, MODE_SMA, PRICE_CLOSE, i + 1);
double s1 = iMA(_Symbol, 0, InpSlow, 0, MODE_SMA, PRICE_CLOSE, i);
double s2 = iMA(_Symbol, 0, InpSlow, 0, MODE_SMA, PRICE_CLOSE, i + 1);
if(f2 <= s2 && f1 > s1) BuyBuf[i] = low[i] - gap;
if(f2 >= s2 && f1 < s1) SellBuf[i] = high[i] + gap;
}
BuyBuf[0] = EMPTY_VALUE;
SellBuf[0] = EMPTY_VALUE;
return rates_total;
}MQL5(MT5)
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots 2
#property indicator_type1 DRAW_ARROW
#property indicator_color1 clrDodgerBlue
#property indicator_width1 2
#property indicator_label1 "Buy"
#property indicator_type2 DRAW_ARROW
#property indicator_color2 clrRed
#property indicator_width2 2
#property indicator_label2 "Sell"
// 移動平均線のクロスで売買サインの矢印を出すインジケーター(MT5)
input int InpFast = 5; // 短期 MA の期間
input int InpSlow = 20; // 長期 MA の期間
double BuyBuf[], SellBuf[];
int hFast = INVALID_HANDLE, hSlow = INVALID_HANDLE;
int OnInit()
{
SetIndexBuffer(0, BuyBuf, INDICATOR_DATA);
SetIndexBuffer(1, SellBuf, INDICATOR_DATA);
PlotIndexSetInteger(0, PLOT_ARROW, 233); // 上向き矢印
PlotIndexSetInteger(1, PLOT_ARROW, 234); // 下向き矢印
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
hFast = iMA(_Symbol, PERIOD_CURRENT, InpFast, 0, MODE_SMA, PRICE_CLOSE);
hSlow = iMA(_Symbol, PERIOD_CURRENT, InpSlow, 0, MODE_SMA, PRICE_CLOSE);
if(hFast == INVALID_HANDLE || hSlow == INVALID_HANDLE) return INIT_FAILED;
return INIT_SUCCEEDED;
}
void OnDeinit(const int reason)
{
IndicatorRelease(hFast);
IndicatorRelease(hSlow);
}
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[])
{
if(BarsCalculated(hFast) < rates_total || BarsCalculated(hSlow) < rates_total) return 0; // MA の計算待ち
double fast[], slow[];
if(CopyBuffer(hFast, 0, 0, rates_total, fast) < rates_total) return 0;
if(CopyBuffer(hSlow, 0, 0, rates_total, slow) < rates_total) return 0;
// MQL5 は 0 = 最も古い足。前回の続きから計算する
int start = (prev_calculated > 1) ? prev_calculated - 1 : InpSlow + 1;
double gap = 10 * _Point; // 矢印をローソク足から離す幅
for(int i = start; i < rates_total; i++)
{
BuyBuf[i] = EMPTY_VALUE;
SellBuf[i] = EMPTY_VALUE;
if(i == rates_total - 1) break; // 未確定の最新の足にはサインを出さない
if(fast[i - 1] <= slow[i - 1] && fast[i] > slow[i]) BuyBuf[i] = low[i] - gap;
if(fast[i - 1] >= slow[i - 1] && fast[i] < slow[i]) SellBuf[i] = high[i] + gap;
}
return rates_total;
}MT4 版・MT5 版とも MetaEditor でコンパイル(エラー・警告なし)を確認済みです。実際の口座で使う前に、デモ口座やストラテジーテスターで動作を確かめてください。
カスタマイズのポイント
- 矢印の形は Wingdings の番号で変えられます(233・234 が矢印、159 が点、108 が丸など)。
- サインの条件を変えたいときは、クロスを判定している if 文の部分を書き換えます。
- このインジケーターのサインで EA に売買させたいときは、iCustom() でバッファ 0(買い)・1(売り)を読みます。
注意点
- 未確定の足(最新の足)にサインを出すと、足の途中で出たり消えたりする「リペイント」になります。確定足だけにサインを出すのが基本です。
- サインのない足に 0 を入れると、価格 0 の位置に矢印が出てしまうことがあります。EMPTY_VALUE を入れます。












