Preguntas de los principiantes MQL5 MT5 MetaTrader 5 - página 786

 

Por favor, arregla el código, si no te importa.

Escribí el código para el desplazamiento de los gráficos abiertos, pero me quedé atascado con la sincronización, no puedo sincronizar por el tiempo de las primeras barras visibles, no tiene en cuenta las barras perdidas - se desplaza por todas ellas, sin tener en cuenta el tiempo


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

Por favor, arregla el código, si no te importa.

Escribí el código para el desplazamiento a través de los gráficos abiertos, pero me quedé atascado con la sincronización, no puedo sincronizar por el tiempo de las primeras barras visibles, no tiene en cuenta las barras perdidas - se desplaza a través de todos ellos, sin tener en cuenta el tiempo

¿Qué debo hacer? Probablemente sería más fácil escribir desde cero que arreglarlo.

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

¿Qué debo hacer? Probablemente sea más fácil escribir desde cero que editar.

Tal vez desde cero, pero tendría que estar sincronizado en el tiempo de alguna manera


 
Vitaly Muzichenko:

Tal vez desde cero, si sólo hubiera una sincronización de tiempo

El vídeo lo deja muy claro. Debería ser fácil de resolver. Cuando esté libre, publicaré mi versión.

 
fxsaber:

El vídeo lo deja muy claro. La solución debe ser sucinta. Cuando esté libre, publicaré mi versión.

Salvo que no destaqué que el desplazamiento funciona desde cualquier gráfico, no sólo el principal.

Gracias.

 
Los comentarios no relacionados con este tema han sido trasladados a "Preguntas de los principiantes de MQL4 MT4 MetaTrader 4".
 
Vitaly Muzichenko:

Salvo que no destaqué que el desplazamiento funciona desde cualquier gráfico, no sólo el 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:

Gracias por el código completo y exhaustivo, lo probaré e informaré más tarde.

 
fxsaber:

El resultado está en el vídeo, pero sin sonido. Se utilizó tu código, y el mío, pero sin sincronización horaria, publicado en el último post como indicador

Cómo sincronizarlo para que si la barra no cae en la ventana de tiempo, es decir, tiempo de no negociación, entonces la omita y utilice la última de negociación.

La tarea principal del código es desplazarse bien desde la ventana con el mayor número de barras, es decir, los pares de divisas, ahora se desplaza bien desde la ventana con el menor número de barras en esas ventanas se salta los períodos de tiempo que caen en el tiempo no comercial del par - esto es correcto y debe ser por la lógica.

Por favor: Modifíquelo para que sea posible rotar suavemente los pares de divisas desde una ventana.

Gracias.

 
Vitaly Muzichenko:

El resultado está en el vídeo, pero sin sonido. Se utilizó tu código, y el mío, pero sin sincronización horaria, publicado en el último post como indicador

Cómo sincronizarlo para que si la barra no cae en la ventana de tiempo, es decir, tiempo de no negociación, entonces la omita y utilice la última de negociación.

La tarea principal del código es desplazarse bien desde la ventana con el mayor número de barras, es decir, los pares de divisas, ahora se desplaza bien desde la ventana con el menor número de barras en esas ventanas, los períodos de tiempo que caen en tiempo no comercial del par - esto es correcto y debe ser lógicamente.

Por favor: Modifíquelo para que sea posible rotar suavemente los pares de divisas desde una ventana.

Gracias.

He comprendido el problema. Tengo que pensar en ello para resolverlo bien.

En cualquier caso, estas dos funciones son básicas.

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

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

Hay que jugar con ellos para lograr una solución.