MetaTrader4では、水平線やトレンドラインを引く機能が基本機能として備わっています。
線の見た目は水平線、垂直線、トレンドラインなど種類ごとに色・太さ・線種を設定することができるのですが、5分足で線を引いたときは細い青の実線、15分足では太い赤い破線・・・といったように自動で見た目がかわるような機能は残念ながらありません。
そこで、表示しているチャートの時間足ごとに、線の見た目が自動で変えられるインジケーターを作ってみたいと思います。
このインジケーター開発のポイントは、オブジェクト(水平線など)が作成された直後のタイミングを捕まえて処理をする、OnChartEventとCHARTEVENT_OBJECT_CREATEイベントハンドラです。これらの説明をしながら、インジケーター作成のポイントを紹介していきます。
これも妻から要望があり、開発にトライしてみました。
インジケーターの仕様
今回もざっくりと大まかな仕様を決めてからコーディングに取りかかりましょう。
はじめに全体のプランを立てれば、コーディング中に迷って仕様がふらふらすることが少なくなります。
- MetaTrader4デフォルトの9つの時間足ごとに線の色を変えられるようにする
- 対象は、ひとまず水平線だけとする
- 色、太さ、線種の3つを「パラメーターの入力」ダイアログで設定できるようにする
かなり大雑把ですが、ひとまずこれくらい決めていればコーディングを始められそうです。
冒頭でも述べた通り、今回のプログラムのキモは「ユーザーが水平線を引いた直後の処理を捕まえる」ことにあります。
ユーザー設定項目
「パラメーターの入力」ダイアログで、各時間足で色・太さ・線種の3つを設定できるようにしましょう。
1 2 3 |
input color M1_Color = clrRed; input int M1_Width = 2; input ENUM_LINE_STYLE M1_Style = STYLE_SOLID; |
上記のコード例では、1分足の水平線を色:赤、太さ:2、線種:実線にするようデフォルト設定しておきます。
ここでは割愛しますが、9つの時間足分同様に設定しておきます。
OnChartEvent関数
チャート上でユーザーがマウスを動かしたり、クリックしたり、キーボードを操作したりするとOnChartEvent関数が呼び出されます。
今回作成するインジケーターで補足したい「水平線を引く」というイベントも、OnCharEventで捕まえることができます。
1 2 3 4 5 |
void OnChartEvent(const int id, // Event ID const long& lparam, // Parameter of type long event const double& dparam, // Parameter of type double event const string& sparam // Parameter of type string events ); |
OnChartEventは4つの引数受け取り、戻り値はありません。
1つめの引数idはイベントのIDですが、2〜5つめの引数は変数名を見ても何を意味しているかわかりません。
答えを先にいってしまうと、いろいろなイベント(マウスを動かした、キーを押した)が呼び出されるため、イベントの種類に特化した型・変数名をつけることができなかったからです。
例えば、マウスを動かした場合は、lparamにはマウスのX座標が設定されていますが、キーを押した場合は、lparamにはキーコード(どのキーを押したか)が設定されます。
そのため、型+パラメータという意味で第2引数から第4引数は、LONG型のパラメータ→lparam、DOUBLE型のパラメータ→dparam、STRING型のパラメータ→sparamとなっています。
(しかもパラメータの中身をいじれるように、参照渡しという念の入れようです!)
さて、水平線を引いた場合は、どんな引数が設定されて呼び出されるのでしょうか?
引数名 | パラメーター |
id | CHARTEVENT_OBJECT_CREATE |
lparam | – |
dparam | – |
sparam | オブジェクトの名称 |
idには、CHARTEVENT_OBJECT_CREATE、sparamにはまさに今作成されたオブジェクトの名称が設定されます。lparamとdparamは使われません。
したがって、この2つのパラメーターを駆使して、1分足が表示されているとき、かつ、水平線が引かれたときに線のプロパティを設定するようコードを書いてみましょう。
実際のコード
上で書いた条件をそのままストレートにコードへ落とすと以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { if (id == CHARTEVENT_OBJECT_CREATE) { if (ObjectType(sparam) == OBJ_HLINE) { if (Period() == PERIOD_M1) { ObjectSet(sparam, OBJPROP_COLOR, M1_Color); ObjectSet(sparam, OBJPROP_WIDTH, M1_Width); ObjectSet(sparam, OBJPROP_STYLE, M1_STYLE); } } } } |
7行目は、ObjectType関数で、作成されたオブジェクトの種類(水平線かどうか)を判定しています。
8行目は、Period関数で、現在表示されているチャートの時間足(1分かどうか)を判定しています。
9行目〜11行目で、色、太さ、線種を設定しています。
初期化
今回のインジケーターでは、特に初期化する必要がなさそうなのですが、1つ落とし穴があります。
CHARTEVENT_OBJECT_CREATEの解説に以下のように記載されています。
Event of graphical object creation (if CHART_EVENT_OBJECT_CREATE=true is set for the chart)
【意訳】画像オブジェクト作成イベントを捕まえたければ、CHART_EVENT_OBJECT_CREATEをtrueに設定しなさい
なかなか見落としそうな感じの注釈です。
ChartSetInteger関数で以下のようにtrueを設定すれば、オブジェクト作成時に無事イベントハンドラが呼び出されます。
1 |
ChartSetInteger(0,CHART_EVENT_OBJECT_CREATE,true); |
さいごに
いかがでしたでしょうか。
時間足ごとに水平線の色を変えるコア部分のプログラミングは、そんなに難しくなかったのではないでしょうか。
今回はコードを掲載しませんでしたが、9つの時間足それぞれパラメータを変えられようにする部分のほうが、単純にコード量が多くて大変だと思います。
また、水平線だけでなくトレンドラインや垂直線などにも拡張できそうです。
がんばってご自身でコーディングしてみてください。
質問やご要望があれば、コメント欄やお問合せでご連絡ください。
初めまして。
インジケータを探していたら、こちらのブログに辿り着きました。
時間足ごとに色を変えるインジケータを使用したいのですが、私はプログラミングの知識がなく、コピペ等で少しチャレンジしてみたのですが、上手くいきませんでした。
良ければ作成方法などをご教授頂けないでしょうか?
よろしくお願いします。