web-dev-qa-db-ja.com

Pandas EWMの計算が間違っていますか?

データフレームの財務データから指数移動平均(EMA)を計算しようとすると、パンダスの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を適切に計算する方法(またはその場合)を誰かに教えてもらえますか?

10
jeronimo

指数移動平均を初期化する方法はいくつかあるので、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
10
chrisb

Pandas span関数でアルファまたは係数(ewm)を使用してEWMAを計算できます。

アルファを使用するための式:_(1 - alpha) * previous_val + alpha * current_val_ where _alpha = 1 / period_

Coeffを使用するための式:_((current_val - previous_val) * coeff) + previous_val_ where 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()
_
6
arkochhar

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
Ben

Ewmのewm(MACD式のように)を計算している場合、2番目以降の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()
0
tentativafc