ピンバーと包み足(エンガルフィング)は、

裁量トレードの反転サインとして人気の高いローソク足パターンですが、

どちらも「見た目で判断する」ことが前提のため、

同じチャートを見ても人によって「これはピンバーだ」

「いや違う」と判断が割れやすいという弱点があります。

この記事では、ボディ・値幅・ヒゲの長さという具体的な数値を使って、

2つのパターンを同時に自動検出し、

矢印で知らせるインジケーターの作り方を解説します。

この記事で分かること
・ピンバーを数値で判定する3つの比率(ボディ・値幅・ヒゲ)
・包み足(エンガルフィング)を数値で判定する実体の包含ロジック
・閾値に唯一の正解はなく、調整が必要な理由
・実際に動く2パターン同時検出インジケーターのコード全体

設計思想: 「見た目の判断」を数値のルールに変換する

まず、ピンバーと包み足をそれぞれ数値でどう定義するかを整理します。

ピンバーの数値的な定義

ピンバーは、ローソク足全体の値幅(高値-安値)に対して、

実体(始値-終値)が小さく、

片側のヒゲだけが極端に長く伸びている形のローソク足です。

ピンバーの一般的な特徴
・実体が値幅全体に対して小さい
・上下どちらか一方のヒゲだけが極端に長い
・長いヒゲが反対側のヒゲの2倍以上あることが多い
・下ヒゲが長ければ反転上昇、上ヒゲが長ければ反転下落の目安とされる

包み足(エンガルフィング)の数値的な定義

包み足は、2本目のローソク足の実体が、

1本目のローソク足の実体を始値・終値ともに完全に覆ってしまう形です。

本体サイトのローソク足の見方の記事で解説されている基本の考え方を、

この記事では「実体の始値・終値の大小関係」という数値条件に落とし込みます。

パターン 必要な本数 判定に使う値
ピンバー 1本 ボディ・値幅・ヒゲの比率
包み足 2本 2本の実体の始値・終値の大小関係

ピンバーの判定ロジック

実際にどの比率をどう計算するかを見ていきます。

ボディ・値幅・ヒゲの比率を計算する

double range = High[i] - Low[i];
double body  = MathAbs(Close[i] - Open[i]);
double upperWick = High[i] - MathMax(Open[i], Close[i]);
double lowerWick = Low[i] - MathMin(Open[i], Close[i]); // 負の値になるため符号反転して使う

値幅に対する実体の割合と、

上下どちらのヒゲが長いかを、この4つの値から判定します。

閾値パラメーターの考え方

本記事では「実体が値幅の35%以下」「長いヒゲが短いヒゲの2倍以上」

という2つの条件を初期値にしていますが、

これは一般的によく使われる目安であり、唯一の正解ではありません。

閾値についての注意
・35%・2倍という数字に業界統一の基準は無い
・通貨ペアや時間足によって「普通の形」が変わる
・厳しくしすぎると矢印が全く出なくなる
・緩くしすぎると普通のローソク足まで検出してしまう

実際に使う通貨ペアの過去チャートで矢印の頻度を見ながら、

入力パラメーターとして調整できるようにしておくことが重要です。

包み足の判定ロジック

2本のローソク足の実体を比較する判定を見ていきます。

実体同士の包含判定

bool bull1 = Close[i+1] < Open[i+1]; // 1本前が陰線
bool bull2 = Close[i]   > Open[i];   // 今のバーが陽線
bool engulfBull = bull1 && bull2
                && Open[i]  <= Close[i+1]
                && Close[i] >= Open[i+1];

1本前が陰線・今のバーが陽線で、

かつ今のバーの実体(始値から終値)が、

1本前の実体を始値・終値ともに覆っていれば、

強気の包み足として判定します。

弱気の包み足は、この条件の陽線・陰線を入れ替えるだけで判定できます。

実際に動くコード全体

実際にMetaEditorでコンパイルできる、

ピンバーと包み足を同時に検出して矢印表示するインジケーターです。

//+------------------------------------------------------------------+
//|                                        PinbarEngulfingArrow.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 4
#property indicator_color1 Lime
#property indicator_width1 2
#property indicator_color2 Red
#property indicator_width2 2
#property indicator_color3 DodgerBlue
#property indicator_width3 2
#property indicator_color4 Orange
#property indicator_width4 2

input double BodyRatioMax = 0.35; //実体が値幅の何%以下ならピンバー候補とするか
input double WickRatioMin = 2.0;  //長いヒゲが短いヒゲの何倍以上ならピンバーとするか

double PinBullArrow[];
double PinBearArrow[];
double EngulfBullArrow[];
double EngulfBearArrow[];

int OnInit()
  {
   SetIndexBuffer(0, PinBullArrow);
   SetIndexStyle(0, DRAW_ARROW);
   SetIndexArrow(0, 233);

   SetIndexBuffer(1, PinBearArrow);
   SetIndexStyle(1, DRAW_ARROW);
   SetIndexArrow(1, 234);

   SetIndexBuffer(2, EngulfBullArrow);
   SetIndexStyle(2, DRAW_ARROW);
   SetIndexArrow(2, 159);

   SetIndexBuffer(3, EngulfBearArrow);
   SetIndexStyle(3, DRAW_ARROW);
   SetIndexArrow(3, 159);

   IndicatorShortName("Pinbar/Engulfing Arrow");
   return(INIT_SUCCEEDED);
  }

bool IsPinBar(int i, bool &bullish)
  {
   double range = High[i] - Low[i];
   if(range <= 0)
      return(false);

   double body = MathAbs(Close[i] - Open[i]);
   if(body / range > BodyRatioMax)
      return(false);

   double upperWick = High[i] - MathMax(Open[i], Close[i]);
   double lowerWick = MathMin(Open[i], Close[i]) - Low[i];

   if(lowerWick >= upperWick * WickRatioMin && lowerWick > 0)
     {
      bullish = true; // 下ヒゲが長い=反転上昇の目安
      return(true);
     }
   if(upperWick >= lowerWick * WickRatioMin && upperWick > 0)
     {
      bullish = false; // 上ヒゲが長い=反転下落の目安
      return(true);
     }
   return(false);
  }

bool IsEngulfing(int i, bool &bullish)
  {
   bool prevBear = Close[i + 1] < Open[i + 1];
   bool prevBull = Close[i + 1] > Open[i + 1];

   bool nowBull = Close[i] > Open[i];
   bool nowBear = Close[i] < Open[i];

   if(prevBear && nowBull && Open[i] <= Close[i + 1] && Close[i] >= Open[i + 1])
     {
      bullish = true;
      return(true);
     }
   if(prevBull && nowBear && Open[i] >= Close[i + 1] && Close[i] <= Open[i + 1])
     {
      bullish = false;
      return(true);
     }
   return(false);
  }

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[])
  {
   int needed = 3;
   if(rates_total < needed)
      return(0);

   int limit = (prev_calculated == 0) ? rates_total - needed : rates_total - prev_calculated + 1;

   for(int i = limit; i >= 0; i--)
     {
      PinBullArrow[i]    = EMPTY_VALUE;
      PinBearArrow[i]    = EMPTY_VALUE;
      EngulfBullArrow[i] = EMPTY_VALUE;
      EngulfBearArrow[i] = EMPTY_VALUE;

      bool pinBullish;
      if(IsPinBar(i, pinBullish))
        {
         if(pinBullish)
            PinBullArrow[i] = Low[i] - 10 * Point;
         else
            PinBearArrow[i] = High[i] + 10 * Point;
        }

      bool engulfBullish;
      if(i + 1 < rates_total && IsEngulfing(i, engulfBullish))
        {
         if(engulfBullish)
            EngulfBullArrow[i] = Low[i] - 20 * Point;
         else
            EngulfBearArrow[i] = High[i] + 20 * Point;
        }
     }

   return(rates_total);
  }

MetaEditorでのコンパイル・実行手順

実際にMT4で動かすまでの手順です。

  1. MetaEditorで新規インジケーター「PinbarEngulfingArrow」を作成し、上のコードを貼り付けてコンパイルする
  2. エラー・警告が0件であることを確認する
  3. チャートに適用し、ピンバーの位置に緑(上昇)・赤(下落)の矢印が出ることを確認する
  4. 包み足の位置に青・オレンジの矢印が出ることを確認する(ピンバーと矢印の形を変えて区別してある)
  5. 入力パラメーターのBodyRatioMax・WickRatioMinを変えて、矢印の出方がどう変わるか見比べる

よくあるエラーと注意点

実装でつまずきやすいポイントをまとめます。

閾値を厳しくしすぎて矢印が全く出ない

BodyRatioMaxを極端に小さくしたり、

WickRatioMinを極端に大きくすると、

理想的すぎる形しか検出されず、

何週間も矢印が出ないことがあります。

まずは初期値のまま過去チャートで頻度を確認してください。

ピンバーと包み足が同じバーで同時に成立する

実体が小さく長いヒゲを持つバーが、

同時に包み足の条件も満たすことがあります。

本記事のコードは両方を独立に判定して別の矢印を出すため、

同じバーに複数の矢印が重なって表示される場合があります。

トレンドの無いレンジ相場で誤検知が増える

細かい値動きが続くレンジ相場では、

本来は意味の薄いヒゲの長いバーが、

ピンバーの条件を満たしてしまうことがあります。

既刊の環境認識系インジケーターと組み合わせて、

トレンド方向を確認してから使うことをおすすめします。

既刊テクニカル指標記事との使い分け

似た「価格パターン検出」型の記事が複数あるため、使い分けを整理します。

記事 検出対象 必要な本数
本記事(ピンバー・包み足) 実体とヒゲの形・2本の実体の包含 1本または2本
ifractals記事(既刊) 5本の高値・安値の形 5本
連続陽線・陰線記事(既刊) 同じ方向の連続本数 可変

よくある質問

ピンバー・包み足の自動検出について、よくある疑問に回答します。

このインジケーターだけで売買判断してよいですか?

おすすめしません。

ピンバー・包み足はどちらも単独では精度の高いサインではなく、

サポート・レジスタンスなど他の根拠と組み合わせて使う前提の

パターンとして広く紹介されています。

EAの発注条件に使えますか?

使えます。

本記事のIsPinBar()・IsEngulfing()関数をそのまま流用すれば、

「ピンバーが出たらエントリーを検討する」

といった発注条件に組み込めます。

閾値はどうやって決めればよいですか?

公式な正解はないため、

使う通貨ペア・時間足の過去チャートで、

実際に目で見て「これはピンバーだ」と思うバーに矢印が出るように、

BodyRatioMax・WickRatioMinを調整するのが実用的な方法です。

【MQL4】ピンバーと包み足を自動検出して矢印表示するインジケーターの作り方(数値での見分け方つき):まとめ

ピンバーと包み足は、どちらも「見た目の判断」が前提のパターンですが、

ボディ・値幅・ヒゲの比率、実体同士の包含関係という数値条件に変換すれば、

自動検出が可能です。

本記事の閾値(35%・2倍)は一般的な目安であり唯一の正解ではないため、

実際に使う通貨ペア・時間足で矢印の頻度を見ながら調整してください。

どちらのパターンも単独では精度の高いサインではないため、

他の根拠と組み合わせて使うことをおすすめします。

関連記事