在前几节的内容中,我们打下了使用Python进行分析和视图的基础。现在,我们可以进行一个更加有趣的分析,不同指数下,使用单均线系统时的历史平均收益率最佳均线长度是多少?
简单单均线系统回顾
在第4节中,我们构建了一个简单的单均线系统,详情可见链接。现在,我们将在此基础上进行改进。
构建单均线系统的收益函数
首先,根据上节的内容,我们可以创建了一个名为 strategie.py
的文件,把单均线系统的收益函数放进去。
import numpy as np
import pandas as pd
from utils import get_moving_average
def single_moving_average_strategy(prices, sma_window_size, initial_capital=1000):
in_position = False
cash = initial_capital
stock_quantity = 0
sma = get_moving_average(prices, sma_window_size)
date_list = []
capital_list = []
for date, price, sma_value in zip(prices.index, prices['Adj Close'], sma):
if not np.isnan(sma_value): # 忽略均线计算前的NaN值
if price > sma_value and not in_position: # 突破均线且当前不在持仓中
in_position = True
stock_quantity = cash / price
cash = 0
elif price < sma_value and in_position: # 跌破均线且当前持仓中
in_position = False
cash = stock_quantity * price
date_list.append(date)
capital_list.append(cash + stock_quantity * price)
return pd.DataFrame({"Date": date_list,
"capital": capital_list}), capital_list[-1] / initial_capital
这个函数有两个输出:一个是关于时间的总资产的DataFrame,另一个是总收益率。
修改主文件 main.py
接下来,我们修改了主文件 main.py
,使用 matplotlib.pyplot
中的 bar
函数绘制柱状图,横坐标表示不同的均线长度,纵坐标表示总收益率。
# main.py
import matplotlib.pyplot as plt
from strategies import single_moving_average_strategy
from utils import get_prices
plt.style.use('dark_background')
def main():
prices = get_prices("^NDX")
sma_size_range = range(2, 365 * 10)
ratio_list = []
for sma_size in sma_size_range:
_, ratio = single_moving_average_strategy(prices, sma_size)
ratio_list.append(ratio)
plt.bar(sma_size_range, ratio_list)
plt.show()
if __name__ == '__main__':
main()
在这段代码中,我们使用了 matplotlib.pyplot
中的 bar
函数绘制柱状图,bar函数中的第一个参数是横坐标,也就是均线长度,第二个参数是纵坐标,这里是总收益率。
代码中_在Python中表示不需要使用的变量,这里相当于一个占位符。
sma_size_range用于测试从2天到10年的均线,我们看一下输出的效果图。

使用日k线,收益最高的均线长度是318,按照美股一年252个交易日计算,大约相当于1.247年。但是,即便是最高点的总收益也没到100,而这段时间纳斯达克100指数的总收益是162.984倍。
测试不同周期的数据
通过替换代码中的周期,我们测试了周K和月K数据。具体如下:
prices = get_prices("^NDX", "1wk")
sma_size_range = range(2, 52 * 10)
prices = get_prices("^NDX", "1mo")
sma_size_range = range(2, 12 * 10)

周k的最高点是110周均线,最高收益大概122倍。

月k的最高点是25个月均线,总收益大概123倍。
结论
我们可以发现:
- 使用周k和月k做分析决策,长线看来是有优势的,因为可以过滤掉很多市场的杂音
- 单均线系统在任何情况下都没有超过指数自己本身的收益,所以使用单一均线反复买卖操作,在纳指上是得不偿失的。
最后,大家可以试试其他指数,看是否会得出相同的结论。
print(prices.iloc[-1]["Adj Close"]/prices.iloc[0]["Open"])#可以用来获得指数收益率
# 指数代码SP500: ^GSPC; A50: 000001.SS
找到原因了,我直接copy文章里的代码,main文件最底下这一行漏掉了
if name == ‘main‘:
main()
是呀,谢谢提醒,我没注意到。。。
请教一下是什么原因呢,执行的时候没有弹出柱状图,只看到控制台显示下面信息
Process finished with exit code 0