MQLを勉強していても、アローの出し方が分からないと困っている人も多いかもしれません。
実は、アローを表示させること自体はとてもシンプルで、そこまで難しいものではありません。
一度作ってしまえば、使いまわしが出来るので、マスターしてしまいましょう。
完成コード
早速ですが、コード全体をはじめにお教えします。
#property copyright "Copyright 2020, eits" #property link "https://trade-engineer.com/" #property version "1.00" #property strict #property indicator_chart_window #property indicator_buffers 2 double HighSignal[]; double LowSignal[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexStyle(0, DRAW_ARROW,0,2,clrRed); SetIndexArrow(0, 233); SetIndexBuffer(0, HighSignal); SetIndexStyle(1, DRAW_ARROW,0,2,clrGreen); SetIndexArrow(1, 234); SetIndexBuffer(1, LowSignal); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { //--- int limit; //limit値計算 if(prev_calculated == 0) { int ExcludePeriod = 100; limit = rates_total - ExcludePeriod - 1; } else limit = rates_total - prev_calculated; //売買シグナルの作成 for(int i = limit; i >= 0; i--) { // 買いシグナルのバッファ HighSignal[i] = EMPTY_VALUE; // 売りシグナルのバッファ LowSignal[i] = EMPTY_VALUE; //M1_終値取得 double M1_Close = iClose(NULL,PERIOD_M1,i); double M1_Open = iOpen(NULL,PERIOD_M1,i); //+------------------------------------------------------------------+ //| Low条件 | //+------------------------------------------------------------------+ if( //エントリー条件 M1_Close - M1_Open > 0 ) { //インジケータバッファ LowSignal[i] = High[i] + 10 * Point; } //+------------------------------------------------------------------+ //| High条件 | //+------------------------------------------------------------------+ else if( //エントリー条件 M1_Close - M1_Open < 0 ) { //インジケータバッファ HighSignal[i] = Low[i] - 10 * Point; } } //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+
プロパティの設定
重要な部分だけ説明すると、インジケーターバッファを2つ用意する必要があるので、以下の宣言が必要になります。
#property indicator_buffers 2
上向きのアロー用のバッファと下向きのアロー用のバッファです。
この宣言がないと後々エラーが発生したりするので、忘れずに宣言しなければなりません。
アロー用の配列を用意
以下の部分です。
double HighSignal[]; double LowSignal[];
ここはあまり説明することがありません。。。
配列をインジケーターバッファに割り当てる
この表現が適切がどうかは別として、用意した配列をインジケーターバッファに割り当てます。
SetIndexStyle(0, DRAW_ARROW,0,2,clrRed); SetIndexArrow(0, 233); SetIndexBuffer(0, HighSignal); SetIndexStyle(1, DRAW_ARROW,0,2,clrGreen); SetIndexArrow(1, 234); SetIndexBuffer(1, LowSignal);
上の3つが配列「HighSignal」のための設定となり、
- SetIndexStyleで、スタイルをアロー(矢印)に指定
- SetIndexArrowで、アローの種類をコードで指定
- SetIndexBufferで、どの配列を割り当てるのかを指定
という感じです。
アローの種類はこちらのサイトで確認出来ます。
OnCalculate関数
この関数内に条件を書いていくことになります。
int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[])
色々気になる部分はあるかもしれませんが、初めはあまり気にしなくても良いですが、2つだけ解説します。
rates_total | ロウソク足の総数が格納された変数です。例えば、ロウソク足が1,000本初めからあるのであれば、1,000 |
prev_calculated | 以前の呼び出しで処理されたロウソク足の数初回は0、処理されたら1,000というように変化します。 |
ロウソク足の本数を確認
初めにチャート上にロウソク足が何本あるのかを確認し、計算に利用するロウソク足の本数を定義しているのが以下のコードです。
計算に利用するロウソク足の本数をlimit という変数に格納するようにしています。
int limit; //limit値計算 if(prev_calculated == 0) { int ExcludePeriod = 100; limit = rates_total - ExcludePeriod - 1; } else limit = rates_total - prev_calculated;
if文を使用して、初回時と2回目以降でlimit 格納するロウソク足の本数を変えています。
初回は、全体のロウソク足を計算する必要があるので、基本全部のロウソク足をlimit 値に格納していますが、2回目以降は初回で計算したロウソク足を再度計算する必要はないので、新しく出来たロウソク足だけ計算するようにしています。
ここでは、「ExcludePeriod 」という変数で、計算に利用するロウソク足を除外するための本数を指定しています。
この点は最初は難しく感じるかもしれませんが、やっているうちにわかってくると思います。
for文を使用して、各ロウソク足の処理をループ
以下の部分です。
//売買シグナルの作成 for(int i = limit; i >= 0; i--) { // 省略 }
for文はプログラミングには欠かせないものですので、しっかり理解しておきましょう。
配列内の値を初期化
正直この部分は、無くても構いませんが、一応記載しました。
// 買いシグナルのバッファ HighSignal[i] = EMPTY_VALUE; // 売りシグナルのバッファ LowSignal[i] = EMPTY_VALUE;
難しく感じるようであれば、あまり気にせず進めても大丈夫です。
条件式を作るための各値の取得
こちらの部分です。
ココでは終値と始値を求めて、変数に格納しています。
double M1_Close = iClose(NULL,PERIOD_M1,i); double M1_Open = iOpen(NULL,PERIOD_M1,i);
主にここで、様々な条件式を通る際の必要な値を取得するところでもあります。
RSI値を求めるならiRSI、ストキャスティクス値を求めるならiStochastic、ボリンジャーバンド値を求めるならiBandsを使うという感じです。
アローを出すLow条件
アローを出すための条件式をif文の中に記述します。
//+------------------------------------------------------------------+ //| Low条件 | //+------------------------------------------------------------------+ if( //エントリー条件 M1_Close - M1_Open > 0 )
今回はシンプルに、終値 – 始値が 0以上である時という条件です。
始値より終値の値が大きいということは、ロウソク足が陽線であるということになるので、ここでは「陽線の時」というif文が表現できます。
この条件に当てはまる時、アローを出すようにするコードが以下の通りです。
//インジケータバッファ LowSignal[i] = High[i] + 10 * Point;
高値 + 10ポイントを指定してます。
高値だけにしてしまうと、アローがロウソク足に被ってしまって見にくくなってしまうので、位置をずらすための処理です。
アローを出すHigh条件
Low条件に当てはまらない場合、High条件を確認することになります。
Low条件の反対で、終値 – 始値が 0未満の時という条件です。
始値より終値が低いということは、ロウソク足が陰線であるということになるので、ここでは「陰線の時」というif文が表現できます。
else if( //エントリー条件 M1_Close - M1_Open < 0 )
この条件に当てはまる時、アローを出すようにするコードが以下の通りです。
//インジケータバッファ HighSignal[i] = Low[i] - 10 * Point;
安値 – 10ポイントを指定しています。
こちらはプラスではなくマイナスの点に注意です。
安値の位置より10ポイント下げることで、ロウソク足に被らないように調整しています。
何ポイントが良いかはお好みなので、値を変えて色々と変えてみると良いです。
チャートに表示
実際に完成したものをチャートに表示してみましょう。
正しく表示されてるけど、これはひどい!笑
ここから改良してみよう
今回は陽線なら、陰線ならというシンプルな条件でアローを出しているのでこんな状態ですが、RSIやストキャス、ボリンジャーバンドを組み合わせてみるとか、色々試してみると良いですね。
一度作成してしまえば、値の取得と条件式を書き換えるだけでアローが出せるので簡単にできますね。
コメント