MT4用チャート同時スクロール(同期)インジを作ろう!

ご連絡・雑記
スポンサーリンク

ネタ探しにゴゴジャンから送られてきたメールを見ていたらこんなものがありました。

SyncSyncSync

スクロールの同期とラインコピーで5,500円です。1,000本以上売れていますが、高いですね‥。

レビューもコミュニティも2021年頃に止まっているので最近は売れていないのかも。

ゴゴジャンはなぜこれを選んだのか?こんなのを紹介するなら私が販売している商品を売ってくれ。

機能を詰め込んでいる代わりに重い、不具合が多いようです。

ラインやオブジェクトを他のチャート(時間軸)にコピーするだけなら無料のツールがいくらでもあります。

私も以前、「ScalTradeAssistProとラインコピーツールが干渉して同時利用できない」という報告を頂いて、干渉しないコピーツールを作ったことがあります。欲しい方は下記リンクからダウンロードしてください。(ラインコピーツール単体で使用可能です)

無料ラインコピーインジケーター「LineCopy」の公開【ScalTradeAssistProと併用可能】

スクロールを同期させたい

スクロールを同期する無料ツールもありますが、オアンダのページに作り方が書いてあったので、今回はそれを見て作ってみました。

チャート操作関数を使って全チャートを一括操作する方法

ここにあるソースコードをコピー&ペーストしてコンパイルしてあげればOKです。

SyncDemoの作成

1.ソースコードを範囲選択してコピー(Ctrl+C)

2.MT4を起動して、メニューの「ツール>メタエディター」でメタエディタを起動(F4キーで起動できます)

3.メニューの「ファイル>新規作成」で表示される、MQLウィザードでカスタムインディケーターを選択して「次へ」

4.名前のIndicators\の後ろに「SyncDemo」と入力して「次へ」(著作権者、リンク、パラメーターは不要です)

5.後は「次へ」を押していって「完了」します。

6.開いたSyncDemo.mq4を全選択(Ctrl+A)した後、ペースト(Ctrl+V)します。(1でコピーした内容で上書きします)

7.メニューの「ファイル>コンパイル」またはF7キーでコンパイルします。エラーがなければ以下のメッセージが下部に表示されているはずです。(表示されていなければ「ツールボックス」を表示してください。メニューの「表示>ツールボックス(Ctrl+T)」で表示/非表示が切り替えられます。)

これで完成です。正しく出来ていればMT4のインディケーターに「SyncDemo」が表示されます。

SyncDemoの動作確認

SyncDemoを設置したチャートでクリックしながらチャートをスクロールさせると別のチャートも動くようになりました。

私的には「クリックしながら」という動作が不要(スクロールするだけで反応してほしい)と思ったので、ちょっと改造します。

OnChartEventにあるCHARTEVENT_CLICKが「クリックしながら」という操作ですので、これをコメントアウト(頭に//を付与)しました。

//if (id == CHARTEVENT_CLICK) {

if文に対応する最後から2番目のブラケットもコメントアウトします。

//}

先ほどと同様に「コンパイル」してエラーがなければOKです。これでマウスクリック無しで同期するようになりました。

どちらの動作が良いかは好みによると思います。(普段は同期したくない、同期させて見たい場合だけ使用したい、という場合にはマウスクリックの方が便利でしょう。)

以下は修正したソースコード全文です。

//+------------------------------------------------------------------+
//|                                                     SyncDemo.mq4 |
//|                        Copyright 2021, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_chart_window
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   
//---
   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);
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
   if (id == CHARTEVENT_CHART_CHANGE) {
      int scale = (int)ChartGetInteger(0, CHART_SCALE);

      long chart_id = ChartFirst();
      while (true) {
         if (chart_id != ChartID()) {
            if (ChartGetInteger(chart_id, CHART_SCALE) != scale) {
               ChartSetInteger(chart_id, CHART_SCALE, scale);
            }
            ChartRedraw(chart_id);
         }
         
         chart_id = ChartNext(chart_id);
         if (chart_id < 0) break;
      }   
   }
   
   //if (id == CHARTEVENT_CLICK) {
      bool auto = (bool)ChartGetInteger(0, CHART_AUTOSCROLL);
      int barR = int(ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR) - ChartGetInteger(0, CHART_WIDTH_IN_BARS));
      if (barR < 0) barR = 0;
      datetime timeR = Time[barR];

      long chart_id = ChartFirst();
      while (true) {
         if (chart_id != ChartID() && !auto) {
            ChartSetInteger(chart_id, CHART_AUTOSCROLL, false);
            int bar = iBarShift(ChartSymbol(chart_id), ChartPeriod(chart_id), timeR);
            
            int shift = 0;
            if (ChartGetInteger(chart_id, CHART_SHIFT)) {
               shift = int(ChartGetInteger(chart_id, CHART_WIDTH_IN_BARS) * ChartGetDouble(chart_id, CHART_SHIFT_SIZE) / 100);
            }
            
            ChartNavigate(chart_id, CHART_END, -bar - 2 - shift);
            ChartRedraw(chart_id);  
         } 
         chart_id = ChartNext(chart_id);
         if (chart_id < 0) break;
      }   
   //}
}
//+------------------------------------------------------------------+

修正箇所が良くわからなかった方はこちらをコピーしてお使いください。

コメント

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