【MQL4定数】アンカーポイントの定数(ENUM_ANCHOR_POINT)

【辞書】MQLリファレンス

アンカーポイントの定数

アンカーポイントの定数は、オブジェクトやチャートのアンカーポイントを設定するときに使われます。

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

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

簡単に関数の説明です。

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

 

それぞれ、OBJPROP_ANCHORと、OBJPROP_CORNERの設定値として、アンカーポイントの定数が使われます。

 

アンカーポイントの定数(ENUM_ANCHOR_POINT)

定数説明
ANCHOR_LEFT_UPPER左上を基準
ANCHOR_LEFT中央左を基準
ANCHOR_LEFT_LOWER左下を基準
ANCHOR_LOWER中央下を基準
ANCHOR_RIGHT_LOWER右下を基準
ANCHOR_RIGHT中央右を基準
ANCHOR_RIGHT_UPPER右上を基準
ANCHOR_UPPER中央上を基準
ANCHOR_CENTER中央を基準

 

アンカーポイントの定数の使い方

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

それぞれ、OBJPROP_ANCHORと、OBJPROP_CORNERの設定値として、アンカーポイントの定数が使われます。

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

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

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

  //ObjectSetInteger関数
  //オブジェクトの左上を基準にする
   bool objectSetInteger1 = ObjectSetInteger(ChartID(), "自動売買を作ろう!", OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER);
   
  //チャートの左上を基準にする
  bool objectSetInteger2 = ObjectSetInteger(ChartID(), "自動売買を作ろう!", OBJPROP_CORNER, ANCHOR_LEFT_UPPER);

 

返り値はbool型です。

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

 

実用的なプログラム例

ここからは、アンカーポイントの定数を使った実用的なプログラム例を紹介します。

例1:チャート右上にスプレッド表示ラベルを作成する

チャートの右上隅にリアルタイムのスプレッドを表示するインジケーターです。ANCHOR_RIGHT_UPPERを使って、ラベルを右上基準で配置しています。

//+------------------------------------------------------------------+
//| SpreadLabel.mq4 - チャート右上にスプレッドを表示するインジケーター
//+------------------------------------------------------------------+
#property indicator_chart_window

// ラベルのオブジェクト名
string labelName = "SpreadLabel";

//+------------------------------------------------------------------+
//| 初期化関数                                                        |
//+------------------------------------------------------------------+
int OnInit()
{
   // ラベルオブジェクトを作成する
   ObjectCreate(ChartID(), labelName, OBJ_LABEL, 0, 0, 0);

   // チャートの右上隅を基準コーナーに設定する
   ObjectSetInteger(ChartID(), labelName, OBJPROP_CORNER, CORNER_RIGHT_UPPER);

   // オブジェクトのアンカーポイントを右上に設定する
   // これにより、ラベルの右上が指定座標に一致する
   ObjectSetInteger(ChartID(), labelName, OBJPROP_ANCHOR, ANCHOR_RIGHT_UPPER);

   // チャート右上隅からのX方向の距離(ピクセル)
   ObjectSetInteger(ChartID(), labelName, OBJPROP_XDISTANCE, 10);

   // チャート右上隅からのY方向の距離(ピクセル)
   ObjectSetInteger(ChartID(), labelName, OBJPROP_YDISTANCE, 20);

   // フォントサイズを設定する
   ObjectSetInteger(ChartID(), labelName, OBJPROP_FONTSIZE, 14);

   // 文字色を設定する(黄色)
   ObjectSetInteger(ChartID(), labelName, OBJPROP_COLOR, clrYellow);

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| ティックごとに呼ばれる関数                                        |
//+------------------------------------------------------------------+
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 currentSpread = (int)MarketInfo(Symbol(), MODE_SPREAD);

   // ラベルのテキストにスプレッド値を表示する
   ObjectSetString(ChartID(), labelName, OBJPROP_TEXT,
                   "Spread: " + IntegerToString(currentSpread) + " pts");

   return(rates_total);
}

//+------------------------------------------------------------------+
//| 終了時にオブジェクトを削除する                                    |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   ObjectDelete(ChartID(), labelName);
}

 

例2:チャート四隅に情報パネルを表示する

チャートの四隅それぞれにラベルを配置し、通貨ペア名・時間足・Bid価格・Ask価格を表示する例です。CORNER定数とANCHOR定数を組み合わせることで、各隅に正しく配置できます。

//+------------------------------------------------------------------+
//| FourCornerInfo.mq4 - チャート四隅に情報を表示するインジケーター
//+------------------------------------------------------------------+
#property indicator_chart_window

// 4つのラベル名を配列で管理する
string labels[4] = {"LabelLU", "LabelRU", "LabelLB", "LabelRB"};

//+------------------------------------------------------------------+
//| ラベルを1つ作成するヘルパー関数                                    |
//+------------------------------------------------------------------+
void CreateCornerLabel(string name,
                       ENUM_BASE_CORNER corner,
                       ENUM_ANCHOR_POINT anchor,
                       int xDist, int yDist, color clr)
{
   // ラベルオブジェクトを作成する
   ObjectCreate(ChartID(), name, OBJ_LABEL, 0, 0, 0);

   // チャートのどの隅を基準にするかを設定する
   ObjectSetInteger(ChartID(), name, OBJPROP_CORNER, corner);

   // オブジェクトのアンカーポイントを設定する
   ObjectSetInteger(ChartID(), name, OBJPROP_ANCHOR, anchor);

   // X方向の距離(ピクセル)
   ObjectSetInteger(ChartID(), name, OBJPROP_XDISTANCE, xDist);

   // Y方向の距離(ピクセル)
   ObjectSetInteger(ChartID(), name, OBJPROP_YDISTANCE, yDist);

   // フォントサイズを設定する
   ObjectSetInteger(ChartID(), name, OBJPROP_FONTSIZE, 12);

   // 文字色を設定する
   ObjectSetInteger(ChartID(), name, OBJPROP_COLOR, clr);
}

//+------------------------------------------------------------------+
//| 初期化関数                                                        |
//+------------------------------------------------------------------+
int OnInit()
{
   // 左上:通貨ペア名を表示(アンカーポイント=左上)
   CreateCornerLabel(labels[0], CORNER_LEFT_UPPER, ANCHOR_LEFT_UPPER,
                     10, 20, clrWhite);

   // 右上:時間足情報を表示(アンカーポイント=右上)
   CreateCornerLabel(labels[1], CORNER_RIGHT_UPPER, ANCHOR_RIGHT_UPPER,
                     10, 20, clrAqua);

   // 左下:Bid価格を表示(アンカーポイント=左下)
   CreateCornerLabel(labels[2], CORNER_LEFT_LOWER, ANCHOR_LEFT_LOWER,
                     10, 10, clrLime);

   // 右下:Ask価格を表示(アンカーポイント=右下)
   CreateCornerLabel(labels[3], CORNER_RIGHT_LOWER, ANCHOR_RIGHT_LOWER,
                     10, 10, clrOrange);

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| ティックごとに呼ばれる関数                                        |
//+------------------------------------------------------------------+
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[])
{
   // 左上に通貨ペア名を表示する
   ObjectSetString(ChartID(), labels[0], OBJPROP_TEXT, Symbol());

   // 右上に現在の時間足を表示する
   ObjectSetString(ChartID(), labels[1], OBJPROP_TEXT,
                   "TF: " + IntegerToString(Period()) + "min");

   // 左下にBid価格を表示する
   ObjectSetString(ChartID(), labels[2], OBJPROP_TEXT,
                   "Bid: " + DoubleToString(Bid, Digits));

   // 右下にAsk価格を表示する
   ObjectSetString(ChartID(), labels[3], OBJPROP_TEXT,
                   "Ask: " + DoubleToString(Ask, Digits));

   return(rates_total);
}

//+------------------------------------------------------------------+
//| 終了時に全ラベルを削除する                                        |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   for(int i = 0; i < 4; i++)
   {
      ObjectDelete(ChartID(), labels[i]);
   }
}

 

例3:EAでエントリー時にチャート上に矢印マークを表示する

EAで売買が発生したとき、チャート上のエントリーポイントに矢印オブジェクトを配置する例です。OBJ_ARROW_UPやOBJ_ARROW_DOWNではANCHOR_TOPやANCHOR_BOTTOMを指定することで、矢印の先端がエントリー価格に正確に一致するよう調整できます。

//+------------------------------------------------------------------+
//| EntryArrowEA.mq4 - エントリー位置に矢印を表示するEA              |
//+------------------------------------------------------------------+
#property strict

// 矢印の連番管理用カウンタ
int arrowCount = 0;

//+------------------------------------------------------------------+
//| 買いエントリー矢印を表示する関数                                  |
//+------------------------------------------------------------------+
void DrawBuyArrow(datetime entryTime, double entryPrice)
{
   // ユニークなオブジェクト名を生成する
   string objName = "BuyArrow_" + IntegerToString(arrowCount);
   arrowCount++;

   // 上向き矢印オブジェクトを作成する
   ObjectCreate(ChartID(), objName, OBJ_ARROW_UP, 0, entryTime, entryPrice);

   // アンカーポイントをTOP(上端)に設定する
   // 矢印の先端(上端)がエントリー価格の位置に来る
   ObjectSetInteger(ChartID(), objName, OBJPROP_ANCHOR, ANCHOR_TOP);

   // 矢印の色を青に設定する(買いシグナル)
   ObjectSetInteger(ChartID(), objName, OBJPROP_COLOR, clrDodgerBlue);

   // 矢印の幅を設定する
   ObjectSetInteger(ChartID(), objName, OBJPROP_WIDTH, 2);
}

//+------------------------------------------------------------------+
//| 売りエントリー矢印を表示する関数                                  |
//+------------------------------------------------------------------+
void DrawSellArrow(datetime entryTime, double entryPrice)
{
   // ユニークなオブジェクト名を生成する
   string objName = "SellArrow_" + IntegerToString(arrowCount);
   arrowCount++;

   // 下向き矢印オブジェクトを作成する
   ObjectCreate(ChartID(), objName, OBJ_ARROW_DOWN, 0, entryTime, entryPrice);

   // アンカーポイントをBOTTOM(下端)に設定する
   // 矢印の先端(下端)がエントリー価格の位置に来る
   ObjectSetInteger(ChartID(), objName, OBJPROP_ANCHOR, ANCHOR_BOTTOM);

   // 矢印の色を赤に設定する(売りシグナル)
   ObjectSetInteger(ChartID(), objName, OBJPROP_COLOR, clrRed);

   // 矢印の幅を設定する
   ObjectSetInteger(ChartID(), objName, OBJPROP_WIDTH, 2);
}

//+------------------------------------------------------------------+
//| ティックごとに呼ばれる関数                                        |
//+------------------------------------------------------------------+
void OnTick()
{
   // 移動平均のゴールデンクロス・デッドクロスで売買判定する例
   double maFast0 = iMA(Symbol(), 0, 5, 0, MODE_SMA, PRICE_CLOSE, 0);
   double maFast1 = iMA(Symbol(), 0, 5, 0, MODE_SMA, PRICE_CLOSE, 1);
   double maSlow0 = iMA(Symbol(), 0, 20, 0, MODE_SMA, PRICE_CLOSE, 0);
   double maSlow1 = iMA(Symbol(), 0, 20, 0, MODE_SMA, PRICE_CLOSE, 1);

   // 現在ポジションがない場合のみエントリーする
   if(OrdersTotal() == 0)
   {
      // ゴールデンクロス:短期MAが長期MAを上抜け → 買い
      if(maFast1 <= maSlow1 && maFast0 > maSlow0)
      {
         int ticket = OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, 0, 0, "BuyEntry", 0, 0, clrBlue);
         if(ticket > 0)
         {
            // 買いエントリー矢印をチャートに描画する
            DrawBuyArrow(TimeCurrent(), Ask);
         }
      }

      // デッドクロス:短期MAが長期MAを下抜け → 売り
      if(maFast1 >= maSlow1 && maFast0 < maSlow0)
      {
         int ticket = OrderSend(Symbol(), OP_SELL, 0.1, Bid, 3, 0, 0, "SellEntry", 0, 0, clrRed);
         if(ticket > 0)
         {
            // 売りエントリー矢印をチャートに描画する
            DrawSellArrow(TimeCurrent(), Bid);
         }
      }
   }
}

//+------------------------------------------------------------------+
//| 終了時に全矢印オブジェクトを削除する                              |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   // "BuyArrow_"で始まるオブジェクトを全削除する
   ObjectsDeleteAll(ChartID(), "BuyArrow_");

   // "SellArrow_"で始まるオブジェクトを全削除する
   ObjectsDeleteAll(ChartID(), "SellArrow_");
}

OBJ_ARROW_UPにANCHOR_TOPを設定すると矢印の先端がローソク足の安値側に正確に接し、OBJ_ARROW_DOWNにANCHOR_BOTTOMを設定すると矢印の先端が高値側に正確に接します。アンカーポイントを適切に設定しないと、矢印がずれて表示されてしまうので注意しましょう。

 

例4:チャート左下に取引状況ダッシュボードを表示する

EAに組み込んで使える、取引状況をリアルタイム表示するダッシュボードの例です。チャート左下にANCHOR_LEFT_LOWERを使って複数行のラベルを整列配置し、保有ポジション数・含み損益・口座残高を表示します。

//+------------------------------------------------------------------+
//| TradeDashboard.mq4 - 取引状況ダッシュボードを表示するEA          |
//+------------------------------------------------------------------+
#property strict

// ダッシュボードのラベル名を定義する
string dashLabels[4] = {"DashTitle", "DashPositions", "DashProfit", "DashBalance"};

// ラベル1行あたりの高さ(ピクセル)
int lineHeight = 22;

//+------------------------------------------------------------------+
//| ダッシュボード用ラベルを1行作成する関数                            |
//+------------------------------------------------------------------+
void CreateDashLabel(string name, int lineIndex, color clr)
{
   // ラベルオブジェクトを作成する
   ObjectCreate(ChartID(), name, OBJ_LABEL, 0, 0, 0);

   // チャートの左下隅を基準にする
   ObjectSetInteger(ChartID(), name, OBJPROP_CORNER, CORNER_LEFT_LOWER);

   // アンカーポイントを左下に設定する
   // これにより、テキストの左下端が指定座標に一致する
   ObjectSetInteger(ChartID(), name, OBJPROP_ANCHOR, ANCHOR_LEFT_LOWER);

   // X方向の距離を設定する(左端から15ピクセル)
   ObjectSetInteger(ChartID(), name, OBJPROP_XDISTANCE, 15);

   // Y方向の距離を設定する(下から行番号に応じて上へずらす)
   // lineIndex=0が一番下、数字が大きいほど上に配置される
   ObjectSetInteger(ChartID(), name, OBJPROP_YDISTANCE, 15 + lineIndex * lineHeight);

   // フォントサイズを設定する
   ObjectSetInteger(ChartID(), name, OBJPROP_FONTSIZE, 11);

   // フォントを等幅フォントに設定する(数値が揃って見やすくなる)
   ObjectSetString(ChartID(), name, OBJPROP_FONT, "Courier New");

   // 文字色を設定する
   ObjectSetInteger(ChartID(), name, OBJPROP_COLOR, clr);
}

//+------------------------------------------------------------------+
//| 保有ポジションの合計損益を計算する関数                            |
//+------------------------------------------------------------------+
double CalcTotalProfit()
{
   double totalProfit = 0.0;

   // 全オーダーをループして含み損益を合計する
   for(int i = 0; i < OrdersTotal(); i++)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         // 現在の通貨ペアのポジションのみ集計する
         if(OrderSymbol() == Symbol())
         {
            totalProfit += OrderProfit() + OrderSwap() + OrderCommission();
         }
      }
   }

   return totalProfit;
}

//+------------------------------------------------------------------+
//| 現在の通貨ペアの保有ポジション数を取得する関数                    |
//+------------------------------------------------------------------+
int CountPositions()
{
   int count = 0;

   for(int i = 0; i < OrdersTotal(); i++)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == Symbol())
         {
            count++;
         }
      }
   }

   return count;
}

//+------------------------------------------------------------------+
//| 初期化関数                                                        |
//+------------------------------------------------------------------+
int OnInit()
{
   // ダッシュボードの各行を作成する(下から順に配置)
   // 行0(一番下):口座残高
   CreateDashLabel(dashLabels[3], 0, clrGold);
   // 行1:含み損益
   CreateDashLabel(dashLabels[2], 1, clrWhite);
   // 行2:保有ポジション数
   CreateDashLabel(dashLabels[1], 2, clrWhite);
   // 行3(一番上):タイトル
   CreateDashLabel(dashLabels[0], 3, clrYellow);

   // タイトル行のテキストを設定する(固定文字列)
   ObjectSetString(ChartID(), dashLabels[0], OBJPROP_TEXT, "== Trade Dashboard ==");

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| ティックごとに呼ばれる関数                                        |
//+------------------------------------------------------------------+
void OnTick()
{
   // 保有ポジション数を更新表示する
   int posCount = CountPositions();
   ObjectSetString(ChartID(), dashLabels[1], OBJPROP_TEXT,
                   "Positions : " + IntegerToString(posCount));

   // 含み損益を計算して更新表示する
   double profit = CalcTotalProfit();
   ObjectSetString(ChartID(), dashLabels[2], OBJPROP_TEXT,
                   "Profit    : " + DoubleToString(profit, 2) + " " + AccountCurrency());

   // 含み損益がプラスなら緑、マイナスなら赤に色を変える
   if(profit >= 0)
      ObjectSetInteger(ChartID(), dashLabels[2], OBJPROP_COLOR, clrLime);
   else
      ObjectSetInteger(ChartID(), dashLabels[2], OBJPROP_COLOR, clrRed);

   // 口座残高を更新表示する
   ObjectSetString(ChartID(), dashLabels[3], OBJPROP_TEXT,
                   "Balance   : " + DoubleToString(AccountBalance(), 2) + " " + AccountCurrency());
}

//+------------------------------------------------------------------+
//| 終了時にダッシュボードのオブジェクトを全削除する                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   for(int i = 0; i < 4; i++)
   {
      ObjectDelete(ChartID(), dashLabels[i]);
   }
}

ANCHOR_LEFT_LOWERを指定することで、チャート左下から上方向に向かって各行が自然に並びます。もしアンカーポイントをANCHOR_LEFT_UPPERにしてしまうと、テキストの上端が基準になるため、行の重なりや位置のずれが起こります。複数行を並べるときは、アンカーポイントの方向と配置の方向を揃えることが大切です。

 

例5:チャート中央にトレードシグナルのテキストを表示する

チャートの中央にANCHOR_CENTERを使って大きなシグナルテキスト(「BUY」「SELL」「WAIT」)を表示するインジケーターの例です。ANCHOR_CENTERを使うことで、テキストの長さに関係なく常にチャートの真ん中に表示されます。

//+------------------------------------------------------------------+
//| CenterSignal.mq4 - チャート中央にシグナルを表示するインジケーター |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property strict

// シグナル表示用のラベル名
string signalLabel = "CenterSignalLabel";

//+------------------------------------------------------------------+
//| 初期化関数                                                        |
//+------------------------------------------------------------------+
int OnInit()
{
   // ラベルオブジェクトを作成する
   ObjectCreate(ChartID(), signalLabel, OBJ_LABEL, 0, 0, 0);

   // チャートの左上隅を基準コーナーに設定する
   ObjectSetInteger(ChartID(), signalLabel, OBJPROP_CORNER, CORNER_LEFT_UPPER);

   // アンカーポイントを中央に設定する
   // テキストの中心が指定座標に一致するようになる
   ObjectSetInteger(ChartID(), signalLabel, OBJPROP_ANCHOR, ANCHOR_CENTER);

   // チャートの幅と高さの中央にラベルを配置する
   // ChartGetInteger関数でチャートの幅・高さをピクセルで取得する
   int chartWidth  = (int)ChartGetInteger(ChartID(), CHART_WIDTH_IN_PIXELS);
   int chartHeight = (int)ChartGetInteger(ChartID(), CHART_HEIGHT_IN_PIXELS);

   // X方向の距離をチャート幅の半分に設定する
   ObjectSetInteger(ChartID(), signalLabel, OBJPROP_XDISTANCE, chartWidth / 2);

   // Y方向の距離をチャート高さの半分に設定する
   ObjectSetInteger(ChartID(), signalLabel, OBJPROP_YDISTANCE, chartHeight / 2);

   // フォントサイズを大きく設定する(目立つように)
   ObjectSetInteger(ChartID(), signalLabel, OBJPROP_FONTSIZE, 32);

   // 初期テキストを設定する
   ObjectSetString(ChartID(), signalLabel, OBJPROP_TEXT, "WAIT");

   // 初期色をグレーに設定する
   ObjectSetInteger(ChartID(), signalLabel, OBJPROP_COLOR, clrGray);

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| ティックごとに呼ばれる関数                                        |
//+------------------------------------------------------------------+
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 chartWidth  = (int)ChartGetInteger(ChartID(), CHART_WIDTH_IN_PIXELS);
   int chartHeight = (int)ChartGetInteger(ChartID(), CHART_HEIGHT_IN_PIXELS);
   ObjectSetInteger(ChartID(), signalLabel, OBJPROP_XDISTANCE, chartWidth / 2);
   ObjectSetInteger(ChartID(), signalLabel, OBJPROP_YDISTANCE, chartHeight / 2);

   // 移動平均を使ったシンプルなシグナル判定
   double maFast = iMA(Symbol(), 0, 10, 0, MODE_SMA, PRICE_CLOSE, 0);
   double maSlow = iMA(Symbol(), 0, 50, 0, MODE_SMA, PRICE_CLOSE, 0);

   // 短期MAが長期MAより上 → 買いシグナル
   if(maFast > maSlow)
   {
      ObjectSetString(ChartID(), signalLabel, OBJPROP_TEXT, "BUY");
      ObjectSetInteger(ChartID(), signalLabel, OBJPROP_COLOR, clrDodgerBlue);
   }
   // 短期MAが長期MAより下 → 売りシグナル
   else if(maFast < maSlow)
   {
      ObjectSetString(ChartID(), signalLabel, OBJPROP_TEXT, "SELL");
      ObjectSetInteger(ChartID(), signalLabel, OBJPROP_COLOR, clrRed);
   }
   // ほぼ同じ → 待機
   else
   {
      ObjectSetString(ChartID(), signalLabel, OBJPROP_TEXT, "WAIT");
      ObjectSetInteger(ChartID(), signalLabel, OBJPROP_COLOR, clrGray);
   }

   return(rates_total);
}

//+------------------------------------------------------------------+
//| 終了時にオブジェクトを削除する                                    |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   ObjectDelete(ChartID(), signalLabel);
}

ANCHOR_CENTERを使うことで、テキストが「BUY」「SELL」「WAIT」と変化しても、常にチャートの中央に表示されます。もしANCHOR_LEFT_UPPERを使った場合、テキストの左上端が中央座標に来るため、文字列の長さによって見た目の位置がずれてしまいます。中央配置にはANCHOR_CENTERが最適です。