Реализация двойного экспоненциального сглаживания, также известного как двойная экспоненциальная скользящая средняя (DEMA)

Если у меня есть данные временных рядов - список пар {x, y} - и я хочу его сгладить, я могу использовать экспоненциальную скользящую среднюю следующим образом:

EMA[data_, alpha_:.1] := 
  Transpose @ {#1, ExponentialMovingAverage[#2, alpha]}& @@ Transpose@data

Как бы вы реализовали двойное экспоненциальное сглаживание?

DEMA[data_, alpha_, gamma_] := (* unstub me! *)

Если бы он сам определил хорошие значения для альфа и гаммы, это было бы очень хорошо.


Связанный с этим вопрос о том, как справиться со случаем, когда во временном ряду есть пробелы, т.е. выборки не распределены равномерно во времени:

Экспоненциальное скользящее среднее, выбранное в разное время


person dreeves    schedule 04.04.2011    source источник
comment
Я почти ничего не понимаю в проблеме, но похоже (из en.wikipedia.org/wiki/Exponential_smoothing), что вам может потребоваться оценка тенденции. reference.wolfram.com/applications/timeseries/   -  person DavidC    schedule 04.04.2011
comment
скажите, пожалуйста, правильно ли выводит код Саши   -  person Mr.Wizard    schedule 04.04.2011
comment
@ Mr.Wizard: Мне это кажется правильным, когда я пробую его на некоторых данных, которые у меня есть. (К сожалению, это также убедило меня, что это не совсем то, что я хочу! Но это моя собственная проблема. Надеюсь, это будет полезно для людей, которые ищут DEMA в системе Mathematica в будущем!)   -  person dreeves    schedule 04.04.2011
comment
Я использовал его несколько раз для анализа финансовых (рыночных) временных рядов. Для чего вы его используете?   -  person Dr. belisarius    schedule 04.04.2011
comment
@belisarius: Я пытался улучшить диету хакера (fourmilab.ch/hackdiet). Например, beeminder.com/d/mass.   -  person dreeves    schedule 12.04.2011


Ответы (2)


Я не уверен, что это самый быстрый код, который можно получить, но, похоже, это делает следующее:

DEMA[data_, alpha_, gamma_] := 
 Module[{st = First[data], bt = data[[2]] - data[[1]], btnew, stnew},
  Reap[
    Sow[st];
    Do[
     stnew = alpha y + (1 - alpha) (st + bt);
     btnew = gamma (stnew - st) + (1 - gamma) bt;
     Sow[stnew];
     st = stnew;
     bt = btnew;
     , {y, Rest@data}]][[-1, 1]
   ]]

Это почти прямо со страницы, на которую вы ссылались. Вы можете изменить начальное условие для b в исходном коде. Первоначальная установка bt равной нулю восстанавливает одноэкспоненциальное сглаживание.

In[81]:= DEMA[{a, b, c, d}, alpha, gamma]

Out[81]= {a, (1 - alpha) b + alpha b, 
 alpha c + (1 - alpha) ((1 - alpha) b + 
     alpha b + (-a + b) (1 - gamma) + (-a + (1 - alpha) b + 
        alpha b) gamma), 
 alpha d + (1 - 
     alpha) (alpha c + (1 - 
        gamma) ((-a + b) (1 - gamma) + (-a + (1 - alpha) b + 
           alpha b) gamma) + (1 - alpha) ((1 - alpha) b + 
        alpha b + (-a + b) (1 - gamma) + (-a + (1 - alpha) b + 
           alpha b) gamma) + 
     gamma (-(1 - alpha) b - alpha b + 
        alpha c + (1 - alpha) ((1 - alpha) b + 
           alpha b + (-a + b) (1 - gamma) + (-a + (1 - alpha) b + 
              alpha b) gamma)))}
person Sasha    schedule 04.04.2011
comment
Спасибо, Саша! Я считаю, что это правильно. Обратите внимание, что это не совсем так, поскольку данные должны быть временными рядами с парами {x, y}. Но это нормально; это аналогично встроенному ExponentialMovingAverage. - person dreeves; 04.04.2011

Вот моя формулировка:

DEMA[data_, alpha_, gamma_] :=
 FoldList[
   Module[{x, y},
     x = #[[1]] + #[[2]];
     y = #2 - alpha x;
     {y + x, #[[2]] + gamma * y}
     ] &,
   {data[[1]], data[[2]] - data[[1]]},
   alpha * Rest@data
 ][[All, 1]]
person Mr.Wizard    schedule 04.04.2011