量化投资与机器学习微信公众号,是业内垂直于量化投资、对冲基金、Fintech、人工智能、大数据领域的主流自媒体公众号拥有来自公募、私募、券商、期货、银行、保险、高校等行业30W+关注者,荣获2021年度AMMA优秀品牌力、优秀洞察力大奖,连续2年被腾讯云+社区评选为“年度最佳作者”。

前言
在之前的文章中,我们使用Qlib实现了GAT与新闻共现矩阵的量化策略(A股实践 :图神经网络与新闻共现矩阵策略(附代码))。后台收到很多留言,希望我们能够出一些Qlib的使用教程。Qlib确实一个非常体系化、流程化且非常优秀的基于机器学习的量化研究框架。它将量化研究与机器学习非常系统化的结合在一起,能够通过配置文件工程化的运行模型。但框架本身又是松耦合,能够单独使用内部的某些功能进行量化研究。
在使用Qlib的过程中,我们也多多少少遇到了些问题。但是,在不断试错及实践中,这些问题都得到了解决。现在,就让我们真正的从零开始,学会如何使用Qlib。
顺便要给大家介绍一下我们之前的Backtrader系列。一经推出,收获无数好评。
QIML一直在专业和质量上为大家提供最好的内容!
Qlib用来做什么?
多因子策略研究的大概流程包括:数据整理、因子构建、因子测试及组合回测等。随着近些年机器学习算法的发展,因子研究的过程中越来越多的使用到了机器学习算法。Qlib就是这样一个结合量化研究流程与机器学习模型的框架:
如何安装?
安装Qlib非常简单,直接使用pip就可以,但由于qlib依赖cython,所以在安装qlib前必须安装cython。当然我们推荐新建一个环境安装qlib,由于现在qlib对python3.8的支持最完善,所以指定创建3.8版本的虚拟环境:
# 新建qlib环境
conda create -n qlib python=
3.8
conda activate qlib



# 安装qlib
pip install --upgrade cython

pip install pyqlib
安装完之后,如果导入qlib没报错,就说明安装成功。
如何批量导入外部数据?
Qlib本身集成了部分数据源,如果希望快速了解Qlib的运行机制,可以直接使用。但由于集成数据的质量问题,不推荐想要深度使用Qlib做研究的用户使用内置数据源。所以该如何导入外部数据呢?
Qlib使用自有的bin格式存储研究数据,如果使用外部数据需要将数据进行转换成bin格式,qlib已经提供了转换数据所需的代码。我们只要将外部数据按照指定的格式准备好,并运行相关代码即可。我们就按照以下步骤一步一步操作:
1、克隆Qlib的代码
由于需要使用qlib提供的数据转换代码,所以我们需要把qlib的代码克隆到本地,如下我们把代码克隆到本地文件夹~/Dev/qlib:

2、准备外部数据
我们以价格数据为例,在准备价格数据时有以下要求:
  • 每个股票保存为一个csv文件。其中日期列命名为'date'。文件名为股票代码,如股票600000的价格数据,保存在'SH600000.csv'。我们将所有A股票的价格数据存在了以下文件夹'~/dev/stock_price_data_wind'
  • 价格为后复权的价格数据。每个csv包含以下数据,关于价格数据的准备有以下注意点
    • 其中价格须为复权后的数据(推荐后复权),factor为复权因子。
    • 如果只有复权价格,没有复权因子也可以,这时有两种方法:删除factor列,或者factor均设置为1。提供factor的好处是在回测时,qlib会通过factor将价格转为真实价格进行动态回测。
    • 如果使用wind数据,需要注意单位,如amount原始表单位是千,所以需要乘以1000,volume为手,需要乘以100。
    • 原始数据中的vwap为未复权的价格,需要乘以复权因子转换为复权后的vwap
下表的成交量为复权后的成交量,计算方法是成交金额/复权后vwap
  • 使用dump_all的方法转换数据。dump_all的方法位于qlib/scripts,一般用于首次批量转换数据,其他还有dump_fix、dump_update等方法(稍后介绍)。数据转换包含以下步骤:
    • 创建转换后数据保存的文件夹,比如dev/qlib_data,在终端运行: mkdir -p ~/dev/qlib_data/cn_data_wind
    • 在终端进入qlib文件夹,cd ~/dev/qlib
    • 运行以下代码进行数据转换,各参数说明如下
      • --csv_path 指定原始csv文件所在目录,这里是~/dev/stock_price_data_wind
      • --qlib_dir 指定转换后的数据存储目录,这里是~/dev/qlib_data/cn_data_wind
      • --freq 数据的频率,默认是day,如果是其他频率K线,如5分钟,可以设置 --freq 5min,需要注意的是如果是小时K线,参数应该是 --freq 60min
      • --date_field_name 如果csv文件内日期列名不是'date',可以使用这个参数指定日期列
      • --exlcude_fields 指定不需要转换的列
      • --include_fields 指定需要转换的列
python scripts/dump_bin.py dump_all --csv_path ~/dev/stock_price_data_wind --qlib_dir ~/dev/qlib_data/cn_data_wind
转换完之后,我们可以看到在目标文件夹 ~/dev/qlib_data/cn_data_wind内多了三个文件夹:

其中calendars是根据价格文件自动生成的交易日历,features目录内保存了刚刚转换的价格数据。存放规则是每个股票一个目录,每个目录内,每一列(一个feature)一个文件:
instruments目录内存放着成分股数据,里面有一个自动生成的all.txt,包含了所有转换的股票。如果需要指数成分股的数据,可以自行导入。具体方法是,按“股票代码-纳入日期-剔除日期”的格式准备txt文件,注意列于列之间用\t分隔,如下图,我们准备了sh000300.txt,即沪深300成分股文件:
如何更新/扩展数据?
dump_all用于将数据批量导入至指定目录,那如何更新数据呢?更新数据不能再使用dump_all,因为dump_all会对目录进行覆盖。可以视情况使用dump_fix或dump_update。三者的区别如下:
  • dump_fix:增加新的因子(一列)、新的股票或重写已经导入的某一个feature。如果新增某个因子,为根据calendar.txt已有的日期进行新增,不在calendar日期覆盖的数据会被忽略。比如新增MACD因子,原先已有的数据保存至2020-12-31,新的MACD因子数据至2021-01-31,那用dump_fix只会新增MACD至2020-12-31。多出的那部分数据需要使用dump_all
  • dump_update:在时间维度上扩展已经存在的数据,所以称之为更新。
总之,dump_fix用于非时间维度的扩展,包括新增标的、因子等。dump_update用于已有数据在时间维度上的更新。
更详细解释可参考:
https://github.com/microsoft/qlib/issues/535
如何使用数据?
准备好数据以后,我们就可以在qlib中使用数据,qlib最近更新了一个tutorial notebook,更适合日常研究场景下在notebook中使用qlib。因为qlib原先使用配置文件+workflow的模式,让初学者很难入手。我们基于这个tutorial notebook介绍下qlib中的数据模块。
首先初始化qlib的数据目录,使用我们刚刚的目录初始化qlib:
qlib中提供了一个数据接口D,可以使用D获取原始数据,如以下代码可以获取股票601216指定时间的价格数据:
from
 qlib.data
import
 D

df = D.features([
'SH601216'
], [
'$open'
,
'$high'
,
'$low'
,
'$close'
,
'$factor'
], start_time=
'2020-05-01'
, end_time=
'2020-05-31'
)
关于qlib中数据获取及使用的更详细介绍,可以参考以下notebook:
https://github.com/microsoft/qlib/blob/main/examples/tutorial/detailed_workflow.ipynb
我们对qlib上不同的数据模块类做一个总结,有利大家更好的理解qlib的各个模块:
  • DataLoader:用于读取原始数据,如果从刚刚dump的文件夹读取转换后的数据,可以使用QlibDataLoader,如果是直接使用外部已经准备好的数据文件,可以使用StaticDataLoader。
  • DataHandler:数据使用DataLoader读取好之后,就需要交给DataHandler进行处理,其中包括缺失值、标准化等处理,也可以自定义处理函数传入DataHandler。
  • Dataset:处理好的数据,需要整理成Dataset,才能在模型训练中使用。
本文核心介绍了,如果在qlib中导入外部数据。关于DataLoader、DataHandler、Dataset更多的使用方法及注意事项,我们将在本系列下一篇推文中更大家分享。
继续阅读
阅读原文