【数据分析】Python+Tushare实现均线金叉死叉交易策略回测
【数据分析】Python+Tushare实现均线金叉死叉交易策略回测
简介
在本文中,我们将利用 Python 和 Tushare 数据接口,对贵州茅台(600519.SH)进行数据分析,并实现基于“双均线”策略的量化回测,完整评估该策略的收益效果。
项目目标
- 使用tushare包获取贵州茅台的历史行情数据。
- 计算该股票历史数据的5日均线和30日均线。
- 分析输出所有金叉日期和死叉日期。
- 模拟实际买卖交易流程。
1.数据获取和处理
导入所需要的库
import tushare as ts
import pandas as pd
from pandas import DataFrame,Series
import numpy as np
初始化Pro接口,填入自己在tushare注册后的Token
pro = ts.pro_api('f573ee6f0129fd70b86b2b3a7858210bf008fe47b0233ce71d98986b')
df = pro.daily(ts_code='600519.SH', start_date='20100101')
print(df)
数据展示
将数据存储在本地
调用to_csv方法将获取到的数据写入到本地进行存储,并进行读取。
df.to_csv('./maotai.csv')
df = pd.read_csv('./maotai.csv')
print(df.head())
运行结果
删除多余的列并查看数据类型
对于多余的Unnamed:0,需要删去
df.drop(labels='Unnamed: 0', axis=1, inplace=True)
查看每一列的数据类型
print(df.info())
运行结果
可以看到并没有缺失值
转化时间序列类型和作为行索引
将date列转为时间序列类型
df['trade_date'] = pd.to_datetime(df['trade_date'], format='%Y%m%d')
将date列作为源数据的行索引
df.set_index('trade_date', inplace=True)
print(df.head())
运行结果
2.计算双均线
- 计算该股票历史数据的5日均线和30日均线
- 什么是均线?
- 对于每一个交易日,都可以计算出前N天的移动平均值,然后把这些移动平均值连起来,成为一条线,就叫做N日移动平均线。移动平均线常用线有5天、10天、30天、60天、120天和240天的指标。
- 5天和10天的是短线操作的参照指标,称做日均线指标;
- 30天和60天的是中期均线指标,称做季均线指标;
- 120天和240天的是长期均线指标,称做年均线指标。
- 均线计算方法:MA=(C1+C2+C3+…+Cn)/N C:某日收盘价 N:移动平均周期(天数)
计算5日和30日均线
ma5 = df['close'].rolling(5).mean()
ma30 = df['close'].rolling(30).mean()
画出5日均线和30日均线
# 画出5日均线
import matplotlib.pyplot as plt
plt.plot(MA5[50:180])
plt.plot(MA30[50:180])
plt.show()
运行结果
计算金叉和死叉
- 分析输出所有金叉日期和死叉日期
- 股票分析技术中的金叉和死叉,可以简单解释为:
- 分析指标中的两根线,一根为短时间内的指标线,另一根为较长时间的指标线。
- 如果短时间的指标线方向拐头向上,并且穿过了较长时间的指标线,这种状态叫“金叉”;
- 如果短时间的指标线方向拐头向下,并且穿过了较长时间的指标线,这种状态叫“死叉”;
- 一般情况下,出现金叉后,操作趋向买入;死叉则趋向卖出。当然,金叉和死叉只是分析指标之一,要和其他很多指标配合使用,才能增加操作的准确性。
设置条件
df = df[30:]
MA5 = MA5[30:]
MA30 = MA30[30:]
s1 = MA5 < MA30
s2 = MA5 > MA30
s1 = MA5 < MA30:金叉(5日均线上穿30日均线)
s2 = MA5 > MA30:死叉(5日均线下穿30日均线)
计算金叉和死叉对应的时间
golden_ex = -(s1|s2.shift(1)) # 判度金叉的条件
golden_date = df.loc[golden_ex].index # 金叉的索引(也就是时间)
death_ex = s1 & s2.shift(1) # 判断死叉的条件
death_date = df.loc[death_ex[df.index]].index # 死叉对应的索引(也就是时间)
print(golden_date,death_date)
运行结果
4.模拟买卖交易
- 如果从2010年1月1日开始,初始资金为1000000元,金叉尽量买入,死叉全部卖出,则到今天为止,炒股收益率如何?
- 分析:
- 买卖股票的单价使用开盘价
- 买卖股票的时机
- 最终手里会有剩余的股票没有卖出去
- 会有。如果最后一天为金叉,则买入股票。估量剩余股票的价值计算到总收益。
- 剩余股票的单价就是用最后一天的收盘价。
计算金叉和死叉对应的时间
# 金叉的标识(1)
s1 = Series(data=1,index=golden_date)
# 死叉的标识(0)
s2 = Series(data=0,index=death_date)
s = pd.concat([s1,s2])
s = s.sort_index() # 排序,存储金叉和死叉对应的时间
print(s)
运行结果
计算总收益
# 设置本金1000000(不变的)
first_money = 1000000
# 设置可变的变量(买股票和卖股票的钱都从该变量进行操作)
money = first_money
# 设置持有的股票的数量(100股=一手)
hold = 0
for i in range(0,len(s)):if s.iloc[i] == 1:# 获取股票的单价time = s.index[i]# 金叉的时间p = df.loc[time]['open']# 金叉股票单价hand_hold = money // (p*100)# 使用1000000最多买入多少手股票hold = hand_hold * 100money -= (hold*p)# 买股票的钱从可变的本金中扣除else:death_time = s.index[i]# 死叉时间p = df.loc[death_time]['open']# 死叉股票单价money += (hold*p)# 卖出的股票收入加入到可变的本金中hold = 0# 持有的股票变为0
last_money = hold * df['close'].iloc[-1]# 剩余股票的价值
# 总收益
print(money+last_money-first_money)
运行结果
-993528.9999999991