MT4の`iFractals()`でフラクタルを取得しようとして、直近の足を指定しているのにいつも0が返ってくる、という経験をした人は多いはずです。

これはバグではなく、フラクタルという指標そのものの仕組みによる、正しい挙動です。

フラクタルは「ある足の高値(または安値)が、その前後2本ずつ、合計5本の中で一番高い(安い)」という条件で決まります。

つまり、直近の1〜2本は「まだ後ろに2本の確定足がない」状態のため、仕組み上どうやってもフラクタルにはなり得ません。

この記事では、`iFractals()`の書式と、この「直近2本は必ず0」という設計上の制約を理解したうえで、確定したフラクタルだけを矢印表示するインジケーターを、実際に動くコードとあわせて解説します。

iFractals関数の書式

double iFractals(
   string symbol,     //通貨ペア(NULLで現在のチャート)
   int    timeframe,  //時間足(0で現在のチャートの時間足)
   int    mode,       //MODE_UPPER(上のフラクタル)またはMODE_LOWER(下のフラクタル)
   int    shift        //何本前の足を見るか
   );

戻り値は、指定した`shift`の足がフラクタルであればその高値(または安値)、フラクタルでなければ`0.0`です。

`mode`には、上側のフラクタル(高値側)を見る`MODE_UPPER`と、下側のフラクタル(安値側)を見る`MODE_LOWER`の2種類があります。

なぜ直近2本は必ず0が返るのか

フラクタルの判定条件を、`shift`を基準にした前後関係で書き直すと、次のようになります。

//shift番目の足が「上のフラクタル」である条件(概念上のイメージ)
high[shift] は high[shift+2], high[shift+1], high[shift-1], high[shift-2] より高い

ここで`shift-1`・`shift-2`は「対象の足より新しい(未来側の)足」を指します。

`shift=0`(現在形成中の足)を指定した場合、`shift-1`・`shift-2`はまだ存在しない未来の足になってしまうため、判定自体が成立せず、必ず`0.0`が返ります。

`shift=1`を指定した場合も同様に、`shift-2`にあたる足がまだ確定していないため、同じ理由で`0.0`が返ります。

フラクタルとして値が返り始めるのは、最短でも`shift=2`以降です。

これはMT4標準のフラクタルインジケーター自体が持つ性質で、リペイントとは違う「後出しでしか確定できない」指標だという理解が、EAへ組み込む際の前提になります。

確定フラクタルだけを矢印表示するコード全体

`shift=2`以降だけをループして判定することで、まだ確定していないフラクタルを誤って矢印表示しない、実際にMetaEditorでコンパイルできるインジケーターです。

//+------------------------------------------------------------------+
//|                                 FractalsConfirmedArrow.mq4        |
//|                     Copyright 2026, FX-EA System Project Creator |
//|                        https://creator.fx-ea-system-project.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, FX-EA System Project Creator"
#property link      "https://creator.fx-ea-system-project.com/"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Lime
#property indicator_color2 Red

input int ArrowGap = 5;//高値・安値から矢印を離すpoint数

double UpFractal[];
double DownFractal[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   SetIndexBuffer(0,UpFractal);
   SetIndexStyle(0,DRAW_ARROW,STYLE_SOLID,1);
   SetIndexArrow(0,217);
   SetIndexEmptyValue(0,EMPTY_VALUE);

   SetIndexBuffer(1,DownFractal);
   SetIndexStyle(1,DRAW_ARROW,STYLE_SOLID,1);
   SetIndexArrow(1,218);
   SetIndexEmptyValue(1,EMPTY_VALUE);

   IndicatorShortName("Fractals Confirmed Arrow");
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Custom indicator iteration function                               |
//+------------------------------------------------------------------+
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[])
  {
   if(rates_total < 5)
      return(0);

   int limit;
   if(prev_calculated==0)
      limit = rates_total-3;
   else
     {
      limit = rates_total-prev_calculated+1;
      if(limit > rates_total-3)
         limit = rates_total-3;
     }

   //shift=0,1は仕組み上フラクタルになり得ないため、i>=2までしかループしない
   for(int i=limit;i>=2;i--)
     {
      UpFractal[i]=EMPTY_VALUE;
      DownFractal[i]=EMPTY_VALUE;

      double up = iFractals(NULL,0,MODE_UPPER,i);
      if(up != 0.0)
         UpFractal[i]=up+ArrowGap*Point;

      double down = iFractals(NULL,0,MODE_LOWER,i);
      if(down != 0.0)
         DownFractal[i]=down-ArrowGap*Point;
     }

   return(rates_total);
  }
//+------------------------------------------------------------------+
Copy

MetaEditorで実際に動かす手順

  1. MT4のMetaEditorで「ファイル」→「新規作成」→「カスタムインディケータ」を選ぶ
  2. 「FractalsConfirmedArrow」という名前で作成し、テンプレートの中身をすべて削除してコード全体を貼り付ける
  3. F7キーでコンパイルし、「0 error(s), 0 warning(s)」になることを確認する
  4. チャートへ適用し、MT4標準のフラクタルインジケーターも同時に表示する
  5. 標準フラクタルの矢印位置と、このインジケーターの矢印位置が一致することを目視で確認する

EAに組み込むときに気をつけること

フラクタルを反転エントリーの根拠としてEAに組み込む場合、判定に使う`shift`を安易に0や1にしないでください。

`shift=2`(直近の確定フラクタル)を使うということは、そのフラクタルが確定した時点で、実際にはすでに2本分の値動きが過ぎたあとだということです。

「フラクタルで反転を検知してすぐエントリー」という発想自体が、この2本分の遅れを前提にしないと成立しません。

高値・安値からすでに離れた位置でエントリーすることになるため、損切り幅の設計にもこの遅れを織り込む必要があります。

矢印が出ない・想定と違う位置に出るとき

  • 出ない: 直近2本(`shift=0`・`shift=1`)を見ていないか。仕組み上この2本は常に`0.0`が返るため矢印は出ない(バグではない)
  • 標準のフラクタルと位置がずれる: このインジケーターの`ArrowGap`の値や、標準インジケーター側の表示パラメーターを確認する。判定条件自体はMT4標準と同じロジックを使っている
  • 矢印が少なすぎる/多すぎると感じる: フラクタルは「前後2本より高い(安い)」という比較的緩い条件のため、レンジ相場では頻発しやすい。単体で売買判断せず、他の環境認識指標と組み合わせる

まとめ

`iFractals()`は、対象の足の前後2本ずつ、計5本の関係でフラクタルを判定する関数のため、直近の1〜2本は仕組み上どうやっても`0.0`しか返りません。

この制約はバグではなく設計そのものであり、`shift=2`以降だけをループして確定済みのフラクタルだけを扱うようにすれば、意図しない挙動を避けられます。EAに組み込む際は、この「2本分の遅れ」を損切り幅の設計にも織り込んでください。

関連記事