昔の記事のインジケータをちょっと改造してみました。
http://mt4program.blogspot.jp/2015/10/mt4_65.html
staplaさんから動かない環境があるというコメントをいただき、あの時よりもMQLに対する知識が深まっているためもう少しシンプルに書けないかな?ということで書いてみました。
機能は大して変わっていませんが、パラメータの指定が開始時間と長さという形に変わっている事と、30分単位で値が指定できるように修正しています。まぁ開始時間が9:30とかになっている取引所もあるかなと思いまして。
基本的には1日のある区間のレンジに対するブレイクをわかりやすく見るためのものです。
よく言われるのは東京時間のレンジをブレイクした方向に順張りとか、最近の日経平均だと午前中の値動きを午後ブレイクするかどうか?といった感じでしょうか?
MT4開発日記で公開している無料インジケータは、こちらの一覧から。
インジケータ一覧
Twitterもよろしくお願いします。
https://twitter.com/mt4program
ブログランキングにご協力よろしくお願いします。m(._.)m
お約束ですが、本ブログは、投資に対する利益を約束する物ではありません。最終的には自己責任によるご判断よろしくお願いいたします。
追記、後 記事一覧のページに記事が表示されない不具合を修正しました。ご迷惑おかけいたしました。
ソースコードはこちらから
//------------------------------------------------------------------
// 一定区間のレンジを表示する
#property copyright "Copyright 2016, Daisuke"
#property link "http://mt4program.blogspot.jp/"
#property version "1.10"
#property strict
#property indicator_chart_window
#define RangeRectangleName "RANGERECT"
#define SEC_OF_HOUR 60 * 60
#define SEC_OF_DAY SEC_OF_HOUR * 24
//バッファーを指定する。
#property indicator_buffers 2
//プロット数を指定する。
#property indicator_plots 2
#property indicator_label1 "HIGH"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrRed
#property indicator_style1 STYLE_DOT
#property indicator_width1 1
#property indicator_label2 "LOW"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrAqua
#property indicator_style2 STYLE_DOT
#property indicator_width2 1
input double StartHour = 2;// 開始サーバー時間(0 < value < 23 30分単位 例 1.5)
input double HourL = 6; // 測定時間(0 < value < 23 30分単位 例 1.5)
input color RectBackColor = clrSlateGray;//矩形背景色
input ENUM_TIMEFRAMES CalculateTimeframe = PERIOD_M30;//計算時間 StartHour、HourLの分解能
// バッファー
double highBuffer[];
double lowBuffer[];
//------------------------------------------------------------------
//初期化
int OnInit()
{
// 時間足以下のみ有効
if ( StartHour < 0 || StartHour > 23 )
{
return INIT_PARAMETERS_INCORRECT;
}
if ( HourL < 0 || HourL > 23 )
{
return INIT_PARAMETERS_INCORRECT;
}
int count = 0 ;
SetIndexBuffer( count++, highBuffer );
SetIndexBuffer( count++, lowBuffer );
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 );
// 先頭文字列がRangeRectangleNameと一致する場合、削除する。
if ( StringFind( name, RangeRectangleName ) == 0 )
{
ObjectDelete( chartId, name );
}
}
}
//------------------------------------------------------------------
//計算イベント
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[] // スプレット
)
{
// 1時間足まで
if ( Period() >= PERIOD_D1 )
{
return rates_total;
}
// 開始時間から終了時間までの高値安値を更新する。
double highValue = 0;
double lowValue = 100000;
long chartID = ChartID();
for ( int i = 0 ; i < rates_total - prev_calculated; i++ )
{
MqlDateTime tm;
TimeToStruct( time[ i ], tm );
tm.hour = 0;
tm.min = 0;
tm.sec = 0;
// 開始日時を算出する。 算出したいバーより開始日時は必ず前になるように計算する。
datetime startTime = StructToTime( tm ) + (int)(StartHour * SEC_OF_HOUR);
while( startTime > time[i] ) startTime -= SEC_OF_DAY;
// 開始日時がが見つかる前さかのぼる
int startShift = -1;
while( !IsStopped() )
{
startShift = iBarShift(Symbol(), CalculateTimeframe, startTime, true);
if( startShift >= 0 || startTime <= time[rates_total - 1] ) break ;
startTime -= SEC_OF_DAY;
}
if( startShift < 0 ) return rates_total - 1;
datetime endTime = startTime + (int)(HourL * SEC_OF_HOUR);
int endShift = iBarShift(Symbol(), CalculateTimeframe, endTime - CalculateTimeframe);
int count = startShift - endShift + 1;
int highnest = iHighest(Symbol(), CalculateTimeframe, MODE_HIGH, count, endShift);
int lowest = iLowest(Symbol(), CalculateTimeframe, MODE_LOW, count, endShift);
double rangeHigh = iHigh(Symbol(), CalculateTimeframe, highnest);
double rangeLow = iLow(Symbol(), CalculateTimeframe, lowest);
CreateOrReplaceObject(GetRectangleName(startTime), startTime, endTime, rangeHigh, rangeLow, RectBackColor);
while( i < rates_total - 1)
{
highBuffer[i] = rangeHigh;
lowBuffer[i] = rangeLow;
if( time[i + 1] < startTime ) break ;
i++;
}
}
return rates_total - 1;
}
//------------------------------------------------------------------
//矩形名を取得する。
string GetRectangleName
(
datetime time //現在時刻
)
{
return RangeRectangleName + TimeToString( time );
}
//------------------------------------------------------------------
//矩形を生成する。
bool CreateOrReplaceObject
( string name
, datetime startTime // 開始時間
, datetime endTime // 終了時間
, double top // 上限値
, double bottom // 下限値
, color backColor // 背景色
)
{
//オブジェクトを作成する。
long chartId = ChartID();
if( ObjectFind(chartId, name) >= 0)
{
ObjectSetInteger(chartId, name, OBJPROP_TIME1, startTime);
ObjectSetInteger(chartId, name, OBJPROP_TIME2, endTime);
ObjectSetDouble(chartId, name, OBJPROP_PRICE1, top);
ObjectSetDouble(chartId, name, OBJPROP_PRICE2, bottom);
ObjectSetInteger( chartId, name, OBJPROP_COLOR, backColor );
}
else
{
if ( ObjectCreate( chartId, name, OBJ_RECTANGLE, 0, startTime, top, endTime, bottom ) == false )
{
return false;
}
ObjectSetInteger( chartId, name, OBJPROP_COLOR, backColor );
ObjectSetInteger(chartId, name, OBJPROP_READONLY, true);
ObjectSetInteger(chartId, name, OBJPROP_SELECTABLE, false);
}
return true;
}
i