威尔斯·怀尔德的移动平均线 pandas
Welles Wilder's moving average with pandas
我正在尝试计算熊猫数据框中 Welles Wilder 的移动平均线类型(也称为累积移动平均线)。
计算系列 'n' 周期 'A' 的 Wilder 移动平均线的方法是:
- 计算'A'中前'n'个值的平均值,并设置为'n'位置的平均值。
- 对于以下值,使用加权 (n-1) 的先前平均值和加权 1 的系列的当前值,然后全部除以 'n'。
我的问题是:如何以矢量化的方式实现它?
我尝试在数据帧上进行迭代(不推荐我阅读的内容,因为速度很慢)。它有效,值正确,但我收到错误
SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
这可能不是最有效的方法。
到目前为止我的代码:
import pandas as pd
import numpy as np
#Building Random sample:
datas = pd.date_range('2020-01-01','2020-01-31')
np.random.seed(693)
A = np.random.randint(40,60, size=(31,1))
df = pd.DataFrame(A,index = datas, columns = ['A'])
period = 12 # Main parameter
initial_mean = A[0:period].mean() # Equation for the first value.
size = len(df.index)
df['B'] = np.full(size, np.nan)
df.B[period-1] = initial_mean
for x in range(period, size):
df.B[x] = ((df.A[x] + (period-1)*df.B[x-1]) / period) # Equation for the following values.
print(df)
您可以使用 Pandas ewm()
方法,它的行为与您在 adjust=False
:
时描述的完全一样
When adjust is False, weighted averages are calculated recursively as:
weighted_average[0] = arg[0];
weighted_average[i] = (1-alpha)*weighted_average[i-1] + alpha*arg[i]
如果您想对第一个 周期 项进行简单平均,您可以先进行计算,然后将 ewm()
应用于结果。
你可以用第一个 period 项的平均值计算一个系列,然后是其他项目逐字重复,公式为:
pd.Series(
data=[df['A'].iloc[:period].mean()],
index=[df['A'].index[period-1]],
).append(
df['A'].iloc[period:]
)
因此,为了计算 Wilder 移动平均线并将其存储在新列中 'C'
,您可以使用:
df['C'] = pd.Series(
data=[df['A'].iloc[:period].mean()],
index=[df['A'].index[period-1]],
).append(
df['A'].iloc[period:]
).ewm(
alpha=1.0 / period,
adjust=False,
).mean()
此时,你可以计算df['B'] - df['C']
,你会发现差异几乎为零(浮点数有一些舍入误差。)所以这相当于你使用循环计算。
您可能需要考虑跳过第一个 周期 项之间的直接平均值,并简单地从头开始应用 ewm()
,这将假定第一行 是第一次计算的前一个平均值。结果会略有不同,但是一旦您经历了几个 周期 ,那么这些初始值几乎不会影响结果。
这样计算会更简单:
df['D'] = df['A'].ewm(
alpha=1.0 / period,
adjust=False,
).mean()
我正在尝试计算熊猫数据框中 Welles Wilder 的移动平均线类型(也称为累积移动平均线)。
计算系列 'n' 周期 'A' 的 Wilder 移动平均线的方法是:
- 计算'A'中前'n'个值的平均值,并设置为'n'位置的平均值。
- 对于以下值,使用加权 (n-1) 的先前平均值和加权 1 的系列的当前值,然后全部除以 'n'。
我的问题是:如何以矢量化的方式实现它?
我尝试在数据帧上进行迭代(不推荐我阅读的内容,因为速度很慢)。它有效,值正确,但我收到错误
SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
这可能不是最有效的方法。
到目前为止我的代码:
import pandas as pd
import numpy as np
#Building Random sample:
datas = pd.date_range('2020-01-01','2020-01-31')
np.random.seed(693)
A = np.random.randint(40,60, size=(31,1))
df = pd.DataFrame(A,index = datas, columns = ['A'])
period = 12 # Main parameter
initial_mean = A[0:period].mean() # Equation for the first value.
size = len(df.index)
df['B'] = np.full(size, np.nan)
df.B[period-1] = initial_mean
for x in range(period, size):
df.B[x] = ((df.A[x] + (period-1)*df.B[x-1]) / period) # Equation for the following values.
print(df)
您可以使用 Pandas ewm()
方法,它的行为与您在 adjust=False
:
When adjust is False, weighted averages are calculated recursively as:
weighted_average[0] = arg[0]; weighted_average[i] = (1-alpha)*weighted_average[i-1] + alpha*arg[i]
如果您想对第一个 周期 项进行简单平均,您可以先进行计算,然后将 ewm()
应用于结果。
你可以用第一个 period 项的平均值计算一个系列,然后是其他项目逐字重复,公式为:
pd.Series(
data=[df['A'].iloc[:period].mean()],
index=[df['A'].index[period-1]],
).append(
df['A'].iloc[period:]
)
因此,为了计算 Wilder 移动平均线并将其存储在新列中 'C'
,您可以使用:
df['C'] = pd.Series(
data=[df['A'].iloc[:period].mean()],
index=[df['A'].index[period-1]],
).append(
df['A'].iloc[period:]
).ewm(
alpha=1.0 / period,
adjust=False,
).mean()
此时,你可以计算df['B'] - df['C']
,你会发现差异几乎为零(浮点数有一些舍入误差。)所以这相当于你使用循环计算。
您可能需要考虑跳过第一个 周期 项之间的直接平均值,并简单地从头开始应用 ewm()
,这将假定第一行 是第一次计算的前一个平均值。结果会略有不同,但是一旦您经历了几个 周期 ,那么这些初始值几乎不会影响结果。
这样计算会更简单:
df['D'] = df['A'].ewm(
alpha=1.0 / period,
adjust=False,
).mean()