FX自動売買基礎と応用

MT5版のRCIを作成する【MQLプログラミングの基礎】

1.ファイルの新規作成

この記事では、サブウィンドウに表示するオシレーター系のインジケーターRCI(順位相関係数)のMT5版を作成します。
RCIの詳細を確認したい場合は、下記の記事等を参照してください。
「RCIの基本的な見方、使い方、トレーディングアイデアを紹介」

まずは、メタエディター(MetaEditor)の「新規作成」アイコンをクリックしてMQLウィザードを開きます。

新規作成

「カスタムインディケータ」を選択して「次へ」をクリックします。

ファイル名

ファイル名を「RCI.mq5」とし、パラメータとして「PERIOD」を追加して、初期値を「14」とし、「次へ」をクリック。

イベントハンドラ

イベントハンドラは一番上の「OnCalculate」のみを選択して「次へ」をクリックします。

描画プロパティ

描画プロパティでは、「サブウインドウに表示」「最小値」「最大値」を選択し、最小値は「-100」、最大値は「100」とします。
また、プロットするバッファを追加し、ラベルを「RCI」、タイプを「Line」、カラーを「White」として、「完了」をクリックすると、ファイルのベースが作成されます。

2. 名称等の修正

サブウインドウでのインジケーター名表示に期間(PERIOD)の値を表示したいので、ラベル名を設定し直します。


#property indicator_label1  "RCI"

の行を削除します。

OnInit()関数内に、下記を追記します。


string name = "RCI(" + (string)PERIOD + ")";
   PlotIndexSetString(0, PLOT_LABEL, name);
   IndicatorSetString(INDICATOR_SHORTNAME, name);

3.バッファ配列方向の設定

OnInit()関数内に、下記を追記します。


   ArraySetAsSeries(RCIBuffer, true);

上記を指定することで、バッファ配列の0番が最新の足の値として扱われます(指定しないと0番が最も古い値になり、配列の並び順が逆になります)。

4.RCI関数の流用

RCIの計算式として、いくつか先人が開発したものがありますが、ここでは軽量版として出回っているものをアレンジした下記の関数をコピペして利用します。
プログラムの最下部に貼り付けてください。


//+------------------------------------------------------------------+
//| RCI function                                                     |
//+------------------------------------------------------------------+
void iRCI(double &close[], double &rci[], int period, int limit)
{
   int D[];
   ArrayResize(D, period);
   for(int i = 0; i < period; i++) D[i] = -i * 2;
   int N = period * (period * period - 1) * 2 / 3;
   int max = ArraySize(rci) - 1;
   
   int n = limit;
   double d = 0;
   for (int i = 0; i < period; i++) {
      for (int j = i + 1; j < period; j++) {
         if (n + j > max) continue;
         if (close[n + i] < close[n + j]) {
            D[i] += 2;
         } else if(close[n + i] == close[n + j]) {
            D[i]++;
            D[j]++;
         } else {
            D[j] += 2;
         }
      }
      d += D[i] * D[i];
   }
   rci[n] = (1 - (d / N)) * 100;

   for(n = limit - 1; n >= 0; n--) {
      d = 0;
      for(int i = period - 1; i >= 1; i--) {
         D[i] = D[i - 1] - 2;
         if (n + i > max || n + period > max) continue;
         if(close[n + i] < close[n]) D[i] += 2;
         else if(close[n + i] == close[n]) D[i]++;
         if(close[n + i] < close[n + period]) D[i] -= 2;
         else if(close[n + i] == close[n + period]) D[i]--;
         d += D[i] * D[i];
      }
      D[0] = 0;
      for(int j = 1; j < period; j++) {
         if (n + j > max) continue;
         if(close[n] < close[n + j]) D[0] += 2;
         else if(close[n] == close[n + j]) D[0]++;
      }
      d += D[0] * D[0];
      rci[n] = (1 - (d / N)) * 100;
   }
}
//+------------------------------------------------------------------+

5.iRCI()関数で利用する終値の配列を用意

OnCalculate()関数で定義されている終値の配列close[]は、MQL5のルール的にiRCI()関数へそのまま渡すことができないので、渡す用の配列array[]を用意します。
OnCalculate()関数内に、下記を追記してください。


   double array[];
   ArraySetAsSeries(array, true);
   ArraySetAsSeries(close, true);
   ArrayCopy(array, close);

6.計算範囲を設定しiRCI()関数で計算

初期時のみチャート全体を計算し、次からは最小限の範囲のみ計算するよう、変数limitを下記の通り定義します。


   int limit = rates_total - prev_calculated - 1;
   if (limit < 1) limit = 1;

iRCI()関数に終値の配列array[]、RCIのバッファRCIBuffer[]、期間PERIOD、計算範囲limitを指定して、RCIを計算させます。


   iRCI(array, RCIBuffer, PERIOD, limit);

上記をOnCalculate()関数内に追記してコンパイルすると、RCIの完成です。

チャートRCI

7.ソースコード

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


//+------------------------------------------------------------------+
//|                                                          RCI.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_minimum -100
#property indicator_maximum 100
#property indicator_buffers 1
#property indicator_plots   1
//--- plot RCI
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrWhite
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- input parameters
input int      PERIOD=14;
//--- indicator buffers
double         RCIBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,RCIBuffer,INDICATOR_DATA);
   ArraySetAsSeries(RCIBuffer, true);
   string name = "RCI(" + (string)PERIOD + ")";
   PlotIndexSetString(0, PLOT_LABEL, name);
   IndicatorSetString(INDICATOR_SHORTNAME, name);
   
//---
   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[])
  {
//---
   double array[];
   ArraySetAsSeries(array, true);
   ArraySetAsSeries(close, true);
   ArrayCopy(array, close);

   int limit = rates_total - prev_calculated - 1;
   if (limit < 1) limit = 1;
   iRCI(array, RCIBuffer, PERIOD, limit);
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| RCI function                                                     |
//+------------------------------------------------------------------+
void iRCI(double &close[], double &rci[], int period, int limit)
{
   int D[];
   ArrayResize(D, period);
   for(int i = 0; i < period; i++) D[i] = -i * 2;
   int N = period * (period * period - 1) * 2 / 3;
   int max = ArraySize(rci) - 1;
   
   int n = limit;
   double d = 0;
   for (int i = 0; i < period; i++) {
      for (int j = i + 1; j < period; j++) {
         if (n + j > max) continue;
         if (close[n + i] < close[n + j]) {
            D[i] += 2;
         } else if(close[n + i] == close[n + j]) {
            D[i]++;
            D[j]++;
         } else {
            D[j] += 2;
         }
      }
      d += D[i] * D[i];
   }
   rci[n] = (1 - (d / N)) * 100;

   for(n = limit - 1; n >= 0; n--) {
      d = 0;
      for(int i = period - 1; i >= 1; i--) {
         D[i] = D[i - 1] - 2;
         if (n + i > max || n + period > max) continue;
         if(close[n + i] < close[n]) D[i] += 2;
         else if(close[n + i] == close[n]) D[i]++;
         if(close[n + i] < close[n + period]) D[i] -= 2;
         else if(close[n + i] == close[n + period]) D[i]--;
         d += D[i] * D[i];
      }
      D[0] = 0;
      for(int j = 1; j < period; j++) {
         if (n + j > max) continue;
         if(close[n] < close[n + j]) D[0] += 2;
         else if(close[n] == close[n + j]) D[0]++;
      }
      d += D[0] * D[0];
      rci[n] = (1 - (d / N)) * 100;
   }
}
//+------------------------------------------------------------------+

EA(自動売買)を学びたい方へオススメコンテンツ

EA運用の注意点

OANDAではEA(自動売買)を稼働するプラットフォームMT4/MT5の基本的な使い方について、画像や動画付きで詳しく解説しています。MT4/MT5のインストールからEAの設定方法までを詳しく解説しているので、初心者の方でもスムーズにEA運用を始めることが可能です。またOANDAの口座をお持ちであれば、独自開発したオリジナルインジケーターを無料で利用することもできます。EA運用をお考えであれば、ぜひ口座開設をご検討ください。


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

この記事をシェアする

ホーム » FX自動売買基礎と応用 » MT5版のRCIを作成する【MQLプログラミングの基礎】