Скачать MetaTrader 5

Пропуски баров на графике

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Подключи MQL5 Cloud Network. Увеличивай свой рейтинг!
TarasBY
1739
TarasBY 2010.12.08 20:48 

Рисую показания тренда по нескольким инструментам (мультивалютный индикатор) и получаю на графике пропуски баров. Выглядит это так:


Кто-нибудь сталкивался с такими несуразностями? Может есть идеи и предложения по устранению?
Жёлтую линию рисует индикаторный буфер в который в начале цикла расчёта индикатора вносится значение:

Buf_OUT[li_Bar] = 0.0;

А затем, в процессе расчёта, это значение изменяется. Стоило ожидать наличие жёлтой линии на всех барах. Ан НЕТ!!!

Aleksander
1673
Aleksander 2010.12.08 20:58  
пользуй функцию типа iBarShift( беря значение ближайшего бара к текущему....
TarasBY
1739
TarasBY 2010.12.08 21:16  
Aleksander:
пользуй функцию типа iBarShift( беря значение ближайшего бара к текущему....
Если бы всё было так просто!...
Вот цикл расчётов:
    for (li_Bar = Limit - 1; li_Bar >= 0; li_Bar--)
    {
        ld_Trend = 0.0; Buf_UPHigh[li_Bar] = 0.0; Buf_UP[li_Bar] = 0.0; Buf_OUT[li_Bar] = 0.0;
        ld_delta_Trend = 0.0; Buf_DWLow[li_Bar] = 0.0; Buf_DW[li_Bar] = 0.0;
        Time_Bar = Time[li_Bar];
        for (li_SMB = 0; li_SMB < cnt_SMB[2]; li_SMB++)
        {
            //---- Суммируем показания индикатора по LONG-корзине
            if (cnt_SMB[0] > 0 && li_SMB < cnt_SMB[0])
            {
                li_Bar_ind = iBarShift (Sym_LONG[li_SMB], Period(), Time_Bar);
                ld_SuperTrend = iCustom (Sym_LONG[li_SMB], Period(), "VininI_Supertrend", iCCI_Period, iATR_Period, 0, li_Bar_ind);
                ld_SuperTrend_1 = iCustom (Sym_LONG[li_SMB], Period(), "VininI_Supertrend", iCCI_Period, iATR_Period, 0, li_Bar_ind + 1);
                ld_SuperTrend_2 = iCustom (Sym_LONG[li_SMB], Period(), "VininI_Supertrend", iCCI_Period, iATR_Period, 0, li_Bar_ind + 2);
                ld_Trend += IIFd ((ld_SuperTrend > ld_SuperTrend_1 && ld_SuperTrend_1 >= ld_SuperTrend_2), 1,
                IIFd ((ld_SuperTrend == ld_SuperTrend_1), 0, -1));
            }
            //---- Суммируем показания индикатора по SHORT-корзине
            if (cnt_SMB[1] > 0 && li_SMB < cnt_SMB[1])
            {
                li_Bar_ind = iBarShift (Sym_SHORT[li_SMB], Period(), Time_Bar);
                ld_SuperTrend = iCustom (Sym_SHORT[li_SMB], Period(), "VininI_Supertrend", iCCI_Period, iATR_Period, 0, li_Bar_ind);
                ld_SuperTrend_1 = iCustom (Sym_SHORT[li_SMB], Period(), "VininI_Supertrend", iCCI_Period, iATR_Period, 0, li_Bar_ind + 1);
                ld_SuperTrend_2 = iCustom (Sym_SHORT[li_SMB], Period(), "VininI_Supertrend", iCCI_Period, iATR_Period, 0, li_Bar_ind + 2);
                ld_Trend += IIFd ((ld_SuperTrend < ld_SuperTrend_1 && ld_SuperTrend_1 <= ld_SuperTrend_2), 1,
                IIFd ((ld_SuperTrend == ld_SuperTrend_1), 0, -1));
            }
        }
        Buf_OUT[li_Bar] = ld_Trend;
        if (ld_Trend >= 0)
        {
            if (ld_Trend > (cnt_SMB[0] + cnt_SMB[1]) / 2)
            {Buf_UPHigh[li_Bar] = ld_Trend;}
            else
            {Buf_UP[li_Bar] = ld_Trend;}
        }
        else
        {
            if (MathAbs (ld_Trend) > (cnt_SMB[0] + cnt_SMB[1]) / 2)
            {Buf_DWLow[li_Bar] = ld_Trend;}
            else
            {Buf_DW[li_Bar] = ld_Trend;}
        }
    }
Это был следующий ход моей мысли после возникновения данной несуразицы. А сначала я использовал номер бара текущего графика для расчёта показаний на других инструментах.
Alexey Subbotin
4998
Alexey Subbotin 2010.12.08 21:19  
Дай весь код, а то будем гадать...
TarasBY
1739
TarasBY 2010.12.08 21:30  
alsu:
Дай весь код, а то будем гадать...
Результат отрабатывает именно этот код, а много кода - чужого кода, отбивает желание вообще его (чужой код) смотреть.
Mislaid
622
Mislaid 2010.12.08 21:37  
Aleksander:
пользуй функцию типа iBarShift( беря значение ближайшего бара к текущему....


Для мультивалютников это обычное дело. Я тоже так делаю. Это позволяет построить индикатор, при отсутствии баров, на основе "последней известной цены". Отсутствие баров бывает по нескольким поводам:

1. история на сервере ДЦ существует, но она еще не закачана;

2. история на сервере ДЦ отсутствует:

2.1 дыра в истории;

2.2 отсутствие баров вследствие низкой ликвидности (характерно для М1, М5, иногда М15).

п. 1 лечится пересчетом окна индикатора приемлемых размеров (со временем история докачивается);

п. 2.2 может быть разрешен на основе "последней известной цены";

п. 2.1 не лечится (диагностируется только при отсутствии подряд "существенного" числа баров )

В общем, основная идея - пересчет окна индикатора приемлемых размеров (со временем история докачивается)

hrenfx
3672
hrenfx 2010.12.08 21:47  

Мне для мультивалютного анализа очень надо было решить эту проблему на все возможные случаи.

Привожу решение, которое использовал. Снабдил комментариями, если что-то непонятно, спрашивайте. Работает на 100% и даже в режиме визуального тестирования.

// Возвращает цену символа по заданному времени
double GetPrice( string Symb, int time )
{
  double Price;

  Price = iClose(Symb, Period(), iBarShift(Symb, Period(), time));

  return(Price);
}

// Возвращает следующее за CurrTime время, для которого есть цена.
// В массиве Symbols названия нужных символов.
// AmountSymbols - их количество.
int GetNextTime( int CurrTime )
{
  static int Pos[MAX_AMOUNTSYMBOLS];
  int i, MinTime, Tmp = -1;

  // Pos[i] содержит следующий номер бара, со временем больше CurrTime
  for (i = 0; i < AmountSymbols; i++)
  {
    Pos[i] = iBarShift(Symbols[i], Period(), CurrTime) - 1;

    if (Pos[i] >= 0)
      Tmp = i;
  }

  // Если все Pos[i] оказались отрицательными, выходим. Т.к. мы дошли до крайних записей в исторической базе.
  if (Tmp < 0)
    return(Time[0]);

  MinTime = iTime(Symbols[Tmp], Period(), Pos[Tmp]);

  i = Tmp - 1;

  // Среди всех Pos[i] ищем наименьшее время.
  while (i >= 0)
  {
    if (Pos[i] >= 0)
    {
      Tmp = iTime(Symbols[i], Period(), Pos[i]);

      if (Tmp < MinTime)
        MinTime = Tmp;
    }

    i--;
  }

  // Найденное наименьшее время и есть ближайшее известное время за CurrTime в исторической базе.
  return(MinTime);
}

// Заполняем матрицу так, чтобы в каждой строке были синхронизированные цены со времени StartTime до Time[0].
void GetBaseMatrix()
{
  int i, CurrTime = StartTime;

  MatrixRows = 0;

  while (CurrTime < Time[0])
  {
    // Заполняем строку матрицы ценами, соответствующими времени CurrTime
    for (i = 0; i < AmountSymbols; i++)
      BaseMatrix[i][MatrixRows] = 1000 * MathLog(GetPrice(Symbols[i], CurrTime));

    // Запомнили значение времени для соответствующей строки матрицы.
    Times[MatrixRows] = CurrTime;

    MatrixRows++;

    // Получили следующее время из исторической базы
    CurrTime = GetNextTime(CurrTime);
  }

  return;
}
TarasBY
1739
TarasBY 2010.12.08 21:49  
Mislaid:


Для мультивалютников это обычное дело. Я тоже так делаю. Это позволяет построить индикатор, при отсутствии баров, на основе "последней известной цены". Отсутствие баров бывает по нескольким поводам:

1. история на сервере ДЦ существует, но она еще не закачана;

2. история на сервере ДЦ отсутствует:

2.1 дыра в истории;

2.2 отсутствие баров вследствие низкой ликвидности (характерно для М1, М5, иногда М15).

п. 1 лечится пересчетом окна индикатора приемлемых размеров (со временем история докачивается);

п. 2.2 может быть разрешен на основе "последней известной цены";

п. 2.1 не лечится (диагностируется только при отсутствии подряд "существенного" числа баров )

В общем, основная идея - пересчет окна индикатора приемлемых размеров (со временем история докачивается)

Я для читабельности убрал из кода проверку на отсутствие истории:

            //---- Суммируем показания индикатора по LONG-корзине
            if (cnt_SMB[0] > 0 && li_SMB < cnt_SMB[0])
            {
                li_Bar_ind = iBarShift (Sym_LONG[li_SMB], Period(), Time_Bar);
                ld_SuperTrend = iCustom (Sym_LONG[li_SMB], Period(), "VininI_Supertrend", iCCI_Period, iATR_Period, 0, li_Bar);
                ld_SuperTrend_1 = iCustom (Sym_LONG[li_SMB], Period(), "VininI_Supertrend", iCCI_Period, iATR_Period, 0, li_Bar + 1);
                ld_SuperTrend_2 = iCustom (Sym_LONG[li_SMB], Period(), "VininI_Supertrend", iCCI_Period, iATR_Period, 0, li_Bar + 2);
                ld_Trend += IIFd ((ld_SuperTrend > ld_SuperTrend_1 && ld_SuperTrend_1 >= ld_SuperTrend_2), 1,
                IIFd ((ld_SuperTrend == ld_SuperTrend_1), 0, -1));
                ld_delta_Trend += (ld_SuperTrend - ld_SuperTrend_2) / gd_PointLB[li_SMB];
                if (Time_Bar != iTime (Sym_LONG[li_SMB], Period(), li_Bar_ind) && li_Bar < 1000)
                {Print ("Не совпадение баров: Bar[", li_Bar, " - ", TS_DM (Time_Bar), "] != Bar[", li_Bar_ind, " - ", TS_DM (iTime (Sym_LONG[li_SMB], Period(), li_Bar_ind)), "] - ", Sym_LONG[li_SMB], " !!!");}
            }

на 1000 последних баров на дырки в истории жаловаться не приходится (на этом TF). У меня стоит инструмент, который в реальном времени подкачивает историю по всему "Обзору рынка". Если бара нет - то значение будет "не адекватным" с точки зрения правильности получаемой на выходе информации. НО результат в виде (в данном случае) жёлтой линии на графике ДОЛЖЕН БЫТЬ, а он ОТСУТСТВУЕТ!!!
Ещё есть идеи?

Aleksander
1673
Aleksander 2010.12.08 22:09  

у тебя не реализовано свойство

exact - Возвращаемое значение если бар не найден. FALSE - iBarShift возвращает ближайший.



int iBarShift( string symbol, int timeframe, datetime time, bool exact=false)
Поиск бара по времени. Функция возвращает смещение бара, которому принадлежит указанное время. Если для указанного времени бар отсутствует ("дыра" в истории), то функция возвращает, в зависимости от параметра exact, -1 или смещение ближайшего бара.
Параметры:
symbol - Символьное имя инструмента. NULL означает текущий символ.
timeframe - Период. Может быть одним из периодов графика. 0 означает период текущего графика.
time - Значение времени для поиска.
exact - Возвращаемое значение если бар не найден. FALSE - iBarShift возвращает ближайший. TRUE - iBarShift возвращает -1.
Пример:
Mislaid
622
Mislaid 2010.12.08 22:18  
TarasBY:

Я для читабельности убрал из кода проверку на отсутствие истории:

на 1000 последних баров на дырки в истории жаловаться не приходится (на этом TF). У меня стоит инструмент, который в реальном времени подкачивает историю по всему "Обзору рынка". Если бара нет - то значение будет "не адекватным" с точки зрения правильности получаемой на выходе информации. НО результат в виде (в данном случае) жёлтой линии на графике ДОЛЖЕН БЫТЬ, а он ОТСУТСТВУЕТ!!!
Ещё есть идеи?


Идея - переписать индикатор VininI_Supertrend, он то, точно, не расчитан на отсутствие баров в истории. Наличие символа в обзоре рынка влияет на закачку истории по символу, если только открыт график по инструменту, или вы ее запрашиваете через одну из функций:

iClose, iHigh, iLow, iOpen

Я пользуюсь в мультивалютниках только индикаторами в окнах фиксированного размера, поэтому на текущем таймфрейме достаточно корректно работает такая функция

//+------------------------------------------------------------------+
//| Функция LastKnownPrice() возвращает последнюю известную цену     |
//| по инструменту SymbolName на момент времени cTime                |
//| Вызываемые процедуры: нет                                        |
//| Вызывается из                                                    |
//+------------------------------------------------------------------+
double  LastKnownPrice( string SymbolName, datetime cTime)
{
   int   shift;
   
   shift = iBarShift( SymbolName, 0, cTime, false);
   if (iTime(SymbolName, 0, shift) > cTime) shift++;
   return( iClose(SymbolName, 0, shift) );
}
//+-- LastKnownPrice() END ------------------------------------------+

TarasBY
1739
TarasBY 2010.12.08 22:22  
Aleksander:

у тебя не реализовано свойство

exact - Возвращаемое значение если бар не найден. FALSE - iBarShift возвращает ближайший.



int iBarShift( string symbol, int timeframe, datetime time, bool exact=false)
Поиск бара по времени. Функция возвращает смещение бара, которому принадлежит указанное время. Если для указанного времени бар отсутствует ("дыра" в истории), то функция возвращает, в зависимости от параметра exact, -1 или смещение ближайшего бара.
Параметры:
symbol - Символьное имя инструмента. NULL означает текущий символ.
timeframe - Период. Может быть одним из периодов графика. 0 означает период текущего графика.
time - Значение времени для поиска.
exact - Возвращаемое значение если бар не найден. FALSE - iBarShift возвращает ближайший. TRUE - iBarShift возвращает -1.
Пример:

Ты вот на эту проверку обратил внимание:

if (Time_Bar != iTime (Sym_LONG[li_SMB], Period(), li_Bar_ind) && li_Bar < 1000)
                {Print ("Не совпадение баров: Bar[", li_Bar, " - ", TS_DM (Time_Bar), "] != Bar[", li_Bar_ind, " - ", TS_DM (iTime (Sym_LONG[li_SMB], Period(), li_Bar_ind)), "] - ", Sym_LONG[li_SMB], " !!!");}
            

В логе записи несоответствия отстутствуют.
Давай возьмём вариант, когда номер бара берётся с графика чарта. Мне (пока - на данный момент) не существенно правильно у меня производится конечный расчёт или нет. Расёт (пусть даже не правильный) присутствует не на всех барах! ПОЧЕМУ???

123
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий