算法交易策略由指示何时购买或出售资产以产生相对于基准(例如指数)的较高回报的信号驱动。 资产回报率中未通过暴露于该基准而无法解释的部分称为alpha,因此旨在产生这种不相关收益的信号也称为alpha因子。
本章主要介绍alpha因子
一、从数据到信号
Alpha因子是原始数据(raw data)的转换,旨在预测资产价格的变动。它们旨在捕获驱动资产回报的风险。每当策略评估因子以获得信号时,因子可以组合一个或多个输入,但为每种资产输出只有单个值。交易决策可能依赖于跨资产的相对因子值或单个资产的形式。
在第一章中我们了解到,alpha因子的工作流程分为两个阶段:研究流程和执行流程。本章重点讲研究阶段。 下一章将介绍执行阶段。 其余部分将重点介绍如何利用机器学习从数据中学习新因子并有效地汇总来自多个alpha因子的信号。
alpha因子是预测市场数据,基本数据和另类数据的转变的信号。 一些因子描述了整个经济领域的基本变量,例如增长,通货膨胀,波动性,生产率和人口风险。其他因子代表投资风格,例如价值或增长,以及可以交易并因此由市场定价的动量投资。 还有一些因子可以根据经济学或金融市场的制度设置或投资者的行为来解释价格走势,包括这种已知的行为偏差。
因子背后的经济学理论可能是理性的(rational),因此,因子在长期具有高回报,以弥补在困难时期的低回报。 这也可能是行为的(behavioral),因子风险溢价是由未套利的代理人的行为可能存在偏见或不完全理性所致。
人们一直在寻找和发现新的因子,以更好地捕捉已知的因子或反映新的回报驱动因子。 管理着近2000亿美元的Research Affiliates公司的联合创始人Jason Hsu确定了截止到2015年已用经验证据在知名期刊上发表的约250个因子。他估计这一数字每年可能会增加40。
为了避免错误的发现并确保一个因子产生一致的结果,它应该基于各种已建立的因子类别(例如动量,价值,波动性或质量及其原理)具有有意义的经济直觉,我们将在下一部分中概述。 这使得该因素反映出市场将要补偿的风险更为合理。
alpha因子是通过使用简单的算术,例如变量随时间的绝对或相对变化,数据序列之间的比率或在时间窗内的汇总(如简单或指数移动平均值)对原始市场数据,基本数据或替代数据进行转换而产生的。 它们还包括从价格和数量模式的技术分析中得出的指标,例如需求与供应的相对强度指数(RSI)以及从证券基础分析中熟悉的众多指标。 Kakushadze于2016列出了101个alpha因子的公式,在撰写本文时,其中80%已用于WorldQuant对冲基金的生产中。
从历史上看,交易策略将简单的排名试探法,价值阈值或分位数法应用于对整个投资领域中的多种证券计算的一个或几个alpha因子。例子包括价值投资方法,该方法在沃伦·巴菲特最喜欢的一本书《证券分析》(Security Analysis)中流行,该书由Graham和Dodd(1934)撰写,它依赖于诸如市销率之类的指标。
Eugene Fama(曾获得2013年诺贝尔经济学奖)和Kenneth French领导了有关预测高于市场收益的alpha因子的现代研究,他们提供了有关规模和价值因子的证据(1993年)。 这项工作得出了FF三因子和FF五因子模型。洪崇理(Andrew Ang)是贝莱德(BlackRock)公司的因子策略头目,其管理近7亿美金,他于2014年撰写了一篇关于现代因子投资的精彩绝伦的综述。
我们将在之后的文章中看到,在没有确定的公式的情况下,机器学习在学习直接从更多样化,更大得多的输入数据集中直接提取信号方面是非常有效的。 但是,正如我们还将看到的那样,Alpha因子对于机器学习模型仍然是有用的输入,它比手动设置规则以更优化的方式组合了它们的信息内容。
结果,当今的算法交易策略会利用大量信号,其中许多信号可能单独使用功效较弱,但通过机器学习算法与其他模型驱动或传统因子结合使用时,其可以产生可靠的预测。
二、著名因子合辑
本文只挑选部分因子,目的是用来给大家做介绍,之后会专门出一片文章,其包含海量因子以及有对应的因子解释
1. 动量与情绪因子
1993年,Jegadeesh和Titman通过定量证据展示了动量因子在美国股票市场的有效性,从此,动量投资一直是最完善的因子策略之一。“趋势是您的朋友,或让您的赢家奔跑”(the trend is your friend or let your winners run)。 动量因子旨在使表现良好的资产多头,而在一定时期内使表现不佳的资产空头。 拥有2000亿美元对冲基金AQR的创始人克利福德·阿内斯(Clifford Asness)最近提供了证据,证明了八种不同资产类别和市场的动量效应。
使用此因子的策略的前提是资产价格呈现趋势,并以正的序列相关性反映出来。这种价格动量反驳了有效市场的假设,即市场仅凭过去的价格回报无法预测未来的表现。尽管有理论相反的观点,价格动量策略已在资产类别中产生了正收益,并且是许多交易策略的重要组成部分。
下图显示了根据对各种alpha因子的影响而形成的投资组合的历史表现(使用Fama-French网站的数据)。 因子 winner-minus-loser(WML)代表在前2到12个月的收益率中,包含美国股市前三名和后三名的股票投资组合之间的业绩差异:
直到2008年危机,动量因子都大大超过了其他突出的风险因子。 其他因子包括High-Minus-Low(HML)价值因子,Robust-Minus-Weak(RMW)盈利能力因子和Conservative-Minus-Aggressive(CMA)投资因子。 股权溢价是市场回报率(例如,标准普尔500指数)与无风险利率之差。
为什么动量和情绪会推动超额收益?
动量效应的原因有以下几个:投资者的行为、持续的供需失衡、风险资产与经济之间的正反馈回路或市场微观结构。
行为理论(behavioral rationale)反映了当投资者以不同的速度处理新信息时,反应不足和反应过度的偏见。 在最初对新闻反应不足之后,投资者通常会推断过去的行为并创造价格动能。 90年代末市场泡沫期间的技术股反弹是一个极端的例子。 恐惧和贪婪的心理也促使投资者增加对获胜资产的敞口,并继续出售亏损资产。
动量也可以具有基本面驱动因素(fundamental drivers),例如风险资产与经济之间的正反馈回路。 经济增长提振了股票,由此产生的财富效应通过增加支出将其反馈到经济中,再次推动了增长。价格和经济之间的正反馈通常将股票和信贷的势头延伸到更长的期限,而债券,FOEX和商品则要长得多,而负反馈会导致逆转,因此需要更短的投资期限。动力的另一个原因可能是由于市场摩擦而导致的持续供需失衡。一个例子是商品生产在适应不断变化的需求方面的延迟。多年来,石油产量可能滞后于经济蓬勃发展带来的更高需求,持续的供应短缺可能触发并支撑价格上涨的势头。
在短期内,当投资者实施模仿其偏见的策略时,市场微观结构效应也可产生价格动能。 例如,减少损失并获利的交易智慧使投资者使用诸如止损,恒定比例投资组合保险(CPPI),动态三角套期保值之类的交易策略,或基于保护性看跌期权的基于期权的策略。 这些策略之所以能产生动力,是因为它们暗示了资产表现不佳时卖出和资产表现极好时买入的事先承诺。
同样,风险平价策略倾向于购买经常表现为正的低波动率资产,并出售通常表现为负的高波动率资产。 使用这些策略的投资组合自动重新平衡,往往会增强价格动能。
如何衡量动量和情绪
动量因子通常是通过识别趋势和模式从价格时间序列的变化得出的。通过比较资产的横截面或分析资产的时间序列(在传统资产类别之内或之间以及在不同时间范围内),可以基于绝对或相对回报来构建它们。
以下是一些例子(以下全用英文显示因子名称)
其他情绪指标包括以下指标: 可以从诸如Quandl或Bloomberg等数据提供者那里获得诸如分析师估计之类的输入:
也有许多数据提供商旨在提供从社交媒体(如Twitter)构建情绪指标。我们在之后讲自然语言处理中时会构建自己的指标。
2. 价值因子
价格相对于基本价值而言较低的股票往往会提供超过资本加权基准的回报。价值因子反映了这种相关性,旨在为相对便宜的被低估资产发送购买信号,为被高估的资产出售信号。因此,任何价值策略的核心都是一个模型,用于估计资产的公允或基本价值。公允价值可以定义为绝对价格水平,相对于其他资产的价差或资产应交易的范围。
相对价值策略
价值策略依赖于资产的公允价值的均值回归。 他们认为,价格只是由于过度反应或羊群效应等行为影响或暂时性市场影响或长期供需摩擦等流动性影响而暂时偏离公允价值。 价值因子通常表现出与动量因子相反的性质,因为它们依赖均值回归。 对于股票而言,与价值股相反的是增长股票,由于增长预期,它们的估值很高。
价值因子支持广泛的系统策略,包括基本面和市场估值以及交叉资产相对价值。 它们通常被统称为统计套利(StatArb)策略,以与市场无关的多头/空头投资组合实施,而不会面临其他传统或替代风险因素。
基本面价值策略
基本面价值策略从取决于目标资产类别的经济和基本指标中得出公允资产价值。 在固定收益类产品,货币和商品中,指标包括资本账户余额,经济活动,通货膨胀或资金流量的水平和变化。 对于股票和公司债,价值因素可以追溯到Graham和Dodd先前提到的Security Analysis。 股权价值方法将股票价格与基本指标(例如账面价值,顶线销售,底线收益或各种现金流量指标)进行比较。
市值策略
市值策略使用统计或机器学习模型来识别由于流动性供应效率低下而导致的定价错误。统计和指数套利是突出的例子,可以捕捉到短期内市场对临时市场影响的逆转。在更长的时间范围内,市场价值交易还利用股票和商品的季节性影响。
交叉资产相对价值策略
跨资产相对价值策略侧重于跨资产类别的定价错误。例如,可转换债券套利涉及可转换为债券的债券与单个公司的基础股票之间的相对价值的交易。相对价值策略还包括信贷和股票波动之间的交易,使用信贷信号交易股票或商品与相关股票之间的交易。
价值因子为何有助于预测收益
价值效应的存在有理性上和行为上的解释,价值效应定义为价值股票投资组合相对于成长股票投资组合的超额收益,其中前者的市场价值低而后者的市场价值高。相对于基本面,我们将从大量研究中列举一些突出的例子。
从理性、有效的市场角度来看,价值溢价弥补了较高的实际或感知风险。 研究人员提供的证据表明,与精益和较灵活的成长型公司相比,价值公司对不利的经济环境的适应能力较弱,或者价值股票风险与较高的财务杠杆和更不确定的未来收益有关。 与价值型和大型股票投资组合相比,成长型和小型股票投资组合对宏观冲击的敏感性也更高。
从行为的角度来看,价值溢价可以用损失规避和心理会计偏见来解释。由于先前收益提供的缓冲,投资者可能不太担心近期表现强劲的资产损失。 这种损失规避的偏见使投资者认为股票的风险比以前低,并以较低的利率折现未来现金流量。相反,近期表现不佳可能会导致投资者提高资产的折现率。
这些不同的回报期望可以产生价值溢价:相对于基本面而言,具有高价格倍数的成长型股票在过去表现良好,但由于投资者对低风险的偏见,投资者未来的平均回报将较低。 适用于价值股。
量化价值因子
从基本面数据中可以计算出大量估值的因子。 这些因子可以组合为机器学习评估模型的输入,以预测资产价格。 以下示例适用于股票,我们将在之后的文章中了解如何使用其中一些因子:
3. 波动性和规模因子
规模效应是较早的风险因子之一,并且与低市值的股票过剩表现有关。 最近,低波动率因子已显示出捕获低于平均波动率,β或特质风险的股票的超额收益的能力,同时市值较大的股票往往具有较低的波动性,因此传统的规模因子通常与较新的波动性因子相结合。
低波动率异常是一个实证中的难题,它与金融的基本原理不符。 资本资产定价模型(CAPM)和其他资产定价模型断言,较高的风险应获得较高的回报,但是在众多市场和较长时期内,情况恰恰相反。 风险较小的资产优于风险较高的同类资产。
下图绘制了1990-2019年标准普尔500指数收益率相对于VIX指数的滚动平均值(VIX指数衡量了标准普尔100指数平价期权的隐含波动率)。它说明了股票收益率和这种波动率的度量如何反向变化,在此期间负相关系数为-0.54。 除了这种综合效应外,还有证据表明,对VIX变动更敏感的股票表现更差。
为何波动性和规模因子有助于预测收益
低波动率异常与有效市场的假设和CAPM假设相矛盾。目前已经提出了几种行为解释来解释其存在。
彩票效应,即个人进行类似于彩票的投注,但预期损失较小,但潜在获胜机会很大,即使该获胜机会可能性很小。 如果投资者认为低价,波动性股票的风险收益状况就像一张彩票,那么这可能是一个有吸引力的选择。 结果,由于偏好偏颇,投资者可能会为高波动性股票支付过多的费用,而为低波动性股票支付不足的费用。
代表性偏见,投资者将一些广为人知的波动性股票的成功推断为所有波动性股票,而忽略了此类股票的投机性质。
投资者对未来的预测能力可能也过于自信,对于波动性较大,结果不确定性更大的股票,他们的观点差异更大。 由于做多(即拥有资产)表达积极观点要比做空(消极观点)消极观点要容易,因此乐观主义者的数量可能超过悲观主义者,并继续推高波动性股票的价格,从而导致回报降低。
此外,在牛市和熊市期间,投资者的行为也有所不同。 在牛市期间,beta系数的分散性要低得多,因此,低波动性股票的表现不会太差,即使有的话也不行,而在危机期间,投资者寻求或保持低波动性股票,贝塔的分散性会增加。 因此,长期来看,波动性较低的资产和投资组合的表现更好。
如何衡量波动率和规模
用于识别低波动性股票的指标涵盖范围很广,一边实现了波动率(标准差),另一边则进行了预测(隐含)波动率和相关性。 有些将低波动性作为低beta值进行操作。 支持波动率异常的证据对于不同指标似乎很可靠。
4. 质量因子
质量因子旨在获取高利润,高效运营,安全,稳定且管理良好(简而言之,高质量)的公司的超额收益。 市场似乎还会奖励相对确定的收益,并对收益波动较大的股票进行惩罚。
长期以来,依赖基本面分析的选股者一直提倡向高质量业务倾斜的投资组合,但这在量化投资中是相对较新的现象。 面临的主要挑战是,鉴于质量的主观性,如何使用定量指标客观地定义质量因子。
基于独立质量因子的策略往往以反周期的方式执行,因为投资者支付一些溢价以最大程度地降低下行风险并提高估值。 因此,在多因子策略中,质量因子通常会与其他风险因子结合在一起。
多空质量因子往往具有负的beta,因为多头是具有低波动性的优质股票,而空头则是更具波动性的低质股票。因此,质量因子通常与低波动性和动量因子正相关,而与价值和广阔的市场敞口等因子负相关。
为什么质量因子很重要
质量因素可能预示着表现极佳,因为,诸如持续盈利、现金流量稳定增长、谨慎杠杆、资本市场融资需求低或金融风险低等优越的基础支撑了对股票的需求,并长期支撑着这类公司的价格。 从公司融资的角度来看,优质公司通常会谨慎管理其资本,并降低过度利用或资本过多的风险。
行为上的解释表明,投资者对质量信息的反应不充分,类似于动量因子的原理,即投资者追逐赢家和输家。
关于优质溢价的另一个论点是羊群效应,类似于成长型股票。 基金经理可能会发现,即使股价变高,购买一家具有强大基本面的公司,也比波动性更大(风险)的股票更容易有说服力。
如何衡量质量
质量因子依赖于从资产负债表和损益表计算得出的指标,这些指标从更高的利润率或现金流量利润率、运营效率、财务实力和竞争力中更广泛地反映出盈利能力,因为它暗示了随着时间的推移维持盈利能力的能力。
因此,质量是使用毛利润率、投资资本回报率、低收益波动率或多者结合来衡量的各种盈利能力,收益质量和杠杆指标,并在下表中列出了一些选项。
盈余管理主要通过操纵应计项目进行。因此,应计金额的大小通常被用作收入质量的代表:相对于资产而言,更高的总应计金额使低收入质量的可能性更大。但是,这并不是明确的,因为应计项目可以反映收益操纵以及对未来业务增长的会计估计:
我们已经对alpha因子进行了高级分类,这些分类已显示出不同程度的异常收益。现在,我们将开始根据市场,基本面数据和替代数据开发自己的财务特征。
三、如何搭建因子
基于对关键因子的类别、原理和流行指标的计算方式,一项关键任务是确定可以更好地捕捉先前设定的收益驱动因素所体现的风险的新因素,或者寻找新的因素。 无论哪种情况,将创新因子的性能与已知因子的性能进行比较以识别增量信号增益都是很重要的。
有助于将数据转换为因子的关键工具包括用于数值计算的Python库,NumPy和pandas,以及用于技术分析的专用库TA-Lib的Python包装器。 替代方法包括Zura Kakushadze在2016年的论文中开发的表达式alphas 101公式化Alphas,并由alphatools库实现。 此外,Quantopian平台提供了大量内置因子,可加快研究过程。
要将一个或多个因子应用于投资领域,我们可以使用Zipline回测库(其中也包含一些内置因素),并使用Alphalens库来评估其绩效。
1. 用pandas和numpy构建因子
NumPy和pandas是自定义因子计算的关键工具。 本节演示如何使用它们快速计算产生各种alpha因子的转换。
Travis Oliphant于2005年通过整合自1990年代中期以来开发的较老的Numeric和Numarray库创建了用于科学计算的NumPy库。 它以称为ndarray的高性能n维数组数据结构进行组织,可实现与MATLAB相当的功能。
Wes McKinney在AQR Capital Management工作时创造了pandas。 它提供了基于NumPy的ndarray的DataFrame数据结构,但允许通过基于标签的索引进行更加用户友好的数据操作。它包括各种特别适合金融数据的计算工具,包括具有自动日期对齐功能的丰富时间序列操作,我们将在这里进行探讨。
以下各节说明了将原始股票价格数据转换为选定因子的一些步骤。
Loading, slicing, reshaping
在之前加载了美国股票的Quandl Wiki股票价格数据后,我们通过将pd.IndexSlice应用于pd.MultiIndex来选择2000-2018个时间片段,这里面包含时间戳和股票代码信息。 然后,我们使用.stack()方法选择并取消调整后的收盘价列,以将DataFrame转换为宽格式,在各列中加上代码,在各行中添加时间戳:
idx = pd.IndexSlice
with pd.HDFStore('../../data/assets.h5') as store:prices = (store['quandl/wiki/prices'].loc[idx['2000':'2018', :], 'adj_close'].unstack('ticker'))
prices.info()
'''
DatetimeIndex: 4706 entries, 2000-01-03 to 2018-03-27
Columns: 3199 entries, A to ZUMZ
'''
Resampling
为了减少训练时间并尝试使用更长的时间范围的策略,我们使用可用的调整后收盘价将每日业务数据转换为月末频率:
monthly_prices = prices.resample('M').last()
如何计算多历史周期的收益率
为了捕获动量模式之类的时间序列动态,我们使用pct_change(n_periods)方法计算历史多周期收益,其中n_periods表示滞后的次数。然后,我们使用.stack()将宽结果转换回长格式。随后,我们使用.pipe()将.clip()方法应用于获得的DataFrame,并用winsorize缩尾,返回[1%,99%]排位的数据; 也就是说,我们将异常值限制在这些百分比上。
最后,我们使用几何平均值对收益进行归一化。使用.swaplevel()更改MultiIndex级别的顺序后,我们获得了六个不同时期(从1到12个月不等)的复合月收益:
outlier_cutoff = 0.01
data = pd.DataFrame()
lags = [1, 2, 3, 6, 9, 12]
for lag in lags:data[f'return_{lag}m'] = (monthly_prices.pct_change(lag).stack().pipe(lambda x:x.clip(lower=x.quantile(outlier_cutoff),upper=x.quantile(1-outlier_cutoff))).add(1).pow(1/lag).sub(1))
data = data.swaplevel().dropna()
data.info()
'''
MultiIndex: 521806 entries, (A, 2001-01-31 00:00:00) to (ZUMZ, 2018-03-
31 00:00:00)
Data columns (total 6 columns):
return_1m 521806 non-null float64
return_2m 521806 non-null float64
return_3m 521806 non-null float64
return_6m 521806 non-null float64
return_9m 521806 non-null float64
return_12m 521806 non-null float6
'''
计算因子的beta
我们将在之后介绍利用Fama-French数据,以估计资产在常见风险因子中的敞口。 Fama-French的五个因子,即系统风险,市场规模,市值,盈利能力和投资,已在实证中证明了可解释资产收益率。 它们通常用于评估投资组合对知名风险和回报驱动因素的敞口,其中无法解释的部分则归因于管理者的特质。 因此,自然而然地将过去的因素敞口作为财务特征纳入旨在预测未来收益的模型中。
我们可以使用pandas-datareader访问历史因子收益,并使用pyfinance库中的PandasRollingOLS滚动线性回归功能估算历史风险,如下所示:
factors = ['Mkt-RF', 'SMB', 'HML', 'RMW', 'CMA']
factor_data = web.DataReader('F-F_Research_Data_5_Factors_2x3','famafrench', start='2000')[0].drop('RF', axis=1)
factor_data.index = factor_data.index.to_timestamp()
factor_data = factor_data.resample('M').last().div(100)
factor_data.index.name = 'date'
factor_data = factor_data.join(data['return_1m']).sort_index()
T = 24
betas = (factor_data.groupby(level='ticker', group_keys=False).apply(lambda x: PandasRollingOLS(window=min(T, x.shape[0]-1), y=x.
return_1m, x=x.drop('return_1m', axis=1)).beta))
之后我们会更详细的进行进一步的因子分析工作。
添加动量因子
我们可以使用1个月和3个月的结果来计算简单的动量因子。下面的代码示例演示如何计算较长时期的收益与最近的每月收益之间的差异,以及如何计算3个月和12个月收益之间的差异:
for lag in [2,3,6,9,12]:data[f'momentum_{lag}'] = data[f'return_{lag}m'].sub(data.return_1m)
data[f'momentum_3_12'] = data[f'return_12m'].sub(data.return_3m)
增加时间列来捕捉季节效应
基本因子还包括季节性,例如一月效应,据观察,该异常会导致本月股票上涨(这可能是出于税收原因)。我们可以通过代表特定时间段(例如年份和/或月份)的指标变量来模拟这些季节性影响。 可以这样生成:
dates = data.index.get_level_values('date')
data['year'] = dates.year
data['month'] = dates.month
创造滞后收益特征
如果要使用滞后收益,即使用以前期间的收益作为输入变量或特征来训练一个学习收益模型以预测未来收益的模型,则可以使用.shift()方法将历史收益向上移动到当前收益期。以下示例将1到6个月前的收益率上移相应的滞后,以便将其与当月的观察值关联:
for t in range(1, 7):data[f'return_1m_t-{t}'] = data.groupby(level='ticker').return_1m.shift(t)
创造超前收益特征
同样,您可以使用带有负周期的.shift()来创建当前期间的远期收益,即将来将要发生的收益(假设您的数据按升序排序):
for t in [1,2,3,6,12]:data[f'target_{t}m'] = (data.groupby(level='ticker')[f'return_{t}m'].shift(-t))
2. 如何使用TA-Lib创建alpha因子
TA-Lib是用C ++编写的带有Python接口的开放源代码库,它被交易软件开发人员广泛使用。它包含用于技术分析的200多个流行因子的标准化实现;这些指标仅使用市场数据,即市场价格和市场数量信息。
TA-Lib与pandas和NumPy兼容,因此使用非常简单。 以下示例演示了如何计算两个流行因子。
布林带(Bollinger Bands)由一个简单的移动平均线(SMA)组成,它周围环绕着两个在SMA上下的滚动标准偏差的带。当价格分别跌落到上下两端的两个波段之外时,它存在潜在超买/超卖情况。 实际上,发明人John Bollinger推荐了一种由22条规则生成交易信号的交易系统。
我们可以用如下所示的代码计算布林带,并且为了进行比较,可以计算本节前面介绍的有关流行alpha因子的相对强度指数(RSI)。
我们加载单个股票的调整后的收盘价(下面的例子为AAPL):
with pd.HDFStore(DATA_STORE) as store:data = (store['quandl/wiki/prices'].loc[idx['2007':'2010', 'AAPL'],['adj_open', 'adj_high', 'adj_low', 'adj_close','adj_volume']].unstack('ticker').swaplevel(axis=1).loc[:, 'AAPL'].rename(columns=lambda x: x.replace('adj_', '')))
然后,我们通过相关的TA-Lib函数传递一维pd.Series:
from talib import RSI, BBANDS
up, mid, low = BBANDS(data.close, timeperiod=21, nbdevup=2, nbdevdn=2, matype=0)
rsi = RSI(adj_close, timeperiod=14)
然后,我们将结果收集到一个DataFrame中,并用AAPL股票价格和30/70线的RSI绘制布林带,这表明了多空的机会:
data = pd.DataFrame({'AAPL': data.close, 'BB Up': up, 'BB Mid': mid, 'BB down': low, 'RSI': rsi})
fig, axes= plt.subplots(nrows=2, figsize=(15, 8))
data.drop('RSI', axis=1).plot(ax=axes[0], lw=1, title='Bollinger Bands')
data['RSI'].plot(ax=axes[1], lw=1, title='Relative Strength Index')
axes[1].axhline(70, lw=1, ls='--', c='k')
axes[1].axhline(30, lw=1, ls='--', c='k')
如下图所示,结果参差不齐,这两个指标都表明在危机后复苏初期,当价格继续上涨时,出现了超买状态:
3. 用卡尔曼滤波给alpha因子降噪
数据中的噪声概念涉及信号处理领域,其目的是从例如通过电磁波形式通过空气发送的信号中检索正确的信息。 当波在太空中移动时,环境干扰会以噪声的形式添加到原始的纯信号中,因此信号都是有噪音的,需要分开。
卡尔曼滤波器于1960年问世,在许多需要处理噪声数据的应用中非常流行,因为它可以对基础信号进行更准确的估算。
除在时间序列分析中使用该技术外,该技术还广泛用于跟踪计算机视觉中的对象,支持飞机和宇宙飞船的定位和导航以及基于嘈杂的传感器数据控制机器人运动。
噪声在数据科学,金融和其他领域中的用法类似,原始数据必须包含有用的信息,例如,就交易信号而言,它需要从许多无关的信息中提取并分离出来。 显然,因为我们不知道真实信号是否一定存在,这种分离是颇具挑战性的。
我们将首先回顾一下卡尔曼滤波器的工作原理以及为实现其目标所做的假设。 然后,我们将演示如何使用pykalman库将其应用于金融数据。
卡尔曼滤波的工作原理
卡尔曼滤波器是诸如时间序列之类的顺序数据的动态线性模型,它可适应新信息的到达。相比于使用固定大小的窗口(如移动平均值)或给定的权重集(如指数移动平均值),卡尔曼滤波将新数据结合到其基于概率模型的时间序列当前值的估计中。
具体而言,卡尔曼滤波器是观测序列
从技术上讲,卡尔曼滤波器采用贝叶斯方法,根据状态变量x随时间的变化推导状态变量x的后验分布。我们还可以将其视为在连续状态空间中跟踪单个对象的无监督算法(在该状态空间中,我们将对象视为证券的价值或收益或alpha因子)。
为了从可能实时获得的一系列观测中恢复隐藏状态,该算法在两个步骤之间进行迭代:
- 预测步骤:估计过程的当前状态。
- 测量步骤:使用嘈杂的观测值,通过对两个步骤中的信息求平均,从而权衡更多确定的估计值,从而更新其估计值。
该算法的基本思想如下:关于动态系统的某些假设以及相应测量的历史,将使我们能够以使先前测量的概率最大化的方式来估计系统的状态。
为了恢复隐藏状态,卡尔曼滤波器进行以下假设:
- 我们正在建模的系统以线性方式运行。
- 隐藏状态过程是马尔可夫链,因此当前隐藏状态 仅取决于最近的先前隐藏状态。
- 测量值会受到具有恒定协方差的高斯无关噪声的影响。
结果,卡尔曼滤波器类似于隐马尔可夫模型,不同之处在于潜变量的状态空间是连续的,并且隐变量和观测变量均具有正态分布,表示为
用数学术语来说,模型的关键组成部分是:
- 初始隐藏状态具有正态分布:
- 隐藏状态 是的仿射变换,
- 观测值 是对隐藏状态的仿射变换,
卡尔曼滤波器的优点之一是,它可以随着分布特性的变化灵活地适应非平稳数据。
主要缺点是金融数据经常违反线性和高斯噪声的假设。 为了解决这些缺点,卡尔曼滤波器已扩展为具有非线性动力学的系统。 粒子滤波器是使用基于采样的蒙特卡洛方法来估计非正态分布的替代方法。
用pykalman库实现卡尔曼滤波
卡尔曼滤波器对于滚动估计随时间变化的数据值或模型参数特别有用。这是因为它会根据新的观察结果在每个时间步调整其估计值,并且倾向于权衡最近的观察结果。
除了传统的移动平均值,卡尔曼滤波器不需要我们指定用于估计的窗口的长度。 相反,我们从对隐藏状态的均值和协方差的估计开始,然后让卡尔曼滤波器根据定期观察来校正我们的估计。
以下代码示例显示了如何应用卡尔曼过滤器来平滑2008-09年期间的S&P500股票价格序列:
with pd.HDFStore(DATA_STORE) as store:sp500 = store['sp500/stooq'].loc['2008': '2009', 'close']
我们使用单位协方差矩阵和零均值来初始卡尔曼滤波(请参阅pykalman文档以获取有关选择合适初始值的建议):
from pykalman import KalmanFilter
kf = KalmanFilter(transition_matrices = [1],observation_matrices = [1],initial_state_mean = 0,initial_state_covariance = 1,observation_covariance=1,transition_covariance=.01)
然后,我们运行filter方法来触发正向算法,该算法迭代地估计隐藏状态,即时间序列的平均值:
state_means, _ = kf.filter(sp500)
最后,我们添加移动平均值方法进行比较并绘制结果:
sp500_smoothed = sp500.to_frame('close')
sp500_smoothed['Kalman Filter'] = state_means
for months in [1, 2, 3]:sp500_smoothed[f'MA ({months}m)'] = (sp500.rolling(window=months * 21).mean())
ax = sp500_smoothed.plot(title='Kalman Filter vs Moving Average', figsize=(14, 6), lw=1, rot=0)
下面的结果图表明,卡尔曼滤波器的性能类似于1个月的移动平均值,但对时间序列行为的变化更敏感:
4. 如何使用小波预处理噪声信号
小波与傅立叶分析有关,傅立叶分析将不同频率的正弦和余弦波组合在一起,以近似噪声信号。 虽然傅里叶分析对于将信号从时域转换到频域特别有用,但小波对于过滤出可能在不同范围出现的特定模式很有用,而这些特定模式又可能对应于一个频率范围。
小波是将离散或连续时间信号分解为不同比例分量的函数或类似波形的模式。小波变换又表示使用小波作为有限长度波形的缩放副本和转换副本的函数。对于具有不连续和尖峰的函数,并且近似于非周期性或非平稳信号,此变换相对于傅立叶变换具有优势。
要对信号进行降噪,可以使用小波收缩和阈值化方法。 首先,您选择特定的小波模式来分解数据集。 小波变换产生与数据集中的细节相对应的系数。
阈值化的想法只是简单地忽略所有低于特定截止值的系数,前提是它们代表了代表真实信号所不必要的次要细节。 然后,将这些剩余系数用于小波逆变换,以重建(去噪)数据集。
现在,我们将使用pywavelets库将小波应用于嘈杂的股票数据。 以下代码示例说明了如何使用正反小波变换(具有Daubechies 6小波和不同阈值)对S&P 500返回值进行降噪。
首先,我们在2008-09期间产生标准普尔500指数的每日收益:
signal = (pd.read_hdf(DATA_STORE, 'sp500/stooq').loc['2008': '2009'].close.pct_change().dropna())
然后,我们从众多内置的小波函数中选择一个Daubechies小波:
import pywt
pywt.families(short=False)
'''
['Haar', 'Daubechies', 'Symlets', 'Coiflets', 'Biorthogonal', 'Reverse
biorthogonal', 'Discrete Meyer (FIR Approximation)', 'Gaussian', 'Mexican
hat wavelet', 'Morlet wavelet', 'Complex Gaussian wavelets', 'Shannon
wavelets', 'Frequency B-Spline wavelets', 'Complex Morlet wavelets']
'''
Daubechies 6小波由缩放函数ψ和小波函数φ本身定义(有关详细信息,请参阅PyWavelet文档):
给定一个小波函数,我们首先使用.wavedec函数分解返回信号,这会产生小波变换的系数。接下来,我们滤除高于给定阈值的所有系数,然后使用逆变换.waverec仅使用那些系数来重构信号:
wavelet = "db6"
for i, scale in enumerate([.1, .5]):coefficients = pywt.wavedec(signal, wavelet, mode='per')coefficients[1:] = [pywt.threshold(i, value=scale*signal.max(), mode='soft') for i in coefficients[1:]]reconstructed_signal = pywt.waverec(coefficients, wavelet, mode='per')signal.plot(color="b", alpha=0.5, label='original signal', lw=2, title=f'Threshold Scale: {scale:.1f}', ax=axes[i])pd.Series(reconstructed_signal, index=signal.index).plot(c='k', label='DWT smoothing}', linewidth=1, ax=axes[i])
下面的结果图清楚地表明了较高的阈值如何产生明显更平滑的序列:
四、用Zipline包进行回测
开源库Zipline是一个事件驱动的回测系统。它生成市场事件以模拟算法交易策略的反应并跟踪其表现。一个特别重要的功能是,它为算法提供了历史时间点数据,从而避免了前瞻性偏差(look-ahead bias)。
该库已由Quantopian推广,并在运作中使用该库来促进算法开发和实时交易。
在本节中,我们将简要说明其基本功能。 之后的文章会包含更详细的介绍,以使我们为更复杂的用例做准备。
1. 如何回测单因子策略
您可以将Zipline脱机与数据包结合使用,以研究和评估alpha因子。 在Quantopian平台上使用它时,您将可以访问更广泛的基础数据和替代数据集。 我们还将在本章中演示Quantopian研究环境,并在下一章中演示回测IDE。
市场数据中的一个单因子
我们首先将说明离线环境中的Zipline alpha因子研究工作流程。 特别是,我们将开发和测试一个简单的均值回归因子,该因子可衡量最近的表现偏离历史平均值的程度。
短期逆转是一种常见的策略,它利用了弱预测模式,即股价可能会在不到1分钟到1个月的时间内恢复到滚动均值。
为此,该系数将计算最后一个月回报相对于上一年的滚动月回报的z-score。 在这一点上,我们不会下任何命令来简单地说明CustomFactor的实现并在模拟过程中记录结果。
Zipline包含许多用于许多常见操作的内置因子(有关详细信息,请参见GitHub上链接的Quantopian文档)。 尽管这通常方便且足够,但在其他情况下,我们希望以不同的方式转换可用数据。 为此,Zipline提供了CustomFactor类,该类为我们指定各种计算提供了很大的灵活性。 它通过NumPy使用可用于证券横截面和自定义回溯期的各种功能来执行此操作。
为此,在进行了一些基本设置之后,MeanReversion继承了CustomFactor的子类并定义了compute()方法。 它会在一个默认的为期一年的窗口内创建月度收益的默认输入,以便在给定的一天中,Quandl数据集中的每种证券的monthly_return变量将具有252行和一列。
compute_factors()方法创建一个MeanReversion因子实例,并创建长、短和排名流水线列。 前两个包含可用于下订单的布尔值,而后两个则反映用于评估总体因素表现的总体排名。 此外,它使用内置的AverageDollarVolume因子将计算限制为更多的流动库存:
from zipline.api import attach_pipeline, pipeline_output, record
from zipline.pipeline import Pipeline, CustomFactor
from zipline.pipeline.factors import Returns, AverageDollarVolume
from zipline import run_algorithm
MONTH, YEAR = 21, 252
N_LONGS = N_SHORTS = 25
VOL_SCREEN = 1000
class MeanReversion(CustomFactor):"""Compute ratio of latest monthly return to 12m average,normalized by std dev of monthly returns"""inputs = [Returns(window_length=MONTH)]window_length = YEARdef compute(self, today, assets, out, monthly_returns):df = pd.DataFrame(monthly_returns)out[:] = df.iloc[-1].sub(df.mean()).div(df.std())def compute_factors():"""Create factor pipeline incl. mean reversion,filtered by 30d Dollar Volume; capture factor ranks"""mean_reversion = MeanReversion()dollar_volume = AverageDollarVolume(window_length=30)return Pipeline(columns={'longs' : mean_reversion.bottom(N_LONGS),'shorts' : mean_reversion.top(N_SHORTS),'ranking':mean_reversion.rank(ascending=False)},screen=dollar_volume.top(VOL_SCREEN))
这些代码将使我们能够下达多头和空头订单。
initialize() 方法注册了compute_factors() 管道(pipeline),而before_ trading_start()方法可确保管道每天运行。 record() 函数将管道的排名列以及当前资产价格添加到 run_algorithm()函数返回的性能DataFrame中:
def initialize(context):"""Setup: register pipeline, schedule rebalancing,and set trading params"""attach_pipeline(compute_factors(), 'factor_pipeline')
def before_trading_start(context, data):"""Run factor pipeline"""context.factor_data = pipeline_output('factor_pipeline')record(factor_data=context.factor_data.ranking)assets = context.factor_data.indexrecord(prices=data.current(assets, 'price'))
最后,以UTC术语定义start和end Timestamp对象,设置一个大写基础,并通过引用关键执行方法来执行run_algorithm()。 性能DataFrame包含嵌套数据,例如,price列由每个单元格的pd.Series组成。 因此,以pickle格式存储时,后续数据访问更加容易:
start, end = pd.Timestamp('2015-01-01', tz='UTC'), pd.Timestamp('2018-01-01', tz='UTC')
capital_base = 1e7
performance = run_algorithm(start=start, end=end, initialize=initialize,
before_trading_start=before_trading_start, capital_base=capital_base)
performance.to_pickle('single_factor.pickle')
在下一节中,我们将使用存储在性能DataFrame中的因子和定价数据来评估不同持有期间的因子性能,但是首先,我们将研究如何通过组合来自多个交易品种的多个alpha因子来创建更复杂的信号。
2. 综合各种数据来源的因子
Quantopian研究环境是为快速测试预测性alpha因子而量身定制的。 该过程非常相似,因为它基于Zipline构建,但是提供了对数据源的更丰富的访问。 下面的代码示例说明了如何不仅像以前一样根据市场数据计算alpha因子,而且还根据基本数据和替代数据计算alpha因子。
Quantopian免费提供了数百个Morningstar基本变量,还包括Stocktwits信号作为替代数据源的示例。 还有一些自定义环境,例如QTradableStocksUS,它应用了几个过滤器,将回测环境限制为在现实市场条件下可能可交易的股票:
from quantopian.research import run_pipeline
from quantopian.pipeline import Pipeline
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.data.morningstar import income_statement, operation_ratios, balance_sheet
from quantopian.pipeline.data.psychsignal import stocktwits
from quantopian.pipeline.factors import CustomFactor, SimpleMovingAverage, Returns
from quantopian.pipeline.filters import QTradableStocksUS
我们将使用自定义的AggregateFundamentals类来使用最后报告的基本数据点。 这样做的目的是要解决基本面按季度报告的事实,而Quantopian目前尚无法提供一种简便的方法来汇总历史数据,例如,滚动获取最近四个季度的总和:
class AggregateFundamentals(CustomFactor):def compute(self, today, assets, out, inputs):out[:] = inputs[0]
我们将再次使用前面代码中的自定义MeanReversion因子。 我们还将使用rank()方法的mask参数为给定的环境空间定义计算其他几个因子:
def compute_factors():universe = QTradableStocksUS()profitability = (AggregateFundamentals(inputs=[income_statement.gross_profit], window_length=YEAR) /balance_sheet.total_assets.latest).rank(mask=universe)roic = operation_ratios.roic.latest.rank(mask=universe)ebitda_yield = (AggregateFundamentals(inputs=[income_statement.ebitda],window_length=YEAR) /USEquityPricing.close.latest).rank(mask=universe)mean_reversion = MeanReversion().rank(mask=universe)price_momentum = Returns(window_length=QTR).rank(mask=universe)sentiment = SimpleMovingAverage(inputs=[stocktwits.bull_minus_bear],window_length=5).rank(mask=universe)factor = profitability + roic + ebitda_yield + mean_reversion +price_momentum + sentimentreturn Pipeline(columns={'Profitability' : profitability,'ROIC' : roic,'EBITDA Yield' : ebitda_yield,"Mean Reversion (1M)": mean_reversion,'Sentiment' : sentiment,"Price Momentum (3M)": price_momentum,'Alpha Factor' : factor})
该算法仅对六个独立因子如何对每种资产进行排名以组合其信息进行平均。 这是一种非常naive的方法,没有考虑每个因素在预测未来收益时可能提供的相对重要性和增量信息。以下各章的机器学习算法将使我们能够使用相同的回测框架来做到这一点。
策略执行还依赖于run_algorithm(),但是Quantopian平台上的返回DataFrame仅包含管道创建的因子值。 这样是很方便的,因为该数据格式可用作Alphalens的输入,Alphalens是用于评估alpha因子的预测性能的库。
五、使用Alphalens包将信号与噪声分离
Quantopian已开源Python Alphalens库,用于对预测库存因子进行性能分析。 它与Zipline回测库以及投资组合绩效和风险分析库pyfolio很好地集成在一起,我们将在下一章中进行探讨。
Alphalens在以下方面有助于分析alpha因子的预测能力:
- 信号与后续收益的相关性
- 基于信号(子集)的同等或因子加权投资组合的盈利能力
- 成交额以表明潜在的交易成本
- 在特定事件中考虑绩效
- 按行业进行因子分类
1. 创建远期收益和因子分位数
要使用Alphalens,我们需要提供两个输入:
- 代表资产的信号,例如信号均值回归因子
- 通过投资给定资产的资产可获得的远期收益
performance = pd.read_pickle('single_factor.pickle')
prices = pd.concat([df.to_frame(d) for d, df in performance.prices.
items()],axis=1).T
prices.columns = [re.findall(r"[(.+)]", str(col))[0] for col inprices.columns]
prices.index = prices.index.normalize()
prices.info()
'''
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 755 entries, 2015-01-02 to 2017-12-29
Columns: 1661 entries, A to ZTS
dtypes: float64(1661)
'''
我们可以使用get_clean_factor_and_forward_returns函数将从Zipline输出数据生成Alphalens输入数据,即因子信号和前文所述的前向收益。 该函数返回信号五分位数,并在给定的保持时间内返回正向:
HOLDING_PERIODS = (5, 10, 21, 42)
QUANTILES = 5
alphalens_data = get_clean_factor_and_forward_returns(factor=factor_data, prices=prices,
periods=HOLDING_PERIODS, quantiles=QUANTILES)
'''
Dropped 14.5% entries from factor data: 14.5% in forward returns computation
and 0.0% in binning phase (set max_loss=0 to see potentially suppressed
Exceptions). max_loss is 35.0%, not exceeded: OK!
'''
alphalens_data DataFrame包含在指定持有期的给定日期在给定资产上给定资产的投资回报,以及因子值,即该日期在该资产的MeanReversion排名和相应的分位数:
前向收益和信号分位数是评估信号预测能力的基础。通常,因子对于不同的分位数应该提供明显不同的回报,例如因子值的最低五分位数的负回报和顶部分位数的正回报。
2. 通过因子分位数预测因子性能
第一步,我们希望通过因子分位数来可视化平均周期收益。 我们可以使用性能模块中的内置函数mean_return_by_quantile和绘图模块中的plot_quantile_returns_bar:
from alphalens.performance import mean_return_by_quantile
from alphalens.plotting import plot_quantile_returns_bar
mean_return_by_q, std_err = mean_return_by_quantile(alphalens_data)
plot_quantile_returns_bar(mean_return_by_q);
如下图所示,除最长的持有时间之外,最低的五分位数产生的负面结果比最高的五分位数多:
10天(10D)持有期在整个交易期间内平均为第一和第四分位数提供了更好的结果差异。
我们还希望看到由每个信号五分位数驱动的投资随时间变化的性能。为此,我们每天计算5天持有期间的每日回报,而不是平均回报。Alphalens调整周期收益以解决每日信号和更长的持有周期之间的不匹配(有关详细信息,请参阅Alphalens文档):
from alphalens.plotting import plot_cumulative_returns_by_quantile mean_return_by_q_daily, std_err = mean_return_by_quantile(alphalens_data, by_date=True) plot_cumulative_returns_by_quantile(mean_return_by_q_daily['5D'], period='5D');
下图的折线图显示,在这三年的大部分时间内,前两个五分位数的表现明显优于后两个五分位数。 但是,如前图所示,由于在2017年期间的相对表现,第四等五等分的信号产生的性能略好于最高五等分的信号:
一个对交易策略有用的因子就是前面的那种模式,其中累积收益沿着明显不同的路径发展,因为这允许具有较低资本要求的多空策略,并因此降低了对整个市场的敞口。
但是,我们还需要考虑周期收益的分散性,而不仅仅是平均值。 为此,我们可以依靠内置的plot_quantile_returns_violin:
from alphalens.plotting import plot_quantile_returns_violin
plot_quantile_returns_violin(mean_return_by_q_daily);
分布图如下图所示,突出表明日收益率的范围相当宽。 尽管有不同的方法,但是分布的分离非常有限,因此在任何给定的日子里,五分位数之间的性能差异可能会非常有限:
当我们专注于单个alpha因子的评估时,我们通过忽略与交易执行相关的实际问题来简化事情,下篇文章我们会讲回测,这些问题将被考虑到。 其中一些包括:
- 交易费用
- 滑点,或决策价格与交易执行价格之差
3. 信息系数
本书的大部分内容是关于使用机器学习模型设计alpha因子的。机器学习是关于优化某些预测目标的,在这一部分中,我们将介绍用于测量alpha因子性能的关键指标。我们将alpha定义为超过基准的平均回报。
这引出了信息比率(IR)的定义,该比率通过将alpha除以跟踪风险来衡量单位风险的平均超额收益。 当基准为无风险利率时,IR对应于众所周知的Sharpe比率,我们将重点介绍在收益率不呈正态分布的典型情况下出现的关键统计测量问题。 我们还将解释主动管理的基本法则,该法则将IR分解为预测技能和有效利用这些预测技能的策略能力的组合。
alpha因子的目标是对未来收益的准确方向预测。因此,自然的绩效指标是alpha因子的预测与目标资产的远期回报之间的相关性。
相关性最好使用非参数Spearman秩相关系数,该系数衡量使用单调函数描述两个变量之间的关系的能力,而一般人们常用的Pearson相关系数衡量的只是线性关系的强弱。
我们可以使用依赖scipy的Alphalens获得信息系数(IC)。 stats.spearmanr在后台(有关如何直接使用scipy获取p值的示例,请参见有关文档)。factor_information_coefficient函数计算周期相关性,plot_ic_ts创建一个具有1个月移动平均值的时序图:
from alphalens.performance import factor_information_coefficient
from alphalens.plotting import plot_ic_ts
ic = factor_information_coefficient(alphalens_data)
plot_ic_ts(ic[['5D']])
下图中的时间序列图显示了具有明显正移动平均IC的扩展周期。如果有足够的机会运用这种预测技能,则当IC值为0.05甚至0.1的情况下,策略的表现将很突出:
年度平均IC曲线图突显了该因子的绩效历来是不均衡的:
ic = factor_information_coefficient(alphalens_data)
ic_by_year = ic.resample('A').mean()
ic_by_year.index = ic_by_year.index.year
ic_by_year.plot.bar(figsize=(14, 6))
结果如下图
风险调整后的IC由平均IC除以IC的标准偏差得出,IC也通过scipy进行了零假设IC = 0的双向t检验(用stats.ttest_1samp方法) :
4. 因子换手率
因子换手率(Factor turnover)衡量与给定分位数更改关联的资产的频率,即需要多少笔交易来调整投资组合以适应信号序列。 更具体地说,它衡量的是当前因子分位数中的资产份额,而上一时期不在该分位数中的次数。 下表由此命令生成:
create_turnover_tear_sheet(alphalens_data)
加入基于五分位数的投资组合的资产所占的比例相当高,这表明交易成本对从预测绩效中获得收益构成了挑战:
关于因子换手率的另一种观点是,由于各种持有时长(也是上表的一部分)中的因子导致的资产等级的相关性:
通常,为了使交易成本可控,最好具有更高的稳定性(低换手率)。
六、alpha因子的资源
研究过程需要根据其信号的预测能力设计和选择alpha因子。 算法交易策略通常将基于为每个资产发送信号的多个alpha因子。 可以使用机器学习模型来汇总这些因素,以优化各种信号如何转化为有关单个位置的时间和规模的决策。
除quantopian用于算法交易和数据收集的其他开源Python库包括以下几个:
- QuantConnect是Quantopian的竞争对手。
- WorldQuant提供在线竞赛,并招募找到量化因子的社区贡献者。
- Alpha Trading Labs提供了一个针对高频的测试基础架构,其业务模型类似于Quantopian。
- Python算法交易库(PyAlgoTrade)专注于回测,并为纸面交易和实盘交易提供支持。 它使您可以使用历史数据评估交易策略的构想,并以最小的努力做到这一点。
- pybacktest是使用熊猫的矢量化回测框架,其目标是紧凑,简单和快速。 (该项目目前处于暂停状态。)
- ultrafinance是一个较旧的项目,结合了实时财务数据收集以及交易策略的分析和回测。
- Trading with Python提供用于定量交易的课程以及一系列功能和类。
- Interactive Brokers提供了一个Python API,可在其平台上进行实时交易。