このEAのソースコードをそのままメタエディタに貼り付けてコンパイルすると、「’False’ – undeclared identifier」というエラーで止まってしまいます。

原因は、MQL4の真偽値は小文字の`true`/`false`で書く必要があるのに、コードの一部に大文字の`False`が混ざっていることです。ロジック自体(ボタンを押したら保有ポジションを全部決済する)は正しく組まれているだけに、このタイプミス1つで最後まで完成できないのはもったいないところです。この記事では、ポジションを一括決済するボタンEAの作り方を、コンパイルエラーの直し方とあわせて最後まで解説します。

ポジションを一括決済することができるボタン

トレードしている際に一つずつポジションを決済していると知らない間にマイナスになることがあります。

そうした際に全決済してポジションを一気に決済できるボタンを作成しましょう。

  • ポジションを全決済するボタン

メタエディタ(MetaEditor)を立ち上げる

メタエディタ(MetaEditor)を立ち上げましょう。操作は以下に記載しています。

【MQL】カスタムインジケーターを作成の流れについてわかりやすく説明してみた

今回は名前を「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 ゴシック");//フォントの種類
Copy

OnDeinit()関数を記述する

OnDeinit()関数を記述しましょう。チャートから削除後にオブジェクトが消えるようにしましょう。

ObjectDelete("All_Delete");//チャートから削除後表示削除

OnDeinit()関数を記述は完了です。

ObjectDelete("All_Delete");//チャートから削除後表示削除
Copy

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);//ボタンが押されているかどうか
}
Copy

コンパイルする

コンパイルしましょう。ポチッとなとボタンを押して決済できれば完了です。

MQL MT4 ポジション 決済 ボタン

ソースコード全体

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);//ボタンが押されているかどうか
     }
  }
//+------------------------------------------------------------------+
Copy

まとめ

これでEAのポジションを決済できるボタンができましたね。コンパイルエラーで詰まりやすい「True/False」の大文字・小文字は、MQL4に限らず自作コードでもよく起きる間違いなので、他のEAを書くときも意識しておくと役立ちます。

関連記事