Обработка пользовательских таймсерий

 

 Появилась необходимость написания некоторых индикаторов, чтобы рассчитывались не все бары имеющиеся в истории, а лишь некоторая их часть (от нулевого бара до определённой даты в историю).

Было решено, что нужно выполнить некоторые шаги для достижения результата:

1. Рассчитать количество баров,  которое имеется от 0-го бара заданного ТФ, до бара с неким заданным пользователем в настройках индикатора временем т.е. получить количество элементов в пользовательской таймсерии, отличной от терминальной rates_total.

2. Заполнить эту таймсерию данными.

По сути, опуская все нюансы и канкретику заполнения данных, покажу что я думаю.

Вот есть накиданный код: 

input datetime dtBuffLimitTime = D'2015.08.02';                // Время граничного бара входных таймсерий

bool      bootstrap = false;                                   // Флаг успешности инициализации входных данных
datetime  lastBarTime;                                         // Время проведение последних операций
int       initialRatesCount,                                   // Количество баров в исходной таймсерии
          currentRatesCount,                                   // Количество входящих таймсерии, на данный момент
          calculatedByNow;                                     // Количество просчитанных баров таймсерии, на предыдущем вызове
//+---------------------------------------------------------------------------------------------------------------------------------------+
//|                                              Custom indicator initialization function                                                 |
//+---------------------------------------------------------------------------------------------------------------------------------------+
int OnInit()
{
   for (int i = 0; i < Bars - 1; i++)
   {
      initialRatesCount++;                                     // Вычисление количества баров входных таймсерий
      
      if (dtBuffLimitTime >= Time[i])  break;
   }
   
   bootstrap = true;                                           // Инициализация входных данных успешна
   
   return(INIT_SUCCEEDED);
}
//+---------------------------------------------------------------------------------------------------------------------------------------+
//|                                                        Расчёт значений индикатора                                                     |
//+---------------------------------------------------------------------------------------------------------------------------------------+
/*void ZigZag (int limit)
{
   for (int i = limit; i > 0; i--)
   {
      int trend = GetTrend(i);
      
      if (trend != ZZ[i].iTendency)
      {
         
      }
   }
}*/
//+---------------------------------------------------------------------------------------------------------------------------------------+
//|                                                Custom indicator iteration function                                                    |
//+---------------------------------------------------------------------------------------------------------------------------------------+
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[])
{
   if (!bootstrap) return(0);
   
//   int limit = rates_total - prev_calculated;
   
   if (lastBarTime != Time[0])
   {
      
//      ZigZag (limit);
      lastBarTime = Time[0];
   }
   
//--- return value of prev_calculated for next call
   return (rates_total);
}

 В принципе, видно, что в коде всё понятно и доходичво. Если что не понятно, спрашивайте, отвечу..

Первоначальное количество элементов таймсерии я получил в переменную initialRatesCount. Но дальше нужно как-то реализовать обработку лишь новых не рассчитанных баров. Раньше я пользовался таким вариантом:

int limit = rates_total - prev_calculated

 Как это реализовать сейчас? Чтобы всё учитывалось чётко. Ведь должен быть полный контроль над появлением новых баров так же и на случай потери связи. Интересно, как кто-нить подобные вопросы решал.

Тут же нужно как-то реализовать полный контроль над количеством имеющихся баров с некоторой заданной даты dtBuffLimitTime  до настоящего времени. Дальше нужно реализовать количество уже рассчитанных баров. Как это реализовать?

У меня имеются мысли, но это как-то очень много писанины. Надеюсь кто гибче вариант предложит.

 
shanty:

 Появилась необходимость написания некоторых индикаторов, чтобы рассчитывались не все бары имеющиеся в истории, а лишь некоторая их часть (от нулевого бара до определённой даты в историю).

Было решено, что нужно выполнить некоторые шаги для достижения результата:

1. Рассчитать количество баров,  которое имеется от 0-го бара заданного ТФ, до бара с неким заданным пользователем в настройках индикатора временем т.е. получить количество элементов в пользовательской таймсерии, отличной от терминальной rates_total.

2. Заполнить эту таймсерию данными.

По сути, опуская все нюансы и канкретику заполнения данных, покажу что я думаю.

Вот есть накиданный код: 

 В принципе, видно, что в коде всё понятно и доходичво. Если что не понятно, спрашивайте, отвечу..

Первоначальное количество элементов таймсерии я получил в переменную initialRatesCount. Но дальше нужно как-то реализовать обработку лишь новых не рассчитанных баров. Раньше я пользовался таким вариантом:

 Как это реализовать сейчас? Чтобы всё учитывалось чётко. Ведь должен быть полный контроль над появлением новых баров так же и на случай потери связи. Интересно, как кто-нить подобные вопросы решал.

Тут же нужно как-то реализовать полный контроль над количеством имеющихся баров с некоторой заданной даты dtBuffLimitTime  до настоящего времени. Дальше нужно реализовать количество уже рассчитанных баров. Как это реализовать?

У меня имеются мысли, но это как-то очень много писанины. Надеюсь кто гибче вариант предложит.

Расчет initialRatesCount.

Считаем limit. Если полученное значение больше 1. То считаем что limit=initialRatesCount;

Примерно  так. Но надо учитывать что у Вас идет обработка пользовательского таймфрейма. Возможно будет лучше делать перерасчет на каждом тике

 
Vinin:

Расчет initialRatesCount.

 Как?

 

Vinin:

Считаем limit. Если полученное значение больше 1. То считаем что limit=initialRatesCount;

 Ну так обычно размер входных таймсерий rates_total возвращается терминалом, и это величина всей подгруженной таймсерии в истории. А тут как это контролировать? Первоначально то я рассчитаю количество элементов в таймсерии, а дальше как?

Мысли в сторону типа:

currentRatesCount = initialRatesCount + счётчик;

 где, значение переменной счётчик будет увеличиваться на 1 после каждого изменения времени на заданном ТФ. Но это уже потом.. (для начала нужно базу реализовать).

 

Vinin:

Примерно  так. Но надо учитывать что у Вас идет обработка пользовательского таймфрейма. Возможно будет лучше делать перерасчет на каждом тике

 А какой в этом резон? Ведь тики тут не нужны на мой взгляд т.к. контроль процесса происходить по событию - изменению времени. Если время изменилось, то.. расчёт значений.. и задание переменной времени нового текущего значения. Разве этого не достаточно?

 
//----   
   counted_bars=IndicatorCounted();             // Возвращает количество баров, не измененных после последнего вызова индикатора
   if(counted_bars < 0) return(-1);
   if(counted_bars>0) counted_bars--;
   limit=Bars-counted_bars;                     // Количество баров на текущем графике минус неизмененные
   if(Days!=0) limit2=Days*1440/Period();       // расчет количества баров для первого просчета (входной параметр Days)
   else limit2=limit;
   limit=fmin(limit,limit2);                    // выбираем меньшее
   if(counted_bars==0) limit--;                 // переменная limit содержит количество баров необходимое для обработки

//----
   for(i=limit; i>=0; i--)                      // цикл просчета
     {
     // считаем
     }
это в OnCalculate
 

noloxe, в том то и дело, что функция IndicatorCounted() используется ещё с первых билдов, но... я ж не в курсе, какая у неё реализация. Обычно её использовали для учёта не изменённых баров на всей подгруженной истории, а не фиксированном интервале данных.

Какие ещё будут предложения? 

 
Виктор, а зачем такие пляски с бубном для определения количества баров? Почему не использовать iBarShift() и потом CopyRates() и будешь иметь всю информацию на данный участок...
 
shanty:

noloxe, в том то и дело, что функция IndicatorCounted() используется ещё с первых билдов, но... я ж не в курсе, какая у неё реализация. Обычно её использовали для учёта не изменённых баров на всей подгруженной истории, а не фиксированном интервале данных.

Какие ещё будут предложения? 

тогда непонятна задача, что нужно? (приведенный вариант использую в своих индикаторах — считает только заданное количество времени и потом только свежие бары)

 
AlexeyVik:
Виктор, а зачем такие пляски с бубном для определения количества баров? Почему не использовать iBarShift() и потом CopyRates() и будешь иметь всю информацию на данный участок...

Алексей, в принципе, можно и так. Но хотелось написать свою функцию, что бы она была универсальна.

noloxe:

тогда непонятна задача, что нужно? (приведенный вариант использую в своих индикаторах — считает только заданное количество времени и потом только свежие бары)

В принципе, нормальный у Вас вариант. Хотя чутка расширен. Я подумаю. Его можно укоротить без потери точности.

 
shanty:

Алексей, в принципе, можно и так. Но хотелось написать свою функцию, что бы она была универсальна.

Куда-же ещё универсальней, чем получить номер бара по времени вместо цикла с проверкой времени бара?
 
AlexeyVik:
Куда-же ещё универсальней, чем получить номер бара по времени вместо цикла с проверкой времени бара?

Я имею ввиду, в плане универсальности использования кроссплатформенно. Спецефических функций подобных в других платформах может и не быть. Поэтому иной раз интересно учится писать всё самому, без использования спецефических функций. Тем более, тот же iBarShift возвращается порядковый номер бара, а это возвращается через цикл по-любому. Единственное удобно, так это запаковка реализации. Хотя, с другой стороны, это не является плюсом. Т.к. зная реализацию, удобнее писать.

Причина обращения: