ボリンジャーバンドにタッチした瞬間、即座にサイン表示&アラート通知!
MT5対応の無料インジケーター「ボリンジャーバンドの極み」は、2σ・3σタッチを視覚と音でわかりやすく知らせてくれるサインツールです。
±2σ・±3σのライン表示やタッチ時の矢印サイン、アラートON/OFFをすべてボタンで簡単に切り替え可能。
本記事では、インジケーターの導入方法から詳しいMQL5のコード解説までを完全網羅。実際に使えるソースコードも無料公開しています。
MT5でのボリバン活用をさらに強化したい方は、ぜひご活用ください。

この記事はサインツールの作り方を紹介する趣旨で作っています。ボリンジャーバンドにタッチしたからと言って必ず反発する訳ではありません。エントリー目的では無く、タッチした後どの様な動きをするか、学習用としてご利用下さい。
サインツール「ボリンジャーバンドの極み」の入れ方
まずは、下記ボタンより「ボリンジャーバンドの極み」をダウンロードします。
ダウンロードファイルはzipになっており、解凍を行うと「bbnokiwami.ex5」と言うファイルが入っています。
bbnokiwami.ex5をMT5に入れる事で使用する事が出来ます。
bbnokiwami.ex5ダウンロード後、MT5を開きます。
MT5のメニューより「ファイル」⇒「データフォルダを開く」を選択します。
「MQL5」を選択します。
「Indicators」を選択します。
「Indicators」の中に「bbnokiwami.ex5」をドラッグ&ドロップで入れます。
ナビゲーターの中に「bbnokiwami」があるので「bbnokiwami」をダブルクリックします。
ポップアップが表示されるので「OK」ボタンをクリックします。
ボリンジャーバンドの極みが起動します。
サインツール「ボリンジャーバンドの極み」の使い方
BB(2σ)をボタンを押すと、ボタンに☑マークが付きます。
±2σのボリンジャーバンドが表示され、高値・安値が±2σのラインをタッチするとサインが表示されます。
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つ使用 |
- +2σのライン
- -2σのライン
- +2σのサイン
- -2σのサイン
- +3σのライン
- -3σのライン
- +3σのサイン
- -3σのサイン
コード | 意味 |
---|---|
#property indicator_plots 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)
コード | 意味 |
---|---|
#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 | 矢印の太さ |
コード | 意味 |
---|---|
#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; | ボリンジャーバンドの期間を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)
コード | 意味 |
---|---|
bool btnState = false; | ボタンの初期はOFFに |
string btnName = "Btn1"; | ボタンの名前 |
string btnLabel = "BB(2σ)"; | ボタンの表示名 |
コード | 意味 |
---|---|
bool btn3State = false; | ボタンの初期はOFFに |
string btn3Name = "BtnBB3"; | ボタンの名前 |
string btn3Label = "BB(3σ)"; | ボタンの表示名 |
コード | 意味 |
---|---|
bool alarmEnabled = false; | ボタンの初期はOFFに |
string btnAlarmName = "BtnAlarm"; | ボタンの名前 |
string btnAlarmLabel = "アラート"; | ボタンの表示名 |
OnInit()で初期値の設定
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つの表示パーツのことです。
- 0番目のプロットに
- BBUpper2[] の値を使って
- インジケーターデータとして描画する
PlotIndexSetInteger(3, PLOT_ARROW, 233);
PlotIndexSetInteger(6, PLOT_ARROW, 234);
PlotIndexSetInteger(7, PLOT_ARROW, 233);
- 2番目のプロットに
- 「矢印の種類:234(↓)」を使って表示
handleBB3 = iBands(_Symbol, _Period, BB_Period, 0, 3.0, PRICE_CLOSE);
「2σのボリンジャーバンドを使いたい」とMetaTraderにお願いして、そのID(番号)を handleBB2に貰っている。
handleBB3 = iBands(_Symbol, _Period, BB_Period, 0, 3.0, PRICE_CLOSE);の場合
「3σのボリンジャーバンドを使いたい」とMetaTraderにお願いして、そのID(番号)を handleBB3に貰っている。
MetaTrader(MQL5)に「この設定でボリンジャーバンドを使いたい」と伝える役割を持ちます。
引数 | 説明 |
---|---|
_Symbol | 現在の通貨ペア |
_Period | 現在の時間足 |
BB_Period | ボリンジャーバンドの計算期間(例:20本) |
0 | シフト(通常は0) |
2.0 | 標準偏差(=2σ) |
PRICE_CLOSE | 終値を基に計算する |
{
Print("BB handle creation failed: ", GetLastError());
return INIT_FAILED;
}
コード | 意味 |
---|---|
||(論理OR) | どちらか1つでも INVALID_HANDLE なら条件は true |
INVALID_HANDLE | まだインジケーターが作られていないことを示す特別な値(-1) |
Print(...) | エラーメッセージと直前のエラーコードを表示 |
GetLastError() | 最後に起きたエラーのコードを取得 |
return INIT_FAILED | インジケーターの初期化失敗を宣言 → OnInit() を中止 |
CreateFancyButton(btn3Name, 20, 55, btn3Label);
CreateFancyButton(btnAlarmName, 20, 90, btnAlarmLabel);
※CreateFancyButton()は自作の関数で、このページの最後に説明しています。
OnChartEvent()でボタンのクリック処理
引数 | 説明 |
---|---|
id | イベントの種類(例:CHARTEVENT_OBJECT_CLICK) |
lparam | イベントの追加情報(使わないことが多い) |
dparam | イベントの追加情報(使わないことが多い) |
sparam | イベントに関連するオブジェクト名(例:"Btn1_rect") |
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(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); | ボタンの表示を更新(☑やテキストを反映) |
{
ArrayInitialize(BBUpper2, EMPTY_VALUE);
ArrayInitialize(BBLower2, EMPTY_VALUE);
ArrayInitialize(Arrow2Down, EMPTY_VALUE);
ArrayInitialize(Arrow2Up, EMPTY_VALUE);
}
{
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();
}
}
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); | ボタンの表示を更新(☑やテキストを反映) |
{
ArrayInitialize(BBUpper3, EMPTY_VALUE);
ArrayInitialize(BBLower3, EMPTY_VALUE);
ArrayInitialize(Arrow3Down, EMPTY_VALUE);
ArrayInitialize(Arrow3Up, EMPTY_VALUE);
}
(=チャートから消す)
OnCalculate()でメイン処理
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[])
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の差) |
コード | 意味 |
---|---|
rates_total | バー(ローソク足)の本数。1本目はインデックス0 |
rates_total - 1 | 最後のバーのインデックス番号(=最新の足) |
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(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];
up:高値が上バンドを超えた⇒ ↓サイン
down:安値が下バンドを割った⇒ ↑サイン
Arrow2Up[i] = down ? low[i] - 2 * _Point : EMPTY_VALUE;
- 条件:down(安値が下バンドに触れたか)
- trueなら:ローソク足の安値の少し下に↑矢印を表示
- falseなら:何も表示しない
_Point とは?通貨の最小単位(例:USD/JPYなら 0.01、EUR/USDなら 0.00001)
2 * _Point は矢印の位置をローソク足と重ならないように上下にずらすための微調整です。
{
Alert("2σ touch!");
lastAlertTime2 = time[i];
}
条件 | 意味 |
---|---|
i == last | 今チェック中のバーが一番新しい足(最新のローソク足)であること |
up || down | 2σの上か下のバンドにタッチしていること |
time[i] != lastAlertTime2 | このバーではまだアラートを鳴らしていない(重複防止) |
alarmEnabled | アラートボタンがONの状態になっていること |
{
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()で削除処理
{
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(); }
- ボタンの部品(背景の四角と文字)を削除します。
- 3つのボタン × 2部品ずつ(合計6オブジェクト)をキレイに消します。
if(handleBB3 != INVALID_HANDLE) IndicatorRelease(handleBB3);
無効(-1)でない場合のみ、リソースを正しく返却します。
・主に ボタン表示が崩れたり消えたりしないように安定して表示させるための補助処理です。
・土日やチャートが止まっている時間でも、UIが維持されます。
OnTimer() は、チャートの表示(ボタンなど)を定期的に更新して、常に正しく見えるようにするための再描画処理です。
{
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 label = baseName + "_label";
color fontColor = clrBlack;
color borderColor = clrDarkGray;
int fontSize = 10;
int btnWidth = 100;
int btnHeight = 30;
(baseName == btn3Name) ? btn3State : alarmEnabled;
string prefix = state ? "☑ " : "";
string fullText = prefix + labelText;
- もし "Btn1"(2σボタン)なら → btnState(ON/OFF)
- もし "BtnBB3"(3σボタン)なら → btn3State
- それ以外(=アラートボタン)なら → alarmEnabled
つまり、それぞれのボタンの現在のON/OFF状態を取得して、state に代入しています。
- state が true(ON)なら "☑ " を付ける
- false(OFF)なら何も付けない(空文字)
→ チェックマークを表示するかどうかを決めています。
int labelX = x + (btnWidth - (int)tw) / 2;
int labelY = y + (btnHeight - (int)th) / 2 + 2;
CreateFancyButton() は、「☑ BB(2σ)」のような見た目のボタンをチャート上に作る関数で、四角とラベルを組み合わせ、ON/OFF表示に対応したUIを構築します。