Требуется средний истинный диапазон и экспоненциальная скользящая средняя для PandasDataSeries

Я застрял при расчете среднего истинного диапазона [ATR] серии. ATR - это, в основном, Exp Movin Avg из TrueRange[TR]

 TR is nothing but MAX of -
       Method 1: Current High less the current Low
       Method 2: Current High less the previous Close (absolute value)
       Method 3: Current Low less the previous Close (absolute value)

В Пандах у нас нет встроенной функции EMA. Скорее у нас есть EWMA, которая является взвешенной скользящей средней.

Если кто-то поможет рассчитать EMA, это тоже будет достаточно хорошо

      def ATR(df,n):
          df['H-L']=abs(df['High']-df['Low'])
          df['H-PC']=abs(df['High']-df['Close'].shift(1))
          df['L-PC']=abs(df['Low']-df['Close'].shift(1))
          df['TR']=df[['H-L','H-PC','L-PC']].max(axis=1)
          df['ATR_' + str(n)] =pd.ewma(df['TR'], span = n, min_periods = n)
          return df

Приведенный выше код не выдает ошибку, но также не дает правильных значений. Я сравнил это с ручным вычислением значений ATR для тех же наборов данных в Excel, и значения были разными

           ATR excel formula-
             Current ATR = [(Prior ATR x 13) + Current TR] / 14

             - Multiply the previous 14-day ATR by 13.
             - Add the most recent day's TR value.
             - Divide the total by 14

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

           start='2016-1-1'
           end='2016-10-30'
           auro=web.DataReader('AUROPHARMA.NS','yahoo',start,end)

2 ответа

Вам нужно использовать ewma. Смотрите здесь: Экспоненциальное скользящее среднее (EMA) - это тип скользящего среднего, который похож на простое скользящее среднее, за исключением того, что более поздним данным присваивается больший вес.

Подробнее: Экспоненциальная скользящая средняя (EMA) http://www.investopedia.com/terms/e/ema.asp

Я не думаю, что ваша формула Excel является правильным... Вот ручной способ расчета EMA в Python

def exponential_average(values, window):
    weights = np.exp(np.linspace(-1.,0.,window))
    weights /= weights.sum()

    a = np.convolve(values, weights) [:len(values)]
    a[:window]=a[window]
    return a

scipy.signal.lfilter может помочь вам.

scipy.signal.lfilter(b, a, x, axis=-1,zi=None)

Функция фильтра реализована в виде прямой II транспонированной структуры. Это означает, что фильтр реализует:

a[0]*y[n] = b[0]*x[n] + b[1]*x[n-1] + ... + b[M]*x[n-M]
                      - a[1]*y[n-1] - ... - a[N]*y[n-N]

Если мы нормализуем приведенную выше формулу, мы получим следующую:

y[n] = b'[0]*x[n] + b'[1]*x[n-1] + ... + b'[M]*x[n-M]
                  - a'[1]*y[n-1] + ... + a'[N]*y[n-N]

где b'[i] = b[i]/a[0], i = 0,1,...,M; a'[j] = a[j]/a[0],j = 1,2,...,N а также a'[0] = 1

Формула экспоненциальной скользящей средней:

y[n] = alpha*x[n] + (1-alpha)*y[n-1]

Таким образом, чтобы применить scipy.signal.lfilter, по формуле выше мы можем установить a и b, как показано ниже:

a[0] = 1, a[1] = -(1-alpha)
b[0] = alpha

Моя реализация, как показано ниже, надеюсь, это поможет вам.

def ema(values, window_size):
    alpha = 2./ (window_size + 1)
    a = np.array([1, alpha - 1.])
    b = np.array([alpha])
    zi = sig.lfilter_zi(b, a)
    y, _ = sig.lfilter(b, a, values, zi=zi)
    return y
Другие вопросы по тегам