マルチタイムフレームの移動平均線がクロス(シフトしたMA)したら縦線を挿入するソースコードを教えてください。

glanzwurde  

MQL4を独学で学んできたため、応用ができず困っています。
ネットで調べても、全く出てきません。見つけたと思っても、移動平均線をシフト (表示をずらす) するとシグナルがでません。
ソースコードが非常に難しいのでしょうか?

以下、自作したマルチタイムフレームの移動平均線(階段状)のソースコードですが、
このソースコードに何を加えたら、シフトした移動平均線と交差した時(ローソク足確定)に、縦線が挿入できるかお力添え頂けると助かります。
何卒、宜しくお願い致します。


(例)
5分足チャートに、1時間足のMTFMAを2本表示(Period10を2本でうち1本はShift3(表示をずらす)し、その2本がクロスしたときに縦線を挿入。

//+------------------------------------------------------------------+
//|                                                  MTFMA VLINE.mq4 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property strict
#property indicator_chart_window
#property indicator_buffers 4

//MTFMA 時間足①
input ENUM_TIMEFRAMES TIMEFRAME1 = PERIOD_H1;    //■①時間足
input int PERIOD1 =10;                           // 期間
input int SHIFT1 = 0;                            // シフト
input ENUM_MA_METHOD METHOD1 = MODE_EMA;         // MA種別
input ENUM_APPLIED_PRICE PRICE1 = PRICE_CLOSE;   // 適用価格
input color CLR1 = clrYellow;                    // 色
input ENUM_LINE_STYLE STYLE1 = STYLE_SOLID;      // 線種
input int WIDTH1 = 2;                            // 太さ


//MTFMA 時間足②
input ENUM_TIMEFRAMES TIMEFRAME1_2 = PERIOD_H1;   //■②時間足
input int PERIOD1_2 =10;                          // 期間
input int SHIFT1_2 = 3;                           // シフト
input ENUM_MA_METHOD METHOD1_2 = MODE_EMA;        // MA種別
input ENUM_APPLIED_PRICE PRICE1_2 = PRICE_CLOSE;  // 適用価格
input color CLR1_2 = clrDodgerBlue;               // 色
input ENUM_LINE_STYLE STYLE1_2 = STYLE_SOLID;     // 線種
input int WIDTH1_2 = 2;                           // 太さ


double Buf1MA[],Buf2MA[],UP[], DN[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
SetIndexBuffer(0, Buf1MA);
SetIndexStyle (0, DRAW_LINE, STYLE1, WIDTH1, CLR1); 
SetIndexBuffer(1, Buf2MA);
SetIndexStyle (1, DRAW_LINE, STYLE1_2, WIDTH1_2, CLR1_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[])
  {
//---
//MTF MA①--------------------------------------------------------------------------------------
   if (_Period > TIMEFRAME1 && TIMEFRAME1 != PERIOD_CURRENT) return -1;

   int limit1 = Bars - IndicatorCounted() - 1;
   int min1 = PeriodSeconds(TIMEFRAME1) / PeriodSeconds();
   if (limit1 < min1) limit1 = min1;

   for (int i = limit1; i >= 0; i--)
    {
      int bar = iBarShift(NULL, TIMEFRAME1, Time[i]);
      Buf1MA[i]  = iMA(NULL, TIMEFRAME1, PERIOD1, SHIFT1, METHOD1, PRICE1, bar );
    }

//MTF MA②
    if (_Period > TIMEFRAME1_2 && TIMEFRAME1_2 != PERIOD_CURRENT) return -1;
   int limit1_2 = Bars - IndicatorCounted() - 1;
   int min1_2 = PeriodSeconds(TIMEFRAME1_2) / PeriodSeconds();
   if (limit1_2 < min1_2) limit1_2 = min1_2;
   for (int i = limit1_2; i >= 0; i--)
    {
      int bar = iBarShift(NULL, TIMEFRAME1_2, Time[i]);
      Buf2MA[i]  = iMA(NULL, TIMEFRAME1_2, PERIOD1_2, SHIFT1_2, METHOD1_2, PRICE1_2, bar );
    }
    
/*    
//======================================================================== 
 ※おそらくここにVLINEのソースコードを挿入すると思われますがその記載方法がわかりません。
     if (Buf1MA[i] > Buf2MA[i] && Buf1MA[i + 1] <= Buf2MA[i + 1])
      {
        // クロスしたら上昇(青)の縦線を引くソースコード    ObjectCreate(chart_id,obj_name,OBJ_VLINE,0,Time.....
      } 
      else 
      if (Buf1MA[i] < Buf2MA[i] && Buf1MA[i + 1] >= Buf2MA[i + 1])
      {
         // クロスしたら下降(赤)の縦線を引くソースコード   ObjectCreate(chart_id,obj_name,OBJ_VLINE,0,Time.....
      }
//======================================================================== 
*/
     
//--- 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)
  {
//---
   
  }
//+------------------------------------------------------------------+
Nagisa Unada  

ソースコードの投稿の際はツールバーの (またはAlt+S)を使ってください。

新規でインジケータを作成するときはMetaEditorのツールバーにある「新規作成」をクリックし、ウィザードに従ってデフォルトのフォーマットを作成し、

その形式で作成したものを投稿してください。

Nagisa Unada  
//+------------------------------------------------------------------+
//|                                                  MTFMA VLINE.mq4 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
//#property indicator_chart_window
#property strict
#property indicator_chart_window
#property indicator_buffers 2 
#property indicator_plots   2
//--- plot Buf1MA //
#property indicator_label1  "Buf1MA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrYellow
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2
//--- plot Buf2MA //
#property indicator_label2  "Buf2MA"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrDodgerBlue
#property indicator_style2  STYLE_SOLID
#property indicator_width2  2

//MTFMA 時間足①
input ENUM_TIMEFRAMES TIMEFRAME1 = PERIOD_H1;    //■①時間足
input int PERIOD1 = 10;                          // 期間
input int SHIFT1 = 0;                            // シフト
input ENUM_MA_METHOD METHOD1 = MODE_EMA;         // MA種別
input ENUM_APPLIED_PRICE PRICE1 = PRICE_CLOSE;   // 適用価格
//input color CLR1 = clrYellow;                    // 色
//input ENUM_LINE_STYLE STYLE1 = STYLE_SOLID;      // 線種
//input int WIDTH1 = 2;                            // 太さ


//MTFMA 時間足②
input ENUM_TIMEFRAMES TIMEFRAME1_2 = PERIOD_H1;   //■②時間足
input int PERIOD1_2 = 10;                         // 期間
input int SHIFT1_2 = 3;                           // シフト
input ENUM_MA_METHOD METHOD1_2 = MODE_EMA;        // MA種別
input ENUM_APPLIED_PRICE PRICE1_2 = PRICE_CLOSE;  // 適用価格
//input color CLR1_2 = clrDodgerBlue;               // 色
//input ENUM_LINE_STYLE STYLE1_2 = STYLE_SOLID;     // 線種
//input int WIDTH1_2 = 2;                           // 太さ


double Buf1MA[], Buf2MA[]; //,UP[], DN[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   //--- indicator buffers mapping
   SetIndexBuffer(0, Buf1MA);
   //SetIndexStyle (0, DRAW_LINE, STYLE1, WIDTH1, CLR1);
   SetIndexBuffer(1, Buf2MA);
   //SetIndexStyle (1, DRAW_LINE, STYLE1_2, WIDTH1_2, CLR1_2);

   //---
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   int max = ObjectsTotal() - 1;

   for (int i = max; i >= 0; i--)
   {
      if (StringFind(ObjectName(i), "VL") > -1)
         ObjectDelete(0, ObjectName(i));
   }
}
//+------------------------------------------------------------------+
//| 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[])
{
//---
//MTF MA①--------------------------------------------------------------------------------------
   /*
      if (_Period > TIMEFRAME1 && TIMEFRAME1 != PERIOD_CURRENT) return -1;

      int limit1 = Bars - IndicatorCounted() - 1;
      int min1 = PeriodSeconds(TIMEFRAME1) / PeriodSeconds();
      if (limit1 < min1) limit1 = min1;

      for (int i = limit1; i >= 0; i--)
      {
         int bar = iBarShift(NULL, TIMEFRAME1, Time[i]);
         Buf1MA[i]  = iMA(NULL, TIMEFRAME1, PERIOD1, SHIFT1, METHOD1, PRICE1, bar );
      }

   //MTF MA②
      if (_Period > TIMEFRAME1_2 && TIMEFRAME1_2 != PERIOD_CURRENT) return -1;
      int limit1_2 = Bars - IndicatorCounted() - 1;
      int min1_2 = PeriodSeconds(TIMEFRAME1_2) / PeriodSeconds();
      if (limit1_2 < min1_2) limit1_2 = min1_2;
      for (int i = limit1_2; i >= 0; i--)
      {
         int bar = iBarShift(NULL, TIMEFRAME1_2, Time[i]);
         Buf2MA[i]  = iMA(NULL, TIMEFRAME1_2, PERIOD1_2, SHIFT1_2, METHOD1_2, PRICE1_2, bar );
      }
   */
   if (Period() > TIMEFRAME1 || Period() > TIMEFRAME1_2)
      return(0);
   int i, n, y, limit;

   if (prev_calculated < 0)
      return(-1);
   if (prev_calculated == 0)
      limit = rates_total - MathMax(PERIOD1 * TIMEFRAME1 / Period(), PERIOD1_2 * TIMEFRAME1_2 / Period()); 
   else
      limit = rates_total - prev_calculated + MathMax(TIMEFRAME1, TIMEFRAME1_2) / Period();

   for (i = limit; i >= 0; i--)
   {
      y = iBarShift(NULL, TIMEFRAME1, time[i]);
      n = SHIFT1 * TIMEFRAME1 / Period();

      if (i - n >= 0)
         Buf1MA[i - n] = iMA(NULL, TIMEFRAME1, PERIOD1, 0, METHOD1, PRICE1, y);

      y = iBarShift(NULL, TIMEFRAME1_2, time[i]);
      n = SHIFT1_2 * TIMEFRAME1_2 / Period();

      if (i - n >= 0)
         Buf2MA[i - n] = iMA(NULL, TIMEFRAME1_2, PERIOD1_2, 0, METHOD1_2, PRICE1_2, y);
   }
   /*
   //======================================================================== 
    ※おそらくここにVLINEのソースコードを挿入すると思われますがその記載方法がわかりません。
        if (Buf1MA[i] > Buf2MA[i] && Buf1MA[i + 1] <= Buf2MA[i + 1])
         {
           // クロスしたら上昇(青)の縦線を引くソースコード    ObjectCreate(chart_id,obj_name,OBJ_VLINE,0,Time.....
         }
         else
         if (Buf1MA[i] < Buf2MA[i] && Buf1MA[i + 1] >= Buf2MA[i + 1])
         {
            // クロスしたら下降(赤)の縦線を引くソースコード   ObjectCreate(chart_id,obj_name,OBJ_VLINE,0,Time.....
         }
   //========================================================================
   */
   for (i = limit; i >= 0; i--)
   {
      string obj_name = "VL" + IntegerToString((int)time[i]);

      if (Buf1MA[i] > Buf2MA[i] && Buf1MA[i + 1] < Buf2MA[i + 1])
      {
         if (ObjectFind(0, obj_name) == -1)
         {
            ObjectCreate(0, obj_name, OBJ_VLINE, 0, time[i], close[i]);
            ObjectSet(obj_name, OBJPROP_STYLE, STYLE_SOLID);
            ObjectSet(obj_name, OBJPROP_COLOR, clrBlue);
            ObjectSet(obj_name, OBJPROP_WIDTH, 2);
         }
      }

      if (Buf1MA[i] < Buf2MA[i] && Buf1MA[i + 1] > Buf2MA[i + 1])
      {
         if (ObjectFind(0, obj_name) == -1)
         {
            ObjectCreate(0, obj_name, OBJ_VLINE, 0, time[i], close[i]);
            ObjectSet(obj_name, OBJPROP_STYLE, STYLE_SOLID);
            ObjectSet(obj_name, OBJPROP_COLOR, clrRed);
            ObjectSet(obj_name, OBJPROP_WIDTH, 2);
         }
      }
   }

//--- 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)
  {
//---

  }
//+------------------------------------------------------------------+
*/

黄色は修正または追加した部分。

全部で3時間ぐらいかかりました。私も暇ではないので今後はできる限り自分で作成し、どうしても分からない部分だけ質問してください。

デバッグの方法は知ってますか? https://www.metatrader5.com/ja/metaeditor/help/development/debug

期待どうりに動かない時、エラーが出るときはデバッガーでトレースすれば大抵のことは解決します。

コードのデバッグ - プログラムの開発 - MetaEditorヘルプ
  • www.metatrader5.com
MetaEditorには、プログラムの実行ステップ (個々の関数ごと) をチェックできる組み込みデバッガがあります。 コードにブレークポイントを配置します。 これらはプログラムの実行を一時ストップする場所です。 次に、通常のチャートまたは ストラテジーテスター でプログラムを起動します...
glanzwurde  

ご返信いただきましてありがとうございます!!
しかも、コンパイルできる状態まで仕上げていただきまして、感激しております!

投稿ルールも解らず、再三指摘いただいているにも関わらず
私のようなものに、ここまで丁寧にご対応頂けることに、言葉にできないほどの感謝の想いでいっぱいです。
改めまして感謝申し上げます。ありがとうござます!

投稿する際に、Nagisa Unadaさんが仰るように、漠然と質問するその姿勢が失礼だとは感じていましたので
少しでも、これまでの努力をご理解いただこうと思い、自身が作成したソースコードを記載したものの
これだけ長い訂正のソースコードが必要であったことからして、結果的にかなり失礼な質問の仕方であり
お手間おかけしたこととお察しします。文末で大変失礼ながら、お詫び申し上げます。


本当にありがとうございました!
心より感謝申し上げます。

glanzwurde  

お伝えし忘れておりました。
デバッグ機能をご教示いただきましてありがとうございます。
知りませんでした。以後、利用させていただきます。

何から何まで本当にありがとうございました!

glanzwurde  

利用して数時間が経過します。
チャートにインジケーターを適用すると、クロスした通貨ペアと同タイミングで
クロスもしていないほかの通貨ペアのチャートほぼ全てにシグナル(縦線)が挿入されます。
※なぜかEURAUDやGBPAUDだけは表示されません。

obj_name に原因があるかと思い、下記のとおり「+ Symbol()」を追記しましたが変化ありません。

「string obj_name = "VL" + Symbol() + IntegerToString((int)time[i]);」


はやり、それだけ難しいソースコードであると理解しました。
もし、対応策がございましたらご教示いただきたいところではありますが…
ここまでしていただいたら、それもなかなか難しいのでしょうか?
もし可能であればご対応いただけると助かります。

素人で申し訳ございません。



Nagisa Unada  

ChartIDに現在は0を設定していますが、個別のIDを設定したら解決しませんか?

ところで、#3に私のアイコンとリンクがありますが、関係ないので削除してください。

右下にカーソルを置けば「 編集 (edit) 」が出ます。

glanzwurde  

早速にご回答いただきましてありがとうございます。
ChartIDや obj_nameの問題かと思いましたが、変更してもなにも変わりません。
インジケーターを適用したあと、最初に確定する新しい足でシグナルの縦線(赤色)がでてきたり
全く、クロスしていないところで縦線(赤色)のシグナルが出てきたりと挙動がおかしいです。
同じチャートに、自分で作成したMTFMAがあったため、干渉を防ぐ意味でチャートから消したうえで
今回、制作いただいたインジケーターのみを適用しても、思うように作動していません。
経過観察の時間を早めるために、1分足にM5(5)とM5(5)のシフト3を適用して確認していますが
今夜、一日かけて原因を探してみたいと思いますが、もはや、素人の私では対応できないレベルで難しいです。

やはり、ネットでどれだけ探してもヒットしない「シフトクロスでのシグナル(縦線)」は
不可能なのかもしれないと感じておりますが、
もしも、もう少しだけ、私のような素人にお付き合いいただけるのであればお力添え頂ければ本当に助かります。


ちなみに、"Buf2MA" のラインで、デフォルトの設定色がclrDodgerBlue のラインですが、更新されず表示が止まっています。
黄色の線は、ローソク足確定とともに更新され、線が継続して描写されています。

glanzwurde  
何度も恐縮です。

バックテストを行うと、 やはり、"Buf2MA" のラインのデフォルトの設定色がclrDodgerBlue のラインが
更新されず表示が止まっています。

お忙しいところ、本当に恐縮です。
できましたら、もう少しだけお付き合いいただきまして原因をご教示いただけますと助かります。
勝手なお願いばかりを申し上げております失礼をお許しください。

何卒、ご理解いただきまして宜しくお願い申し上げます。
Nagisa Unada  

バーナンバーを i - n とした場合起動時以降のデータがリセットされてしまうようです。

エラーも何も出ないので気づきませんでした。

結局次のとおり元のままでよかったみたいです。

 for (i = limit; i >= 0; i--)
 {
      y = iBarShift(NULL, TIMEFRAME1, time[i]);
      Buf1MA[i] = iMA(NULL, TIMEFRAME1, PERIOD1, SHIFT1, METHOD1, PRICE1, y);

      y = iBarShift(NULL, TIMEFRAME1_2, time[i]);
      Buf2MA[i] = iMA(NULL, TIMEFRAME1_2, PERIOD1_2, SHIFT1_2, METHOD1_2, PRICE1_2, y);
 }

int i, n, y, limit; の n を削除。

glanzwurde  
Nagisa Unada #:

バーナンバーを i - n とした場合起動時以降のデータがリセットされてしまうようです。

エラーも何も出ないので気づきませんでした。

結局次のとおり元のままでよかったみたいです。

int i, n, y, limit; の n を削除。

ご返信が遅くなりまして申し訳ありません。
この度は、本当にありがとうございます。何度でも申し上げますが
こんなに親切に対応頂けることに感謝感激しております。

実は、ご返信できなかったのも、クロスした際のライン描写の挙動がやはり不安定なためでした。
結論的は、そもそもの問題点は、私がベースで作成した階段状のMTFのソースコードにありました。
つまり、1時間足は5分足の12本であり、その間にMTFがクロスしてもシグナルがでているため
「階段状ではないスムーズな線と線がクロスしたときにシグナル」というソースコートが
大前提で必要だった点です。

今回、私が投稿した目的は、縦ラインの挿入方法だったため、それについては大変的確なご回答を頂けたにも関わらず
このような基本的でかつ、重要な大前提に全く気付いていませんでした。お恥ずかしい限りです…(なさけないです…)。
ここ数日、ほぼ寝ずにMTFの階段状の線をスムーズな線へと変更する作業を続けていますが全くうまくいきません (ダブルで情けないです…苦笑)。


これ以上、お願いするとお叱りを受けそうですが
下記URLのような、スムーズな線を描写し、その線と線がクロスした時にシグナルを出せるようなソースコードにするための訂正すべき箇所を
もしもご教示いただけるならば幸いです。
何度もお聞きする厚かましい私の対応に苦慮されることと思いますので、私自身で解決しろと言われても当然です。
ここまで親切にご対応いただきまして点について、再度、心より感謝しています。重ね重ねお礼申し上げます。


(しがないDJがFX専業トレーダーになるまで)
https://dj-trader.net/fx/custom_indicator/10145


【MT4 / MT5】滑らかに表示できるマルチタイムフレーム移動平均線(バージョンアップ 2022.11.26)
【MT4 / MT5】滑らかに表示できるマルチタイムフレーム移動平均線(バージョンアップ 2022.11.26)
  • 2022.02.17
  • dj-trader.net
対象の時間足 表示させたい上位時間足を指定します。現在足にすると通常の移動平均線として使用できます。 ※ 5分足以下に月足を表示させると MT4 / MT5 の処理が遅くなります。例えば1分足に月足の期間 30 を表示すると、月末に向かって最大 1,296,000 本のバーを対象に毎ティック計算することになります。このインジケーターはバー数制限をしても、その本数以上を必要とする時間足を指定すると最低1本のラインは表示しようとします。ただし、オプションで指定するチャートの最大バー数を超えて表示することはできません。 期間 計算する期間(バーの本数)を指定します。 表示移動(シフト) 移動平均線の表示位置を左右にずらせます。 移動平均の種別 「単純移動平均(Simple Moving...
理由: