ブログタイトルを「FX自動売買システム開発部」から「autoFX」に変更しました!

1分足(M1)から全ての時間足を生成する

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 りゅーき |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#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です。プログラムで躓いた時は標準で付属されているものを参考にするのもアリだと思います。学ぶは真似るから。

MQL4プログラミングの最新記事8件

>完全放ったらかしEA 「AutoEndlessCatchRange」

完全放ったらかしEA 「AutoEndlessCatchRange」

「本業が忙しい!」「でも資産運用したい!」そんなあなたに最適なEAです。兼業トレーダーの方はチャートを毎日みて分析してトレードする時間はなかなか確保できないものです。トレードは本EAに任せて、本業やプライベートの時間をもっと増やしませんか?元々は自分自身のために開発したEAですので、手抜き無しのガチものです。

CTR IMG