FX・ビットコイン・オプションのシステムトレード開発と取引録

FXとビットコインのシステムトレードの開発録、オプション取引の履歴を書き連ねています。MT4, Pythonで開発しています。

MQL4ブック MT4

オーダーの終了と削除

オーダーの終了と削除

 

マーケット注文の終了

市場受注を終了するための取引要求は、OrderClose()関数を使用して形成されます。

関数 OrderClose()

これは、市場の注文を閉じるために使用される関数です。 取引が正常に実行されると、この関数はTRUEを返します。 取引が失敗した場合はFALSEを返します。

パラメーター:

ticket - オーダーの一意の番号

lots - 閉じられるロットの量。 注文のロットの利用可能な量よりも少ない値を指定することは許可されています。 この場合、取引要求が正常に実行された場合、注文は部分的に閉鎖されます。

Price - クローズ価格。 このパラメータは、取引を実行するために受け入れられる要件および制限に従って設定されます(取引注文の特性とルール、および付録3を参照)。 価格の流れで市場の注文を終了するために要求された価格がない場合、またはそれが時代遅れである場合、この取引要求は却下される。 価格が時代遅れであるが価格の流れで見つかったと同時に、スリッページ価値内の現在の価格範囲からの逸脱である場合、取引要求はクライアント端末によって受け入れられ、取引サーバに送られる。

Slippage - 注文を終了するために要求された価格の、市場価格からの許容最大偏差(ポイント単位)。

Color - チャート内の閉じる矢印の色。 このパラメータが使用できない場合、またはその値がCLR_NONEの値と等しい場合、矢印はグラフに表示されません。

 

プログラムに、閉鎖される注文のタイプ、その固有の番号、閉鎖されるロットの金額に関する情報が含まれている場合、注文を閉じるのは非常に簡単です。 このためには、プログラムコード内でプリセットパラメータを使用してOrderClose()関数呼び出しを使用する必要があります。 たとえば、注文Buyの一意の番号が12345で、0.5ロットを閉じる場合は、注文を閉じる関数の呼び出しは次のようになります。

どのような注文とどのような順序で閉じなければならないかを決定するためには、現状で開かれたすべての注文のデータを持たなければなりません。 MQL4には、任意の順序を特徴付けるさまざまなデータを取得するために使用できるいくつかの関数があります。 たとえば、関数OrderOpenPrice()は、注文オープン価格(または保留中の注文の要求価格)を返し、関数OrderLots()はロット数を返し、関数OrderType()は注文の種類を返し、 OrderSelect()関数によって選択されたオーダーへの実行時に、オーダー特性呼び出しの値を返すすべての関数。

 

関数OrderSelect()

注文のパラメータ(マーケットや保留中、未決済、または未決済)を取得するには、まずOrderSelect()関数を使用してパラメータを選択する必要があります。

OrderSelectは、それ以降の操作のための注文を選択する関数です。 関数が正常に実行された場合、TRUEを返します。 それ以外の場合は、FALSEを返します。

パラメーター:

index - 順序の位置または数.2番目のパラメータによって異なります。

select - 選択メソッドのフラグ パラメータ 'select'は、次の2つの値のいずれかをとります。

SELECT_BY_POS - パラメータ 'index'で、リスト内の注文番号が返されます(番号付けは0から始まります)。

SELECT_BY_TICKET - パラメータ 'index'にチケット番号(一意の注文番号)が返されます。

pool - 選択するデータソース パラメータ 'select'がSELECT_BY_POSの値と等しい場合、パラメータ 'pool'が使用されます。 注文番号がチケット番号(SELECT_BY_TICKET)で選択されている場合、パラメータ 'pool'は無視されます。 パラメータ 'pool'には、次の2つの値があります。

MODE_TRADES(デフォルトでは) - 注文は、未決済注文、すなわち、「ターミナル」ウィンドウの「取引」タブに表示されている注文の中から選択されます。

MODE_HISTORY - 注文は、閉じられた注文や削除された注文、つまり、[端末]ウィンドウの[アカウント履歴]タブに表示された注文の中から選択されます。 この場合、閉じられた注文と削除された注文を表示するためにユーザーが指定した履歴の深さが重要です。

 

市場の注文を閉じるために取引関数を使用する方法を実証するために、問題を解決しよう:

問題28アカウントで利用可能なマーケット注文の1つをクローズするスクリプトを書く。 スクリプトの実行によって、マウスを使用してシンボルウィンドウにアタッチされたスクリプトの場所に最も近い注文が閉じられる必要があります。

記号Eur / UsdとUsd / Chfに対して開かれている保留中の注文について、端末に3つの市場注文が開かれていると仮定する。

イチジク。 90.異なるシンボルに対して開いた複数の注文を端末ウィンドウに表示する。

マウスでドラッグして「ナビゲータ」ウィンドウからシンボルウィンドウにドラッグできるスクリプトを作成すると、マーケットオーダーの1つ、つまりカーソルに最も近い順序(つまり、ユーザーがマウスボタンを放した)。 Fig。 91の場合、カーソルが売り注文4372889に最も近い代替案を見ることができます。これは、スクリプト実行の結果として閉じなければならない注文です。

イチジク。 91.選択した注文を閉じるために使用されるcloseorder.mqのスクリプト。

この問題を解決するには、スクリプトがドロップされたウィンドウ内で、シンボルに対して開いたものだけをすべての注文の中から選択する必要があります(OrderSymbol()関数を使用)。 次に、選択されたすべての市場指図のオープン価格を見つける(つまり、各注文に対してOrderOpenPrice関数を連続して実行する)。注文のオープンプライスを知っているので、我々は問題のステートメントに対応するそれらの1つを簡単に選択することができます。 関数OrderClose()のパラメータの適切な値を指定するには、選択した注文に関する他のデータも知っておく必要があります:ロットの量(関数OrderLots()によって決まる)と一意の注文番号関数OrderTicket())。 さらに、双方向見積もりの​​1つまたは別の価格を見つけるためには、注文のタイプ(関数OrderType()によって決定される)を知る必要があります。

上記の注文特性を得るために、どのパラメータをOrderSelect()関数で指定しなければならないかを考えてみましょう。

まず、注文選択方法を選択する必要があります。 私たちの問題では、選択方法は問題文そのものによって決まります。注文番号に関するデータは、実行スクリプトを起動する瞬間にはプログラムで使用できないと考えられます。つまり、プログラムにはブロックが含まれているとみなされます。それらの注文番号を決定します。 つまり、「端末」(図64.1)に表示されるすべての注文を1つずつ確認する必要があるため、パラメータSELECT_BY_POSを使用する必要があります。

注文の選択源も明白です。 この問題を解決するには、クローズと削除された注文を分析する必要はありません。 この場合、マーケットオーダーにのみ関心がありますので、OrderSelect()関数でMODE_TRADESパラメータを使用して検索します。 パラメータ 'pool'では、MODE_TRADESのデフォルト値が関数ヘッダーに指定されているので、スキップすることができます。

市場および未決注文を分析するためのブロックを構築する方法を以下に示します。

サイクル演算子の見出しでは、初期値はi = 1として指定されますが、サイクルを終了する条件は式i <= OrdersTotal()です。 関数OrdersTotal()は、市場および保留中の注文の合計金額、つまり[端末]ウィンドウの[取引]タブに表示されている注文を返します。 これは、多くの受注が取引に参加するのと同じくらい多くの繰り返しが周期内に存在する理由です。

各反復で、条件が演算子 'if'で計算されると、関数OrderSelect(i-1、SELECT_BY_POS)が実行されます。 以下の重要事項をここに記載しなければなりません:

市場および保留中の注文のリスト内の注文の番号付けはゼロから始まります。

これは、リスト(図90)の最初の注文がゼロの位置に置かれ、2番目の注文の位置が1、3番目の注文の番号が2などであることを意味します。これが、関数OrderSelect()を呼び出すと、indexの値はi-1として与えられます。 したがって、選択されたすべての注文について、このインデックスは常に変数iの値よりも1少ない(次の繰り返しの数と一致する)。

関数OrderSelect()は、注文が正常に選択された場合にtrueを返します。 注文選択が失敗する可能性があることを意味します。 これは、処理中に注文量が変更された場合に発生します。 MQL4でプログラミングする場合は、アプリケーションプログラムがリアルタイムモードで動作し、いくつかのパラメータを処理している間に、これらのパラメータの値が変化する可能性があることを忘れないでください。 例えば、受注の開閉と未受注の受注の変更の結果、市場の受注額が変わる可能性があります。 注文処理をプログラミングする際には、次のルールを守る必要があります。注文はできるだけ早く処理する必要がありますが、この処理を担当するプログラムブロックは、可能であれば冗長なプログラム行を含むべきではありません。

図1に示すコードによれば、 64.3、演算子 'if'のヘッダで、プログラムは、選択された瞬間に次の注文が注文リストで利用可能かどうかを分析します。 次の注文が利用可能であれば、コントロールは注文パラメータを処理するために演算子 'if'の本体に渡されます。 このような構成は、競合の可能性がある場合には、パラメータの処理中に順序が失われる可能性があるため、あまり役に立たないことに注意する必要があります。 しかし、その選択の瞬間に、注文がもう利用できない場合、この解決策は最も効率的であることが分かります。 演算子 'if'の本体で、選択された注文のパラメータが分析されます。 OrderOpenPrice()、OrderTicket()、OrderType()などの関数を実行すると、関数OrderSelect()の実行結果として選択された順序の特定の特性の値が返されます。

問題28を解決するプログラムでは、上記の推論がすべて使用されました。

マーケットオーダーのクローズを意図した単純なスクリプトの例。公開価格は他の注文のオープンプライス( closeorder.mq4 )よりもスクリプトの添付ファイルの場所に近い。

 

closeorder.mqプログラムの全コードは、特殊関数start()に集中しています。 ブロック1-2では、いくつかの変数が初期化される。 変数Distは、スクリプトがドロップされた場所から最も近い順序までの距離です。 変数Real_Orderは、クライアント端末に少なくとも1つのマーケットオーダーの利用可能性(非負の値)を表示するフラグです。 変数Win_Priceは、ユーザーがスクリプトをシンボルウィンドウに添付した価格です。 ブロック2-6では、注文が分析される。利用可能な注文のうちの1つが閉鎖されるように割り当てられる。 ブロック6-10は注文を終了し、取引の実行中に発生する可能性のあるエラーを処理するブロックである。

ユーザがスクリプトを記号ウィンドウに添付した瞬間から、変数の値はブロック1-2で計算され、変数Win_Priceはユーザがスクリプトを添付したレベルで価格の値をとる。 この場所に最も近い注文(その特性とともに)を見つける必要があります。

'for'サイクル(ブロック2-6)では、注文が検索されます。ブロック2-3では、プログラムは「端末」の次の行に注文があるかどうかをチェックします。 注文が見つかった場合、その注文の特性を取得して分析するために、コントロールは演算子 'if'の本体に渡されます。 ブロック3-4において、間違った記号(プログラムが実行されている記号ではない)に対して開かれた注文は、フィルタリングされて取り除かれる。 私たちの場合、それはUsd / Chfのために開かれた注文4372930です。 関数OrderSymbol()は、選択した注文のシンボル名を返します。 このシンボル名がプログラムの実行中のもの以外の場合、現在の反復は中断され、別のシンボルに対して開かれた順序が処理されなくなります。 分析中の注文が「私たちの」シンボルのために開かれていると判明した場合、もう1つのチェックが行われます。 注文タイプは、関数OrderType()を使用して決定されます( 取引のタイプを参照)。 注文タイプが1より大きい場合は、注文が保留中であることを意味します。 この場合、保留中の注文には関心がないので、現在の繰り返しも中断されます。 この例では、このような順序がありますが、別のシンボルのために開かれているので、すでにフィルタされています。 ブロック3-4を成功裏に通過した注文は全て市場のものです。

ブロック4-5は、先行するブロックを首尾よく通過したすべてのマーケット注文のうちの1つの注文のみを選択することを意図している。 この注文は、事前定義された価格(変数Win_Priceの値)に最も近いものでなければなりません。 ユーザーはマウスカーソルで注文行を「特定」する必要はありません。 実行のためにスクリプトを起動する時点で他の注文よりもカーソルに近い注文が選択されます。 処理された注文のオープンプライスは、OrderOpenPrice()関数を使用して検索されます。 現在の注文の価格と「カーソル価格」との間の距離の絶対値が前の注文の同じ距離よりも小さい場合、現在の注文が選択される(距離の絶対値は、オーダーラインの下または上のカーソル位置の影響)。 この場合、この注文は、閉鎖のためのフロントランナーとしての 'for'サイクルの現在の反復で記憶される。 この注文については、ブロック4-5の最後に、チケット番号(注文の個数)とロットの金額が計算されます。 この例(図90)では、受注総額が4つ(市場3つと保留の1つの注文)であるため、 'for'サイクルで4回の繰り返しが実行され、閉じるために必要なすべてのデータが検索されます選択された1つの注文の

次に、実行中のプログラムの制御がサイクル演算子 'while'に渡される(ブロック6-10)。 ブロック6-7において、発見された市場注文が利用可能かどうかが検査される。ブロック2-4でマーケット注文が見つからない場合(これはかなり可能である)、Real_Orderフラグの値は-1のままであり、市場注文が利用できないことを意味する。 ブロック6-7でのチェックがマーケット注文を検出しなかった場合、サイクル「while」の実行は破られ、プログラムはその動作を終了する。 変数Real_Orderの値が0または1に等しいことが判明した場合、これはマーケットがクローズのためにあらかじめ定義されており、クローズする必要があることを意味します。

ブロック7-8において、注文タイプにしたがって注文の終値が計算される。 これは、買い注文のための入札の値、および売り注文のためのAskの値です( 取引行う際の要件と制限を参照)。

ブロック7-8において、補助変数Textの値が計算される。 注文完了のための取引要求は、以下の行のOrderClose()関数で形成されます。

Trade関数OrderClose()は、取引が成功した場合はtrueを返し、成功しなかった場合はfalseを返します。 取引要求がサーバー上で正常に実行されると、値 'true'が変数Ans(answer)に割り当てられます。 この場合、ブロック8-9を実行するとき、プログラムはユーザに注文完了の成功を知らせる。 その後、サイクル演算子 'while'の実行が停止され、プログラムの動作は終了します。 そうでなければ、制御はブロック9-10に進み、クライアント端末からプログラムに返されたエラーを分析する。

ブロック9-10の開始時に、エラーコードが計算される。 その後、エラーコードに従って、プログラムの終了または繰り返し動作が実行される。 第1のオペレータ 'スイッチ'では、プログラムが暗黙的に耐え難いエラーを処理します。つまり、エラーは取引を実行する際に一時的な困難とみなすことができます。 このようなエラーごとにすべての必要なアクションが実行され、現在の反復が停止され、サイクル 'while'の実行が再開されます。 (この例では、演算子 'continue'の使用の結果として出て来る演算子 'switch'をエラー処理するために使用することに注意してください。この構成は、オペレータ 'スイッチ'が外部サイクルオペレータ 'while'の内容の一部であり、オペレータ 'continue'がオペレータ 'のヘッダに制御を渡すことによって現在の反復を中断するという理由だけで機能する' )。

エラーコードが最初の演算子 'switch'で処理されない場合、このエラーは重大であるとみなされます。 この場合、コントロールは、第2のオペレータ 'スイッチ'に渡され、これは、ユーザに1つまたは別の重大なエラーが発生したことを知らせるために実行されます。 さらに、プログラムは、 'while'サイクルの実行を中断する演算子 'break'を使用します。 何らかの理由でサイクル 'while'を終了すると、プログラム動作の終了に関するメッセージを生成するブロック9-10に制御が渡される。 演算子 'return'は、特殊関数start()の実行を停止し、プログラムはその操作を終了します。

指定された条件(図90と91を参照)でスクリプトを起動した後の実際の結果を以下に示します。 貿易はサーバー上で正常に行われました。

イチジク。 92. closeorder.mq4スクリプトが正常に実行された結果として受信されたメッセージ。

注文の1つが終了した結果、Eur / Usdのウィンドウに2つの注文が残っています。

イチジク。 スクリプトcloseorder.mq4を実行すると、注文の1つが終了します。

注文終了は、「ターミナル」ウィンドウにも表示されています。

イチジク。 94. closeorder.mq4スクリプトの実行後、2つのマーケット注文が「ターミナル」ウィンドウに表示されます。

後で、このスクリプトを使用して他の2つの注文もクローズされます。

 

保留中の注文の削除

保留中の注文を削除するための取引要求は、OrderDelete()関数を使用して形成されます。

関数OrderDelete()

この関数は、以前に配置された保留中の注文を削除します。 正常に処理された場合はTRUEを返します。 それ以外の場合は、FALSEを返します。

パラメーター:

ticket - オーダーの一意の番号

arrow_color - グラフ内の矢印の色です。 このパラメータが使用できない場合、またはその値がCLR_NONEの値と等しい場合、矢印はグラフに表示されません。

関数OrderDelete()に、ボリュームの指定と、削除される注文の終了価格が含まれていないことは容易に分かります。

市場価格に関係なく注文は削除されます。 注文の部分的な削除も不可能です。 保留中の注文のロット数を2段階で減らすことができます。既存の注文を削除し、減少した(任意の)ロット数で新しい保留オーダーを配置します。

保留中の注文を削除するプログラムのアルゴリズムは、マーケットオーダーの締め切りと全く同じです。 保留中の注文を削除するために近い価格が必要ないという点でわずかな違いがあるため、以下のプログラムには市場価格を更新するブロックが含まれていません。

保留中の注文を削除するための単純なスクリプトの例。要求された価格は、他の保留中の注文( deleteorder.mq4 )の価格よりもスクリプトの添付ファイルの場所に近い。

 

エラー処理ブロックも若干変更されています。 市場の注文を閉じる際に価格の変更(エラー135および136)に関連するエラーの可能性を考慮する必要がありますが、保留中の注文を削除するときはこのようなエラーは発生しません。 同じ理由で、関数RefreshRates()はプログラムのどこにも使われません。

エラー4やエラー137( エラーコード参照)などのエラーを処理するのは少し難しいかもしれません。 たとえば、エラー137が発生した場合、プログラムは「ブローカがビジー」であることを考慮に入れることができます。 しかし、自然な問題が発生します:ブローカーはいつ無料ですか、ユーザーは彼または彼女の取引を続行する? エラー137はそのような情報を提供しません。 このため、プログラマは、このようなエラーを適切に処理するプログラムを構築する方法を自分で決定する必要があります。単純なケースでは、要求はある休止(この例では3秒後)後に繰り返すことができます。 一方、一連の注文を削除しようとしても(または一般的には、閉じる、開いたり変更したりする)、サーバーはエラー141を返す可能性があります。 このエラーにより、 deleteorder.mq4スクリプトが機能しなくなります。 一般に、このような紛争はプログラミングの問題ではありません。 そのような場合は、ディーリングセンターのサポートサービスに連絡して、拒否理由を明らかにする必要があります。

保留中の注文(一般的には、市場注文の停止注文となり得る)が市場価格に近すぎると、エラー145が発生する可能性があります。 あなたが静かな市場で着実に取引している場合、このエラーは発生しません。 価格が急激に変化した場合、ブローカーは特定の注文がすぐに開かれると判断して、ブローカーがその注文を削除または変更することを許可しません。 このエラーは、スクリプト内で重要なものとみなされ、プログラムの終了につながります(取引要求でブローカを悩ますことは意味がありません)。 しばらくして価格が変更された場合は、再度実行するためにスクリプトを起動して注文を削除しようとすることができます。

通常、取引センターによって設定された凍結レベルを考慮すると、エラー145の発生を防ぐことができます。 フリーズレベルは、オーダーが「凍結」とみなされる価格帯を決​​定する値です。つまり、それを削除することは禁止されています。 たとえば、保留中の注文が1.2500に、凍結レベルが10ポイントに等しい場合、価格が1.2490から1.2510の範囲であれば、保留中の注文の削除は禁止されていることを意味します。 要求識別子MODE_FREEZELEVELを使用してMarketInfo()関数を実行したフリーズレベル値を取得できます。

 

反対注文のクローズ

反対注文は、同じシンボルに対して開かれた別の市場指図の方向とは反対の方向に開かれた市場注文です。

特定のシンボルに対して2つの反対の注文がある場合は、OrderCloseBy()関数を使用してそれらを同時に閉じることができます。 このような操作を実行すると、1つのスプレッドを保存します。

関数OrderCloseBy()

この関数は、同じシンボルに対して反対方向に開かれた別の市場指図によって1つの市場指図を終了します。 この関数は、正常に完了するとTRUEを返し、失敗した場合はFALSEを返します。

パラメーター:

ticket - 閉じる順序の一意の番号

opposite - 反対の順序の一意の番号。

Color - チャート内の閉じる矢印の色。 このパラメータが使用できない場合、またはその値がCLR_NONEの値と等しい場合、矢印はグラフに表示されません。

逆の注文が同じ音量である必要はありません。 逆の注文で注文を締め切ると、取引量は、注文量の少ない注文量で実行されます。

例を考えてみましょう。 クライアント端末には同じボリュームの2つのマーケットオーダー、BuyとOne Sellがあります。 OrderClose()関数を使ってそれぞれを別々に閉じると、我々の経済生産は各注文から得られた利益の合計になります:

イチジク。 OrderClose()関数を使用して注文を別々に処理した結果。

しかし、このような状況でOrderCloseBy()関数を使用して注文を反対に処理しようとすると、経済的生産は(1つの注文の広がりのコストに比例する)

イチジク。 96. OrderCloseBy()関数を使用して他の注文による注文を終了した結果。

ターミナルで反対の注文がクローズされる場合、OrderClose()ではなくOrderCloseBy()関数を使用することは経済的に妥当であることは明らかです。

逆の注文を締め切る際のスプレッドの節約については、より一般的な説明をする必要があります。 実際には、注文(例えば、買い注文)を開くことは、注文を閉じるのと同程度に反対方向(すなわち、売り注文)で注文を開くこととは反対の取引であることを意味する購入注文)。 言い換えれば、市場の秩序を崩すか、同じボリュームの反対の注文を開く(そして、両方の注文をお互いに閉じる)ことは、経済的に同じです。 これらの2つの選択肢の違いは、市場受注を支援するために転用する資金を計算するために、異なる取引センターで使用されるさまざまな方法でしか成立しない場合があります( 図85および図88を参照)。

逆の注文を閉じるには、OrderCloseBy()関数で近い価格を指定する必要がないこともわかります。 2つの反対注文の利益と損失が相互に返済するので、これは不要です。したがって、総経済生産量は市場価格に依存しません。 もちろん、このルールは同じ数量の注文に対してのみ有効です。 たとえば、1つのシンボルに対して2つの注文:1ロットの買い注文と0.7ロットの売り注文がある場合、この取引は0.3ロットの買い注文部分に関連する市場価格にのみ依存し、0.7ロット両方の注文はシンボル価格に依存しません。

反対の注文はトータルの取引結果に影響を与えません。 このため、反対注文の開設に基づく取引戦術には非公式の内容が含まれていない(このため、一部の取引センターは、一致したロット内の反対の注文を強制的に終了する)。 そのような戦術の唯一の(否定的な)影響力は、いくつかの取引センターで受け入れられた規則に従って資金を流用することにあります。 さらに、いくつかの逆の注文の利用可能性は、プログラムされた取引の文脈において、1つの注文よりも困難をもたらす。 様々なコミッションとスワップを(市場の注文ごとに別々に)検討すると、反対の注文を閉じる必要性が明らかになります。

シンボルの反対の注文( closeby.mq4 )をすべて閉じる単純なスクリプトの例。