注文成功時
OrderSend()関数でエラーが発生した場合の説明の前に、成功時の説明をします。
OrderSend()関数を使った新規注文を発注し、サーバーが注文を受け付けてくれた場合、戻り値にチケットNoを返してくれます。
FXトレーダーでチケットNoを知らない人はいないと思いますが、
これは手動やEAに関係なく全ての注文に対してチケットNoが付与されます。
今保有している注文に対してリミット・ストップ・決済注文をしたい場合は、このチケットNoのポジションに対して行います。
リミット・ストップ・決済注文の方法は長くなるので別途記載しますが、今回はチケットNoのログ出力だけ行います。
ソースコード:
if ( IsDemo() == false ) {
Print("デモ口座でのみ動作します");
return;
}
int ea_ticket_res = -1;
ea_ticket_res = OrderSend(
Symbol(),
OP_BUY,
0.01,
Ask,
20,
0,
0,
"テストオーダー",
20200518
);
if ( ea_ticket_res != -1) {
printf( "【%d】エントリーオーダー正常完了。チケットNo = %d" , __LINE__ , ea_ticket_res);
}
まぁMT4が自動でオーダー情報をログ表示してくれるので意味の無い処理ですが、勉強用という事でw
成行注文が約定した直後にリミット・ストップ注文を入れたい場合はここに処理を追加します。
ただリミット・ストップ注文はこの段階で必ず入れなければならないわけでは無く、EA作成者次第になるので今回は説明しません、別ページにて説明します。
注文失敗時
本題のOrderSend()関数を使った発注でエラーになった場合の処理を説明します。
OrderSend()でエラーになった場合、エラー情報を必ずログ出力するようにして下さい。
ログを残さないと一体何が原因でエラーになったか分からなくなります。
特に取引サーバー側の問題によるエラーだった場合、バックテストでは絶対に再現出来ないエラーの可能性が高く、
ログが残っていないと
デバッグする事が非常に困難になります。
それではエラーの場合にログ出力する処理を追加しましょう。
OrderSend()はエラーの場合は戻り値に-1を返すので、戻り値が-1の時にエラーログ出力するようにします。
基本的に
D3.ログ出力を用いたデバッグと同じ内容の処理ですので詳しくは説明しません。
詳細は
D3.ログ出力を用いたデバッグのページを参照して下さい。
ErrorDescription()関数は
stdlib.mqhを
インクルードしていないと使えないので注意。
C言語と違ってMQL4ではインクルードを使用する事はあまり無い(上級者は除く)ので、詳細説明は別途します。
今回はとりあえず関数の外に以下ソースコードを追加して下さい。
ランタイムエラーの場合
ログ出力処理を追加したら、実際にエラーになるようにしてみましょう。
一番簡単な方法は異常なロットを指定する事です。
OrderSend()関数の
ロットの引数設定を0に変更して、スクリプトを実行してみて下さい。
結果:
[45]エントリーオーダーエラー。 エラーコード=4051 エラー内容=invalid function parameter value
4桁のエラーコードとエラー内容がログ出力されたと思います。
「引数の値が無効」というエラー内容です。
4桁のエラーコードは
ランタイムエラーなのでサーバーへの発注は行われていません。
この場合は完全にソースコード自体に問題があるエラーになります。
トレードサーバーが返すエラーの場合
次はサーバー側が約定拒否をした場合のエラーを確認しましょう。
今度は
ロットの設定を0.001(百通貨)にして試して下さい。
結果:
[45]エントリーオーダーエラー。 エラーコード=131 エラー内容=invalid trade volume
今度は3桁のエラーコードがログ出力されました。
「無効なトレード量(lot数)です」というエラー内容です。
3桁のエラーコードは
トレードサーバーが返すエラーなので、
サーバーへの発注が行われ、その注文が拒否された時のエラーです。
この手のエラーはバックテスト中では発生しないケースもあります。
今回のケースではソースコード自体に問題がありますが、
3桁のエラーコードの場合は必ずしもソースコードが問題とは限らない場合があるので、エラーコードをログ出力していないと原因を見つける事が困難になる場合があります。
(トレードサーバーが返すエラーの場合、通常ログは「エキスパート」では無く「取引履歴」の方に表示されます。 )
例えば「136:ERR_OFF_QUOTES(レートが提示されていません)」はトレードサーバー側の都合によるエラーになります。
高速取引していた時はこのエラーが頻繁に出ました。あまりにも
流動性が低下すると気配値表示されていても約定拒否される事があります。
この場合はプログラムが悪いわけでは無いのでどうしようもありません。
完成したサンプルソースコード
ソースコード:
#property copyright "yuki"
#property link "https://yukifx.web.fc2.com/"
#property version "1.00"
#property strict
#include <stdlib.mqh>
void OnStart()
{
if ( IsDemo() == false ) {
Print("デモ口座でのみ動作します");
return;
}
int ea_ticket_res = -1;
ea_ticket_res = OrderSend(
Symbol(),
OP_BUY,
0.01,
Ask,
20,
0,
0,
"テストオーダー",
20200518
);
if ( ea_ticket_res != -1) {
printf( "【%d】エントリーオーダー正常完了。チケットNo = %d" , __LINE__ , ea_ticket_res);
} else {
int get_error_code = GetLastError();
string error_detail_str = ErrorDescription(get_error_code);
printf( "[%d]エントリーオーダーエラー。 エラーコード=%d エラー内容=%s"
, __LINE__ , get_error_code , error_detail_str
);
}
}