基于Tushare使用Python实现双均线策略

TushareID:458567


一、双均线策略是什么?

双均线策略的思想很简单,是根据长短周期的价格的移动平均线之间的关系来确定买卖点。其中,短周期均线和长周期均线分别代表近期的走势和长期的走势,当短周期均线从下向上突破长周期均线时,意味着当前时间段具有上涨趋势,突破点也就是常说的金叉,这是多头信号;当长周期均线从下向上突破短周期信号时,则意味着当前时间段具有下跌趋势,突破点也就是常说的死叉,这是空头信号。

二、代码编写思路

  • 数据准备:通过 Tushare Pro 获取用于策略验证的股票数据,并提取出收盘价用于历史回测。
  • 策略编写:计算价格的长短周期移动平均线。当短周期移动平均线 MA10 从下向上穿过长周期均线MA20时,为买入信号;当长周期移动平均线MA20从上向下穿过短周期均线MA10时, 为卖出信号 “
  • 回测结果评估:通过 FFn 库来计算各种风险指标, 并对策略的回测结果进行评估。

三、代码实现

1.收取数据

首先需要获取用于历史回测的数据。先通过 Tushare Pro 获取平安银行的股票日线数据,时间是从2018年1月1日到2019年12月30日,再从获取的数据中只选取日期和收盘价,并将其保存到本地。


import tushare as ts
ts_pro = ts.pro_api('your token')
#获取平安银行的历史数据
df = ts_pro.daily(ts code='000001.SZ', start_date='20180101', end_date='20191230')
#逆序
df = df.reindex(index=df.index[::-1])
# 用到的列
used_cols = ['trade_date', 'close']
df = df[used_cols]
# 保存到本地
df.to csv('./000001.SZ.csv', index=None)

2.导入库并定义全局变量

import pandas as pd
import numpy as mp
import matplotlib.pyplot as plt
import ffn
# 是否持仓
hold = False
# 持仓数
pos = 0
# 回测资金
capital = 100000
# 剩余资金
rest = 0
# 手续费万分之三
fee = 0.0003
# 每日资金数列表
capital_list = []
# 20日均线数组
MA20_array = np.zeros(20)
# 10日均线数组
MA10_array = np.zeros(10)
# 读取历史数据
df = pd.read_csv('./000001.SZ.csv')

之后对历史数据进行遍历。 先取出每行数据中的收盘价和日期,再将前面定义的MA10和MA20数据平移一个单位,并将新数据追加到两个数组中。由于 MA20指标至必需要20个数据,所以如界数据小于20个就通过 continue语句跳转到下一次循环。当数据达到需要的缓存数目后,再计算相应的 MA10 和MA20 指标。

# 遍历历史数据
for i in range(1en(df))
	price = df.loc[i, 'close']
	date = df.loc[i, 'trade_date']
	# 价格序列乎移	
	MA10_array[0:9] = MA10_array[1:10]
	MA20_array[0:19] = MA2O_array[1:20]
	# 将新数据追加到数组木端
	MA10_array[-1] = price
	MA20_array|-1] = price
	# 如果小于20个数据就跳过
	if i < 20:
		continue
	# 计算 MA 指标
	MA10 = MA10_array.mean()
	MA20 = MA20_array.mean()

在计算得到MA 指标之后,下面来判断是否达到了开仓和平仓信号。如果 MA1O指标大于MA20指标且没有持仓,就以当前价格进行买入开仓(因为股票买入的仓位数需要是100的倍数,所以先计算开仓数,这里设置的是每次开仓全仓买入;因为全仓买入后还有剩余资金,所以还需要记录剩余资金,这里将手续费也考虑了进去;之后将持仓状态设置为True,并输出当前的交易操作);如果MA10指标小于 MA20指标且持仓,就进行平仓(以当前的价格乘仓位数并扣除手续费,最后再加上剩余资金来计算平仓后的资金;之后将持仓数日设置为0,持仓状态设置为False, 并输出当前的交易操作)。

# 判断是否达到开仓和平仓信号
if MA10 >= MA20 and hold == False:
	# 计算开仓数目
	pos = int(capital / price / 100* 100
	# 剩余资金
	rest = capital - pos * price * (1 + fee)
	# 持仓设置为True
	hold = True
	print ('buy at', date, 'price', price, 'capital', capital)
elif MA10 < MA2o and hold == True:
	# 计算平仓后的资金
	capital = pos * price * (1 - fee) + rest
	# 持仓数设置为0
	pos = 0
	# 持仓设置为False
	hold = False
	print('sell at', date, 'price', price, 'capital', capital)

接着计算每日的资金数目,如果持仓,总资金就是当前的市值加上剩余资金;如果没有持仓,总资金就是当前的资金数。

# 计算每日的资金数目
if hold == True:
	# 如果持仓,就记录当前市值
	capital_list.append(rest + pos * price)
else:
	# 如果没有持仓,就记录当前资金
	capital_list.append(capital)

输出结果如下,可以看到控制台中输出了每次的交易记录及资金的变化。

buy at 20180130 price 13.65 capital 100000
sell at 20180206 price 14.00 capital 102494.44650000000
buy at 20180418 price 11.50 capital 102494.44650000000
sell at 20180504 price 10.68 capital 95137.22590000000
buy at 20180723 price 9.42 capital 95137.22590000000
sell at 20180813 price 9.05 capital 91381.81590000002
buy at 20180827 price 10.43 capital 91381.81590000002
sell at 20180918 price 10.08 capital 88283.28480000002

最后通过 Matplotlib 库及 FFn 库对回测结果进行可视化并计算风险指标。

# 将资金序列转换为 Series 对象
capital_series = pd.series (capital_list)
# 计算资金序列的简单收益率
capital_returns = ffn.to_returns(capital_series)
# 计算收益率
print(ffn.calc_total_return(capital_series))
# 计算最大回撤率
print (ffn.calc_max_drawdown(capital_series))
# 计算夏普比率
print(ffn.calc_sharpe(capital_returns))
# 可视化资金曲线
pit.plot(range(len(capital_list)), capital_list)
plt.show()

输出结果如下,可以看到策略的收益率为0.22,最大回撒率为-0.23,夏普比率为0.036。

0.22267539847024254
-0.23702968890874887
0.03621325983054644
  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值