Coding the exponential moving average with Python

元气小坏坏 提交于 2019-11-30 18:38:19

问题


I want to do calculations on three columns of a dataframe df. In order to do that I want run a price of assets (cryptocurrencies) list in a three column table in order to calculate the exponential moving average of them after having enough data.

def calculateAllEMA(self,values_array):
    df = pd.DataFrame(values_array, columns=['BTC', 'ETH', 'DASH'])
    column_by_search = ["BTC", "ETH", "DASH"]
    print(df)
    for i,column in enumerate(column_by_search):
        ema=[]
        # over and over for each day that follows day 23 to get the full range of EMA
        for j in range(0, len(column)-24):
            # Add the closing prices for the first 22 days together and divide them by 22.
            EMA_yesterday = column.iloc[1+j:22+j].mean()
            k = float(2)/(22+1)
            # getting the first EMA day by taking the following day’s (day 23) closing price multiplied by k, then multiply the previous day’s moving average by (1-k) and add the two.
            ema.append(column.iloc[23 + j]*k+EMA_yesterday*(1-k))
        print("ema")
        print(ema)
        mean_exp[i] = ema[-1]
    return mean_exp

Yet, when I print what's in len(column)-24 I get -21 (-24 + 3 ?). I can't therefore go through the loop. How can I cope with this error to get exponential moving average of the assets ?

I tried to apply this link from iexplain.com for the pseudo code of the exponential moving average.

If you have any easier idea, I'm open to hear it.

Here is the data that I use to calculate it when it bugs :

        BTC     ETH    DASH
0   4044.59  294.40  196.97
1   4045.25  294.31  196.97
2   4044.59  294.40  196.97
3   4045.25  294.31  196.97
4   4044.59  294.40  196.97
5   4045.25  294.31  196.97
6   4044.59  294.40  196.97
7   4045.25  294.31  196.97
8   4045.25  294.31  196.97
9   4044.59  294.40  196.97
10  4045.25  294.31  196.97
11  4044.59  294.40  196.97
12  4045.25  294.31  196.97
13  4045.25  294.32  197.07
14  4045.25  294.31  196.97
15  4045.41  294.46  197.07
16  4045.25  294.41  197.07
17  4045.41  294.41  197.07
18  4045.41  294.47  197.07
19  4045.25  294.41  197.07
20  4045.25  294.32  197.07
21  4045.43  294.35  197.07
22  4045.41  294.46  197.07
23  4045.25  294.41  197.07

回答1:


pandas.stats.moments.ewma from the original answer has been deprecated.

Instead you can use pandas.DataFrame.ewm as documented here.


Below is a complete snippet with random data that builds a dataframe with calculated ewmas from specified columns.

Code:

# imports
import pandas as pd
import numpy as np

np.random.seed(123)

rows = 50
df = pd.DataFrame(np.random.randint(90,110,size=(rows, 3)), columns=['BTC', 'ETH', 'DASH'])
datelist = pd.date_range(pd.datetime(2017, 1, 1).strftime('%Y-%m-%d'), periods=rows).tolist()
df['dates'] = datelist 
df = df.set_index(['dates'])
df.index = pd.to_datetime(df.index)

def ewmas(df, win, keepSource):
    """Add exponentially weighted moving averages for all columns in a dataframe.

    Arguments: 
    df -- pandas dataframe
    win -- length of ewma estimation window
    keepSource -- True or False for keep or drop source data in output dataframe

    """

    df_temp = df.copy()

    # Manage existing column names
    colNames = list(df_temp.columns.values).copy()
    removeNames = colNames.copy()

    i = 0
    for col in colNames:

        # Make new names for ewmas
        ewmaName = colNames[i] + '_ewma_' + str(win)   

        # Add ewmas
        #df_temp[ewmaName] = pd.stats.moments.ewma(df[colNames[i]], span = win)
        df_temp[ewmaName] = df[colNames[i]].ewm(span = win, adjust=True).mean()

        i = i + 1

    # Remove estimates with insufficient window length
    df_temp = df_temp.iloc[win:]

    # Remove or keep source data
    if keepSource == False:
        df_temp = df_temp.drop(removeNames,1)

    return df_temp

# Test run
df_new = ewmas(df = df, win = 22, keepSource = True)
print(df_new.tail())

Output:

             BTC  ETH   DASH  BTC_ewma_22  ETH_ewma_22    DASH_ewma_22
dates                                                             
2017-02-15   91   96    98    98.752431    100.081052     97.926787
2017-02-16  100  102   102    98.862445    100.250270     98.285973
2017-02-17  100  107    97    98.962634    100.844749     98.172712
2017-02-18  103  102    91    99.317826    100.946384     97.541684
2017-02-19   99  104    91    99.289894    101.214755     96.966758

Plot using df_new[['BTC', 'BTC_ewma_22']].plot():




回答2:


In your loop for i,column in enumerate(column_by_search): you iterate over the elements in your column_by_search list, that is column takes on the values "BTC", "ETH", "DASH" in turn. Thus, len(column) will give you the length of the string "BTC", which is 3 in fact.

Try df[column] instead, that will return a list with the elements in the desired column and you can iterate over it.



来源:https://stackoverflow.com/questions/45665217/coding-the-exponential-moving-average-with-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!