Вопросы от начинающих MQL5 MT5 MetaTrader 5 - страница 786

 
fxsaber:

А что делать должен? Написать с нуля, наверное, будет проще, чем править.

Может и с нуля, вот бы синхронизировать как-то по времени


 
Vitaly Muzichenko:

Может и с нуля, вот бы синхронизировать как-то по времени

С видео все очень доходчиво. Лаконично должно решаться. Освобожусь - выложу свой вариант.

 
fxsaber:

С видео все очень доходчиво. Лаконично должно решаться. Освобожусь - выложу свой вариант.

Вот только не сделал ударение на то, что прокрутка работает с любого графика, а не только с основного.

Спасибо!

 
Комментарии, не относящиеся к этой теме, были перенесены в "Вопросы от начинающих MQL4 MT4 MetaTrader 4".
 
Vitaly Muzichenko:

Вот только не сделал ударение на то, что прокрутка работает с любого графика, а не только с основного.

// 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 = 1e5 )
{
  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:

Спасибо за полный и развёрнутый код, буду его пробовать, потом отпишусь о результатах!

 
fxsaber:

Результат на видео, но без звука. Использовался ваш код, и мой, но без синхронизации по времени, выложен в прошлом сообщении в виде индикатора 

Как-бы его синхронизировать так, что если бар не попадает во временной промежуток, то есть неторговое время, то его пропускать и использовать последний торговый.

Основная задача кода, хорошо прокручивать с окна с наибольшим количеством баров, то есть форекс пар, сейчас он хорошо прокручивает с окна наименьшим количеством баров, на тех окнах проскакивают временные участки попавшие в неторговое время данной пары - это правильно, так и должно быть по логике.

Просьба: доработать так, чтоб можно было плавно крутить с окна форекс пары.

Спасибо!

 
Vitaly Muzichenko:

Результат на видео, но без звука. Использовался ваш код, и мой, но без синхронизации по времени, выложен в прошлом сообщении в виде индикатора 

Как-бы его синхронизировать так, что если бар не попадает во временной промежуток, то есть неторговое время, то его пропускать и использовать последний торговый.

Основная задача кода, хорошо прокручивать с окна с наибольшим количеством баров, то есть форекс пар, сейчас он хорошо прокручивает с окна наименьшим количеством баров, на тех окнах проскакивают временные участки попавшие в неторговое время данной пары - это правильно, так и должно быть по логике.

Просьба: доработать так, чтоб можно было плавно крутить с окна форекс пары.

Спасибо!

Проблему понял. Чтобы решить красиво, нужно подумать.

В любом случае, эти две функции являются основными

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

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

Их использование нужно обыграть, чтобы добиться решения.

 
fxsaber:

Проблему понял. Чтобы решить красиво, нужно подумать.

В любом случае, эти две функции являются основными

Их использование нужно обыграть, чтобы добиться решения.

Как реализовать, Я примерно представляю, но как заложить в код - нет(

Нужно наверное сравнить время баров, и если оно меньше от текущего - пропустить прокрутку. Вариант №2: считать количество баров графиков от текущего времени до первого видимого, и на это количество прокручивать, так наверное будет плавнее.

В любом случае, ни одну реализацию не могу заложить в код - заработался наверное(

 
Vitaly Muzichenko:

Как реализовать, Я примерно представляю, но как заложить в код - нет(

Нужно наверное сравнить время баров, и если оно меньше от текущего - пропустить прокрутку. Вариант №2: считать количество баров графиков от текущего времени до первого видимого, и на это количество прокручивать, так наверное будет плавнее.

В любом случае, ни одну реализацию не могу заложить в код - заработался наверное(

Перемудрили, там проблема только в том, чтобы определить, какой график является ведущим в настоящий момент. Решается это через статический массив, где хранится время правого бара для каждого чарта. В таймере сравнивается с текущим положением, кто отличается - тот и ведущий. Завтра допилю.


ЗЫ Допилил.