period_converter_ALL.mq4で正常動作するなら不要
FxProで作成中のインジケーターをテスト中に処理が進まなくなる現象が発生しました。原因を調べると、1時間足(H1)のチャートデータがおかしなことになっていました。これが直接の原因のようです。
テストにはいつもFXDDのから取得した1分足(M1)のヒストリカルデータを用いています。
ここに置いてあるのは1分足だけなので、他の時間足も必要になります。そこで、使うのがperiod_converter_ALL.mq4という便利なスクリプトです。
これを使えば、M1から全ての足(M5, M15, M30, H1, H4, D1, W1, MN1)を作ってくれます。使い方はGoogle等で検索すれば沢山ヒットすると思いますので、割愛します。
今まで私もこのスクリプトを使ってきたのですが、どうもFxProのMT4とは相性が悪いらしく、H1のチャートデータが生成されません。
まぁ、随分昔に作られたスクリプトですし、現在のMT4(Build 600で大きな仕様変更がありました)とかみ合わないことがあってもおかしくはありません。
じゃあ、現在のMT4に合ったperiod_converter_ALL.mq4にリニューアルすればいいやということで作ったのが以下のスクリプトです。その名も「PeriodConverterALL.mq4」。そのまんまです(笑)。
中身は以下の通りです。
//+------------------------------------------------------------------+
//| PeriodConverterALL.mq4 |
//| Copyright 2006-2014, MetaQuotes Software Corp. |
//| Modified by りゅーき |
//+------------------------------------------------------------------+
#property copyright "2006-2014, MetaQuotes Software Corp."
#property link "http://www.mql4.com"
#property description "Period Converter to updated format of history base"
#property strict
//#property show_inputs
#include <WinUser32.mqh>
int ExtHandle = -1;
static int ArrayPeriod[];
//+------------------------------------------------------------------+
//| script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
if(Period() != PERIOD_M1){
Comment("Start Period Must be M1.");
return;
}
datetime time0;
ulong last_fpos = 0;
long last_volume = 0;
int i;
int start_pos;
int periodseconds;
int hwnd = 0;
int cnt = 0;
string cmnt;
ArrayResize(ArrayPeriod, 8);
ArrayPeriod[0] = PERIOD_M5;
ArrayPeriod[1] = PERIOD_M15;
ArrayPeriod[2] = PERIOD_M30;
ArrayPeriod[3] = PERIOD_H1;
ArrayPeriod[4] = PERIOD_H4;
ArrayPeriod[5] = PERIOD_D1;
ArrayPeriod[6] = PERIOD_W1;
ArrayPeriod[7] = PERIOD_MN1;
//---- History header
int file_version = 401;
string c_copyright = "(C)opyright 2003, MetaQuotes Software Corp.";
string c_symbol = Symbol();
int i_period;
int i_digits = Digits;
int i_unused[13];
MqlRates rate;
for(int idx = 0; idx < ArraySize(ArrayPeriod); idx++){
i_period = ArrayPeriod[idx];
cmnt = "Converting to Period (" + (string)i_period + "), bars to end: ";
ExtHandle = FileOpenHistory(c_symbol + (string)i_period + ".hst", FILE_BIN|FILE_WRITE|FILE_SHARE_WRITE|FILE_SHARE_READ|FILE_ANSI);
if(ExtHandle < 0){
return;
}
ArrayInitialize(i_unused, 0);
//--- write history file header
FileWriteInteger(ExtHandle, file_version, LONG_VALUE);
FileWriteString(ExtHandle, c_copyright, 64);
FileWriteString(ExtHandle, c_symbol, 12);
FileWriteInteger(ExtHandle, i_period, LONG_VALUE);
FileWriteInteger(ExtHandle, i_digits, LONG_VALUE);
FileWriteInteger(ExtHandle, 0, LONG_VALUE);
FileWriteInteger(ExtHandle, 0, LONG_VALUE);
FileWriteArray(ExtHandle, i_unused, 0, 13);
//--- write history file
periodseconds = i_period * 60;
start_pos = Bars - 1;
rate.open = Open[start_pos];
rate.low = Low[start_pos];
rate.high = High[start_pos];
rate.tick_volume = (long)Volume[start_pos];
rate.spread = 0;
rate.real_volume = 0;
//--- normalize open time
rate.time = Time[start_pos] / periodseconds;
rate.time *= periodseconds;
for(i = start_pos - 1; i >= 0; i--){
if(IsStopped()){
break;
}
if(MathMod(i, 1000) == 0){
Comment(cmnt + " " + (string)i);
}
time0 = Time[i];
//--- history may be updated
if(i == 0){
//--- modify index if history was updated
if(RefreshRates()){
i = iBarShift(NULL, 0, time0);
}
}
if(time0 >= rate.time + periodseconds || i == 0){
if(i == 0 && time0 < rate.time + periodseconds){
rate.tick_volume += (long)Volume[0];
if(rate.low > Low[0]){
rate.low = Low[0];
}
if(rate.high < High[0]){
rate.high = High[0];
}
rate.close = Close[0];
}
last_fpos = FileTell(ExtHandle);
last_volume = (long)Volume[i];
FileWriteStruct(ExtHandle, rate);
cnt++;
if(time0 >= rate.time + periodseconds){
rate.time = time0 / periodseconds;
rate.time *= periodseconds;
rate.open = Open[i];
rate.low = Low[i];
rate.high = High[i];
rate.close = Close[i];
rate.tick_volume = last_volume;
}
}else{
rate.tick_volume += (long)Volume[i];
if(rate.low > Low[i]){
rate.low = Low[i];
}
if(rate.high < High[i]){
rate.high = High[i];
}
rate.close = Close[i];
}
}
FileFlush(ExtHandle);
Print(cnt, " record(s) written");
if(ExtHandle >= 0){
FileClose(ExtHandle);
ExtHandle = -1;
}
Comment("");
}
}
使い方はperiod_converter_ALL.mq4と一緒です。ちなみに、ベースとなっているのはMT4をインストールすると標準で付属されているPeriodConverter.mq4です。プログラムで躓いた時は標準で付属されているものを参考にするのもアリだと思います。学ぶは真似るから。
