【超入門】MQL5 EA講座 第102回「資金管理用のインクルードファイルを作る」【EAの作り方】

MQL5でEA作ろう講座

前回は、資金管理ロット調整に関する基本的な部分を解説し、MQL5資金管理ロット調整を行う記述についても併せて解説を行いました。

今回は、前回の内容を踏まえた上で、資金管理ロット調整を容易に記述する為の関数を作っていきます。そして、それらの関数を一つに集約させたインクルードファイルを作っていく過程を解説していこうと思います。

今回解説する、資金管理ロット調整用のインクルードファイルを作ることによって、EA開発時の資金管理記述が楽になりますし、資金管理の行き届いたEAは実運用の際にも、資産の堅牢性を高めてくれます。

スポンサーリンク
スポンサーリンク
  1. 資金管理・ロット調整用のインクルードファイルを作る
  2. 資金の最大リスクを規定する定数を設定する
  3. ロット調整を行う関数を追加する
    1. VerifyVolume関数の戻り値
    2. VerifyVolume関数の仮引数
    3. VerifyVolume関数の処理実装記述
      1. double型の変数「minVolume」は、取り扱い最小ロットを格納する
      2. double型の変数「maxVolume」は、取り扱い最大ロットを格納する
      3. double型の変数「stepVolume」は、ロットのステップ幅を格納する
      4. 発注時に渡す、最終的なロット数を格納する変数「tradeSize」を宣言する
      5. 変数「tradeSize」に格納されているロット数を適切な形に整える記述を行う
      6. ブローカーの規定するステップ幅に応じて正規化を行う
  4. 資金管理を考慮したロット数を算出する関数を追加する
    1. MoneyRiskManagement関数の戻り値と仮引数について
      1. MoneyRiskManagement関数の戻り値はロット数
      2. 第1仮引数の「parSymbol」は取引銘柄情報が記述される想定
      3. 第2仮引数の「parFixedVol」は、固定ロットが記述される想定
      4. 第3仮引数の「parPercent」は許容損失%が記述される想定
      5. 第4仮引数の「parStopPoints」はポイントベースの損切り幅が記述される想定
    2. MoneyRiskManagement関数の処理実装記述
        1. ロット数を格納する変数を宣言する
        2. 仮引数が適切に設定されているかを確認する
        3. 最大リスク許容%を超えていたら、//最大リスク許容%に設定しなおす
        4. 許容損失額を設定する
        5. 1ティックごとの変動額を算出する
        6. ロット数を算出する
        7. 算出したロット数が適切かどうか、VerifyVolume関数で確認する。
        8. 仮引数に許容損失額を算出する値が設定されていな場合の記述を行う
  5. 約定価格とストップロス価格との差分をポイントに変換する関数を追加する
    1. StopPriceToPoints関数の戻り値と仮引数
      1. 第1仮引数の「parSymbol」は取引銘柄情報が記述される想定
      2. 第2仮引数の「parStopPrice」は損切り価格が記述される想定
      3. 第3仮引数の「parOrderPrice」は約定価格が記述される想定
    2. StopPriceToPoints関数の処理実装記述について
      1. 約定価格とストップロス価格との差分を算出する。
        1. MathAbs関数について
          1. 絶対値とは?
      2. 取引銘柄のポイント情報を取得して、変数に格納する
      3. 差分情報をポイントに変換して、変数に格納する
    3. StopPriceToPoints関数はどうやって使うのか?
  6. まとめ
  7. 今回の「OriginalMoneyManagement.mqh」ファイル全体の記述

資金管理・ロット調整用のインクルードファイルを作る

まずは資金管理ロット調整用のインクルードファイル(=.mqhファイル)を作っていきます。

//+------------------------------------------------------------------+
//|                                      OriginalMoneyManagement.mqh |
//|                                                         MQL5ssei |
//|                                    https://mqlinvestmentlab.com/ |
//+------------------------------------------------------------------+
#property copyright "MQL5ssei"
#property link      "https://mqlinvestmentlab.com/"
//+------------------------------------------------------------------+

ファイル名を「OriginalMoneyManagement.mqh」ファイルとしました。

このファイルに資金管理・ロット調整用の関数を作っていきます。

インクルードファイルって何?」という方がいらっしゃいましたら、↓の記事をご覧ください。

資金の最大リスクを規定する定数を設定する

OriginalMoneyManagement.mqh」ファイルに関数を追加していく前に、資金管理をする上で資金の最大何%までの損失を許容するか?という事を規定する定数を設定します。

#define MAX_RISK_PERCENT 10		// 最大リスク許容度を設定する

定数名を「MAX_RISK_PERCENT」としました。

この定数の具体的な使い方はこの後解説しますが、サンプルコードのように「10」とした場合は、口座残高の10%までは損失を許容する、という意味になります。

#define命令については↓の記事をご覧ください。

MQL5 EA講座 第17回「定数(Constant)について」

ロット調整を行う関数を追加する

まずはロット調整を行う関数を追加します。

今回はクラス所属のメンバ関数ではなく、独立関数として宣言をします。

// ロット数を確認・調整する関数
double VerifyVolume(string parSymbol,double parVolume)
{

}

関数名をVerifyVolumeとしました。

VerifyVolume関数の戻り値

ロット数を戻り値として返す想定なので、戻り値データ型double型です。

VerifyVolume関数の仮引数

第1引数の「parSymbol」は取引銘柄情報が記述される想定なので、データ型string型です。

第2引数の「parVolume」はロット数が記述される想定なので、データ型double型です。

VerifyVolume関数の処理実装記述

VerifyVolume関数の処理実装記述は以下の通りです。

基本的に前回の第101回にて「ロット調整に関する記述について」セクションで解説した内容と同じです。

// ロット数を確認・調整する関数
double VerifyVolume(string parSymbol,double parVolume)
{
	double minVolume = SymbolInfoDouble(parSymbol,SYMBOL_VOLUME_MIN);
	double maxVolume = SymbolInfoDouble(parSymbol,SYMBOL_VOLUME_MAX);
	double stepVolume = SymbolInfoDouble(parSymbol,SYMBOL_VOLUME_STEP);
	
	double tradeSize;
	if(parVolume < minVolume) tradeSize= minVolume;
	else if(parVolume > maxVolume) tradeSize= maxVolume;
	else tradeSize = MathRound(parVolume / stepVolume) * stepVolume;
	
	if(stepVolume >= 0.1) tradeSize = NormalizeDouble(tradeSize,1);
	else tradeSize = NormalizeDouble(tradeSize,2);
	
	return(tradeSize);
}

double型の変数「minVolume」は、取り扱い最小ロットを格納する

double型ローカル変数「minVolume」には、各ブローカーが設定している、対象取引通貨ペアの取り扱い最小ロットを格納します。

	double minVolume = SymbolInfoDouble(parSymbol,SYMBOL_VOLUME_MIN);

取り扱い最小ロットの取得には、SymbolInfoDouble関数の第2引数定数「SYMBOL_VOLUME_MIN」を記述します。

double型の変数「maxVolume」は、取り扱い最大ロットを格納する

double型ローカル変数「maxVolume」には、各ブローカーが設定している、対象取引通貨ペアの取り扱い最大ロットを格納します。

double maxVolume = SymbolInfoDouble(parSymbol,SYMBOL_VOLUME_MAX);

取り扱い最大ロットの取得には、SymbolInfoDouble関数の第2引数定数「SYMBOL_VOLUME_MAX」を記述して取得します。

double型の変数「stepVolume」は、ロットのステップ幅を格納する

double型ローカル変数「stepVolume」には、ロットのステップ幅を格納します。

double stepVolume = SymbolInfoDouble(parSymbol,SYMBOL_VOLUME_STEP);

ロットのステップ幅の取得には、SymbolInfoDouble関数の第2引数定数「SYMBOL_VOLUME_STEP」を記述して取得します。

発注時に渡す、最終的なロット数を格納する変数「tradeSize」を宣言する

double tradeSize;

double型ローカル変数「tradeSize」は、発注の際、

MqlTradeRequest構造体メンバ変数である .Volumeへの値を代入する為に使います。

変数「tradeSize」に格納されているロット数を適切な形に整える記述を行う

if(parVolume < minVolume) tradeSize = minVolume;
	

(parVolume< minVolume)は、引数「parVolume」に格納されている値が、ブローカーの規定した取引最小ロットよりも小さい値になっている事を意味します。

これではエラーになってしまうので、この場合は、

tradeSize = minVolume;

とし、規定されている取引最小ロットの値を変数「tradeSize」に代入します。

else if(parVolume > maxVolume) tradeSize = maxVolume;

その次のelse if文()の条件文

(parVolume> maxVolume)は、引数「parVolume」に格納されている値が、ブローカーの規定した取引最大ロットよりも大きい値になっている事を意味します。これもエラーになってしまうので、この場合も、

tradeSize = maxVolume;

すなわち、規定されている取引最大ロットの値を変数「tradeSize」に代入します

最後のelse文に、最小ロット・最大ロットに違反していない場合の記述を行います。

else tradeSize = MathRound(parVolume / stepVolume) * stepVolume;

MathRound(parVolume / stepVolume) * stepVolume;

↑の記述の解説については、前回行っておりますので、前回の「最小ロット・最大ロットに違反していない場合の記述を行う」セクション以降をご確認ください。

MathRound関数についてはコチラのリンクをご覧ください。

ブローカーの規定するステップ幅に応じて正規化を行う

if(stepVolume >= 0.1) tradeSize = NormalizeDouble(tradeSize,1);
	else tradeSize = NormalizeDouble(tradeSize,2);

最後に念の為、ブローカーの規定するステップ幅に応じて正規化を行います。

正規化というのは、プログラムが取り扱うルールに則って値を整える作業

のことを言います。

正規化にはNormalizeDouble関数を利用します。

NormalizeDouble関数については↓の記事をご覧ください。

変数「stepVolume」の値が0.1以上のときは、小数点第1位で、

そうでない時、すなわち変数「stepVolume」の値が0.1より小さいときは、小数点第2位で、

それぞれ正規化を行います。

以上の処理を経て、適切な値に整えたロット数を、変数「tradeSize」に格納し、return戻り値として返します。

VerifyVolume関数の処理実装記述はこれで完了です。

資金管理を考慮したロット数を算出する関数を追加する

続いて資金管理を考慮したロット数を算出する関数を「OriginalMoneyManagement.mqh」ファイルに追加していきます。

簡単に言うと、口座残高の何%までの損失なら許容する、という設定をEA稼働前に任意にできるようにした上で、その許容損失額を1回のトレードで超えないようにロット数を調整する関数です。

// 資金管理を考慮したロット数を算出する関数
double MoneyRiskManagement(string parSymbol,double parFixedVol,double parPercent,int parStopPoints)
{

}

関数名はMoneyRiskManagementとしました。

MoneyRiskManagement関数の戻り値と仮引数について

MoneyRiskManagement関数の戻り値はロット数

ロット数を戻り値として返す想定なので、戻り値データ型double型です。

第1仮引数の「parSymbol」は取引銘柄情報が記述される想定

第1引数の「parSymbol」は取引銘柄情報が記述される想定なので、データ型string型です。

第2仮引数の「parFixedVol」は、固定ロットが記述される想定

第2引数の「parFixedVol」は、固定ロットが記述される想定です。

「リスク管理を考慮してロットを算出する関数なのになぜ固定ロット?」と思われるかもしれません。

後で、処理実装記述を解説する時に詳しく説明しますが、算出されたロットが不適切だった場合には、固定ロットを発注する為にこの引数は設けられています。

第3仮引数の「parPercent」は許容損失%が記述される想定

第3引数の「parPercent」は許容損失%が記述される想定です。データ型double型となります。

例えば、ここに「1」と入っていれば口座残高の1%までは1回のトレードで損失を許容する、という設計にします。

どのようにしてそれを実現するかは処理実装記述の時に解説します。

第4仮引数の「parStopPoints」はポイントベースの損切り幅が記述される想定

第4引数の「parStopPoints」はポイントベースの損切り幅が記述される想定です。

データ型int型です。「ポイントベースの損切り幅って何?」と思われたかもしれませんが、例えば、この引数に「500」という値を設定していた場合、500ポイント→取引銘柄がドル円であった場合は0.5(円)が損切り幅になるように処理実装記述を行います。これも詳しくは処理実装記述の所で説明します。

MoneyRiskManagement関数の処理実装記述

MoneyRiskManagement関数の処理実装記述は以下の通りです。

// 資金管理を考慮したロット数を算出する関数
double MoneyRiskManagement(string parSymbol,double parFixedVol,double parPercent,int parStopPoints)
{
	double tradeSize;//ロット数を格納する変数を宣言
	
	if(parPercent > 0 && parStopPoints > 0)
	{  //最大リスク許容%を超えていたら、//最大リスク許容%に設定しなおす
		if(parPercent > MAX_RISK_PERCENT) parPercent = MAX_RISK_PERCENT;
		
		//許容損失額を設定する
		double margin = AccountInfoDouble(ACCOUNT_BALANCE) * (parPercent / 100);
		//1ポイントごとの変動額を算出する
		double tickSize = SymbolInfoDouble(parSymbol,SYMBOL_TRADE_TICK_VALUE);
		
		//ロット数を算出する。
		tradeSize = (margin / parStopPoints) / tickSize;
		//算出したロット数が適切かどうかVerifyVolume関数で確認する。
		tradeSize = VerifyVolume(parSymbol,tradeSize);
		//ロット数を戻り値として返す
		return(tradeSize);
	}
	else
	{//仮引数に許容損失額を算出する値が設定されていなければ固定ロットを返す
		tradeSize = parFixedVol;
		tradeSize = VerifyVolume(parSymbol,tradeSize);
		
		return(tradeSize);
	}

一つ一つ順を追って見ていきます。

ロット数を格納する変数を宣言する
double tradeSize;//ロット数を格納する変数を宣言

まずはロット数を格納する変数を宣言します。

変数名は「tradeSize」とします。戻り値として返すので、データ型double型です。

仮引数が適切に設定されているかを確認する
//仮引数が適切に設定されているかを確認する
	if(parPercent > 0 && parStopPoints > 0)
{

}

損失許容%を設定する為の引数「parPercent」、ポイントベースの損切り幅を設定する引数「parStopPoints」に適切な値が入っているかどうかをif文で切り分けています。

どちらから0より小さい値になっていた場合、固定ロットに切り替えます(この記事の「仮引数に許容損失額を算出する値が設定されていな場合の記述を行う」セクションで後述します)

最大リスク許容%を超えていたら、//最大リスク許容%に設定しなおす

if(parPercent > 0 && parStopPoints > 0)の条件式がtrueだった場合の{}内記述に移りますが、↓

if(parPercent > 0 && parStopPoints > 0)
	{  //最大リスク許容%を超えていたら、最大リスク許容%に設定しなおす
		if(parPercent > MAX_RISK_PERCENT) parPercent = MAX_RISK_PERCENT;

今回の記事の冒頭、「資金の最大リスクを規定する定数を設定する」セクションにて、「MAX_RISK_PERCENT」という定数#define命令により設定しました。

サンプルコードでの定数「10」としていましたが、この場合どんなにリスクをとっても最大10%という事になります。このサンプルコードの記述に従うと、

もし仮引数「parPercent」の値が、15とか20になっていた場合、定数「MAX_RISK_PERCENT」で10に修正しよう・・・というのがこの記述の意味です。

許容損失額を設定する
//許容損失額を設定する
		double margin = AccountInfoDouble(ACCOUNT_BALANCE) * (parPercent / 100);

続いて損失許容額を設定します。

損失許容額を設定するにはまず口座残高情報を取得しなくてはいけません。

口座残高情報を取得するには、AccountInfoDouble関数引数定数「ACCOUNT_BALANCE」を記述して取得します。

その後の、

(parPercent / 100)

という記述についてですが、引数「parPercent」は、「第3仮引数の「parPercent」は許容損失%が記述される想定」セクションで解説した通り、許容損失%が記述される想定なので、例えば「3」という値になっていたら、3/100→0.03、すなわち3%ということになります。

それを口座残高に掛け算をすると、1回のトレードにおける許容損失額が導き出されます。

仮に口座残高が100万円だとすると、3万円が許容損失額になります。

算出された値をdouble型ローカル変数「margin」に代入します。

1ティックごとの変動額を算出する
//1ロットにおける、1ティックごとの変動額を算出する
		double tickSize = SymbolInfoDouble(parSymbol,SYMBOL_TRADE_TICK_VALUE);

続いては1ロット(=10万通貨)における、1ティックごとの変動額を算出します。

「1ロットにおける、1ティックごとの変動額」という言葉にピンとこない人がいらっしゃるかもしれません。1ティックというのは、各取引銘柄における、最低変動幅の事です。

3桁通貨であれば0.001、5桁通貨であれば0.00001となります。

「1ティックごとの変動額」というのは、この最低変動幅の動きがあった時、金額的にはいくらの変動があるのか?ということを示す情報になります。

「1ティックごとの変動額」情報を取得するにはSymbolInfoDouble関数の第2引数定数「SYMBOL_TRADE_TICK_VALUE」を記述して実現します。

例えば、対象取引銘柄がドル円であったとします。定数「SYMBOL_TRADE_TICK_VALUE」をSymbolInfoDouble関数の第2引数に指定して取得できる「1ロットにおける、1ティックごとの変動額」は100(円)です。

この値をdouble型ローカル変数「tickSize」に代入します。

ロット数を算出する

ロット算出に必要な情報は一通り取得出来たので、ロット算出の記述を行います

//ロット数を算出する。
		tradeSize = (margin / parStopPoints) / tickSize;

変数「margin」には許容損失額が格納されています。仮に口座残高100万円、許容損失%=3%だとすると30000という値になっているはずです。

変数「parStopPoints」はポイントベースでの損切り幅が格納されています。仮に入力されているのが「1000」だとしましょう。その場合、(margin / parStopPoints)は(30000/1000)という事になり、「30」という答えが導き出されます。

変数「tickSize」には先述した通り、ドル円の場合であれば「100」という数字が格納されている筈なので、(margin / parStopPoints) / tickSize→(30000/1000)/100=0.3という値になります。

すなわち0.3ロットが設定したリスク許容度における適切なロット数ということになります。

これを変数「tradeSize」に代入します。

算出したロット数が適切かどうか、VerifyVolume関数で確認する。
//算出したロット数が適切かどうかVerifyVolume関数で確認する。
		tradeSize = VerifyVolume(parSymbol,tradeSize);
		//ロット数を戻り値として返す
		return(tradeSize);

算出したロット数が適切かどうか、VerifyVolume関数で確認します。

VerifyVolume関数については、先ほど解説しました。

主にやっている処理は

取り扱い最小ロットよりも小さくなっていないか?のチェック

取り扱い最大ロットより大きくなっていないか?のチェック

ロットステップ幅の調整

などです。

※もし、VerifyVolume関数について、よくわからなくなってしまったら、今回の記事の「ロット調整を行う関数を追加する」セクションから一度読み直して頂ければと思います。

VerifyVolume関数で、変数「tradeSize」の値を確認した後、return変数「tradeSize」に格納されている値を戻り値として返します。

仮引数に許容損失額を算出する値が設定されていな場合の記述を行う

MoneyRiskManagement関数の処理実装記述のelse文

if(parPercent > 0 && parStopPoints > 0)

に対応したものになります。即ち、引数「parPercent」や「parStopPoints 」どちらに0以下の数字が格納されていた場合の処理記述となります。

この場合、口座残高に対する許容損失額が算出できないので固定ロットを戻り値として返します。

else
	{//仮引数に許容損失額を算出する値が設定されていなければ固定ロットを返す
		tradeSize = parFixedVol;
		tradeSize = VerifyVolume(parSymbol,tradeSize);
		
		return(tradeSize);
	}
}

第2引数の「parFixedVol」はここで登場します。

許容損失額を前提としたロットを算出できないので、「parFixedVol」にあらかじめ設定してある固定ロット(メインプログラムにてinput変数などで設定するのが一般的です)を変数「tradeSize」に代入します。

ここでも、VerifyVolume関数で、変数「tradeSize」の値を確認するのは同じです。確認後、return変数「tradeSize」に格納されている値を戻り値として返します。

MoneyRiskManagement関数の処理実装記述は以上で終了です。

約定価格とストップロス価格との差分をポイントに変換する関数を追加する

今回の講座では、最後にもう一つ関数を追加します。

担う処理は約定価格とストップロス価格との差分をポイントに変換する事です。・・・←何を言っているのか、わかならないという人も多いかもしれません。

が!一旦待ってください。この時点ではわからなくても大丈夫です。関数の処理実装記述の解説でしっかり説明いたします。

//約定価格とストップロス価格との差分をポイントに変換する関数
double StopPriceToPoints(string parSymbol,double parStopPrice, double parOrderPrice)
{
	
}

関数名を「StopPriceToPoints」としました。

StopPriceToPoints関数の戻り値と仮引数

続いては戻り値引数です。

戻り値「約定価格とストップロス値との差分をポイントに変換した値」になります。

データ型double型です。

くどいようですが、「約定価格とストップロス値との差分をポイントに変換した値」が何を意味するのかについては、もう少々お待ちください。

第1仮引数の「parSymbol」は取引銘柄情報が記述される想定

第1引数の「parSymbol」は取引銘柄情報が記述される想定なので、データ型string型です。

第2仮引数の「parStopPrice」は損切り価格が記述される想定

第2引数の「parStopPrice」は損切り価格が記述される想定です。

損切り価格という事は必然的にデータ型double型となります。

第3仮引数の「parOrderPrice」は約定価格が記述される想定

第3引数の「parOrderPrice」は約定価格が記述される想定です。約定価格なので、データ型double型です。

StopPriceToPoints関数の処理実装記述について

StopPriceToPoints関数の処理実装記述は以下の通りです。

//約定価格とストップロス価格との差分をポイントに変換する関数
double StopPriceToPoints(string parSymbol,double parStopPrice, double parOrderPrice)
{
	double stopDiff = MathAbs(parStopPrice - parOrderPrice);
	double getPoint = SymbolInfoDouble(parSymbol,SYMBOL_POINT);
	double priceToPoint = stopDiff / getPoint;
	return(priceToPoint);
}

一つ一つ上から順に記述を追って見ていきましょう

約定価格とストップロス価格との差分を算出する。

まずは約定価格とストップロス価格との差分を算出します。

double stopDiff = MathAbs(parStopPrice - parOrderPrice);

引数「parStopPrice」は損切り価格、引数「parOrderPrice」は約定価格がそれぞれ記述される想定になっています。

parStopPrice-parOrderPrice、即ち、損切り価格-約定価格 を計算する事で差分が算出されるわけですが、ポジションが買いの場合、損切り価格の方が小さくなるので、答えがマイナスになってしまいます。正しく差分を算出する為に、MathAbs関数を使って絶対値を取得します。

MathAbs関数について

MathAbs関数引数に指定した値・計算式の絶対値を求める関数になります。

絶対値とは?

絶対値とは、0からの距離を表す「マイナスではない数」のことです。

絶対値を求めるには、数値がマイナスの場合にはマイナスを取り除いたものを採用します。例えば、-5という数値の場合、5がその絶対値になります。(分かり易さを重視して、用語の厳密さは欠いている部分があります)

取引銘柄のポイント情報を取得して、変数に格納する

続いて取引銘柄のポイント情報を取得して、変数「getPoint」に代入します。

double getPoint = SymbolInfoDouble(parSymbol,SYMBOL_POINT);

ポイント情報の取得にはSymbolInfoDouble関数の第2引数定数「SYMBOL_POINT」を記述します。

差分情報をポイントに変換して、変数に格納する

約定価格とストップロス価格の差分をポイントに変換して、変数「priceToPoint」に代入します。

double priceToPoint = stopDiff / getPoint;
return(priceToPoint);

変数「stopDiff」には約定価格とストップロス価格の差分が格納されています。

仮に取引銘柄がドル円だとして、約定価格が101円、ストップロス価格が100円だとすると、101-100→1が格納される想定です。

変数「getPoint」には取引銘柄のポイント情報が格納されています。

仮に取引銘柄がドル円だとすると、ドル円はポイントは0.001となっています。

ポイントについてはコチラをご覧ください。

上記の例を

stopDiff / getPoint に当てはめると 1/0.001→1000ポイント

という値が導き出されます。この値を変数「priceToPoint」に代入し、最後にreturn戻り値として返してStopPriceToPoints関数の処理は終了です。

StopPriceToPoints関数はどうやって使うのか?

StopPriceToPoints関数は、約定価格とストップロス価格との差分をポイントに変換する処理を行う関数なのですが、なんのためにこんな関数を用意したのかピンとこない人も多いかもしれません。

例えば、「資金管理を考慮したロット数を算出する関数を追加する」セクションで解説したMoneyRiskManagement関数は、第4引数ポイントベースの損切り幅を記述することによって、ロット数を割り出しています。

input変数でパラメータ化した値をこの第4引数に記述したりする場合は問題ないのですが、直近高安値だったり、インジケータではじき出した値をストップロスに設定したい場合は、その価格をポイントに変換してからでないと、今回作ったMoneyRiskManagement関数に使うことができません。

例えば、特定期間の直近高安値をストップロス値に設定する場合であれば、

1:iHighest関数iLowest関数を使って、直近高安値の情報を取得する。

2:1で取得した値をStopPriceToPoints関数の第2引数に記述してポイントに変換する

3:2でポイントに変換した値をMoneyRiskManagement関数の第4引数に記述する

以上のプロセスを踏むことによって、直近高安値をストップロス値に設定しつつ、損失額は常に口座残高の一定%内に収まるようなEAを作ることができるようになります。

※直近高安値については、以下の記事をご参照ください。

まとめ

今回は、資金管理ロット調整を容易に行うための関数を作り、その解説を行いました。

またそれらの関数を集約させるためのインクルードファイル、「OriginalMoneyManagement.mqh」ファイルを作りました。

OriginalMoneyManagement.mqh」ファイル内に作った関数は以下の通りです↓

VerifyVolume関数ロット調整を行う)

MoneyRiskManagement関数資金管理を考慮したロット数を算出する)

StopPriceToPoints関数(約定価格とストップロス価格との差分をポイントに変換する)

今回の「OriginalMoneyManagement.mqh」ファイル全体の記述

今回の「OriginalMoneyManagement.mqh」ファイル全体の記述は以下の通りです。

//+------------------------------------------------------------------+
//|                                      OriginalMoneyManagement.mqh |
//|                                                         MQL5ssei |
//|                                    https://mqlinvestmentlab.com/ |
//+------------------------------------------------------------------+
#property copyright "MQL5ssei"
#property link      "https://mqlinvestmentlab.com/"
//+------------------------------------------------------------------+

#define MAX_RISK_PERCENT 10		// 最大リスク許容度

// ロット数を確認・調整する関数
double VerifyVolume(string parSymbol,double parVolume)
{
	double minVolume = SymbolInfoDouble(parSymbol,SYMBOL_VOLUME_MIN);
	double maxVolume = SymbolInfoDouble(parSymbol,SYMBOL_VOLUME_MAX);
	double stepVolume = SymbolInfoDouble(parSymbol,SYMBOL_VOLUME_STEP);
	
	double tradeSize;
	if(parVolume < minVolume) tradeSize = minVolume;
	else if(parVolume > maxVolume) tradeSize = maxVolume;
	else tradeSize = MathRound(parVolume / stepVolume) * stepVolume;
	
	if(stepVolume >= 0.1) tradeSize = NormalizeDouble(tradeSize,1);
	else tradeSize = NormalizeDouble(tradeSize,2);
	
	return(tradeSize);
}

// 資金管理を考慮したロット数を算出する関数
double MoneyRiskManagement(string parSymbol,double parFixedVol,double parPercent,int parStopPoints)
{
	double tradeSize;//ロット数を格納する変数を宣言
	
	//仮引数が適切に設定されているかを確認する
	if(parPercent > 0 && parStopPoints > 0)
	{  //最大リスク許容%を超えていたら、//最大リスク許容%に設定しなおす
		if(parPercent > MAX_RISK_PERCENT) parPercent = MAX_RISK_PERCENT;
		
		//許容損失額を設定する
		double margin = AccountInfoDouble(ACCOUNT_BALANCE) * (parPercent / 100);
		//1ティックごとの変動額を算出する
		double tickSize = SymbolInfoDouble(parSymbol,SYMBOL_TRADE_TICK_VALUE);
		
		//ロット数を算出する。
		tradeSize = (margin / parStopPoints) / tickSize;
		//算出したロット数が適切かどうかVerifyVolume関数で確認する。
		tradeSize = VerifyVolume(parSymbol,tradeSize);
		//ロット数を戻り値として返す
		return(tradeSize);
	}
	else
	{//仮引数に許容損失額を算出する値が設定されていなければ固定ロットを返す
		tradeSize = parFixedVol;
		tradeSize = VerifyVolume(parSymbol,tradeSize);
		
		return(tradeSize);
	}
}


//約定価格とストップロス価格との差分をポイントに変換する関数
double StopPriceToPoints(string parSymbol,double parStopPrice, double parOrderPrice)
{
	double stopDiff = MathAbs(parStopPrice - parOrderPrice);
	double getPoint = SymbolInfoDouble(parSymbol,SYMBOL_POINT);
	double priceToPoint = stopDiff / getPoint;
	return(priceToPoint);
}

今回は以上とさせていただきます。

最後までお読みいただきありがとうございました。

MQL5 EA講座 第101回「資金管理とロット調整について」

    →MQL5 EA講座 第103回「価格とバーに関するデータへのアクセス:その1現在値」

コメント

タイトルとURLをコピーしました