熊猫计算错了吗?

时间:2016-06-20 13:55:12

标签: pandas exponential moving-average

当尝试从数据框中的财务数据计算指数移动平均线(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?

4 个答案:

答案 0 :(得分:7)

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

这是一种计算它的方法:

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

答案 1 :(得分:6)

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

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

使用coeff的公式:((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()

答案 2 :(得分:3)

以下是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 :(得分:0)

如果您正在计算ewm的ewm(如MACD公式),则结果会很糟糕,因为第二个及之后的ewm将使用从0开始并以句号结尾的索引。我使用以下解决方案。

use strict;
use warning;

my $dirname = "../../../experiment/";
my $keyword = "Book";
my @result;

my $find_file = sub {
    my $F = $File::Find::name;
    if ($F =~ /txt$/) {
       open my $in, "<", $F or die $!;
       while(<$in>) {
          if (/\Q$keyword\E/){
             next;
          }else{
             push @result, $F;
             return;          
          }
      }
   }  
};

find ({ wanted => $find_file, no_chdir=>1}, $dirname );
foreach my $result (@result){
   chomp $result;
   $result =~ s{.*/}{};
   print "$result\n";
}