【MQL4定数】矢印オブジェクトのアンカー定数(ENUM_ARROW_ANCHOR)

【辞書】MQLリファレンス

矢印オブジェクトのアンカー定数

矢印オブジェクトのアンカー定数は、矢印オブジェクトのアンカーを設定するときに使われます。

矢印オブジェクトのアンカーとは、矢印オブジェクトを表示するときに基準となる座標のことです。

主に、ObjectSetInteger関数で使われます。

簡単に関数の説明です。

  • ObjectSetInteger関数:オブジェクトの状態を設定する

 

それぞれ、OBJPROP_ANCHORの設定値として、矢印オブジェクトのアンカー定数が使われます。

 

矢印オブジェクトのアンカー定数(ENUM_ARROW_ANCHOR)

定数説明
ANCHOR_TOPオブジェクトの上にアンカーを設定
ANCHOR_BOTTOMオブジェクトの下にアンカーを設定

 

矢印オブジェクトのアンカー定数の使い方

主に、ObjectSetInteger関数で使用されます。

それぞれ、OBJPROP_ANCHORの設定値として、矢印オブジェクトのアンカー定数が使われます。

上記の定数を入力しましょう。

すると、その定数に対応したアンカーが設定されます。

例えば、以下のように使用します。

  //ObjectSetInteger関数
  //オブジェクトの上を基準座標にする
   bool objectSetInteger = ObjectSetInteger(ChartID(), "自動売買を作ろう!", OBJPROP_ANCHOR, ANCHOR_TOP);

 

返り値はbool型です。

成功すればture、失敗すればfalseが返ってきます。

 

実用的なプログラム例

ここでは、矢印オブジェクトのアンカー定数を実際のインジケーターやEAで活用する例を紹介します。

例1:ローソク足の高値・安値に矢印を表示するインジケーター

直近のローソク足の高値に下向き矢印、安値に上向き矢印を表示する例です。ANCHOR_TOPとANCHOR_BOTTOMを使い分けることで、矢印がローソク足に重ならず見やすく配置されます。

//+------------------------------------------------------------------+
//| 高値・安値に矢印を表示するインジケーター                            |
//+------------------------------------------------------------------+
#property indicator_chart_window

//+------------------------------------------------------------------+
//| 矢印オブジェクトを作成する関数                                      |
//+------------------------------------------------------------------+
void CreateArrow(string name, datetime time, double price,
                 int arrowCode, color clr, ENUM_ARROW_ANCHOR anchor)
{
   // 既に同名のオブジェクトが存在する場合は削除
   if(ObjectFind(0, name) >= 0)
      ObjectDelete(0, name);

   // 矢印オブジェクトを作成
   ObjectCreate(0, name, OBJ_ARROW, 0, time, price);

   // 矢印の種類を設定(例:234=下矢印、233=上矢印)
   ObjectSetInteger(0, name, OBJPROP_ARROWCODE, arrowCode);

   // 矢印の色を設定
   ObjectSetInteger(0, name, OBJPROP_COLOR, clr);

   // アンカーを設定(矢印の基準位置)
   // ANCHOR_BOTTOM:矢印の下側が座標に来る → 安値の下に矢印が表示される
   // ANCHOR_TOP:矢印の上側が座標に来る → 高値の上に矢印が表示される
   ObjectSetInteger(0, name, OBJPROP_ANCHOR, anchor);

   // 矢印のサイズを設定
   ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);
}

//+------------------------------------------------------------------+
//| OnCalculate - ティックごとに呼び出される                            |
//+------------------------------------------------------------------+
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[])
{
   // 直近の確定足(1本前)の高値に下向き矢印を表示
   // ANCHOR_BOTTOMを使い、矢印の下端が高値に接するように配置
   CreateArrow("HighArrow", Time[1], High[1],
               234, clrRed, ANCHOR_BOTTOM);

   // 直近の確定足(1本前)の安値に上向き矢印を表示
   // ANCHOR_TOPを使い、矢印の上端が安値に接するように配置
   CreateArrow("LowArrow", Time[1], Low[1],
               233, clrDodgerBlue, ANCHOR_TOP);

   return(rates_total);
}

 

例2:移動平均線のゴールデンクロス・デッドクロスに矢印シグナルを表示

短期・長期移動平均線のクロスを検出し、買いシグナル(上矢印)・売りシグナル(下矢印)をチャートに表示する実用的な例です。

//+------------------------------------------------------------------+
//| MA クロスシグナル表示インジケーター                                  |
//+------------------------------------------------------------------+
#property indicator_chart_window

input int ShortMAPeriod = 5;   // 短期移動平均の期間
input int LongMAPeriod  = 25;  // 長期移動平均の期間

//+------------------------------------------------------------------+
//| シグナル矢印を作成する関数                                         |
//+------------------------------------------------------------------+
void CreateSignalArrow(string name, datetime time, double price,
                       bool isBuy)
{
   // 既存の同名オブジェクトを削除
   if(ObjectFind(0, name) >= 0)
      ObjectDelete(0, name);

   // 矢印オブジェクトを作成
   ObjectCreate(0, name, OBJ_ARROW, 0, time, price);

   if(isBuy)
   {
      // 買いシグナル:上向き矢印(Wingdings 233)
      ObjectSetInteger(0, name, OBJPROP_ARROWCODE, 233);
      ObjectSetInteger(0, name, OBJPROP_COLOR, clrLime);
      // 安値の下に表示するため、矢印の上端を基準にする
      ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_TOP);
   }
   else
   {
      // 売りシグナル:下向き矢印(Wingdings 234)
      ObjectSetInteger(0, name, OBJPROP_ARROWCODE, 234);
      ObjectSetInteger(0, name, OBJPROP_COLOR, clrRed);
      // 高値の上に表示するため、矢印の下端を基準にする
      ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_BOTTOM);
   }

   ObjectSetInteger(0, name, OBJPROP_WIDTH, 3);
}

//+------------------------------------------------------------------+
//| OnCalculate                                                       |
//+------------------------------------------------------------------+
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 < LongMAPeriod + 2) return(0);

   int limit = rates_total - prev_calculated;
   if(limit > rates_total - LongMAPeriod - 2)
      limit = rates_total - LongMAPeriod - 2;

   for(int i = limit; i >= 1; i--)
   {
      // 現在のバーと1つ前のバーの移動平均値を取得
      double shortMA_curr = iMA(NULL, 0, ShortMAPeriod, 0, MODE_SMA, PRICE_CLOSE, i);
      double longMA_curr  = iMA(NULL, 0, LongMAPeriod, 0, MODE_SMA, PRICE_CLOSE, i);
      double shortMA_prev = iMA(NULL, 0, ShortMAPeriod, 0, MODE_SMA, PRICE_CLOSE, i + 1);
      double longMA_prev  = iMA(NULL, 0, LongMAPeriod, 0, MODE_SMA, PRICE_CLOSE, i + 1);

      // ゴールデンクロス検出(短期MAが長期MAを下から上に抜ける)
      if(shortMA_prev < longMA_prev && shortMA_curr > longMA_curr)
      {
         string buyName = "BuySignal_" + IntegerToString(i);
         CreateSignalArrow(buyName, Time[i], Low[i], true);
      }

      // デッドクロス検出(短期MAが長期MAを上から下に抜ける)
      if(shortMA_prev > longMA_prev && shortMA_curr < longMA_curr)
      {
         string sellName = "SellSignal_" + IntegerToString(i);
         CreateSignalArrow(sellName, Time[i], High[i], false);
      }
   }

   return(rates_total);
}

 

例3:RSIの買われすぎ・売られすぎで矢印を表示するインジケーター

RSI(相対力指数)が買われすぎ水準(70以上)から下がったとき、または売られすぎ水準(30以下)から上がったときに矢印を表示する例です。アンカーの使い分けにより、矢印がローソク足から適切にオフセットされます。

//+------------------------------------------------------------------+
//| RSI反転シグナル矢印インジケーター                                   |
//+------------------------------------------------------------------+
#property indicator_chart_window

input int    RSIPeriod      = 14;   // RSIの計算期間
input double OverboughtLevel = 70.0; // 買われすぎ水準
input double OversoldLevel   = 30.0; // 売られすぎ水準

//+------------------------------------------------------------------+
//| 矢印オブジェクトを作成する共通関数                                   |
//+------------------------------------------------------------------+
void DrawArrow(string name, datetime time, double price,
               int code, color clr, ENUM_ARROW_ANCHOR anchor)
{
   // 既存オブジェクトがあれば削除
   if(ObjectFind(0, name) >= 0)
      ObjectDelete(0, name);

   // 矢印オブジェクトを新規作成
   ObjectCreate(0, name, OBJ_ARROW, 0, time, price);
   ObjectSetInteger(0, name, OBJPROP_ARROWCODE, code);
   ObjectSetInteger(0, name, OBJPROP_COLOR, clr);

   // アンカー設定:矢印がローソク足に重ならないように調整
   ObjectSetInteger(0, name, OBJPROP_ANCHOR, anchor);
   ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);

   // 背面に表示されないよう、前面描画を有効にする
   ObjectSetInteger(0, name, OBJPROP_BACK, false);
}

//+------------------------------------------------------------------+
//| OnCalculate                                                       |
//+------------------------------------------------------------------+
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 < RSIPeriod + 2) return(0);

   // 処理範囲の決定(初回は全バー、2回目以降は新しいバーのみ)
   int limit = rates_total - prev_calculated;
   if(limit > rates_total - RSIPeriod - 2)
      limit = rates_total - RSIPeriod - 2;

   for(int i = limit; i >= 1; i--)
   {
      // 現在のバーと1つ前のバーのRSI値を取得
      double rsiCurr = iRSI(NULL, 0, RSIPeriod, PRICE_CLOSE, i);
      double rsiPrev = iRSI(NULL, 0, RSIPeriod, PRICE_CLOSE, i + 1);

      // 売られすぎ水準から上抜け → 買いシグナル(上向き矢印)
      if(rsiPrev <= OversoldLevel && rsiCurr > OversoldLevel)
      {
         string name = "RSI_Buy_" + IntegerToString(i);
         // ANCHOR_TOP:矢印の上端を安値に合わせ、矢印本体は下に伸びる
         DrawArrow(name, Time[i], Low[i], 233, clrDodgerBlue, ANCHOR_TOP);
      }

      // 買われすぎ水準から下抜け → 売りシグナル(下向き矢印)
      if(rsiPrev >= OverboughtLevel && rsiCurr < OverboughtLevel)
      {
         string name = "RSI_Sell_" + IntegerToString(i);
         // ANCHOR_BOTTOM:矢印の下端を高値に合わせ、矢印本体は上に伸びる
         DrawArrow(name, Time[i], High[i], 234, clrOrangeRed, ANCHOR_BOTTOM);
      }
   }

   return(rates_total);
}

//+------------------------------------------------------------------+
//| インジケーター終了時に全矢印オブジェクトを削除                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   // "RSI_"で始まるオブジェクトをすべて削除
   for(int i = ObjectsTotal(0) - 1; i >= 0; i--)
   {
      string objName = ObjectName(0, i);
      if(StringFind(objName, "RSI_") == 0)
         ObjectDelete(0, objName);
   }
}

 

例4:EAのエントリー・決済ポイントを矢印で記録するスクリプト

EAで実際に注文が約定したタイミングでチャート上に矢印を残す例です。エントリーと決済のポイントを視覚的に確認でき、トレード結果の振り返りに役立ちます。

//+------------------------------------------------------------------+
//| トレード履歴矢印を表示するEAモジュール                               |
//+------------------------------------------------------------------+

// グローバル変数:矢印の通し番号
int g_arrowCount = 0;

//+------------------------------------------------------------------+
//| トレード矢印をチャートに描画する関数                                 |
//| type: 0=買いエントリー, 1=売りエントリー,                           |
//|       2=買い決済, 3=売り決済                                       |
//+------------------------------------------------------------------+
void DrawTradeArrow(int type, datetime time, double price)
{
   // 矢印名を一意にするため通し番号を付与
   g_arrowCount++;
   string name = "Trade_" + IntegerToString(g_arrowCount);

   // 矢印オブジェクトを作成
   ObjectCreate(0, name, OBJ_ARROW, 0, time, price);

   switch(type)
   {
      case 0: // 買いエントリー:安値付近に上向き矢印
         ObjectSetInteger(0, name, OBJPROP_ARROWCODE, 233);
         ObjectSetInteger(0, name, OBJPROP_COLOR, clrLime);
         // ANCHOR_TOP:矢印の上端が価格に接する → 矢印は下に伸びる
         ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_TOP);
         break;

      case 1: // 売りエントリー:高値付近に下向き矢印
         ObjectSetInteger(0, name, OBJPROP_ARROWCODE, 234);
         ObjectSetInteger(0, name, OBJPROP_COLOR, clrRed);
         // ANCHOR_BOTTOM:矢印の下端が価格に接する → 矢印は上に伸びる
         ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_BOTTOM);
         break;

      case 2: // 買い決済:チェックマークで表示
         ObjectSetInteger(0, name, OBJPROP_ARROWCODE, 252);
         ObjectSetInteger(0, name, OBJPROP_COLOR, clrGold);
         // ANCHOR_BOTTOM:マークの下端を価格に合わせる
         ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_BOTTOM);
         break;

      case 3: // 売り決済:チェックマークで表示
         ObjectSetInteger(0, name, OBJPROP_ARROWCODE, 252);
         ObjectSetInteger(0, name, OBJPROP_COLOR, clrMagenta);
         // ANCHOR_TOP:マークの上端を価格に合わせる
         ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_TOP);
         break;
   }

   // 矢印サイズを大きめに設定して見やすくする
   ObjectSetInteger(0, name, OBJPROP_WIDTH, 3);

   // ツールチップに情報を表示
   string tooltip = "Price: " + DoubleToString(price, Digits);
   ObjectSetString(0, name, OBJPROP_TOOLTIP, tooltip);
}

//+------------------------------------------------------------------+
//| OnTick - EAのメインロジック例                                      |
//+------------------------------------------------------------------+
void OnTick()
{
   // ポジションがない場合のエントリー判定例
   if(OrdersTotal() == 0)
   {
      // 簡易的なエントリー条件(例:終値が始値より高ければ買い)
      if(Close[1] > Open[1])
      {
         int ticket = OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3,
                                0, 0, "BuyEntry", 0, 0, clrBlue);
         if(ticket > 0)
         {
            // 買いエントリーの矢印をチャートに描画
            DrawTradeArrow(0, TimeCurrent(), Ask);
            Print("買いエントリー:矢印を描画しました");
         }
      }
   }
}

//+------------------------------------------------------------------+
//| EA終了時に全トレード矢印を削除                                      |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   for(int i = ObjectsTotal(0) - 1; i >= 0; i--)
   {
      string objName = ObjectName(0, i);
      if(StringFind(objName, "Trade_") == 0)
         ObjectDelete(0, objName);
   }
}

 

例5:ピンバー(上ヒゲ・下ヒゲ)を自動検出して矢印で強調表示

プライスアクションの基本パターンであるピンバー(長い上ヒゲや下ヒゲのローソク足)を自動検出し、該当バーに矢印を表示するインジケーターです。アンカー定数の切り替えによって、矢印がヒゲの先端から適切な方向に描画されます。

//+------------------------------------------------------------------+
//| ピンバー検出インジケーター                                          |
//+------------------------------------------------------------------+
#property indicator_chart_window

input double PinBarRatio = 2.0;  // ヒゲと実体の比率しきい値

//+------------------------------------------------------------------+
//| OnCalculate                                                       |
//+------------------------------------------------------------------+
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 < 3) return(0);

   int limit = rates_total - prev_calculated;
   if(limit > rates_total - 3)
      limit = rates_total - 3;

   for(int i = limit; i >= 1; i--)
   {
      // ローソク足の各部分のサイズを計算
      double bodySize  = MathAbs(Close[i] - Open[i]);        // 実体の大きさ
      double upperWick = High[i] - MathMax(Close[i], Open[i]); // 上ヒゲの長さ
      double lowerWick = MathMin(Close[i], Open[i]) - Low[i];  // 下ヒゲの長さ
      double totalRange = High[i] - Low[i];                   // ローソク足全体の長さ

      // 実体が極端に小さい場合はスキップ(ゼロ除算防止)
      if(bodySize < Point * 2 || totalRange < Point * 5)
         continue;

      // 上ヒゲピンバーの検出:上ヒゲが実体のPinBarRatio倍以上
      if(upperWick > bodySize * PinBarRatio && upperWick > lowerWick * 2.0)
      {
         string name = "PinBar_Bear_" + IntegerToString(i);
         if(ObjectFind(0, name) < 0)
         {
            ObjectCreate(0, name, OBJ_ARROW, 0, Time[i], High[i]);
            // 下向き矢印(売り圧力を示唆)
            ObjectSetInteger(0, name, OBJPROP_ARROWCODE, 234);
            ObjectSetInteger(0, name, OBJPROP_COLOR, clrOrangeRed);
            // ANCHOR_BOTTOM:矢印の下端を高値に合わせる
            // → 矢印本体は高値の上に表示され、ヒゲの先を指す
            ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_BOTTOM);
            ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);
            ObjectSetString(0, name, OBJPROP_TOOLTIP,
                            "上ヒゲピンバー検出 (売り圧力)");
         }
      }

      // 下ヒゲピンバーの検出:下ヒゲが実体のPinBarRatio倍以上
      if(lowerWick > bodySize * PinBarRatio && lowerWick > upperWick * 2.0)
      {
         string name = "PinBar_Bull_" + IntegerToString(i);
         if(ObjectFind(0, name) < 0)
         {
            ObjectCreate(0, name, OBJ_ARROW, 0, Time[i], Low[i]);
            // 上向き矢印(買い圧力を示唆)
            ObjectSetInteger(0, name, OBJPROP_ARROWCODE, 233);
            ObjectSetInteger(0, name, OBJPROP_COLOR, clrDeepSkyBlue);
            // ANCHOR_TOP:矢印の上端を安値に合わせる
            // → 矢印本体は安値の下に表示され、ヒゲの先を指す
            ObjectSetInteger(0, name, OBJPROP_ANCHOR, ANCHOR_TOP);
            ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);
            ObjectSetString(0, name, OBJPROP_TOOLTIP,
                            "下ヒゲピンバー検出 (買い圧力)");
         }
      }
   }

   return(rates_total);
}

//+------------------------------------------------------------------+
//| インジケーター終了時にピンバー矢印をすべて削除                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   for(int i = ObjectsTotal(0) - 1; i >= 0; i--)
   {
      string objName = ObjectName(0, i);
      if(StringFind(objName, "PinBar_") == 0)
         ObjectDelete(0, objName);
   }
}

 

例6:アンカー定数の違いを視覚的に比較するスクリプト

ANCHOR_TOPとANCHOR_BOTTOMの違いを一目で理解するためのスクリプトです。同じ座標に対して異なるアンカーを設定した矢印を並べて表示し、基準位置がどのように変わるかを確認できます。

//+------------------------------------------------------------------+
//| アンカー定数の比較スクリプト                                        |
//| 同じ価格座標に異なるアンカーの矢印を表示して違いを確認                |
//+------------------------------------------------------------------+
#property script_show_inputs

void OnStart()
{
   // 基準となる時間と価格を取得(直近の確定足の終値を使用)
   datetime baseTime  = Time[1];
   double   basePrice = Close[1];

   // --- ANCHOR_TOP の矢印 ---
   string nameTop = "Compare_AnchorTop";
   if(ObjectFind(0, nameTop) >= 0)
      ObjectDelete(0, nameTop);

   ObjectCreate(0, nameTop, OBJ_ARROW, 0, baseTime, basePrice);
   ObjectSetInteger(0, nameTop, OBJPROP_ARROWCODE, 233);  // 上向き矢印
   ObjectSetInteger(0, nameTop, OBJPROP_COLOR, clrDodgerBlue);
   // ANCHOR_TOP:矢印の上端が基準座標に来る
   ObjectSetInteger(0, nameTop, OBJPROP_ANCHOR, ANCHOR_TOP);
   ObjectSetInteger(0, nameTop, OBJPROP_WIDTH, 3);
   ObjectSetString(0, nameTop, OBJPROP_TOOLTIP, "ANCHOR_TOP:上端が基準座標");

   // --- ANCHOR_BOTTOM の矢印(1本右のバーに表示して比較しやすくする) ---
   string nameBottom = "Compare_AnchorBottom";
   if(ObjectFind(0, nameBottom) >= 0)
      ObjectDelete(0, nameBottom);

   ObjectCreate(0, nameBottom, OBJ_ARROW, 0, Time[2], basePrice);
   ObjectSetInteger(0, nameBottom, OBJPROP_ARROWCODE, 233);  // 同じ上向き矢印
   ObjectSetInteger(0, nameBottom, OBJPROP_COLOR, clrOrangeRed);
   // ANCHOR_BOTTOM:矢印の下端が基準座標に来る
   ObjectSetInteger(0, nameBottom, OBJPROP_ANCHOR, ANCHOR_BOTTOM);
   ObjectSetInteger(0, nameBottom, OBJPROP_WIDTH, 3);
   ObjectSetString(0, nameBottom, OBJPROP_TOOLTIP, "ANCHOR_BOTTOM:下端が基準座標");

   // チャートを再描画
   ChartRedraw(0);

   Print("アンカー比較矢印を描画しました。青=ANCHOR_TOP、赤=ANCHOR_BOTTOM");
   Print("同じ価格座標でも、アンカーの違いにより矢印の表示位置が変わります。");
}

 

このスクリプトを実行すると、同じ価格に対してANCHOR_TOP(青)とANCHOR_BOTTOM(赤)の矢印が並んで表示されます。ANCHOR_TOPでは矢印の上端が基準座標に来るため矢印は下に伸び、ANCHOR_BOTTOMでは矢印の下端が基準座標に来るため矢印は上に伸びることが視覚的に確認できます。