Perguntas de Iniciantes MQL5 MT5 MetaTrader 5 - página 786

 

Se não se importar, por favor, conserte o código.

Escrevi código para percorrer gráficos abertos, mas fiquei preso à sincronização, não consigo sincronizar pela hora das primeiras barras visíveis, não leva em conta as barras perdidas - rola por todas elas, não levando em conta o tempo


//+------------------------------------------------------------------+
#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:

Se não se importar, por favor, conserte o código.

Escrevi código para percorrer os gráficos abertos, mas fiquei preso à sincronização, não consigo sincronizar pela hora das primeiras barras visíveis, não leva em conta as barras perdidas - percorre-as todas, sem considerar o tempo

O que devo fazer? Seria provavelmente mais fácil escrever a partir do zero do que consertá-lo.

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

O que devo fazer? Seria provavelmente mais fácil escrever a partir do zero do que editar.

Talvez a partir do zero, mas teria de ser sincronizado no tempo de alguma forma


 
Vitaly Muzichenko:

Talvez do zero, se ao menos houvesse uma sincronização de tempo

O vídeo é muito simples. Deve ser fácil de resolver. Quando estiver livre, publicarei a minha versão.

 
fxsaber:

O vídeo deixa tudo muito claro. A solução deve ser sucinta. Quando estiver livre, publicarei a minha versão.

Só que eu não sublinhei que a rolagem funciona a partir de qualquer gráfico, não apenas do gráfico principal.

Obrigado!

 
Comentários não relacionados com este tópico foram transferidos para "Perguntas dos principiantes do MQL4 MT4 MetaTrader 4".
 
Vitaly Muzichenko:

Só que eu não sublinhei que a rolagem funciona a partir de qualquer gráfico, não apenas do principal.

// 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:

Obrigado pelo código completo e abrangente, vou experimentá-lo e apresentarei o meu relatório mais tarde!

 
fxsaber:

O resultado está no vídeo, mas sem som. O seu código foi utilizado, e o meu, mas sem sincronização de tempo, afixado no último post como um indicador

Como sincronizá-lo para que, se a barra não cair na janela temporal, ou seja, tempo não comercial, então salte-a e use a última barra comercial.

A tarefa principal do código é percorrer bem a partir da janela com o maior número de barras, ou seja, pares de divisas, agora percorre bem a partir da janela com o menor número de barras nessas janelas, os períodos de tempo que caem em tempo não comercial do par - isto é correcto e deve ser lógico.

Por favor: Por favor, modifique-o para que seja possível rodar suavemente os pares de moedas a partir de uma janela.

Obrigado!

 
Vitaly Muzichenko:

O resultado está no vídeo, mas sem som. O seu código foi utilizado, e o meu, mas sem sincronização de tempo, afixado no último post como um indicador

Como sincronizá-lo para que, se a barra não cair na janela temporal, ou seja, tempo não comercial, então salte-a e use a última barra comercial.

A tarefa principal do código é percorrer bem a partir da janela com o maior número de barras, ou seja, pares de divisas, agora percorre bem a partir da janela com o menor número de barras nessas janelas salta períodos de tempo que caem em tempo não negociável do par - isto é correcto e deve ser por lógica.

Por favor: Por favor, modifique-o para que seja possível rodar suavemente os pares de moedas a partir de uma janela.

Obrigado!

Eu compreendi o problema. Tenho de pensar sobre isso para o resolver bem.

Em qualquer caso, estas duas funções são básicas.

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

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

Tem de se brincar com eles para se conseguir uma solução.

Razão: