【MQL5で最高値最安値を取得する方法その1】

EA制作お役立ち記事

スポンサーリンク
スポンサーリンク

最高値最安値について

MT5EAを開発するにあたり、

特定期間の最高値・最安値をトレード戦略の肝に据えることは多いのではないでしょうか?

ブレイクアウト狙いのトレンドフォローエントリーや、ストップロスエントリーの目安にする

などの戦略は割と一般的かと思います。(個人的にも有用な戦略であると考えています)

トレンドフォローについては以下の記事も参考になるかと思います。↓

最高値・最安値の取得方法については、いろいろな記述の仕方があるかとは思いますが、

今回は

ArrayMaximum関数、ArrayMinimum関数を使ったやり方

を紹介します。

後日、iHighest関数,iLowest関数を使ったやり方を紹介する予定ですが、この記述は簡易でMQL4利用者にもなじみ深い一方で、

MQL5で頻出する、

インジケータハンドルを取得→配列の時系列セット→コピー関数による情報の配列コピー

という工程に親和性が高いのは、ArrayMaximum関数ArrayMinimum関数を使った記述法のような気がするからです。

そんなわけで、今回は

  • 直近100本の最高値、最安値の値を取得し、
  • ↑を水平線にて描画し、
  • 最高値と最安値の差分レンジをコメントに表示

以上の回路を作っていきたいと思います。

最高値と最安値の取得におけるロードマップ

以下の手順でコードを記述していきます

  • 高値と安値の差を格納する変数を宣言
  • 直近高値、直近安値の取得に必要な変数配列の宣言
  • 配列を時系列にセット
  • 高値と安値の情報を配列にコピー
  • 最高値・最安値インデックスを取得し、変数に格納
  • MqlRates構造体を利用して、最高値・最安値を取得する
  • 取得した最高値・最安値を水平線で描画する

高値と安値の差を格納する変数を宣言

これは最高値、最安値を取得するのは無関係なのですが、

チャート上に、最高値と最安値のレンジ幅がどのくらいか、というのをチャート上にコメント表示するために使います。

 //高値と安値の差を格納する変数を宣言
      double tradingRange=0;

直近高値、直近安値の取得に必要な変数・配列の宣言

HighestCandle,LowestCandleは直近から100本の時系列範囲で、どの時点での足が最高値、最安値だったかを格納するint型変数です。

例えば、3本前の足が最高値だったら、HighestCandleに「3」が格納される・・・そんな感じです。

※実際の最高値最安値データが格納されるわけではないので注意してください。

High[],Low[]配列は、後述するCopyHigh関数CopyLow関数を使って、各足ごとの高値、安値情報を格納する配列です。

※あくまで時間足ごとの高値、安値であり最高値・最安値を格納している配列ではない点に注意してください。

//直近高値、直近安値の場所を格納する変数を宣言
      int HighestCandle,LowestCandle;
      
      //高値と安値の情報を格納する変数配列を宣言
      double High[],Low[];

配列を時系列にセット

最新足から古い時間足に向かってデータが格納されるように配列をセットします。

配列の時系列セットにはArraySetAsSeries関数を用います。

インデックス[0]が一番直近の時間足のデータになります。

//配列を時系列にセット
      ArraySetAsSeries(High,true);
      ArraySetAsSeries(Low,true);

ArraySetAsSeries関数については↓をご覧ください。

高値と安値の情報を配列にコピー

高値データはCopyHigh関数、安値データはCopyLow関数を使って、配列にデータをコピーしていきます。

※Copy~関数は、上記以外にも多数種類があります。

詳しくは↓の講座記事で解説しておりますので、ご参照ください。

MQL5 EA講座 第105回「CopyRates関数以外のCopy関数」

 //高値と安値の情報を配列にコピー
      CopyHigh(_Symbol,_Period,0,100,High);
      CopyLow(_Symbol,_Period,0,100,Low);

最高値・最安値インデックスを取得し、変数に格納

時系列ごとの高値・安値を格納している配列High[]、Low[]のなかから最高値・最安値のインデックスを見つけ出し、変数に格納します。

インデックスの取得にはArrayMaximum関数ArrayMinimum関数を利用します。

iHighest関数iLowest関数はチャートの中から、指定期間高安値インデックスを取得しますが、ArrayMaximum関数ArrayMinimum関数配列の中から指定期間高安値インデックスを取得する、

という違いがあります。

//高値格納配列の最高値インデックスを格納
      HighestCandle=ArrayMaximum(High,0,100);
      //安値格納配列の最安値インデックスを格納 
      LowestCandle=ArrayMinimum(Low,0,100);

MqlRates構造体を利用して、最高値・最安値を取得する

構造体というのは、

複数の変数をセットで持てるデータ型のことで、

MqlRates構造体MQL5側で事前に定義済みの構造体です。

定義は↓のようになっています。

struct MqlRates
 {
  datetime time;         // 期間開始時間
  double   open;         // 始値
  double   high;         // 期間中の最高値
  double   low;         // 期間中の最安値
  double   close;       // 終値
  long     tick_volume; // ティックボリューム
  int     spread;       // スプレッド
  long     real_volume; // 取引高
 };

お弁当パックのように、チャート上の様々な情報をいろいろ詰め込めるようになっています。

今回は

PriceInfo[]

という配列で宣言しているので、↓のようなロッカー上に情報を格納できるようになっています。

[0][1][2][3]
期間開始時間
始値
期間中の最高値
終値
ティックボリューム
スプレッド
取引高

配列を時系列にセットするのは、高値・安値配列のときと同じですね。

MqlRates構造体インスタンスに情報を格納するには、CopyRates関数を使います。

これで、MqlRates構造体が定義している情報を使えるようになります。

//MqlRates構造体のインスタンス配列を宣言
      MqlRates PriceInfo[];
      
      //配列を時系列にセット
      ArraySetAsSeries(PriceInfo,true);
      
      //価格情報をMqlRates構造体インスタンス配列に格納
      int Data=CopyRates(_Symbol,_Period,0,Bars(_Symbol,_Period),PriceInfo);

※最後の行、「int Data」でCopyRates関数がコピーした要素数を格納していますが、特にこの後何かに利用したりはしていません。

MqlRates構造体の使い方についてはコチラの記事も参考になるかと思います。↓

取得した最高値・最安値を水平線で描画する

下のソースコードを見ても、ぱっと見ではどれが取得した最高値・最安値かはわからないかもしれません。

最高値=PriceInfo[HighestCandle].high

最安値=PriceInfo[LowestCandle].low

となっています。

↑そんな仕組みになっています。

取得した最高値・最安値をもとに各種Object~関数を用いて、水平ラインを描画する記述を書きます。

//オブジェクト生成シークエンス(高値)
      ObjectCreate(0,"Line1",OBJ_HLINE,0,0,PriceInfo[HighestCandle].high);
      ObjectSetInteger(0,"Line1",OBJPROP_COLOR,clrOrange);
      ObjectSetInteger(0,"Line1",OBJPROP_WIDTH,3);
      ObjectMove(0,"Line1",0,0,PriceInfo[HighestCandle].high);
    
      //オブジェクト生成シークエンス(安値)
      ObjectCreate(0,"Line2",OBJ_HLINE,0,0,PriceInfo[LowestCandle].low);
      ObjectSetInteger(0,"Line2",OBJPROP_COLOR,clrOrange);
      ObjectSetInteger(0,"Line2",OBJPROP_WIDTH,3);
      ObjectMove(0,"Line2",0,0,PriceInfo[LowestCandle].low);

高値と安値の差分を算出し、コメント出力

見やすくするために、改行をしてはいますが、

やっていることは単純に最高値から最安値を引いているだけです。

  //高値と安値の差分を算出し、格納
      tradingRange=NormalizeDouble(
                                       (PriceInfo[HighestCandle].high 
                                       -
                                       PriceInfo[LowestCandle].low
                                       ),
                                  _Digits);
      
      
      Comment("最高値~最安値のレンジ: ",tradingRange);
  }

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

全体のプログラムコード

全体のサンプルコードは以下のようになります。



void OnTick()
  {
      //高値と安値の差を格納する変数を宣言
      double tradingRange=0;
      
      //直近高値、直近安値の場所を格納する変数を宣言
      int HighestCandle,LowestCandle;
      
      //高値と安値の情報を格納する変数配列を宣言
      double High[],Low[];
      
      //配列を時系列にセット
      ArraySetAsSeries(High,true);
      ArraySetAsSeries(Low,true);
      
      //高値と安値の情報を配列にコピー
      CopyHigh(_Symbol,_Period,0,100,High);
      CopyLow(_Symbol,_Period,0,100,Low);
      
     
     //高値格納配列の最高値インデックスを格納
      HighestCandle=ArrayMaximum(High,0,100);
      //安値格納配列の最安値インデックスを格納 
      LowestCandle=ArrayMinimum(Low,0,100);
      
      //MqlRates構造体のインスタンス配列を宣言
      MqlRates PriceInfo[];
      
      //配列を時系列にセット
      ArraySetAsSeries(PriceInfo,true);
      
      //価格情報をMqlRates構造体インスタンス配列に格納
      int Data=CopyRates(_Symbol,_Period,0,Bars(_Symbol,_Period),PriceInfo);
      
      //オブジェクト生成シークエンス(高値)
      ObjectCreate(0,"Line1",OBJ_HLINE,0,0,PriceInfo[HighestCandle].high);
      ObjectSetInteger(0,"Line1",OBJPROP_COLOR,clrOrange);
      ObjectSetInteger(0,"Line1",OBJPROP_WIDTH,3);
      ObjectMove(0,"Line1",0,0,PriceInfo[HighestCandle].high);
    
      //オブジェクト生成シークエンス(安値)
      ObjectCreate(0,"Line2",OBJ_HLINE,0,0,PriceInfo[LowestCandle].low);
      ObjectSetInteger(0,"Line2",OBJPROP_COLOR,clrOrange);
      ObjectSetInteger(0,"Line2",OBJPROP_WIDTH,3);
      ObjectMove(0,"Line2",0,0,PriceInfo[LowestCandle].low);
    
      //高値と安値の差分を算出し、格納
      tradingRange=NormalizeDouble(
                                       (PriceInfo[HighestCandle].high 
                                       -
                                       PriceInfo[LowestCandle].low
                                       ),
                                  _Digits);
      
      
      Comment("最高値~最安値のレンジ: ",tradingRange);
  }
//+------------------------------------------------------------------+

サンプルコードの挙動は以下のようになります↓

最後までお読みいただきありがとうございました<(_ _)>

※最高値・最安値の取得方法については<MQL5でEAを作ろう講座>でも↓の記事で解説しておりますので、よろしければ参考にしていただければと思います。

MQL5 EA講座 第106回「最高値と最安値の取得について」

また、最高値・最安値の値を取得する別の方法に興味があれば↓の記事もご覧ください。

※当サイトでは、プログラミング経験ゼロの方でも、プログラミングの基礎から学べる

<MQL5でEAを作ろう講座>

をメインコンテンツとして展開しています。

【言語基礎編】

【中級実際にEAを作ろう編】

【発展編・MT5用EAを作る工程をカスタマイズしていく】

第0回から、順を追って勉強していけばプログラミングの経験がなくてもMQL5を使って、MT5用のEAが作れるように書いています。最初は難しいと感じるかもしれませんが、繰り返し勉強していく事で自然とスキルが身についていくはずです。興味ある方は是非ご覧ください。

コメント

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