Pandas 计算 ewm 是不是错误?

Posted

技术标签:

【中文标题】Pandas 计算 ewm 是不是错误?【英文标题】:Does Pandas calculate ewm wrong?Pandas 计算 ewm 是否错误? 【发布时间】:2016-10-21 19:38:51 【问题描述】:

当尝试从数据框中的财务数据计算指数移动平均线 (EMA) 时,Pandas 的 ewm 方法似乎不正确。

下面的链接很好地解释了基础知识: http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:moving_averages

去Pandas讲解时,采取的做法如下(使用“adjust”参数为False):

   weighted_average[0] = arg[0];
   weighted_average[i] = (1-alpha) * weighted_average[i-1] + alpha * arg[i]

在我看来这是不正确的。 “arg”应该是(例如)收盘值,但是,arg[0] 是第一个平均值(即所选期间长度的第一系列数据的简单平均值),但不是第一个收盘值.因此,arg[0] 和 arg[i] 永远不能来自相同的数据。使用“min_periods”参数似乎无法解决此问题。

谁能解释我如何(或是否)可以使用 Pandas 来正确计算数据的 EMA?

【问题讨论】:

相关github问题:github.com/pydata/pandas/issues/13638 pandas issue 13638 is still open,如果你想看到它的实现,你可以关注、点赞和贡献代码。 【参考方案1】:

如果您正在计算 ewm 的 ewm(如 MACD 公式),您将得到不好的结果,因为第二个和后面的 ewm 将使用从 0 开始并以句点结尾的索引。我使用以下解决方案。

sma = df['Close'].rolling(period, min_periods=period).mean()
#this variable is used to shift index by non null start minus period
idx_start = sma.isna().sum() + 1 - period
idx_end = idx_start + period
sma = sma[idx_start: idx_end]
rest = df[item][idx_end:]
ema = pd.concat([sma, rest]).ewm(span=period, adjust=False).mean()

【讨论】:

item 指的是什么?【参考方案2】:

以下是 Pandas 如何计算调整和未调整 ewm 的示例:

name = 'closing'
series = pd.Series([1, 2, 3, 5, 8, 13, 21, 34], name=name).to_frame()
period = 4
alpha = 2/(1+period)

series[name+'_ewma'] = np.nan
series.loc[0, name+'_ewma'] = series[name].iloc[0]

series[name+'_ewma_adjust'] = np.nan
series.loc[0, name+'_ewma_adjust'] = series[name].iloc[0]

for i in range(1, len(series)):
    series.loc[i, name+'_ewma'] = (1-alpha) * series.loc[i-1, name+'_ewma'] + alpha * series.loc[i, name]

    ajusted_weights = np.array([(1-alpha)**(i-t) for t in range(i+1)])
    series.loc[i, name+'_ewma_adjust'] = np.sum(series.iloc[0:i+1][name].values * ajusted_weights) / ajusted_weights.sum()

print(series)
print("diff adjusted=False -> ", np.sum(series[name+'_ewma'] - series[name].ewm(span=period, adjust=False).mean()))
print("diff adjusted=True -> ", np.sum(series[name+'_ewma_adjust'] - series[name].ewm(span=period, adjust=True).mean()))

数学公式可以在https://github.com/pandas-dev/pandas/issues/8861找到

【讨论】:

【参考方案3】:

您可以在 Pandas ewm 函数中使用 alpha 或系数 (span) 计算 EWMA。

使用 alpha 的公式:(1 - alpha) * previous_val + alpha * current_val 其中alpha = 1 / period

系数使用公式:((current_val - previous_val) * coeff) + previous_val 其中coeff = 2 / (period + 1)

以下是使用 Pandas 计算上述公式的方法:

con = pd.concat([df[:period][base].rolling(window=period).mean(), df[period:][base]])

if (alpha == True):
    df[target] = con.ewm(alpha=1 / period, adjust=False).mean()
else:
    df[target] = con.ewm(span=period, adjust=False).mean()

【讨论】:

我不明白你的代码中的“基础”是什么,你可能根本不需要它。此外,隐蔽期浮动会更安全,特别是对于 python 2。否则很好的答案 抱歉含糊不清。 base 是 DataFrame 中要计算 EWMA 的基列。 小修正 df[target] = con.ewm(alpha=1.0 / period, adjust=False).mean()【参考方案4】:

有几种方法可以初始化指数移动平均线,所以我不会说 pandas 做错了,只是不同而已。

这是一种按照您的意愿计算的方法:

In [20]: s.head()
Out[20]: 
0    22.27
1    22.19
2    22.08
3    22.17
4    22.18
Name: Price, dtype: float64

In [21]: span = 10

In [22]: sma = s.rolling(window=span, min_periods=span).mean()[:span]

In [24]: rest = s[span:]

In [25]: pd.concat([sma, rest]).ewm(span=span, adjust=False).mean()
Out[25]: 
0           NaN
1           NaN
2           NaN
3           NaN
4           NaN
5           NaN
6           NaN
7           NaN
8           NaN
9     22.221000
10    22.208091
11    22.241165
12    22.266408
13    22.328879
14    22.516356
15    22.795200
16    22.968800
17    23.125382
18    23.275312
19    23.339801
20    23.427110
21    23.507635
22    23.533520
23    23.471062
24    23.403596
25    23.390215
26    23.261085
27    23.231797
28    23.080561
29    22.915004
Name: Price, dtype: float64

【讨论】:

由于一个我无法解释的原因,我需要这行代码的一种稍微不同的形式 (@chrisb):pd.concat([sma, rest]).ewm(alpha=1/span, adjust=False).mean() 有了这个,它达到了我的预期并采用了之前的平均值,乘以 (span - 1),加上新值,然后将总数除以跨度。 使用 ewm 给我一个 TypeError: unsupported operand type(s) for /: 'EWM' and 'EWM' ,这是为什么呢?如何解决?我正在使用带有 spyder 的 windows 系统作为 anaconda 的 ide。我的熊猫版本是 1.0.5

以上是关于Pandas 计算 ewm 是不是错误?的主要内容,如果未能解决你的问题,请参考以下文章

Pandas 中的 EWM 用于时间序列转换

NumPy 版本的“指数加权移动平均线”,相当于 pandas.ewm().mean()

Pandas。滚动指定时间窗口和win_type

Python Pandas 错误

Pandas to PySpark给出OOM错误而不是溢出到磁盘[重复]

如何修复 Jupyter Notebook pandas 错误(OSError:[WinError 193] %1 不是有效的 Win32 应用程序)