【发布时间】:2022-09-27 09:49:21
【问题描述】:
我是 pandas 的新手,正在尝试将指标从 pine 脚本迁移到 python。我有一个计算依赖于动态计算的前一行值来获取当前行的值。我只能使用 for 循环来做到这一点,并且还没有找到使用 numpy 或 dataframe.apply 来做到这一点的好方法。问题是这个计算运行得非常慢,太慢了,无法用于我的目的。仅 21951 行 14 秒。
有谁知道如何在熊猫中以更有效的方式做到这一点?当我构建其他指标时,弄清楚这一点肯定会对我有所帮助,因为大多数指标都依赖于先前的行值。
\"\"\"
//
// @author LazyBear
// List of all my indicators:
// https://docs.google.com/document/d/15AGCufJZ8CIUvwFJ9W-IKns88gkWOKBCvByMEvm5MLo/edit?usp=sharing
//
study(title=\"Coral Trend Indicator [LazyBear]\", shorttitle=\"CTI_LB\", overlay=true)
src=close
sm =input(21, title=\"Smoothing Period\")
cd = input(0.4, title=\"Constant D\")
ebc=input(false, title=\"Color Bars\")
ribm=input(false, title=\"Ribbon Mode\")
\"\"\"
# @jit(nopython=True) -- Tried this but was getting an error ==> argument 0: Cannot determine Numba type of <class \'pandas.core.frame.DataFrame\'>
def coral_trend_filter(df, sm = 21, cd = 0.4):
new_df = df.copy()
di = (sm - 1.0) / 2.0 + 1.0
c1 = 2 / (di + 1.0)
c2 = 1 - c1
c3 = 3.0 * (cd * cd + cd * cd * cd)
c4 = -3.0 * (2.0 * cd * cd + cd + cd * cd * cd)
c5 = 3.0 * cd + 1.0 + cd * cd * cd + 3.0 * cd * cd
new_df[\'i1\'] = 0
new_df[\'i2\'] = 0
new_df[\'i3\'] = 0
new_df[\'i4\'] = 0
new_df[\'i5\'] = 0
new_df[\'i6\'] = 0
for i in range(1, len(new_df)):
new_df.loc[i, \'i1\'] = c1*new_df.loc[i, \'close\'] + c2*new_df.loc[i - 1, \'i1\']
new_df.loc[i, \'i2\'] = c1*new_df.loc[i, \'i1\'] + c2*new_df.loc[i - 1, \'i2\']
new_df.loc[i, \'i3\'] = c1*new_df.loc[i, \'i2\'] + c2*new_df.loc[i - 1, \'i3\']
new_df.loc[i, \'i4\'] = c1*new_df.loc[i, \'i3\'] + c2*new_df.loc[i - 1, \'i4\']
new_df.loc[i, \'i5\'] = c1*new_df.loc[i, \'i4\'] + c2*new_df.loc[i - 1, \'i5\']
new_df.loc[i, \'i6\'] = c1*new_df.loc[i, \'i5\'] + c2*new_df.loc[i - 1, \'i6\']
new_df[\'cif\'] = -cd*cd*cd*new_df[\'i6\'] + c3*new_df[\'i5\'] + c4*new_df[\'i4\'] + c5*new_df[\'i3\']
new_df.dropna(inplace=True)
# trend direction
new_df[\'cifd\'] = 0
# trend direction color
new_df[\'cifd\'] = \'blue\'
new_df[\'cifd\'] = np.where(new_df[\'cif\'] < new_df[\'cif\'].shift(-1), 1, -1)
new_df[\'cifc\'] = np.where(new_df[\'cifd\'] == 1, \'green\', \'red\')
new_df.drop(columns=[\'i1\', \'i2\', \'i3\', \'i4\', \'i5\', \'i6\'], inplace=True)
return new_df
df = coral_trend_filter(data_frame)
评论回复: 一个建议是使用 shift。由于在每次迭代中都会更新每行计算,因此这不起作用。移位存储初始值并且不更新移位的列,因此计算值是错误的。请参阅此屏幕截图,该屏幕截图与 cif 列中的原始屏幕不匹配。另请注意,我留在 shift_i1 以显示列保持为 0,这对于计算是不正确的。
更新:
通过更改为使用.at 而不是.loc,我获得了明显更好的性能。我的问题可能是我在这种类型的处理中使用了错误的访问器。
标签: python pandas dataframe numpy