前回は、待機注文を修正するメンバ関数「ChangePending関数」をOriginalCTradeクラスに追加する模様を解説しました。
待機注文を削除する関数「DeletePending」を宣言する
例によって、まずはOriginalCTradeクラスにまずはメンバ関数を宣言します。
関数名は「DeletePending」とします。
EA(自動売買プログラム)のメインプログラムで呼び出す事を目的としているので、アクセスレベルはpublicになります。
publicセクションであればどこでも良いのですが、前回作ったChangePending関数の下あたりに、宣言を行います。
//待機注文を修正する
bool ChangePending(ulong parTicket, double parPrice, double parStop, double parProfit, datetime parExpiration = 0);
//待機注文を削除する
bool DeletePending(ulong parTicket);
※クラスのアクセスレベルについては↓の記事をご参照ください。
DeletePending関数の仮引数と戻り値について
DeletePending関数の仮引数と戻り値は以下の通りです。
//待機注文を削除する
bool DeletePending(ulong parTicket);
parTicketには待機注文のオーダー番号が記述される想定になっています。
※MQL5ではオーダー番号、ポジション番号、約定番号(ディール番号)という概念が存在します。
それぞれの違いについては各用語のアンカーテキストリンクから該当の記事をご参照ください。
DeletePending関数の処理実装記述について
DeletePending関数の処理実装記述は以下の通りです。
//待機注文を削除する
bool OriginalCTrade::DeletePending(ulong parTicket)
{ //インスタンスのリセット
ZeroMemory(request);
ZeroMemory(result);
//各種メンバ変数への値代入
request.action = TRADE_ACTION_REMOVE;
request.order = parTicket;
// リトライ回数とリターンコードを格納する変数を宣言
int retryCount = 0;//再試行回数を格納する
int checkCode = 0;//リターンコードを格納する
do
{ //待機注文の削除注文を出す。
bool sent = OrderSend(request,result);
//注文結果を返す
checkCode = ReturnCodeCheck(result.retcode);
//約定成功の場合do-whileループを抜ける
if(checkCode == CHECK_RETCODE_OK) break;
//再試行しても解決しないエラーの場合
else if(checkCode == CHECK_RETCODE_ERROR)
{ //リターンコードを取得
string errDesc = TradeServerReturnCodeDescription(result.retcode);
//アラートを発出
Alert("待機注文削除エラー: エラー内容 ",result.retcode," - ",errDesc);
//ログの出力
TradeLog();
break;//ループを抜ける
}
else
{
Print("サーバーエラーを検知。 再試行中...");
//次の処理までの待機
Sleep(RETRY_MILLISECONDS);
//再試行回数をカウントする変数をインクリメントする
retryCount++;
}
}
while(retryCount < RETRY_LIMIT);
if(retryCount >= RETRY_LIMIT)
{
string errDesc = TradeServerReturnCodeDescription(result.retcode);
Alert("再注文上限回数に達しました: エラー内容 ",result.retcode," - ",errDesc);
}
string errDesc = TradeServerReturnCodeDescription(result.retcode);
Print("待機注文削除エラー #",parTicket,": ",
result.retcode," - ",errDesc);
if(checkCode == CHECK_RETCODE_OK)
{
Comment("待機注文 ",parTicket," 削除されました");
return(true);
}
else return(false);
}
講座記事を順番に見ている方には、もはや説明不要の記述が増えてきたかもしれませんが、この記事だけスポット的に見ることもあるかと思うので、例によって順番にコードの記述を見ていきましょう。
処理実装記述その1:-インスタンスのリセット~各種メンバ変数への値代入-
MqlTradeRequest構造体やMqlTradeResult構造体のインスタンスをリセット~各種メンバ変数への値代入というお決まりの流れです。これまでの講座記事では
第72回「ポジションオープン関数を実装する」、第76回「SLとTPを設定する関数をクラスに追加する」、第85回「ポジションを決済する関数を作る」、第90回「待機注文を修正する関数を実装する」
などでも解説してきた記述です。
//インスタンスのリセット
ZeroMemory(request);
ZeroMemory(result);
//各種メンバ変数への値代入
request.action = TRADE_ACTION_REMOVE;
request.order = parTicket;
待機注文の削除にあたって必要なMqlTradeRequest構造体のメンバ変数は、.actionと.orderのみです。
新規成行注文、新規待機注文、現有ポジションのSLTP変更、待機注文修正などに比べるとシンプルですね。
取引の種類を設定する.actionには、待機注文を削除する定数値TRADE_ACTION_REMOVEを代入します。
request.order はオーダー番号を格納するメンバ変数なので、オーダー番号が記述される想定の仮引数「parTicket」の値を代入します。
※インスタンスについては、↓の記事をご参照ください。
処理実装記述その2-リトライ回数とリターンコードを格納する変数を宣言する-
<参照リンク>
// リトライ回数とリターンコードを格納する変数を宣言
int retryCount = 0;//再試行回数を格納する
int checkCode = 0;//リターンコードを格納する
処理実装記述その3-do-while文の中に発注回路を組み込んでいく-
他の注文関数と同様にdo-while文を使って、待機注文の削除に関する発注回路を記述していきます。
do
{ //待機注文の削除注文を出す。
bool sent = OrderSend(request,result);
//注文結果を返す
checkCode = ReturnCodeCheck(result.retcode);
//約定成功の場合do-whileループを抜ける
if(checkCode == CHECK_RETCODE_OK) break;
//再試行しても解決しないエラーの場合
else if(checkCode == CHECK_RETCODE_ERROR)
{ //リターンコードを取得
string errDesc = TradeServerReturnCodeDescription(result.retcode);
//アラートを発出
Alert("待機注文削除エラー: エラー内容 ",result.retcode," - ",errDesc);
//ログの出力
TradeLog();
break;//ループを抜ける
}
else
{
Print("サーバーエラーを検知。 再試行中...");
//次の処理までの待機
Sleep(RETRY_MILLISECONDS);
//再試行回数をカウントする変数をインクリメントする
retryCount++;
}
}
while(retryCount < RETRY_LIMIT);
OrderSend関数で待機注文の削除注文を出す
ReturnCodeCheck関数で注文結果の次を行動を規定する。
↓
「約定が成功した場合」「再試行しても解決しないエラーの場合」「再試行すれば解決する可能性のあるエラーの場合」という3つをif文 else文で条件分岐させ処理を切り分けていきます。
※TradeServerReturnCodeDescription関数については→コチラをご覧ください。
※ReturnCodeCheck関数の戻り値であるデータ型「ENUM_CHECK_RETCODE」については→コチラをご覧ください。
※do-while構文については、→の記事をご覧ください。第39回「do-while文について」
※インクリメントについては↓をご覧ください。
インクリメントとデクリメント(Increment,Decrement)
処理実装記述その4-再注文試行が上限回数に達した場合の記述-
if(retryCount >= RETRY_LIMIT)
{
string errDesc = TradeServerReturnCodeDescription(result.retcode);
Alert("再注文上限回数に達しました: エラー内容 ",result.retcode," - ",errDesc);
}
if(retryCount >= RETRY_LIMIT)
という記述は↑再注文試行回数が#define命令で設定した定数RETRY_LIMITの数を上回っている事を意味します。
TradeServerReturnCodeDescription関数でリターンコードを獲得後、変数「errDesc」に格納→Alert関数で変数に格納された内容を発出します。
処理実装記述その5:結果をPrint関数でログ出力
string errDesc = TradeServerReturnCodeDescription(result.retcode);
Print("待機注文削除エラー #",parTicket,": ",
result.retcode," - ",errDesc);
待機注文削除の結果をPrint関数でログ出力します。この処理は、待機注文の削除が成功した場合でも、失敗した場合でも行います。
処理実装記述その6:戻り値を返して終了
if(checkCode == CHECK_RETCODE_OK)
{
Comment("待機注文 ",parTicket," 削除されました");
return(true);
}
else return(false);
}
DeletePending関数の戻り値はbool型です。待機注文の削除に成功した場合はtrue、失敗した場合はfalseを返すよう設計しています。
まとめ
今回の記事では、待機注文を削除するメンバ関数「DeletePending関数」をOriginalCTradeクラスに追加する模様を解説しました。
※今回の関数はあくまで「待機注文の削除する」為の関数です。いったん待機注文が約定しポジションとして有効化された場合は、この関数を使ってポジションをクローズする事はできません。
ポジションをクローズするする場合は、第85回「ポジションを決済する関数を作る」で作ったClosePosition関数を使います。
DeletePending関数の宣言部分↓は以下の通りです。
//待機注文を削除する
bool DeletePending(ulong parTicket);
の処理実装記述部分↓は以下の通りです。
//待機注文を削除する
bool OriginalCTrade::DeletePending(ulong parTicket)
{ //インスタンスのリセット
ZeroMemory(request);
ZeroMemory(result);
//各種メンバ変数への値代入
request.action = TRADE_ACTION_REMOVE;
request.order = parTicket;
// リトライ回数とリターンコードを格納する変数を宣言
int retryCount = 0;//再試行回数を格納する
int checkCode = 0;//リターンコードを格納する
do
{ //待機注文の削除注文を出す。
bool sent = OrderSend(request,result);
//注文結果を返す
checkCode = ReturnCodeCheck(result.retcode);
//約定成功の場合do-whileループを抜ける
if(checkCode == CHECK_RETCODE_OK) break;
//再試行しても解決しないエラーの場合
else if(checkCode == CHECK_RETCODE_ERROR)
{ //リターンコードを取得
string errDesc = TradeServerReturnCodeDescription(result.retcode);
//アラートを発出
Alert("待機注文削除エラー: エラー内容 ",result.retcode," - ",errDesc);
//ログの出力
TradeLog();
break;//ループを抜ける
}
else
{
Print("サーバーエラーを検知。 再試行中...");
//次の処理までの待機
Sleep(RETRY_MILLISECONDS);
//再試行回数をカウントする変数をインクリメントする
retryCount++;
}
}
while(retryCount < RETRY_LIMIT);
if(retryCount >= RETRY_LIMIT)
{
string errDesc = TradeServerReturnCodeDescription(result.retcode);
Alert("再注文上限回数に達しました: エラー内容 ",result.retcode," - ",errDesc);
}
string errDesc = TradeServerReturnCodeDescription(result.retcode);
Print("待機注文削除エラー #",parTicket,": ",
result.retcode," - ",errDesc);
if(checkCode == CHECK_RETCODE_OK)
{
Comment("待機注文 ",parTicket," 削除されました");
return(true);
}
else return(false);
}
今回紹介した現時点(講座記事第91回時点)でのOriginalTrade.mqhファイル全体のコード記述は↓の記事からご確認ください。
講座記事第91回時点でのOriginalTrade.mqhファイル全体のコード記述について
※講座記事第90回時点でのOriginalTrade.mqhファイル全体のコード記述は↓コチラ
講座記事第90回時点でのOriginalTrade.mqhファイル全体のコード記述について
※講座記事第87回時点でのOriginalTrade.mqhファイル全体のコード記述は↓コチラ
講座記事第87回時点でのOriginalTrade.mqhファイル全体のコード記述について
第86回、第87回、第88回、第89回、第90回、そして今回の第91回の6回にかけて待機注文のクラス・関数を作ってきました。次回はこれらを利用して待機注文を使ったEA(自動売買プログラム)を作っていきたいと思います。
今回は以上とさせていただきます。
最後までお読みいただきありがとうございました。
コメント