MQL5でサインツールを作成する際に課題となりやすいのが、「サインの切り替え」です。
単一のサインだけを表示するのであれば、ボタンを使う必要はありませんが、複数の条件で異なるサインを表示したい場合には、ボタンを設置することで操作性が格段に向上します。
今回のサンプルでは「陽線のみにサインを表示する」処理をしていますが、このツールの本質的なテーマは『ボタンの活用』にあります。
サインの条件については、どんなものでも構いませんので、ご自身で作成したサイン表示のロジックを当てはめて試してみてください。
サインツールの動作
サインツールを立ち上げると画面左上に「現在サイン非表示中⇒サイン表示へ」ボタンがあるのでそちらをクリックします。
ボタンをクリックすると、陽線のみにサインが表示されます。ボタンの表示が「現在サイン表示中⇒サイン非表示へ」に変更されます。
もう一度ボタンをクリックするとサインが非表示になります。
ボタンのON・OFFでサインを出すサインツールのコード
//+------------------------------------------------------------------+
//| ボタン付きインジケーター |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1
#property strict
#property indicator_type1 DRAW_ARROW
#property indicator_color1 clrDeepSkyBlue
#property indicator_width1 2
#property indicator_label1 "BullishSignal"
input int ArrowOffset = 10;
double SignalBuffer[];
double close[], open[], low[];
bool showSignal = false; // 表示ON/OFFの状態を管理
string toggleButtonName = "ShowSignalButton";
//+------------------------------------------------------------------+
int OnInit()
{
SetIndexBuffer(0, SignalBuffer, INDICATOR_DATA);
PlotIndexSetInteger(0, PLOT_ARROW, 233); // 矢印コード
ArrayInitialize(SignalBuffer, EMPTY_VALUE);
CreateToggleButton();
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const int begin,
const double &price[])
{
if (rates_total < 2)
return rates_total;
if (!showSignal)
return rates_total;
if (!CopyClose(_Symbol, _Period, 0, rates_total, close) ||
!CopyOpen(_Symbol, _Period, 0, rates_total, open) ||
!CopyLow(_Symbol, _Period, 0, rates_total, low))
return rates_total;
int start = MathMax(prev_calculated - 1, 1);
for (int i = start; i < rates_total; i++)
{
SignalBuffer[i] = (close[i] > open[i]) ? (low[i] - ArrowOffset * _Point) : EMPTY_VALUE;
}
return rates_total;
}
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
if (id == CHARTEVENT_OBJECT_CLICK)
{
if (sparam == toggleButtonName)
{
showSignal = !showSignal; // 表示状態を反転
ArrayInitialize(SignalBuffer, EMPTY_VALUE); // サイン消去
if (showSignal)
RedrawSignals();
UpdateToggleButtonText();
}
}
}
//+------------------------------------------------------------------+
void RedrawSignals()
{
int rates_total = Bars(_Symbol, _Period);
if (rates_total < 2)
return;
if (!CopyClose(_Symbol, _Period, 0, rates_total, close) ||
!CopyOpen(_Symbol, _Period, 0, rates_total, open) ||
!CopyLow(_Symbol, _Period, 0, rates_total, low))
return;
for (int i = 1; i < rates_total; i++)
{
if (close[i] > open[i])
SignalBuffer[i] = low[i] - ArrowOffset * _Point;
else
SignalBuffer[i] = EMPTY_VALUE;
}
}
//+------------------------------------------------------------------+
void CreateToggleButton()
{
ObjectDelete(0, toggleButtonName);
ObjectCreate(0, toggleButtonName, OBJ_BUTTON, 0, 0, 0);
ObjectSetInteger(0, toggleButtonName, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, toggleButtonName, OBJPROP_XDISTANCE, 10);
ObjectSetInteger(0, toggleButtonName, OBJPROP_YDISTANCE, 50);
ObjectSetInteger(0, toggleButtonName, OBJPROP_XSIZE, 250);
ObjectSetInteger(0, toggleButtonName, OBJPROP_YSIZE, 30);
ObjectSetInteger(0, toggleButtonName, OBJPROP_COLOR, clrWhite);
ObjectSetInteger(0, toggleButtonName, OBJPROP_BGCOLOR, clrSlateGray);
ObjectSetInteger(0, toggleButtonName, OBJPROP_BORDER_TYPE, BORDER_RAISED);
ObjectSetInteger(0, toggleButtonName, OBJPROP_FONTSIZE, 12);
ObjectSetInteger(0, toggleButtonName, OBJPROP_HIDDEN, false);
UpdateToggleButtonText();
}
//+------------------------------------------------------------------+
void UpdateToggleButtonText()
{
string text = showSignal
? "現在サイン表示中⇒サイン非表示へ"
: "現在サイン非表示中⇒サイン表示へ";
ObjectSetString(0, toggleButtonName, OBJPROP_TEXT, text);
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
ObjectDelete(0, toggleButtonName);
}