同期型のクロスヘアラインを作ってみようか


まえがき

クロスヘアラインとは何か

言うまでもないかもしれないけど”Crosshair line”っていうのは、


1.クロスヘアラインとは

これですね

これってMT5だと他チャートには同期しないんです

・たとえばさ、

マルチタイムフレーム分析をしてる時とか、
1時間足で見たこのポイントは日足/5分足ではどんな様子かな、、、とか

相関(通貨強弱)分析をしてるときとか、
EURUSDのこの上昇の起点はEURJPYのそれとマッチしてるかな、、、とか

1枚の画面に何枚かのチャートを表示してる場合に便利な場面とか

ほしくなる場面があるわけです。


別に波の形見れば大体わかるし、規則的に時間軸を並べてればぱっと見でわかるけど

それでもね

トキmake it

じゃあ作っていきましょう

これは自分の初めての記事ですし、国語くそ苦手なので構成や文章は悪しからずですが

なおかつ同期型クロスヘアの実装だけならコーディングは簡単ですし、

プログラミングをはじめて1年ちょいの自分でもさらっと書けるし伝えられるという点で


かなり事細かに工程を書き起こしていて、
思い描く動きをそのまま書いて、足りない部分を足したり改めたりするところまで含んでいるためボリューミーになっています

その分この記事は手元にパソコンがなくても開発過程がわかるでしょうし、
開発に慣れていない方にとってはこの先自身で開発するとき躓きにくくなるでしょう

初等者はこうして作るんだなと体感しながら読み進めてみてください


ただし、中途半端に理解している人が勉強がてら読むと
逆にわかりにくさを感じる部分があるかもしれません

細かな解説はないからです(例えば引数について)

これはあえてこうすることで、作成過程の全体像が見えなくなるのを防ぐためです
一回一回細かく確認していると視野が狭くなって今何をしてるのかわからなくなるものです

なぜここはこう書くのか、というのは後回しにして
こんな風にして構築していくという流れがわかるように作っています



それでは、よろしくどうぞ~

※ちなみに今回の環境はiMacのBootCamp上で走らせているWindows10です


作り方

やることリスト

  1. ファイルを作る

  2. 線を描いてみよう(ObjectCreate)

  3. 線を動かしてみよう1(ObjectMove, ChartXYToTimePrice, OnChartEvent)

  4. 線を動かしてみよう2(OnChartEvent::CHART_EVENT_MOUSE_MOVE)

  5. ちょっと寄り道(ObjectSetInteger, ChartSetString)

  6. 他チャートにも同期させよう(ChartFirst, ChartNext)

  7. 全チャートに同期させよう(while)

  8. クロスヘアラインに機能を追加しよう(OnCahrtEvent::CHARTEVENT_MOUSE_MOVE, ObjectFind, ObjectDelete, etc…)



1.ファイルを作る

2-1-1.ナビゲータウィンドウ

まずは”CTRL+D”でナビゲータウインドウを開いて”Indicators”を選択


2-1-2.メニューバー

上の”新規作成”を押して


2-1-3.ソースファイル作成画面1

”カスタムインジケータ”を選択して、次へ


2-1-4.ァイル作成画面2

”名前”が選択されている状態なのでここに

note_crosshair\draw_line

と入力しましょう

※バックスラッシュ”\”は円マーク”¥”に勝手に変わりますんでコピペで大丈夫です

そして、次へ


2-1-5.ァイル作成画面3

次へ


2-1-6.ァイル作成画面4

完了


2-1-7.作成されたソースコードファイル画面

こんな感じの画面になったかと思います

※もしかすると小窓で出てくるので、見づらければ窓を最大化すればこうなります

<ここから余談>

ちなみに背景とかフォントのカラーについては上の
ツール>オプション>カラー
で変えられます

自分はその中の”基本配色”を”Dark”にして
”要素”の”コメント”を”DarkGray”にしています

記事にある画像の画面風景と自分のパソコンの画面風景が違くて気持ち悪い人は一旦合わせていてもいいかもしれません

フォントサイズは使っているパソコン/モニターの解像度によっても変わりますので見やすくなるように設定して


2-1-8.スタイラー

ちなみにメタエディター画面上の真ん中ちょい右にあるブラシみたいなマークを押すと
書かれているコードをきれいに整えてくれるんですが、その設定はこんな感じ

<ここまで余談>

ここまで出来たら一度”F7”キーを押してみましょう


2-1-9.ツールボックスとエラー表示

するとこんな感じに下に出てくると思います

下の”ツールボックス”という窓jは”CTRL+T”で表示と非表示を切り替えられますので


2.線を描いてみよう(ObjectCreate)

じゃあまずコードを書くんだけどその前に、、、

一度MT5に戻ってこのインジケータをチャートに適用させておいてください

作ったインジケータは
ナビゲータウインドウ>指標>note_crosshair
に居ます

それではコード内上部にある

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit() {
//--- indicator buffers mapping

//---
   return(INIT_SUCCEEDED);
}

この中にラインを描画するコードを書き入れます

   ObjectCreate(0, "test", OBJ_VLINE, 0, 0, 0);

これを入れてください


2-2-1.垂直線を描画する記述

ここですよ

これでまた”F7”を押して”F4”を押します

※今後、【実行する】と言ったら「”F7”を押して”F4”を押す」と思ってください


2-2-2.作成中の指標を適用したチャートのオブジェクトリスト

今作っているインジケータを適用しておいたチャートで右クリック

”B”を押すか、”オブジェクトリスト”をクリックして
オブジェクトリスト、要にチャートに挿入されている水平線とか矢印とかの一覧が開きます

その画面の中の右にある”すべて”を押すとこんな風に”test”という名前の
”Vertical Line”(垂直線)が居ると思います

じゃあ水平線も作ってみましょう

   ObjectCreate(0, "test", OBJ_HLINE, 0, 0, 0);

これをさっきの下に追加して実行してみます

そしてオブジェクトリストを開きなおす

すると、、、

2-2-3.水平線を追加するコードを追加

おや?
増えていませんね

これは同じ名前のオブジェクトを追加できないからなんですね

じゃあ名前を変えます

int OnInit() {
//--- indicator buffers mapping
   ObjectCreate(0, "test_v", OBJ_VLINE, 0, 0, 0);
   ObjectCreate(0, "test_h", OBJ_HLINE, 0, 0, 0);
//---
   return(INIT_SUCCEEDED);
}

こんな風にして”V”の方には”_v”、”H”の方には”_h”を書き加えて実行してみると

オブジェクトリストを開きなおした結果


2-2-4.水平線を追加するコードの修正

こんな風になりましたか?

これがクロスヘアラインの種になります

線が見えないのは見えないところに線が居るからです
安心して

3.線を動かしてみよう1(ObjectMove, ChartXYToTimePrice, OnChartEvent)

つぎはちょっと重労働です

まずコード内一番下に新人を雇います

void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam) {

}

”onch”まで打つと候補が二つ出てきますから、そのままEnterを押すと
OnChartEvent→
みたいな感じで矢印が出ます

この状態でTabを押すとバッとなるので

その中に描画した線を移動させるコードを書いていきます

と、その前に先ほど書いた
”test_h”
"test_v"

というのはチャートに追加するラインに与える名前だったんですが

今後も何かする際にはこの名前を指定して指示を送ります

LINEのグループでも指名せずに依頼投げたらだれも反応しないし誰もやってくれてないあるある、あるでしょ
それを指名して強制力をつけるための行為です

これをいちいち書くのはだるいのでコードの初めにネームプレートを作っておきます

コード内の

#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window

これの下に

#define CH_VLINE "crosshair_ver"
#define CH_HLINE "crosshair_hor"

これを追加します

そして、画像2-2-1にあたる場所を

int OnInit() {
//--- indicator buffers mapping
   ObjectCreate(0, CH_VLINE, OBJ_VLINE, 0, 0, 0);
   ObjectCreate(0, CH_HLINE, OBJ_HLINE, 0, 0, 0);
//---
   return(INIT_SUCCEEDED);
}

こんな風に書き換えてあげます

一応この時点で実行してチャートのオブジェクトリストを確認してみると

2-3-1.ネームプレートを与えられたオブジェクト達

こんな具合になっているはずです

それでは作ったネームプレートを使って名指しで場所を移動する指示を出していきます

まずは追加した新人の中に

   ObjectMove(0, CH_VLINE, 0, 0, 0);

これを追加します

これで実行してみると


、、、


nothing happenes


it's ok


新人にもう一つ追加します

   printf("id:%d, lp:%d, dp:%f, sp:%s", id, lparam, dparam, sparam);

これで実行して、

今度はMT5の方でツールボックスを開きます

”CTRL+T”を押して、下にある”エキスパート”というタブを開きます

2-3-2.MT5のツールボックス内エキスパートの画面

この状態でチャートのどっかを左クリックしてみましょう

2-3-3.チャート内をクリックすると出てくるメッセージ

ここで
id:4
lp:281
dp:665.00000
sp:

と書かれています

あなたの画面では”id”以外違う数字が書かれているでしょう

どこをクリックしたか知りませんが、普通は真ん中くらいを押したと思うので
その数字を使ってみましょう

例として上記の数値を使うのでそれを使ってもいいですよ

線を移動させるコードを改めます

   ObjectMove(0, CH_VLINE, 0, 281, 665);

こんな風に書いてみましょう

これで実行してチャート内のどこかを左クリックしてみてください


まだ、

何も起こりませんね


何をしたかというと、さっき出てきた
lpの数値はチャートの左端から右端に向かってどのくらい離れているか
dpの数値はチャートの上端から下端に向かってどのくらい離れているか

を現した数値になっています

要にその位置、座標とも言えますが
クリックしたポイントを移動先の場所に指定してるんですから
そこに”CH_VLINE”というネームプレートを持った垂直線(名前は””crosshair_ver)がひょこっと現れてほしかったわけです

「(名前)は(位置)に移動しなさい」

と私はコードで言いましたから


でも来てくれません

これは簡単に言うと、使っている言葉が違うからです


もろのアメリカ人にもろの日本語で話しても通じませんから

それが通じるようにするため翻訳をしてあげます

移動指示を本人に出す前にこちらの指示をかくためのメモ用紙を用意します

   datetime time;
   double price;
   int win;

我々の指示は
「チャートの左上から、
右に281、下に665だけ離れた場所に移動しなさい」
です。

これを翻訳機を通してメモ用紙に書き込みます

   ChartXYToTimePrice(0, 281, 665, win, time, price);

winは今いる場所(特定の位置ではなく”場”です。一旦無視でおk)

timeとpriceに我々の指示が翻訳された状態で書き込まれて返ってきます


このメモを渡してあげます

   ObjectMove(0, CH_VLINE, 0, time, price);

これなら通じるはずです

全体としてはこんな感じ

void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam) {
   datetime time;
   double price;
   int win;
   ChartXYToTimePrice(0, 281, 665, win, time, price);
   ObjectMove(0, CH_VLINE, 0, time, price);
   printf("id:%d, lp:%d, dp:%f, sp:%s", id, lparam, dparam, sparam);
}

これで実行してみると


2-3-4.帰ってきたドラえもん

現れました

じゃあ水平線に対しても同じことをしてみましょう

垂直線に出した指示の後に続けます

   ObjectMove(0, CH_HLINE, 0, time, price);

これを実行すると


2-3-5.帰ってきたドラえもん(二人目)

十字の線になりましたね

ちなみに先の”lp”と”dp”は、元をたどると”lparam”と”dparam”です


ここで
id:4
lp:281
dp:665.00000
sp:

と書かれています

となっていましたが、この具体的な数値というのは”lparam”と”dparam”が運んできたものなので

産地直送、そのまま指示にしてみると

   ChartXYToTimePrice(0, lparam, dparam, win, time, price);

こうなります

これで実行してチャート内をクリックして回ってみてください


チラついたりカクカクしたりして見えるかもしれませんが
クリックした場所に水平線と垂直線がパッと移動してくるはずです

4.線を動かしてみよう2(OnChartEvent::CHART_EVENT_MOUSE_MOVE)

ここから楽しくなってきますよ

クロスヘアラインというのはチャート上で今マウスカーソルが居る場所を見るためにスラスラと移動するもんです

移動させましょう


まず、線を用意したタイミングで前提を立ててあげます

   ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, true);

これまではクリックしないと気付いてくれなかった彼氏が、動いただけで気づいてくれるようになります

気が利く彼氏

int OnInit() {
//--- indicator buffers mapping
   ObjectCreate(0, CH_VLINE, OBJ_VLINE, 0, 0, 0);
   ObjectCreate(0, CH_HLINE, OBJ_HLINE, 0, 0, 0);
   ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, true);
//---
   return(INIT_SUCCEEDED);
}

こうして実行して、今度はチャート内でマウスカーソルを縦横無尽に動かしてみてください

すると、、、


まだおぼつかないけど、気が利くでしょ

この時、MT5のツールボックスを見てみると


2-4-1.マウスカーソルを動かしたときのメッセージ

さっきと似ていますが”id”が”4”ではなく”10”になっていると思います

マウスを動かしたりクリックして今いる位置を具体的にしてするわけですが、
マウスカーソルの移動は左クリックの十分条件ですから
”id”が”10”のときだけ動いてくれれば十分な働きです

それを指定してあげます

   if(id == 10) {
   }

これで”id”が”10”の時に絞れるので、このときにやってほしいことを書いてあげます

   if(id == 10) {
      datetime time;
      double price;
      int win;
      ChartXYToTimePrice(0, lparam, dparam, win, time, price);
      ObjectMove(0, CH_VLINE, 0, time, price);
      ObjectMove(0, CH_HLINE, 0, time, price);
      printf("id:%d, lp:%d, dp:%f, sp:%s", id, lparam, dparam, sparam);
   }

これで外野が何を言おうともマウスカーソルが動いた時だけ線が移動してくれます

実行してみましょう


まだまだ、カクカクシカジカですが
さっきまではたまに変なところに行くような動きが今はなくなっています


指示して完了されたときにはしっかりと報告が欲しいものです

まだ気が利かないのでそれも伝えてあげましょう

      ChartRedraw();

動いた後にこうしろと伝えます

void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam) {
   if(id == 10) {
      datetime time;
      double price;
      int win;
      ChartXYToTimePrice(0, lparam, dparam, win, time, price);
      ObjectMove(0, CH_VLINE, 0, time, price);
      ObjectMove(0, CH_HLINE, 0, time, price);
      ChartRedraw();
      printf("id:%d, lp:%d, dp:%f, sp:%s", id, lparam, dparam, sparam);
   }
}

これで実行してみると


ちょっとだけついてこれませんが、しっかりマウスの動きに機敏に対応してくれるようになりましたね

調教完了です


5.ちょっと寄り道(ObjectSetInteger, ChartSetString)

人間の欲は底知れぬものですから、、、


理想のパートナーの完全体は見た目もいいものです

彼氏をかっこよくしちゃいましょう


チャートに図形を追加するとき、”線の太さ”とか”線の色”を設定できます
プロパティなんて言いますが

これを追加していきます

まずは垂直線の方から

   ObjectCreate(0, CH_VLINE, OBJ_VLINE, 0, 0, 0);
   ObjectSetInteger(0, CH_VLINE, OBJPROP_WIDTH, 1);
   ObjectSetInteger(0, CH_VLINE, OBJPROP_COLOR, clrWhite);
   ObjectSetInteger(0, CH_VLINE, OBJPROP_STYLE, STYLE_DOT);

三つ見た目要素を追加します

太さはスマートに細め
肌は色白
他にとられたくないので影薄めに

という感じで

これを実行してみると

2-5-1.垂直線のプロパティを編集

おお~!いい感じ

水平線にもやっちゃいましょう

   ObjectCreate(0, CH_HLINE, OBJ_HLINE, 0, 0, 0);
   ObjectSetInteger(0, CH_HLINE, OBJPROP_WIDTH, 1);
   ObjectSetInteger(0, CH_HLINE, OBJPROP_COLOR, clrWhite);
   ObjectSetInteger(0, CH_HLINE, OBJPROP_STYLE, STYLE_DOT);

見た目三銃士を追加して、実行すると


2-5-2.水平線のプロパティを編集

らしくなってきましたね

カーソルにいちいち説明が出てきてうるさいですから黙らせましょう

   ObjectSetString(0, CH_VLINE, OBJPROP_TOOLTIP, "\n");

これで黙らせることができます

   ObjectSetString(0, CH_HLINE, OBJPROP_TOOLTIP, "\n");

二人とも黙らせました

int OnInit() {
//--- indicator buffers mapping
   ObjectCreate(0, CH_VLINE, OBJ_VLINE, 0, 0, 0);
   ObjectSetInteger(0, CH_VLINE, OBJPROP_WIDTH, 1);
   ObjectSetInteger(0, CH_VLINE, OBJPROP_COLOR, clrWhite);
   ObjectSetInteger(0, CH_VLINE, OBJPROP_STYLE, STYLE_DOT);
   ObjectSetString(0, CH_VLINE, OBJPROP_TOOLTIP, "\n");
   ObjectCreate(0, CH_HLINE, OBJ_HLINE, 0, 0, 0);
   ObjectSetInteger(0, CH_HLINE, OBJPROP_WIDTH, 1);
   ObjectSetInteger(0, CH_HLINE, OBJPROP_COLOR, clrWhite);
   ObjectSetInteger(0, CH_HLINE, OBJPROP_STYLE, STYLE_DOT);
   ObjectSetString(0, CH_HLINE, OBJPROP_TOOLTIP, "\n");
   ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, true);
//---
   return(INIT_SUCCEEDED);
}

こんな状態にして実行してみると


ナルシスとな自己主張が静まってさらにいい男になりましたね


ここまでのコードはこんな感じです

//+------------------------------------------------------------------+
//|                                                    draw_line.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#define CH_VLINE "crosshair_ver"
#define CH_HLINE "crosshair_hor"
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit() {
//--- indicator buffers mapping
   ObjectCreate(0, CH_VLINE, OBJ_VLINE, 0, 0, 0);
   ObjectSetInteger(0, CH_VLINE, OBJPROP_WIDTH, 1);
   ObjectSetInteger(0, CH_VLINE, OBJPROP_COLOR, clrWhite);
   ObjectSetInteger(0, CH_VLINE, OBJPROP_STYLE, STYLE_DOT);
   ObjectSetString(0, CH_VLINE, OBJPROP_TOOLTIP, "\n");
   ObjectCreate(0, CH_HLINE, OBJ_HLINE, 0, 0, 0);
   ObjectSetInteger(0, CH_HLINE, OBJPROP_WIDTH, 1);
   ObjectSetInteger(0, CH_HLINE, OBJPROP_COLOR, clrWhite);
   ObjectSetInteger(0, CH_HLINE, OBJPROP_STYLE, STYLE_DOT);
   ObjectSetString(0, CH_HLINE, OBJPROP_TOOLTIP, "\n");
   ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, true);
//---
   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[]) {
//---

//--- return value of prev_calculated for next call
   return(rates_total);
}
//+------------------------------------------------------------------+
void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam) {
   if(id == 10) {
      datetime time;
      double price;
      int win;
      ChartXYToTimePrice(0, lparam, dparam, win, time, price);
      ObjectMove(0, CH_VLINE, 0, time, price);
      ObjectMove(0, CH_HLINE, 0, time, price);
      ChartRedraw();
      printf("id:%d, lp:%d, dp:%f, sp:%s", id, lparam, dparam, sparam);
   }
}
//+------------------------------------------------------------------+


6.他チャートにも同期させよう(ChartFirst, ChartNext)

クラス内に理想の彼氏ができたところで、他クラスでも複製して楽しみましょう

まずは他クラスを生成します


MT5で同じ銘柄・同じ時間軸の新しいチャートを開いて作成中のインジケータを適用
クローンを作ります

まずは新しいチャートでも同様に動くかどうかチェックしてみましょう


問題なく動くでしょうか

動くはずですね


ここからはまた作業が変わってきますので、新しくソースファイルを立ち上げましょう

はじめと同様にして

note_crosshair\line_sync

名前はこんな感じにして新しく作ります

そしたら先ほどのコードを丸っと全部コピペします


”draw_line”の方で”CTRL+A”を押して”CTRL+C”

”line_sync”の方で”CTRL+A”を押して”CTRL+V”


これで丸っとコピペ完了、同じものができましたから実行して
今度はMT5の方で開いている二つのチャートに”line_sync”を適用します

このタイミングで先に適用した”draw_line”は消してしまいましょう


これから他のチャート上のクロスヘアを移動させてあげます

これをするためには、先と同じように今カーソルが居るチャート上の位置を翻訳してあげて
各々のクロスヘアをそこへ移動させます


クラスの人数が違くても”2の川”は”2の川”です

ひとつは3の川まで、もうひとつは5の川まであると
教室内の相対的な位置は違うかもしれませんが2の川は2の川で変わりません


クロスヘアを移動させる際、バラ組やイチゴ組といったクラスの名前指定します

まずは自分のクラス、それは”0”です

これまで”0”と書いてきました


他クラスも渡してあげましょう

自分と他クラスをすべて調べるためにクラス名を持ってきます


まずはこのクラス、次はこのクラス、、、

クラス名を取っておくためのメモ用紙を用意します

      long chart_first;

まずはこのクラスからやってねとクラス名を書いておきます

      chart_first = ChartFirst();

我々が伝えた位置は相手にとってどの場所なのか、調べてもらいます

      ChartXYToTimePrice(chart_first, lparam, dparam, win, time, price);

できました

      long chart_first;
      chart_first = ChartFirst();
      ChartXYToTimePrice(chart_first, lparam, dparam, win, time, price);

こんな風に並べてあげて

      ObjectMove(chart_first, CH_VLINE, 0, time, price);
      ObjectMove(chart_first, CH_HLINE, 0, time, price);

こんな風に指示して実行してあげると

特にこれまでと変わりませんね

相変わらずクロスヘアは片方のチャートで動き回ります
ただ、片方だけ他方のクロスヘアも動かすでしょう

じゃあ次のクラスです
下に続けて

      long chart_next;

まずは次のクラスを書くためのメモ用紙

      chart_next = ChartNext(chart_first);

初めのクラスの隣にはどのクラスがあるか調べてきてもらいます

      ChartXYToTimePrice(chart_next, lparam, dparam, win, time, price);

また更に、我々が伝えた位置はそのクラスにおいてはどの場所なのか、調べてもらいます

      long chart_next;
      chart_next = ChartNext(chart_first);
      ChartXYToTimePrice(chart_next, lparam, dparam, win, time, price);
      ObjectMove(chart_next, CH_VLINE, 0, time, price);
      ObjectMove(chart_next, CH_HLINE, 0, time, price);

こんな風に並べて実行してあげると


他方のチャートはカクカクしますが、二つのチャートでクロスヘアが同期したはずです

他のクラスにいても完了報告してくれるようにしましょう

      ChartRedraw(chart_first);

まずは自分のクラス

      ChartRedraw(chart_next);

隣のクラスも

void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam) {
   if(id == 10) {
      datetime time;
      double price;
      int win;
      long chart_first;
      chart_first = ChartFirst();
      ChartXYToTimePrice(chart_first, lparam, dparam, win, time, price);
      ObjectMove(chart_first, CH_VLINE, 0, time, price);
      ObjectMove(chart_first, CH_HLINE, 0, time, price);
      ChartRedraw(chart_first);
      long chart_next;
      chart_next = ChartNext(chart_first);
      ChartXYToTimePrice(chart_next, lparam, dparam, win, time, price);
      ObjectMove(chart_next, CH_VLINE, 0, time, price);
      ObjectMove(chart_next, CH_HLINE, 0, time, price);
      ChartRedraw(chart_next);
      printf("id:%d, lp:%d, dp:%f, sp:%s", id, lparam, dparam, sparam);
   }
}

全体としてはこんな感じです

これで実行してみると


どうでしょう

完璧に同期して、欲しかった動きをしてくれています


片方のチャートの時間軸を変えてみましょう

今はどちらも1時間足になっていると思うので、
一つはそのまま
もう一つは5分足にしてみましょう

2-6-1.違った時間足でプログラムを実行

おやおや

5分足では左側でも、1時間足ではまだ右のほうにいるはずなのに
二つのチャートの同じくらいの場所に二つのクロスヘアが居ますね


ここから修正していきます

まず、これを書いた時点でひとつ余計なことをしています
我々が指示した場所が今いるクラスのどこにあたるのかを調べて、翻訳させて
そこに移動してねと言いたかったはずなのに

翻訳する際に各クラスに応じた場所を調べてしまっています

これは、
我々が指示した位置が、
ひとつのクラスでは2の川にあたる
もうひとつのクラスでは3の川にあたる
そこにそれぞれ移動してねを伝えてしまっています


そうじゃないですね
我々が指示した位置が、
ひとつのクラスでは2の川にあたる、だから
もうひとつのクラスでも2の川にあたる
そこにそれぞれ移動してねを伝えなければなりません

要に場所を調べるときは自分のクラスに限定します

自分のクラスは”0”でした

だから

      ChartXYToTimePrice(0, lparam, dparam, win, time, price);

こうしてあげましょう


位置は一度調べれば変わることはないので

void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam) {
   if(id == 10) {
      datetime time;
      double price;
      int win;
      long chart_first;
      chart_first = ChartFirst();
      ChartXYToTimePrice(0, lparam, dparam, win, time, price);
      ObjectMove(chart_first, CH_VLINE, 0, time, price);
      ObjectMove(chart_first, CH_HLINE, 0, time, price);
      ChartRedraw(chart_first);
      long chart_next;
      chart_next = ChartNext(chart_first);
      ObjectMove(chart_next, CH_VLINE, 0, time, price);
      ObjectMove(chart_next, CH_HLINE, 0, time, price);
      ChartRedraw(chart_next);
      printf("id:%d, lp:%d, dp:%f, sp:%s, ", id, lparam, dparam, sparam);
   }
}

一度だけ翻訳してそのまま伝えます

これで実行してみると

2-6-2.同じ場所を違ったチャートごとに実行

求めていた形になってくれました


二つのチャートの時間軸をいろんなものに変えてみましょう

また更に、面白くなってきたはずです


同期ができたら、次は全体での統一を図っていきます

7.全チャートに同期させよう(while)

ここまでは、まずクロスヘアを作って
それを他チャートに同期させました

でもまだ完成ではありません。

実用のシーンを考えてみましょう


今回は二つのチャートで同期を確認しました

でも実際に分析する際には、チャートは何枚出しているかわからない
そのたびに隣のクラスを書くためのメモを増やしたり減らしたりしていたらキリがありませんね


幸いにもメモ用紙は使いまわせるようです

そのように書いてみましょう

      long chart;

ここから先は

51,779字 / 18画像

¥ 490

この記事が気に入ったらチップで応援してみませんか?