MT5版のボタン操作でエントリーするEAを作成する【MQLプログラミングの基礎】
1.ファイルの新規作成
この記事では、チャートに設置したボタン操作で手動成行エントリーするEAを作成します。
※この記事はMQL5の内容です。
MetaEditorの「新規作成」アイコンをクリックしてMQLウィザードを開始します。

「エキスパートアドバイザ(テンプレート)」を選択して「次へ」をクリック。

ファイル名を「TradePanel.mq5」とし、「次へ」をクリック。

イベントハンドラはOnTimerとOnChartEventを選択して「次へ」をクリック。
OnTimer関数は、押したボタンを自動で戻す機能で利用します。
OnChartEvent関数は、ボタンをクリックしたことを検知し、そのときに処理を実行する回路で利用します。

テスターイベントハンドラは何も選択せず「完了」をクリックすれば、ファイルのベースが作成されます。
2.ボタンの設置
オブジェクトの名称の頭に共通の文字列を付けて管理するために、接頭辞を定義します。
ファイル上部のプロパティ「#property version “1.00”」の下に、下記を追記します。
#define PREFIX MQLInfoString(MQL_PROGRAM_NAME) + "_"
ボタンオブジェクトを表示するために、MQLリファレンス内にある関数を利用します。
MetaEditorメニューの「ヘルプ」から「MQL5リファレンス」を開いて、「目次」タブを選択し、「標準的な定数、列挙と構造体」→「オブジェクト定数」→「オブジェクト型」にある「OBJ_BUTTON」を選択してください。
OBJ_BUTTON内にある「//| ボタンを作成する」以下にある「ButtonCreate」関数をコピーして、今回のプログラムの最下部へ貼り付けます。
――――― コピーして貼り付けするコード(ここから) ―――――
//+------------------------------------------------------------------+
//| ボタンを作成する |
//+------------------------------------------------------------------+
bool ButtonCreate(const long chart_ID=0, // チャート識別子
const string name="Button", // ボタン名
const int sub_window=0, // サブウィンドウ番号
const int x=0, // X 座標
const int y=0, // Y 座標
const int width=50, // ボタンの幅
const int height=18, // ボタンの高さ
const ENUM_BASE_CORNER corner=CORNER_LEFT_UPPER, // アンカーに使用されるチャートのコーナー
const string text="Button", // テキスト
const string font="Arial", // フォント
const int font_size=10, // フォントサイズ
const color clr=clrBlack, // テキストの色
const color back_clr=C'236,233,216', // 背景色
const color border_clr=clrNONE, // 境界線の色
const bool state=false, // 押される/放される
const bool back=false, // 背景で表示する
const bool selection=false, // 強調表示して移動
const bool hidden=true, // オブジェクトリストに隠す
const long z_order=0) // マウスクリックの優先順位
{
//--- エラー値をリセットする
ResetLastError();
//--- ボタンを作成する
if(!ObjectCreate(chart_ID,name,OBJ_BUTTON,sub_window,0,0))
{
Print(__FUNCTION__,
": failed to create the button! Error code = ",GetLastError());
return(false);
}
//--- ボタン座標を設定する
ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x);
ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y);
//--- ボタンサイズを設定する
ObjectSetInteger(chart_ID,name,OBJPROP_XSIZE,width);
ObjectSetInteger(chart_ID,name,OBJPROP_YSIZE,height);
//--- ポイント座標が相対的に定義されているチャートのコーナーを設定
ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner);
//--- テキストを設定する
ObjectSetString(chart_ID,name,OBJPROP_TEXT,text);
//--- テキストフォントを設定する
ObjectSetString(chart_ID,name,OBJPROP_FONT,font);
//--- フォントサイズを設定する
ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,font_size);
//--- テキストの色を設定する
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//--- 背景色を設定する
ObjectSetInteger(chart_ID,name,OBJPROP_BGCOLOR,back_clr);
//--- 境界線の色を設定する
ObjectSetInteger(chart_ID,name,OBJPROP_BORDER_COLOR,border_clr);
//--- 前景(false)または背景(true)に表示
ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//--- ボタンの状態を設定する
ObjectSetInteger(chart_ID,name,OBJPROP_STATE,state);
//--- マウスでのボタンを移動させるモードを有効(true)か無効(false)にする
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//--- オブジェクトリストのグラフィックオブジェクトを非表示(true)か表示(false)にする
ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//--- チャートのマウスクリックのイベントを受信するための優先順位を設定する
ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//--- 実行成功
return(true);
}
//+------------------------------------------------------------------+
――――― コピーして貼り付けするコード(ここまで) ―――――
OnInit関数内に下記を追記し、売りエントリー用のボタンを作成して表示します。
ButtonCreate(0, PREFIX + " Sell", 0, 0, 20, 80, 40, CORNER_LEFT_UPPER, "Sell", "Arial Black", 20, clrWhite, clrDodgerBlue, clrNONE);
上記のように引数を指定することで、チャートの左上を基準とし、X座標0、Y座標20の位置に、幅80、高さ40のボタンが表示されます。
ボタン色はDodgerBlue、文字色はWhite、フォントはArial Blackで「Sell」という文字を表示させています。
同様に下記を追記し、買いエントリー用のボタンを表示します。
ButtonCreate(0, PREFIX + "Buy", 0, 80, 20, 80, 40, CORNER_LEFT_UPPER, "Buy", "Arial Black", 20, clrWhite, clrRed, clrNONE);
EA(エキスパートアドバイザ)の削除や再読み込み時に、ボタンオブジェクトを消去するため、OnDeinit関数内へ下記を追記します。
ObjectsDeleteAll(0, PREFIX);
ここまでの状態でコンパイルし、本EAをチャートにセットするとボタンが表示されることを確認できます。

3.エントリー用の関数を作成
プログラムの任意の場所(他の各種関数の外)へ、新たに下記の関数を追記します。
//+------------------------------------------------------------------+
//| エントリー関数 |
//+------------------------------------------------------------------+
void Entry()
{
}
//+------------------------------------------------------------------+
エントリー用の関数を作成するために、MQLリファレンス内にある例文を利用します。
MetaEditorメニューの「ヘルプ」から「MQL5リファレンス」を開いて、「目次」タブを選択し、「標準的な定数、列挙と構造体」→「取引定数」→「取引操作の種類」を開きます。

「//— リクエストと結果の宣言と初期化」から「 PrintFormat(“OrderSend error %d”,GetLastError()); // リクエストの送信が失敗した場合、エラーコードを出力する」までの行をコピーして、作成したEntry関数内へ貼り付けます。
――――― コピーして貼り付けするコード(ここから) ―――――
//--- リクエストと結果の宣言と初期化
MqlTradeRequest request={};
MqlTradeResult result={};
//--- リクエストのパラメータ
request.action =TRADE_ACTION_DEAL; // 取引操作タイプ
request.symbol =Symbol(); // シンボル
request.volume =0.1; // 0.1ロットのボリューム
request.type =ORDER_TYPE_BUY; // 注文タイプ
request.price =SymbolInfoDouble(Symbol(),SYMBOL_ASK); // 発注価格
request.deviation=5; // 価格からの許容偏差
request.magic =EXPERT_MAGIC; // 注文のMagicNumber
//--- リクエストの送信
if(!OrderSend(request,result))
PrintFormat("OrderSend error %d",GetLastError()); // リクエストの送信が失敗した場合、エラーコードを出力する
――――― コピーして貼り付けするコード(ここまで) ―――――
エントリー時にエントリー方向、ロット数、エントリー価格、SL(決済逆指値)、TP(決済指値)、許容スリッページ、マジックナンバーを指定できるよう、Entry関数を下記のように編集します。
void Entry(ENUM_ORDER_TYPE type, double lot, double price, double sl, double tp, int slip, int magic, string comment)
{
ENUM_ORDER_TYPE_FILLING filling;
long mode = SymbolInfoInteger(NULL, SYMBOL_FILLING_MODE);
if ((mode & SYMBOL_FILLING_IOC) != 0) filling = ORDER_FILLING_IOC;
else if ((mode & SYMBOL_FILLING_FOK) != 0) filling = ORDER_FILLING_FOK;
else filling = ORDER_FILLING_RETURN;
//--- リクエストと結果の宣言と初期化
MqlTradeRequest request = {};
MqlTradeResult result = {};
//--- リクエストのパラメータ
request.action = TRADE_ACTION_DEAL; // 取引操作タイプ
request.symbol = Symbol(); // シンボル
request.volume = lot; // ロットのボリューム
request.type = type; // 注文タイプ
request.price = price; // 発注価格
request.sl = sl; // SL (指定する為に行を追加)
request.tp = tp; // TP (指定する為に行を追加)
request.deviation = slip; // 価格からの許容偏差
request.type_filling = filling; // 注文充填(指定する為に行を追加)
request.magic = magic; // 注文のMagicNumber
//--- リクエストの送信
if(!OrderSend(request,result))
PrintFormat("OrderSend error %d",GetLastError()); // リクエストの送信が失敗した場合、エラーコードを出力する
else PlaySound("ok.wav");
}
ボリューム実行ポリシー(request.type_filling)を指定するために、変数fillingを関数内に追加で定義しています。
また、通貨ペアの注文充填モード(SYMBOL_FILLING_MODE)に合わせて、filling(ENUM_ORDER_TYPE_FILLING)を設定しています。
https://www.mql5.com/ja/docs/constants/tradingconstants/orderproperties#enum_order_type_filling
SL・TPを指定するために、リクエストのパラメータに「request.sl = sl;」「request.tp = tp;」を追加しています。
そして約定時に音を鳴らすよう、「 else PlaySound(“ok.wav”);」を追加しています。
4.ボタン操作でエントリー
エントリー条件を指定するため、プログラム上部の「#define PREFIX MQLInfoString(MQL_PROGRAM_NAME) + “_”」の下へ、下記のパラメーターを追記します。
input int MAGIC = 1; // マジックナンバー
input double LOT = 0.1; // ロット
input double TP = 50; // TP [pips]
input double SL = 50; // SL [pips]
input double SLIP = 1; // 許容スリッページ [pips]
input string COMMENT = ""; // コメント
Buyボタンをクリックしたことを認識するために、下記のif文をOnChartEvent関数内へ追記します。
if (id == CHARTEVENT_OBJECT_CLICK) {
if (sparam == PREFIX + "Buy") {
}
}
if文「if (sparam == PREFIX + “Buy”) { }」の中括弧{}内に、エントリー価格とSL・TPを定義するために、下記を追記します。
double price = SymbolInfoDouble(NULL, SYMBOL_ASK);
double sl = NormalizeDouble(price - SL * _Point * 10, _Digits);
double tp = NormalizeDouble(price + TP * _Point * 10, _Digits);
ボタンクリック時に買いエントリーするよう、Entry関数を追記します。
Entry(ORDER_TYPE_BUY, LOT, price, sl, tp, int(SLIP * 10), MAGIC, COMMENT);
同様に、Sellボタンクリックで売りエントリーするよう、if文「if (id == CHARTEVENT_OBJECT_CLICK) { }」の中括弧{}内に、下記を追記します。
if (sparam == PREFIX + "Sell") {
double price = SymbolInfoDouble(NULL, SYMBOL_BID);
double sl = NormalizeDouble(price + SL * _Point * 10, _Digits);
double tp = NormalizeDouble(price - TP * _Point * 10, _Digits);
Entry(ORDER_TYPE_SELL, LOT, price, sl, tp, int(SLIP * 10), MAGIC, COMMENT);
}
上記までの状態でコンパイル後、「Sell」「Buy」ボタンをクリックすると、成行エントリーすることが確認できます。
チャート右上隅に表示されているEA名称の右側のマークをダブルクリックすると、EAの設定画面が開きます。
EAを利用してトレードをする際は、設定画面の「共有」タブの「アルゴリズム取引を許可」にチェックを入れる必要があります。

MT5ウィンドウ上部のメニュー下にあるツールバーの「アルゴリズム取引」ボタンがONになっていないと、EAでのトレードができません。
OFFになっている場合は、ONにしてください。
- ・ON表示

- ・OFF表示

5.ボタンの自動戻し回路
現在の状態では、ボタンを押すと押しっぱなしの状態になってしまいます。
押したボタンを自動で戻すために、OnTimer関数を利用します。
OnInit関数内の「EventSetTimer(60);」を下記に書き換えます。
EventSetMillisecondTimer(100);
0.1秒(100ミリ秒)間隔でOnTimer関数内の回路が繰り返し実行されるようになります。
ボタンが押されたとき、自動でボタンが戻るよう、OnTimer回路内に下記を追記します。
static bool stateBuy = false, stateSell = false;
if (stateBuy) ObjectSetInteger(0, PREFIX + "Buy", OBJPROP_STATE, false);
stateBuy = ObjectGetInteger(0, PREFIX + "Buy", OBJPROP_STATE);
if (stateSell) ObjectSetInteger(0, PREFIX + "Sell", OBJPROP_STATE, false);
stateSell = ObjectGetInteger(0, PREFIX + "Sell", OBJPROP_STATE);
ChartRedraw();
ボタンが押されていることを認識した後、0.1秒後にボタンを戻す動作となります。
以上で、今回のプログラムは完成です。
6.ソースコード
今回、作成したソースコードは下記の通りです。
//+------------------------------------------------------------------+
//| TradePanel.mq5 |
//| Copyright 2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#define PREFIX MQLInfoString(MQL_PROGRAM_NAME) + "_"
input int MAGIC = 1; // マジックナンバー
input double LOT = 0.1; // ロット
input double TP = 50; // TP [pips]
input double SL = 50; // SL [pips]
input double SLIP = 1; // 許容スリッページ [pips]
input string COMMENT = ""; // コメント
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
ButtonCreate(0, PREFIX + "Sell", 0, 0, 20, 80, 40, CORNER_LEFT_UPPER, "Sell", "Arial Black", 20, clrWhite, clrDodgerBlue, clrNONE);
ButtonCreate(0, PREFIX + "Buy", 0, 80, 20, 80, 40, CORNER_LEFT_UPPER, "Buy", "Arial Black", 20, clrWhite, clrRed, clrNONE);
//--- create timer
EventSetMillisecondTimer(100);
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
ObjectsDeleteAll(0, PREFIX);
//--- destroy timer
EventKillTimer();
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
}
//+------------------------------------------------------------------+
//| Timer function |
//+------------------------------------------------------------------+
void OnTimer()
{
//---
static bool stateBuy = false, stateSell = false;
if (stateBuy) ObjectSetInteger(0, PREFIX + "Buy", OBJPROP_STATE, false);
stateBuy = ObjectGetInteger(0, PREFIX + "Buy", OBJPROP_STATE);
if (stateSell) ObjectSetInteger(0, PREFIX + "Sell", OBJPROP_STATE, false);
stateSell = ObjectGetInteger(0, PREFIX + "Sell", OBJPROP_STATE);
ChartRedraw();
}
//+------------------------------------------------------------------+
//| ChartEvent function |
//+------------------------------------------------------------------+
void OnChartEvent(const int32_t id,
const long &lparam,
const double &dparam,
const string &sparam)
{
if (id == CHARTEVENT_OBJECT_CLICK) {
if (sparam == PREFIX + "Buy") {
double price = SymbolInfoDouble(NULL, SYMBOL_ASK);
double sl = NormalizeDouble(price - SL * _Point * 10, _Digits);
double tp = NormalizeDouble(price + TP * _Point * 10, _Digits);
Entry(ORDER_TYPE_BUY, LOT, price, sl, tp, int(SLIP * 10), MAGIC, COMMENT);
}
if (sparam == PREFIX + "Sell") {
double price = SymbolInfoDouble(NULL, SYMBOL_BID);
double sl = NormalizeDouble(price + SL * _Point * 10, _Digits);
double tp = NormalizeDouble(price - TP * _Point * 10, _Digits);
Entry(ORDER_TYPE_SELL, LOT, price, sl, tp, int(SLIP * 10), MAGIC, COMMENT);
}
}
}
//+------------------------------------------------------------------+
//| ボタンを作成する |
//+------------------------------------------------------------------+
bool ButtonCreate(const long chart_ID=0, // チャート識別子
const string name="Button", // ボタン名
const int sub_window=0, // サブウィンドウ番号
const int x=0, // X 座標
const int y=0, // Y 座標
const int width=50, // ボタンの幅
const int height=18, // ボタンの高さ
const ENUM_BASE_CORNER corner=CORNER_LEFT_UPPER, // アンカーに使用されるチャートのコーナー
const string text="Button", // テキスト
const string font="Arial", // フォント
const int font_size=10, // フォントサイズ
const color clr=clrBlack, // テキストの色
const color back_clr=C'236,233,216', // 背景色
const color border_clr=clrNONE, // 境界線の色
const bool state=false, // 押される/放される
const bool back=false, // 背景で表示する
const bool selection=false, // 強調表示して移動
const bool hidden=true, // オブジェクトリストに隠す
const long z_order=0) // マウスクリックの優先順位
{
//--- エラー値をリセットする
ResetLastError();
//--- ボタンを作成する
if(!ObjectCreate(chart_ID,name,OBJ_BUTTON,sub_window,0,0))
{
Print(__FUNCTION__,
": failed to create the button! Error code = ",GetLastError());
return(false);
}
//--- ボタン座標を設定する
ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x);
ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y);
//--- ボタンサイズを設定する
ObjectSetInteger(chart_ID,name,OBJPROP_XSIZE,width);
ObjectSetInteger(chart_ID,name,OBJPROP_YSIZE,height);
//--- ポイント座標が相対的に定義されているチャートのコーナーを設定
ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner);
//--- テキストを設定する
ObjectSetString(chart_ID,name,OBJPROP_TEXT,text);
//--- テキストフォントを設定する
ObjectSetString(chart_ID,name,OBJPROP_FONT,font);
//--- フォントサイズを設定する
ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,font_size);
//--- テキストの色を設定する
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//--- 背景色を設定する
ObjectSetInteger(chart_ID,name,OBJPROP_BGCOLOR,back_clr);
//--- 境界線の色を設定する
ObjectSetInteger(chart_ID,name,OBJPROP_BORDER_COLOR,border_clr);
//--- 前景(false)または背景(true)に表示
ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//--- ボタンの状態を設定する
ObjectSetInteger(chart_ID,name,OBJPROP_STATE,state);
//--- マウスでのボタンを移動させるモードを有効(true)か無効(false)にする
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//--- オブジェクトリストのグラフィックオブジェクトを非表示(true)か表示(false)にする
ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//--- チャートのマウスクリックのイベントを受信するための優先順位を設定する
ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//--- 実行成功
return(true);
}
//+------------------------------------------------------------------+
//| エントリー関数 |
//+------------------------------------------------------------------+
void Entry(ENUM_ORDER_TYPE type, double lot, double price, double sl, double tp, int slip, int magic, string comment)
{
ENUM_ORDER_TYPE_FILLING filling;
long mode = SymbolInfoInteger(NULL, SYMBOL_FILLING_MODE);
if ((mode & SYMBOL_FILLING_IOC) != 0) filling = ORDER_FILLING_IOC;
else if ((mode & SYMBOL_FILLING_FOK) != 0) filling = ORDER_FILLING_FOK;
else filling = ORDER_FILLING_RETURN;
//--- リクエストと結果の宣言と初期化
MqlTradeRequest request = {};
MqlTradeResult result = {};
//--- リクエストのパラメータ
request.action = TRADE_ACTION_DEAL; // 取引操作タイプ
request.symbol = Symbol(); // シンボル
request.volume = lot; // ロットのボリューム
request.type = type; // 注文タイプ
request.price = price; // 発注価格
request.sl = sl; // SL (指定する為に行を追加)
request.tp = tp; // TP (指定する為に行を追加)
request.deviation = slip; // 価格からの許容偏差
request.type_filling = filling; // 注文充填
request.magic = magic; // 注文のMagicNumber
//--- リクエストの送信
if(!OrderSend(request,result))
PrintFormat("OrderSend error %d",GetLastError()); // リクエストの送信が失敗した場合、エラーコードを出力する
else PlaySound("ok.wav");
}
//+------------------------------------------------------------------+
本記事の監修者・HT FX
2013年にFXを開始し、その後専業トレーダーへ。2014年からMT4/MT5のカスタムインジケーターの開発に取り組む。ブログでは100本を超えるインジケーターを無料公開。投資スタイルは自作の秒足インジケーターを利用したスキャルピング。
EA(自動売買)を学びたい方へオススメコンテンツ

OANDAではEA(自動売買)を稼働するプラットフォームMT4/MT5の基本的な使い方について、画像や動画付きで詳しく解説しています。MT4/MT5のインストールからEAの設定方法までを詳しく解説しているので、初心者の方でもスムーズにEA運用を始めることが可能です。またOANDAの口座をお持ちであれば、独自開発したオリジナルインジケーターを無料で利用することもできます。EA運用をお考えであれば、ぜひ口座開設をご検討ください。
本ホームページに掲載されている事項は、投資判断の参考となる情報の提供を目的としたものであり、投資の勧誘を目的としたものではありません。投資方針、投資タイミング等は、ご自身の責任において判断してください。本サービスの情報に基づいて行った取引のいかなる損失についても、当社は一切の責を負いかねますのでご了承ください。また、当社は、当該情報の正確性および完全性を保証または約束するものでなく、今後、予告なしに内容を変更または廃止する場合があります。なお、当該情報の欠落・誤謬等につきましてもその責を負いかねますのでご了承ください。