2016年6月1日水曜日

[MT4インジケータ]RSIに矢印を出して見てる。標準インジケータを修正して遊ぼう。

■標準インジケータを修正した矢印付きRSI


MT4には各種インジケータのコードが添付されています。これらは修正が可能です。
定番インジケータだけど、あんな機能ほしいなーとおもったら、ちょこっと触ってみるのもありかもしれません。

ということで、RSIを修正して、指定のレベルをまたいで来たら矢印を出すインジケータを作ってみました。

MT4のIndicatorsフォルダ直下にあるRSI.mq4を修正して矢印を出してみます。

プログラム的な注意点は、MT4についてきているインジケータは、計算の頭で配列の順序を通常と逆転させています。

   ArraySetAsSeries(close,false);

OnCalculate関数でわたってくる、closeなど配列は、0が一番新しいデータという仕様になっています。上記の関数をコールすると、0が一番古いデータとなります。チャート左端が0という配列順序になります。組む人が逆転させた方が便利だなーと思ったのかと・・・。

 ということで、修正してみました。RSIを使って逆張りを仕掛ける際の参考矢印として出してみることに。
 EURUSD1時間足で見ましたが、RSIだけで仕掛けると間違いなく死ぬことがわかります。よく言う大局面トレンドに対する逆張りという意味ではRSIありでしょうか?EURUSDで15分足も見てみます。

■EURUSD M15 RSI

現在時間足は下げトレンドですが、15分足では一時的な反発となりました。それに対しての売り位置はなかなか良い位置にシグナルが出ているように思われます。

ソースコードは記事の最後に記載しています。
RSI.mq4に対する修正箇所はコメントで区切っています。ご参考に。
//---------修正箇所
//---------修正箇所ここまで

また、コードの下記の部分を触ると矢印を表示するタイミングを変更可能です。

         if( ExtRSIBuffer[i - 1] >= UpperLevel && ExtRSIBuffer[i] < UpperLevel )
         {
            //上限レベルを下回って来たら売り矢印
            CreateArrawObject(SellObjectType, time[i], high[i], low[i]);
         }
         else if( ExtRSIBuffer[i - 1] <= LowerLevel && ExtRSIBuffer[i] > LowerLevel )
         {
            //下限レベルを上回ったら買い矢印
            CreateArrawObject(BuyObjectType, time[i], high[i], low[i]);
         }

例えば、50超えたら買い、下回ったら売りとかにする場合はこんな感じになります。RSIをトレンド判定に使う場合はこんな感じになります。
         if( ExtRSIBuffer[i - 1] >= 50 && ExtRSIBuffer[i] < 50 )
         {
            CreateArrawObject(SellObjectType, time[i], high[i], low[i]);
         }
         else if( ExtRSIBuffer[i - 1] <= 50 && ExtRSIBuffer[i] > 50 )
         {
            CreateArrawObject(BuyObjectType, time[i], high[i], low[i]);
         }

・・・・・ま、RSIを使って矢印をだすインジケータは世の中にたくさんありますが^^;;;自分で修正できると楽しいですよー。

「MT4でFXを勝ち抜く研究をするブログ」で公開している無料インジケータは、こちらの一覧から。
インジケータ一覧

Twitterもよろしくお願いします。
https://twitter.com/mt4program

ブログランキングにご協力よろしくお願いします。m(._.)m
にほんブログ村 為替ブログ MetaTraderへ
にほんブログ村

お約束ですが、本ブログは、投資に対する利益を約束する物ではありません。最終的には自己責任によるご判断よろしくお願いいたします。

プログラムはこちらから

//+------------------------------------------------------------------+
//|                                                          RSI.mq4 |
//|                   Copyright 2005-2014, MetaQuotes Software Corp. |
//|                                              http://www.mql4.com |
//+------------------------------------------------------------------+
#property copyright   "2005-2014, MetaQuotes Software Corp."
#property link        "http://www.mql4.com"
#property description "Relative Strength Index"
#property strict

#property indicator_separate_window
#property indicator_minimum    0
#property indicator_maximum    100
#property indicator_buffers    1
#property indicator_color1     DodgerBlue

//---------修正箇所
//レベルはパラメータから設定する。
//#property indicator_level1     30.0
//#property indicator_level2     70.0
//---------修正箇所 ここまで

#property indicator_levelcolor clrSilver
#property indicator_levelstyle STYLE_DOT
//--- input parameters
input int InpRSIPeriod=14; // RSI Period
//--- buffers
double ExtRSIBuffer[];
double ExtPosBuffer[];
double ExtNegBuffer[];

//---------修正箇所
input double UpperLevel = 70;    // 上限レベル
input double LowerLevel = 30;    // 下限レベル

input ENUM_OBJECT BuyObjectType = OBJ_ARROW_BUY;   //買い時オブジェクトタイプ
input ENUM_OBJECT SellObjectType = OBJ_ARROW_SELL; //売り時オブジェクトタイプ

input int BuyArrowCode = 233; //買い時矢印形状 233上矢印、161丸、
input int SellArrowCode = 234; //売り時矢印形状 234下矢印、161丸
input color BuyColor = C'128,128,255';
input color SellColor = C'255,128,128';
#define OBJECT_NAME "RSIOBJ"
//---------修正箇所 ここまで

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit(void)
  {
   string short_name;
//--- 2 additional buffers are used for counting.
   IndicatorBuffers(3);
   SetIndexBuffer(0,ExtRSIBuffer);
   SetIndexBuffer(1,ExtPosBuffer);
   SetIndexBuffer(2,ExtNegBuffer);
//--- indicator line
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,ExtRSIBuffer);
//--- name for DataWindow and indicator subwindow label
   short_name="RSI("+string(InpRSIPeriod)+")";
   IndicatorShortName(short_name);
   SetIndexLabel(0,short_name);
//--- check for input
   if(InpRSIPeriod<2)
     {
      Print("Incorrect value for input variable InpRSIPeriod = ",InpRSIPeriod);
      return(INIT_FAILED);
     }
//---
   SetIndexDrawBegin(0,InpRSIPeriod);
//--- initialization done

//---------修正箇所
// レベルはパラメータから指定する。
   IndicatorSetDouble( INDICATOR_LEVELVALUE, 0, UpperLevel );
   IndicatorSetDouble( INDICATOR_LEVELVALUE, 1, LowerLevel );
//---------修正箇所 ここまで

   return(INIT_SUCCEEDED);
  }
  
//---------修正箇所
//------------------------------------------------------------------
//終了処理
void OnDeinit(const int reason)
{
   long chartId = ChartID();

   int total = ObjectsTotal(chartId);
   //生成したオブジェクトを削除する。
   //0から削除するとインデックス位置がずれて
   //正しく削除できないため、後ろから削除するようにする。
   for( int i = total - 1; i >= 0 ; i--)
   {
      string name = ObjectName(chartId, i);
      
      // 先頭文字列がOBJECT_NAMEと一致する場合、削除する。
      if( StringFind(name, OBJECT_NAME) == 0 )
      {
         ObjectDelete(chartId, name);
      }
   }
}
//---------修正箇所 ここまで
  
//+------------------------------------------------------------------+
//| Relative Strength Index                                          |
//+------------------------------------------------------------------+
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    i,pos;
   double diff;
//---
   if(Bars<=InpRSIPeriod || InpRSIPeriod<2)
      return(0);
//--- counting from 0 to rates_total
   ArraySetAsSeries(ExtRSIBuffer,false);
   ArraySetAsSeries(ExtPosBuffer,false);
   ArraySetAsSeries(ExtNegBuffer,false);
   ArraySetAsSeries(close,false);
   
//---------修正箇所
//矢印を描画するのに、時間と高値安値をみるため、こちらの配列も順序を変更する。
   ArraySetAsSeries(time,false);
   ArraySetAsSeries(high,false);
   ArraySetAsSeries(low,false);
//---------修正箇所 ここまで

//--- preliminary calculations
   pos=prev_calculated-1;
   if(pos<=InpRSIPeriod)
     {
      //--- first RSIPeriod values of the indicator are not calculated
      ExtRSIBuffer[0]=0.0;
      ExtPosBuffer[0]=0.0;
      ExtNegBuffer[0]=0.0;
      double sump=0.0;
      double sumn=0.0;
      for(i=1; i<=InpRSIPeriod; i++)
        {
         ExtRSIBuffer[i]=0.0;
         ExtPosBuffer[i]=0.0;
         ExtNegBuffer[i]=0.0;
         diff=close[i]-close[i-1];
         if(diff>0)
            sump+=diff;
         else
            sumn-=diff;
        }
      //--- calculate first visible value
      ExtPosBuffer[InpRSIPeriod]=sump/InpRSIPeriod;
      ExtNegBuffer[InpRSIPeriod]=sumn/InpRSIPeriod;
      if(ExtNegBuffer[InpRSIPeriod]!=0.0)
         ExtRSIBuffer[InpRSIPeriod]=100.0-(100.0/(1.0+ExtPosBuffer[InpRSIPeriod]/ExtNegBuffer[InpRSIPeriod]));
      else
        {
         if(ExtPosBuffer[InpRSIPeriod]!=0.0)
            ExtRSIBuffer[InpRSIPeriod]=100.0;
         else
            ExtRSIBuffer[InpRSIPeriod]=50.0;
        }
      //--- prepare the position value for main calculation
      pos=InpRSIPeriod+1;
     }
//--- the main loop of calculations
   for(i=pos; i<rates_total && !IsStopped(); i++)
     {
      diff=close[i]-close[i-1];
      ExtPosBuffer[i]=(ExtPosBuffer[i-1]*(InpRSIPeriod-1)+(diff>0.0?diff:0.0))/InpRSIPeriod;
      ExtNegBuffer[i]=(ExtNegBuffer[i-1]*(InpRSIPeriod-1)+(diff<0.0?-diff:0.0))/InpRSIPeriod;
      if(ExtNegBuffer[i]!=0.0)
         ExtRSIBuffer[i]=100.0-100.0/(1+ExtPosBuffer[i]/ExtNegBuffer[i]);
      else
        {
         if(ExtPosBuffer[i]!=0.0)
            ExtRSIBuffer[i]=100.0;
         else
            ExtRSIBuffer[i]=50.0;
        }

//---------修正箇所
      if( i > 0 )
      {
         // まずは矢印削除
         DeleteArrawObject(time[i]);
         //ArraySetAsSeriesで0が一番古いデータとなっているのに注意
         if( ExtRSIBuffer[i - 1] >= UpperLevel && ExtRSIBuffer[i] < UpperLevel )
         {
            //上限レベルを下回って来たら売り矢印
            CreateArrawObject(SellObjectType, time[i], high[i], low[i]);
         }
         else if( ExtRSIBuffer[i - 1] <= LowerLevel && ExtRSIBuffer[i] > LowerLevel ) 
         {
            //下限レベルを上回ったら買い矢印
            CreateArrawObject(BuyObjectType, time[i], high[i], low[i]);
         }
      }
//---------修正箇所 ここまで
        
     }
//---
   return(rates_total);
  }
//+------------------------------------------------------------------+

//---------修正箇所
//------------------------------------------------------------------
//売買矢印オブジェクトを生成する。
bool CreateArrawObject(
   ENUM_OBJECT objectType,  //オブジェクトの種類
   datetime time,           //表示時間(横軸)
   double high,            //高値
   double low              //安値
   )
{
   //オブジェクトを作成する。
   long chartId = ChartID();
   
   double price = objectType == BuyObjectType ? high : low;
    
   string name = OBJECT_NAME + TimeToStr(time);
   if( !ObjectCreate(chartId, name, objectType, 0, time, price) )
   {
      return false;
   }
   ObjectSetInteger(chartId, name, OBJPROP_READONLY, true);
   ObjectSetInteger(chartId, name, OBJPROP_SELECTABLE, false);
   ObjectSetInteger(chartId, name, OBJPROP_HIDDEN, true);
   ObjectSetInteger(chartId, name, OBJPROP_COLOR, objectType == BuyObjectType ? BuyColor : SellColor);
   ObjectSetInteger(chartId, name, OBJPROP_ARROWCODE, objectType == BuyObjectType ? BuyArrowCode : SellArrowCode);
   
   int anchor;
   
   anchor = objectType == BuyObjectType ? ANCHOR_BOTTOM : ANCHOR_TOP;
   
   ObjectSetInteger(chartId, name, OBJPROP_ANCHOR, anchor);
   return true;
}

//------------------------------------------------------------------
//売買矢印オブジェクトを削除する。
bool DeleteArrawObject(
   datetime time           //表示時間(横軸)
)
{
   //オブジェクトを作成する。
   long chartId = ChartID();
   string name = OBJECT_NAME + TimeToStr(time);
   return ObjectDelete(chartId, name);
}
//---------修正箇所ここまで