Tushare介绍

Tushare pro是一个python财经数据接口包。主要实现对股票等金融数据从数据采集、清洗加工 到 数据存储的过程,能够为金融分析人员提供快速、整洁、和多样的便于分析的数据,为他们在数据获取方面极大地减轻工作量,使他们更加专注于策略和模型的研究与实现上。考虑到Python pandas包在金融量化分析中体现出的优势,Tushare返回的绝大部分的数据格式都是pandas DataFrame类型,非常便于用pandas/NumPy/Matplotlib进行数据分析和可视化。

Tushare安装


学习文档

说明文档:https://tushare.pro/

Tushare使用

调用Pro版本的数据

  • 用户注册:[https://tushare.pro/register?reg=379314](https://tushare.pro/register?reg=379314)
  • 获取token
  • 初始化接口,调取数据 ```python

    导入tushare模块

    import tushare as ts

初始化pro接口

pro = ts.pro_api(‘your token’) pro

  1. <a name="QY0jk"></a>
  2. ### Tushare基本使用
  3. <a name="gomox"></a>
  4. #### 练习1
  5. 1. 使用tushare 获取五粮液股票的历史行情数据
  6. 1. 输出该股票所有收盘比开盘上涨3%以上的日期
  7. 1. 输出该股票所有开盘比前日收盘跌幅超过2%的日期
  8. 1. 假如我从2010年1月1日开始,每月第一个交易日买入1手股票,每年最后一个交易日卖出所有股票。到今天为止,我的收益如何?
  9. ```python
  10. import tushare as ts
  11. import pandas as pd
  12. import numpy as np
  13. pro = ts.pro_api("your token")
  14. """
  15. 使用tushare获取五粮液股票的历史行情数据
  16. """
  17. wly_stock = pro.daily(ts_code="000858.SZ", start_date="20000101")
  18. """
  19. 将数据保存为csv文件
  20. """
  21. wly_stock.to_csv("wly000858.csv", index=False)
  22. """
  23. 读取五粮液文件数据,指定trade_date为时间序列索引.
  24. - parse_dates 设置索引为时间序列索引,传入的类型为list
  25. """
  26. wly_df = pd.read_csv("wly000858.csv", index_col="trade_date", parse_dates=["trade_date"])
  27. wly_df.info()
  28. wly_df.head()
  29. """
  30. 输出所有收盘价比开盘上涨3%以上的日期
  31. 公式: (close - open)/ open > 0.03
  32. """
  33. wly_df[(wly_df["close"] - wly_df["open"])/wly_df["open"] > 0.03].index
  1. """
  2. 一个简单的策略
  3. 假设从2010年1月开始,每月从第一个交易日买入1手股票,每年最后一个交易日卖出所有股票,到今天为止的收益如何?
  4. 需求分析
  5. - 每月第一个交易日买入: 1、支出 2、支出的是每月第一个交易日该股票的开盘价*1手(1手 = 100股)
  6. - 每年最后一个交易日卖出: 1、收入 2、收入的是每年最后一个交易日该股票的开盘价*12手
  7. """
  8. # 截取2010年~2019年的数据
  9. wly_df2 = wly_df["2019":"2010"]
  10. # 每月第一个交易日的数据
  11. wly_monthly_f = wly_df2.resample("MS").first() # first()取每个月汇总第一个交易日的数据
  12. # 每年最后一个交易日的数据
  13. wly_yearly_l = wly_df2.resample("A").last()
  14. # wly_yearly_l
  15. """
  16. 计算收益
  17. """
  18. # 初始化每个月需要购买股票所话的成本
  19. cost_money = 0
  20. # 初始化,已持有的股票
  21. hold = 0
  22. # 获取2010~2019年每一年所有的成本以及收入
  23. for year in range(2010, 2019):
  24. cost_money += wly_monthly_f[str(year)]["open"].sum() * 100 # 累加每年买股票所花的成本
  25. hold += len(wly_monthly_f[str(year)]) * 100
  26. sell_money = wly_yearly_l[str(year)]["open"].values[0]*hold # 年末卖出的价格*所卖出的价格
  27. cost_money -= sell_money # 每年总成本 - 每年总收入
  28. hold = 0 # 由于已经卖出了,所以持有股数清0
  29. print(f"save_money:{-cost_money}, hold:{hold}")

双均线分析

对于每一个交易日,都可以计算出前N天的移动平均值,然后把这些移动平均值连起来,成为一条线,就叫做N日移动平均线。移动平均线常用:5天,10天,30天,60天,120天和240天的指标

  • 5天和10天的是短线操作的参照指标,称做日均线指标;
  • 30天和60天的是中期均线指标,称做季均线指标;
  • 120天和240天的是长期均线指标,称做年均线指标。

黄金交叉

短期均线上穿长期均线,买入信号
image.png

死亡交叉

短期均线下穿长期均线,卖出信号
image.png

双均线分析练习

  • 使用tushare包获取某股票的历史行情数据
  • 使用tushare包计算该股票历史数据的5日均线和30日均线
  • 使用matplotlib包可视化历史数据的收盘价和两条均线
  • 分析输出所有金叉日期和死叉日期
  • 假如我从2010年1月1日开始,初始资金为10W,金叉尽量买入,死叉全部卖出,则到今天为止。我的炒股收益率如何?


import tushare as ts
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt

# 初始化pro接口
pro = ts.pro_api("28c5c9f8976917756a3d42b04a765e83782c282a70da38b0ea71615f")

# 获取云南白药2010年至今的数据
by_stock = pro.daily(ts_code="000538.SZ", start_date="20100101")
# 将数据保存到本地
by_stock.to_csv("000538.csv", index=False)

# 读取云南白药的数据
by_df = pd.read_csv("000538.csv", index_col="trade_date", parse_dates=["trade_date"])[["open","high","low","close"]]
# by_df.head()

by_df.sort_index(inplace=True)  # 时间升序

"""
使用tushare包计算该股票历史数据的5日均线和30日均线
"""
# 添加MA5和MA30两列并赋值NAN
by_df["MA5"] = np.nan
by_df["MA30"] = np.nan
# by_df.head()

"""
方法1
MA5是短期均线,规律是0~4, 1~5, 2~6
公式: 定义一个变量i, i的取值范围为4~len(by_df), 取值范围从4开始是因为符合i-4~i+1的规律. 
例如i=4时, i-4=0 i+1=5,由于是左闭右开的,因此就会生成从0~4的5个值,以此类推,这样就符合MA5的规律
"""
# 计算MA5
for i in range (4, len(by_df)):
    # 获取到MA5列i行的值赋值为收盘价的5日均价
    by_df.loc[by_df.index[i], "MA5"] = by_df["close"][i-4:i+1].mean()

for i in range (29, len(by_df)):
    # 获取到MA5列i行的值赋值为收盘价的5日均价
    by_df.loc[by_df.index[i], "MA30"] = by_df["close"][i-29:i+1].mean()    


"""
方法二: 用rolling实现
"""
by_df["close"].rolling(5).mean()
# by_df["close"].rolling(30).mean()

"""
输出图表
"""
by_df[["close","MA5","MA30"]].plot()
plt.show()

"""
分析输出所有金叉日期和死叉日期
"""
by_data = by_df.dropna()  # 过滤掉NAN的数据
# by_data.info()
# by_data.head()

"""
方法一:
- 金叉:短期均线上穿长期均线 ==> 前一天MA5<=MA30 并且后一天MA5>=30
- 死叉:短期均线下穿长期均线 ==> 前一天MA5>=MA30 并且后一天MA5<=30
"""

gloden_cross = []
death_cross = []
for i in range(1, len(by_data)):
    # 金叉
    if by_data["MA5"][i] >= by_data["MA30"][i] and by_data["MA5"][i-1] <= by_data["MA30"][i-1]:
        # 将金叉的时间构建成列表
#         print(by_data.index[i])
        gloden_cross.append(by_data.index[i])


    if by_data["MA5"][i] <= by_data["MA30"][i] and by_data["MA5"][i-1] >= by_data["MA30"][i-1]:
        # 将金叉的时间构建成列表
        death_cross.append(by_data.index[i])

# print(gloden_cross)


"""
方法2
以金叉为例
- 短期均线比长期均线波动大
- 短期均线上穿长期均线为金叉
- 金叉和死叉交替出现

如果现在是死叉,从死叉过度到金叉
- 比较MA5<MA30就会出现TRUE, 然后可能一直TTTT,然后到了某一天MA5>=MA30时,就会是False,因此出现的情况可能就是TTTFFF,所以当出现TF时,这个点就是金叉

由于除了要比较MA5<MA30,还需要比较MA5>MA30的情况,因此如果是MA5>MA30时,就会可能会出现FFFFTTTT的情况,也因此:
像这种情况:
MA5<MA30:TTTTFFFF
MA5>MA30:  FFFFTTTT (往前挪一位,错位比较)
“MA5<MA30”和“MA5>MA30”在两个都出现F时,这个点就是金叉;反之,如果都为T时,就是死叉
"""
se1 = by_data["MA5"] < by_data["MA30"]
se2 = by_data["MA5"] >= by_data["MA30"]

"""
由于需要两个都出现F时,才是金叉
因此这里的比较符不能使用&, 要使用|
"""
gloden_cross2 = by_data[~(se1 | se2.shift(1))].index
# gloden_cross2

"""
两个都为T时,就是死叉
"""
death_cross2 = by_data[se1 & se2.shift(1)].index
death_cross2


"""
假如我从2010年1月1日开始,初始资金为10W,金叉尽量买入,死叉全部卖出,则到今天为止。我的炒股收益率如何?
"""
sr1 = pd.Series(1, index=gloden_cross2)  # 1代表金叉
sr2 = pd.Series(0, index=death_cross2)  # 0代表死叉
sr = sr1.append(sr2).sort_index()  # sr1 拼接sr2

money = 100000  # 初始化起始资金
hold = 0  # 初始化持有股

for i in range(0, len(sr)):
    """
    获取价格
    - 获取open价格
    - 再通过取出sr的时间索引获取对应时间的价格
    """
#     print(by_data["open"][sr.index[i]])  # 每一次交叉点的价格
    p = by_data["open"][sr.index[i]]
    if sr.iloc[i] == 1:
        # 金叉,买入
        buy = money //(100*p)  # 计算买入多少股
        hold += buy*100  # 计算总共持有多少股
        money -= buy*100*p  # 因为买入了,所以起始资金会减少

        if i == len(sr)-1:
            money += buy*100*p  # 如果最后一个点是金叉,买入所花的这笔钱,也算作你的收入
    else:
        # 死叉,卖出
        money += hold*p  # 卖出,资金增加
        hold = 0  # 因为是全部卖出,所以持有股清0


gains = money - 100000  # 最终盈利金额
# gains