Redian新闻
>
Qlib来啦:策略篇(一)

Qlib来啦:策略篇(一)

财经


量化投资与机器学习微信公众号,是业内垂直于量化投资、对冲基金、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读取回测结果:


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')



# 回测报告(净值,交易成本等)
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:交易所组件


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


@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:


df_signal = recorder.load_object('pred.pkl')
df_signal.head()




Signal


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


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。下面我们看一个例子:


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,多给星⭐️

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
小说连载:祝钰儿(十一)你应该知道的死亡教育:与光同尘 我心安宁(一)TikTok电商折戟英国背后:策略失误、考核混乱、部门内耗艺术家父母如何引导和与孩子进行“性话题”的交流(一)“外星”荒原,视觉飨宴——(一)拱门国家公园【英译唐诗和咏唱】李白《黄鹤楼送孟浩然之广陵》唐山事件:舆情,及其背后的社会、心理、伦理(一)孔兵开发了小马丁品牌效应——足球追梦人孔兵(二十一)洋河,再度崛起(一)对父母帮成年子女的几点思考英国骄傲月限定来啦:彩虹硬币/邮票/奶昔/白T...买起来!【炜炜道来】六月策略延续-社融加速下的稳增长交易策略2021精选投资买卖案例(一)Qlib来啦:数据篇(二)Qlib来啦:模型训练篇七大策略规模以上机构4月业绩快报:4月延续下跌态势,仅债券策略获得正收益孔兵叹息足球大环境对球员运动生涯的伤害——足球追梦人孔兵(十一)高频有两大误解!百亿私募世纪前沿陈家馨:对抗量化周期一手策略升级,一手多策略配置冷战遗孽,“脑死亡”后如何借尸还魂? | “且看北约”系列评论(一)我从2000公里外收养的这只小土狗狗,后续故事来啦:)消费与零售行业的秘密武器:面向未来的组织能力建设(一)VR陀螺五一宅家系列(一):VR健身VS看刘耕宏直播健身,你选哪个?从中国视角看驱动当代俄罗斯的政治理念(一)北京“秘境”(一)芝加哥植物园兰花展走向工业化之路:中国绕过了那些坑?(一)足球追梦人孔兵 (一)防控体系的重要迭代:第九版防控方案学习(一)【24/50】活动--黑白极简穿搭大篇:伊拉克猖狂的腐败(一)网络与复杂系统(一)“数据跨境安全网关”条款评注(一):第一版前言勘误——兼谈近阶段的人生感悟揭开保险金信托的面纱(一)我眼中的保险金信托国际 | 世界银行2022碳定价状况和趋势报告解读(一):碳税
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。