FX自動売買基礎と応用

MQLプログラミング言語で3本表示のRCIを作成する方法


3本表示に書き換え


この記事ではMT4には初期搭載されていないものの、多くのトレーダーに利用されているRCIを取り上げます。そのひな形として私が無料で公開している「HT_RCI」というインジケーターを用い、改修のポイントを解説していきます。

ブログ:HT FX (MT4・MT5で快適トレード)

そのままのファイルでは、1本のRCIのみ表示されます。これを3本のRCIが表示される仕様に改修してみましょう。まず、バッファーの数が指定できるようになっていないので、追加して「3」にします。また、それぞれの書式、色、太さ、線種を指定できるように増やします。太さと線種はそのままで、色を白と黄色、赤に設定します。


#property indicator_buffers 3
#property indicator_plots   3
#property indicator_color1 clrWhite
#property indicator_color2 clrYellow
#property indicator_color3 clrRed
#property indicator_width1 1
#property indicator_width2 1
#property indicator_width3 1
#property indicator_style1 STYLE_SOLID
#property indicator_style2 STYLE_SOLID
#property indicator_style3 STYLE_SOLID

RCIの期間を短期「10」、中期「20」、長期「50」としておきます。


input int PERIOD_S = 10; // 短期
input int PERIOD_M = 20; // 中期
input int PERIOD_L = 50; // 長期

バッファーもそれぞれ使えるように増やし、「0」「1」「2」とします。


double RCI0[], RCI1[], RCI2[];

それぞれのバッファーに対して指定できるように増やします。「Label」は、それぞれの期間が反映されるように書き換えます。「string name」は、それぞれの期間をカンマでつなげます。


SetIndexBuffer(0, RCI0, INDICATOR_DATA);
SetIndexBuffer(1, RCI1, INDICATOR_DATA);
SetIndexBuffer(2, RCI2, INDICATOR_DATA);
SetIndexLabel(0, "RCI(" + (string)PERIOD_S + ")");
SetIndexLabel(1, "RCI(" + (string)PERIOD_M + ")");
SetIndexLabel(2, "RCI(" + (string)PERIOD_L + ")");
string name = "RCI(" + (string)PERIOD_S + "," + (string)PERIOD_M + "," + (string)PERIOD_L  + ")";

計算内容も、それぞれ3種類を指定していきます。


for(int i = limit; i >= 0; i--) {
   RCI0[i] = iRCI(NULL, 0, PERIOD_S, i);
   RCI1[i] = iRCI(NULL, 0, PERIOD_M, i);
   RCI2[i] = iRCI(NULL, 0, PERIOD_L, i);

計算するBARSについては、重くなってしまわないように数を制限します。


input int BARS = 500;    // 計算バー本数

計算「BARS」の本数を仮に500本として、最大でも500本までしか計算しないように制限しておきます。


int limit = MathMin(Bars  - 1, BARS);

これで指定したパラメータ、または全体の「BARS」の本数のどちらか小さい方の分だけ計算するようにしました。以上の改修で、RCIが3本が表示されるようになりました。

RCIが3本


矢印表示の条件設定


次は、3本のRCIが短期、中期、長期と順に並んだときに、サイン表示する条件式を作ります。

まず、上から順に短期>中期>長期と並んだ状態を「up」とします。「短期が中期より大きい」、かつ「中期が長期より大きい」という条件を作ります。「bool」というのは条件が成立か不成立かを定義するための型です。これを1本前の足(i+1)でも判定させます。また、「up」とは正反対の並びの「dn」についても、符号を逆にして同様の手順で作ります。


bool upNow = RCI0[i] > RCI1[i] && RCI1[i] > RCI2[i];
bool upPre = RCI0[i + 1] > RCI1[i + 1] && RCI1[i + 1] > RCI2[i + 1];
bool dnNow = RCI0[i] < RCI1[i] && RCI1[i] < RCI2[i];
bool dnPre = RCI0[i + 1] < RCI1[i + 1] && RCI1[i + 1] < RCI2[i + 1];

これを利用してif文を作っていきます。「現在は並びが成立していて、その1本前が不成立」という条件です。「!」記号を付けると条件が反転し、ここでは条件不成立を意味します。これにより、並びが成立したときに矢印サインが表示されます。なお、表示する矢印としては、メニューバーの「挿入」→「矢印類」にある矢印オブジェクト(Arrowオブジェクト)を利用します。


if (upNow && !upPre)


矢印を表示する


名前を仮に「3RCI_Sign」と定義して、「i」番目の足という情報を入れておきます。ObjectCreate関数で0番目(現在表示しているチャート)を指定し、オブジェクトの種類は「OBJ_ARROW」とします。表示するウィンドウはメインウィンドウなので「0」です。これを「1」とすると一つ目のサブウィンドウ、「2」とすると二つ目のサブウィンドウを意味します。時間や価格も設定できますが、今回は「0」「0」としておきます。


string name = "3RCI_Sign_" + (string)i; 
ObjectCreate(0, name, OBJ_ARROW, 0, 0, 0);

次にObjectSetInteger関数を使って時間を指定していきます。

先ほどと同じ手順で進めて「OBJPROP_TIME」を選び、時間情報を「i」とします。


ObjectSetInteger(0, name, OBJPROP_TIME, 0, Time[i]);

同様にObjectSetDouble関数で、買いサインを安値側に表示します。また「ANCHOR」といって、オブジェクトの基準点をどこにするかという指定もします。Arrowオブジェクトの場合は「TOP」か「BOTTOM」を選択することになります。今回は下側に表示するのでTOPを選びます。そして大きさを「2」、色を赤、アローコードを「233」とします。


ObjectSetDouble(0, name, OBJPROP_PRICE, 0, Low[i]);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_TOP);
ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);
ObjectSetInteger(0, name, OBJPROP_COLOR, clrRed);
ObjectSetInteger(0, name, OBJPROP_ARROWCODE, 233);

これと同じように売りサインの設定も行います。売りの場合は「BOTTOM」を選んで高値側に表示し、色は青、アローコードは「234」とします。これでRCIが短期>中期>長期の順に並んだら赤い矢印(買いサイン)、短期<中期<長期の順に並んだら青い矢印(売りサイン)が表示されるようになります。

赤い矢印(買いサイン)と青い矢印(売りサイン)が表示


矢印表示のリセット


サイン表示の見た目はできました。しかし、矢印が表示され続けることになっているので、時間足を切り替えたりすることでどんどん増えていってしまいます。

その表示をリセットするために、ObjectsDeleteAllという関数を使います。これは現在のチャートで、指定した文字列を含むオブジェクトを全て消すという関数です。これを入れることでチャート切り替えるたびに、古い矢印が消え、新しい矢印が表示されるようになります。


ObjectsDeleteAll(0, "3RCI_Sign_");

最後にこのインジケーターを削除した時にオブジェクトが残らないようにします。OnDeinit関数は、時間足が切り替わったり、パラメータを変えたり、インジケーターが終了する時に、一度だけ実行される関数です。


void OnDeinit(const int reason)
  {
   ObjectsDeleteAll(0, "3RCI_Sign_");
  }

これでインジケーターをチャートから削除した時に、矢印も消えてくれるようになります。


ソースコード


今回、作成したソースコードは下記の通りです。


//+------------------------------------------------------------------+
//|                                                        3RCI_Sign |
//|                                                            HT FX |
//|                                        http://htfx.blog.fc2.com/ |
//+------------------------------------------------------------------+
#property copyright "HT FX"
#property link      "http://htfx.blog.fc2.com/"
#property description "Copyright (C) 2020  HT FX  All Rights Reserved.¥n"
#property description "http://htfx.blog.fc2.com/¥n"
#property description "htfxjp@gmail.com"
#property version "1.00"
#property strict
#property indicator_separate_window
#property indicator_maximum  1
#property indicator_minimum -1
#property indicator_buffers 3
#property indicator_plots   3
#property indicator_color1 clrWhite
#property indicator_color2 clrYellow
#property indicator_color3 clrRed
#property indicator_width1 1
#property indicator_width2 1
#property indicator_width3 1
#property indicator_style1 STYLE_SOLID
#property indicator_style2 STYLE_SOLID
#property indicator_style3 STYLE_SOLID

//+------------------------------------------------------------------+
//| Input parameters                                                 |
//+------------------------------------------------------------------+
input int BARS = 500;    // 計算バー本数
input int PERIOD_S = 10; // 短期
input int PERIOD_M = 20; // 中期
input int PERIOD_L = 50; // 長期

//--- indicator buff
double RCI0[], RCI1[], RCI2[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   IndicatorSetInteger(INDICATOR_DIGITS, 6);
   SetIndexStyle(0, DRAW_LINE);
   SetIndexStyle(1, DRAW_LINE);
   SetIndexStyle(2, DRAW_LINE);
   SetIndexBuffer(0, RCI0, INDICATOR_DATA);
   SetIndexBuffer(1, RCI1, INDICATOR_DATA);
   SetIndexBuffer(2, RCI2, INDICATOR_DATA);
   SetIndexLabel(0, "RCI(" + (string)PERIOD_S + ")");
   SetIndexLabel(1, "RCI(" + (string)PERIOD_M + ")");
   SetIndexLabel(2, "RCI(" + (string)PERIOD_L + ")");
   string name = "RCI(" + (string)PERIOD_S + "," + (string)PERIOD_M + "," + (string)PERIOD_L  + ")";
   IndicatorSetString(INDICATOR_SHORTNAME, name);
   
   return 0;
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ObjectsDeleteAll(0, "3RCI_Sign_");
  }
  
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   int counted_bars = IndicatorCounted();
//---- check for possible errors
   if(counted_bars < 0) return -1;
//---- last counted bar will be recounted
   if(counted_bars > 0) counted_bars--;

   int limit = MathMin(Bars  - 1, BARS);
//   if (limit < 1) limit = 1;

   ObjectsDeleteAll(0, "3RCI_Sign_");

   for(int i = limit; i >= 0; i--) {
      RCI0[i] = iRCI(NULL, 0, PERIOD_S, i);
      RCI1[i] = iRCI(NULL, 0, PERIOD_M, i);
      RCI2[i] = iRCI(NULL, 0, PERIOD_L, i);
      
      bool upNow = RCI0[i] > RCI1[i] && RCI1[i] > RCI2[i];
      bool upPre = RCI0[i + 1] > RCI1[i + 1] && RCI1[i + 1] > RCI2[i + 1];
      bool dnNow = RCI0[i] < RCI1[i] && RCI1[i] < RCI2[i];
      bool dnPre = RCI0[i + 1] < RCI1[i + 1] && RCI1[i + 1] < RCI2[i + 1];
      
      if (upNow && !upPre) {
         string name = "3RCI_Sign_" + (string)i;       
         ObjectCreate(0, name, OBJ_ARROW, 0, 0, 0);
         ObjectSetInteger(0, name, OBJPROP_TIME, 0, Time[i]);
         ObjectSetDouble(0, name, OBJPROP_PRICE, 0, Low[i]);
         ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_TOP);
         ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);
         ObjectSetInteger(0, name, OBJPROP_COLOR, clrRed);
         ObjectSetInteger(0, name, OBJPROP_ARROWCODE, 233);
      }
      if (dnNow && !dnPre) {
         string name = "3RCI_Sign_" + (string)i;       
         ObjectCreate(0, name, OBJ_ARROW, 0, 0, 0);
         ObjectSetInteger(0, name, OBJPROP_TIME, 0, Time[i]);
         ObjectSetDouble(0, name, OBJPROP_PRICE, 0, High[i]);
         ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_BOTTOM);
         ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);
         ObjectSetInteger(0, name, OBJPROP_COLOR, clrDodgerBlue);
         ObjectSetInteger(0, name, OBJPROP_ARROWCODE, 234);
      }
   }

   return 0;
}
//+------------------------------------------------------------------+


本記事の監修者・HT FX


2013年にFXを開始し、その後専業トレーダーへ。2014年からMT4/MT5のカスタムインジケーターの開発に取り組む。ブログでは100本を超えるインジケーターを無料公開。投資スタイルは自作の秒足インジケーターを利用したスキャルピング。


本ホームページに掲載されている事項は、投資判断の参考となる情報の提供を目的としたものであり、投資の勧誘を目的としたものではありません。投資方針、投資タイミング等は、ご自身の責任において判断してください。本サービスの情報に基づいて行った取引のいかなる損失についても、当社は一切の責を負いかねますのでご了承ください。また、当社は、当該情報の正確性および完全性を保証または約束するものでなく、今後、予告なしに内容を変更または廃止する場合があります。なお、当該情報の欠落・誤謬等につきましてもその責を負いかねますのでご了承ください。

この記事をシェアする

ホーム » FX自動売買基礎と応用 » MQLプログラミング言語で3本表示のRCIを作成する方法