Questions from Beginners MQL5 MT5 MetaTrader 5 - page 786

 

Please fix the code, if you don't mind.

I wrote code for scrolling open charts, but I got stuck with synchronization, I can't synchronize by time of first visible bars, it doesn't take into account missed bars - it scrolls by all of them, not taking into account time


//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_plots 0


long     mass_id[];
datetime Time[1];
long     MassID;
string   MassSY;
int      Shift=0;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTimer()
  {
   int  _CHART_WIDTH_IN_BARS = (int)ChartGetInteger(0, CHART_WIDTH_IN_BARS);
   int  BarTimeVisible = iBarShift(Symbol(), 0, TIME(_CHART_WIDTH_IN_BARS));//Print(TIME(_CHART_WIDTH_IN_BARS));

   long ID=ArraySize(mass_id);
// Запомним время
   for(int i=0; i<ID; i++)
     {
      MassID = mass_id[i];
      Shift = BarTimeVisible - (int)ChartGetInteger(MassID, CHART_VISIBLE_BARS);
      if(GlobalVariableGet("FirstVisibleBar") != TIME((int)ChartGetInteger(MassID, CHART_FIRST_VISIBLE_BAR) + Shift))
        {
         GlobalVariableSet("FirstVisibleBar", TIME((int)ChartGetInteger(MassID, CHART_FIRST_VISIBLE_BAR) + Shift));
         break;
        }
     }

// Прокрутка графиков
   for(int i=0; i<ID; i++)
     {
      MassID = mass_id[i];
      MassSY = ChartSymbol(MassID);
      Shift = (BarTimeVisible -  (int)ChartGetInteger(MassID, CHART_VISIBLE_BARS));
      if(GlobalVariableGet("FirstVisibleBar") != TIME((int)ChartGetInteger(MassID, CHART_FIRST_VISIBLE_BAR) + Shift))
        {
         ChartNavigate(MassID, CHART_END, (_CHART_WIDTH_IN_BARS - iBarShift(Symbol(), 0, (datetime)GlobalVariableGet("FirstVisibleBar"))) - 2);
        }
     }
  }
  
  
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   ChartGetIDList(mass_id);
   EventSetMillisecondTimer(50);
//---
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
int ChartGetIDList(long &aList[])
  {
   int i=0;
   long handle=0;
   long chartID=ChartNext(handle);
   while(chartID!=-1)
     {
      handle=chartID;
      i++;
      ArrayResize(aList,i);
      aList[i-1]=chartID;
      chartID=ChartNext(handle);
     }
   return(i);
  }

//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
int iBarShift(string symbol,ENUM_TIMEFRAMES timeframe,datetime time,bool exact=false)
  {
   datetime LastBAR;
   if(!SeriesInfoInteger(symbol,timeframe,SERIES_LASTBAR_DATE,LastBAR))
     {
      datetime opentimelastbar[1];
      if(CopyTime(symbol,timeframe,0,1,opentimelastbar)==1)
         LastBAR=opentimelastbar[0];
      else
         return(-1);
     }
//--- if time > LastBar we always return 0
   if(time>LastBAR)
      return(0);
//---
   int shift=Bars(symbol,timeframe,time,LastBAR);
   datetime checkcandle[1];

   if(CopyTime(symbol,timeframe,time,1,checkcandle)==1)
     {
      if(checkcandle[0]==time)
         return(shift-1);
      else if(exact && time>checkcandle[0]+PeriodSeconds(timeframe))
         return(-1);
      else
         return(shift);
     }
   return(-1);
  }

//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
datetime TIME(int index=0)
  {
   return(CopyTime(Symbol(),PERIOD_CURRENT,index,1,Time)?Time[0]:WRONG_VALUE);
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
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);
  }
 
Vitaly Muzichenko:

Please fix the code, if you don't mind.

I wrote code for scrolling through open charts, but I got stuck with synchronization, I cannot synchronize by time of first visible bars, it does not take into account missed bars - it scrolls through all of them, not considering time

What should I do? It would probably be easier to write from scratch than to fix it.

SyncChart
SyncChart
  • votes: 12
  • 2016.09.16
  • o_o
  • www.mql5.com
Синхронизация показываемых баров на всех открытых в терминале графиках. Синхронизация графиков происходит по таймеру. Без DLL! Дополнительные возможности: опция синхронизации вертикальных...
 
fxsaber:

What should I do? It would probably be easier to write from scratch than to edit.

Maybe from scratch, but it would have to be time-synchronised somehow


 
Vitaly Muzichenko:

Maybe from scratch, if only there was a time synchronisation

The video is very straightforward. It should be easy to solve. When I'm free, I'll post my version.

 
fxsaber:

The video makes it all very clear. The solution should be succinct. When I'm free, I'll post my version.

Except I didn't stress that scrolling works from any chart, not just the main one.

Thank you!

 
Comments not related to this topic have been moved to "Questions from MQL4 MT4 MetaTrader 4 beginners".
 
Vitaly Muzichenko:

Except I didn't stress that scrolling works from any chart, not just the main one.

// MQL4&5-code
// Синхронизация всех чартов по правому времени

sinput int TimerInterval = 1; // Интервал обновления в миллисекундах

// Отрубает на всех чартах автоскролл и сдвиг
bool AutoShiftOff( void )
{
  long handle = ChartFirst();

  while (handle != INVALID_HANDLE)
  {
    ChartSetInteger(handle, CHART_SHIFT, false);
    ChartSetInteger(handle, CHART_AUTOSCROLL, false);

    handle = ChartNext(handle);
  }

  return(true);
}

const bool Init = EventSetMillisecondTimer(TimerInterval) && AutoShiftOff();

void OnTimer()
{
  SyncCharts();
}

// Возвращает true, если нет бара с таким временем ("дырка")
bool IsHole( const string Symb, const ENUM_TIMEFRAMES TimeFrame, const datetime time )
{
  return(Bars(Symb, TimeFrame, SeriesInfoInteger(_Symbol, PERIOD_CURRENT, SERIES_FIRSTDATE), time) +
         Bars(Symb, TimeFrame, time, SeriesInfoInteger(_Symbol, PERIOD_CURRENT, SERIES_LASTBAR_DATE)) ==
         SeriesInfoInteger(_Symbol, PERIOD_CURRENT, SERIES_BARS_COUNT));
}

// Возвращает бар по времени
int iBarShift( const string Symb, const ENUM_TIMEFRAMES TimeFrame, datetime time )
{
  int Res = -1;
  datetime LastBar;

  time -= time % PeriodSeconds(TimeFrame);

  if (SeriesInfoInteger(Symb, TimeFrame, SERIES_LASTBAR_DATE, LastBar))
  {
    if (time > LastBar)
      Res = (int)((LastBar - time) / PeriodSeconds(TimeFrame));
    else
    {
      const int Shift = Bars(Symb, TimeFrame, time, LastBar);

      if (Shift > 0)
      {
        Res = Shift - 1;

        if (IsHole(Symb, TimeFrame, time))
          Res++;
      }
    }
  }

  return(Res);
}

// Возвращает время по бару
datetime iBarShift( const string Symb, const ENUM_TIMEFRAMES TimeFrame = PERIOD_CURRENT, const int Pos = 0 )
{
  datetime Tmp[1];

  CopyTime(Symb, TimeFrame, (Pos < 0) ? 0 : Pos, 1, Tmp);

  return(Tmp[0] - ((Pos < 0) ? Pos * PeriodSeconds(TimeFrame) : 0));
}

// Возвращает правый бар чарта
int ChartBarRight( const long chartID = 0 )
{
  return((int)(ChartGetInteger(chartID, CHART_FIRST_VISIBLE_BAR) - ChartGetInteger(chartID, CHART_WIDTH_IN_BARS) + 1));
}

// Возвращает правое время чарта
datetime GetChartTimeRight( const long chartID = 0 )
{
  return(iBarShift(ChartSymbol(chartID), ChartPeriod(chartID), ChartBarRight(chartID)));
}

// Устанавливает правое время чарта, возвращает установленное время
datetime SetChartTimeRight( datetime time, const long chartID = 0, const ulong MaxTime = 1 e5 )
{
  const string Symb = ChartSymbol(chartID);
  const ENUM_TIMEFRAMES period = ChartPeriod(chartID);

  const int Pos = iBarShift(Symb, period, time);
  const int PrevPos = ChartBarRight(chartID);

  if ((Pos != PrevPos) && ChartNavigate(chartID, CHART_END, -1 - Pos))
  {
    const ulong StartTime = GetMicrosecondCount();
    int NewPos = ChartBarRight(chartID);

    while (((NewPos != Pos)|| (NewPos == PrevPos)) && (GetMicrosecondCount() - StartTime < MaxTime) && !IsStopped())
    {
      Sleep(0);
      
      NewPos = ChartBarRight(chartID);
    }
  }

  return(GetChartTimeRight(chartID));
}

// Добавление элемента в конец произвольного массива
template <typename T>
void AddArrayElement( T &Array[], const T Value, const int Reserve = 0 )
{
  const int Size = ArraySize(Array);

  ArrayResize(Array, Size + 1, Reserve);

  Array[Size] = Value;
}

// Получает время правого бара каждого чарта
int GetChartsTimeRight( datetime &RightTime[], long &Handles[] )
{
  ArrayFree(RightTime);
  ArrayFree(Handles);

  long handle = ChartFirst();

  while (handle != INVALID_HANDLE)
  {
    AddArrayElement(RightTime, GetChartTimeRight(handle));
    AddArrayElement(Handles, handle);

    handle = ChartNext(handle);
  }

  return(ArraySize(RightTime));
}

// Устанавливает правое время на все чарты
int SetChartsTimeRight( const datetime time, datetime &RightTime[], const long ExcludeHandle = 0 )
{
  ArrayFree(RightTime);

  long handle = ChartFirst();

  while (handle != INVALID_HANDLE)
  {
    AddArrayElement(RightTime, (ExcludeHandle == handle) ? GetChartTimeRight(handle) : SetChartTimeRight(time, handle));

    handle = ChartNext(handle);
  }

  return(ArraySize(RightTime));
}

// Возвращает чарт, что время правого бара которого изменилось
long GetChangeChart( const datetime &PrevRightTime[])
{
  datetime Handles[];
  datetime RightTime[];

  long Res = ArraySize(PrevRightTime) ? 0 : ChartID();

  for (int i = MathMin(ArraySize(PrevRightTime), GetChartsTimeRight(RightTime, Handles)) - 1; i >= 0; i--)
    if (RightTime[i] != PrevRightTime[i])
    {
      Res = Handles[i];

      break;
    }

  return(Res);
}

// Синхронизация всех чартов по правому времени, возвращает количество синхронизированных чартов
int SyncCharts()
{
  static datetime PrevRightTime[];

  const long handle = GetChangeChart(PrevRightTime);

  return(handle ? SetChartsTimeRight(GetChartTimeRight(handle), PrevRightTime, handle) : 0);
}
 
fxsaber:

Thanks for the full and comprehensive code, I'll try it out and report back later!

 
fxsaber:

The result is on the video, but without sound. Your code was used, and mine, but without time synchronisation, posted in the last post as an indicator

How to sync it so that if the bar doesn't fall in the time window, i.e. non-trading time, then skip it and use the last trading one.

The main task of the code is to scroll well from the window with the greatest number of bars, that is, forex pairs, it now scrolls well from the window with the least number of bars on those windows, the time periods falling into non-trading time of the pair - this is correct and should be logically.

Please: Please modify it so that it would be possible to smoothly rotate the forex pairs from one window.

Thank you!

 
Vitaly Muzichenko:

The result is on the video, but without sound. Your code was used, and mine, but without time synchronisation, posted in the last post as an indicator

How to synchronise it so that if the bar doesn't fall in the time window, i.e. non-trading time, then skip it and use the last trading one.

The main task of the code is to scroll well from the window with the greatest number of bars, that is, forex pairs, it now scrolls well from the window with the least number of bars on those windows, the time periods falling into non-trading time of the pair - this is correct and should be logically.

Please: Please modify it so that it would be possible to smoothly rotate the forex pairs from one window.

Thank you!

I have understood the problem. I have to think about it to solve it nicely.

In any case, these two functions are basic.

// Возвращает правое время чарта
datetime GetChartTimeRight( const long chartID = 0 );

// Устанавливает правое время чарта
bool SetChartTimeRight( const datetime time, const long chartID = 0 );

You have to play around with them to achieve a solution.

Reason: