Scripts: sSyncScroll - página 2

 
De fato, ao tentar rolar o gráfico para trás e visualizar o histórico, quando um novo tique chega, o gráfico retorna ao início. Nesse caso, por que eu preciso disso? Eu já sei que, ao desenhar o último candle em M1, ele também é o último candle para todos os outros TFs. E sem esse indicador em todas as janelas, os últimos candlesticks são redesenhados automaticamente.
 
Дима Джумок #:
De fato, ao tentar rolar o gráfico para trás e visualizar o histórico, quando um novo tique chega, o gráfico retorna ao início. Nesse caso, por que eu preciso disso? Eu já sei que, ao desenhar o último candle em M1, ele também é o último candle para todos os outros TFs. E sem esse indicador em todas as janelas, os últimos candlesticks são redesenhados automaticamente.

Ele quebrou após as próximas alterações no idioma. Tenho outro aqui, também quebrado. Procure outros, pois há alguns que estão funcionando aqui.

 
Dmitry Fedoseev #:

Ele quebrou após outra alteração no idioma. Tenho outro aqui, também quebrado. Procure mais, há alguns que estão funcionando aqui.

Dmitry, obrigado por sua resposta. Para minha tristeza, o Google fornece links apenas para seus desenvolvimentos. O fórum também não me ofereceu nenhuma alternativa. O Admiral Market oferece essa função, mas apenas em sua plataforma, que não é o MT5. Caro fxsaber ofereceu em 2017 sua variante Simultaneous autoscrolling of charts for one instrument in different timeframes for MT5 - Technical Indicators and Forex Market Analysis - MQL5 Algo-Traders Forum (há o texto do indicador no último comentário), mas não sei como convertê-lo para o terminal MT5, então não posso determinar se é uma variante funcional. Se você não se importar, por favor, converta-o, talvez ele esteja funcionando.

// Código MQL4&5
// Sincronização de todos os gráficos por hora certa

sinput int TimerInterval = 1; // Intervalo de atualização em milissegundos

// Desativa a rolagem automática e o deslocamento em todos os gráficos
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();
}

// Retorna true se não houver nenhuma barra com esse tempo ("hole")
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));
}

// Retorna a barra de tempo
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);
}

// Retorna o tempo da barra
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));
}

// Retorna a barra direita do gráfico
int ChartBarRight( const long chartID = 0 )
{
  return((int)(ChartGetInteger(chartID, CHART_FIRST_VISIBLE_BAR) - ChartGetInteger(chartID, CHART_WIDTH_IN_BARS) + 1));
}

// Retorna o tempo correto do gráfico
datetime GetChartTimeRight( const long chartID = 0 )
{
  return(iBarShift(ChartSymbol(chartID), ChartPeriod(chartID), ChartBarRight(chartID)));
}

// Define o tempo do gráfico correto e retorna o tempo definido
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));
}

// Adicionar um elemento ao final de uma matriz arbitrária
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;
}

// Obtém a hora da barra direita de cada gráfico
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));
}

// Define a hora certa para todos os gráficos
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));
}

// Retorna o gráfico em que o tempo da barra direita foi alterado
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);
}

// Sincroniza todos os gráficos pela hora certa, retorna o número de gráficos sincronizados
int SyncCharts()
{
  static datetime PrevRightTime[];

  const long handle = GetChangeChart(PrevRightTime);

  return(handle ? SetChartsTimeRight(GetChartTimeRight(handle), PrevRightTime, handle) : 0);
}
fxsaber
fxsaber
  • 2023.01.17
  • www.mql5.com
Профиль трейдера
 
Дима Джумок #:

Dmitry, obrigado por sua resposta. Para minha tristeza, o Google fornece links apenas para seus desenvolvimentos. O fórum também não me ofereceu nenhuma alternativa. O Admiral Market oferece essa função, mas apenas em sua plataforma, que não é o MT5. Caro fxsaber ofereceu em 2017 sua variante Simultaneous autoscrolling of charts for one instrument in different timeframes for MT5 - Technical Indicators and Forex Market Analysis - MQL5 Algo-Traders Forum (há o texto do indicador no último comentário), mas não sei como convertê-lo para o terminal MT5, então não posso determinar se é uma variante funcional. Se você não se importar, por favor, converta-o, talvez ele esteja funcionando.

Então, é melhor consertar a sua própria.

Baixei o meu agora e ele funciona. Um inconveniente: se os recuos não estiverem ativados, a barra necessária no gráfico de rolagem ultrapassa a borda e a linha não fica visível. Isso terá de ser corrigido.

O que está acontecendo no seu script, como ele não está funcionando? O script desativa a rolagem automática com a chegada de um novo tique.

Esse botão na barra de ferramentas deve ser pressionado automaticamente em todos os gráficos quando o script for anexado:

 
Bomba! Está funcionando! Muito obrigada!