【MQL5】ChartTimePriceToXY関数の使い方と自動売買実装コード

1. ChartTimePriceToXY関数の概要と実務での活用法

MQL5でカスタムインジケーターやEA(エキスパートアドバイザー)を開発していると、「チャート上の特定の価格や時刻の位置に、ボタンやラベルなどのGUI部品を配置したい」という場面に必ず遭遇します。しかし、MT5の描画系オブジェクトには「価格と時刻」で位置を指定するものと、「ピクセル(X, Y座標)」で指定するものの2種類が存在します。

ChartTimePriceToXY関数は、「価格(Price)と時刻(Time)」というチャート上の座標を、画面上の「ピクセル座標(X, Y)」に変換するための架け橋となる関数です。

実務での活用シーン

  • 独自のダッシュボード作成: 現在価格のすぐ横に「一括決済ボタン」を表示させるなど、価格追従型のUIを構築する際に必須となります。
  • 情報の視覚化: 特定のエントリーポイントから線を引いたり、マウスカーソルの位置にある価格情報をツールチップとして表示したりする場合に使用します。
  • グラフィック描画: Canvasクラスを用いた高度な描画を行う際、チャートのスケールに合わせた描画位置の特定に利用します。

初心者の方は「単純に座標を変換するだけ」と考えがちですが、チャートのスクロールやズーム、ウィンドウサイズの変更によってピクセル座標は刻々と変化するため、動的な制御が求められる難易度の高い関数でもあります。


2. 構文と戻り値

ChartTimePriceToXY関数の基本的な構文は以下の通りです。

bool  ChartTimePriceToXY(
   long           chart_id,     // チャートID(0は現在のチャート)
   int            sub_window,   // サブウィンドウ番号(0はメインウィンドウ)
   datetime       time,         // 変換したい時刻
   double         price,        // 変換したい価格
   int&           x,            // X座標を受け取る変数(参照渡し)
   int&           y             // Y座標を受け取る変数(参照渡し)
   );

パラメーター解説

  • chart_id: 操作対象のチャートIDを指定します。通常は 0 で現在のチャートを指します。
  • sub_window: 変換対象のウィンドウ番号です。メインチャートなら 0、RSIなどのインジケーターが表示されているサブウィンドウなら 1 以降を指定します。
  • time / price: 変換元の座標データです。
  • x / y: 変換後のピクセル値が格納される変数です。これらは「参照渡し」となっており、関数を実行すると指定した変数の中に数値が書き込まれます。

戻り値

  • 成功時: true を返します。
  • 失敗時: false を返します。指定した時刻や価格が現在のチャートの表示範囲外にある場合、変換に失敗することがあります。

3. 具体的な使い方・実践サンプルコード

以下のサンプルコードは、最新のローソク足の終値位置をピクセル座標に変換し、その場所にボタンを表示・追従させるEAの簡易実装です。

//+------------------------------------------------------------------+
//|                                              SamplePriceToXY.mq5 |
//+------------------------------------------------------------------+
#property strict

// ボタンのオブジェクト名
const string OBJ_NAME = "PriceFollowButton";

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
    // 起動時にボタンを作成
    ObjectCreate(0, OBJ_NAME, OBJ_BUTTON, 0, 0, 0);
    ObjectSetString(0, OBJ_NAME, OBJPROP_TEXT, "価格追従ボタン");
    ObjectSetInteger(0, OBJ_NAME, OBJPROP_WIDTH, 120);
    ObjectSetInteger(0, OBJ_NAME, OBJPROP_HEIGHT, 30);
    ObjectSetInteger(0, OBJ_NAME, OBJPROP_CORNER, CORNER_LEFT_UPPER); // 左上を起点にする

    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    ObjectDelete(0, OBJ_NAME);
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
    datetime currentTime = TimeCurrent();
    double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);

    int x, y;

    // チャート上の価格・時刻をピクセル座標(x, y)に変換
    if(ChartTimePriceToXY(0, 0, currentTime, currentPrice, x, y))
    {
        // 変換に成功した場合、ボタンの位置を更新
        // ボタンの中心が価格にくるように微調整
        ObjectSetInteger(0, OBJ_NAME, OBJPROP_XDISTANCE, x + 20); 
        ObjectSetInteger(0, OBJ_NAME, OBJPROP_YDISTANCE, y - 15);
    }
}

//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
    // チャートがスクロールされたりズームされた時も再計算が必要
    if(id == CHARTEVENT_CHART_CHANGE)
    {
        OnTick();
    }
}

4. 使用上の注意点とよくあるエラー

開発中によく遭遇するトラブルをまとめました。

  1. 表示範囲外の座標指定:
    time(時刻)がチャートの左端よりも過去だったり、未来すぎる場合、関数は false を返します。最新の価格を表示したい場合は、常に TimeCurrent()iTime() で最新の時刻を取得して渡すようにしましょう。

  2. サブウィンドウ番号の指定ミス:
    メインチャートに描画したいのに sub_window1 にしている、あるいはその逆のミスが非常に多いです。サブウィンドウに配置したインジケーターから呼び出す場合は、ChartWindowFind() を使って動的に番号を取得するのが安全です。

  3. 再計算のタイミング:
    ピクセル座標は、価格の変動だけでなく「ユーザーがチャートをドラッグした時」「ウィンドウサイズを変えた時」「ズームを変更した時」にも変わります。OnTick だけでなく、OnChartEvent 内で CHARTEVENT_CHART_CHANGE をトリガーにして座標更新を行うのが、スムーズなUIを作るコツです。

  4. 座標の基準点(Corner):
    ObjectSetIntegerOBJPROP_CORNER を設定している場合、ChartTimePriceToXY で得られる座標とズレが生じることがあります。基本的には CORNER_LEFT_UPPER(左上基準)で考えるのが最もシンプルです。


5. 【重要】自動売買における約定スピードと環境の罠

アルゴリズムトレードにおいて、ロジックの正確さ以上に収益を左右するのが「物理的な通信遅延(レイテンシ)」です。どれほど完璧なコードを書き、ChartTimePriceToXYを駆使した高度なUIを構築したとしても、自宅のPC環境から一般的なインターネット回線で注文を出している限り、プロのクオンツやHFT(高頻度取引)勢には太刀打ちできません。

FXのサーバーは世界各地のデータセンターに設置されており、自宅PCからの注文は数百ミリ秒の遅延を伴います。このわずかな遅延が、相場急変時のスリッページや約定拒否を引き起こし、バックテスト結果とかけ離れた損失を生む原因となります。極限まで約定スピードを高め、有利な価格で約定させるためには、ブローカーのサーバーに物理的に近い場所に位置する「専用のVPS(仮想専用サーバー)」の利用が不可欠です。24時間安定稼働し、ネットワーク遅延を最小化する環境を整えることこそが、勝てるトレーダーへの第一歩と言えます。

💡 この記事の内容を実運用で活かすには?

この記事の内容を実運用で活かすには、正しい環境が必要です。
特にVPSを使わないと、このロジックは再現できません。

コメント

タイトルとURLをコピーしました