避免循环计算简单的移动平均交叉衍生信号
Avoid looping to calculate simple moving average crossing-derived signals
我想根据简单移动平均线 (SMA) 交叉计算股票的买入和卖出信号。一旦 SMA_short 高于 SMA_long(即 SMA_difference > 0)。为了避免头寸被卖得太快,我想只有在 SMA_short 已经大大超过交叉点(即 SMA_difference < -1),重要的是,即使这会持续超过一天。
我通过这个 实现了它(见下文):
- 买入和卖出信号由 in 和 out 表示。
- 列 位置 首先考虑 buy_limit。
- In Position_extended 然后为 [=69 的所有情况设置 in =]刚刚穿过SMA_long (SMA_short < SMA_long) 但 SMA_short > -1。为此,它考虑了 i-1 的 Position extended,以防穿越超过一天但 SMA_short剩余:
0 > SMA_short > -1
.
Python代码
import pandas as pd
import numpy as np
index = pd.date_range('20180101', periods=6)
df = pd.DataFrame(index=index)
df["SMA_short"] = [9,10,11,10,10,9]
df["SMA_long"] = 10
df["SMA_difference"] = df["SMA_short"] - df["SMA_long"]
buy_limit = 0
sell_limit = -1
df["Position"] = np.where((df["SMA_difference"] > buy_limit),"in","out")
df["Position_extended"] = df["Position"]
for i in range(1,len(df)):
df.loc[index[i],"Position_extended"] = \
np.where((df.loc[index[i], "SMA_difference"] > sell_limit) \
& (df.loc[index[i-1],"Position_extended"] == "in") \
,"in",df.loc[index[i],'Position'])
print df
结果是:
SMA_short SMA_long SMA_difference Position Position_extended
2018-01-01 9 10 -1 out out
2018-01-02 10 10 0 out out
2018-01-03 11 10 1 in in
2018-01-04 10 10 0 out in
2018-01-05 10 10 0 out in
2018-01-06 9 10 -1 out out
该代码有效,但是,它使用了 for
循环,这会大大降低脚本的速度,并且在该分析的更大范围内变得不适用。由于 SMA 交叉是一种非常常用的工具,我想知道是否有人可以为此找到更优雅、更快速的解决方案。
如果第 T 行需要输入在第 T-1 行计算的值,那么您可能需要进行迭代计算。通常回测是通过按顺序迭代价格数据来完成的。您可以仅根据市场状况计算出一些信号,但除非您从头开始并及时向前推进,否则您不会知道投资组合价值、盈亏或投资组合头寸。这就是为什么如果你查看像 Quantopian 这样的网站,回测总是 运行 从开始日期到结束日期。
本质上,您试图通过传播最后一个非零值来消除矛盾的零条目。类似于零阶保持。您可以这样做,我首先用 NaN 替换零值,然后使用 ffill
.
对后者进行插值
import pandas as pd
import numpy as np
index = pd.date_range('20180101', periods=6)
df = pd.DataFrame(index=index)
df["SMA_short"] = [9,10,11,10,10,9]
df["SMA_long"] = 10
df["SMA_difference"] = df["SMA_short"] - df["SMA_long"]
buy_limit = 0
sell_limit = -1
df["ZOH"] = df["SMA_difference"].replace(0,np.nan).ffill()
df["Position"] = np.where((df["ZOH"] > buy_limit),"in","out")
print df
结果:
SMA_short SMA_long SMA_difference ZOH Position
2018-01-01 9 10 -1 -1.0 out
2018-01-02 10 10 0 -1.0 out
2018-01-03 11 10 1 1.0 in
2018-01-04 10 10 0 1.0 in
2018-01-05 10 10 0 1.0 in
2018-01-06 9 10 -1 -1.0 out
我想根据简单移动平均线 (SMA) 交叉计算股票的买入和卖出信号。一旦 SMA_short 高于 SMA_long(即 SMA_difference > 0)。为了避免头寸被卖得太快,我想只有在 SMA_short 已经大大超过交叉点(即 SMA_difference < -1),重要的是,即使这会持续超过一天。
我通过这个
- 买入和卖出信号由 in 和 out 表示。
- 列 位置 首先考虑 buy_limit。
- In Position_extended 然后为 [=69 的所有情况设置 in =]刚刚穿过SMA_long (SMA_short < SMA_long) 但 SMA_short > -1。为此,它考虑了 i-1 的 Position extended,以防穿越超过一天但 SMA_short剩余:
0 > SMA_short > -1
.
Python代码
import pandas as pd
import numpy as np
index = pd.date_range('20180101', periods=6)
df = pd.DataFrame(index=index)
df["SMA_short"] = [9,10,11,10,10,9]
df["SMA_long"] = 10
df["SMA_difference"] = df["SMA_short"] - df["SMA_long"]
buy_limit = 0
sell_limit = -1
df["Position"] = np.where((df["SMA_difference"] > buy_limit),"in","out")
df["Position_extended"] = df["Position"]
for i in range(1,len(df)):
df.loc[index[i],"Position_extended"] = \
np.where((df.loc[index[i], "SMA_difference"] > sell_limit) \
& (df.loc[index[i-1],"Position_extended"] == "in") \
,"in",df.loc[index[i],'Position'])
print df
结果是:
SMA_short SMA_long SMA_difference Position Position_extended
2018-01-01 9 10 -1 out out
2018-01-02 10 10 0 out out
2018-01-03 11 10 1 in in
2018-01-04 10 10 0 out in
2018-01-05 10 10 0 out in
2018-01-06 9 10 -1 out out
该代码有效,但是,它使用了 for
循环,这会大大降低脚本的速度,并且在该分析的更大范围内变得不适用。由于 SMA 交叉是一种非常常用的工具,我想知道是否有人可以为此找到更优雅、更快速的解决方案。
如果第 T 行需要输入在第 T-1 行计算的值,那么您可能需要进行迭代计算。通常回测是通过按顺序迭代价格数据来完成的。您可以仅根据市场状况计算出一些信号,但除非您从头开始并及时向前推进,否则您不会知道投资组合价值、盈亏或投资组合头寸。这就是为什么如果你查看像 Quantopian 这样的网站,回测总是 运行 从开始日期到结束日期。
本质上,您试图通过传播最后一个非零值来消除矛盾的零条目。类似于零阶保持。您可以这样做,我首先用 NaN 替换零值,然后使用 ffill
.
import pandas as pd
import numpy as np
index = pd.date_range('20180101', periods=6)
df = pd.DataFrame(index=index)
df["SMA_short"] = [9,10,11,10,10,9]
df["SMA_long"] = 10
df["SMA_difference"] = df["SMA_short"] - df["SMA_long"]
buy_limit = 0
sell_limit = -1
df["ZOH"] = df["SMA_difference"].replace(0,np.nan).ffill()
df["Position"] = np.where((df["ZOH"] > buy_limit),"in","out")
print df
结果:
SMA_short SMA_long SMA_difference ZOH Position
2018-01-01 9 10 -1 -1.0 out
2018-01-02 10 10 0 -1.0 out
2018-01-03 11 10 1 1.0 in
2018-01-04 10 10 0 1.0 in
2018-01-05 10 10 0 1.0 in
2018-01-06 9 10 -1 -1.0 out