Calculate Exponential Moving Average In Python


Answer :

EDIT: It seems that mov_average_expw() function from scikits.timeseries.lib.moving_funcs submodule from SciKits (add-on toolkits that complement SciPy) better suits the wording of your question.


To calculate an exponential smoothing of your data with a smoothing factor alpha (it is (1 - alpha) in Wikipedia's terms):

>>> alpha = 0.5 >>> assert 0 < alpha <= 1.0 >>> av = sum(alpha**n.days * iq  ...     for n, iq in map(lambda (day, iq), today=max(days): (today-day, iq),  ...         sorted(zip(days, IQ), key=lambda p: p[0], reverse=True))) 95.0 

The above is not pretty, so let's refactor it a bit:

from collections import namedtuple from operator    import itemgetter  def smooth(iq_data, alpha=1, today=None):     """Perform exponential smoothing with factor `alpha`.      Time period is a day.     Each time period the value of `iq` drops `alpha` times.     The most recent data is the most valuable one.     """     assert 0 < alpha <= 1      if alpha == 1: # no smoothing         return sum(map(itemgetter(1), iq_data))      if today is None:         today = max(map(itemgetter(0), iq_data))      return sum(alpha**((today - date).days) * iq for date, iq in iq_data)  IQData = namedtuple("IQData", "date iq")  if __name__ == "__main__":     from datetime import date      days = [date(2008,1,1), date(2008,1,2), date(2008,1,7)]     IQ = [110, 105, 90]     iqdata = list(map(IQData, days, IQ))     print("\n".join(map(str, iqdata)))      print(smooth(iqdata, alpha=0.5)) 

Example:

$ python26 smooth.py IQData(date=datetime.date(2008, 1, 1), iq=110) IQData(date=datetime.date(2008, 1, 2), iq=105) IQData(date=datetime.date(2008, 1, 7), iq=90) 95.0 

I did a bit of googling and I found the following sample code (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 

I'm always calculating EMAs with Pandas:

Here is an example how to do it:

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) 

More infos about Pandas EWMA:

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


Comments

Popular posts from this blog

Converting A String To Int In Groovy

"Cannot Create Cache Directory /home//.composer/cache/repo/https---packagist.org/, Or Directory Is Not Writable. Proceeding Without Cache"

Android How Can I Convert A String To A Editable