引言
之前的文章中,我使用优矿平台完成了一个简单的策略分析。在那篇文章的末尾,我提到一个提高的方向就是自己实现数据获取和回测。我个人并不喜欢看不到源码的框架,并且优矿想要获取加密货币的数据必须付费,所以这里想基于abu(一个开源的量化系统)进行一个开发。不过值得说明的是,像我这样的个人研究者,受迫于资金和工具的落后,相对来说,使用优矿这样的工具平台其实是一个更好的选择,可以帮助研究人员更专注于策略。我这么做只是自己的偏好而已。本项目地址
https://github.com/qiushui777/Qsabuabu简介
abu是由阿布开发的一个量化交易系统,已经公布源码,官方网站在https://blog.abuquant.com/。其上有丰富的教程。此处就不再多做介绍了。abu数据获取源码分析
为了增加币安的api,我们需要先分析清楚abu的相关源码。(1)判断是从本地还是网络获取数据
获取数据首先从ABuSymbolPd.py文件开始,它自身并不是一个类,而是写了几个重要的函数。在示例中,代码通过make_kl_df函数获取数据。该函数有以下参数1 | :param data_mode: EMarketDataSplitMode对象 |
如果这里设定了要使用并行的话,将会调用kl_df_dict_parallel函数,其他情况下,调用的是_make_kl_df。而后者进一步调用了kline_pd函数。这个函数在ABuDataSource.py中,并且会设置数据源source_dict。此处函数关键的部分如下。
1 | if ABuEnv.g_data_fetch_mode != EMarketDataFetchMode.E_DATA_FETCH_FORCE_NET: |
分别是从本地和从网络来获取数据。这两个关键的函数都在ABuDataCache.py中。
kline_pd这个函数还有一个比较重要的地方是,它最初会设置一个symbol,这对后面的很多东西都会有影响。这部分逻辑在code_to_symbol函数中提现。
(2)本地数据获取
在load_kline_df中,会先通过load_kline_key判断对应的数据集是否存在,如果存在就会进一步调用load_kline_func函数也就是_load_kline_csv。load_df_csv会返回一个Dataframe也就是那个csv的内容。1 | date_key = None |
(3网络数据的获取
从网络获取数据的关键就是先实例化对象,然后调用对象的kline函数来获取数据。1 | # 实例化数据源对象 |
这里的source最初是在ABuDataSource.py 中被定义,而后一路传递过来。
1 | source_dict = {EMarketSourceType.E_MARKET_SOURCE_bd.value: BDApi, |
对应的每个值为ABuEnv.py中EMarketSourceType类被定义。
1 | class EMarketSourceType(Enum): |
而这里的HBApi类则在ABuDataFeed.py中被定义。在这个datafeed中,我们看到它有调用到ABuDataParser.py中的HBTCParser来进行数据的解析。
(4)数据存储
在load_kline_df_net函数中,获取网络的数据后,会调用dump_kline_df函数。1 | dump_kline_df(df, temp_symbol.value, df_key) |
这个函数中,如果发现本地没有存储过相关有的数据,会去调用
1 | dump_kline_func(symbol_key, date_key, dump_df) |
一般情况下,我们用csv的格式进行存储,这里的话也就是_dump_kline_csv。
增加币安api
通过以上的分析,我们已经可以开始修改源码增加api了。(1)全局变量设置
首先在ABuEnv.py的类EMarketSourceType中加入1 | E_MARKET_SOURCE_binance= 201 |
在ABuDataSource.py中添加SourceDict的对应项,并记得在import的时候导入
1 | EMarketSourceType.E_MARKET_SOURCE_binance: BNApi |
在ABuDataFeed.py中加入对应的BNApi类。由于BNApi类需要继承SuppportMixin,这个类会检查自身是否支持传入的这个交易对。在加入这个类的过程中,可以发现kline_pd的code_to_symbol函数也需要做相应的修改,否则无法返回我们需要的symbol对象。所以我们需要在这个函数中加入如下的代码,专门为我们自定义的数据请求服务。
1 | qs_flag = code[:2] |
并且,我们在SupportMixin类的check_support函数中也添加对应的代码
1 | if(symbol.symbol_code[:2] == "Qs"): |
(2)数据处理
对于币安返回的数据,我们需要设置一个parser进行处理。这里需要解决的问题是,币安返回的date是毫秒级别的unix time,所以我们在ABuDateUtil.py中加入这样的一个函数进行时间的转换。1 | def fmt_epoch(epoch_time): |
在此之后,我们就可以写出针对币安的数据解析类
1 |
|
(3)BNApi
到这里,我们可以完成BNApi这个类了。1 | class BNApi(TCBaseMarket, SupportMixin): |
完成这一切后就可以愉快地使用这个api来获取币安地数据了,不过很快,我们就悲剧地发现币安的api存在诸多问题,例如‘BTCUSDT’这个交易对只能获取17年到18年底的数据。显然,我们开发的这个api并不实用,所以我们可以根据上述模式增加较好的api。具体使用方法如下。
1 | abupy.env.g_market_source = EMarketSourceType.E_MARKET_SOURCE_binance |
结论
写到这里,我总结下我这个小project的优缺点优点:
- 能够获取币安的加密货币数据,优矿上需要付费才能获得,并且abu原本的火币接口已经无法使用
- 后续想要增加接口可以按照此模式进行
缺点:
- 该接口无法获取完整数据,不同的交易对能获取的数据时间段并不相同
- 只有获取某时间段交易数据的接口,其他接口未开发
- 币安接口调用必须翻墙,自身ip需要是海外ip
后续研究
- 增加较为实用的api,币安很多api暂时未实现
- 利用离线数据进行策略研究