このEAのソースコードをそのままメタエディタに貼り付けてコンパイルすると、
「’False’ – undeclared identifier」
というエラーで止まってしまいます。
原因は、MQL4の真偽値は小文字の`true`/`false`で書く必要があるのに、
コードの一部に大文字の`False`が混ざっていることです。
ロジック自体(ボタンを押したら保有ポジションを全部決済する)は正しく組まれているだけに、
このタイプミス1つで最後まで完成できないのはもったいないところです。
この記事では、ポジションを一括決済するボタンEAの作り方を、
コンパイルエラーの直し方とあわせて最後まで解説します。
ポジションを一括決済することができるボタンの作り方
トレードしている際に一つずつポジションを決済していると、
知らない間にマイナスになることがあります。
そうした際に全決済してポジションを一気に決済できるボタンを作成しましょう。
- ポジションを全決済するボタン
ボタンの土台を作る(メタエディタ起動・OnInit関数)
まず、ボタンの土台になる部分から作っていきます。
メタエディタ(MetaEditor)を立ち上げる
メタエディタ(MetaEditor)を立ち上げましょう。
操作は以下に記載しています。

今回は名前を「All-Delete」で作成します。
OnInit()関数でボタンを作成する
OnInit()関数を記述していきます。
まずはObjectCreateでボタンを作成しましょう。
ObjectCreate("All_Delete", OBJ_BUTTON, 0, 0, 0);//ボタンを作成
次にObjectSetでX軸とY軸のアンカーを決めましょう。
今回はX軸は0PixelでY軸は30Pixelにしましょう。
ObjectSet("All_Delete", OBJPROP_XDISTANCE, 0);//ピクセル単位のX軸アンカー
ObjectSet("All_Delete", OBJPROP_YDISTANCE, 30);//ピクセル単位のY軸アンカー
次にオブジェクトのサイズを決めましょう。
ObjectSetでX軸のサイズを180Pixelに、
Y軸のサイズを50Pixelにしましょう。
ObjectSet("All_Delete", OBJPROP_XSIZE, 180);//オブジェクトのX軸のサイズ
ObjectSet("All_Delete", OBJPROP_YSIZE, 50);//オブジェクトのY軸のサイズ
次にアンカーコーナーを決めましょう。
アンカーコーナーというのはチャートの四つ角をどこの視点にするかです。
今回は、左上なので0を選択します。
ObjectSet("All_Delete", OBJPROP_CORNER, 0);// オブジェクトのアンカーコーナー0: 左上、1: 右上、2: 右下、3: 左下)
次にフォントサイズを10にしましょう。
ObjectSet("All_Delete", OBJPROP_FONTSIZE, 10);//フォントサイズ
次にカラーを決めましょう。文字カラーをブラックにして背景カラーをダークグレーにしましょう。
ObjectSet("All_Delete", OBJPROP_COLOR, Black);//文字カラー
ObjectSet("All_Delete", OBJPROP_BGCOLOR, DarkGray);//背景カラー
表示テキストを作りましょう。今回はポチッととなにしました。
ObjectSetString(0, "All_Delete", OBJPROP_TEXT, "_(┐「ε:)_ポチッとな");//表示テキスト
最後です。フォントの種類を決めましょう。無難にMSゴシックにしました。
ObjectSetString(0, "All_Delete", OBJPROP_FONT, "MS ゴシック");//フォントの種類
これでOnInit()関数を記述は完了です。
ObjectCreate("All_Delete", OBJ_BUTTON, 0, 0, 0);//ボタンを作成
ObjectSet("All_Delete", OBJPROP_XDISTANCE, 0);//ピクセル単位のX軸アンカー
ObjectSet("All_Delete", OBJPROP_YDISTANCE, 30);//ピクセル単位のY軸アンカー
ObjectSet("All_Delete", OBJPROP_XSIZE, 180);//オブジェクトのX軸のサイズ
ObjectSet("All_Delete", OBJPROP_YSIZE, 50);//オブジェクトのY軸のサイズ
ObjectSet("All_Delete", OBJPROP_CORNER, 0);// オブジェクトのアンカーコーナー0: 左上、1: 右上、2: 右下、3: 左下)
ObjectSet("All_Delete", OBJPROP_FONTSIZE, 10);//フォントサイズ
ObjectSet("All_Delete", OBJPROP_COLOR, Black);//文字カラー
ObjectSet("All_Delete", OBJPROP_BGCOLOR, DarkGray);//背景カラー
ObjectSetString(0, "All_Delete", OBJPROP_TEXT, "_(┐「ε:)_ポチッとな");//表示テキスト
ObjectSetString(0, "All_Delete", OBJPROP_FONT, "MS ゴシック");//フォントの種類
ボタンのクリックで全決済する処理を書く(OnDeinit・OnChartEvent)
最後に、ボタンを消す処理とクリック時の決済処理を書きます。
OnDeinit()関数を記述する
OnDeinit()関数を記述しましょう。
チャートから削除後にオブジェクトが消えるようにしましょう。
ObjectDelete("All_Delete");//チャートから削除後表示削除
OnDeinit()関数を記述は完了です。
ObjectDelete("All_Delete");//チャートから削除後表示削除
OnChartEvent()関数でクリック判定と決済処理を書く
OnChartEvent()関数を記述していきます。
まず、チャート上で何かしらのイベント(クリック、ドラッグなど)が起きたときに、
それがこのボタンのクリックなのかを判定します。
if(id==CHARTEVENT_OBJECT_CLICK && sparam=="All_Delete")//ボタンがクリックされた場合
sparamだけを見て判定すると、
たまたま同じ文字列を持つ別のイベントにも反応してしまう可能性があるため、
id(イベントの種類)が「オブジェクトがクリックされた」ことを表す、
CHARTEVENT_OBJECT_CLICKであることも合わせて確認します。
次にfor文で、保有しているポジションと待機注文の合計数から、
1を引いた値をi変数の初期値にして、
0になるまで降順にループさせます。
for(int i = OrdersTotal() -1; i >= 0; i--)
ループの中でポジションを1件ずつ選択します。
選択に失敗した場合(存在しないインデックスを指定した場合など)は、
そのまま次のループへ進みます。
if(!OrderSelect(i, SELECT_BY_POS)) continue;//ポジションを選択
ポジションの通貨ペアとオブジェクトを表示している通貨ペアが、
同じであればという条件をつくります。
if (OrderSymbol() == Symbol())//ポジションの通貨ペアと現在の通貨ペアが同じであれば
ポジションがロングの場合というif文を作成します。
if(OrderType() == OP_BUY)//ポジションがロングの場合
次にレート更新しましょう。
RefreshRates();//レート更新
決済を試み、失敗した場合の処理も書いておきましょう。
if(OrderClose(OrderTicket(), OrderLots(), SymbolInfoDouble(OrderSymbol(), SYMBOL_BID), 5, Yellow) == false)
決済に失敗した場合はエラーコードを表示してcontinueしましょう。
Print("決済に失敗しました。エラーコード=",GetLastError());//エラーがあれば表示
continue;//コンテニューでループ再開
ポジションがショートの場合は
else if(OrderType() == OP_SELL)//ポジションがショートの場合
同様にレートを更新して
RefreshRates();//レート更新
決済を試みます。
買いポジションを決済するときはBid、
売りポジションを決済するときはAskを使う点に注意してください。
if(OrderClose(OrderTicket(), OrderLots(), SymbolInfoDouble(OrderSymbol(), SYMBOL_ASK), 5, Yellow) == false)
決済に失敗した場合の処理も同様です。
Print("決済に失敗しました。エラーコード=",GetLastError());//エラーがあれば表示
continue;//コンテニューでループ再開
Sleep() 関数はプログラムコードの実行を停止し、
所定の時間間隔が経過したあとに続行を許可します。
パラメータとしてミリ秒の単位であらわされる時間間隔の値を取ります。
今回は値を100にしました。
Sleep(100);//実行停止の時間間隔
OBJPROP_STATEはボタン押下状態を選択できます。
押されていない状態に戻すので、falseを指定します。
**ここは必ず小文字のfalseで書いてください。
** 大文字のFalseはMQL4では定義されていない識別子のため、
コンパイルエラー(「’False’ – undeclared identifier」
)の原因になります。
ObjectSet("All_Delete", OBJPROP_STATE, false);//ボタンが押されているかどうか
これでOnChartEvent()関数を記述は完了です。
if(id==CHARTEVENT_OBJECT_CLICK && sparam=="All_Delete")//ボタンがクリックされた場合
{
for(int i = OrdersTotal() -1; i >= 0; i--)
{
if(!OrderSelect(i, SELECT_BY_POS)) continue;//ポジションを選択
if (OrderSymbol() == Symbol())//ポジションの通貨ペアと現在の通貨ペアが同じであれば
{
if(OrderType() == OP_BUY)//ポジションがロングの場合
{
RefreshRates();//レート更新
if(OrderClose(OrderTicket(), OrderLots(), SymbolInfoDouble(OrderSymbol(), SYMBOL_BID), 5, Yellow) == false)
{
Print("決済に失敗しました。エラーコード=",GetLastError());//エラーがあれば表示
continue;//コンテニューでループ再開
}
}
else if(OrderType() == OP_SELL)//ポジションがショートの場合
{
RefreshRates();//レート更新
if(OrderClose(OrderTicket(), OrderLots(), SymbolInfoDouble(OrderSymbol(), SYMBOL_ASK), 5, Yellow) == false)
{
Print("決済に失敗しました。エラーコード=",GetLastError());//エラーがあれば表示
continue;//コンテニューでループ再開
}
}
}
}
Sleep(100);//実行停止の時間間隔
ObjectSet("All_Delete", OBJPROP_STATE, false);//ボタンが押されているかどうか
}
コンパイルして動作確認する
コンパイルしましょう。ポチッとなとボタンを押して決済できれば完了です。

All-Deleteのソースコード全体
All-Deleteのソースコード全体は以下に記載しています。
//+------------------------------------------------------------------+
//| All-Delete.mq4 |
//| Copyright 2020, FX-EA System Project Creator |
//| https://creator.fx-ea-system-project.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, FX-EA System Project Creator"
#property link "https://creator.fx-ea-system-project.com/"
#property version "1.01"
#property strict
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
ObjectCreate("All_Delete", OBJ_BUTTON, 0, 0, 0);//ボタンを作成
ObjectSet("All_Delete", OBJPROP_XDISTANCE, 0);//ピクセル単位のX軸アンカー
ObjectSet("All_Delete", OBJPROP_YDISTANCE, 30);//ピクセル単位のY軸アンカー
ObjectSet("All_Delete", OBJPROP_XSIZE, 180);//オブジェクトのX軸のサイズ
ObjectSet("All_Delete", OBJPROP_YSIZE, 50);//オブジェクトのY軸のサイズ
ObjectSet("All_Delete", OBJPROP_CORNER, 0);// オブジェクトのアンカーコーナー0: 左上、1: 右上、2: 右下、3: 左下)
ObjectSet("All_Delete", OBJPROP_FONTSIZE, 10);//フォントサイズ
ObjectSet("All_Delete", OBJPROP_COLOR, Black);//文字カラー
ObjectSet("All_Delete", OBJPROP_BGCOLOR, DarkGray);//背景カラー
ObjectSetString(0, "All_Delete", OBJPROP_TEXT, "_(┐「ε:)_ポチッとな");//表示テキスト
ObjectSetString(0, "All_Delete", OBJPROP_FONT, "MS ゴシック");//フォントの種類
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
ObjectDelete("All_Delete");//チャートから削除後表示削除
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
}
//+------------------------------------------------------------------+
//| ChartEvent function |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,//イベントID
const long &lparam,//longイベント
const double &dparam,//doubleイベント
const string &sparam)//stringイベント
{
//---
if(id==CHARTEVENT_OBJECT_CLICK && sparam=="All_Delete")//ボタンがクリックされた場合
{
for(int i=OrdersTotal()-1; i>=0; i--)
{
if(!OrderSelect(i,SELECT_BY_POS)) continue;//ポジションを選択
if(OrderSymbol()==Symbol())//ポジションの通貨ペアと現在の通貨ペアが同じであれば
{
if(OrderType()==OP_BUY)//ポジションがロングの場合
{
RefreshRates();//レート更新
if(OrderClose(OrderTicket(),OrderLots(),SymbolInfoDouble(OrderSymbol(),SYMBOL_BID),5,Yellow)==false)
{
Print("決済に失敗しました。エラーコード=",GetLastError());//エラーがあれば表示
continue;//コンテニューでループ再開
}
}
else if(OrderType()==OP_SELL)//ポジションがショートの場合
{
RefreshRates();//レート更新
if(OrderClose(OrderTicket(),OrderLots(),SymbolInfoDouble(OrderSymbol(),SYMBOL_ASK),5,Yellow)==false)
{
Print("決済に失敗しました。エラーコード=",GetLastError());//エラーがあれば表示
continue;//コンテニューでループ再開
}
}
}
}
Sleep(100);//実行停止の時間間隔
ObjectSet("All_Delete", OBJPROP_STATE, false);//ボタンが押されているかどうか
}
}
//+------------------------------------------------------------------+
【MQL】ポジションを一括決済することができるボタン【中級編】:まとめ
これでEAのポジションを決済できるボタンができましたね。
コンパイルエラーで詰まりやすい「True/False」の大文字・小文字は、
MQL4に限らず自作コードでもよく起きる間違いなので、
他のEAを書くときも意識しておくと役立ちます。
コメント