Tushare ID:497485
今年年初的时候,我和几位小伙伴一起合作打花旗杯,项目和量化交易有关。不可避免地会使用到一些常规的量化工具(尤其是python的第三方库),虽然决赛还没有开始,我们已经确定进入了二十强。非常感谢一些第三方库包括tushare、jqdatasdk等给予的支持,决定写几篇文章向大家介绍一下(事情有点多,拖到了现在…)
Tushare(官网:Tushare大数据社区)。
Tushare是一个免费、开源的财经数据接口包,拥有丰富的数据内容。目前已经可以通过http、Python、Matlab、R语言方式来获取数据。由于我们的策略由Python实现,这里只介绍与Python有关的内容。用户可以在本地下载第三方库进行调用。
平台采取“积分制”的形式返回数据,部分数据需要达到一定的积分才能获取。(在校学生和高校老师绑定可以获取1500的积分哦,具体操作见:Tushare大数据社区)
数据类型:
Tushare涵盖了大量的财经数据,下面简单介绍一下:
在股票方面,提供了沪深股票的股票基本列表,上市公司信息、交易日历等,行情方面提供日线行情、中高频分钟行情、tick级行情,复权因子等,财务方面提供利润表、资产负债表、现金流量表等数据。除了股票数据,tushare还提供指数、公募基金、期货、现货、期权、债券、外汇、港股、美股等数据,可以满足大多数量化交易员所需要的数据要求。
具体使用方法:
tushare的使用方法也非常简单。(正好前段时间anaconda崩了,重装了下,正好可以演示下)
以jupyter notebook为例,直接使用pip install tushare 的命令即可以安装tushare库,进行后续的数据获取。
安装tushare
登录tushare
我们需要借助token码才能登录,这个需要去官网注册
利用接口获取数据,这里选取了南京新百的股票:
下面介绍一个非常简单的双均线策略(这块基本上其实和tushare没有多少关系,用例子简单说明下怎么做策略)
我们首先需要引入其他两个库pandas和numpy,这也是数据分析的实用工具了:
data是数据框类型,利用pandas库对数据进行预处理:
第一行是根据交易日期进行从小到大的排序,第二行是将trade_data转换为时间序列,第三行是重置index。我们发现最开始的数据是没有数据的,这时股票没有上市,需要把这些行去除掉:
计算5日均值和20日均值,并添加到dataframe中:
设置cash和持股数量:
接下来根据五日均值和二十日均值的大小关系进行买入/卖出操作:
得到持仓信息:
计算equity和baseline:
计算收益率并进行绘图:
在参数随意选取5和20的情况下策略的表现并不是太好。在现实中一般会通过网格搜索找到最佳的参数,这里不详细介绍了。这只是一个较为简略的策略,实际上还要考虑涨停不能买、跌停不能卖、交易手续费、滑点等等问题,策略的收益率还会更低一些。
个人拙见,均线策略还是蛮玄学的。通过找到某个参数当然可以拟合出最佳策略,但是参数很难有量化的意义,未来这些参数能否继续历史的表现也是未知的。还是因子选股等方法靠谱些。
源代码如下:
在这里插入代码片
##########################双均线策略##################################import tushare as ts
import pandas as pd
import numpy as np
ts.set_token('#####')//这里请填写自己的token码
pro = ts.pro_api()data = ts.pro_bar(ts_code='600682.SH', adj='qfq', end_date='20220101')
data.sort_values(by="trade_date", inplace=True)
data["trade_date"] = pd.to_datetime(data["trade_date"])
data.reset_index(inplace=True, drop=True)data["ma5"] = data["close"].rolling(5).mean().fillna(method="bfill")
data["ma20"] = data["close"].rolling(20).mean().fillna(method="bfill")CASH = 1000000
STOCKHOLD = 0data.loc[0, "cash"] = CASH
data.loc[0, "stock_hold"] = STOCKHOLDdata.loc[1, "cash"] = CASH
data.loc[1, "stock_hold"] = STOCKHOLDfor i in range(1, len(data) - 1):if data.loc[i, "ma5"] > data.loc[i, "ma20"] and data.loc[i - 1, "ma5"] < data.loc[i - 1, "ma20"] and data.loc[i, "stock_hold"] == 0:data.loc[i + 1, "stock_hold"] = data.loc[i, "cash"] // (100 * data.loc[i + 1, "open"]) * 100data.loc[i + 1, "cash"] = data.loc[i, "cash"] - data.loc[i + 1, "stock_hold"] * data.loc[i + 1, "open"]continueif data.loc[i, "ma5"] < data.loc[i, "ma20"] and data.loc[i - 1, "ma5"] > data.loc[i - 1, "ma20"] and data.loc[i, "stock_hold"] > 0:data.loc[i + 1, "stock_hold"] = 0data.loc[i + 1, "cash"] = data.loc[i, "cash"] + data.loc[i, "stock_hold"] * data.loc[i + 1, "open"]continuedata.loc[i + 1, "stock_hold"] = data.loc[i, "stock_hold"]data.loc[i + 1, "cash"] = data.loc[i, "cash"]data["equity"] = data["stock_hold"] * data["close"] + data["cash"]
data["equity_baseline"] = data["close"] / data.iloc[0]["close"] * CASH
data["MAXDDRATE"] = (data["equity"] - data["equity"].expanding().max()) / data["equity"].expanding().max()import matplotlib.pyplot as plt
fig = plt.figure()
# Equity
ax = fig.add_subplot(111)
ax.plot(data["trade_date"], data["equity"], c="r", label="my")
ax.plot(data["trade_date"], data["equity_baseline"], c="g", label="market")
# MaxDrawDown
ax2 = ax.twinx()
ax2.fill_between(data["trade_date"], data["MAXDDRATE"], facecolor="b", interpolate=True, alpha=.25)
ax.legend(loc=4)
ax.set_xlabel("DATE")
ax.set_ylabel("EQUITY")
ax2.set_ylabel("MAXDDRATE")
# calculate the return rate per year
delta_days = (data["trade_date"].iloc[-1] - data["trade_date"].iloc[0]).days
return_rate_per_year = (data["equity"].iloc[-1] / data["equity"].iloc[0]) ** (252 / delta_days) - 1
return_rate_per_year_pct = round(return_rate_per_year * 100, 2)
ax3 = fig.add_subplot(122)
ax3.axis("off")
print("Return per year is " + str(return_rate_per_year_pct) + "%.")
# calculate the sharpe ratio
return_sr = data["equity"] / data["equity"].shift(1) - 1
RF = 0.05
mean_ = np.mean(return_sr) * 252
sigma_ = np.std(return_sr) * np.sqrt(252)
sharpe = (mean_ - RF) / sigma_
print("Sharpe ratio is " + str(round(sharpe, 2)) + ".")
plt.show()