初めてのインジケータ作成③ 水平線を表示するインジケータを作る

この記事では、チャートに水平線を引くインジケータの作り方を説明します。

簡単なプログラムを作りながら説明します。実際にご自身で作りながら読んでいただくと理解しやすいと思います。

インジケーターを作るのが初めての人は前回の記事からお読みください。

作成するインジケータ

今回作るインジケーターは、下図のように「現在のBid価格を水平線で示する」というものです。

水平線のインジケータ

前回に続いて今回のインジケーターも実用性は全くありませんがお許しください。

MQLでは、水平線やトレンドライン、四角形などチャート内に表示する図形のことを総称して「オブジェクト」と呼びます。今回はオブジェクトを生成・操作するのが説明のポイントです。

1. 処理フローを考えよう

インジケーターを作る場合には、まず処理のフロー(全体像)を考えるのがコツです。処理のフローがはっきりしていると、実際にプログラムを書くときにミスが少なくなります。

今回のインジケーターのフローチャートを考えてみました(下図)。

フローチャート

↑シンプルですね。必要な処理内容はざっくりと2つになります。一つは「水平線を新規作成する」で、もう一つが「水平線をBid価格に移動する」です。

「水平線を新規作成する処理」はインジケーターをチャートに適用したときに1度だけ行う処理になります。「水平線を最新のBid価格に移動する処理」は、ティックを受信するたびに行う処理となります。

ではインジケーターの構想が出来上がったので、実際に作っていきましょう。

2. テンプレート作成

まずは、前回の記事で説明した要領で、MQLウィザードを使ってインジケータのテンプレートを作成してください。

テンプレートの構造

今回は②のエリアと③のエリアにコードを記述していきます。

に以下の処理をするコードを書きます。

②のエリア(最初に1度だけ実行される)
水平線を新規生成する
③のエリア(ティック受信のたびに実行される)
水平線の位置を現在のBid価格に移動する

それぞれ具体的にコードを書いていきましょう。

3. 水平線を新規生成する処理

②のエリアは、インジケータをチャートに適用した直後に一度だけ実行されます。ここに、水平線を新規生成する処理を書きます。コードは下記の通り。

int OnInit()
{
   // 水平線を新規作成
   ObjectCreate(0, "testline", OBJ_HLINE, 0, 0, 0);

   // 水平線の色を黄色に設定
   ObjectSetInteger(0, "testline", OBJPROP_COLOR, clrYellow);

   // 水平線の太さを2に設定
   ObjectSetInteger(0, "testline", OBJPROP_WIDTH, 2);

   return(INIT_SUCCEEDED);
}

最初のObjectCreate()の処理は、「現在のチャートに、testlineという名前の水平線オブジェクトを価格0(ゼロ)の位置に生成する」という内容です。

その後にObjectSetInteger()で水平線のプロパティ(色や太さなど)を設定します。省略するとデフォルトの色と太さが適用されます。

4. 水平線を現在のBid価格に移動する処理

③のエリアは、「MT4がティックを受信するたびに実行されます。」ここに、水平線を現在のBid価格に移動する処理を書きます。コードは下記の通り。

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[])
{

   // 水平線(testline)を現在のBid価格に移動する
   ObjectMove("testline", 0, 0, Bid);

   return(rates_total);
}

ここはシンプルです。追記した処理はObjectMove("testline", 0, 0, Bid);だけです。「testlineという名前のオブジェクトをBid価格に移動せよ」という内容です。

ティック受信のたびにこの処理が実行されるので、水平線が常に最新のBid価格に追従します。

これでコードの記述は全て完了です。

5. チャートに適用

コードの記述が完了したら、前回の記事で説明した要領でコンパイルしてから、チャートに適用してください。正常に適用されると、下図のようにBid価格の位置に黄色い水平線が表示されます。

水平線のインジケータ

ティック受信の度に水平線の位置が動くので、インジケーターっぽくなりましたね。

コード全体

今回作ったコード全体を以下に記載しておきます。


//+------------------------------------------------------------------+
//|                                                         TEST.mq4 |
//|                                                     minagachi FX |
//|                                            https://minagachi.com |
//+------------------------------------------------------------------+
#property copyright "minagachi FX"
#property link      "https://minagachi.com"
#property version   "1.00"
#property strict
#property indicator_chart_window
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   // 水平線を新規作成
   ObjectCreate(0, "testline", OBJ_HLINE, 0, 0, 0);

   // 水平線の色を黄色に設定
   ObjectSetInteger(0, "testline", OBJPROP_COLOR, clrYellow);

   // 水平線の太さを2に設定
   ObjectSetInteger(0, "testline", OBJPROP_WIDTH, 2);

   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[])
{

   // 水平線(testline)を現在のBid価格に移動する
   ObjectMove("testline", 0, 0, Bid);

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

まとめ

今回は水平線を表示するインジケーターの作り方を説明しました。

使ったオブジェクトは水平線でしたが、トレンドラインや四角形など他のオブジェクトでも今回使ったObjectCreate()関数を使って方法でチャートに表示することができます。

さて次のステップでは、このインジケーターを少しだけ改造して、ユーザー用の入力パラメーターを追加します。お茶でも飲んでからどうぞ。

コメント

この記事へのコメント(6 件)

  • 水平さんより

    はじめまして。自分で「水平線」のインジケーターが作れないかネットで検索していたところ、こちらのサイトにたどり着きました。(とはいっても、インジケーター作成は全くの素人です)

    水平線のプログラム関連記事でしたので、参考になりました。

    チャートに水平線をたくさん引いていると、チャートが見づらくなってしまうので、右側に短く5センチくらい表示するようなインジケーターを作るやり方はないでしょうか。
    色や太さ、線の種類を変えられて、MAX200本くらい線が引ける仕様を考えています。
    もし、可能でしたら、それに関する記事を書いていただけるとありがたいです。

  • 管理人ですさんより

    水平さんへ
    コメントありがとうございます。できるだけご希望に近い記事を書きたいと思いますので、1つ教えていただけますか。
    Q.「右側に5センチ」というのは、「チャートの右端に5センチ分の水平線を引く」ということでしょうか。それとも例えばロウソクの高値など「特定の位置から5センチの水平線を引く」ということでしょうか。

  • 水平さんより

    「チャートの右端に5センチ分の水平線を引く」という意味です。通常、上下いろいろな価格に引く水平線が、チャートの横幅左右いっぱいに広がることなく、右側だけに収まっているというイメージです。5センチが3~4センチでもかまいません。
    線を途中の長さで切ることが難しければ、価格の部分と線の部分の色を別々に指定できるようにして、線の部分の色を「none」にして価格の部分だけ色を残す(線は全く見えなくなる)というのでも、用は足りるのかもしれませんが、プログラムについては詳しくないため、どういうやり方が現実的でやさしいのか、わかっていません。
    わかりづらくて、どうもすみません。

  • 管理人ですさんより

    水平さんへ
    チャートの右端という意味ですね。わかりました。MT4の水平線は、ラインの色をNoneにして価格表示だけ色を残すということができないので、トレンドラインとテキストラベルを使って水平線と似た機能を実現することになります。
    シンプルなプログラム例を作りますのでまた出来たらここでお知らせしますね。
    【追記】この記事に書いておきました⇒MQL チャートの右端に短い水平線を引く方法

  • りっちゃんさんより

    はじめましてこんばんは。
    MT5でゴールデンクロスデッドクロス時にアラート届くようにカスタムインジケーターを作りたいのですが、難しいですかね...?素人でこれから勉強して作りたいなと考えているのですがどうでしょうか...

  • 管理人ですさんより

    りっちゃんさんへ
    こんばんは。コメントありがとうございます。
    私はもっぱらMT4で作っているので、MT5の場合については答えられません。ごめんなさい。(一般的にはMT5の方がMT4よりもプログラミングが難しいと言われています。MT5はコードの書き方がやや煩雑なためです。)
    もしMT4で作るのであれば難しいインジではないですよ。まずは見た目や使い勝手にはこだわらず、クロスでアラートさせるだけのシンプルなインジを目指すと良いと思います。移動平均価格を取得するiMAという関数を使うのが簡単だと思います。
    よくわからないことがあれば、聞いていただければできる限りはお答えいたします。