見出し画像

【mql】保有中の全ポジションを一括決済するコードと、待機中注文を一括削除するコード

本noteでは、私がEAを作成した時に参考になったサイトを紹介します。
保有中の全ポジションを一括決済するコードと、待機中の全注文を一括削除するコードです。両建てや、ナンピン、マーチン系のEAで使用されるケースが多いかと思います。
EAやインジケーターを作成している方に役立てば幸いです。

参考サイト

https://autofx100.com/2015/04/05/145656/

問合せ

ご質問・ご意見は以下メールアドレスへお気軽にご連絡下さい。
gabrielfx2100@gmail.com

公式LINEの友達追加はコチラ
(ガブリエルのFX事情を配信中です)

コード紹介

//+------------------------------------------------------------------+
//| 定義                                                          
//+------------------------------------------------------------------+
#define MAX_RETRY_TIME   10.0      // 秒
#define SLEEP_TIME        0.1      // 秒
#define MILLISEC_2_SEC 1000.0      // ミリ秒
int MAGIC=1;                       //マジックナンバー
int Slippage=3;                    //スリッページ(point)
string comment="COMMENT";          //
//+------------------------------------------------------------------+
//|initとdeinit                                                      |
//+------------------------------------------------------------------+
void init()return;
int deinit()return(0);
//+------------------------------------------------------------------+
//|OnTick                                                            |
//+------------------------------------------------------------------+
void OnTick()
  {
  //保有中の全ポジション決済
   if(/* ここに決済条件を記載 */)
     {
      allOrderClose(MAGIC,Slippage,comment);
     }

  //待機中の全注文削除
   if(/* ここに削除条件を記載 */)
     {
      allOrderDelete(MAGIC,comment);
     }
   }

//+------------------------------------------------------------------+
//|【関数】指定マジックナンバーのポジション全決済                    
//|                                                                  
//|【引数】 IN OUT  引数名             説明                          
//|        --------------------------------------------------------- 
//|         ○      aMagic             マジックナンバー              
//|         ○      aSlippage          許容スリッページ              
//|         △      aComment           対象コメント                  
//|                                                                  
//|【戻値】なし                                                      
//|                                                                  
//|【備考】△:既定値あり                                            
//+------------------------------------------------------------------+
void allOrderClose(int aMagic,int aSlippage,string aComment="")
  {
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(OrderSelect(i,SELECT_BY_POS)==false)
        {
         break;
        }

      if(OrderSymbol()!=Symbol() || OrderMagicNumber()!=aMagic)
        {
         continue;
        }

      if(aComment!="" && OrderComment()!=aComment)
        {
         continue;
        }

      int type=OrderType();

      if(type!=OP_BUY && type!=OP_SELL)
        {
         continue;
        }

      int ticket=OrderTicket();

      Print("Attempted allOrderClose("+(string)aMagic+", "+(string)aSlippage+", Comment:"+aComment+")");

      bool result=orderCloseReliable(ticket,OrderLots(),OrderClosePrice(),aSlippage);

      if(result==false)
        {
         Print("allOrderClose: Ticket #",ticket,", failed to close");
        }
     }
  }
//+------------------------------------------------------------------+
//|【関数】信頼できる仕切り注文                                      
//|                                                                  
//|【引数】 IN OUT  引数名             説明                          
//|        --------------------------------------------------------- 
//|         ○      aTicket            チケット番号                  
//|         ○      aLots              ロット数                      
//|         ○      aPrice             仕切り価格                    
//|         ○      aSlippage          スリッページ(ポイント)      
//|         △      aArrow_color       チャート上の矢印の色          
//|                                                                  
//|【戻値】true :正常終了                                           
//|        false:異常終了                                           
//|                                                                  
//|【備考】△:初期値あり                                            
//+------------------------------------------------------------------+
bool orderCloseReliable(int aTicket,double aLots,double aPrice,int aSlippage,color aArrow_color=CLR_NONE)
  {
   bool result=false;
   uint startTime=GetTickCount();
   bool selected=OrderSelect(aTicket,SELECT_BY_TICKET,MODE_TRADES);

   string symbol = OrderSymbol();
   int    type   = OrderType();

   int digits=(int)MarketInfo(symbol,MODE_DIGITS);

   while(true)
     {
      if(IsStopped())
        {
         return(false);
        }

      if(GetTickCount()-startTime>MAX_RETRY_TIME*MILLISEC_2_SEC)
        {
         return(false);
        }

      // MarketInfo関数でレートを取得しており、定義済変数であるAskとBidは未使用のため、不要のはずだけど、念のため
      RefreshRates();

      if(type==OP_BUY)
        {
         aPrice=MarketInfo(symbol,MODE_BID);
           }else if(type==OP_SELL){
         aPrice=MarketInfo(symbol,MODE_ASK);
        }

      aPrice=NormalizeDouble(aPrice,digits);

      if(IsTradeContextBusy())
        {
           }else{
         result=OrderClose(aTicket,aLots,aPrice,aSlippage,aArrow_color);

         if(result)
           {
            return(result);
           }

         int err=GetLastError();

         // 一時的エラーの場合はリトライするが、恒常的エラーの場合は処理中断(リトライしてもエラーになるため)
         if(err == ERR_NO_ERROR ||
            err == ERR_COMMON_ERROR ||
            err == ERR_SERVER_BUSY ||
            err == ERR_NO_CONNECTION ||
            err == ERR_TOO_FREQUENT_REQUESTS ||
            err == ERR_TRADE_TIMEOUT ||
            err == ERR_INVALID_PRICE ||
            err == ERR_TRADE_DISABLED ||
            err == ERR_PRICE_CHANGED ||
            err == ERR_OFF_QUOTES ||
            err == ERR_BROKER_BUSY ||
            err == ERR_REQUOTE ||
            err == ERR_TOO_MANY_REQUESTS ||
            err==ERR_TRADE_CONTEXT_BUSY)
           {
              }else{
            return(result);
           }

         // 最適化とバックテスト時はリトライは不要
         if(IsOptimization() || IsTesting())
           {
            return(result);
           }
        }
      Sleep(SLEEP_TIME*MILLISEC_2_SEC);
     }

   return(result);
  }
//+------------------------------------------------------------------+
//|【関数】指定マジックナンバーの待機注文全削除                      
//|                                                                  
//|【引数】 IN OUT  引数名             説明                          
//|        --------------------------------------------------------- 
//|         ○      aMagic             マジックナンバー             
//|         △      aComment           対象コメント                  
//|                                                                  
//|【戻値】なし                                                      
//|                                                                  
//|【備考】△:既定値あり                                            
//+------------------------------------------------------------------+
void allOrderDelete(int aMagic,string aComment="")
  {
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(OrderSelect(i,SELECT_BY_POS)==false)
        {
         break;
        }

      if(OrderSymbol()!=Symbol() || OrderMagicNumber()!=aMagic)
        {
         continue;
        }

      if(aComment!="" && OrderComment()!=aComment)
        {
         continue;
        }

      int type=OrderType();

      if(type==OP_BUY || type==OP_SELL)
        {
         continue;
        }

      int ticket=OrderTicket();

      Print("Attempted allOrderDelete("+(string)aMagic+", Comment:"+aComment+")");

      bool result=orderDeleteReliable(ticket);

      if(result==false)
        {
         Print("allOrderDelete: Ticket #",ticket,", failed to delete");
        }
     }
  }
//+------------------------------------------------------------------+
//|【関数】信頼できる待機注文削除                                    
//|                                                                  
//|【引数】 IN OUT  引数名             説明                          
//|        --------------------------------------------------------- 
//|         ○      aTicket            チケット番号                  
//|                                                                  
//|【戻値】true :正常終了                                           
//|        false:異常終了                                           
//|                                                                  
//|【備考】なし                                                      
//+------------------------------------------------------------------+
bool orderDeleteReliable(int aTicket)
  {
   bool result=false;
   uint startTime=GetTickCount();
   while(true)
     {
      if(IsStopped())
        {
         return(-1);
        }
      if(GetTickCount()-startTime>MAX_RETRY_TIME*MILLISEC_2_SEC)
        {
         return(-1);
        }
      if(IsTradeContextBusy())
        {
           }else{
         result=OrderDelete(aTicket);

         if(result)
           {
            return(result);
           }

         int err=GetLastError();

         // 一時的エラーの場合はリトライするが、恒常的エラーの場合は処理中断(リトライしてもエラーになるため)
         if(err == ERR_NO_ERROR ||
            err == ERR_COMMON_ERROR ||
            err == ERR_SERVER_BUSY ||
            err == ERR_NO_CONNECTION ||
            err == ERR_TOO_FREQUENT_REQUESTS ||
            err == ERR_TRADE_TIMEOUT ||
            err == ERR_INVALID_PRICE ||
            err == ERR_TRADE_DISABLED ||
            err == ERR_PRICE_CHANGED ||
            err == ERR_OFF_QUOTES ||
            err == ERR_BROKER_BUSY ||
            err == ERR_REQUOTE ||
            err == ERR_TOO_MANY_REQUESTS ||
            err==ERR_TRADE_CONTEXT_BUSY)
           {
              }else{
            return(result);
           }

         // 最適化とバックテスト時はリトライは不要
         if(IsOptimization() || IsTesting())
           {
            return(result);
           }
        }

      Sleep(SLEEP_TIME*MILLISEC_2_SEC);
     }

   return(result);
  }


以上、ご購読いただきありがとうございました。

ご質問・ご意見は以下メールアドレスへお気軽にご連絡下さい。
gabrielfx2100@gmail.com

公式LINEの友達追加はコチラ
(ガブリエルのFX事情を配信中です)

記事をご覧いただきありがとうございます。 皆様のサポートが次の記事を書くモチベーションに繋がっています! もしよろしければサポートしていただけると嬉しいです!