2010年5月6日木曜日

★タイムフレーム指定を簡単に
Specifying Timeframe Simply


メタトレーダー4(MT4)ではタイムフレームとして取りうる値は通常以下の10通りである。
MTF(Multi TimeFrame)インジケーターなど、パラメーターでタイムフレームを指定するものの場合、 5分や15分、せいぜい4時間までは数値での指定でも問題ないと思うが、日足や週足を指定したいとなると ちょっと大変である...
    コード上(定数) タイムフレーム 値(分)
    0 チャートと同じ 0
    PERIOD_M1 1分 1
    PERIOD_M5 5分 5
    PERIOD_M15 15分 15
    PERIOD_M30 30分 30
    PERIOD_H1 1時間 60
    PERIOD_H4 4時間 240
    PERIOD_D1 1日 1440
    PERIOD_W1 1週間 10080
    PERIOD_MN1 1ヵ月 43200

そこで、最近作っているインジケーター(例えば 00-Envelopeなど。 インジケーター作成リスト) ではタイムフレームを"D1"や"W1"のように文字列でも指定可能なようにしている。 (対応しているのはパラメーターが"sTimeFrame"となっているもの。's'はstrings)
sTimeFrameに指定可能な値は以下の通りで、"D1"や"W1"のほか、数値(分)指定も可能である。 (文字列で指定する場合、大文字/小文字は無視するようにしているので、"d1"や"w1"でもOK)
    コード上(定数) 時間 数値指定 文字列指定
    0 チャートと同じ 0 0
    PERIOD_M1 1分 1 M1
    PERIOD_M5 5分 5 M5
    PERIOD_M15 15分 15 M15
    PERIOD_M30 30分 30 M30
    PERIOD_H1 1時間 60 H1
    PERIOD_H4 4時間 240 H4
    PERIOD_D1 1日 1440 D1
    PERIOD_W1 1週間 10080 W1
    PERIOD_MN1 1ヵ月 43200 MN1

プログラム上では、まずsTimeFrameをすべて大文字に変換し、その中に"MN"/"W1"/"D1"/"H4"/"H1"/"M30"/"M15"/"M5"/"M1"が 含まれるかどうかをこの順番で調べ、含まれていれば対応するタイムフレームを採用する。 "MN"から調べているのは、"M15"を"M1"より先に調べるためで、逆だと"M15"に対して先に"M1"がマッチしてしまうため。 (完全一致でもよかったが、空白が入ってしまった場合やコメントを許すため。まぁコメントは使わないかもだがw)

参考までにコード上は以下の関数toUpper()で大文字変換を行い、関数convTF()で数値(分)に変換している。 (そういえば今回は日本語には対応していないので、全角で"D1"などはNG)

string toUpper(string s)
{
  int n = StringLen(s);
  for (int i = 0; i < n; i++) {
    int c = StringGetChar(s, i);
    if (c >= 'a' && c <= 'z') {
      c += 'A' - 'a';
      s = StringSetChar(s, i, c);
    }
  }
  
  return(s);
}
int convTF(string s)
{
  s = toUpper(s);
  
  if (StringFind(s, "MN") >= 0) {
    return(PERIOD_MN1);
  }
  if (StringFind(s, "W1") >= 0) {
    return(PERIOD_W1);
  }
  if (StringFind(s, "D1") >= 0) {
    return(PERIOD_D1);
  }
  if (StringFind(s, "H4") >= 0) {
    return(PERIOD_H4);
  }
  if (StringFind(s, "H1") >= 0) {
    return(PERIOD_H1);
  }
  if (StringFind(s, "M30") >= 0) {
    return(PERIOD_M30);
  }
  if (StringFind(s, "M15") >= 0) {
    return(PERIOD_M15);
  }
  if (StringFind(s, "M5") >= 0) {
    return(PERIOD_M5);
  }
  if (StringFind(s, "M1") >= 0) {
    return(PERIOD_M1);
  }
  
  int tf = StrToDouble(s);
  
  switch (tf) {
  case 0:
  case PERIOD_M1:
  case PERIOD_M5:
  case PERIOD_M15:
  case PERIOD_M30:
  case PERIOD_H1:
  case PERIOD_H4:
  case PERIOD_D1:
  case PERIOD_W1:
  case PERIOD_MN1:
    // ok
    break;
  
  default:
    tf = 0;
    break;
  }
  
  return(tf);
}
(convTF()switch 文の default:
tf = PERIOD_D1;
となっていたのを、認識できない文字列の場合にチャートと同じタイムフレームとして扱うように以下の ように修正した。
tf = 0;
この記事を書くのに 00-DayRange のコードを元にしたので PERIOD_D1 となってしまっていた。 00-Envelope_v102.mq4 にもそのコードが残ってしまっている。 2010/5/16 追記)

0 件のコメント:

コメントを投稿