データフレームの財務データから指数移動平均(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を適切に計算する方法(またはその場合)を誰かに教えてもらえますか?
指数移動平均を初期化する方法はいくつかあるので、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
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()
_
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()))
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()