【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事情を配信中です)
記事をご覧いただきありがとうございます。 皆様のサポートが次の記事を書くモチベーションに繋がっています! もしよろしければサポートしていただけると嬉しいです!