MT4EA稼働中に出るOrderSend Error 130の原因や対策方法を解説!

Stop-Level

EAを稼働させていると、「OrderSend Error 130」というエラーが生じることがあります。

1.OrderSend Error 130 とは

「OrderSend Error 130」とは、定数が「ERR_INVALID_STOPS」(=無効な損切り値)となっているように、以下のような場合に生じるエラーです。

  1. 損切り(利益確定)価格が現在のレートに近すぎる。
  2. 損切り(利益確定)価格を算出する計算式が正しくない。
  3. 損切り(利益確定)価格が正規化されていない。

「OrderSend Error 130」が生じる原因は上記のとおりですが、その中でも、特に1番目が当該エラーを生じさせる原因となっていることが多いと思われるので、1番目の原因を生じさせないようにし、「OrderSend Error 130」エラーを回避するプログラミング方法について解説していきます。

2.ストップレベル

「損切り(利益確定)価格が現在のレートに近すぎる」ことを原因とした「OrderSend Error 130」の発生を回避するためには、まず、「ストップレベル」(Stop Level)について理解を得ておく必要があります。

⑴ ストップレベルとは

MetaTrader4(MT4)を採用している各FX業者は、過大な取引サーバーに対する負荷を避けるために、現在値から一定のpips以上離れた位置に損切り価格や利益確定価格を設定しなければ、新規に損切り価格や利益確定価格を設定した注文を受け付けないようにしています。

この、新規注文に対する損切り価格や利益確定価格の設定に対する値幅制限を、ストップレベルといいます。

Stop-Level

⑵ ストップレベルによる注文の制限

各種注文に対するストップレベルによる制限をまとめた表を、以下に示します(以下の表に示した条件を満たさない場合には、注文は執行されません。)。

注文種別
(逆)指値
損切り値(SL)
利益確定値(TP)
成行買い
「Bid-SL」

ストップレベル
以上
「TP-Bid」

ストップレベル
以上
成行売り
「SL-Ask」

ストップレベル
以上
「Ask-TP」

ストップレベル
以上
指値買い
「Ask-指値」

ストップレベル
以上
「指値-SL」

ストップレベル
以上
「TP-指値」

ストップレベル
以上
指値売り
「指値-Bid」

ストップレベル
以上
「SL-指値」

ストップレベル
以上
「指値-TP」

ストップレベル
以上
逆指値買い
「逆指値-Ask」

ストップレベル
以上
「逆指値-SL」

ストップレベル
以上
「TP-逆指値」

ストップレベル
以上
逆指値売り
「Bid-逆指値」

ストップレベル
以上
「SL-逆指値」

ストップレベル
以上
「逆指値-TP」

ストップレベル
以上

3.具体的な回避策

OrderSend Error 130 が、損切り価格と利益確定価格をストップレベルの範囲内に設定しようとすることから生じるのであれば、当該エラーを回避するためには、以下のような対策を講じればよいということになります。

  1. 設定しようとする損切り価格と利益確定価格が、ストップレベルの範囲内にあるかどうかを検証する。
  2. 検証の結果、ストップレベル違反が認められた場合には、設定しようとする損切り価格と利益確定価格が、ストップレベルの範囲外の値に自動的に修正されるようにする。

具体的なコードとしては、以下のようになります。

OrderSend-Error-130_Code

 

⑴ 変数の宣言

まず、以下のような変数を宣言しておきます。

  • Adjust_Stop
    後述の⑸ウ参照。
  • Stop_Loss
    約定価格から、損切り価格までのpips数を指定します。
  • Take_Profit
    約定価格から、利益確定価格までのpips数を指定します。
  • Ticket_L
    ロングエントリーしたポジションのチケット番号を格納します。
  • Ticket_S
    ショートエントリーしたポジションのチケット番号を格納します。
  • Pips
    損切り価格や利益確定価格などをpips単位で算出するための値を格納します。
  • Modified
    OrderModify()関数(詳細については「こちら」を参照してください。)の戻り値を格納します。
  • Buy_Stop_Loss
    買いポジションに対する損切り価格を格納します。
  • Buy_Take_Profit
    買いポジションに対する利益確定価格を格納します。
  • Sell_Stop_Loss
    売りポジションに対する損切り価格を格納します。
  • Sell_Take_Profit
    売りポジションに対する利益確定価格を格納します。

⑵ 関数の定義

損切り値や利益確定値を、提示レートの小数点以下の桁数にかかわらず、常にpips単位で算出することができるように、AdjustPoint()関数を宣言しています。

⑶ 初期設定の記述

損切り価格や利益確定価格などをpips単位で算出するために使用する変数「Pips」に、AdjustPoint()関数の戻り値を格納しています。

当該処理は、EAを稼働させてから一度だけ行えば足りるので、OnInit()関数内で行っています。

⑷ 保有ポジションの選択

具体例では、「OrderSend Error130」 の発生を回避するために、以下の手順を踏むことにしています。

  1. 損切り価格及び利益確定価格を指定しないエントリー注文を発注。
  2. エントリー注文約定後に、保有したポジションに対して、ストップレベルを考慮した損切り価格及び利益確定価格を設定する。

そこで、以下のような処理を行っています。

  1. OrderSend(関数(詳細はについては「こちら」を参照してください。)の戻り値を変数「Ticket_L」に格納する。
  2. 変数「Ticket_L」の値が「正」(=注文が正常に約定した。)であるかどうか確認する。
  3. 変数「Ticket_L」の値が「正」であれば、OrderSelect()関数(詳細については「こちら」を参照してください。)を使用して、保有したポジションを選択する。

⑸ ストップレベルの計算

ア ストップレベルを取得する

ストップレベルは、MarketInfo()関数を使用することによって取得することができます。

MarketInfo()関数によって取得されるストップレベルはポイント単位なので、例えば、ストップレベルが3pipsの場合、戻り値は以下のようになります。

  • 提示レートが小数点以下2桁又は4桁
    「3」
  • 提示レートが小数点以下3桁又は5桁
    「30」

したがって、MarketInfo()関数で取得したストップレベルの値を、実際の値幅に変換するためには、MarketInfo()関数で取得したストップレベルの値に予約変数「Point」に格納されている値を乗じることになります。

  • Pointの詳細については「こちら」を参照してください。

具体例では、以下のように記述して、実際の値幅に変換したストップレベルの値を、変数「Stop_Level」に格納しています。

サンプルコード


double Stop_Level =
MarketInfo(Symbol(),MODE_STOPLEVEL) *
Point

イ 損切り価格・利益確定価格の設定可能値を算出する

損切り価格及び利益確定価格は、現在のレートにストップレベルの値を加減した値以上(下)でなければなりません。

具体的には、買いポジションの利益確定価格・売りポジションの損切り価格・買いの逆指値注文・売りの指値注文は、以下の値以上でなければならないということになります。

売り気配値(=Ask値) + ストップレベル(=Upper_Stop_Levelとします。)

また、売りポジションの利益確定価格・買いポジションの損切り価格・売りの逆指値注文・買いの指値注文は、以下の値以下でなければならないということになります。

買い気配値(=Bid値) - ストップレベル(=Lower_Stop_Levelとします。)

具体例では、以下のように記述して、損切り価格・利益確定価格の設定可能価格を、変数「Upper_Stop_Level」及び「Lower_Stop_Level」に格納するようにしています。

サンプルコード


RefreshRates();

double Upper_Stop_Level =
Ask + Stop_Level;
double Lower_Stop_level =
Bid - Stop_Level;

ウ スリッページを考慮する

損切り価格や利益確定価格を、「Upper_Stop_Level」や「Lower_Stop_Level」と等しい値にしてしまうと、相場状況によってはスリッページが発生し、損切り価格や利益確定価格を新規に設定した注文が無効となる場合が生じます。

そこで、具体例では、損切り価格や利益確定価格を、「Upper_Stop_Level」や「Lower_Stop_Level」に一定のpips分加減した値に設定するようにしています。

具体例では、「Upper_Stop_Level」や「Lower_Stop_Level」からのスリッページを考慮した調整値を任意の値に設定することができるように、これをパラメーター化した変数「Adjust_Stop」としています。

また、実際に「Upper_Stop_Level」や「Lower_Stop_Level」に加減するpips数を変数「Minimum_Stop」に格納するようにしています。


double Minimum_Stop =
Adjust_Stop * Pips;

⑹ 損切り価格と利益確定価格の計算

ア 買いポジションの損切り価格の計算

買いポジションの損切り価格は、以下の計算式から算出されます。

約定価格 - 損切り幅

具体例においては、以下のように記述して、買いポジションの損切り価格を、変数「Buy_Stop_Loss」に格納しています。


Buy_Stop_Loss =
OrderOpenPrice() - (Stop_Loss * Pips);

イ 買いポジションの利益確定価格の計算

買いポジションの利益確定価格は、以下の計算式から算出されます。

約定価格 + 利益確定幅

具体例においては、以下のように記述して、買いポジションの利益確定価格を、変数「Buy_Take_Profit」に格納しています。


Buy_Take_Profit =
OrderOpenPrice() + (Take_Profit * Pips);

⑺ 損切り価格と利益確定価格の検証

ア 買いポジションの損切り価格の検証

買いポジションの損切り価格は、「Lower_Stop_Level」以下でなければなりません。

そこで、具体例においては、以下のように記述して、新規に設定する買いポジションに対する損切り価格が「Lower_Stop_Level」よりも高かった場合は、買いポジションの損切り価格を「Lower_Stop_Level」からスリッページを考慮した調整値を控除した値に修正するようにし、修正が行われた際には、その旨を「ターミナルウィンドウ」の「エキスパート」タブに出力するようにしています。

サンプルコード

if(Buy_Stop_Loss > Lower_Stop_Level &&
   Buy_Stop_Loss > 0)
  {
    Buy_Stop_Loss =
    Lower_Stop_Level - Minimum_Stop;
    
    Print("Stop-Loss has been
          automatically adjusted.");
  }

Print()関数の詳細については「こちら」を参照してください。

イ 買いポジションの利益確定価格の検証

買いポジションの利益確定価格は、「Upper_Stop_Level」以上でなければなりません。

そこで、具体例においては、以下のように記述して、新規に設定する買いポジションに対する利益確定価格が「Upper_Stop_Level」よりも低かった場合は、買いポジションの利益確定値を「Upper_Stop_Level」からスリッページを考慮した調整値を加算した値に修正するようにし、修正が行われた際には、その旨を「ターミナルウィンドウ」の「エキスパート」タブに出力するようにしています。

サンプルコード


if(Buy_Take_Profit < Upper_Stop_Level &&
   Buy_Take_Profit > 0)
  {
    Buy_Take_Profit =
    Upper_Stop_Level + Minimum_Stop;
    
    Print("Take-Profit has been
          automatically adjusted.");
  }

⑻ 注文の修正

買いポジションに対する損切り価格及び利益確定価格の計算・検証が終了した場合には、OrderModify()関数を使用して、損切り価格及び利益確定価格を設定しています。

⑼ 売りポジションに対する計算・検証・設定

上記⑷~⑺と同様の処理を、売りポジションに対するものに適するように、適宜修正したコードを記述しています。