MQL4MQL5 EA(エキスパートアドバイザー) オブジェクト・画面
チャートにボタンを置いて、押したら注文したい
結論:OBJ_BUTTON を作り、OnChartEvent() で CHARTEVENT_OBJECT_CLICK を受け取ってボタン名を判定します。
考え方
ボタン(OBJ_BUTTON)を押すと、OnChartEvent() が「オブジェクトがクリックされた」というイベントで呼ばれます。sparam にボタンの名前が入るので、どのボタンかを判定して処理します。ここでは「買い」「売り」「全決済」の3つのボタンを置く EA を例にしています。
- OnInit() でボタンを作り、位置・大きさ・文字・色を設定する
- OnChartEvent() で id が CHARTEVENT_OBJECT_CLICK のとき、sparam(ボタン名)で処理を分ける
- 押されたボタンは押された状態のままになるので、OBJPROP_STATE を false に戻す
- OnDeinit() でボタンを削除する
そのまま使えるコード
MetaEditor の「新規作成」で「エキスパートアドバイザ(テンプレート)」を選び、できたファイルの中身をすべてこのコードに置き換えてコンパイル(F7)します。ファイルは Experts フォルダに保存され、ナビゲーターからチャートにドラッグして使います。
MQL4(MT4)
#property strict
// 「買い」「売り」「全決済」ボタンを置く EA(MT4)
input double InpLots = 0.1; // ロット
input int InpMagic = 20240; // マジックナンバー
void MakeButton(string name, string text, int x, color bg)
{
ObjectCreate(0, name, OBJ_BUTTON, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, 30);
ObjectSetInteger(0, name, OBJPROP_XSIZE, 90);
ObjectSetInteger(0, name, OBJPROP_YSIZE, 32);
ObjectSetInteger(0, name, OBJPROP_BGCOLOR, bg);
ObjectSetInteger(0, name, OBJPROP_COLOR, clrWhite);
ObjectSetString(0, name, OBJPROP_TEXT, text);
}
int OnInit()
{
MakeButton("BtnBuy", "買い", 10, clrRoyalBlue);
MakeButton("BtnSell", "売り", 110, clrCrimson);
MakeButton("BtnClose", "全決済", 210, clrDimGray);
return INIT_SUCCEEDED;
}
void OnDeinit(const int reason)
{
ObjectDelete(0, "BtnBuy");
ObjectDelete(0, "BtnSell");
ObjectDelete(0, "BtnClose");
}
void OnTick()
{
}
void CloseAll()
{
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
if(OrderSymbol() != _Symbol || OrderMagicNumber() != InpMagic || OrderType() > OP_SELL) continue;
if(!OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 30))
Print("決済失敗 error=", GetLastError());
}
}
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
if(id != CHARTEVENT_OBJECT_CLICK) return;
if(sparam == "BtnBuy")
{
if(OrderSend(_Symbol, OP_BUY, InpLots, Ask, 30, 0, 0, "button", InpMagic) < 0)
Print("買い失敗 error=", GetLastError());
}
else if(sparam == "BtnSell")
{
if(OrderSend(_Symbol, OP_SELL, InpLots, Bid, 30, 0, 0, "button", InpMagic) < 0)
Print("売り失敗 error=", GetLastError());
}
else if(sparam == "BtnClose")
CloseAll();
else
return;
ObjectSetInteger(0, sparam, OBJPROP_STATE, false); // 押された状態を戻す
ChartRedraw();
}MQL5(MT5)
// 「買い」「売り」「全決済」ボタンを置く EA(MT5)
#include <Trade\Trade.mqh>
input double InpLots = 0.1; // ロット
input ulong InpMagic = 20240; // マジックナンバー
CTrade trade;
void MakeButton(string name, string text, int x, color bg)
{
ObjectCreate(0, name, OBJ_BUTTON, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, 30);
ObjectSetInteger(0, name, OBJPROP_XSIZE, 90);
ObjectSetInteger(0, name, OBJPROP_YSIZE, 32);
ObjectSetInteger(0, name, OBJPROP_BGCOLOR, bg);
ObjectSetInteger(0, name, OBJPROP_COLOR, clrWhite);
ObjectSetString(0, name, OBJPROP_TEXT, text);
}
int OnInit()
{
trade.SetExpertMagicNumber(InpMagic);
MakeButton("BtnBuy", "買い", 10, clrRoyalBlue);
MakeButton("BtnSell", "売り", 110, clrCrimson);
MakeButton("BtnClose", "全決済", 210, clrDimGray);
return INIT_SUCCEEDED;
}
void OnDeinit(const int reason)
{
ObjectDelete(0, "BtnBuy");
ObjectDelete(0, "BtnSell");
ObjectDelete(0, "BtnClose");
}
void OnTick()
{
}
void CloseAll()
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol || (ulong)PositionGetInteger(POSITION_MAGIC) != InpMagic) continue;
if(!trade.PositionClose(ticket))
Print("決済失敗 ", trade.ResultRetcodeDescription());
}
}
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
if(id != CHARTEVENT_OBJECT_CLICK) return;
if(sparam == "BtnBuy")
{
if(!trade.Buy(InpLots))
Print("買い失敗 ", trade.ResultRetcodeDescription());
}
else if(sparam == "BtnSell")
{
if(!trade.Sell(InpLots))
Print("売り失敗 ", trade.ResultRetcodeDescription());
}
else if(sparam == "BtnClose")
CloseAll();
else
return;
ObjectSetInteger(0, sparam, OBJPROP_STATE, false); // 押された状態を戻す
ChartRedraw();
}MT4 版・MT5 版とも MetaEditor でコンパイル(エラー・警告なし)を確認済みです。実際の口座で使う前に、デモ口座やストラテジーテスターで動作を確かめてください。
カスタマイズのポイント
- ボタンを増やすときは MakeButton() の呼び出しを足し、OnChartEvent() に同じ名前の分岐を足します。
- 損切り・利確を付けたいときは、注文の部分を「損切り・利確を pips で指定する」レシピの書き方に変えます。
注意点
- ボタンはチャート上の操作なので、ストラテジーテスターでは押せません。
- ツールバーの「自動売買」がオフだと、ボタンを押しても注文できません。
このコードで使っている関数
うまく動かないときに出やすいエラー
あわせて読みたいレシピ
「オブジェクト・画面」のレシピ一覧
- チャートにボタンを置いて、押したら注文したい
- 手で引いた水平線にタッチしたら知らせたい
- 自分が作ったオブジェクトだけをまとめて消したい












