前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Qlib来啦:策略篇(一)

Qlib来啦:策略篇(一)

作者头像
量化投资与机器学习微信公众号
发布2022-05-30 15:48:15
2.6K0
发布2022-05-30 15:48:15
举报

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

完整源代码请点击阅读原文

在QIML公众号官方GitHub查看

QIML官方GitHub上线

https://github.com/QuantWorld2022

希望大家多Follow,多给星⭐️

历史推文

Qlib来啦:数据篇(一)

Qlib来啦:数据篇(二)

Qlib来啦:模型训练篇

前言

在之前的文章中,我们介绍了使用配置文件进行模型训练。一个典型的配置文件中,主要由两大部分组成:

  • qlib_init:指定数据存储的位置
  • task:训练任务的详细配置,主要包括model, dataset, record的配置

如下图标示,task中三个核心的配置,也正是研究的三个主要步骤:

  • 在model中详细定义需要训练的模型;
  • 在dataset中详细定义股票池、特征及训练目标等信息;
  • record部分主要用于定义模型训练完之后,对结果进行分析的流程。针对多因子量化研究的场景,一个典型的结果分析流程包括:
    • 使用SignalRecord,针对测试集数据,使用训练完的模型生成预测值;
    • 使用SigAnaRecord,对预测结果进行因子分析,计算IC、ICIR等指标;
    • 使用PortAnaRecord,对预测结果进行策略回测,如下图中使用了Qlib内置的TopKDropout策略,计算策略回测的绩效指标。

回测结果

运行完PortAnaRecord,回测结果会存储在mlruns文件夹下的以下文件中:

我们可以使用recorder读取回测结果:

代码语言:javascript
复制
from qlib.workflow import R
R.list_experiments() # 列出当前所有experiments
recorder = R.get_recorder(recorder_id='ff8c69f711204e8a9ea57ad165b09f25', experiment_name="gbdt_csi300_test")

# RankIc序列
recorder.load_object('sig_analysis/ric.pkl')
代码语言:javascript
复制
# 回测报告(净值,交易成本等)
recorder.load_object('portfolio_analysis/report_normal_1day.pkl')

关于策略类-BaseStrategy

在上面的回测中,使用了Qlib内置的TopKDropout策略。Qlib中策略的实现需要继承策略的基类BaseStrategy,策略的核心逻辑需要在generate_trade_decision的函数中实现。BaseStrategy有三个重要的属性:

  • level_infra: LevelInfrastructure, 一些通用的基础组件,比如交易日历trader_calendar
  • common_infra: CommonInfrastructure, 通过它可以获得当前持仓trade_position,及交易所组件exchange
  • trade_exchange:交易所组件

当前,我们只需要知道,这些属性主要是为了策略回测过程中获取相关信息所用。回测时会自动创建这些组件。

代码语言:javascript
复制
@property
def trade_calendar(self) -> TradeCalendarManager:
    return self.level_infra.get("trade_calendar")

@property
def trade_position(self) -> BasePosition:
    return self.common_infra.get("trade_account").current_position

当我们看TopKDropout的源码时,我们发现TopKDropout是继承自BaseSignalStrategy。BaseSignalStrategy也是BaseStrategy的一个子类,它与BaseStrategy最大的区别是属性中增加了signal,signal就是某个时间对某个股票的预测,比如上面预测结果pred就是signal:

代码语言:javascript
复制
df_signal = recorder.load_object('pred.pkl')
df_signal.head()

Signal

BaseSignalStrategy在初始化时,signal参数可以接受多种形式,但最终都会由create_signal_from转化成Signal类。Signal类的下有一个重要的方法get_signal,用在策略回测过程中获取指定时间的预测信号。

代码语言:javascript
复制
from qlib.contrib.strategy.signal_strategy import create_signal_from
signal = create_signal_from(df_signal)
signal.get_signal('2020-01-10', '2020-01-10')

学习TopkDropoutStrategy源码

分析一下TopkDropoutStrategy策略的源码,最核心的就是generate_trade_decision。如果大家熟悉常用的回测框架,如zipline,就可以把generate_trade_decision看作是zipline里的handle_data。在回测时,历史上每一天都会调用该方法,并返回TradeDecisionWO(可以看做是Order列表),策略执行器(BaseExecutor)会根据TradeDecisionWO执行交易并更新当前账户信息及持仓,并把这次的执行结果(execute_result)返回给策略。以下是简化的运行流程:

如果要实现自定义策略,就需要完成以下三个步骤:

1、继承BaseSignalStrategy

2、实现generate_trade_decision

3、把每日的Order通过TradeDecisionWO返回

仅使用策略回测功能

得益于Qlib的松耦合设计,我们可以单独使用策略回测功能。在分析PorAnaRecord的源码时,我们发现其中回测调用了qlib.backtest.backtest函数。这个函数除了一些基本的回测设置参数外,还需要传入策略strategy和执行器executor。

backtest函数具体的调用路径如下,可以看到在最后一步collect_data_loop的源码,就是我们在学习TopkDropoutStrategy源码文中作图展示的逻辑。 

backtest中必须要传入executor,但在qlib.contrib.evaluate.backtest_daily中,对backtest进行了进一步的包装。其内部默认实例化一个简单的SimulatorExecutor,所以如果需要单独进行策略回测可以直接使用backtest_daily。下面我们看一个例子:

代码语言:javascript
复制
from pprint import pprint
import pandas as pd
from qlib.utils.time import Freq
from qlib.utils import flatten_dict
from qlib.contrib.evaluate import backtest_daily
from qlib.contrib.evaluate import risk_analysis
from qlib.contrib.strategy import TopkDropoutStrategy


CSI300_BENCH = "SH000300"
STRATEGY_CONFIG = {
    "topk": 50,
    "n_drop": 5,
    # pred_score, pd.Series
    "signal": df_signal,
}

strategy_obj = TopkDropoutStrategy(**STRATEGY_CONFIG)
report_normal, positions_normal = backtest_daily(
    start_time="2020-01-02", end_time="2022-03-01", strategy=strategy_obj
)
analysis = dict()
# default frequency will be daily (i.e. "day")
analysis["excess_return_without_cost"] = risk_analysis(report_normal["return"] - report_normal["bench"])
analysis["excess_return_with_cost"] = risk_analysis(report_normal["return"] - report_normal["bench"] - report_normal["cost"])

analysis_df = pd.concat(analysis) # type: pd.DataFrame
pprint(analysis_df)

总结

1、Qlib中的策略基于BaseStrategy实现,BaseStrategy可以通过level_infra和common_infra获得账户信息及交易日历等;

2、如果在模型训练过程中直接进行策略回测分析,可以使用PortAnaRecord;

3、策略回测功能也可以单独使用,需要以下几个步骤:

  • 准备需要回测的策略
  • 调用backtest_daily函数

Qlib中还有指数增加策略,运行时需要因子暴露/风险模型/组合优化器,这些qlib都进行了实现,下一篇我们详细分享qlib中的指数增强策略。

完整源代码请点击阅读原文

在QIML公众号官方GitHub查看

QIML官方GitHub上线

https://github.com/QuantWorld2022

希望大家多Follow,多给星⭐️

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-05-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 量化投资与机器学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 量化投资与机器学习微信公众号,是业内垂直于量化投资、对冲基金、Fintech、人工智能、大数据等领域的主流自媒体。公众号拥有来自公募、私募、券商、期货、银行、保险、高校等行业30W+关注者,荣获2021年度AMMA优秀品牌力、优秀洞察力大奖,连续2年被腾讯云+社区评选为“年度最佳作者”。
相关产品与服务
数据保险箱
数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档