Пользовательские индикаторы > Фильтр восстановления сигнала

Дополнительные индикаторы от пользователей Альфа-Директ 4. Готовые решения от пользователей.
BugsDigger
Сообщения: 339
Зарегистрирован: 11 ноя 2018, 17:11
Благодарил (а): 21 раз
Поблагодарили: 42 раза

Фильтр восстановления сигнала

Непрочитанное сообщение BugsDigger » 16 фев 2020, 20:39

Многочисленные фильтры на основе бегущего среднего имеют схожую особенность: они запаздывают. Это запаздывание имеет свои плюсы, но иногда все же хочется как-то увидеть сглаженный график без запаздывания.
Можно использовать "центральное" бегущее среднее (усреднять на период/2 влево и вправо от точки в прошлом), но тогда на краях (особенно на правом, который нам больше всего и интересен) остается незаполненное место размером период/2...

Я использую предлагаемый фильтр много лет при решении разных задач. Приплыл он ко мне под именем "фильтра восстановления сигнала Ушакова" от одного коллеги, недавнего (тогда) студента, очевидно, с какой-то лабы в вузе. С тех пор я несколько раз пытался найти первоисточник, но безуспешно. Да и бог с ним.

Фильтр является некоторой разновидностью медианного, смысл его работы в следующем. Берем три последовательных точки, считаем среднее по двум крайним. Если центральная точка уклоняется от этого среднего меньше, чем на предопределенную величину (уровень шума), то заменяем значение в центральной точке на среднее. В противном случае подтягиваем центральную точку к среднему на величину шума. Применяем этот алгоритм последовательно ко всем тройкам точек на интервале. Затем операцию повторяем заданное число раз. В результате шумы нивелируются, а гэпы более-менее остаются.

Код: Выделить всё

function Initialize()
{
 IndicatorName = "UF";
 PriceStudy = true;
 AddInput("Input", Inputs.Price);
 AddParameter("Period", 10);
 AddParameter("Gap", 1.0);                  // % уровень разницы в значениях, трактуемый как несглаживаемый разрыв; меньшие разницы трактуются как шум
 AddParameter("Iterations", 10);            // число итераций фильтрации
 AddSeries("UF", DrawAs.Line, Color.Black); // выходная серия индикатора
}

function Evaluate()
{
 //-------------------------------------------------------------
 // Фильтр восстановления сигнала (Ушакова)
 // Для входной серии индикатора
 Action<TA.Script.AdsInput, int, double, int, TA.Script.XSeries>
  UFilter=(TA.Script.AdsInput _input, int _period, double _gap, int _iterations, TA.Script.XSeries _series_out) =>
 
 // Для серии (в т.ч. другого индикатора)
 // Action<TA.Script.XSeries, int, double, int, TA.Script.XSeries>
 //  UFilter=(TA.Script.XSeries _input, int _period, double _gap, int _iterations, TA.Script.XSeries _series_out) =>
 {
  if(_period<3) _period=3;
  if(CurrentIndex<_period) return;
 
  int from=_period-1;
  double[] inpval=new double[_period];
  double[] outval=new double[_period];
  for(int i=-from, o=0; i<=0; i++, o++) inpval[o]=(outval[o]=_input[i]);

  double g=_gap/100.0;
  double avg, gapBound, v;
  for(int iter=0; iter<_iterations; iter++)
  {
   for(int i=1; i<from; i++)
   {
    avg=(outval[i-1]+outval[i+1])/2.0;
    gapBound=avg*g;
    v=inpval[i];
    outval[i]=Math.Max(v-gapBound, Math.Min(v+gapBound, avg));
   }
   
   avg=(outval[0]+outval[1])/2.0;
   gapBound=avg*g;
   v=inpval[0];
   outval[0]=Math.Max(v-gapBound, Math.Min(v+gapBound, avg));
 
   avg=(outval[from-1]+outval[from])/2.0;
   gapBound=avg*g;
   v=inpval[from];
   outval[from]=Math.Max(v-gapBound, Math.Min(v+gapBound, avg));
  }
 
  for(int i=-from, o=0; i<=0; i++, o++) _series_out[i]=outval[o];
 };
 //-------------------------------------------------------------

 if(CurrentIndex<MaxIndex) return;     // отрисовка только на правом краю графика

 UFilter(Input, (int)Period, (double)Gap, (int)Iterations, UF);
}

Как вы, очевидно, заметили, индикатор правит точки в прошлом, поэтому его нельзя использовать в тестировании/оптимизации стратегии. Для нормального тестирования следует перетащить ф-цию UFilter непосредственно в код стратегии и считать ее уже там на каждом шаге.

UF sample.png

Число итераций можно делать достаточно большим (десятки и даже сотни).
На графике есть изломы; они как раз находятся на месте гэпов.
На каждом следующем шаге расчета форма кривой может существенно поменяться (при смене направления движения, особенно с гэпом).

Не стоит обольщаться "красивым" следованием за графиком цен, т.к. сглаживание идет по уже известным данным в прошлом.
Интерес представляют несколько (2-3...) крайних правых точек. Производную UF (в простейшем случае просто разность UF[0]-UF[-1]; обычно такая разность сильно шумит, но UF сам по себе сглажен, так что в данном случае шума нет) можно, например, использовать для построения экстраполятора в будущее ... (которое, как известно, от прошлого особо не зависит :mrgreen: )

Можно пытаться использовать две кривые с разной степенью фильтрации вместо обычных бегущих средних. Отличие тут в том, что "быстрая" кривая, обеспечивая нужное сглаживание, может все же лучше следить за текущими колебаниями за счет того, что фильтр не имеет фиксированной частоты среза, т.е. адаптивен и не так сильно отстает от входных данных.

Вернуться в «Пользовательские индикаторы»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 5 гостей