calculate exponential moving average in python

后端 未结 14 2344
囚心锁ツ
囚心锁ツ 2020-12-01 00:59

I have a range of dates and a measurement on each of those dates. I\'d like to calculate an exponential moving average for each of the dates. Does anybody know how to do t

相关标签:
14条回答
  • 2020-12-01 01:43

    In matplotlib.org examples (http://matplotlib.org/examples/pylab_examples/finance_work2.html) is provided one good example of Exponential Moving Average (EMA) function using 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
    
    0 讨论(0)
  • 2020-12-01 01:44

    more simply, using pandas

    def EMA(tw):
        for x in tw:
            data["EMA{}".format(x)] = data['close'].ewm(span=x, adjust=False).mean()
            EMA([10,50,100])
    
    0 讨论(0)
  • 2020-12-01 01:47

    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
    
    0 讨论(0)
  • 2020-12-01 01:49

    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

    0 讨论(0)
  • 2020-12-01 01:50

    I found the above code snippet by @earino pretty useful - but I needed something that could continuously smooth a stream of values - so I refactored it to this:

    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
    

    and I use it like this:

    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()))
    

    (where pin.read() produces the next value I'd like to consume).

    0 讨论(0)
  • 2020-12-01 01:54

    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
    
    0 讨论(0)
提交回复
热议问题