2015年4月24日金曜日

レンジ・エクスパンション・インデックス(REI)を作ってみた。

レンジ・エクスパンション・インデックスが見当たらなかったため、作成してみました。
海外サイトには古いMT4向けのコードはあったのですが、新MT4向けではなかったため1から作成しました。

英語版Wikiに説明が乗っていまして、こちらの方が正確そうなため、英語版Wikiをベースに作成しています。
http://en.wikipedia.org/wiki/Range_expansion_index

すごくざっくり説明すると、改良版モメンタムです。
モメンタムを計算する際、5本~8本前の足の高値低値を比較することで波形の類似性を確認して、類似している場合は同じトレンドに乗っていると判断してだましシグナルを回避する思想のようです。

REI1.PNG
チャート画像にて上がREI、下がモメンタムです。上昇トレンドにおいて、REIでは0を割っていないのに対して、モメンタムでは途中一度100を割って、だましのシグナルが発生していることが見て取れます。

REIでは、レンジが+-60付近を超えている場合の反対方向への動きはだましの可能性が高いと判断するようです。
2015.4.27 修正
私が読み間違えていたみたいです。+-60超えは買われすぎ・売られすぎです。
モメンタム(相場の推進力の強弱を表す)系のオシレータです。0のラインを下回っていたら弱気、上回っていたら強気と読み取るようです。そのため0のラインを超えた方向に売買。買われすぎの場合は反転を狙うというのが基本です。チャートと見比べると、確かに相場が行き過ぎている事はつかみやすいのですが、波形が崩れるとすぐ0のラインを超えてしまいます。
波形が崩れるという事は相場反転の合図ではあるのですが、シグナルが早めに出る傾向になり一時的な損を抱えることも多そうです。そのため、高値つかみ安値つかみを避ける指標として使用するのがよさそうと感じました。

//------------------------------------------------------------------
// レンジ・エクスパンション・インデックス
// http://en.wikipedia.org/wiki/Range_expansion_index より
#property copyright "Copyright 2015,  Daisuke"
#property link      "http://mt4program.blogspot.jp/"
#property version   "1.00"
#property strict


#property indicator_separate_window
#property indicator_minimum   -100
#property indicator_maximum   100
#property indicator_level1    60
#property indicator_level2    -60
#property indicator_levelcolor clrSilver
#property indicator_levelstyle STYLE_DOT

#property indicator_buffers 1

#property indicator_label1  "REI"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrYellow
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

// 入力パラメータ REI期間
extern int ReiPeriod = 8;

// バッファー
double reiBuffer[];

//------------------------------------------------------------------
//初期化
int OnInit()
{
SetIndexBuffer(0, reiBuffer);
IndicatorShortName("REI (" + IntegerToString(ReiPeriod) + ")");
SetIndexDrawBegin(0, ReiPeriod + 8);

return(INIT_SUCCEEDED);
}

//------------------------------------------------------------------
//計算イベント
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[])            //スプレット
{

//元となる値を計算する。
for( int i = (rates_total - prev_calculated - 1); i >= 0 ; i-- )
{
if( i >=  rates_total - ReiPeriod - 8 - 1 )
{
reiBuffer[i] = 0 ;
continue;
}

double sigmaS1 = 0 ;
double sigmaS2 = 0 ;

// s1 = sigma(j=1 to k) nj*mj*sj
// s2 = sigma(j=1 to k) |High[j] - High[j - 2]| + |Low[j] - Low[j - 2]|

for( int j = i; j < i + ReiPeriod; j++ )
{
// nj = if ((High[j – 2] < Close[j - 7]) && (High[j - 2] < Close[j - 8]) && (High[j] < High[j - 5])
// && (High[j] < High[j - 6])) n_j = 0  else n_j = 1

// 2本前の高値が、7本or8本前の終値未満かつ、現在の高値が5本or6本前の高値未満の場合 値を採用しない。
int nj = high[j + 2] < close[j + 7] && high[j + 2] < close[j + 8] && high[j] < high[j + 5] && high[j] < high[j + 6] ? 0 : 1;

// mj = if ((Low[j – 2] > Close[j – 7]) && (Low[j – 2] > Close[j – 8]) && (Low[j] > Low[j – 5])
// && (Low[j] > Low[j – 6])) m_j = 0 else m_j = 1
// 2本前の安値が、7本or8本前の終値より大きいかつ、現在の安値が5本or6本前の安値より大きい場合 値を採用しない。
int mj = low[j + 2] > close[j + 7] && low[j + 2] > close[j + 8] && low[j] > low[j + 5] && low[j] > low[j + 6] ? 0 : 1;

//上記で波形の近似性を見ている。

// 高値安値のモメンタムの合計
// s_j = High[j] - High[j - 2] + Low[j] - Low[j - 2]
double sj = high[j] - high[j + 2] + low[j] - low[j + 2];

// 高値安値のモメンタムの絶対値合計
sigmaS1 += nj * mj * sj;
sigmaS2 += MathAbs(high[j] - high[j + 2]) + MathAbs(low[j] - low[j + 2]);
}

// モメンタム合計/絶対値合計*100にて%化している。
reiBuffer[i] = sigmaS2 != 0 ? sigmaS1 * 100 / sigmaS2 : 0;
}

return (rates_total - 1);
}


※利益の増加や損失の減少を保証するものではありません。ご自身の判断にてお取引いただきますようお願いいたします。