作者: 阿布
阿布量化版权所有 未经允许 禁止转载
abu量化系统github地址 (欢迎+star)
abupy除了之前章节讲解示例时使用的内置沙盒数据外,也内置了几个数据源,支持实时获取美股,A股,港股,期货和比特币等类型数据,内置的数据源仅供学习使用,abupy提供了接入外部数据源的接口和规范,本节的示例将讲解内置数据源的切换,以及接入用户外部的数据源的接口规范。
首先导入abupy中本节使用的模块:
In [2]:
# 基础库导入
from __future__ import print_function
from __future__ import division
import warnings
warnings.filterwarnings('ignore')
warnings.simplefilter('ignore')
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
import os
import sys
# 使用insert 0即只使用github,避免交叉使用了pip安装的abupy,导致的版本不一致问题
sys.path.insert(0, os.path.abspath('../'))
import abupy
# 使用沙盒数据,目的是和书中一样的数据环境
abupy.env.enable_example_env_ipython()
In [3]:
from abupy import abu, EMarketTargetType, AbuMetricsBase, ABuMarketDrawing, ABuProgress, ABuSymbolPd, get_price, ABuIndustries
from abupy import EMarketDataFetchMode, EDataCacheType, EMarketSourceType, FuturesBaseMarket, TCBaseMarket, ABuDateUtil
from abupy import AbuDataParseWrap, StockBaseMarket, SupportMixin, ABuNetWork, Symbol, code_to_symbol
和之前的章节不一样,关闭沙盒数据接口,使用实时数据源提供数据:
In [4]:
abupy.env.disable_example_env_ipython()
In [5]:
abupy.env.g_data_fetch_mode
Out[5]:
默认使用模式为E_DATA_FETCH_NORMAL,NORMAL的意义是默认优先从缓存中获取,如果缓存中不存在,再访问网络,尝试从网络获取,除此之外还有一些优化,比如虽然缓存中的数据也无法满足要求,但是缓存索引纪录今天已经尝试从网络获取,这种情况下也不再访问网络。
更多详情请阅读ABuDataSource代码
E_DATA_FETCH_FORCE_NET为强制使用网络进行数据更新,一般不推荐使用,如果切换了数据源,或者缓存中的数据存在问题的情况下会使用:
In [8]:
abupy.env.g_data_fetch_mode = EMarketDataFetchMode.E_DATA_FETCH_FORCE_NET
In [6]:
ABuSymbolPd.make_kl_df('usBIDU').tail()
Out[6]:
E_DATA_FETCH_FORCE_LOCAL为强制从缓存获取,实际上在做回测的时候,使用的一般都是这种模式,因为比如编写了一个策略进行回测结果度量,通常情况下需要反复的修改策略,重新进行回测,强制使用缓存的好处是:
In [7]:
abupy.env.g_data_fetch_mode = EMarketDataFetchMode.E_DATA_FETCH_FORCE_LOCAL
In [8]:
ABuSymbolPd.make_kl_df('usBIDU').tail(1)
Out[8]:
下面把数据获取模式恢复为默认的E_DATA_FETCH_NORMAL:
In [12]:
abupy.env.g_data_fetch_mode = EMarketDataFetchMode.E_DATA_FETCH_NORMAL
In [6]:
abupy.env.g_data_cache_type
Out[6]:
缓存的csv数据存贮文件路径在~/abu/data/csv/,可使运行下面命令直接打开目录:
In [7]:
if abupy.env.g_is_mac_os:
!open $abupy.env.g_project_kl_df_data_csv
else:
!echo $abupy.env.g_project_kl_df_data_csv
可以通过g_data_cache_type切换其它存贮模式,如下使用HDF5进行数据存贮:
In [8]:
abupy.env.g_data_cache_type = EDataCacheType.E_DATA_CACHE_HDF5
缓存的hdf5文件路径在~/abu/data/df_kl.h5,可使运行下面命令直接打开目录, 或者显示完整路径:
In [9]:
if abupy.env.g_is_mac_os:
!open $abupy.env.g_project_data_dir
else:
!echo $abupy.env.g_project_data_dir
In [13]:
ABuSymbolPd.make_kl_df('usTSLA').tail()
Out[13]:
下面仍然切换回默认的csv模式,csv的优点是存贮空间需要小,可以并行读写,且针对不同平台兼容性好:
In [10]:
abupy.env.g_data_cache_type = EDataCacheType.E_DATA_CACHE_CSV
In [17]:
abupy.env.g_market_source
Out[17]:
如下想要获取比特币的数据,但是输出显示百度的数据源不支持比特币:
In [23]:
ABuSymbolPd.make_kl_df('btc')
切换数据源为火币数据源,即可正常获取数据,如下:
In [22]:
abupy.env.g_market_source = EMarketSourceType.E_MARKET_SOURCE_hb_tc
ABuSymbolPd.make_kl_df('btc').tail()
Out[22]:
类似,下面想要获取期货鸡蛋的数据,但是输出显示火币的数据源不支持期货市场:
In [25]:
ABuSymbolPd.make_kl_df('jd0')
切换数据源为新浪期货数据源,即可正常获取数据,如下:
In [28]:
abupy.env.g_market_source = EMarketSourceType.E_MARKET_SOURCE_sn_futures
In [29]:
ABuSymbolPd.make_kl_df('jd0').tail()
Out[29]:
在之前的章节使用abu.run_loop_back进行交易回测,使用的都是沙盒数据,如果需要使用实时数据,特别是回测交易多的情况下,比如全市场测试,推荐在使用abu.run_loop_back进行回测前先使用abu.run_kl_update将数据进行更新。
在run_kl_update中会首先强制使用网络数据进行全市场数据更新,在更新完毕后会将全市场的交易数据都写入缓存,再abu.run_loop_back运行回测的时候使用本地数据模式,即实现数据更新与策略回测分离,运行效率提高。
下面的代码将分别获取美股,A股,港股,期货,比特币,莱特币6年的交易数据,在后面的章节将分别使用这些数据做回测示例,读者可只获取自己关心的市场的交易数据,不必全部运行。
所有获取的数据已经存放在百度云盘上,后面的章节使用的数据都是本节更新的数据,建议直接从云盘下载入库完毕的数据库,不需要从各个数据源再一个一个的下载数据进行入库,百度云地址如下:
csv格式美股,A股,港股,币类,期货6年日k数据 密码: gvtr
下面数据存贮格式为hdf5数据,由于hdf5文件解压后非常大,还需要区分python版本,所以如果没有足够的存贮空间 特别是python2下,建议使用csv格式的缓存文件:
mac系统python3 美股,A股,港股,币类,期货6年日k数据 密码: ecyp
mac系统python2 A股6年日k数据: 密码: sid8
mac系统python2 美股6年日k数据: 密码: uaww
windows python3 美股,A股,港股,币类,期货6年日k数据 密码: 3cwe
windows python2 A股6年日k数据: 密码: 78mb
windows python2 美股6年日k数据: 密码: 63r3
下载完毕上述数据后,hdf5解压得到df_kl.h5文件,csv解压得到csv文件夹,解压后放到下面路径下即可
In [4]:
if abupy.env.g_is_mac_os:
!open $abupy.env.g_project_data_dir
else:
!echo $abupy.env.g_project_data_dir
如果不想通过直接下载数据文件的方式,也可下面通过切换至腾讯数据源,然后进行美股数据全市场更新:
备注:耗时操作,大概需要运行15分钟左右,可以在做其它事情的时候运行
In [ ]:
%%time
abupy.env.g_market_source = EMarketSourceType.E_MARKET_SOURCE_tx
abupy.env.g_data_cache_type = EDataCacheType.E_DATA_CACHE_CSV
abu.run_kl_update(start='2011-08-08', end='2017-08-08', market=EMarketTargetType.E_MARKET_TARGET_US, n_jobs=10)
如果不想通过直接下载数据文件的方式,也可切换至百度数据源,然后进行A股数据全市场更新:
备注:耗时操作,大概需要运行20分钟左右,可以在做其它事情的时候运行
In [6]:
%%time
abupy.env.g_market_source = EMarketSourceType.E_MARKET_SOURCE_bd
abupy.env.g_data_cache_type = EDataCacheType.E_DATA_CACHE_CSV
abu.run_kl_update(start='2011-08-08', end='2017-08-08', market=EMarketTargetType.E_MARKET_TARGET_CN, n_jobs=10)
如果不想通过直接下载数据文件的方式,也可切换至网易数据源,然后进行港股数据全市场更新:
备注:耗时操作,大概需要运行5分钟左右,可以在做其它事情的时候运行
In [7]:
%%time
abupy.env.g_market_source = EMarketSourceType.E_MARKET_SOURCE_nt
abupy.env.g_data_cache_type = EDataCacheType.E_DATA_CACHE_CSV
abu.run_kl_update(start='2011-08-08', end='2017-08-08', market=EMarketTargetType.E_MARKET_TARGET_HK, n_jobs=10)
切换至新浪期货数据源,然后进行期货数据全市场更新:
备注:非耗时操作,大概30秒
In [32]:
%%time
abupy.env.g_market_source = EMarketSourceType.E_MARKET_SOURCE_sn_futures
abupy.env.g_data_cache_type = EDataCacheType.E_DATA_CACHE_CSV
abu.run_kl_update(start='2011-08-08', end='2017-08-08', market=EMarketTargetType.E_MARKET_TARGET_FUTURES_CN, n_jobs=4)
切换至火币数据源,然后进行比特币,莱特币数据全市场更新:
备注:非耗时操作,大概需要5秒
In [33]:
%%time
abupy.env.g_market_source = EMarketSourceType.E_MARKET_SOURCE_hb_tc
abupy.env.g_data_cache_type = EDataCacheType.E_DATA_CACHE_CSV
abu.run_kl_update(start='2011-08-08', end='2017-08-08', market=EMarketTargetType.E_MARKET_TARGET_TC, n_jobs=2)
In [56]:
@AbuDataParseWrap()
class SNUSParser(object):
"""snus数据源解析类,被类装饰器AbuDataParseWrap装饰"""
def __init__(self, symbol, json_dict):
"""
:param symbol: 请求的symbol str对象
:param json_dict: 请求返回的json数据
"""
data = json_dict
# 为AbuDataParseWrap准备类必须的属性序列
if len(data) > 0:
# 时间日期序列
self.date = [item['d'] for item in data]
# 开盘价格序列
self.open = [item['o'] for item in data]
# 收盘价格序列
self.close = [item['c'] for item in data]
# 最高价格序列
self.high = [item['h'] for item in data]
# 最低价格序列
self.low = [item['l'] for item in data]
# 成交量序列
self.volume = [item['v'] for item in data]
上面编写的SNUSParser即为一个数据源返回数据解析类:
__init__
函数,根据这里的数据json_dict来拆分成self.date,self.open,self.close,self.high,self.low,self.volume如本例中每一条json数据的格式为:
{'d': '2017-08-08', 'o': '102.29', 'h': '102.35', 'l': '99.16', 'c': '100.07', 'v': '1834706'}
init函数目的就是通过拆解网络原始数据形成上述的五个基本序列,之后在类装饰器AbuDataParseWrap中会进行数据的再次加工以及规范标准化处理
更多详情请阅读源代码ABuDataParser
备注:这里拆解的过程没有在乎效率,只为好理解过程
在编写数据解析类后就需要编写个数据源类,如下所示,以新浪美股数据源为例:
In [46]:
class SNUSApi(StockBaseMarket, SupportMixin):
"""snus数据源,支持美股"""
K_NET_BASE = "http://stock.finance.sina.com.cn/usstock/api/json_v2.php/US_MinKService.getDailyK?" \
"symbol=%s&___qn=3n"
def __init__(self, symbol):
"""
:param symbol: Symbol类型对象
"""
super(SNUSApi, self).__init__(symbol)
# 设置数据源解析对象类
self.data_parser_cls = SNUSParser
def _support_market(self):
"""声明数据源支持美股"""
return [EMarketTargetType.E_MARKET_TARGET_US]
def kline(self, n_folds=2, start=None, end=None):
"""日k线接口"""
url = SNUSApi.K_NET_BASE % self._symbol.symbol_code
data = ABuNetWork.get(url=url, timeout=(10, 60)).json()
kl_df = self.data_parser_cls(self._symbol, data).df
if kl_df is None:
return None
return StockBaseMarket._fix_kline_pd(kl_df, n_folds, start, end)
def minute(self, n_fold=5, *args, **kwargs):
"""分钟k线接口"""
raise NotImplementedError('SNUSApi minute NotImplementedError!')
上面编写的SNUSApi即为一个股票数据源类:
__init__
函数中指定数据源解析类下面示例使用,如下通过check_support检测是否支持A股,结果显示False:
In [47]:
SNUSApi(code_to_symbol('sh601766')).check_support(rs=False)
Out[47]:
如下通过check_support检测是否支持美股,结果显示True:
In [48]:
SNUSApi(code_to_symbol('usSINA')).check_support(rs=False)
Out[48]:
如下通过kline接口获取数据,如下所示:
In [42]:
SNUSApi(code_to_symbol('usSINA')).kline().tail()
Out[42]:
接入SNUSApi至abupy系统中,只需要将数据源类名称直接赋予abupy.env.g_private_data_source:
In [50]:
abupy.env.g_private_data_source = SNUSApi
下面使用make_kl_df接口获取sh601766数据,显示SNUSApi不支持:
In [53]:
ABuSymbolPd.make_kl_df('sh601766')
下面使用make_kl_df接口获取美股数据, 返回的数据即是通过上面实现的SNUSApi返回的:
In [54]:
ABuSymbolPd.make_kl_df('usSINA').tail()
Out[54]:
In [12]:
@AbuDataParseWrap()
class SNFuturesParser(object):
"""示例期货数据源解析类,被类装饰器AbuDataParseWrap装饰"""
# noinspection PyUnusedLocal
def __init__(self, symbol, json_dict):
"""
:param symbol: 请求的symbol str对象
:param json_dict: 请求返回的json数据
"""
data = json_dict
# 为AbuDataParseWrap准备类必须的属性序列
if len(data) > 0:
# 时间日期序列
self.date = [item[0] for item in data]
# 开盘价格序列
self.open = [item[1] for item in data]
# 最高价格序列
self.high = [item[2] for item in data]
# 最低价格序列
self.low = [item[3] for item in data]
# 收盘价格序列
self.close = [item[4] for item in data]
# 成交量序列
self.volume = [item[5] for item in data]
上面编写的SNFuturesParser与SNUSParser基本相同:被类装饰器AbuDataParseWrap装饰,实现__init__
函数
如本例中每一条json数据的格式为, 所以通过序号解析对应的值:
['2017-08-08', '4295.000', '4358.000', '4281.000', '4345.000', '175570']
在编写数据解析类后就需要编写个数据源类,如下所示,以新浪期货数据源为例:
In [58]:
class SNFuturesApi(FuturesBaseMarket, SupportMixin):
"""sn futures数据源,支持国内期货"""
K_NET_BASE = "http://stock.finance.sina.com.cn/futures/api/json_v2.php/" \
"IndexService.getInnerFuturesDailyKLine?symbol=%s"
def __init__(self, symbol):
"""
:param symbol: Symbol类型对象
"""
super(SNFuturesApi, self).__init__(symbol)
# 设置数据源解析对象类
self.data_parser_cls = SNFuturesParser
def _support_market(self):
"""声明数据源支持期货数据"""
return [EMarketTargetType.E_MARKET_TARGET_FUTURES_CN]
def kline(self, n_folds=2, start=None, end=None):
"""日k线接口"""
url = SNFuturesApi.K_NET_BASE % self._symbol.symbol_code
data = ABuNetWork.get(url=url, timeout=(10, 60)).json()
kl_df = self.data_parser_cls(self._symbol, data).df
if kl_df is None:
return None
return FuturesBaseMarket._fix_kline_pd(kl_df, n_folds, start, end)
上面编写的SNFuturesApi即为一个期货数据源类:
__init__
函数中指定数据源解析类下面示例使用,如下通过check_support检测是否支持美股,结果显示False:
In [26]:
SNFuturesApi(code_to_symbol('usSINA')).check_support(rs=False)
Out[26]:
如下通过check_support检测是否支持期货,结果显示True:
In [6]:
SNFuturesApi(code_to_symbol('jd0')).check_support(rs=False)
Out[6]:
接入SNFuturesApi至abupy系统中, 使用make_kl_df接口获取期货鸡蛋连续数据:
In [34]:
abupy.env.g_private_data_source = SNFuturesApi
ABuSymbolPd.make_kl_df('jd0').tail()
Out[34]:
与期货市场类似的是美股期权市场,abupy同样支持美股期权市场的回测分析等操作,但由于暂时没有合适的可对外的数据源提供,所以暂时无示例,用户也可以在abupy中接入自己的美股期权数据源。
In [60]:
@AbuDataParseWrap()
class HBTCParser(object):
"""示例币类市场数据源解析类,被类装饰器AbuDataParseWrap装饰"""
def __init__(self, symbol, json_dict):
"""
:param symbol: 请求的symbol str对象
:param json_dict: 请求返回的json数据
"""
data = json_dict
# 为AbuDataParseWrap准备类必须的属性序列
if len(data) > 0:
# 时间日期序列
self.date = [item[0] for item in data]
# 开盘价格序列
self.open = [item[1] for item in data]
# 最高价格序列
self.high = [item[2] for item in data]
# 最低价格序列
self.low = [item[3] for item in data]
# 收盘价格序列
self.close = [item[4] for item in data]
# 成交量序列
self.volume = [item[5] for item in data]
# 时间日期进行格式转化,转化为如2017-07-26格式字符串
self.date = list(map(lambda date: ABuDateUtil.fmt_date(date), self.date))
上面编写的HBTCParser与上面的数据解析类基本相同:被类装饰器AbuDataParseWrap装饰,实现__init__
函数
如本例中每一条json数据的格式为, 所以通过序号解析对应的值:
['20170809000000000', 22588.08, 23149.99, 22250.0, 22730.0, 7425.5134]
所以需要使用ABuDateUtil.fmt_date将时间进行格式转化,下面编写对应的数据源类,如下所示,以火币数据源为例:
In [62]:
class HBApi(TCBaseMarket, SupportMixin):
"""hb数据源,支持币类,比特币,莱特币"""
K_NET_BASE = 'https://www.huobi.com/qt/staticmarket/%s_kline_100_json.js?length=%d'
def __init__(self, symbol):
"""
:param symbol: Symbol类型对象
"""
super(HBApi, self).__init__(symbol)
# 设置数据源解析对象类
self.data_parser_cls = HBTCParser
def _support_market(self):
"""只支持币类市场"""
return [EMarketTargetType.E_MARKET_TARGET_TC]
def kline(self, n_folds=2, start=None, end=None):
"""日k线接口"""
req_cnt = n_folds * 365
if start is not None and end is not None:
# 向上取整数,下面使用_fix_kline_pd再次进行剪裁, 要使用current_str_date不能是end
folds = math.ceil(ABuDateUtil.diff(ABuDateUtil.date_str_to_int(start),
ABuDateUtil.current_str_date()) / 365)
req_cnt = folds * 365
url = HBApi.K_NET_BASE % (self._symbol.symbol_code, req_cnt)
data = ABuNetWork.get(url=url, timeout=(10, 60)).json()
kl_df = self.data_parser_cls(self._symbol, data).df
if kl_df is None:
return None
return TCBaseMarket._fix_kline_pd(kl_df, n_folds, start, end)
def minute(self, *args, **kwargs):
"""分钟k线接口"""
raise NotImplementedError('HBApi minute NotImplementedError!')
上面编写的HBApi即为一个支持比特币,莱特币数据源类:
__init__
函数中指定数据源解析类下面示例使用,如下通过check_support检测是否支持美股,结果显示False:
In [63]:
HBApi(code_to_symbol('usSINA')).check_support(rs=False)
Out[63]:
如下通过check_support检测是否支持比特币,结果显示True:
In [18]:
HBApi(code_to_symbol('btc')).check_support(rs=False)
Out[18]:
接入HBApi至abupy系统中, 使用make_kl_df接口获取期货比特币数据:
In [20]:
abupy.env.g_private_data_source = HBApi
ABuSymbolPd.make_kl_df('btc').tail()
Out[20]:
小结:
abupy内置的数据源仅供学习使用,abupy提供了接入外部数据源的接口和规范,推荐购买数据源接入使用,特别是在实盘中。
abu量化系统文档教程持续更新中,请关注公众号中的更新提醒。
更多关于量化交易相关请阅读《量化交易之路》
更多关于量化交易与机器学习相关请阅读《机器学习之路》
更多关于abu量化系统请关注微信公众号: abu_quant