【MT5/MQL5】ボリバンタッチでサイン&アラート!コード・ツールを無料配布

サインツール

ボリンジャーバンドにタッチした瞬間、即座にサイン表示&アラート通知!

MT5対応の無料インジケーター「ボリンジャーバンドの極み」は、2σ・3σタッチを視覚と音でわかりやすく知らせてくれるサインツールです。

±2σ・±3σのライン表示やタッチ時の矢印サイン、アラートON/OFFをすべてボタンで簡単に切り替え可能。

本記事では、インジケーターの導入方法から詳しいMQL5のコード解説までを完全網羅。実際に使えるソースコードも無料公開しています。

MT5でのボリバン活用をさらに強化したい方は、ぜひご活用ください。

綾瀬文也
綾瀬 文也

この記事はサインツールの作り方を紹介する趣旨で作っています。ボリンジャーバンドにタッチしたからと言って必ず反発する訳ではありません。エントリー目的では無く、タッチした後どの様な動きをするか、学習用としてご利用下さい。

サインツール「ボリンジャーバンドの極み」の入れ方

まずは、下記ボタンより「ボリンジャーバンドの極み」をダウンロードします。

ボリンジャーバンドの極みのex5

ダウンロードファイルはzipになっており、解凍を行うと「bbnokiwami.ex5」と言うファイルが入っています。

bbnokiwami.ex5をMT5に入れる事で使用する事が出来ます。

MT5⇒データフォルダーを開く

bbnokiwami.ex5ダウンロード後、MT5を開きます。

MT5のメニューより「ファイル」⇒「データフォルダを開く」を選択します。

MT5のMQL5フォルダ

「MQL5」を選択します。

MT5のIndicators

「Indicators」を選択します。

Indicatorsの中にファイルを移動

「Indicators」の中に「bbnokiwami.ex5」をドラッグ&ドロップで入れます。

MT5のナビゲーター

ナビゲーターの中に「bbnokiwami」があるので「bbnokiwami」をダブルクリックします。

bbnokiwamiのポップアップ

ポップアップが表示されるので「OK」ボタンをクリックします。

ボリンジャーバンドの極みのが表示

ボリンジャーバンドの極みが起動します。

サインツール「ボリンジャーバンドの極み」の使い方

ボリンジャーバンドの極み(2σ)

BB(2σ)をボタンを押すと、ボタンに☑マークが付きます。

±2σのボリンジャーバンドが表示され、高値・安値が±2σのラインをタッチするとサインが表示されます。

ボリンジャーバンドの極み(3σ)

BB(3σ)をボタンを押すと、ボタンに☑マークが付きます。

±3σのボリンジャーバンドが表示され、高値・安値が±3σのラインをタッチするとサインが表示されます。

ボリンジャーバンドの際に(アラート)

アラートボタンを押すとアラートが機能します。連続でアラートを出したくない時は、1回目のアラートが鳴った後にボタンをクリックする事で、アラートを止める事が出来ます。

ボリバンタッチでサイン&アラート「ボリンジャーバンドの極」コードを公開

コードはこのままコピー&ペーストで使う事が出来ます。

※チャートが停止する土日は動かないので、そこだけご注意下さい。


//+------------------------------------------------------------------+
//| BB_SigmaArrow_AlarmToggleButton.mq5                              |
//| 2σ=青矢印、3σ=緑矢印、アラートON/OFF切替ボタン付き           |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 8
#property indicator_plots   8
#property strict

//--- 2σラインと矢印
#property indicator_label1  "+2σ"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrDeepSkyBlue
#property indicator_width1  1

#property indicator_label2  "-2σ"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrDeepSkyBlue
#property indicator_width2  1

#property indicator_label3  "2σ ↓"
#property indicator_type3   DRAW_ARROW
#property indicator_color3  clrMediumSlateBlue
#property indicator_width3  2

#property indicator_label4  "2σ ↑"
#property indicator_type4   DRAW_ARROW
#property indicator_color4  clrMediumSlateBlue
#property indicator_width4  2

//--- 3σラインと矢印
#property indicator_label5  "+3σ"
#property indicator_type5   DRAW_LINE
#property indicator_color5  clrLimeGreen
#property indicator_width5  1

#property indicator_label6  "-3σ"
#property indicator_type6   DRAW_LINE
#property indicator_color6  clrLimeGreen
#property indicator_width6  1

#property indicator_label7  "3σ ↓"
#property indicator_type7   DRAW_ARROW
#property indicator_color7  clrLimeGreen
#property indicator_width7  2

#property indicator_label8  "3σ ↑"
#property indicator_type8   DRAW_ARROW
#property indicator_color8  clrLimeGreen
#property indicator_width8  2

input int BB_Period = 20;

//--- バッファ
double BBUpper2[], BBLower2[], Arrow2Down[], Arrow2Up[];
double BBUpper3[], BBLower3[], Arrow3Down[], Arrow3Up[];

//--- ハンドル
int handleBB2 = INVALID_HANDLE;
int handleBB3 = INVALID_HANDLE;

//--- ボタン
bool btnState = false;
string btnName = "Btn1";
string btnLabel = "BB(2σ)";

bool btn3State = false;
string btn3Name = "BtnBB3";
string btn3Label = "BB(3σ)";

bool alarmEnabled = false;
string btnAlarmName = "BtnAlarm";
string btnAlarmLabel = "アラート";

//--- アラート管理
datetime lastAlertTime2 = 0;
datetime lastAlertTime3 = 0;

//+------------------------------------------------------------------+
int OnInit()
{
   SetIndexBuffer(0, BBUpper2, INDICATOR_DATA);
   SetIndexBuffer(1, BBLower2, INDICATOR_DATA);
   SetIndexBuffer(2, Arrow2Down, INDICATOR_DATA);
   SetIndexBuffer(3, Arrow2Up, INDICATOR_DATA);
   SetIndexBuffer(4, BBUpper3, INDICATOR_DATA);
   SetIndexBuffer(5, BBLower3, INDICATOR_DATA);
   SetIndexBuffer(6, Arrow3Down, INDICATOR_DATA);
   SetIndexBuffer(7, Arrow3Up, INDICATOR_DATA);

   PlotIndexSetInteger(2, PLOT_ARROW, 234);
   PlotIndexSetInteger(3, PLOT_ARROW, 233);
   PlotIndexSetInteger(6, PLOT_ARROW, 234);
   PlotIndexSetInteger(7, PLOT_ARROW, 233);

   handleBB2 = iBands(_Symbol, _Period, BB_Period, 0, 2.0, PRICE_CLOSE);
   handleBB3 = iBands(_Symbol, _Period, BB_Period, 0, 3.0, PRICE_CLOSE);

   if(handleBB2 == INVALID_HANDLE || handleBB3 == INVALID_HANDLE)
   {
      Print("BB handle creation failed: ", GetLastError());
      return INIT_FAILED;
   }

   CreateFancyButton(btnName, 20, 20, btnLabel);
   CreateFancyButton(btn3Name, 20, 55, btn3Label);
   CreateFancyButton(btnAlarmName, 20, 90, btnAlarmLabel);

   EventSetTimer(1);
   return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)
{
   if(id != CHARTEVENT_OBJECT_CLICK) return;

   if(sparam == btnName + "_rect" || sparam == btnName + "_label")
   {
      btnState = !btnState;
      CreateFancyButton(btnName, 20, 20, btnLabel);
      if(!btnState)
      {
         ArrayInitialize(BBUpper2, EMPTY_VALUE);
         ArrayInitialize(BBLower2, EMPTY_VALUE);
         ArrayInitialize(Arrow2Down, EMPTY_VALUE);
         ArrayInitialize(Arrow2Up, EMPTY_VALUE);
      }
      ChartRedraw();
   }

   if(sparam == btn3Name + "_rect" || sparam == btn3Name + "_label")
   {
      btn3State = !btn3State;
      CreateFancyButton(btn3Name, 20, 55, btn3Label);
      if(!btn3State)
      {
         ArrayInitialize(BBUpper3, EMPTY_VALUE);
         ArrayInitialize(BBLower3, EMPTY_VALUE);
         ArrayInitialize(Arrow3Down, EMPTY_VALUE);
         ArrayInitialize(Arrow3Up, EMPTY_VALUE);
      }
      ChartRedraw();
   }

   if(sparam == btnAlarmName + "_rect" || sparam == btnAlarmName + "_label")
   {
      alarmEnabled = !alarmEnabled;
      CreateFancyButton(btnAlarmName, 20, 90, btnAlarmLabel);
      ChartRedraw();
   }
}

//+------------------------------------------------------------------+
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 last = rates_total - 1;

   if(btnState)
   {
      double m2[], u2[], l2[];
      if(CopyBuffer(handleBB2, 0, 0, rates_total, m2) <= 0 ||
         CopyBuffer(handleBB2, 1, 0, rates_total, u2) <= 0 ||
         CopyBuffer(handleBB2, 2, 0, rates_total, l2) <= 0)
         return prev_calculated;

      for(int i = 0; i < rates_total; i++)
      {
         BBUpper2[i] = u2[i];
         BBLower2[i] = l2[i];
         bool up = high[i] >= u2[i];
         bool down = low[i] <= l2[i];

         Arrow2Down[i] = up ? high[i] + 2 * _Point : EMPTY_VALUE;
         Arrow2Up[i]   = down ? low[i] - 2 * _Point : EMPTY_VALUE;

         if(i == last && (up || down) && time[i] != lastAlertTime2 && alarmEnabled)
         {
            Alert("2σ touch!");
            lastAlertTime2 = time[i];
         }
      }
   }

   if(btn3State)
   {
      double m3[], u3[], l3[];
      if(CopyBuffer(handleBB3, 0, 0, rates_total, m3) <= 0 ||
         CopyBuffer(handleBB3, 1, 0, rates_total, u3) <= 0 ||
         CopyBuffer(handleBB3, 2, 0, rates_total, l3) <= 0)
         return prev_calculated;

      for(int i = 0; i < rates_total; i++)
      {
         BBUpper3[i] = u3[i];
         BBLower3[i] = l3[i];
         bool up = high[i] >= u3[i];
         bool down = low[i] <= l3[i];

         Arrow3Down[i] = up ? high[i] + 4 * _Point : EMPTY_VALUE;
         Arrow3Up[i]   = down ? low[i] - 4 * _Point : EMPTY_VALUE;

         if(i == last && (up || down) && time[i] != lastAlertTime3 && alarmEnabled)
         {
            Alert("3σ touch!");
            lastAlertTime3 = time[i];
         }
      }
   }

   return rates_total;
}

//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   string btns[] = {btnName, btn3Name, btnAlarmName};
   for(int i = 0; i < ArraySize(btns); i++)
   {
      ObjectDelete(0, btns[i] + "_rect");
      ObjectDelete(0, btns[i] + "_label");
   }

   EventKillTimer();
   if(handleBB2 != INVALID_HANDLE) IndicatorRelease(handleBB2);
   if(handleBB3 != INVALID_HANDLE) IndicatorRelease(handleBB3);
}

void OnTimer() { ChartRedraw(); }

//+------------------------------------------------------------------+
void CreateFancyButton(string baseName, int x, int y, string labelText)
{
   string rect = baseName + "_rect";
   string label = baseName + "_label";

   color bgColor = clrWhite;
   color fontColor = clrBlack;
   color borderColor = clrDarkGray;
   int fontSize = 10;
   int btnWidth = 100;
   int btnHeight = 30;

   bool state = (baseName == btnName)  ? btnState :
                (baseName == btn3Name) ? btn3State : alarmEnabled;

   string prefix = state ? "☑ " : "";
   string fullText = prefix + labelText;

   if(ObjectFind(0, rect) < 0)
      ObjectCreate(0, rect, OBJ_RECTANGLE_LABEL, 0, 0, 0);
   ObjectSetInteger(0, rect, OBJPROP_CORNER, CORNER_LEFT_UPPER);
   ObjectSetInteger(0, rect, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, rect, OBJPROP_YDISTANCE, y);
   ObjectSetInteger(0, rect, OBJPROP_XSIZE, btnWidth);
   ObjectSetInteger(0, rect, OBJPROP_YSIZE, btnHeight);
   ObjectSetInteger(0, rect, OBJPROP_COLOR, borderColor);
   ObjectSetInteger(0, rect, OBJPROP_BGCOLOR, bgColor);
   ObjectSetInteger(0, rect, OBJPROP_STYLE, STYLE_SOLID);
   ObjectSetInteger(0, rect, OBJPROP_WIDTH, 1);
   ObjectSetInteger(0, rect, OBJPROP_SELECTABLE, false);
   ObjectSetInteger(0, rect, OBJPROP_HIDDEN, false);

   uint tw = 0, th = 0;
   TextGetSize(fullText, tw, th);
   int labelX = x + (btnWidth - (int)tw) / 2;
   int labelY = y + (btnHeight - (int)th) / 2 + 2;

   if(ObjectFind(0, label) < 0)
      ObjectCreate(0, label, OBJ_LABEL, 0, 0, 0);
   ObjectSetInteger(0, label, OBJPROP_CORNER, CORNER_LEFT_UPPER);
   ObjectSetInteger(0, label, OBJPROP_XDISTANCE, labelX);
   ObjectSetInteger(0, label, OBJPROP_YDISTANCE, labelY);
   ObjectSetInteger(0, label, OBJPROP_COLOR, fontColor);
   ObjectSetInteger(0, label, OBJPROP_FONTSIZE, fontSize);
   ObjectSetInteger(0, label, OBJPROP_SELECTABLE, false);
   ObjectSetInteger(0, label, OBJPROP_HIDDEN, false);
   ObjectSetString(0, label, OBJPROP_TEXT, fullText);
}
//+------------------------------------------------------------------+


「ボリンジャーバンドの極み」コードを完全解説

#propertyでインジケーターの基本プロパティを設定

コード 意味
#property indicator_chart_window メインチャートにインジケーター描画
#property indicator_buffers 必要なバッファ(箱)を用意、8つ使用
8つのバッファ(箱)に入れる内容
  • +2σのライン
  • -2σのライン
  • +2σのサイン
  • -2σのサイン
  • +3σのライン
  • -3σのライン
  • +3σのサイン
  • -3σのサイン
コード 意味
#property indicator_plots 8 インジケーターで表示する線や矢印の「種類と数」を定義。8つ使用
8つの定義(事項で定義)
  • +2σのライン(DRAW_LINE)
  • -2σのライン(DRAW_LINE)
  • +2σのサイン(DRAW_ARROW)
  • -2σのサイン(DRAW_ARROW)
  • +3σのライン(DRAW_LINE)
  • -3σのライン(DRAW_LINE)
  • +3σのサイン(DRAW_ARROW)
  • -3σのサイン(DRAW_ARROW)
+2σ用ラインの設定
コード 意味
#property indicator_label1 "+2σ" チャート上に表示される名前
#property indicator_type1 DRAW_LINE 線でチャートに描画する
#property indicator_color1 clrDeepSkyBlue 線の色
#property indicator_width1 1 線の太さ
-2σ用ラインの設定
コード 意味
#property indicator_label2 "-2σ" チャート上に表示される名前
#property indicator_type2 DRAW_LINE 線でチャートに描画する
#property indicator_color2 clrDeepSkyBlue 線の色
#property indicator_width2 1 線の太さ
+2σ用矢印の設定
コード 意味
#property indicator_label3 "2σ ↓" チャート上に表示される名前
#property indicator_type3 DRAW_ARROW 矢印でチャートに描画する
#property indicator_color3 clrMediumSlateBlue 矢印の色
#property indicator_width3 2 矢印の太さ
-2σ用矢印の設定
コード 意味
#property indicator_label4 "2σ ↑" チャート上に表示される名前
#property indicator_type4 DRAW_ARROW 矢印でチャートに描画する
#property indicator_color4 clrMediumSlateBlue 矢印の色
#property indicator_width4 2 矢印の太さ
+3σ用ラインの設定
コード 意味
#property indicator_label5 "+3σ" チャート上に表示される名前
#property indicator_type5 DRAW_LINE 線でチャートに描画する
#property indicator_color5 clrLimeGreen 線の色
#property indicator_width5 1 線の太さ
-3σ用ラインの設定
コード 意味
#property indicator_label6 "-3σ" チャート上に表示される名前
#property indicator_type6 DRAW_LINE 線でチャートに描画する
#property indicator_color6 clrLimeGreen 線の色
#property indicator_width6 1 線の太さ
+3σ用矢印の設定
コード 意味
#property indicator_label7 "3σ ↓" チャート上に表示される名前
#property indicator_type7 DRAW_ARROW 矢印でチャートに描画する
#property indicator_color7 clrLimeGreen 矢印の色
#property indicator_width7 2 矢印の太さ
-3σ用矢印の設定
コード 意味
#property indicator_label8 "3σ ↑" チャート上に表示される名前
#property indicator_type8 DRAW_ARROW 矢印でチャートに描画する
#property indicator_color8 clrLimeGreen 矢印の色
#property indicator_width8 2 矢印の太さ
ボリンジャーバンドの期間用
コード 意味
input int BB_Period = 20; ボリンジャーバンドの期間を20にする
バッファの設定

double BBUpper2[], BBLower2[], Arrow2Down[], Arrow2Up[];
double BBUpper3[], BBLower3[], Arrow3Down[], Arrow3Up[];

見やすい様に2つに分けていますが、一つにまとめてもOK

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

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

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

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

ハンドルの設定

int handleBB2 = INVALID_HANDLE;
int handleBB3 = INVALID_HANDLE;

複数のインジケーターを起動する場合、ハンドルで判断させます。ハンドル = インジケーターを操作するための“番号”や“ID”のようなもの。

INVALID_HANDLEでハンドル(ID)が自動で振り当てられます。

意味
  • int:整数型(ハンドル番号を保持)
  • handleBB2:2σ用のボリンジャーバンドインジケーターのハンドル名
  • INVALID_HANDLE:まだインジケーターが作られていないことを示す特別な値(-1)
ボタンの設定(2σ)
コード 意味
bool btnState = false; ボタンの初期はOFFに
string btnName = "Btn1"; ボタンの名前
string btnLabel = "BB(2σ)"; ボタンの表示名
ボタンの設定(3σ)
コード 意味
bool btn3State = false; ボタンの初期はOFFに
string btn3Name = "BtnBB3"; ボタンの名前
string btn3Label = "BB(3σ)"; ボタンの表示名
ボタンの設定(アラート)
コード 意味
bool alarmEnabled = false; ボタンの初期はOFFに
string btnAlarmName = "BtnAlarm"; ボタンの名前
string btnAlarmLabel = "アラート"; ボタンの表示名

OnInit()で初期値の設定

int OnInit(){}
説明
インジケーターがチャートに読み込まれたときに最初に1回だけ実行される初期化関数です。
SetIndexBuffer(0, BBUpper2, INDICATOR_DATA);
SetIndexBuffer(1, BBLower2, INDICATOR_DATA);
SetIndexBuffer(2, Arrow2Down, INDICATOR_DATA);
SetIndexBuffer(3, Arrow2Up, INDICATOR_DATA);
SetIndexBuffer(4, BBUpper3, INDICATOR_DATA);
SetIndexBuffer(5, BBLower3, INDICATOR_DATA);
SetIndexBuffer(6, Arrow3Down, INDICATOR_DATA);
SetIndexBuffer(7, Arrow3Up, INDICATOR_DATA);
説明

SetIndexBufferは、「このプロットに、このデータ配列を使って描画する」とMetaTraderに伝える関数です。

※プロットとは、チャートに表示される「線」や「矢印」などの1つ1つの表示パーツのことです。

SetIndexBuffer(0, BBUpper2, INDICATOR_DATA);の場合
  • 0番目のプロットに
  • BBUpper2[] の値を使って
  • インジケーターデータとして描画する
PlotIndexSetInteger(2, PLOT_ARROW, 234);
PlotIndexSetInteger(3, PLOT_ARROW, 233);
PlotIndexSetInteger(6, PLOT_ARROW, 234);
PlotIndexSetInteger(7, PLOT_ARROW, 233);
説明
PlotIndexSetIntegerは、「このプロットの表示スタイル(矢印の種類など)を設定する」ための関数です。
PlotIndexSetInteger(2, PLOT_ARROW, 234);の場合
  • 2番目のプロットに
  • 「矢印の種類:234(↓)」を使って表示
handleBB2 = iBands(_Symbol, _Period, BB_Period, 0, 2.0, PRICE_CLOSE);
handleBB3 = iBands(_Symbol, _Period, BB_Period, 0, 3.0, PRICE_CLOSE);
説明
handleBB2 = iBands(_Symbol, _Period, BB_Period, 0, 2.0, PRICE_CLOSE);の場合

「2σのボリンジャーバンドを使いたい」とMetaTraderにお願いして、そのID(番号)を handleBB2に貰っている。

handleBB3 = iBands(_Symbol, _Period, BB_Period, 0, 3.0, PRICE_CLOSE);の場合

「3σのボリンジャーバンドを使いたい」とMetaTraderにお願いして、そのID(番号)を handleBB3に貰っている。

iBands(...)
ボリンジャーバンド(Bollinger Bands)を計算するためのインジケーターハンドルを作成する関数です。
MetaTrader(MQL5)に「この設定でボリンジャーバンドを使いたい」と伝える役割を持ちます。
引数 説明
_Symbol 現在の通貨ペア
_Period 現在の時間足
BB_Period ボリンジャーバンドの計算期間(例:20本)
0 シフト(通常は0)
2.0 標準偏差(=2σ)
PRICE_CLOSE 終値を基に計算する
エラー処理
if(handleBB2 == INVALID_HANDLE || handleBB3 == INVALID_HANDLE)
{
Print("BB handle creation failed: ", GetLastError());
return INIT_FAILED;
}
説明
2σか3σのどちらかでも作れなかったら、エラー内容を出して初期化を止める処理です。
コード 意味
||(論理OR) どちらか1つでも INVALID_HANDLE なら条件は true
INVALID_HANDLE まだインジケーターが作られていないことを示す特別な値(-1)
Print(...) エラーメッセージと直前のエラーコードを表示
GetLastError() 最後に起きたエラーのコードを取得
return INIT_FAILED インジケーターの初期化失敗を宣言 → OnInit() を中止
ラベル(ボタン)を配置
CreateFancyButton(btnName, 20, 20, btnLabel);
CreateFancyButton(btn3Name, 20, 55, btn3Label);
CreateFancyButton(btnAlarmName, 20, 90, btnAlarmLabel);
説明
このインジケーターではラベルをボタンの様に配置してしています。
※CreateFancyButton()は自作の関数で、このページの最後に説明しています。
その他
EventSetTimer(1);
説明
EventSetTimer(1) は、1秒おきに OnTimer() を実行し、ボタンの状態を常に正しく表示するための仕組みです。

return INIT_SUCCEEDED;
説明
インジケーターの初期化が正常に完了したことを MetaTrader に伝える命令です。

OnChartEvent()でボタンのクリック処理

void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)
説明
OnChartEvent() は、チャート上での操作(特にボタンクリック)に反応して動くイベント処理関数です。
引数 説明
id イベントの種類(例:CHARTEVENT_OBJECT_CLICK)
lparam イベントの追加情報(使わないことが多い)
dparam イベントの追加情報(使わないことが多い)
sparam イベントに関連するオブジェクト名(例:"Btn1_rect")
if(id != CHARTEVENT_OBJECT_CLICK) return;

if(sparam == btnName + "_rect" || sparam == btnName + "_label")
{
btnState = !btnState;
CreateFancyButton(btnName, 20, 20, btnLabel);
if(!btnState)
{
ArrayInitialize(BBUpper2, EMPTY_VALUE);
ArrayInitialize(BBLower2, EMPTY_VALUE);
ArrayInitialize(Arrow2Down, EMPTY_VALUE);
ArrayInitialize(Arrow2Up, EMPTY_VALUE);
}
ChartRedraw();
}

説明
2σボタンがクリックされたとき、状態(ON/OFF)を切り替えて表示を更新する処理です。

if(id != CHARTEVENT_OBJECT_CLICK) return;

クリックイベント以外なら何もしないで終了。

if(sparam == btnName + "_rect" || sparam == btnName + "_label")

👉 クリックされたオブジェクト名(sparam)が「2σボタン」の「四角い図形」または「ラベル」だった場合だけ、処理を実行します。

※ボタンは背景と文字の2つでできているので、どちらがクリックされても反応するようにしています。

コード 意味
sparam クリックされたものの名前
btnName + "_rect" ボタンの背景(四角い図形)
btnName + "_label" ボタンの文字部分
btnState = !btnState; ボタンの状態を反転(ON ↔ OFF)例:☐ → ☑、☑ → ☐
CreateFancyButton(btnName, 20, 20, btnLabel); ボタンの表示を更新(☑やテキストを反映)
if(!btnState)
{
ArrayInitialize(BBUpper2, EMPTY_VALUE);
ArrayInitialize(BBLower2, EMPTY_VALUE);
ArrayInitialize(Arrow2Down, EMPTY_VALUE);
ArrayInitialize(Arrow2Up, EMPTY_VALUE);
}
説明
OFFにしたときは、2σのラインや矢印をすべて非表示にする(=チャートから消す)
if(sparam == btn3Name + "_rect" || sparam == btn3Name + "_label")
{
btn3State = !btn3State;
CreateFancyButton(btn3Name, 20, 55, btn3Label);
if(!btn3State)
{
ArrayInitialize(BBUpper3, EMPTY_VALUE);
ArrayInitialize(BBLower3, EMPTY_VALUE);
ArrayInitialize(Arrow3Down, EMPTY_VALUE);
ArrayInitialize(Arrow3Up, EMPTY_VALUE);
}
ChartRedraw();
}

if(sparam == btnAlarmName + "_rect" || sparam == btnAlarmName + "_label")
{
alarmEnabled = !alarmEnabled;
CreateFancyButton(btnAlarmName, 20, 90, btnAlarmLabel);
ChartRedraw();
}
}

説明
3σボタンがクリックされたとき、状態(ON/OFF)を切り替えて表示を更新する処理です。

if(id != CHARTEVENT_OBJECT_CLICK) return;

クリックイベント以外なら何もしないで終了。

if(sparam == btnName + "_rect" || sparam == btnName + "_label")

👉 クリックされたオブジェクト名(sparam)が「3σボタン」の「四角い図形」または「ラベル」だった場合だけ、処理を実行します。

※ボタンは背景と文字の2つでできているので、どちらがクリックされても反応するようにしています。

コード 意味
sparam クリックされたものの名前
btnName + "_rect" ボタンの背景(四角い図形)
btnName + "_label" ボタンの文字部分
btnState = !btnState; ボタンの状態を反転(ON ↔ OFF)例:☐ → ☑、☑ → ☐
CreateFancyButton(btnName, 20, 90, btnLabel); ボタンの表示を更新(☑やテキストを反映)
if(!btnState)
{
ArrayInitialize(BBUpper3, EMPTY_VALUE);
ArrayInitialize(BBLower3, EMPTY_VALUE);
ArrayInitialize(Arrow3Down, EMPTY_VALUE);
ArrayInitialize(Arrow3Up, EMPTY_VALUE);
}
説明
OFFにしたときは、3σのラインや矢印をすべて非表示にする
(=チャートから消す)
ChartRedraw();
説明
今の状態をチャートに即時反映させる(画面更新)

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 は、インジケーターの表示データをチャート上に計算・描画するためのメイン処理関数です。

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[] スプレッド(Bid-Askの差)
int last = rates_total - 1;
説明
一番新しいバー(=直近のローソク足)のインデックス番号を取得するための変数です。
コード 意味
rates_total バー(ローソク足)の本数。1本目はインデックス0
rates_total - 1 最後のバーのインデックス番号(=最新の足)
if(btnState){
double m2[], u2[], l2[];
if(CopyBuffer(handleBB2, 0, 0, rates_total, m2) <= 0 ||CopyBuffer(handleBB2, 1, 0, rates_total, u2) <= 0 ||CopyBuffer(handleBB2, 2, 0, rates_total, l2) <= 0)
return prev_calculated;
for(int i = 0; i < rates_total; i++){
BBUpper2[i] = u2[i];
BBLower2[i] = l2[i];
bool up = high[i] >= u2[i];
bool down = low[i] <= l2[i];
Arrow2Down[i] = up ? high[i] + 2 * _Point : EMPTY_VALUE;
Arrow2Up[i] = down ? low[i] - 2 * _Point : EMPTY_VALUE;
if(i == last && (up || down) && time[i] != lastAlertTime2 && alarmEnabled)
{
Alert("2σ touch!");
lastAlertTime2 = time[i];
}
}
}
説明
2σボタンがONのとき、2σボリンジャーバンドの値を取得し、全バーに対してラインと矢印を描画、最新バーでタッチがあればアラートを1回だけ鳴らします。
if(btnState)
説明
2σボタンがONになっているか?」を確認
double m2[], u2[], l2[];
説明
中央線(m2)、上バンド(u2)、下バンド(l2)を一時的に入れる配列。

if(CopyBuffer(handleBB2, 0, 0, rates_total, m2) <= 0 ||CopyBuffer(handleBB2, 1, 0, rates_total, u2) <= 0 ||CopyBuffer(handleBB2, 2, 0, rates_total, l2) <= 0) return prev_calculated;

説明
2σのバンド値をインジケーターから取得。上・下・中央が1つでも取得できなければ中止(return prev_calculated;)。

for(int i = 0; i < rates_total; i++)

説明
すべてのバー(ローソク足)について処理を行う。

BBUpper2[i] = u2[i];
BBLower2[i] = l2[i];

説明
上下バンドの値を描画用バッファに代入(チャートに表示される)。

bool up = high[i] >= u2[i];
bool down = low[i] <= l2[i];

説明
ローソク足が2σバンドにタッチしたかどうかを判定

up:高値が上バンドを超えた⇒ ↓サイン

down:安値が下バンドを割った⇒ ↑サイン

Arrow2Down[i] = up ? high[i] + 2 * _Point : EMPTY_VALUE;
Arrow2Up[i] = down ? low[i] - 2 * _Point : EMPTY_VALUE;
説明
  • 条件:down(安値が下バンドに触れたか)
  • trueなら:ローソク足の安値の少し下に↑矢印を表示
  • falseなら:何も表示しない

_Point とは?通貨の最小単位(例:USD/JPYなら 0.01、EUR/USDなら 0.00001)

2 * _Point は矢印の位置をローソク足と重ならないように上下にずらすための微調整です。

if(i == last && (up || down) && time[i] != lastAlertTime2 && alarmEnabled)
{
Alert("2σ touch!");
lastAlertTime2 = time[i];
}
説明
「今の足が2σに触れて、まだアラートを鳴らしておらず、アラート機能がONなら、アラートを鳴らす」処理です。
条件 意味
i == last 今チェック中のバーが一番新しい足(最新のローソク足)であること
up || down 2σの上か下のバンドにタッチしていること
time[i] != lastAlertTime2 このバーではまだアラートを鳴らしていない(重複防止)
alarmEnabled アラートボタンがONの状態になっていること
if(btn3State)
{
double m3[], u3[], l3[];

if(CopyBuffer(handleBB3, 0, 0, rates_total, m3) <= 0 ||
CopyBuffer(handleBB3, 1, 0, rates_total, u3) <= 0 ||
CopyBuffer(handleBB3, 2, 0, rates_total, l3) <= 0)
return prev_calculated;
for(int i = 0; i < rates_total; i++)
{
BBUpper3[i] = u3[i];
BBLower3[i] = l3[i];
bool up = high[i] >= u3[i];
bool down = low[i] <= l3[i];
Arrow3Down[i] = up ? high[i] + 4 * _Point : EMPTY_VALUE;
Arrow3Up[i] = down ? low[i] - 4 * _Point : EMPTY_VALUE;
if(i == last && (up || down) && time[i] != lastAlertTime3 && alarmEnabled)
{
Alert("3σ touch!");
lastAlertTime3 = time[i];
}
}
}

return rates_total;
}

OnDeinit()で削除処理

void OnDeinit(const int reason)
{
string btns[] = {btnName, btn3Name, btnAlarmName};
for(int i = 0; i < ArraySize(btns); i++) { ObjectDelete(0, btns[i] + "_rect"); ObjectDelete(0, btns[i] + "_label"); } EventKillTimer(); if(handleBB2 != INVALID_HANDLE) IndicatorRelease(handleBB2); if(handleBB3 != INVALID_HANDLE) IndicatorRelease(handleBB3); } void OnTimer() { ChartRedraw(); }
説明
OnDeinit() は、インジケーター終了時にボタンやハンドルなどをきれいに削除して、システムリソースを無駄にしないための後処理です。
string btns[] = {btnName, btn3Name, btnAlarmName};
説明
3つのボタン名(2σ・3σ・アラート)を配列にまとめます。
for(int i = 0; i < ArraySize(btns); i++) { ObjectDelete(0, btns[i] + "_rect"); ObjectDelete(0, btns[i] + "_label"); }
説明
  • ボタンの部品(背景の四角と文字)を削除します。
  • 3つのボタン × 2部品ずつ(合計6オブジェクト)をキレイに消します。
EventKillTimer();
説明
EventSetTimer() で設定した定期タイマーを停止します。
if(handleBB2 != INVALID_HANDLE) IndicatorRelease(handleBB2);
if(handleBB3 != INVALID_HANDLE) IndicatorRelease(handleBB3);
説明
2σ・3σのボリンジャーバンドハンドルを解放します。
無効(-1)でない場合のみ、リソースを正しく返却します。
void OnTimer() { ChartRedraw(); }
説明
1秒ごとにチャートを再描画する処理です(EventSetTimer(1); に対応)。

・主に ボタン表示が崩れたり消えたりしないように安定して表示させるための補助処理です。
・土日やチャートが止まっている時間でも、UIが維持されます。

OnTimer() は、チャートの表示(ボタンなど)を定期的に更新して、常に正しく見えるようにするための再描画処理です。

CreateFancyButto()独自関数ラベルのボタン
void CreateFancyButton(string baseName, int x, int y, string labelText)
{
string rect = baseName + "_rect";
string label = baseName + "_label";

color bgColor = clrWhite;
color fontColor = clrBlack;
color borderColor = clrDarkGray;
int fontSize = 10;
int btnWidth = 100;
int btnHeight = 30;

bool state = (baseName == btnName) ? btnState :
(baseName == btn3Name) ? btn3State : alarmEnabled;

string prefix = state ? "☑ " : "";
string fullText = prefix + labelText;

if(ObjectFind(0, rect) < 0)  
ObjectCreate(0, rect, OBJ_RECTANGLE_LABEL, 0, 0, 0);
ObjectSetInteger(0, rect, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, rect, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, rect, OBJPROP_YDISTANCE, y);
ObjectSetInteger(0, rect, OBJPROP_XSIZE, btnWidth);
ObjectSetInteger(0, rect, OBJPROP_YSIZE, btnHeight);
ObjectSetInteger(0, rect, OBJPROP_COLOR, borderColor);
ObjectSetInteger(0, rect, OBJPROP_BGCOLOR, bgColor);
ObjectSetInteger(0, rect, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, rect, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, rect, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, rect, OBJPROP_HIDDEN, false);

uint tw = 0, th = 0;
TextGetSize(fullText, tw, th);
int labelX = x + (btnWidth - (int)tw) / 2;
int labelY = y + (btnHeight - (int)th) / 2 + 2;

if(ObjectFind(0, label) < 0)
ObjectCreate(0, label, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, label, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, label, OBJPROP_XDISTANCE, labelX);
ObjectSetInteger(0, label, OBJPROP_YDISTANCE, labelY);
ObjectSetInteger(0, label, OBJPROP_COLOR, fontColor);
ObjectSetInteger(0, label, OBJPROP_FONTSIZE, fontSize);
ObjectSetInteger(0, label, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, label, OBJPROP_HIDDEN, false);
ObjectSetString(0, label, OBJPROP_TEXT, fullText);
}

ラベルをボタンの様に見せる為の独自関数になります。

通常のボタンより記述する事が多くなるのですが、ボタンより見た目のカスタマイズが用意なので採用しています。

void CreateFancyButton(string baseName, int x, int y, string labelText)

引数 説明
baseName ボタンの識別名(例:"Btn1")
x, y 表示位置(左上からの距離)
labelText ボタンに表示する文字(例:"BB(2σ)")
string rect = baseName + "_rect";
string label = baseName + "_label";
説明
背景(四角)と文字(ラベル)を区別するため、別々のオブジェクト名を作成します。
color bgColor = clrWhite;
color fontColor = clrBlack;
color borderColor = clrDarkGray;
int fontSize = 10;
int btnWidth = 100;
int btnHeight = 30;
説明
ボタンの背景・文字・枠線の色、文字サイズやボタンの幅・高さを定義。
bool state = (baseName == btnName) ? btnState :
(baseName == btn3Name) ? btn3State : alarmEnabled;
string prefix = state ? "☑ " : "";
string fullText = prefix + labelText;
説明
ボタンのチェック状態(ON/OFF)に応じて、「☑」マークを付けるかどうかを決めて、最終的な表示テキストを作るための処理です。
baseName(ボタン名)がどれなのかを確認
  • もし "Btn1"(2σボタン)なら → btnState(ON/OFF)
  • もし "BtnBB3"(3σボタン)なら → btn3State
  • それ以外(=アラートボタン)なら → alarmEnabled

つまり、それぞれのボタンの現在のON/OFF状態を取得して、state に代入しています。

string prefix = state ? "☑ " : "";
  • state が true(ON)なら "☑ " を付ける
  • false(OFF)なら何も付けない(空文字)

→ チェックマークを表示するかどうかを決めています。

string fullText = prefix + labelText;
"☑ "(または空)と、元のラベル文字(例:"BB(2σ)")をつなげて、最終的に表示するテキストを作成
ObjectCreate(0, rect, OBJ_RECTANGLE_LABEL, 0, 0, 0);
説明
ボタンの背景となる白い四角を作成。位置や色、サイズを細かく設定。
TextGetSize(fullText, tw, th);
int labelX = x + (btnWidth - (int)tw) / 2;
int labelY = y + (btnHeight - (int)th) / 2 + 2;
説明
テキストがボタンの中央にくるように位置調整(+2は微調整)
ObjectCreate(0, label, OBJ_LABEL, 0, 0, 0);
説明
チェックマーク付きのテキストをラベルとして表示。フォントサイズや色も指定。

CreateFancyButton() は、「☑ BB(2σ)」のような見た目のボタンをチャート上に作る関数で、四角とラベルを組み合わせ、ON/OFF表示に対応したUIを構築します。

タイトルとURLをコピーしました