“绩效度量”是基于一本量化交易书: “Successful Algorithmic Trading”第十二章的翻译。互联网上可以找到这本书的英文版本。
这一章主要描述如何对策略绩效进行度量,如何评估策略的好与坏。
分割线
绩效度量是算法交易中非常重要的组成部分。没有绩效评估,没有持续的记录,很难判断我们的策略收益到底是来自于运气还是真正的市场优势。
为了在算法交易中获得成功,有必要明白影响交易盈利情况和最终策略的所有因素。我们应该不断地去寻找所有算法交易栈的方方面面的改进。特别是我们应该总是尽力减少我们的交易成本(交易费,佣金以及滑点),改进软件和硬件,改善数据源的质量以及持续寻找新的策略增加到投资组合中。所有这些领域的绩效度量提供了一种标准,可以用于度量其他可选方案。
算法交易最根本是产生利润。因此多尺度度量绩效是非常重要的,可以搞清楚如何以及为什么我们的系统产生这些盈利。这些都激发了绩效评估,在交易的层面进行评估,在策略和投资组合的层面进行评估。特别是我们正在寻找:
是否已经编码进入到策略里面的系统规则真正产生持续的回报,是否策略在回测中拥有正收益。
是否策略在实盘中能维持正收益,是否策略已经过期要被淘汰。
比较多个策略和投资组合的能力,比如减少因为分配有限的交易资本有关的机会成本。
我们感兴趣的绩效量化分析有如下几项:
回报 - 交易策略最明显的关注点,回测或者实盘的收益百分比。两个主要的绩效度量是总回报(TR)和组合年度增长率(CAGR)
回撤 - 策略或者投资组合的资金曲线之前有最高峰。我们将在下面有更具体的定义,你能想象一下你的绩效图表上有向下的坡度。
风险 - 风险有许多方面构成,我们将在后面的章节花大量的时间讲解,总的来说,风险指的是资本损失,比如回报的回撤和波动,后者经常通过回报的年度标准差来计算。
风险/奖励比率 - 机构投资者主要关心经过风险调整后的回报。更高的波动经常会导致更高的回报,当然附带着更大的回撤。他们总是关心每单位的回报会有多少风险。因此一系列的绩效度量被发明出来用于量化策略这方面的风险,比如Sharpe Ratio(夏普比率),Sortino Ratio(索提诺比率)和 CALMAR Ratio(卡玛比率)等等。讨论策略绩效时,样本外夏普比率是机构投资者首先考虑的。
交易分析 - 先前的绩效度量都是针对策略和投资组合。考察单个交易的绩效也是很有意义的,也存在很多方法描述这些绩效。我们将量化盈亏的交易次数,交易的平均盈利以及盈亏比等等。
交易是算法策略最基本的方面,因此我们首先进行交易分析。
12.1 交易分析
分析任何策略的第一步就是考察实际交易的绩效。像这样的指标在不同策略之间可能完全不同。经典的例子就是趋势跟踪策略和均值回归策略的绩效差别。
趋势跟踪策略通常由许多亏损的交易,每个亏损的交易可能损失很小。当趋势建立以后,少量盈利的交易会产生,来自这些盈利的交易的绩效可能明显超出大量亏损交易的绩效。配对交易-均值回归策略恰恰相反。它们总是由大量微小盈利的交易组成。而且,价格序列没有预期地回归均值,也可能会导致后续的损失。这可能抵消掉大量的微小收益。
本质上,你需要意识到策略的盈利和你的心理预期盈利,两者需要一起比较。否则,你将发现在一段时间的剧烈回撤时你可能无法坚持。
我们现在看看一些交易级别的统计。
12.1.1 摘要统计
考察交易时,我们对下列的统计感兴趣。这里的“周期”指包含OHLCV(译者注:开,高,低,收,交易量)的Bar数据覆盖的时间周期。对于长期周期来说,经常会用到每日Bar数据。对于高频策略,经常会用到小时或者分钟Bar数据。
总盈利/亏损(PnL)- 总的收益,表示是否策略盈利还是亏损。
平均周期PnL - 平均值,在一定周期内,每个Bar平均产生的收益。
最大周期盈利 - 最大值,在一定周期内,最大盈利的Bar对应的收益。
最大周期亏损 - 最小值,在一定周期内,亏损最大的Bar对应的亏损。
平均周期盈利 - 平均值,在一定周期内,盈利的Bar的平均收益。
平均周期亏损 - 平均值,在一定周期内,亏损的Bar的平均亏损。
盈利周期数 - 总的周期数,盈利的Bar的数量。
亏损周期数 - 总的周期数,亏损的Bar的数量。
盈利/亏损周期数百分比 - 比率,盈利周期数 / 亏损周期数。在这个指标上,趋势跟踪策略和均值回归策略之间会有显著差异。
令人欣慰的是我们投资组合工具直接输出了这些信息,不用再手工记录。但是,这将导致我们从未停止过分析数据!
每个月至少评估交易1到2次,这是非常重要的。这可以帮助我们进行早期预警:当策略开始退化时能够识别出来。这比简单的使用累计PnL要好的多。
12.2 策略和投资组合分析
交易级别的分析对于长期策略是相当有用的,特别是有复杂交易的,比如那些涉及到衍生品的。对于高频策略来说,对单个交易不感兴趣,感兴趣的是策略级别的绩效度量。显然,长期策略同样对策略级别的绩效感兴趣。我们主要感兴趣下面三个关键点:
回报分析 - 策略的回报囊括了盈利的概念。在机构环境中,通常采用净费用以及投资多少钱赚多少钱。特别是有现金流入流出时,回报计算简单。
风险/奖励分析 - 外部投资者首先考虑的是策略的样本外夏普比率(后面章节会描述)。这是一个业界标准尺度,尝试描述多少风险带来多少回报。
回撤分析 - 机构环境中,这可能是三个要素中最重要的。策略,投资组合或者基金的收益和回撤范围形成了风险管理的一个关键组成部分。我们将在后面的章节定义回撤。
尽管我们强调的是机构的绩效,作为个人交易者,这些仍然是高度重要的尺度,有了这些适当的风险管理(看下一章节),将形成持续策略评估的基础。
12.2.1 回报分析
个人和机构交易者讨论策略绩效时最广泛引用的数据经常是总回报,年度回报和月度回报。看到带有月度回报表格的套保基金绩效新闻是相当平常的。另外,每个人都想知道策略的“回报”到底是什么。
在没有外部投资或者现金流入/流出的个人交易者来说,总回报计算相对直接,百分比计算公式为:
rt = (Pf - Pi) / Pi * 100
这里rt是总回报,Pf是最后投资组合的美元价值,Pi是初始投资组合的美元价值。我们最感兴趣的是净回报,那就是扣除交易/业务手续费以后的投资组合/基金价值。
注意,这个公式仅仅应用于做多和无杠杆的投资组合。如果希望增加卖出或者杠杆操作,我们需要修改回报计算公式,因为交易的是借来的更大的投资组合,这叫做保证金交易。
举个例子,一个交易策略买进1000美金的某个品种,然后卖出1000美金的另外一个品种。这是以美元为中心的投资组合,名义交易总量为2000美金。如果这个策略生成200美金的收益,那么这个交易的总回报为10%。当你考虑借贷费用和杠杆利率时,这将变得更复杂。去除这些成本将会得到净总回报,这就是经常引用的“总回报”。
资金曲线
假如这个基金做的很好,资金曲线通常是基于基金绩效报告最重要的可视化成果之一。它是总的时间与投资组合净值的图表。本质上,它用于展示基金从成立开始账户的增长情况。同样,对于个人交易者,它展示了账户资产在整个交易期间的增长情况。下图是一个典型的资金曲线图:
典型日内策略资金曲线
像这样的图有什么用处?本质上它是策略过去波动的“调味剂”,也是一个可视化指标,从图像中可以看出策略运行过程中,是否存在很长一段时间的停滞时期或者回撤。它也揭示了策略交易期结束时总回报如何计算。
在资金曲线中,我们可以找到不寻常的历史事件如何影响策略。比如,一个常见的问题就是2008年策略是否有过度的波动。另一个问题则可能关心回报的一致性。
解释资金曲线时必须小心的是它总是显示“向上倾斜的线”.通过分割曲线,我们能看到剧烈波动时期或者可能在整个时间段并不严重的持续回撤。因而资金曲线需要考虑其他一些分析,特别是风险/奖励分析和回撤分析。
12.2.2 风险/奖励分析
上面我们提到的风险/奖励分析在机构环境中是非常重要的。当然,作为个人投资者也不能忽视。你应该密切注意策略的风险/奖励度量,因为它们将影响策略的回撤,杠杆和总的复合增长率。
这些概念将在下一章“风险和资金管理”进一步讲解。现在我们将讨论一般的比率,比如夏普比率,在金融领域非常普遍的比较手段。它在量化交易中有非常高的关注,因此我们将更详细的讨论它。
夏普比率
考虑这样的情形:我们有两个回报相同的策略。我们如何知道哪个策略有更高的风险?更进一步,更高的风险指的是什么?在金融领域,我们经常关心回报的波动和回撤周期。因而当其中一个策略的回报有明显高的波动,我们可能认为它是不够吸引人的,尽管它的历史回报可能是相似或者一样的。这些策略比较的问题和风险评价激发了夏普比率的使用。
William Forsyth Sharpe 是诺贝尔经济学奖获得者,他于1966年创建了资产定价模型(CAPM)和开发了夏普比率。
夏普比率 S 定义如下:
这里Ra是资产或者策略的回报,Rb是基准的回报,比如无风险利率。
这个比率实际是回报的均值除以回报的标准偏差。因此,在同样的回报均值的情况下,回报的更低的波动将会导致更大的夏普比率。
经常会被用到的是年度夏普比率,它的计算依赖交易周期,假定一年有N个交易日,年度夏普比率定义如下:
注意,夏普比率本身也需要基于时间周期来计算。比如一个基于“天”周期的策略,N = 252 (一年有252个交易日,不是365),Ra,Rb是每天的回报。类似基于“小时”周期的策略,N = 252 * 6.5 = 1638, 不是 N = 252 * 24 = 6048,因为在美国股票市场,一个交易日只有6.5小时。
上面的夏普比率公式暗含了基准的使用。基准作为一个衡量尺度,衡量策略是否值得考虑。比如,一个操作美国大盘股的简单做多策略平均下来收益应该能战胜S&P500指数,或者有更小的波动,否则直接投资指数有更低的管理费,更划算。
基准的选择有时是不清晰的。ETF指数基金应该作为个股的绩效基准吗?还是S&P500?为什么不是Russell 3000?同样地对冲基金策略应该与市场指数进行比较还是应该与其他对冲基金比较呢?
“无风险利率”也有争议。指国债利率?或者一揽子国际债券利率?又或者短期或长期票据利率?又或者几者混合?很明显,有很多方式选择基准。针对美股策略,夏普比率一般选择10年期国库券利率作为无风险利率。
也有特例,针对市场中性策略,选择使用无风险利率还是0作为基准是一个难点。市场指数本身不是市场中性的。对于市场中性策略,不应该减去无风险利率,它是自给的。因为你持有保证金也能够获得贷款利息Rf, 实际回报的计算如下:
(Ra + Rf) - Rf = Ra. 因此,市场中性的策略没有真正减去无风险利率。
尽管在量化金融领域,夏普比率非常流行,但是它也有很多限制。夏普比率是“后向”指标,它只是统计历史回报分布和波动,不代表将来。当我们通过夏普比率来做决策时,一个明显的假定就是过去与未来相似。这明显不总是这样,特别是市场机制改变的时候。
夏普比率计算假定回报是正太分布(高斯分布)。不幸的是,市场经常遭遇超过正态分布的尖峰。本质上回报的分布是“厚尾”分布, 我们相信极端事件比高斯分布更可能出现。因此,夏普比率很难刻画“尾部风险”。策略中像这样的风险很明显,比如看涨期权的销售又叫做“滚动的便士”。随着看涨期权的销售,期权溢价源源不断的产生,这将导致低波动的,远远超过基准的回报。这个例子中,策略拥有高夏普比率。但是它没有考虑到像这样的期权可能被“召回”,导致明显的回撤甚至归零。因此夏普比率不能被孤立的使用。
显而易见地,为了更加真实,交易费用应该包含在夏普比率的计算当中。有很多交易策略的例子中,它们有高的夏普比率和大的盈利可能性,一旦考虑了真实的交易成本,实际上变成低的夏普比率和低的盈利策略。这意味着我们计算夏普比率时时应该采用净回报,计算过程中应该考虑交易成本。
一个显而易见的未解决的问题是“一个好的交易策略的夏普比率应该是多少?”。这真正是一个很难回答的问题,因为不同的投资者有不同的风险偏好。一般的规则是:年度夏普比率 S < 1 的量化策略通常不应该被考虑使用。但是这也有例外,特别是期货市场中的趋势跟踪策略。
量化基金通常忽略夏普比率 S < 2的策略。我熟悉的一个有影响力的量化对冲基金甚至不会考虑使用夏普比率 S < 3的策略。作为个人算法交易者,如果你能够获得样本外(或者实盘交易)夏普比率 S > 2的策略,你将可以做的很好。
夏普比率通常随着交易频率的增加而增加。一些高频策略有高1位数字(有时低2位数字)的夏普比率。因为这些策略几乎能够每天每月都能盈利。这些策略很少遭受灾难性风险(比如大的损失),并且能够减小回报的波动,这导致了相当高的夏普比率。意识到像这样的高频策略也可能突然失去作用,但这是风险的另一个方面,并不会完全反映在夏普比率上。
现在我们看看夏普比率实际的例子。我们考虑一个简单的,只买多,只买单个股票,买入并持有的市场中性策略。我们用Pandas来完成这些例子代码。
第一个任务是获取数据,然后把它置入Pandas DataFrame对象。先前的章节我们用Python和MySQL实现了这些。另外,我们可以用简单的代码抓取Google金融数据。这段代码的最后我创建了一个方法,基于回报的时间序列来计算年度夏普比率。代码如下:
#!/usr/bin/python
# -*- coding: utf-8 -*-
# sharpe.py
from __future__ import print_function
import datetime
import numpy as np import pandas as pd
import pandas.io.data as web
def annualised_sharpe(returns, N=252):
"""
Calculate the annualised Sharpe ratio of a returns stream
based on a number of trading periods, N. N defaults to 252, which then
assumes a stream of daily returns.
The function assumes that the returns are the excess of
those compared to a benchmark.
"""
return np.sqrt(N) * returns.mean() / returns.std()
现在我们可以直接从Google金融数据来计算年度夏普比率,我们可以针对2个股票来测试购买持有策略。我们将采用2000年1月1日到2013年1月1日的Google金融数据。
可以创建一个工具方法帮助我们快速的查看相同周期,跨多个股票的购买持有策略的夏普比率。
代码如下:
def equity_sharpe(ticker):
"""
Calculates the annualised Sharpe ratio based on the daily
returns of an equity ticker symbol listed in Google Finance.
The dates have been hardcoded here for brevity.
"""
start = datetime.datetime(2000,1,1)
end = datetime.datetime(2013,1,1)
# Obtain the equities daily historic data for the desired time period # and
add to a pandas DataFrame
pdf = web.DataReader(ticker, ’google’, start, end)
# Use the percentage change method to easily calculate daily returns
pdf[’daily_ret’] = pdf[’Close’].pct_change()
# Assume an average annual risk-free rate over the period of 5%
pdf[’excess_daily_ret’] = pdf[’daily_ret’] - 0.05/252
# Return the annualised Sharpe ratio based on the excess daily returns
return annualised_sharpe(pdf[’excess_daily_ret’])
对于谷歌股票,买入持有策略的夏普比率为0.703:
>>> equity_sharpe(’GOOG’)
0.70265563285799615
现在我们可以针对市场中性策略做同样的计算。市场中性的策略的目标通常是特定股票的绩效。通过做空相同金额的ETF基金可以达到这个目标,ETF基金是用来跟踪市场的。对于美国股票市场,显而易见的是选择 S&P500指数,它是用来跟踪 SPDR ETF的,股票代码:SPY。
为了计算像这种策略的年度夏普比率,我们获取SPY的历史价格,跟之前的股票一样计算回报的百分比。这里的例外是我们不使用无风险基准利率,我们将计算净回报,通过减去做多和做空的回报,并且除以2,因为我们使用了2倍的交易成本。下面是Python/pandas代码:
def market_neutral_sharpe(ticker, benchmark):
"""
Calculates the annualised Sharpe ratio of a market
neutral long/short strategy inolving the long of ’ticker’ with a
corresponding short of the ’benchmark’.
"""
start = datetime.datetime(2000, 1, 1)
end = datetime.datetime(2013, 1, 1)
# Get historic data for both a symbol/ticker and a benchmark ticker
# The dates have been hardcoded, but you can modify them as you see fit!
tick = web.DataReader(ticker, ’google’, start, end)
bench = web.DataReader(benchmark, ’google’, start, end)
# Calculate the percentage returns on each of the time series
tick[’daily_ret’] = tick[’Close’].pct_change()
bench[’daily_ret’] = bench[’Close’].pct_change()
# Create a new DataFrame to store the strategy information # The net returns
#are (long - short)/2, since there is twice # the trading capital for this
#strategy
strat = pd.DataFrame(index=tick.index)
strat[’net_ret’] = (tick[’daily_ret’] - bench[’daily_ret’])/2.0
# Return the annualised Sharpe ratio for this strategy
return annualised_sharpe(strat[’net_ret’])
对于Google股票,多空市场中性策略的夏普比率是0.832:
>>> market_neutral_sharpe(’GOOG’, 'SPY')
0.83197496084314604
我们下面将讨论其他的风险/奖励比率。
索提诺比率
夏普比率同时捕捉向上和向下的波动,但是,投资者(对冲基金经理)总的来说不会被明显向上的波动困扰。风险管理中感兴趣的主要是向下的波动和回撤周期。因此索提诺比率被定义成回报均值除以向下的波动的偏差:
索提诺比率在机构环境里会被使用,但很确定的是不如夏普比率那么普遍。
卡马比率
有人可能会争论投资者或者交易者也关心最大回撤,而不是平均回撤。CALMAR(加利福利亚管理账户报告)比率由此产生,也叫做回撤比率,它定义为回报均值除以最大回撤:
再次说明,卡马比率不像夏普比率使用那么广泛。
12.2.3 回撤分析
我认为,回撤是算法交易系统最重要的一个方面。简单的说,如果你的账户资金被消灭了,什么绩效指标都不重要。回撤分析关心账户资金从高水位的点下降的幅度。高水位的点定义为最近账户资金在资金曲线上的峰值。
在机构环境中,回撤特别重要因为大多数对冲基金只有当账户资金持续创新高才有酬劳。也就是说,一个基金经理没有绩效费如果基金维持在“水位以下”,比如账户资金回撤了一段时间。
当一个基金有10%的回撤时,大多数投资者会担心,并且将会赎回他们的投资一旦回撤超过30%。在个人环境中,这种情形非常不同。个人可能可以承受较大的回撤来换取更高的回报。
最大回撤与回撤持续时间
两个关键的回撤指标是最大回撤和回撤持续时间。前一个描述账户资金从前一个高峰位置最大比例的回撤到当前位置或者前一个低谷。在机构环境中交易基金时经常被使用。个人交易者也对这个数据保持极大的关注。后一个描述回撤的持续时间。这个数据经常以“天”为单位来表示,但是更高频策略会用细粒度的时间周期。
在回测中,这些方法提供了一些主意供我们判断策略在将来会如何表现。整体而言,资金曲线可能看起来非常诱人,但是,向上的资金曲线可能很容易掩饰先前经历的回撤有多么困难。
当一个策略的回撤低于10%,或者低于20%时,需要强大意志力来继续执行这个策略。尽管策略可能在历史上,在回测中,经历过类似的时期。对于算法交易和系统交易都面临同样的问题。这也自然地激发了设置回撤边界和特定的规则,比如当回撤达到设置的级别时账户止损。
回撤曲线
重要的是感受最大回撤和回撤持续时间,看策略回撤的时间序列图表肯定更有吸引力。
Fig 12.2.3很清晰的表明这个策略遭遇了相当长时间的回撤从2010第三季度到2011年第二季度,最大回撤达到14.8%。然而策略本身在想当长的时间持续明显的盈利,这个特定时期非常困难值得忍耐。另外,这是迄今为止目前发生的最大历史回撤,策略有可能在将来发生更大的回撤。有必要和其他绩效方法一样关注回撤曲线。
Figure 12.2: 典型日内策略回撤曲线
在下面的章节我们将讨论量化风险管理的概念和描述能帮我们最小化回撤和最大化回报的技术,始终保持风险在合理的程度。