Экспоненциальная скользящая средняя по временному интервалу [дубликат]

Ну, простыми словами:

Вы пытаетесь получить доступ к объекту, который не создан или в настоящее время не находится в памяти.

Итак, как это решить:

  1. Отладить и отпустить отладчик ... Он сразу приведет вас к переменной, которая сломана ... Теперь ваша задача - просто исправить это. Используя новое ключевое слово в соответствующем месте.
  2. Если это вызвано некоторыми командами базы данных, потому что объект отсутствует, все, что вам нужно сделать, это выполнить нулевую проверку и обработать его:
    if (i == null) {
        // Handle this
    }
    
  3. Самый сложный. если GC уже собрал объект ... Это обычно происходит, если вы пытаетесь найти объект, используя строки ... То есть, найдя его по имени объекта, может случиться, что GC, возможно, уже очистил его ... Это трудно найти и станет проблемой. Лучшим способом решения этой проблемы является выполнение нулевых проверок везде, где это необходимо в процессе разработки. Это сэкономит вам много времени.

Поиск по имени означает, что некоторые фреймворки позволяют использовать FIndObjects с помощью строк, а код может выглядеть так: FindObject («ObjectName»);

18
задан Jason S 28 January 2009 в 19:07
поделиться

10 ответов

Мой python немного ржавый (любой может отредактировать этот код, чтобы внести исправления, если я каким-то образом испортил синтаксис), но здесь идет ....

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

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

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

(SIDE ПРИМЕЧАНИЕ: если бы я использовал язык, отличный от python, я Сначала создайте полноразмерный пустой массив, а затем залейте его назад-порядок, чтобы мне не пришлось отменить его в конце. Но я не думаю, что вы можете объявить большой пустой массив в python. python list, добавление намного дешевле, чем добавление, поэтому я создал список в обратном порядке. Пожалуйста, исправьте меня, если я ошибаюсь.)

Аргумент «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)
17
ответ дан jfs 28 August 2018 в 18:11
поделиться
  • 1
    Как вы применяете его к не непрерывным данным, когда он доступен в неравномерных временных интервалах, например, в вопросе: сегодня, 5 дней назад, 6 дней назад? – jfs 29 January 2009 в 00:33
  • 2
    Синтаксис в основном правильный, за исключением: '||' - & GT; 'или', '& amp; & amp;' - & GT; 'и', 'list.length' - & gt; 'len (list)', скобки рядом с if, while не нужны. Вы можете создать копию списка в Python: result = values[:] или создать большой «пустой». один: result = [None]*len(values). – jfs 29 January 2009 в 00:43
  • 3
    Условия могут быть записаны следующим образом: если не 0 & lt; = alpha & lt; = 1: повысить значение ValueError («вне диапазона», ожидается 0..1 получить: «% s» «% альфа») – jfs 29 January 2009 в 00:57
  • 4
    Ваш алгоритм квадратичен, когда (alpha == 1 или epsilon == 0). M = log (epsilon) / log (alpha) может быть большим фактором (количество времени, в течение которого внутренний цикл выполняется, если len (значения) велико), поэтому я бы не стал беспокоиться о values.reverse() - это еще один передавать данные. – jfs 29 January 2009 в 01:06
  • 5
    Существуют алгоритмы, позволяющие вычислять AWME за один проход (см. ema() из ответа @ earino и mov_average_expw() из моего. – jfs 29 January 2009 в 01:07
  • 6
    Привет, Ю.Ф. Себастьян, я бы хотел использовать эту формулу EWMA, чтобы показывать тенденции на моем сайте. Я разместил вопрос о SO - stackoverflow.com/questions/9283856 . Кто-то предложил алгоритм EWMA для этого, поскольку мне нужно больше внимания уделять последним, чем более старым. Поскольку у меня нет опыта работы со статистикой, я немного смущен относительно того, как я вычисляю значение α. Любая помощь? Спасибо. – Mridang Agarwalla 20 February 2012 в 17:09
  • 7
    Связанные страницы больше не доступны, можете ли вы их обновить? – sebix 6 October 2014 в 17:05
  • 8
    @sebix: не стесняйтесь редактировать. Если google не помогает, попробуйте wayback machine – jfs 6 October 2014 в 17:07

Я всегда вычисляю EMA с помощью Pandas:

Вот пример, как это сделать:

import pandas as pd
import numpy as np

def ema(values, period):
    values = np.array(values)
    return pd.ewma(values, span=period)[-1]

values = [9, 5, 10, 16, 5]
period = 5

print ema(values, period)

Дополнительная информация о Pandas EWMA:

http://pandas.pydata.org/pandas-docs/stable/generated/pandas.ewma.html

6
ответ дан bdriven 28 August 2018 в 18:11
поделиться
  • 1
    Не более новые версии Pandas имеют новые и лучшие функции ? – Cristian Ciupitu 11 May 2016 в 14:10

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

y_new = y_old + (input - y_old)*alpha

, где alpha = dt / tau, dt = timestep фильтра, tau = постоянная времени фильтра? (форма переменной-timestep заключается в следующем: просто клип dt / tau не должен быть больше 1.0)

y_new = y_old + (input - y_old)*dt/tau

Если вы хотите отфильтровать что-то вроде даты, убедитесь, что вы конвертируете в число с плавающей запятой, например, количество секунд с 1 января 1970 г.

4
ответ дан Jason S 28 August 2018 в 18:11
поделиться

Я немного искал поисковую систему, и я нашел следующий пример кода ( http://osdir.com/ml/python.matplotlib.general/2005-04/msg00044.html ):

def ema(s, n):
    """
    returns an n period exponential moving average for
    the time series s

    s is a list ordered from oldest (index 0) to most
    recent (index -1)
    n is an integer

    returns a numeric array of the exponential
    moving average
    """
    s = array(s)
    ema = []
    j = 1

    #get n sma first and calculate the next n period ema
    sma = sum(s[:n]) / n
    multiplier = 2 / float(1 + n)
    ema.append(sma)

    #EMA(current) = ( (Price(current) - EMA(prev) ) x Multiplier) + EMA(prev)
    ema.append(( (s[n] - sma) * multiplier) + sma)

    #now calculate the rest of the values
    for i in s[n+1:]:
        tmp = ( (i - ema[j]) * multiplier) + ema[j]
        j = j + 1
        ema.append(tmp)

    return ema
8
ответ дан Joe Holloway 28 August 2018 в 18:11
поделиться
  • 1
    Почему функция использует локальную переменную с тем же именем, что и функция? Помимо того, что код был немного менее разборчивым, он мог бы затруднить обнаружение логических ошибок дальше по строке ... – Homunculus Reticulli 4 June 2012 в 12:13
  • 2
    в чем смысл s = array(s)? У меня были синтаксические ошибки, пока я просто не прокомментировал это. – swdev 6 November 2017 в 08:43

Вы также можете использовать метод фильтра SciPy, потому что EMA является IIR-фильтром. Это будет иметь преимущество примерно в 64 раза быстрее, чем измерено в моей системе, используя timeit для больших наборов данных по сравнению с подходом enumerate () .

import numpy as np
from scipy.signal import lfilter

x = np.random.normal(size=1234)
alpha = .1 # smoothing coefficient
zi = [x[0]] # seed the filter state with first value
# filter can process blocks of continuous data if <zi> is maintained
y, zi = lfilter([1.-alpha], [1., -alpha], x, zi=zi)
2
ответ дан papahabla 28 August 2018 в 18:11
поделиться

Я нашел приведенный выше фрагмент кода by @earino довольно полезным - но мне нужно было что-то, что могло бы непрерывно сглаживать поток значений, поэтому я реорганизовал его на это:

def exponential_moving_average(period=1000):
    """ Exponential moving average. Smooths the values in v over ther period. Send in values - at first it'll return a simple average, but as soon as it's gahtered 'period' values, it'll start to use the Exponential Moving Averge to smooth the values.
    period: int - how many values to smooth over (default=100). """
    multiplier = 2 / float(1 + period)
    cum_temp = yield None  # We are being primed

    # Start by just returning the simple average until we have enough data.
    for i in xrange(1, period + 1):
        cum_temp += yield cum_temp / float(i)

    # Grab the timple avergae
    ema = cum_temp / period

    # and start calculating the exponentially smoothed average
    while True:
        ema = (((yield ema) - ema) * multiplier) + ema

, и я использую его как это:

def temp_monitor(pin):
    """ Read from the temperature monitor - and smooth the value out. The sensor is noisy, so we use exponential smoothing. """
    ema = exponential_moving_average()
    next(ema)  # Prime the generator

    while True:
        yield ema.send(val_to_temp(pin.read()))

(где pin.read () создает следующее значение, которое я хотел бы использовать).

2
ответ дан Rikard Anglerud 28 August 2018 в 18:11
поделиться

В примерах matplotlib.org ( http://matplotlib.org/examples/pylab_examples/finance_work2.html ) показан один хороший пример функции экспоненциального скользящего среднего (EMA) с использованием numpy:

def moving_average(x, n, type):
    x = np.asarray(x)
    if type=='simple':
        weights = np.ones(n)
    else:
        weights = np.exp(np.linspace(-1., 0., n))

    weights /= weights.sum()

    a =  np.convolve(x, weights, mode='full')[:len(x)]
    a[:n] = a[n]
    return a
5
ответ дан sebix 28 August 2018 в 18:11
поделиться

Быстрый способ (скопированный с здесь ) следующий:

def ExpMovingAverage(values, window):
    """ Numpy implementation of EMA
    """
    weights = np.exp(np.linspace(-1., 0., window))
    weights /= weights.sum()
    a =  np.convolve(values, weights, mode='full')[:len(values)]
    a[:window] = a[window]
    return a
0
ответ дан silgon 28 August 2018 в 18:11
поделиться

Вот простой пример, который я разработал на основе http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:moving_averages

Обратите внимание, что в отличие от их таблицы, я не вычисляю SMA, и я не жду, чтобы создать EMA после 10 выборок. Это означает, что мои значения немного отличаются друг от друга, но если вы его нарисуете, то это будет точно после 10 образцов. Во время первых 10 выборок EMA, которые я вычисляю, соответствующим образом сглаживается.

def emaWeight(numSamples):
    return 2 / float(numSamples + 1)

def ema(close, prevEma, numSamples):
    return ((close-prevEma) * emaWeight(numSamples) ) + prevEma

samples = [
22.27, 22.19, 22.08, 22.17, 22.18, 22.13, 22.23, 22.43, 22.24, 22.29,
22.15, 22.39, 22.38, 22.61, 23.36, 24.05, 23.75, 23.83, 23.95, 23.63,
23.82, 23.87, 23.65, 23.19, 23.10, 23.33, 22.68, 23.10, 22.40, 22.17,
]
emaCap = 10
e=samples[0]
for s in range(len(samples)):
    numSamples = emaCap if s > emaCap else s
    e =  ema(samples[s], e, numSamples)
    print e
1
ответ дан user9170 28 August 2018 в 18:11
поделиться

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

def expma(aseries, ratio):
    return sum([ratio*aseries[-x-1]*((1-ratio)**x) for x in range(len(aseries))])
0
ответ дан Xiaotian 28 August 2018 в 18:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: