FXで「レバレッジ」というと、必要となる証拠金に対して、実際に取引できる金額がその何倍かという倍率を表します。レバレッジが高い方が資金効率が高いと言えますが、むやみに売買ロット数を増やすと、単にリスクが増えるだけです。

ここでは、利用可能な証拠金に対して実際に取引する金額がその何倍かという「実質レバレッジ」を使ってロット数を変化させるシステムを考えます。

コード

//共通ライブラリ
#include "LibEA.mqh"

input int Leverage = 2; //実質レバレッジ

//ティック時実行関数
void Tick()
{
   int sig_entry = EntrySignal(); //仕掛けシグナル
   double lots = CalculateLots(Leverage); //ロット数の算出
   //成行売買
   MyOrderSendMarket(sig_entry, sig_entry, lots);
}

input int MomPeriod = 20; //モメンタムの期間

//仕掛けシグナル関数
int EntrySignal()
{
   //1本前のモメンタム
   double mom1 = iMomentum(_Symbol, 0, MomPeriod, PRICE_CLOSE, 1);

   int ret = 0; //シグナルの初期化

   //買いシグナル
   if(mom1 > 100) ret = 1;
   //売りシグナル
   if(mom1 < 100) ret = -1;

   return ret; //シグナルの出力
}

//ロット数算出関数
double CalculateLots(double leverage)
{
   string acct_cur = AccountInfoString(ACCOUNT_CURRENCY);//口座通貨
   double free_margin = AccountInfoDouble(ACCOUNT_MARGIN_FREE);//利用可能証拠金
   string trade_cur = StringSubstr(_Symbol, 0, 3);//売買通貨

   string conv_symbol = trade_cur+acct_cur+StringSubstr(_Symbol, 6); //変換通貨ペア
   string reverse_symbol = acct_cur+trade_cur+StringSubstr(_Symbol, 6); //逆変換通貨ペア
   double conv_close = iClose(conv_symbol, 0, 0); //変換通貨ペア価格
   double reverse_close = iClose(reverse_symbol, 0, 0); //逆変換通貨ペア価格
   
   double conv = 1; //変換レート
   if(conv_close != 0) conv = conv_close;
   else if(reverse_close != 0) conv = 1/reverse_close;
   
   //ロット数の計算
   double lots = free_margin*leverage/(100000*conv);
   return NormalizeLots(lots); //正規化ロット数
}

説明

毎回のトレードのロット数を、利用可能な証拠金と実質レバレッジLeverageから算出します。ロット数の算出は、別途定義する関数CalculateLots()で行います。

実質レバレッジは、証拠金の入っている口座の通貨を基準に考えます。まず、AccountInfoString(ACCOUNT_CURRENCY)で口座の通貨名をacct_curに、AccountInfoDouble(ACCOUNT_MARGIN_FREE)で利用可能な証拠金をfree_marginに取得します。

例えば、取引する通貨ペアがUSDJPYの場合、1ロットの取引でUSD100,000を売買することになります。口座通貨も同じくUSDであれば、free_margin*leverageの売買ができるということなので、ロット数はfree_margin*leverage/100000と算出します。

ただし、売買する通貨と口座通貨が異なる場合、売買する通貨の金額を口座通貨に換算する必要があります。

口座通貨がJPYであれば、USDJPYのレートを掛けてJPYに換算、口座通貨がEURであれば、EURUSDのレートで割ってEURに換算する必要があります。この換算レートをconvという変数に求めています。

換算レートを掛けるか、割るかは、対応する通貨ペアによります。あらかじめ、USDJPYとJPYUSDという二つの通貨ペアをconv_symbolreverse_symbolとして作っておきます。そして、iClose()でそれぞれの通貨ペアの価格を求めます。

通貨ペアが存在しなければ0となるので、0でなかった通貨ペアの価格を換算レートとします。そして、ロット数を算出する式の100000(100000*conv)とします。

ただし、このままではロット数の値が半端な値になってしまうので、取引可能なロット数に変換するために、NormalizeLots()を通して出力します。


<aside> 💡 通貨ペア名を文字列として作成する際に、通貨名のみを取り出すためにStringSubstr()という関数を利用します。例えば、「USDJPY」という通貨ペアの場合、StringSubstr("USDJPY", 0, 3)で「USD」が、StringSubstr("USDJPY", 3, 3)で「JPY」が取り出せます。また「USDJPY-a」のようにサフィックスがついている場合、StringSubstr("USDJPY-a", 6)でサフィックス「-a」が取り出せます。

</aside>