Python 机器学习算法交易实用指南(一)(1)https://developer.aliyun.com/article/1523715
Alpha 因子研究和评估
Alpha 因子的设计旨在从数据中提取信号,以预测给定投资宇宙在交易周期内的资产回报。当评估时,一个因子对每个资产都有一个值,但可能结合一个或多个输入变量。该过程涉及下图中概述的步骤:
交易策略工作流的研究阶段包括 Alpha 因子的设计、评估和组合。机器学习在这个过程中起着重要作用,因为投资者对较简单因子的信号衰减以及当今可用的数据更加丰富而作出反应,因素的复杂性增加了。
预测性 Alpha 因子的开发需要探索输入数据与目标回报之间的关系,创造性的特征工程,并测试和微调数据转换以优化输入的预测能力。
数据转换范围从简单的非参数排名到复杂的集成模型或深度神经网络,取决于输入中的信号量和输入与目标之间关系的复杂性。许多较简单的因子已经从学术研究中出现,并且在过去几十年中在工业中越来越广泛地使用。
为了最小化由数据挖掘导致的假发现的风险,并且因为金融领域已经经历了几十年的研究,并产生了几个诺贝尔奖,投资者更喜欢依赖与金融市场和投资者行为理论相一致的因子。阐明这些理论不在本书的范围之内,但参考资料将突出显示进一步探讨这种算法交易策略重要框架方面的途径。
要验证 alpha 因子候选的信号内容,就需要在代表市场体制的环境中获得其预测能力的稳健估计。可靠的估计需要避免许多方法论和实践上的陷阱,包括使用导致存活或前瞻性偏差的数据,因为它们不反映真实的 PIT 信息,或者由于对同一数据进行多次测试而未能纠正偏差。
从 alpha 因子中得出的信号通常单独很弱,但与其他因子或数据源结合起来,例如,根据市场或经济环境的情况调节信号,就足够强大了。
投资组合优化与风险管理
Alpha 因子发出入场和退出信号,导致买入或卖出订单,订单执行结果导致投资组合持仓。各个持仓的风险配置相互作用,形成特定的投资组合风险配置。投资组合管理涉及优化持仓权重,以实现所需的投资组合风险和回报配置,该过程高度动态,可以不断纳入不断演化的市场数据。
在此过程中的交易执行需要平衡交易员的困境:快速执行往往会由于市场影响而增加成本,而慢速执行可能会在实现价格偏离决策时的价格时引起执行差距。风险管理贯穿整个投资组合管理过程,以根据观察到或预测到的市场环境变化来调整持仓或承担对冲,从而影响投资组合风险配置。
策略回测
将投资理念纳入算法策略中需要进行广泛的测试,采用科学方法试图根据其在备用样本市场情景中的表现来拒绝该理念。测试可能涉及使用模拟数据来捕捉被认为可能但在历史数据中未反映出来的情景。
一个策略回测引擎需要逼真地模拟策略的执行,以实现无偏的性能和风险估计。除了数据或统计学使用上的缺陷可能引入的潜在偏差之外,回测引擎还需要准确地表示与市场条件相一致的交易信号评估、订单下达和执行等实践方面的内容。
机器学习和算法交易策略
量化策略已经在三个阶段中演变并变得更加复杂:
- 在 1980 年代和 1990 年代,信号通常源自学术研究,并使用从市场和基本数据中衍生出的单一或极少量的输入。这些信号现在在很大程度上被商品化,并且作为 ETF 可得,例如基本的均值回归策略。
- 在 2000 年代,基于因子的投资大量涌现。基金使用算法识别暴露于价值或动量等风险因子的资产,以寻求套利机会。金融危机早期的赎回引发了 2007 年 8 月的量化颤抖,这一现象在基于因子的基金行业中蔓延开来。现在,这些策略也以长期智能贝塔基金的形式出现,根据一组给定的风险因子倾斜投资组合。
- 第三个时代由对 ML 能力和替代数据的投资驱动,以生成可重复交易策略的利润信号。因子衰减是一个主要挑战:从发现到出版,新异常的超额收益已经显示出下降了四分之一,并且在出版后因竞争和拥挤导致下降超过 50%。
有几种使用算法执行交易规则的交易策略类别:
- 旨在从小的价格波动中获利的短期交易,例如由于套利。
- 旨在利用预测其他市场参与者行为的行为策略。
- 旨在优化交易执行的程序,以及
- 基于预测定价的大量交易群体。
上述 HFT 基金主要依赖短期持有期从基于买卖盘套利或统计套利的微小价格波动中获利。行为算法通常在较低流动性环境中运作,并旨在预测大型参与者可能会对价格产生重大影响的动向。价格影响的期望基于嗅探算法,这些算法产生有关其他市场参与者策略或市场模式(例如 ETF 强制交易)的见解。
交易执行程序旨在限制交易的市场影响,并从简单的切片交易以匹配时间加权平均价格(TWAP)或成交量加权平均价格(VWAP)到更复杂的算法。这些算法可以在证券或投资组合级别操作,例如,实施多腿衍生品或跨资产交易。
交易 ML 的用例
ML 从各种市场、基本和替代数据中提取信号,并可以应用于算法交易策略过程的所有步骤。关键应用包括:
- 数据挖掘以识别模式和提取特征。
- 通过监督学习生成风险因子或 Alpha,并提出交易思路。
- 将个体信号聚合成策略。
- 根据算法学到的风险配置资产。
- 通过使用合成数据来测试和评估策略。
- 使用强化学习进行交易策略的交互式自动优化。
我们简要介绍了其中一些应用,并确定我们将在后面的章节中演示它们的使用。
用于特征提取的数据挖掘
对大型复杂数据集的成本效益评估需要大规模检测信号。全书中有几个示例:
- 信息论是一个有用的工具,用于提取捕捉潜在信号的特征,并可用于 ML 模型。在第四章,Alpha Factor Research中,我们使用互信息来评估单个特征对监督学习算法预测资产收益的潜在价值。
- 在第十二章,无监督学习中,我们介绍了从高维数据集中创建特征的各种技术。在第十四章,主题建模中,我们将这些技术应用于文本数据。
- 我们强调了获取有关单个变量预测能力的模型特定方法。我们使用一种称为SHapley Additive exPlanations(SHAP)的新颖博弈论方法来将预测性能归因于具有大量输入变量的复杂梯度增强机器中的单个特征。
监督学习用于α因子的创建和聚合
将 ML 应用于交易的主要理由是获得关于资产基本面、价格走势或市场状况的预测。策略可以利用多个 ML 算法相互构建。下游模型可以通过整合关于个别资产前景、资本市场预期和证券之间相关性的预测,生成组合水平的信号。或者,ML 预测可以像上面概述的量化基本方法那样通知自主交易。ML 预测还可以针对特定风险因素,如价值或波动性,或者实施技术方法,如趋势跟踪或均值回归:
- 在第三章,金融替代数据中,我们说明了如何处理基本数据以创建 ML 驱动的估值模型的输入
- 在第十三章,处理文本数据,第十四章,主题建模,和第十五章,词嵌入中,我们使用企业评论的替代数据,该数据可用于为公司的收入制定预测,作为估值练习的输入。
- 在第八章,时间序列模型中,我们演示了如何预测宏观变量作为市场预期的输入以及如何预测波动性等风险因素
- 在第十八章,递归神经网络中,我们介绍了递归神经网络(RNNs),它们在非线性时间序列数据上表现出优越的性能。
资产配置
ML 已被用于基于决策树模型进行投资组合配置,该模型计算一种层次化的风险平衡形式。因此,风险特征是由资产价格模式驱动的,而不是由资产类别驱动的,实现了优越的风险收益特征。
在第五章,策略评估和第十二章,无监督学习中,我们说明了层次聚类如何提取数据驱动的风险类别,这些类别比传统资产类别定义更好地反映了相关性模式。
测试交易想法
回测是选择成功的算法交易策略的关键步骤。使用合成数据的交叉验证是生成可靠的样本外结果的关键 ML 技术,当结合适当的方法来纠正多次测试时。金融数据的时间序列性质要求对标准方法进行修改,以避免前瞻性偏差或以其他方式污染用于训练、验证和测试的数据。此外,历史数据的有限可用性已经促使出现了使用合成数据的替代方法:
- 我们将演示使用市场、基本和替代数据来测试 ML 模型的各种方法,以获得对样本外误差的合理估计。
- 在第二十章,自动编码器和生成对抗网络中,我们介绍了能够生成高质量合成数据的 GAN。
强化学习
交易发生在竞争激烈、互动式市场中。强化学习旨在训练代理以学习基于奖励的策略函数。
- 在第二十一章,强化学习中,我们介绍了关键的强化学习算法,如 Q-Learning 和 Dyna 架构,并演示了使用 OpenAI 的 gym 环境对交易进行强化学习算法的训练。
概要
在本章中,我们介绍了算法交易策略以及 ML 如何成为设计和组合 alpha 因子的关键因素,这些因素又是投资组合表现的关键驱动因素。我们涵盖了围绕算法交易策略的各种行业趋势,替代数据的出现以及利用 ML 来利用这些新信息优势来源的情况。
此外,我们介绍了算法交易策略设计过程,重要的 alpha 因子类型,以及我们将如何使用 ML 来设计和执行我们的策略。在接下来的两章中,我们将更仔细地研究任何算法交易策略的推动力—市场、基本和替代数据来源—使用 ML。
第二章:市场和基本数据
数据一直是交易的重要驱动因素,交易员长期以来一直在努力通过获取优越信息来获取优势。这些努力至少可以追溯到有关罗斯柴尔德家族利用鸽子跨越海峡携带的关于滑铁卢战役英军胜利的提前消息进行债券购买的传闻。
如今,对更快数据访问的投资采取了由领先的高频交易(HFT)公司组成的 Go West 联盟的形式,该联盟将芝加哥商品交易所(CME)与东京连接起来。在 CME 和纽约 BATS 交易所之间的往返延迟已降至接近理论极限的 8 毫秒,因为交易员竞相利用套利机会。
传统上,投资策略主要依赖于公开可用的数据,有限地努力创建或获取私有数据集。在股票的情况下,基本策略使用基于报告的财务数据构建的金融模型,可能结合行业或宏观数据。由技术分析驱动的策略从市场数据中提取信号,例如价格和成交量。
机器学习(ML)算法可以更有效地利用市场和基本数据,特别是当与替代数据结合使用时,这是下一章的主题。我们将在后续章节中介绍几种侧重于市场和基本数据的技术,例如经典和现代时间序列技术,包括循环神经网络(RNNs)。
本章介绍市场和基本数据源以及它们被创建的环境。熟悉各种订单类型和交易基础设施很重要,因为它们影响交易策略的回测模拟。我们还说明了如何使用 Python 访问和处理交易和财务报表数据。
特别是,本章将涵盖以下主题:
- 市场微观结构如何塑造市场数据
- 如何利用 Nasdaq ITCH 从 tick 数据重建订单簿
- 如何使用各种类型的条形图总结 tick 数据
- 如何处理可扩展业务报告语言(XBRL)编码的电子申报
- 如何解析和结合市场和基本数据以创建 P/E 序列
- 如何使用 Python 访问各种市场和基本数据源
如何处理市场数据
市场数据是在众多市场交易中买卖订单的提交和处理过程中产生的。这些数据反映了交易场所的机构环境,包括管理订单、交易执行和价格形成的规则和法规。
算法交易员使用机器学习算法分析买卖订单的流动以及由此产生的成交量和价格统计数据,提取能捕捉到例如需求-供给动态或某些市场参与者行为的交易信号或特征。
我们将首先审查影响在回测期间模拟交易策略的机构特征。然后,我们将介绍如何从订单簿来源重建 Tick 数据。接下来,我们将重点介绍几种规范化 Tick 数据的方法,并旨在最大化信息内容。最后,我们将说明如何访问各种市场数据提供商接口,并突出几个提供商。
市场微观结构
市场微观结构是金融经济学的一个分支,它研究交易过程以及相关市场的组织。机构细节在不同资产类别及其衍生品、交易场所和地理位置上相当复杂和多样化。在我们深入研究交易产生的数据之前,我们将对关键概念进行简要概述。GitHub 上的参考链接指向了几个对这一主题进行了详细处理的来源。
市场场所
金融工具的交易发生在有组织的、主要是电子交易所和场外市场上。交易所是买方和卖方相遇的中央市场,在这里买方竞相出价,而卖方竞相报出最低的报价。
在美国和国外有许多交易所和替代交易场所。以下表格列出了一些较大的全球交易所以及截至 2018 年 03 月各种资产类别(包括衍生品)的 12 个月交易量。通常,少数金融工具占据了大部分交易量:
股票 | |
交易所 | 市值(美元百万) |
纽约证券交易所 | 23,138,626 |
纳斯达克-美国 | 10,375,718 |
日本交易所集团 | 6,287,739 |
上海证券交易所 | 5,022,691 |
欧洲交易所 | 4,649,073 |
香港交易及结算所 | 4,443,082 |
伦敦证券交易所集团 | 3,986,413 |
深圳证券交易所 | 3,547,312 |
德国交易所 | 2,339,092 |
印度孟买证券交易所有限公司 | 2,298,179 |
印度国家证券交易所有限公司 | 2,273,286 |
BATS 全球市场 - 美国 | |
芝加哥期权交易所 | |
国际证券交易所 |
交易所可能依赖双边交易或以订单为驱动的系统,根据某些规则匹配买入和卖出订单。价格形成可能通过拍卖进行,例如在纽约证券交易所(NYSE)中,最高出价和最低报价被匹配,或通过买家从卖家购买然后卖给买家的交易商进行。
许多交易所使用提供流动性的中间人,即通过在某些证券中做市来进行交易的能力。例如,纽约证券交易所通常有一个指定的市场主持人,他确保每个证券的交易有序进行,而全国证券交易商自动报价系统(Nasdaq)有几个。中间人可以充当作为自己代理人交易的交易商,也可以充当作为他人代理人交易的经纪人。
交易所过去是成员所有的,但随着市场改革的加剧,它们经常转为公司所有。纽约证券交易所可以追溯到 1792 年,而纳斯达克于 1971 年开始,是世界上第一个电子股票交易市场,并接管了大多数曾在场外交易的股票交易。仅在美国股票市场,交易分散在 13 个交易所和 40 多个另类交易场所,每个都向综合带报告交易,但延迟不同。
订单类型
交易员可以提交各种类型的买入或卖出订单。一些订单保证立即执行,而另一些可能规定价格阈值或其他触发执行的条件。订单通常仅在同一交易日有效,除非另有规定。
市场订单保证在到达交易场所时立即执行订单,以那一刻的价格为准。相比之下,限价订单仅在市场价格高于(低于)卖出(买入)限价订单的限价时执行。转而停止订单仅在市场价格上升到(下跌到)买入(卖出)停止订单的指定价格时才变为活动状态。购买停止订单可用于限制空头交易的损失。停止订单也可能有限制。
订单可能附加有许多其他条件——全或无订单防止部分执行,仅在指定数量的股票可用时才会被填充,并且可以在当天或更长时间内有效。它们需要特殊处理,对市场参与者不可见。立即成交或取消订单也防止部分执行,但如果未立即执行则取消。立即取消订单立即买入或卖出可用的股票数量并取消剩余部分。不持有订单允许经纪人决定执行的时间和价格。最后,市场开盘/收盘订单在市场开盘或收盘时或附近执行。允许部分执行。
处理订单簿数据
市场数据的主要来源是订单簿,它在整天实时不断更新以反映所有交易活动。 交易所通常将此数据作为实时服务提供,并可能免费提供一些历史数据。
交易活动体现在市场参与者发送的大量有关交易订单的消息中。 这些消息通常符合用于实时交换证券交易和市场数据的电子金融信息交换(FIX)通信协议或本地交换协议的语法。
FIX 协议
就像 SWIFT 是后台(例如,用于交易结算)消息传递的消息协议一样,FIX 协议是交易执行之前和之间的默认消息标准,在交易所、银行、经纪商、结算公司和其他市场参与者之间的通信中。 富达投资和所罗门兄弟公司于 1992 年引入了 FIX,以促进经纪商和机构客户之间的电子通信,当时他们通过电话交换信息。
它在全球股票市场上变得流行,然后扩展到外汇、固定收益和衍生品市场,进一步扩展到后交易以支持直通处理。 交易所提供对 FIX 消息的访问作为实时数据提要,由算法交易员解析以跟踪市场活动,并且例如识别市场参与者的踪迹并预测其下一步行动。
消息序列允许重建订单簿。 跨多个交易所的交易规模产生了大量(~10 TB)难以处理的非结构化数据,因此可以成为竞争优势的来源。
FIX 协议目前版本为 5.0,是一个具有庞大相关行业专业人士社区的免费开放标准。 它像更近期的 XML 一样是自描述的,FIX 会话由底层的传输控制协议(TCP)层支持。 社区不断添加新功能。
该协议支持管道分隔的键值对,以及基于标签的 FIXML 语法。 请求服务器登录的示例消息如下所示:
8=FIX.5.0|9=127|35=A|59=theBroker.123456|56=CSERVER|34=1|32=20180117- 08:03:04|57=TRADE|50=any_string|98=2|108=34|141=Y|553=12345|554=passw0rd!|10=131|
有一些用于制定和解析 FIX 消息的 Python 开源 FIX 实现可以使用。 交互经纪商提供了用于自动交易的基于 FIX 的计算机对计算机接口(CTCI)(请参见 GitHub 存储库中本章的资源部分)。
纳斯达克 TotalView-ITCH 订单簿数据
虽然 FIX 具有主导的大市场份额,但交易所也提供本地协议。 纳斯达克提供了一种 TotalView ITCH 直接数据提要协议,允许订阅者跟踪股票工具的单个订单,从下单到执行或取消。
因此,它允许重建订单簿,跟踪特定证券或金融工具的活跃限价买入和卖出订单列表。订单簿通过列出每个价格点上投标或报价的股份数量来显示全天市场深度。它还可能识别特定买入和卖出订单的市场参与者,除非它是匿名下达的。市场深度是流动性的关键指标,以及大额市场订单的潜在价格影响。
除了匹配市价和限价订单,纳斯达克还进行市场开盘和闭市时执行大量交易的拍卖或交叉交易。随着被动投资继续增长,交叉交易变得越来越重要,交易员寻找执行更大块的股票的机会。TotalView 还发布了纳斯达克开市和闭市以及纳斯达克 IPO/停牌交叉交易的净订单失衡指示器(NOII)。
解析二进制 ITCH 消息
ITCH v5.0 规范声明了与系统事件、股票特征、限价订单的下达和修改以及交易执行相关的 20 多种消息类型。它还包含有关开市和闭市前净订单失衡的信息。
纳斯达克提供了数月的每日二进制文件样本。本章的 GitHub 存储库包含一个名为 build_order_book.ipynb
的笔记本,演示了如何解析 ITCH 消息的示例文件,并重建任何给定 tick 的执行交易和订单簿。
以下表格显示了样本文件日期为 2018 年 3 月 29 日时最常见消息类型的频率:
消息类型 | 订单簿影响 | 消息数量 |
A |
新的未归属限价订单 | 136,522,761 |
D |
订单取消 | 133,811,007 |
U |
订单取消并替换 | 21,941,015 |
E |
完全或部分执行;可能有多条针对同一原始订单的消息 | 6,687,379 |
X |
部分取消后修改 | 5,088,959 |
F |
添加归属订单 | 2,718,602 |
P |
交易消息(非交叉) | 1,120,861 |
C |
在不同于初始显示价格的价格上全部或部分执行 | 157,442 |
Q |
交叉交易消息 | 17,233 |
对于每条消息,规范列出了组件及其相应的长度和数据类型:
名称 | 偏移量 | 长度 | 值 | 注释 |
消息类型 | 0 | 1 | F | 添加订单 MPID 归属消息 |
股票定位 | 1 | 2 | 整数 | 标识证券的定位代码 |
跟踪编号 | 3 | 2 | 整数 | 纳斯达克内部跟踪编号 |
时间戳 | 5 | 6 | 整数 | 自午夜以来的纳秒数 |
订单参考编号 | 11 | 8 | 整数 | 新订单的唯一参考编号 |
买卖指示符 | 19 | 1 | 字母 | 订单类型:B = 买入订单,S = 卖出订单 |
股票 | 20 | 4 | 整数 | 添加到订单簿的订单股票数量 |
股票 | 24 | 8 | Alpha | 股票符号,右侧填充空格 |
价格 | 32 | 4 | 价格(4) | 新订单的显示价格 |
归属 | 36 | 4 | Alpha | 与订单相关联的纳斯达克市场参与者标识符 |
Python 提供了 struct
模块,通过格式字符串来解析二进制数据,该格式字符串通过指定字节字符串的各个组件的长度和类型来标识消息元素,按照规范中的排列方式。
让我们逐步解析交易消息并重建订单簿的关键步骤:
- ITCH 解析器依赖于作为
.csv
文件提供的消息规范(由create_message_spec.py
创建),并根据formats
字典组装格式字符串:
formats = { ('integer', 2): 'H', # int of length 2 => format string 'H' ('integer', 4): 'I', ('integer', 6): '6s', # int of length 6 => parse as string, convert later ('integer', 8): 'Q', ('alpha', 1) : 's', ('alpha', 2) : '2s', ('alpha', 4) : '4s', ('alpha', 8) : '8s', ('price_4', 4): 'I', ('price_8', 8): 'Q', }
- 解析器将消息规范转换为格式字符串和捕获消息内容的
namedtuples
:
# Get ITCH specs and create formatting (type, length) tuples specs = pd.read_csv('message_types.csv') specs['formats'] = specs[['value', 'length']].apply(tuple, axis=1).map(formats) # Formatting for alpha fields alpha_fields = specs[specs.value == 'alpha'].set_index('name') alpha_msgs = alpha_fields.groupby('message_type') alpha_formats = {k: v.to_dict() for k, v in alpha_msgs.formats} alpha_length = {k: v.add(5).to_dict() for k, v in alpha_msgs.length} # Generate message classes as named tuples and format strings message_fields, fstring = {}, {} for t, message in specs.groupby('message_type'): message_fields[t] = namedtuple(typename=t, field_names=message.name.tolist()) fstring[t] = '>' + ''.join(message.formats.tolist())
alpha
类型的字段需要按照format_alpha
函数中定义的进行后处理:
def format_alpha(mtype, data): for col in alpha_formats.get(mtype).keys(): if mtype != 'R' and col == 'stock': # stock name only in summary message 'R' data = data.drop(col, axis=1) continue data.loc[:, col] = data.loc[:, col].str.decode("utf- 8").str.strip() if encoding.get(col): data.loc[:, col] = data.loc[:, col].map(encoding.get(col)) # int encoding return data
- 单日的二进制文件包含超过 3 亿条消息,总计超过 9 GB。该脚本会将解析的结果迭代地附加到以快速的
HDF5
格式存储的文件中,以避免内存限制(有关此格式的更多信息,请参阅本章的最后一节)。以下(简化的)代码处理二进制文件,并生成按消息类型存储的解析订单:
with (data_path / file_name).open('rb') as data: while True: message_size = int.from_bytes(data.read(2), byteorder='big', signed=False) message_type = data.read(1).decode('ascii') message_type_counter.update([message_type]) record = data.read(message_size - 1) message = message_fields[message_type]._make(unpack(fstring[message_type], record)) messages[message_type].append(message) # deal with system events like market open/close if message_type == 'S': timestamp = int.from_bytes(message.timestamp, byteorder='big') if message.event_code.decode('ascii') == 'C': # close store_messages(messages) break
- 预料之中,这一天交易的 8500 多只股票中的一小部分占了大部分交易:
with pd.HDFStore(hdf_store) as store: stocks = store['R'].loc[:, ['stock_locate', 'stock']] trades = store['P'].append(store['Q'].rename(columns= {'cross_price': 'price'}).merge(stocks) trades['value'] = trades.shares.mul(trades.price) trades['value_share'] = trades.value.div(trades.value.sum()) trade_summary = trades.groupby('stock').value_share.sum().sort_values (ascending=False) trade_summary.iloc[:50].plot.bar(figsize=(14, 6), color='darkblue', title='% of Traded Value') plt.gca().yaxis.set_major_formatter(FuncFormatter(lambda y, _: '{:.0%}'.format(y)))
我们得到了以下图形的绘制:
Python 机器学习算法交易实用指南(一)(3)https://developer.aliyun.com/article/1523718