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

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

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

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

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

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

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

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

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

中身は以下の通りです。

01//+------------------------------------------------------------------+
02//|                                                    LotSizing.mqh |
03//|                                     Copyright (c) 2015, りゅーき |
04//|                                            https://autofx100.com/ |
05//+------------------------------------------------------------------+
06#property copyright "Copyright (c) 2015, りゅーき"
07#property link      "https://autofx100.com/"
08#property version   "1.00"
09 
10//+------------------------------------------------------------------+
11//|【関数】資産のN%のリスクのロット数を計算する                    |
12//|                                                                  |
13//|【引数】 IN OUT  引数名             説明                          |
14//|        --------------------------------------------------------- |
15//|         ○      aFunds             資金                          |
16//|                                      AccountFreeMargin()         |
17//|                                      AccountBalance()            |
18//|         ○      aSymbol            通貨ペア                      |
19//|         ○      aStopLossPips      損切り値(pips)              |
20//|         ○      aRiskPercent       リスク率(%)                |
21//|                                                                  |
22//|【戻値】ロット数                                                  |
23//|                                                                  |
24//|【備考】計算した結果、最小ロット数未満になる場合、-1を返す        |
25//+------------------------------------------------------------------+
26double calcLotSizeRiskPercent(double aFunds, string aSymbol, double aStopLossPips, double aRiskPercent)
27{
28  // 取引対象の通貨を1ロット売買した時の1ポイント(pipsではない!)当たりの変動額
29  double tickValue = MarketInfo(aSymbol, MODE_TICKVALUE);
30 
31  // tickValueは最小価格単位で計算されるため、3/5桁業者の場合、10倍しないと1pipsにならない
32  if(MarketInfo(aSymbol, MODE_DIGITS) == 3 || MarketInfo(aSymbol, MODE_DIGITS) == 5){
33    tickValue *= 10.0;
34  }
35 
36  double riskAmount = aFunds * (aRiskPercent / 100.0);
37 
38  double lotSize = riskAmount / (aStopLossPips * tickValue);
39 
40  double lotStep = MarketInfo(aSymbol, MODE_LOTSTEP);
41 
42  // ロットステップ単位未満は切り捨て
43  // 0.123⇒0.12(lotStep=0.01の場合)
44  // 0.123⇒0.1 (lotStep=0.1の場合)
45  lotSize = MathFloor(lotSize / lotStep) * lotStep;
46 
47  // 証拠金ベースの制限
48  double margin = MarketInfo(aSymbol, MODE_MARGINREQUIRED);
49   
50  if(margin > 0.0){
51    double accountMax = aFunds / margin;
52 
53    accountMax = MathFloor(accountMax / lotStep) * lotStep;
54 
55    if(lotSize > accountMax){
56      lotSize = accountMax;
57    }
58  }
59 
60  // 最大ロット数、最小ロット数対応
61  double minLots = MarketInfo(aSymbol, MODE_MINLOT);
62  double maxLots = MarketInfo(aSymbol, MODE_MAXLOT);
63 
64  if(lotSize < minLots){
65    // 仕掛けようとするロット数が最小単位に満たない場合、
66    // そのまま仕掛けると過剰リスクになるため、エラーに
67    lotSize = -1.0;
68  }else if(lotSize > maxLots){
69    lotSize = maxLots;
70  }
71 
72  return(lotSize);
73}

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

1// 取引対象の通貨を1ロット売買した時の1ポイント(pipsではない!)当たりの変動額
2double 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当たりの変動額になります。

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

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

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

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

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

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

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

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

1//+------------------------------------------------------------------+
2//| ライブラリ                                                       |
3//+------------------------------------------------------------------+
4// …
5#include <Original/LotSizing.mqh>
6// …
1//+------------------------------------------------------------------+
2//| EAパラメータ設定情報                                             |
3//+------------------------------------------------------------------+
4// …
5extern bool   UseVariableLotSizeFlg = true;
6extern double FixLotSize            = 0.01;
7extern double RiskPercent           = 2.0;
8// …
01//+------------------------------------------------------------------+
02//| Expert tick function                                             |
03//+------------------------------------------------------------------+
04void OnTick()
05{
06// …
07  // -----------------------------------------------------------------
08  // ロット数計算
09  // -----------------------------------------------------------------
10  if(UseVariableLotSizeFlg){
11    double lotSize = calcLotSizeRiskPercent(AccountFreeMargin(), Symbol(), InitialSL_Pips, RiskPercent);
12  }else{
13    lotSize = FixLotSize;
14  }
15// …
16}

サンプルEA

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

01//+------------------------------------------------------------------+
02//|                                                       Sample.mq4 |
03//|                                     Copyright (c) 2015, りゅーき |
04//|                                            https://autofx100.com/ |
05//+------------------------------------------------------------------+
06#property copyright "Copyright (c) 2015, りゅーき"
07#property link      "https://autofx100.com/"
08#property version   "1.00"
09 
10//+------------------------------------------------------------------+
11//| ライブラリ                                                       |
12//+------------------------------------------------------------------+
13#include <stderror.mqh>
14#include <stdlib.mqh>
15#include <WinUser32.mqh>
16#include <Original/Basic.mqh>
17#include <Original/DateAndTime.mqh>
18#include <Original/LotSizing.mqh>
19#include <Original/OrderHandle.mqh>
20#include <Original/OrderReliable.mqh>
21 
22//+------------------------------------------------------------------+
23//| EAパラメータ設定情報                                             |
24//+------------------------------------------------------------------+
25extern string Note01                = "=== General ==================================================";
26extern int    MagicNumber           = 7777777;
27extern int    SlippagePips          = 5;
28extern string Comments              = "";
29extern string Note01_1              = "--- Risk % lot -----------------------------------------------";
30extern bool   UseVariableLotSizeFlg = true;
31extern double FixLotSize            = 0.01;
32extern double RiskPercent           = 2.0;
33 
34extern string Note02                = "=== Exit =====================================================";
35extern double InitialSL_Pips        = 50.0;
36 
37//+------------------------------------------------------------------+
38//| グローバル変数                                                   |
39//+------------------------------------------------------------------+
40// 共通
41double gPipsPoint     = 0.0;
42int    gSlippage      = 0.0;
43color  gArrowColor[6] = {Blue, Red, Blue, Red, Blue, Red}; //BUY: Blue, SELL: Red
44 
45//+------------------------------------------------------------------+
46//| Expert initialization function                                   |
47//+------------------------------------------------------------------+
48int OnInit()
49{
50  gPipsPoint = currencyUnitPerPips(Symbol());
51  gSlippage = getSlippage(Symbol(), SlippagePips);
52 
53  return(INIT_SUCCEEDED);
54}
55 
56//+------------------------------------------------------------------+
57//| Expert deinitialization function                                 |
58//+------------------------------------------------------------------+
59void OnDeinit(const int reason)
60{
61}
62 
63//+------------------------------------------------------------------+
64//| Expert tick function                                             |
65//+------------------------------------------------------------------+
66void OnTick()
67{
68  // -----------------------------------------------------------------
69  // ロット数計算
70  // -----------------------------------------------------------------
71  if(UseVariableLotSizeFlg){
72    double lotSize = calcLotSizeRiskPercent(AccountFreeMargin(), Symbol(), InitialSL_Pips, RiskPercent);
73  }else{
74    lotSize = FixLotSize;
75  }
76 
77  if(lotSize < 0){
78    return;
79  }
80 
81  // -----------------------------------------------------------------
82  // 仕掛け
83  // -----------------------------------------------------------------
84  // 成行注文
85  int ticket = orderSendReliableRange(Symbol(), OP_BUY, lotSize, Ask, gSlippage, InitialSL_Pips, 0.0, Comments, MagicNumber, 0, gArrowColor[OP_BUY]);
86 
87  // 本来はticketの値によって後続の処理を制御する必要があるが、簡単のため、ここでは無視
88 
89}

MT4の無料プログラミング講座

メルマガ登録して、MT4のプログラミング講座を無料で受けちゃおう!

超豪華プレゼントも盛りだくさん♪

MT4プログラミングを習得すると、オリジナルEA運用、作成代行、商品販売等、複数の収入源を手に入れられるよ。副業に最適だね!

↓↓↓ 詳細はこちら ↓↓↓

アイキャッチ

>

エターナル・パートナーPRO ~MT4裁量トレード支援ツール~ 「MT4は裁量トレーダーに優しくない」そう思ったことありませんか?もっと快適にトレードするための強力な売買ツールが必要だと考え、開発したのが「エターナル・パートナーPRO」です。元々は自分自身のために開発したツールですので、手抜き無しのガチものです。既に200名近い方に手に取っていただき、喜びの声が続々と届いております。ぜひご覧ください!

CTR IMG