前回はOriginalTrade.mqhファイルに以下の関数を追加・実装する過程を解説しました。↓
- ModifyUpperStopLevel関数(ストップレベルの最小値を満たすよう修正する独立関数)
- ModifyLowerStopLevel関数(ストップレベルの最大値を満たすよう修正する独立関数)
今回は、動的ストップロスに関する話をしていきたいと思います。
- 動的ストップロスとは?
- 直近高値・直近安値を利用した動的ストップロス設定のロードマップ
- 今回の記事のまとめ
動的ストップロスとは?
MQL5でEA作ろう講座の第76回~80回までは、ストップロス(SL)に関連する記事でした。↓
- 第76回「SLとTPを設定する関数をクラスに追加する」
- 第77回「固定SLTPを計算する関数を実装する」
- 第78回「ストップレベルについて」
- 第79回「注文価格がストップレベルに違反していないかをチェックする関数」
- 第80回「ストップレベルに違反していた場合に、自動修正する関数」
講座記事を通して、ストップロス設定をするのに必要な関数群をOriginalTrade.mqhファイルにいくつか追加してきたわけですが、基本的にこれまで説明してきたのは固定ストップロス設定についてでした。
固定ストップロスというのは、一度ストップロス値(SL値)を設定したら、そのストップロス値を変更しないストップロス設定方式のことです。
それに対して、動的ストップロスというのは、一度設定したストップロス値を戦略に応じて変更させていくストップロス設定方式です。
動的ストップロスについても、サポートライン・レジスタンスラインを使ったり、各種インジケータの値を使ったり・・・と、作るEAの戦略に応じて色々なやり方があるかと思いますが、今回は直近高値・直近安値を利用した動的ストップロスを設定する方法を紹介したいと思います。
直近高値・直近安値を利用した動的ストップロス設定のロードマップ
直近高値・直近安値を利用した動的ストップロス設定の実現には、以下の工程を経て実現していきます。
- 直近高値・直近安値情報を取得する
- input変数にて、ModifyUpperStopLevel関数やModifyLowerStopLevel関数の第3引数に記述する、ストップレベルの上振れ幅・下振れ幅の値を設定する。
- 取得した直近高値・直近安値情報をModifyUpperStopLevel関数やModifyLowerStopLevel関数の第2引数に記述して、最終的なSL値を算出する。
直近高値・直近安値情報を取得する
直近高値・直近安値情報を取得する為には、
直近高値情報に関しては、
直近安値情報に関しては、
を使います。
今回はiHighest関数とiLowest関数を使った方法で解説していこうと思います。(ArrayMaximum関数・ ArrayMinimum関数はちょっと記述が複雑になってしまう為)
iHighest関数について
iHighest関数の引数構成と戻り値は以下のようになっています。
int iHighest(
const string symbol, // 銘柄
ENUM_TIMEFRAMES timeframe, // 期間
ENUM_SERIESMODE type, // 時系列識別子
int count=WHOLE_ARRAY, // 要素数
int start=0 // インデックス
);
戻り値は第4引数-第5引数で指定した期間内における最高値のインデックス
(最高値を戻しているわけではない点に注意)
第1引数には銘柄を指定する
第1引数には銘柄を指定します。定義済み変数「_Symbol」あるいはSymbol関数を記述すると、プログラムを挿入したチャートの銘柄を指定したことになります。
第2引数には時間軸を指定する
第2引数には時間軸を指定します。定数値ENUM_TIMEFRAMESで定められた値を設定します。0、もしくはPERIOD_CURRENTと記述すると現在のチャートの時間軸が適用されます。
第3引数には取得したい情報を指定する
ENUM_SERIESMODE列挙体で定められている定数値から取得したい情報の定数値を記述します。
※ENUM_SERIESMODE列挙体は以下のような定数リストになっています。
識別子 | 説明 |
---|---|
MODE_OPEN | 始値 |
MODE_LOW | 安値 |
MODE_HIGH | 高値 |
MODE_CLOSE | 終値 |
MODE_VOLUME | ティックボリューム |
MODE_REAL_VOLUME | 実のボリューム |
MODE_SPREAD | スプレッド |
iHighest関数はこの第3引数で指定した情報の最大値を検索し、最大値だったインデックスを戻り値として返します。例えばMODE_HIGHに指定すると、指定期間内の高値情報を検索し、最高値だったインデックスを返します。
※最高値そのものを返すわけではないことに注意が必要です。
第4引数には 情報を取得する期間 を指定する
第4引数では、第3引数で指定した「取得したい情報」を、どこまでの期間検索・取得したいかを指定します。例えばここに「20」と記述すると、20期間分の情報を検索・取得する事を明示したことになります。
第5引数には 検索開始インデックス を指定する
第5引数には 検索開始インデックス を指定します。例えばここに0と記述した場合は、現在足から第4引数で指定した期間分情報を検索・取得する事を明示したことになります。
iLowest関数について
iLowest関数の引数構成と戻り値は以下のようになっています。
int iLowest(
const string symbol, // 銘柄
ENUM_TIMEFRAMES timeframe, // 期間
ENUM_SERIESMODE type, // 時系列識別子
int count=WHOLE_ARRAY, // 要素数
int start=0 // インデックス
);
戻り値は戻り値は第4引数-第5引数で指定した期間内における最安値のインデックス
(最安値を戻しているわけではない点に注意)
第1引数には銘柄を指定する
第1引数には銘柄を指定します。定義済み変数「_Symbol」あるいはSymbol関数を記述すると、プログラムを挿入したチャートの銘柄を指定したことになります。
第2引数には時間軸を指定する
第2引数には時間軸を指定します。定数値ENUM_TIMEFRAMESで定められた値を設定します。0、もしくはPERIOD_CURRENTと記述すると現在のチャートの時間軸が適用されます。
第3引数には取得したい情報を指定する
ENUM_SERIESMODE列挙体で定められている定数値から取得したい情報の定数値を記述します。iLowest関数はこの第3引数で指定した情報の最小値を検索し、最小値だったインデックスを戻り値として返します。例えばMODE_LOWに指定すると、指定期間内の安値情報を検索し、最安値だったインデックスを返します。
※最安値そのものを返すわけではないことに注意です。
第4引数には 情報を取得する期間 を指定する
第3引数で指定した、「取得したい情報」を、どこまでの期間検索・取得したいかを指定します。例えばここに「20」と記述すると、20期間分の情報を検索・取得する事を明示したことになります。
第5引数には 検索開始インデックス を指定する
第5引数には 検索開始インデックス を指定します。例えばここに0と記述した場合は、現在足から第4引数で指定した期間分情報を検索・取得する事を明示したことになります。
iHighest関数とiLowest関数を使い、指定期間内の直近高安値が、いつの時点(直近高安値のインデックス)か取得出来たら今度はiHigh関数とiLow関数を使って、直近高値や直近安値が具体的にいくらなのか、という情報を取得しに行きます。
iHigh関数について
double iHigh(
const string symbol, // 銘柄
ENUM_TIMEFRAMES timeframe, // 期間
int shift // シフト
);
戻り値は、第3引数で指定した位置での高値
第1引数には銘柄を指定する
第1引数には銘柄を指定します。定義済み変数「_Symbol」あるいはSymbol関数を記述すると、プログラムを挿入したチャートの銘柄を指定したことになります。
第2引数には時間軸を指定する
第2引数には時間軸を指定します。定数値ENUM_TIMEFRAMESで定められた値を設定します。0、もしくはPERIOD_CURRENTと記述すると現在のチャートの時間軸が適用されます。
第3引数には 高値を取得する位置 を指定する
第3引数には 高値を取得する位置 を指定します。例えば「0」を指定すると現在足の高値情報を取得できます。ここに、iHighest関数で取得したインデックスを記述すれば、特定期間内の直近高値を取得することができます。
iLow関数について
double iLow(
const string symbol, // 銘柄
ENUM_TIMEFRAMES timeframe, // 期間
int shift // シフト
);
戻り値は、第3引数で指定した位置での安値
第1引数には銘柄を指定する
第1引数には銘柄を指定します。定義済み変数「_Symbol」あるいはSymbol関数を記述すると、プログラムを挿入したチャートの銘柄を指定したことになります。
第2引数には時間軸を指定する
第2引数には時間軸を指定します。定数値ENUM_TIMEFRAMESで定められた値を設定します。0、もしくはPERIOD_CURRENTと記述すると現在のチャートの時間軸が適用されます。
第3引数には 安値を取得する位置 を指定する
第3引数には 安値を取得する位置 を指定します。例えば「0」を指定すると、現在足の安値情報を取得できます。ここに、iLowest関数で取得したインデックスを記述すれば、特定期間内の直近高値を取得することができます。
実際に直近高安値を取得するサンプルコードを見てみる
iHighest関数、iLowest関数、iHigh関数、iLow関数についての説明が終わったところで、一度どうやって指定期間の最高値最安値を取得するのかサンプルコードを見てみましょう。
例えば、直近15期間の最高値を取得したい場合、↓
//直近15期間の最高値インデックスを取得
int highestIndex=iHighest(_Symbol,_Period,MODE_HIGH,15,0);
//直近15期間の最高値を取得
double highestPrice= iHigh(_Symbol,_Period,highestIndex);
変数「highestIndex」に、iHighest関数の戻り値を格納させます。第3引数で「MODE_HIGH」、第4引数で「15」、第5引数で「0」を指定しているので「highestIndex」には、「直近15期間での最高値インデックス(最高値を記録した場所)が格納されています
直近安値の場合も、iLowest関数とiLow関数を使って、これと同じことを逆にやるだけです↓
//直近15期間の最安値インデックスを取得
int lowestIndex=iLowest(_Symbol,_Period,MODE_LOW,15,0);
//直近15期間の最安値を取得
double lowestPrice= iLow(_Symbol,_Period,lowestIndex);
直近最高値・最安値の取得方法が分かったところで、動的ストップロスに向けた次のステップに移ります。
※なお、iHighest関数とiLowest関数を使った最高値最安値の取得方法については↓の記事でも解説しています。
ArrayMaximum関数やArrayMinimum関数を使った最高値最安値の取得方法についても↓の記事でも解説しています。
input変数にて、ModifyUpperStopLevel関数やModifyLowerStopLevel関数の第3引数に設定するストップレベルの上振れ幅・下振れ幅の値を設定する。
指定期間の最高値・最安値が取得出来たら、その値をストップロス(SL)にするべく、さっそく前回作ったModifyUpperStopLevel関数(ストップレベルの最小値を満たすよう修正する独立関数)とModifyLowerStopLevel関数(ストップレベルの最大値を満たすよう修正する独立関数)を使っていきます。
上記2つの関数の処理内容詳細については、前回の記事を見て頂きたいのですが、大まかに言って
①現在値を取得する→②現在値からストップレベルを取得する→③第2引数で指定した価格と第3引数で指定した値の合算がストップレベルに違反していないかを切り分け、違反しているようなら注文価格を修正する。
という働きを担っています。
従って、ここでは第3引数に指定するストップレベルにプラスアルファする値をグローバル領域(関数の外の領域)にinput変数にしておきます。↓
//ストップレベルにプラスアルファする上振れ・下振れ分の値を設定する
input int MinSL = 50;
//-------------------------------------------------------------
OnTick()
{
//直近15期間の最安値インデックスを取得
int lowestIndex=iLowest(_Symbol,_Period,MODE_LOW,15,0);
//直近15期間の最安値を取得
double lowestPrice= iLow(_Symbol,_Period,lowestIndex);
}
input変数名は「MinSL」としました。初期値を仮に「50」としています。この変数「MinSL」が
ModifyUpperStopLevel関数やModifyLowerStopLevel関数の第3引数の記述されます。ModifyUpperStopLevel関数やModifyLowerStopLevel関数の中で、変数「MinSL」と定義済み変数「_Point」が乗算され、その値がストップレベルにプラスアルファされます。
※input変数については↓の記事をご覧ください。
取得した直近高値・直近安値情報をModifyUpperStopLevel関数やModifyLowerStopLevel関数の第2引数に記述して、最終的なSL値を算出する。
「直近高値・直近安値情報を取得する」セクションで、指定する直近高安値を取得し、
「input変数にて、ModifyUpperStopLevel関数やModifyLowerStopLevel関数の第3引数に記述するストップレベルの上振れ幅・下振れ幅の値を設定する」セクションでストップレベル修正関数の第3引数に記述input変数「MinSL」を設定しました。
あとはModifyUpperStopLevel関数/ModifyLowerStopLevel関数の第2引数に直近高安値、第3引数に変数「MinSL」を記述し、その戻り値をMqlTradeRequest構造体のメンバ変数であるrequest.slに格納させれば、直近高安値を動的ストップロスにした設定記述は完了です。
仮に、買いポジションの動的ストップロスを設定する場合であれば、ModifyLowerStopLevel関数を使うことになります。↓
//直近15期間の最安値をSLに設定する
request.sl =ModifyLowerStopLevel(_Symbol, lowestPrice, MinSL);
MqlTradeRequest構造体については→コチラをご覧ください。
今回の記事のまとめ
今回は、全体をコピペして試せるような類のサンプルコードにはなっていませんが、以下のよう流れでコードを記述していく感じです。↓(買いポジションのSLを設定する前提です)
※第55回「MQL5プログラムの全体構造について」 なども参考にしながら確認していただければと思います。
//グローバル領域
//ストップレベルにプラスアルファする上振れ下振れ分の値を設定する
input int MinSL = 50;
//イベントハンドラー内記述
void OnTick()
{
//直近15期間の最安値インデックスを取得
int lowestIndex=iLowest(_Symbol,_Period,MODE_LOW,15,0);
//直近15期間の最安値を取得
double lowestPrice= iLow(_Symbol,_Period,lowestIndex);
//直近15期間の最安値をSLに設定する
request.sl =ModifyLowerStopLevel(_Symbol, lowestPrice, MinSL);
}
本日はここまでとさせていただきます。
最後までお読みいただきありがとうございました<m(__)m>