EZインベスト証券のUSDJPYレート 小数点以下4桁表示対応について考える

今週のはじめ、2018年2月5日(月)からEZインベスト証券のMT4にて、USDJPYのレートのみ小数点以下4桁で配信されることとなりました。

スキャルピングでトレードする人にとっては、良い変更だと思います。
しかしこの変更、システムトレーダーにとっては頭を悩ませるポイントです。

これまでの開発経緯

これまでMT4のUSDJPYのレートは、小数点以下3桁が主流で、稀に2桁の口座があるという状況でした。
開発者にとっては2種類ある環境から既に悩みの種がありました。
小数点以下の桁数の違いは、TPやSLのように値幅で入力したいパラメーターを設定する時に問題となります。

USDJPYで50pips(0.5円)にTPを発注する処理を例に説明します。

MQL4ではTPをpips単位で指定して発注はできませんので、ユーザーがパラメーターに入力した50という数値を適切な価格に変換して発注する必要があります。
MQL4にはPoint(あるいは_Point)という通貨ペアごとの最小単位を取得できる定義済み変数があるので、これを使って処理を作成することとなります。

仮に今、USDJPYの小数点以下の桁数が2桁だとしますと、Pointは0.01となります。
発注価格がAskで買い取引あれば、TPはAskの50pips上ですので次のように計算できます。

double takeprofit = Ask + TP * Point;

TPとPointを掛け合わせると、50 × 0.01 = 0.5 となり、利食いしたい値幅の0.5円が得られます。
これを発注価格Askに足して利食い価格が得られます。
この価格をOrderSend関数に渡すことで、エントリー価格+50pipsにTPが入った発注が可能です。

しかしUSDJPYチャートの小数点以下桁数が3桁だと話は変わってきます。
小数点以下3桁ですとPointの値が0.001へと変わるため、先ほどの計算は結果が変わってします。

50 × 0.001 = 0.05円で利食い。

利食いの値幅が10倍も変わってくると、当然成績も大きく変わってしまいます。
このように、小数点以下の桁数によって成績が変わるのを防ぐため、多くの開発者は桁数を揃えるための倍率変数を用意しました。

int mult = 1; // 倍率変数
if (Digits == 3) {
   mult = 10; // 小数点以下3桁では10に変更
}
double takeprofit = Ask + TP * Point * mult;

このような変数を用意するとこで、ユーザーの入力いsた50pipsに対する挙動が統一されます。

小数点以下2桁の場合 50 0.01 1 = 0.5

小数点以下3桁の場合 50 0.001 10 = 0.5

USDJPYが小数点以下2桁の口座ではEURUSDなど非クロス円通貨ペアは小数点以下4桁であり、USDJPYが小数点以下2桁の口座では、EURUSDなどは5桁であるため、実際には下記のような処理を使います。

int mult = 1; // 倍率変数
if (Digits == 3 || Digits == 5) {
   mult = 10; // 小数点以下3桁または5桁では10に変更
}

上記のような処理を追加することで、ほとんどの口座・通貨ペアで同様に動作可能な、汎用性のあるEAを作成することができます。
これにより複数のブローカーで使用可能となり、USDJPYとEURUSDのように小数点以下の桁数が大きく違う通貨ペアでもそのままの処理で検証可能となりました。

多少書き方は違いますが、他にも以下のような書き方もあります。

int mult;
if (Digits == 3 || Digits == 5) {
   mult = 10; // 小数点以下3桁または5桁では10に変更
} else {
   mult = 1;
}
int mult = (Digits == 3 || Digits == 5) ? 10 : 1;

ここまでが今までのEA開発の経緯です。

EZインベスト証券のUSDJPY4桁追加

さて、EZインベスト証券のUSDJPYが追加されたことで、これまでのコードでは問題が出るようになりました。
先ほどのコードをEZインベスト証券のUSDJPYで使用するとどうなるでしょうか?

int mult = 1; 
if (Digits == 3 || Digits == 5) {
   mult = 10; 
}
double takeprofit = Ask + TP * Point * mult;

上記のコードはPointが0.0001、multが1となりますので、50 × 0.0001 × 1 = 0.005円で利食いとなってしまいます。

想定していた利食い幅と100倍のズレが出てしまいました。
上記のコードはUSDJPYが小数点以下4桁を想定していないため、仕方のないことです。

これまで汎用的に使えていた処理ですが、EZインベストUSDJPYに限っては不具合が出るようになってしまいました。
これにより、EA開発者は選択を迫られることとなります。

  1. EZインベスト証券のUSDJPYは例外として切り捨ててこれまでのコードを使用する
  2. EZインベスト証券のUSDJPYにも対応したコードを作成する

私も考えてみましたが、USDJPY4桁に対する有効なコードはまだ検討中です。
とりあえずの案として下記のコードを作成しました。

Int mult = (Digits == 3 || Digits == 5) ? 10 : 1;
if  (AccountCompany() == "EZ Invest Securities Co., Ltd." &&
StringSubstr(_Symbol, 0, 6) == "USDJPY") {
   Price::scale = 100;
}

EZインベスト証券で、尚且つUSDJPYチャートの場合のみ倍率変数を100に変える処理をベタ書きしています。
USDJPY以外の通貨ペアや、EZインベスト証券以外にも4桁口座が増えた場合、都度コードを修正しなくていけないのでスマートとは言えませんが、とりあえずは動作します。

今後も考えるとメンテの不要なスマートなコードが求められますので、近々時間をとってじっくり考えてみます。

開発者以外のEAユーザーの方も、EAやインジケーターをそのままEZインベスト証券のUSDJPYチャートで使用すると、これまで違った結果になってしまう可能性があるので注意してご利用ください。

arrow_upward