pekonoriブログ関連

Expert Advisor Programming for MetaTrader5【日本語訳 第九章】発注

  1. HOME >
  2. pekonoriブログ関連 >

Expert Advisor Programming for MetaTrader5【日本語訳 第九章】発注

発注 P79

OderSend() P79

OrderSend()関数は注文の発注、変更およびクローズに使用されます。関数の使用法がMQL4から変更されました。OrderSend()の関数定義は次の通りです。

                  bool OrderSend(MqlTreadeRequest& request, MqlTreadeResult& result)

OrderSend()関数には2つのパラメータがあります。注文パラメータを含むMqlTreadeRequest オブジェクトと注文リクエストの結果を返す MqlTreadeResultオブジェクトです。関数定義の&(アンパサンド)は両方のオブジェクトが参照によって渡されることを示します。

MqlTradeRequest構造体 P79

MqlTradeRequest構造を調べてみましょう。23ページの構造体については以前に説明しました。MqlTradeRequest型のオブジェクトを宣言し、トレードパラメータをオブジェクトのメンバー変数に割り当てます。MQL5リファレンスからのMqlTradeRequest構造定義は次のとおりです。

struct MqlTradeRequest

{

ENUM_TRADE_REQUEST_ACTIONS action;  //トレード操作タイプ

ulong magic;                                 //マジックナンバー

ulong order;                                 //注文チケット(未決済注文の変更用)

string symbol;                               //シンボル

double volume;                             //ロット単位のボリューム

double price;                               //注文始値

double stoplimit;                           //ストップリミット価格(ストップリミット注文の場合)

double sl;                                   //ストップロス価格

double tp;                                  //テイクプロフィット価格

ulong deviation;                            //ポイント単位の偏差

ENUM_ORDER_TYPE type;                  //注文タイプ

ENUM_ORDER_TYPE_FILLING type_filling;  //実行タイプ

ENUM_ORDER_TYPE_TIME type_time;      //有効期限タイプ

datetime expiration;                       //有効期限

string comment;                            //注文コメント

ulong position;                             //ポジションチケット(ヘッジ注文の変更用)

ulong position_by;                          //反対側のチケット(近接用)

}

MqlTradeRequestオブジェクトを宣言するには、MqlTradeRequestを宣言するだけです。

                  MqlTradeRequest request ;

これにより、requestという名前のオブジェクトが作成されます。MqlTradeRequestオブジェクトは通常、プロブラムのOnTick()イベントハンドラの早い段階で、またはクラスメンバーとして宣言されます。ドット()演算子を使用して、トレードパラメータをオブジェクトの変数に割り当てられることができます。

request.symbol = Symbol;

request.volume = 0.5;

request.type = ORDER_TYPE_BUY;

MqlTradeRequest構造体のメンバーを詳しく見てみましょう。

○ Action – 取引操作タイプ。必須。この変数はENUM_TRADE_REQUEST_ACTION列挙の値を受け入れます。

・  TRADE_ACTION_DEAL – Order Send()関数は成行き注文を出します。

  • TRADE_ACTION_PENDING – Order Send()関数は未決注文を出します。
  • TRADE_ACTION_SLTP – Order Send()関数は現在のポジションのストップロスおよび/またはテイクプロフィットを変更  

します。

  • TRADE_ACTION_MODIFY – Order Send()関数は以前に出された未決注文を変更します。
  • TRADE_ACTION_REMOVE – Order Send()関数は以前に出された未決注文をキャンセルします。
  • TRADE_ACTION_CLOSE_BY – Meta Trader5に追加された新機能。Order Send()関数は一度に2つのポジションを決済し、2つのポジションを別々に決済することで消費される1つのスプレッドを節約します。

○ magic - 「マジックナンバー」この番号は特定のEAによって発注された注文を一意に識別します。オプション。

○ order –以前に出された未決注文の注文チケット。action変数がTRADE_ACTION_MODIFYまたTRADE_ACTION_REMOVE

に設定されている場合は必須です。

○ Symbol – 取引する金融証券のシンボル(例:”EURUSD”または_Symbol)。必須。

○ volume – ロット単位の取引量。必須。

○ price – 注文の始値。未決注文の場合、価格は現在の市場価格より上または下の有効な価格にすることができます。成り行き注文の場合、価格は現在のask価格(買い注文の場合)または現在のbid価格(売り注文の場合)でなければなりません。成り行き又は取引所の執行を使用するブローカーは成行き注文を出すときにこのパラメータを必要としません。それ以外の場合、actionがTRADE_ACTION_DEAL、 TRADE_ACTION_PENDING、またはTRADE_ACTION_MODIFYに設定されている場合は必須です。

○ stoplimit – これは、ストップリミット注文の指値注文価格です。action変数はTRADE_ACTION_PENDINGに設定する必要があり、以下のタイプ変数はORDER_TYPE_BUY_STOP_LIMITまたはORDER_TYPE_SELL_STOP_LIMITに設定する必要があります。ストップリミット注文に必要です。

○ sl – ストップロス価格。ブローカーがリクエストまたは即時実行タイプを使用する場合、成り行き注文に必要です。指値注文にも必要です。ブローカーが市場または取引所の実行を使用する場合、ストップロスは配置されません。

○ tp - テイクプロフィット価格。ブローカーがリクエストまたは即時実行タイプを使用する場合、成り行き注文に必要です。指値注文にも必要です。ブローカーが市場又は取引所の執行を使用する場合、テイクプロフィットは設定されません。

○ deviation - ポイント単位の最大偏差。成り行き注文のリクエストまたは即時実行に必要です。

○ type – 注文タイプ。この変数はENUM_ORDER_TYPE列挙の値を受け入れます。必須。

・ ORDER_TYPE_BUY – 成り行き買い注文

・ ORDER_TYPE_SELL – 成り行き売り注文

・ ORDER_TYPE_BUY_STOP – ストップ未決買い注文

・ ORDER_TYPE_SELL_STOP – ストップ未決売り注文

・ ORDER_TYPE_BUY_LIMIT – 指値未決買い注文

・ ORDER_TYPE_BUY_STOP_LIMIT – ストップリミット未決買い注文

・ ORDER_TYPE_SELL_STOP_LIMIT – ストップリミット未決売り注文

○ type_filling – 注文の条約ポリシー。この変数はENUM_ORDER_TYPE_FILLING列挙の値を受け入れます。指定しない場合、取引サーバーのデフォルトが使用されます。

・  ORDER_FILLING_FOK – FillまたはKill。要求された取引量と価格で注文が約定できない場合、注文は発注されません。

  • ORDER_FILLING_IOC – 即時またはキャンセル(FillまたはCancelとも呼ばれる)。注文が要求された取引量と価格で約定                      

できない場合、部分注文が約定されます。 

  • ORDER_FILLING_RETURN - 返品。注文が要求された取引量と価格で約定できない場合、取引サーバーは未約定量の追加  

注文を出します。

○ type_time – 指値注文の有効期限タイプ。この変数はENUM_ORDER_TYPE_TIME列挙の値を受け入れます。オプション。指定しない場合、取引サーバーのデフォルト(通常はGood Til Canceled)が使用されます。

・ ORDER_TIME_GTC – グッドティルキャンセル。保留中の注文は期限切れになりません。

・ ORDER_TIME_DAY - 未決注文は取引日の終わりに失効します。

・ ORDER_TIME_SPECIFIED – 保留中の注文は以下の有効期限変数で指定された日時に期限切れになります。

○ expiration - 未決注文の有効期限。type_time変数がORDER_TIME_SPECIFIEDに設定されている場合は必須です。値は日時型である必要があり、将来のある時点で設定する必要があります。

○ comment - 注文コメントとして使用するテキスト文字列。

○ position – ヘッジポジションのオーダーチケット。ヘッジ注文を修正又はクローズする場合にのみ使用されます。

○ position_by – クローズする反対のヘッジポジションのオーダーチケット。Close By注文操作については後程説明します。

成行注文を開く P82

MqlTradeRequest構造体を利用して成行き注文を出す方法を示しましょう。最初に行う必要があるのはMqlTradeRequestおよびMqlTradResultオブジェクトを宣言することです。MqlTradeResult構造については、次の章で説明します。

                  MqlTradeRequest request ;

MqlTradResult result ;

この例では、ストップロスまたはテイクプロフィットなしで現在のチャートシンボルに1.00ロットの買い成行き注文を出します。

                  request.action = TRADE_ACTION_DEAL ;

                  request.type = ORDER_TYPE_BUY ;

                  request.symbol = _Symbol ;

                  request.volume = 1 ;

                  request.type = ORDER_FILLING_FOK ;

                  request.price = SymbolInfoDouble(_Symbol,SYMBOL_ASK) ;

                  request.sl = 0 ;

                  request.tp = 0 ;

                  request.deviation = 50 ;

                  request.magic = 43 ;

                  OrderSend(request,result) ;

action変数はTRADE_ACTION_DEALに設定され、これは成行き注文であることを示します。type変数はORDER_TYPE_BUYに設定され、これは買い注文であることを示します。定義済みの_Symbol変数をシンボル変数に割り当てて、現在のチャートシンボルに注文を出すことを示します。volume変数は1ロットに設定されます。type_filling変数は塗りつぶしタイプをFillまたはKillに設定します。すべての実行タイプで、上記の5つの変数を指定する必要があります。(type_fillingが指定されていない場合はサーバーのデフォルトのfillポリシーがデフォルトになります。)

SymbolInfoDouble()関数を使用して、現在のチャートシンボルの現在の売値を返し、その値を価格変数に割り当てます。買い成行き注文は現在のask価格で発注されることに注意して下さい。sl変数とtp変数は両方ともゼロに設定されます。偏差変数は、偏差を50ポイントに設定します。

市場または取引所の実行タイプを使用するブローカーは、価格、sl、tp、および偏差変数を無視します。ただし、実行タイプに関係なくすべてのプローカーでコードを動作させたいため、インスタントまたはrequest実行タイプを使用するブローカーのこれらの変数に値を割り当てます。

特にヘッジ口座で取引している場合は、マジックナンバーを指定することをお勧めします。マジックナンバーはこのEAによって設定された注文を識別するユーザーによって設定された識別子です。上記の例では、マジックナンバーを43に設定しています。

ストップロスまたはテイクプロフィットが定義されていないことに注意して下さい。市場及び為替執行ブローカーはストップロスを無視して利益を確定するため、注文後にポジションにストップロスを追加して利益を確定します。これにより、ポジションの開始価格に対するストップロスとテイクプロフィットの正確な配置も保証されます。

最後にOrderSend()関数を呼び出して、リクエストオブジェクトと結果オブジェクトをパラメータとして渡します。取引サーバーは注文を出そうと試み、結果オプジェクト変数に結果を返します。

ストップロスを追加して利益を得る P83

成行き注文を出した後、指定されている場合はストップロスとテイクプロフィットを追加します。簡単にするためにこの例では、有効なストップロスとテイクプロフィットの価格をsl変数とtp変数に割り当てます。以下の例は、nettingポジションの注文を変更します。

                  request.action = TRADE_ACTION_SLTP ;

                  request.symbol = _Symbol ;

                  request.sl = 1.3500 ;

                  request.tp = 1.3650 ;

                  OrderSend(request,result);

action変数はTRADER_ACTION_SLTPに設定されています。これは現在のポジションでストップロスとテイクプロフィットを変更することを示します。シンボル変数は、現在のチャートシンボルのオープンポジションを変更することを指定します。ポジションの開始価格が1.3500から1.3650の間であると仮定して、買いポジションで有効なストップロスとテイクプロフィットの価格を設定しました。

ストップロスまたはテイクプロフィットの値が変更されていないかどうかに関係なく、ポジション変更するときは、上記の全ての変数を指定する必要があります。ストップロスまたはテイクプロフィットの値を設定したくない場合は、適切な変数をゼロに設定します。

ヘッジポジションのストップロスまたはテイクプロフィットの価格を変更する場合、request.positionパラメータを使用して、変更するオープンポジションのチケット番号を指定する必要があります。マジックナンバーを指定することもできます。これは、どの注文がEAによって行われたかを判断するために使用される一意の識別子です。この例では、オープン注文の有効なチケット番号であると想定する任意のチケット番号を使用し、マジックナンバー43を設定します。

                  request.action = TRADE_ACTION_SLTP ;

                  request.symbol = _Symbol ;

                  request.sl = 1.3500 ;

                  request.tp = 1.3650 ;

                  request.position = 452365 ;

                  request.magic = 43 ;

                  OrderSend(request,result)

成行注文を閉める P84

成行き注文を閉じるには、同じシンボルに反対の取引要求を出すだけです。nettingポジションの場合、ポジションの一部または全部をクローズするか、現在開いているポジションよりも大きなボリュームを指定してポジションを反転させることもできます。この例では、以前に配置した買いポジションをクローズします。

                  request.action = TRADE_ACTION_DEAL ;

                  request.type = ORDER_TYPE_SELL ;

                  request.symbol = Symbol ;

                  request.volume = 1 ;

                  request.type_filling = ORDER_FILLING_FOK ;

                  request.price = SymbolInfoDouble(_Symbol,SYMBOL_BID);

                  request.deviation = 50 ;

OrderSend(request,sesult) ;

ヘッジポジションの場合、request.position変数に割り当てて、注文のチケット番号も指定する必要があります。

request.action = TRADE_ACTION_DEAL ;

                  request.type = ORDER_TYPE_SELL ;

                  request.symbol = Symbol ;

                  request.volume = 1 ;

                  request.type_filling = ORDER_FILLING_FOK ;

                  request.price = SymbolInfoDouble(_Symbol,SYMBOL_BID);

                  request.deviation = 50 ;

                  request.position = 452365 ;

                  OrderSend(request,result) ;

ヘッジ注文の変更とクローズ P85

ストップロスまたはテイクプロフィットを追加するとき、またはヘッジアカウントで成行き注文を閉じるときは、追加の変数を指定する必要があります。request.position変数は変更または決済する成行き注文の注文チケット番号を受け取ります。以下の例ではrequrst.position変数に割り当てられたチケット番号に一致する買い成行き注文をクローズします。

request.action = TRADE_ACTION_DEAL ;

                  request.type = ORDER_TYPE_SELL ;

                  request.symbol = Symbol ;

                  request.position = 5211547 ;

                  request.volume = 1 ;

                  request.type_filling = ORDER_FILLING_FOK ;

                  request.price = SymbolInfoDouble(_Symbol,SYMBOL_BID);

                  request.deviation = 50 ;

                  OrderSend(request,result) ;

操作で閉じる P85

Metarader5の新機能は”クローズバイオペレーション”です。これにより、2つの反対のhedgingポジションを一度にクローズし、効果的にスプレッドを節約できます。request.position_by変数を使用して、2番目のチケット番号を指定する必要があります。

                  request.action = TRADE_ACTION_CLOSE_BY ;

                  request.position = 452365 ;

                  request.posision = 451256 ;

                  OrderSend(request,result) ;

未決注文を開く P86

次に、指値注文の配置を示しましょう。この注文にストップロス、テイクプロフィット、有効期限を追加します。指値注文を出すときは、以下の全ての変数を指定する必要があります。

                  request.action = TRADE_ACTION_PENDING ;

                  request.type = ORDER_TYPE_BUY_STOP ;

                  request.symbol = _Symbol ;

                  request.volume = 1 ;

                  request.price = 1.3550 ;

                  request.sl = 1.3500 ;

                  request.tp = 1.3650 ;

                  request.type_time = ORDER_TIME_SPECIFIED ;

                  request.expiration = D’2018.01.10 15:00’ ;

                  request.type_filling = ORDER_FILLING_FOK ;

                  request.stoplimit = 0 ;

                  OrderSend(request,result);

action変数はTRADE_ACTION_PENDINGに設定され、未決注文を出していることを示します。type変数はORDER_TYPE_BUY_STOPに設定され、買いストップ注文を示します。Symbol、volume、価格、slおよびtp変数にはすべて適切な値が割り当てられます。

type_time変数はORDER_TIME_SPECIFIEDに設定されます。これは、注文に有効期限があることを示します。2018年1月10日 15:00の日時設定が有効変数に割り当てられています。type_filling変数は塗りつぶしタイプのfillまたはkillに設定します。Stoplimit変数はストップリミット注文を出すときにのみ必要ですが、値0を割り当てます。

指値注文を変更する P86

指値注文を変更する方法を示しましょう。未決注文を変更するには、未決注文の注文チケットが必要です。注文チケットを取得するには、OrderGetTicket()関数を使用して注文プールを反復処理し、適切な未決注文を選択します。未決注文の管理については第13章で説明します。ここでは、ticket変数が正しい注文チケット番号を保持していると仮定します。

request.action = TRADE_ACTION_MODIFY ;

                  request.order = _ticket ;

                  request.price = 1.3600 ;

                  request.sl = 1.3500 ;

                  request.tp = 1.3700 ;

                  request.type_time = ORDER_TIME_SPECIFIED ;

                  request.expirtion = D’2018.01.10 18:00’ ;

                  OrderSend(request,result) ;

action変数TRADE_ACTION_MODIFYに設定され、現在の注文を変更していることを示します。Order変数には、変更したい注文のチケット番号が割り当てられます。これはticket変数に保存されます。Price、sl、tpおよび expiration変数には適切な値が割り当てられ、注文はこれらの変更を反映するように変更されます。

保留中の注文を削除する P87

最後に、保留中の注文を削除する方法を示します。必要な変数はaction変数とorder変数だけです。

                  request.action = TRADE_ACTION_REMOVE ;

                  request.order = ticket ;

                  OrderSend(request,result) ;

Action変数はTRADE_ACTION_REMOVEに設定され、未決注文を削除したいことを示します。以前と同様に、チケット番号はticket変数に格納され、リクエストオブジェクトのorder変数に割り当てられます。上記のパラメータでOrderSend()関数を呼び出すと、注文変数のチケット番号と一致する未決注文が削除されます。

MqlTradeResult構造体 P87

OrderSend()関数を使用して注文を出した後、MqlTraderResultオブジェクトをチェックして、注文が成功したかどうかを確認します。MqlTradeResultオブジェクトの変数には、取引サーバーからのリターンコード、取引のチケット番号、取引のボリュームと価格、およびbidとaskの価格が含まれます。MQL5リファレンスからのMqlTradeResult構造の定義は次のとおりです。

struct MqlTradeResult

{

uint retcode ;      //リターンコード

ulong deal ;        //ディールチケット

ulong order ;       //注文チケット

double volume ;    //取引量

double price ;      //取引価格

double bid ;        //現在のbid価格

double ask ;        //現在のask価格

string comment ;   //オペレーションへのブローカー コメント

}

この章で示したようにresultという名前のMqlTradeResultオブジェクトを宣言し、そのオブジェクトをOrderSend()関数の2番目のパラメータとして渡します。取引サーバーは取引リクエストの結果でオブジェクトを埋めます。OrderSend()関数が呼び出された後、MqlTradeResultオブジェクトの変数をチェックして、取引が正しく行われたことを確認します。取引操作のタイプによっては、すべてのMqlTradeResult変数が満たされるわけではありません。

MqlTradeResult構造体の最も重要な変数は、取引サーバーからの戻りコードであるretcodeです。戻りコードは要求が成功したかどうかを示します。取引が行われなかった場合、リターンコードはエラー状態を示します。

各戻りコードは定数で表されます。もっとも一般的なリターンコードはTRADE_RETCODE_PLACED(10008) とTRADE_RETCODE_DONE(10009)で、どちらも取引が正常に行われたことを示します。他のほとんどすべてのリターンコードは、取引を行う際の問題を示しています。戻りコードの説明は、問題の性質を示します。

リターンコードの完全なリストは、MQL5リファレンスの標準定数、列挙および構造>エラーおよび警告のコード>取引サーバーリターンコードの下にあります。

リターンコードに応じて、取引確認を電子メールで送信したり、エラーメッセージを画面に出力したりするなど、さまざまなアクションを実行する必要がある場合があります。サーバーからの戻りコードを処理する方法の簡単な例を次に示します。

                  OrderSend(request,result)

If(result.retcode == TRADE_RETCODE_DONE || result.retcode == TRADE_RETCODE_PLACED)

{

                  Print(“trade placed”);

}

else

{

                  Print(“ trade not placed. Error code ” , result.retcode);

}

OrderSend()関数が取引リクエストをサーバーに送信し、結果オブジェクトの変数を埋めた後、request.retcode変数で戻りコードを確認します。戻りコードがTRADE_RETCODE_DONEまたはTRADE_RETCODE_PLACEDに等しい場合、取引が正常に行われたことを示すメッセージをログに出力します。それ以外の場合は、取引が行われなかったことを示すメッセージと、エラー状態を示すリターンコードを出力します。

取引変数と注文変数には、取引の取引チケット番号と注文チケット番号が含まれます。注文は取引を行うための最初の要求であり、取引は取引が行われたことの確認です。nettingポジションの場合、シンボル名でポジションを処理するため、通常はチケット番号を気にする必要はありません。逆に、注文チケット番号は、hedgingを処理する際に非常に重要であり、ヘッジ口座で取引する際には、注文チケット番号の取得と保存に多大な努力を払います。

結果オブジェクトの他の変数を使用して、注文の配置を確認したり、失敗した注文の配置をトラブルシューティングしたりできます。以下の例では、取引サーバーから返されたボリューム、価格、bidおよびaskの値を含むメッセージをログに出力します。

                  OrderSend(request,result) ;

If(result.retcode == TRADE_RETCODE_DONE || result.retcode == TRADE_RETCODE_PLACED)

{

                  Print(“trade placed”);

}

else

{

                  Print(“ trade not placed. Error code ” , result.retcode);

}

Print(“Return Code:”, result.retcode ,”, Volume: ”,result.volume,”, Price: ”,result.price,”, Bid: ”,result.bid,”, Ask: ”,result.ask);

MqlTradeResultオブジェクトの戻り値はブローカーに依存することに注意して下さい。例えば、一部のブローカーはbidまたはaskの値を返しません。

次の章では、注文発注機能にコードを追加して、エラーのトラブルシューティングを支援し、回復可能なエラーで発注を再試行します。

シンプルなEA P89

OrderSend()関数が単純なEAでどのように機能するかを示しましょう。この取引戦略は、現在の終値が移動平均よりも大きい場合に買い成行き注文を開き、終値が移動平均よりも小さい場合に売り成行き注文を開きます。ユーザーはストップロスを指定し、ポイントで利益を得るオプションと取引量を指定できます。

ソースコードをダウンロードした場合、このEAのファイル名はSimple Expert Advisor.mq5で、\MQL5\Experts\Mql5Bookフォルダでコードを表示できます。このコードはアカウントがnettingポジションシステムを使用していることを前提としています。アカウントをヘッジするためのこのEAのバージョンについては、この章の後半で説明します。

このプログラムを1セクションずつ見ていきましょう。

                  //入力変数

                  input double tradeVolume = 0.1 ;

                  input int StopLoss = 1000 ;

                  input int TakeProfit = 1000 ;

                  input int MAPeriod = 10 ;

これらは、エンドユーザーに表示される入力変数です。これらにより、ユーザーは取引量、ストップロスとテイクプロフィット(ポイント単位)、および移動平均の期間を調整できます。

                  //グローバル変数

                  bool glBuyPlaced, glSellPlaced ;

これらは、プログラム全体から見えるグローバル変数です。グローバル変数には、この本全体でglプレフィックス(接頭語)が付きます。glBuyPlaced変数とglSellPlaced変数は買いポジションまたは売りポジションが以前に開かれたかどうかを判断します。これにより、現在のポジションがストップロスまたはテイクプロフィット価格で決済された後、別のポジションが同じ方向に開かれるのを防ぎます。

                  //OnTick()イベントハンドラ

                  void OnTick()

                  {

                                   //取引構造

                                   MqlTradeRequest request ;

                                   MqlTradeResult result ;

                                   ZeroMemory(request) ;

OnTick()イベントハンドラーの先頭には、要求オブジェクトと結果オブジェクトの宣言が含まれています。ZeroMemory()関数、リクエストオブジェクトのメンバー変数が確実にゼロになるようにします。

                                   //移動平均

                                   double ma[];

                                   ArraySetAsSeries(ma , true);

                                   int manhandle = iMA(_Symbol , 0 , MAPeriod , MODE_SMA , 0 , PRICE_CLOSE);

                                   CopyBuffer(manhandle , 0 , 0 , 1 , ma);

                                   //終値

                                   double close[];

                                   ArraySetAsSeries(close , true);

                                   CopyClose(_Symbol , 0 , 0 , 1 , close);

上記のコードは、移動平均値と終値を保持する配列を初期化します。第16章と第17章で価格と指標データについて説明します。ma[]配列は移動平均指標値を保持し、close[]配列は各バーの終値を保持します。

                                   //現在位置情報

                                   bool openPosition = PositionSelect(_Symbol);

                                   long positionType = PositionGetInteger(POSITION_TYPE);

                                   double currentVolume = 0;

                                   if(openPosition == true)currentVolume = PositionGetDouble(POSITION_VOLUME);

注文を開く前に、既に開いているポジションがあるかどうかを確認する必要があります。PositionSelect()関数は、現在の銘柄でポジションがオープンしている場合、trueの値を返します。結果は、開いているposition変数に割り当てられます。POSITION_TYPEパラメータを指定したPositionGetInteger()関数は、現在のポジションのタイプ(買いまたは売り)を返し、それをpositionType変数に割り当てます。ポジションが現在オープンしている場合、POSITION_VOLUMEパラメータを指定したPositionGetDouble()関数は、現在のポジションボリュームをcurrentVolume変数に割り当てます。位置情報については第12章で説明します。

                                   //買い成り行き注文を開く

                                   if(close[0] > ma[0] && glBuyPlaced == false

&& (positionType ! = POSITION_TYPE_BUY || openPosition == false))

{

    request.action = TRADE_ACTION_DEAL ;

    request.type = ORDER_TYPE_BUY ;

    request.symbol = _Symbol ;

    request.volume = TradeVolume + currentVolume ;

    request.price = SymbolInfoDouble(_Symbol , SYMBOL_ASK) ;

    request.sl = 0 ;

    request.tp = 0 ;

    request.deviation = 50 ;

    bool sent = OrderSend(request , result);

これは、買い成り行き注文の条件をチェックするコードです。close[0]配列は現在のバーの終値を参照し、ma[0]は現在の移動平均値です。現在のバーの終値が移動平均線よりも大きい場合、それは買いシグナルを示します。しかし、まずオープンポジションの存在を確認し、前の注文が買い注文であったかどうかを判断する必要があります。

glBuyPlacedグローバル変数がtrueの場合、最後の注文が買い注文であったことを示します。当社の取引システムは、取引シグナルが発生すると1つの注文を出します。その注文がストップロスまたはテイクプロフィットの価格で決済されると、別の注文をオープンする前に反対方向の新しいトレードシグナルを持ちます。売り取引シグナルは、glBuyPlaced変数をfalseに設定します。

オープンポジションのタイプも確認する必要があります。positionType変数がPOSITION_TYPE_BUY定数の値と等しくない場合、買いポジションは現在開いていないとみなすことができます。ポジションが現在開いているかどうかを確認するために、openPosition変数もチェックする必要があります。これを行うのは、ポジションがオープンしていない場合、positionType変数に0の値が含まれるためです。POSITION_TYPE_BUYの整数値はたまたま0です。したがって、買いポジションの確認をするにはopenPosition変数が必要です。

買い注文の条件を要約すると、終値が移動平均よりも大きく、最後に開かれた注文が買い注文ではなく、ポジションが現在開かれていない(または現在開いているポジションが売りポジションである)場合、成行注文を買います。既存の売りポジションはすべてクローズされます。売り注文を出す場合はその逆です。

OrderSend()関数が後に続くリクエスト変数は、すでにおなじみのはずです。request.volumeの割り当てに注意してください。TradeVolume入力変数の値をcurrentVolumeローカル変数の値に追加します。売りポジションが現在開いている場合、売りポジションが決済されるように、より大きな買い注文を開きたいと考えており、TradeVolumeに入力された金額に等しいネットロングポジションが残されます。

OrderSend()に送信されたリクエストパラメータが有効な場合、送信されたブール変数はtrueに設定されます。結果オブジェクトの戻りコードを確認する必要がありますが、これは次に行います。OrderSend()の戻り値をsent変数に割り当てる利用は、コンパイラの警告を回避するためです。

//SL/TPを変更

if(result.retcode == TRADE_RETCODE_PLACED || result.retcode == TRADE_RETCODE_DONE)

{

request.action = TRADE_ACTION_SLTP;

PositionSelect(_Symbol);

double positionOpenPrice = PositionGetDouble(POSHITION_PRICE_OPEN);

if(StopLoss > 0)request.sl = positionOpenPrice – (StopLoss * Point);

if(TakeProfit > 0)request.tp = positionOpenPrice + (TakeProfit * Point);

if(request.sl > 0 && request.tp > 0)OrderSend(request , result);

glBuyPlaced = true;

glSellPlaced = false;

}

}

}

買い成り行き注文が出された後、取引が成功したかどうかを確認します。もしそうなら、先に進みストップロスを追加して利益を得るためにポジションを修正します。最初に行うことは、result.retcode変数の値をチェックして、注文が正常に行われたかどうかを確認することです。実行タイプに応じて、TRADE_RETCODE_PLACEDまたはTRADE_RETCODE_DONEの戻りコード値は、注文が失敗したことを示します。retcode変数がこれらの値のいずれかに一致する場合、ストップロスとテイクプロフィットの価格を計算し注文を修正します。

TRADE_ACTION_SLTP値をrequest.action変数に割り当てて、ストップロスとテイクプロフィットを変更していることを示します。次に、開いたばかりのポジションの始値を取得する必要があります。PositionSelect()関数は、ポジションに関する情報を取得できるように、現在の銘柄で現在開いているポジションを選択します。次にPositionGetDouble()でPOSITION_PRICE_OPENパラメータを使用してポジションの開始価格を取得し、その結果をpositionOpenPrice変数に割り当てます。

StopLossおよび/またはTakeProfitの入力変数がゼロより大きい場合、positionOpenPrice変数に関連する加算または減算し、その結果をrequest.slまたはrequest.tpに割り当てることによって、ストップロスおよび/またはテイクプロフィットの価格を計算します。request.slまたはrequest.tpのいずれかにゼロより大きい値が含まれている場合、OrderSend()関数を呼び出して、新しいストップロスおよび/またはテイクプロフィット価格でポジションを変更します。

最後にglBuyPlacedおよびglSellPlaced変数を設定する必要があります。買い注文が正常に発注されたので、glBuyPlacedをtrueに設定します。これにより、買いポジションがストップロスまたはテイクプロフィットによってクローズされた場合に、2番目の買い注文が開かれるのを防ぐことができます。また、glSellPlacedをfalseに設定します。これにより、終値が移動平均線を反対方向に横切る場合に売りポジションを開くことができます。

ヘッジバージョン P93

シンプルなEAのヘッジバージョンには、ヘッジ取引の管理と配置に必要な、いくつかの大幅な変更があります。プログラムは上記と同じ構造に従いますが、ポジション情報、注文のオープン、クローズ、および変更は異なる方法で処理する必要があります。

ファイルはSimple Expert Advisor(Hedhing).mq5という名前で、¥MQL5\Experts\Mq5Bookファルダにあります。OnTick()イベントハンドラ内の関連する変更は、太字で強調表示されています。

                  //OnTick()イベントハンドラ

                  void OnTick()

                  {

                      //トレード構造

                      MqlTradeRequset request;

                      MqlTradeResult result;

                      ZeroMemory(requset);

                      //移動平均

                      double ma[];

                      ArraySetAsSeries(ma , true);

                      int manHandle = iMA(_Symbol , 0 , MAPeriod , MODE_LWMA , 0 , PRICE_CLOSE);

                      CopyBuffer(manHandle , 0 , 0 , 1 , ma);

                      //終値

                      double close[];

                    ArraySetAsSeries(close ,true);

                      CopyClose(_Symbol ,0 ,0 ,1 ,close);

                      //現在の成り行き注文を取得する

                  ulong buyTicket = 0 ,sellTicket = 0;

                  for(int i = 0; i < PositionsTotal(); i++)

                  {

                            ulong tiket = PositionGetTicket(i);

                            PositionSelectTicker(ticket);

                            if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)

                            {

                   glBuyTicket = ticket;

                               glBuyPlaced = true;

}

else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)

{

   glSellTicket = ticket;

   glSellPlaced = true;

}

}

現在開いているポジションを取得するには、注文プールをループして注文チケット番号を取得する必要があります。forループは、0からPositionsTotal()関数によって示されるオープンポジションの数から1を引いた数まで反復します。PositionGetTicket()関数は、注文プール内の指定されたインデックスの注文チケットを取得します。注文プールのもっとも古い注文のインデックスは0ですが、最新の注文のインデックスはPositionTotal()-1です。

チケット番号を取得したら、PositionSelectByTicket()関数を使用して注文を選択します。これにより、その注文に関する情報を取得できます。POSITION_TYPEパラメータを指定したPositionGetInteger()関数は、注文タイプ(POSITION_TYPE_BUYまたはPOSITION_TYPE_SELL)を取得します。注文の種類に応じて、チケット番号をbuyTicketまたはsellTicketローカル変数に割り当てます。また、glBuyPlacedまたはglSellPlacedの値をtrueに設定します。これにより、同じ方向での別の注文の開始が防止されます。

現在、1つの買い注文または売り注文のみが開かれていると予想されます。後で、買い注文と売り注文の合計数とチケット番号を返すメソッドを作成します。

//成り行き買い注文を開く

if(close[0] > ma[0] && glBuyPlaced == false)

{

   //売り注文を閉める

  if(sellTicket > 0)

  {

      PositionSelectByTicket(sellTicket);

request.action = TRADE_ACTION_DEAL;

request.type = ORDER_TYPE_BUY;

 request.symbol = _Symbol;

request.position = sellTicket;

request.volume = PositionGetDouble(POSITION_VOLUME);

request.price = SymbolInfoDouble(_Symbol ,SYMBOL _ASK);

request.deviation = 50;

bool sent = OrderSend(request ,result);

}

買い成り行き注文が最近開かれたかどうかを判断するには、glBuyPlaced変数の値をチェックします。falseに設定され、終値が移動平均値よりも大きい場合、買い成り行き注文を出します。

新しい買い成り行き注文を開く前に、既存の売りポジションをクローズする必要があります。当社のnettingEAでは、現在のポジションよりも大きい逆方向の注文を開くだけで、ポジションを反転できることを覚えておいてください。これは、ヘッジ口座には機能しません。ヘッジ口座で成り行き注文をクローズするには、オープン注文ボリューム以下のボリュームで反対方向に注文する必要があります。クローズしたい注文のチケット番号を指定する必要があります。

request.positionパラメータは、決済する成行注文のチケット番号を示すために使用されます。成行注文を閉じるには、sellTicket変数のチケット番号の値をrequest.positionに割り当て、注文のボリュームをrequest.volumeに割り当てます。残りのパラメータは、買い成り行き注文を出すために使用する設定と同じです。

//買い注文を開く

request.action = TRADE_ACTION_DEAL;

request.type = ORDER_TYPE_BUY;

 request.symbol = _Symbol;

request.position = 0;

request.volume = TradeVolume;

request.price = SymbolInfoDouble(_Symbol ,SYMBOL _ASK);

request.sl = 0;

request.tp = 0;

request.deviation = 50;

bool sent = OrderSend(request ,result);

//SL/TPを変更する

if(result.retcode == TRADE_RETCODE_PLACED || result.retcode == TRADE_RETCODE_DONE)

{

   request.retcode = TRADE_ACTION_SLTP;

   request.position = result.order;

   PositionSelectByTicket(result.order);

   double positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);

   if(StopLoss > 0)request.sl = positionOpenPreice – (StopLoss * _Point);

   if(TakeProfit > 0)request.tp = positionOpenPreice + (TakeProfit * _Point);

   if(request.sl > 0 && request.tp > 0)sent = OrderSend(request ,result);

   glSellPlaced = false;

}

}

}

買い成り行き注文を出すと、リクエストはクリアされます。position変数を変更し、request.volume変数を実際の取引量に設定します。次に、新しく出された買い注文のストップロスとテイクプロフィット価格を変更するとき、request.positionをその注文のチケット番号に設定し、result.orderに保存します。

ヘッジ注文を直接操作するときはいつでも、request.positionをチケット番号に設定するか、新しい注文を開く場合は0に設定する必要があります。

概要 P96

この章で紹介する2つのEAは、トレンドに基づいて買い注文と売り注文を交互に行う、価格と指標データを使用する単純な取引システムを表しています。ストップロスとテイクプロフィットの価格を設定でき、注文量と指標期間を調整できます。

これが今あなたにとって少し圧倒されているように見えても、心配しないでください。上記のEAの例は、単純な取引シグナルを使用してMQL5で注文をオープン、クローズ、および変更するプロセスを示していますが、このコードの実際の実装は、次のいくつかの章で作成するクラスト関数に隠されています。プログラマーとしてのあなたの仕事は、トレーディングシステムロジックに集中し、ライブラリに発注と管理の詳細を処理させることです。

≪≪【日本語訳 第八章】Expert Advisorの基本

【日本語訳 第十章】発注クラスの作成≫≫

-pekonoriブログ関連