股票的各个指标中,Bollinger Bands(一般简称为BOL指数)简单暴力,却又有着统计学内涵,实在是深得我心。Bollinger Bands一般有三条线,中间一条就是20日均线MA,而上线和下线分别是MA加减2个20日标准差[1]。
当然了,如果你拉随便一个股票的历史股价绘制一个直方图,你会发现其实这些股价并不符合正态分布,所以Bollinger Bands多少在理论上有点站不住脚。不过呢,如果你去统计一下,基本上价格波动95%的时候都在Bands内,5%都在Bands外。所以究竟如何还是自己思考吧。
tushare是很好用的一个国内的交易数据api,获取数据流程简单,而且和pandas无缝连接,所以很值得试试。现在有专业版,可以免费用,初始的积分可以做一些简单操作,以日线数据为例,基础积分每分钟内最多调取500次,每次5000条数据,相当于23年历史,所以基本上够用的了。但是tushare也还有很多很好的数据需要更高的积分才能调取,付费50元加入高级用户群可以买500积分,然后也基本够用的了。
整个工作流程分以下几个部分:
- 配置环境
- 读取数据
- 计算MA与std,绘图
配置环境
首先肯定要安装tushare
pip install tushare --upgrade
然后在程序开头载入tushare以及pandas,matplotlib
import pandas as pd
import tushare as ts
import snoop
import matplotlib.pyplot as plt
import os
from datetime import date
snoop是用来查错,不是必须
接下来配置tushare接口:
from yaml import full_load
with open('config.yaml') as config_file:
_config_yaml = full_load(config_file)
TOKEN = _config_yaml['token']
pro = ts.pro_api(TOKEN)
tushare专业版需要提供token访问api,这个api可以在个人主页下面的接口TOKEN中看到。我是将token写在了一个config.yaml文件中,这样只需要将这个文件在.gitignore
里面声明一下,自己的token信息就不会被不小心写进git库,甚至在网上公开了。ts.pro_api
将建立一个api连接,只要提供TOKEN就行了
读取数据
tushare的日线数据调取代码如下:
df = pro.daily(ts_code='000001.SZ,600000.SH', start_date='20180701', end_date='20180718')
主要是提供ts_code, start_date和end_date三个数据。从例程可以看到start_date
和end_date
两个参数的日期格式是%Y%m%d的形式,所以可以用date.today().strftime("%Y%m%d")
将今天的日期转化成符合函数参数需求的格式
我想将股票从上市开始到现在的全部日线信息都下载下来。如前所述,end_date
设置成当前日期只需要对date.today()
进行格式转化就好,而 start_date
和ts_code
则需要根据具体股票进行调整。下面以海康威视(002352)为例展示一下如何从股票代码(symbol)获取ts_code和start_date。
使用tushare的stock_basic接口可以获得各个股票的基本信息,所以可以先用这个接口抓取一次股票基本信息,然后保存在本地,这样就不需要每次调试都走线上了(index=False
避免存储的时候将自动生成的数值index也写入csv):
data = pro.stock_basic(exchange='', list_status='L', fields='ts_code,symbol,name,area,industry,list_date')
data.to_csv('stock_basic_info.csv',index=False)
上面的代码运行后,下次要用数据信息的时候只需要直接载入就好,不过要注意的一点是,pandas读取csv的时候会做一些数据类型转化,所以symbol里面像平安银行(000001)这种就会变成1
,为了避免这种情况要在读取的时候设置好 dtype
。
df_stock_basic = pd.read_csv(stock_basic_path, dtype={'symbol':str,'list_date':str}).set_index('symbol')
symbol
一列保存的是股票代码,用这个作为index,后续就能够使用loc命令查询了,比如海康威视的002352
symbol = '002352'
ts_code = df_stock_basic.loc[symbol,'ts_code']
list_date = df_stock_basic.loc[symbol,'ts_code']
有了上面的ts_code
和list_date
,获取日线数据就很简单了
df_daily:pd.DataFrame = pro.daily(
ts_code=ts_code,
start_date = list_date,
end_date= date.today().strftime("%Y%m%d")
)
df_daily:pd.DataFrame
里面的冒号是为了声明df_daily
的类型,明确类型以后在pycharm才能更好的帮你做代码补全。
计算MA,std与绘图
这里的时移均线主要靠的是pandas的rolling实现。但是在开始计算以前,首先我们要对下载下来的df_daily
做一些处理,按照常规的时序分析流程:
- 将
trade_date
设置为index, 并且用pandas的to_datetime
转成timestamp
df_daily.index = pd.to_datetime(df_daily['trade_date'])
2. 将数据框升序排列(原本数据是按照从新到旧的顺序排列的,在分析的时候这会造成问题)
df_daily = df_daily.sort_index()
然后就可以计算MA以及std了
rolling_days = 20
std_multiplier = 2
df_daily['MA'] = df_daily['close'].rolling(rolling_days).mean()
df_daily['std'] = df_daily['close'].rolling(rolling_days).std()
df_daily['upper_bound'] = df_daily['MA']+df_daily['std']*std_multiplier
df_daily['lower_bound'] = df_daily['MA']-df_daily['std']*std_multiplier
绘图就只要用
df_daily[['MA','close','upper_bound','lower_bound']].plot(grid=True)
plt.show()
当然了,上面只是放了收盘价,时移均线以及Bollinger Band上下界,还可以进一步放蜡烛图一类的。
这些代码可能最好做成一个类,然后通过调用方法的形式组织代码才比较好。
参考
- ^20日均线和2个标准差主要是约定俗成,当然也可以将均线时间增加一些,酌情调整吧