Мой питон немного заржавел (любой может смело редактировать этот код, чтобы внести исправления, если я как-то испортил синтаксис), но здесь идет ...
def movingAverageExponential(values, alpha, epsilon = 0):
if not 0 < alpha < 1:
raise ValueError("out of range, alpha='%s'" % alpha)
if not 0 <= epsilon < alpha:
raise ValueError("out of range, epsilon='%s'" % epsilon)
result = [None] * len(values)
for i in range(len(result)):
currentWeight = 1.0
numerator = 0
denominator = 0
for value in values[i::-1]:
numerator += value * currentWeight
denominator += currentWeight
currentWeight *= alpha
if currentWeight < epsilon:
break
result[i] = numerator / denominator
return result
Эта функция перемещается назад, от конца списка к началу, вычисляя экспоненциальную скользящую среднюю для каждого значения, работая в обратном направлении до тех пор, пока весовой коэффициент для элемента не станет меньше указанного эпсилона.
В конце функции происходит обратное изменение значений перед возвратом списка (чтобы они были в правильном порядке для вызывающей стороны).
(ВНИМАНИЕ: если бы я использовал язык, отличный от python, я сначала создал бы пустой массив в натуральную величину, а затем заполнил бы его в обратном порядке, чтобы в конце мне не пришлось обращать его вспять. Но я не думаю, что вы можете объявить большой пустой массив в python. А в списках python добавление намного дешевле, чем добавление, поэтому я построил список в обратном порядке. Пожалуйста, исправьте меня, если я ошибаюсь.)
Аргумент 'alpha' - это коэффициент затухания на каждой итерации. Например, если вы использовали альфа 0,5, то сегодняшнее значение скользящего среднего будет состоять из следующих взвешенных значений:
today: 1.0
yesterday: 0.5
2 days ago: 0.25
3 days ago: 0.125
...etc...
Конечно, если у вас огромный массив значений, значения от десяти до пятнадцати дней назад не будут сильно влиять на средневзвешенное значение сегодняшнего дня. Аргумент 'epsilon' позволяет вам установить точку отсечения, ниже которой вы перестанете заботиться о старых значениях (поскольку их вклад в сегодняшнее значение будет незначительным).
Вы бы вызвали функцию примерно так:
result = movingAverageExponential(values, 0.75, 0.0001)