ブログタイトルを「FX自動売買システム開発部」から「autoFX」に変更しました!

資産のN%のリスクのロット数を計算する機能

アイキャッチ

固定ロット数は分かりやすいが適切ではない

仕掛ける時にロット数を設定する必要があります。一番シンプルなのは固定ロット数です。口座にいくらあるかは関係なく、常に一定のロット数を投入する方法ですね。

固定ロット数は分かりやすくて良い面もあるのですが、資金効率、資金管理の面から見て良いとは言えません。

資金効率、資金管理の面から見て、より好ましいのは資産のN%のリスクでロット数を決める方法です。例えば、100万円で2%のリスクとした場合、損切り時に最大2万円の損失になるようにロット数を決めるわけです。

こうすることで、(勝てば)複利を効かすことができますし、(負ければ)ロット数を減らすことができます。100万円の時に0.1ロットなら問題ないでしょうが、仮に20万円まで減った時に0.1ロットではハイレバ過ぎます。

豊嶋久道氏の「FXメタトレーダー実践プログラミング」にもロット数計算の関数が掲載されていますが、レバレッジ倍率をベースにしたもので、個人的には使いにくいという印象です。通常、仕掛ける時に「よし、今度はレバレッジ2倍で注文しよう!」って考えないですよね。レバレッジ倍率はあくまで結果であって、ロット数を決める際に使うものではないというのが私の考えです。

※豊嶋氏の名誉のために書かせていただきますが、上記の書籍は非常に素晴らしい内容(特に構成が素敵です)で、これからMQL4を学ばれる方にとってはバイブルとも言える書籍です。事実、私もこの書籍でMQL4の基礎を学び、現在に至っています。

まず、ライブラリーを作ります(ライブラリーの作り方はよく使う関数をライブラリー化 を参照)。ファイル名は「LotSizing.mqh」にしました。

中身は以下の通りです。

//+------------------------------------------------------------------+
//|                                                    LotSizing.mqh |
//|                                     Copyright (c) 2015, りゅーき |
//|                                            https://autofx100.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright (c) 2015, りゅーき"
#property link      "https://autofx100.com/"
#property version   "1.00"

//+------------------------------------------------------------------+
//|【関数】資産のN%のリスクのロット数を計算する                    |
//|                                                                  |
//|【引数】 IN OUT  引数名             説明                          |
//|        --------------------------------------------------------- |
//|         ○      aFunds             資金                          |
//|                                      AccountFreeMargin()         |
//|                                      AccountBalance()            |
//|         ○      aSymbol            通貨ペア                      |
//|         ○      aStopLossPips      損切り値(pips)              |
//|         ○      aRiskPercent       リスク率(%)                |
//|                                                                  |
//|【戻値】ロット数                                                  |
//|                                                                  |
//|【備考】計算した結果、最小ロット数未満になる場合、-1を返す        |
//+------------------------------------------------------------------+
double calcLotSizeRiskPercent(double aFunds, string aSymbol, double aStopLossPips, double aRiskPercent)
{
  // 取引対象の通貨を1ロット売買した時の1ポイント(pipsではない!)当たりの変動額
  double tickValue = MarketInfo(aSymbol, MODE_TICKVALUE);

  // tickValueは最小価格単位で計算されるため、3/5桁業者の場合、10倍しないと1pipsにならない
  if(MarketInfo(aSymbol, MODE_DIGITS) == 3 || MarketInfo(aSymbol, MODE_DIGITS) == 5){
    tickValue *= 10.0;
  }

  double riskAmount = aFunds * (aRiskPercent / 100.0);

  double lotSize = riskAmount / (aStopLossPips * tickValue);

  double lotStep = MarketInfo(aSymbol, MODE_LOTSTEP);

  // ロットステップ単位未満は切り捨て
  // 0.123⇒0.12(lotStep=0.01の場合)
  // 0.123⇒0.1 (lotStep=0.1の場合)
  lotSize = MathFloor(lotSize / lotStep) * lotStep;

  // 証拠金ベースの制限
  double margin = MarketInfo(aSymbol, MODE_MARGINREQUIRED);
  
  if(margin > 0.0){
    double accountMax = aFunds / margin;

    accountMax = MathFloor(accountMax / lotStep) * lotStep;

    if(lotSize > accountMax){
      lotSize = accountMax;
    }
  }

  // 最大ロット数、最小ロット数対応
  double minLots = MarketInfo(aSymbol, MODE_MINLOT);
  double maxLots = MarketInfo(aSymbol, MODE_MAXLOT);

  if(lotSize < minLots){
    // 仕掛けようとするロット数が最小単位に満たない場合、
    // そのまま仕掛けると過剰リスクになるため、エラーに
    lotSize = -1.0;
  }else if(lotSize > maxLots){
    lotSize = maxLots;
  }

  return(lotSize);
}

コードのコメントにも記載していますが、まず押さえるべきポイントはtickValueです。

  // 取引対象の通貨を1ロット売買した時の1ポイント(pipsではない!)当たりの変動額
  double tickValue = MarketInfo(aSymbol, MODE_TICKVALUE);

これは、取引対象の通貨を1ロット売買した時の1ポイント(pipsではない!)当たりの変動額を求める関数です。これに損切り値を掛けることで、その値幅における1ロット当たりの損失額が分かります。

MODE_TICKVALUEについて誤解されている記事(有名どころですと、MT4用EA開発時代 - ロット数の計算(サイジング)プログラミングについて【改訂版】[EA Tip 8] 常に資金の2%で注文する)がありますが、「[MQL4] 資産の4%のリスクで取引する(リンク先消滅)」にもある通り、正しくはpipsではなくポイントです。MQL4はpipsという単位を理解できません。内部での管理はポイントで行われていますので、くれぐれもご注意ください。

次のコードも分かりにくいかもしれません。損切り値はpipsで考えていますので、単位を揃えるためにtickValueをポイントからpipsに変換する必要があります。3/5桁業者の場合、1ポイント=0.1pipsでした。つまり、tickValueを10倍することで、取引対象の通貨を1ロット売買した時の1pips当たりの変動額になります。

  // tickValueは最小価格単位で計算されるため、3/5桁業者の場合、10倍しないと1pipsにならない
  if(MarketInfo(aSymbol, MODE_DIGITS) == 3 || MarketInfo(aSymbol, MODE_DIGITS) == 5){
    tickValue *= 10.0;
  }

riskAmountは資金(余剰証拠金にするか口座残高にするかはお好みで)の何パーセントの損失額になります。100万円の2%ならriskAmountは2万円ということです。それを損切りの値幅における1ロット当たりの損失額で割ることでロット数が求められます。

  double riskAmount = aFunds * (aRiskPercent / 100.0);
  double lotSize = riskAmount / (aStopLossPips * tickValue);

この段階のlotSizeは、上記の計算結果によっては、0.123753…のようにロットステップの単位になっていない場合があります。そのため、以下の処理でロットステップの単位に揃えています。切り捨てにしているのは、過剰ロット数を避けてリスクを減らすためです。

  // ロットステップ単位未満は切り捨て
  // 0.123⇒0.12(lotStep=0.01の場合)
  // 0.123⇒0.1 (lotStep=0.1の場合)
  lotSize = MathFloor(lotSize / lotStep) * lotStep;

以降の処理はロット数計算における異常時の対応で、本質から外れます。詳しくはFXメタトレーダー実践プログラミングへの補足(3)/CalculateLotsの改良?をご覧ください。

なお、本関数を作成するにあたって、FXメタトレーダー実践プログラミングへの補足(3)/CalculateLotsの改良?と「[MQL4] 資産の4%のリスクで取引する(リンク先消滅)」を参考にさせていただきました。

EA本体に記述する内容は以下の通りです。UseVariableLotSizeFlgで固定ロットか変動ロットかを切り替えられるようにしています。また、RiskPercentは何パーセントのリスクを負うかを設定するパラメータです。

//+------------------------------------------------------------------+
//| ライブラリ                                                       |
//+------------------------------------------------------------------+
// …
#include <Original/LotSizing.mqh>
// …
//+------------------------------------------------------------------+
//| EAパラメータ設定情報                                             |
//+------------------------------------------------------------------+
// …
extern bool   UseVariableLotSizeFlg = true;
extern double FixLotSize            = 0.01;
extern double RiskPercent           = 2.0;
// …
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
// …
  // -----------------------------------------------------------------
  // ロット数計算
  // -----------------------------------------------------------------
  if(UseVariableLotSizeFlg){
    double lotSize = calcLotSizeRiskPercent(AccountFreeMargin(), Symbol(), InitialSL_Pips, RiskPercent);
  }else{
    lotSize = FixLotSize;
  }
// …
}

サンプルEA

イメージが沸きづらいと思いますので、サンプルEAを載せておきます。

//+------------------------------------------------------------------+
//|                                                       Sample.mq4 |
//|                                     Copyright (c) 2015, りゅーき |
//|                                            https://autofx100.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright (c) 2015, りゅーき"
#property link      "https://autofx100.com/"
#property version   "1.00"

//+------------------------------------------------------------------+
//| ライブラリ                                                       |
//+------------------------------------------------------------------+
#include <stderror.mqh>
#include <stdlib.mqh>
#include <WinUser32.mqh>
#include <Original/Basic.mqh>
#include <Original/DateAndTime.mqh>
#include <Original/LotSizing.mqh>
#include <Original/OrderHandle.mqh>
#include <Original/OrderReliable.mqh>

//+------------------------------------------------------------------+
//| EAパラメータ設定情報                                             |
//+------------------------------------------------------------------+
extern string Note01                = "=== General ==================================================";
extern int    MagicNumber           = 7777777;
extern int    SlippagePips          = 5;
extern string Comments              = "";
extern string Note01_1              = "--- Risk % lot -----------------------------------------------";
extern bool   UseVariableLotSizeFlg = true;
extern double FixLotSize            = 0.01;
extern double RiskPercent           = 2.0;

extern string Note02                = "=== Exit =====================================================";
extern double InitialSL_Pips        = 50.0;

//+------------------------------------------------------------------+
//| グローバル変数                                                   |
//+------------------------------------------------------------------+
// 共通
double gPipsPoint     = 0.0;
int    gSlippage      = 0.0;
color  gArrowColor[6] = {Blue, Red, Blue, Red, Blue, Red}; //BUY: Blue, SELL: Red

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
  gPipsPoint = currencyUnitPerPips(Symbol());
  gSlippage = getSlippage(Symbol(), SlippagePips);

  return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
  // -----------------------------------------------------------------
  // ロット数計算
  // -----------------------------------------------------------------
  if(UseVariableLotSizeFlg){
    double lotSize = calcLotSizeRiskPercent(AccountFreeMargin(), Symbol(), InitialSL_Pips, RiskPercent);
  }else{
    lotSize = FixLotSize;
  }

  if(lotSize < 0){
    return;
  }

  // -----------------------------------------------------------------
  // 仕掛け
  // -----------------------------------------------------------------
  // 成行注文
  int ticket = orderSendReliableRange(Symbol(), OP_BUY, lotSize, Ask, gSlippage, InitialSL_Pips, 0.0, Comments, MagicNumber, 0, gArrowColor[OP_BUY]);

  // 本来はticketの値によって後続の処理を制御する必要があるが、簡単のため、ここでは無視

}

MQL4プログラミングの最新記事8件

>完全放ったらかしEA 「AutoEndlessCatchRange」

完全放ったらかしEA 「AutoEndlessCatchRange」

「本業が忙しい!」「でも資産運用したい!」そんなあなたに最適なEAです。兼業トレーダーの方はチャートを毎日みて分析してトレードする時間はなかなか確保できないものです。トレードは本EAに任せて、本業やプライベートの時間をもっと増やしませんか?元々は自分自身のために開発したEAですので、手抜き無しのガチものです。

CTR IMG