||
R语言的程序包中有不少和投资组合或策略回测有关的方法。本章就quantmod包的回测方法介绍基于技术指标的量化投资方法。
当谈到量化投资的时候,最常提到的一个词可能就是“回测”(backtesting)。什么是“回测”呢?
所谓“回测”,就是对交易策略(投资策略)在历史数据上的演算测试。也就是说,当我们对一个策略是否有盈利的可能性的时候,可以先将它在历史数据上“演练”一遍,看看是否能够盈利,以及盈亏的时机和多少,从而对该策略在未来的表现有一个基本的认识。
但是,回测不是万能的,更不是具有决定性力量的论据。一个说明回测局限的经典幽默是这样说的:
有一只火鸡在笼子里被喂养了1000天,这只火鸡确信,每天都会有友善的人类“照顾它的最佳利益”。直到复活节的前一天,也就是火鸡在笼子里的第1001天,它依然认为主人还会来喂食,而没有想到它的大限已至(烤火鸡是感恩节的传统食物)。
图表12‑1死心眼信任回测的乐观的火鸡
回测亦是如此:它只能计算在已经成为历史的“historical data”上一个策略的表现,不能完美地预测这个策略在未来的表现。
回测的另一个局限是:它不能展现对数据的影响。在实际的投资过程中,资金的流动会反过来影响市场的变化的,即:市场中的买入操作会抬升价格,而抛售操作会压低价格。但在回测的时候,历史数据是无法对策略的运作发生反应的。
虽然有诸多局限,但说回测是金融工程中最为强大的投资工具可能并不过分,因为所有新的投资策略,在没有经过回测的时候,一般是不能直接拿到市场上应用的;而所有对新的策略的研发,也必须以回测结果作为策略论证的重要依据提交决策层参考。
本章根据quantmod提供的功能,对量化投资中的回测方法做一个比较详细的阐述。
按软件著作者自己的说法(JeffreyA. Ryan,http://www.quantmod.com/),quantmod包是用于帮助量化投资者开发、测试和部署基于统计的交易模型的软件系统。它是一个快速原型环境,量化投资者(宽客)可以快速和干净地对交易模型进行构建和探索;但是,quantmod并不试图替代任何统计软件,也没有什么新的“建模”过程。虽然它提供了一些新的绘图方法,但更多的是一个封包器(wrapper),将大家常用和爱用的R包和函数打包在一起提供给大家。quantmod使得金融工程的建模更为平顺,因为它消除了围绕在数据管理、建模接口和性能分析等事务的各种工作流问题。
对用户来说,我们可以这样评价quantmod:quantmod是R平台用于金融建模的扩展包,其主要功能有:从多个数据源获取历史数据、绘制金融数据图表、在金融数据图表中添加技术指标、计算不同时间尺度的收益率、金融时间序列分析、金融模型拟合与计算等,是使用R平台做金融大数据处理几乎必用此扩展软件包。
由于quantmod不是R的基本配置,因此在使用quantmod之前要安装(一次性)和加载(每次新启动R都需要重新加载):
>install.packages("quantmod")
…
package ‘quantmod’successfully unpacked and MD5 sums checked
> library(quantmod)
本书中前面的章节以及多次用到本包的getSymbols()函数,再此就不再重复。
本包的一个特色功能,是在已有图线上叠加技术指标图线。例如:下面指令将开盘收盘价差叠加到雅虎公司的股票价格图线上:
#chap12_TA.R
#library(quantmod)
getSymbols('YHOO')#Yahoo! OHLC data
#addTA允许将技术指标附加到已有的图标上,
#即便这个指标不在quantmod包定义亦可
chartSeries(YHOO,theme=chartTheme('white'), TA=NULL)
#将开盘和收盘的价差作为指标叠加上图
addTA(OpCl(YHOO),col='blue', type='h')
图表12‑2绘图时的指标图线叠加
上面指令中theme参数用于指定绘图的颜色主题,OpCl()函数用于获取开收盘价差。
quantmod还专门为图线叠加设计了许多方法。参看下面的IBM股价的例子,我们加入多个指标的图线:
ibm=getYahooData('IBM',start=20120101)
chartSeries(ibm[,'Open'],theme="white") #draw the chart
addBBands() #addBollinger Bands
addCCI() #addCommodity Channel Index
addRSI()
addMACD()
效果为:
图表12‑3包含多个指标图线叠加的IBM股价
附注:OpCl()函数是quantmod中用于从OHLC数据中提取相关成分的多个函数之一。类似的函数包括:
#提取单列数据
Op(x)
Hi(x)
Lo(x)
Cl(x)
Vo(x)
Ad(x)
#提取最大或最小值
seriesHi(x)
seriesLo(x)
#判断数据的变化趋势
seriesIncr(x,thresh=0, diff.=1L)
seriesDecr(x,thresh=0, diff.=1L)
#求差值
OpCl(x)
ClCl(x)
HiCl(x)
LoCl(x)
LoHi(x)
OpHi(x)
OpLo(x)
OpOp(x)
#求多个列组分
HLC(x)
OHLC(x)
OHLCV(x)
其中参数thresh为噪音阈值,diff为判断时的周期差,用于seriesIncr()和seriesDecr()函数判断序列的走向趋势(即:判断某点的观测值相对于diff周期以前是升还是降)。
下面我们再稍微详细一点地介绍技术分析指标,及另一个相关的软件包,TTR,用于获取这些技术指标(Technical TradingRules,TTR)。
技术指标(technicalanalysis indicators)是通过对市场某些侧面建立数学模型,给出计算公式,得到的一个可能能够体现市场的某个方面内在实质的数字。将连续不断得到的技术指标值制成图表,并根据所制成的图表对市场进行行情研制,这样的方法就是技术指标法(技术分析法)。
技术指标法是金融市场中技术分析中极为重要的分支,大约在20世纪70年代之后,技术指标逐步得到流行。全世界各种各样的技术指标至少有1000个,它们都有自己的拥护者,并在实际应用中取得一定的效果。
赞同技术分析的市场人士认为,该指标的具体数值和各个指标之间的相互间关系,可直接反映股市所处的状态,为我们的操作行为提供指导。而反对派则认为,技术指标往往来源于个人灵感,缺乏严格的理论基础,不足以成为市场动向的标示。特别是“有效市场假说”(Efficient MarketsHypothesis,EMH)认为,通过历史数据来推测市场的未来发展是没有效果的,因为市场中任何可能存在的超额的套利空间,都会被理性投资人迅速的填补,从而使所谓的技术分析没有用武之地。
技术分析方法还有其他的一些局限性;例如:
2 大部分技术指标只重视价格,不重视成交量,不可避免地在研判上会有所偏颇。
2 技术指标的变化和发出的买卖信号仍然是一个随机过程,它反映的是行情的过去历史,但股民需要预测的则是未来行情走势的可能性。
2 每一种技术指标都是局部的和片面的指标,只能反映局部的走势,不能全面真实地反映市场的资金面、基本面、技术面、政策面和投机操作手法等。
虽然技术分析有以上的问题,但我们认为,它仍不失为一种非常重要的投资策略的参考依据,理由如下:
首先,目前国内的金融市场基本上还不能算是完全“有效”的,因此技术分析仍有它的发挥作用的空间。
其次,即便是比较成熟和规范的市场,技术分析的方法也没有退出市场;所有的媒体和财经专家在评论市场的时候,多是会提及两个层面的分析:基本面分析和技术分析;这也从侧面说明了技术分析在大众心目中的重要地位,而这种重要地位本身,就会影响技术分析的有效性,完全忽视技术分析的作用是没有道理的。
最后,通过指标分析市场走向,已经是一个被行业认可的普遍做法,区别仅仅在于如何有效地定义指标,以及如何根据指标来进行研判。随着技术的发展,也会不断有新的更有效果的技术指标出现,因此我们没有理由盖棺定论,固步自封,而应积极地掌握和利用这种方法,并在实践中不断积累数据,纠正可能的偏差,从而为经济决策提供更为可靠和有效的参考。
TTR包主要提供各种技术指标的计算函数,以及从美国股市和雅虎财经数据的提取方法。其主要特点为:
Ø 功能众多
ü 超过50个技术分析指标
ü 以及多个辅助函数
Ø 灵活
ü 改进了的指标计算方式
ü 自动适应多种时间序列类型
Ø 快速
ü 多个函数使用编译模式提高计算速度
ü 可处理高频数据
TTR包含的部分指标见下表。
表格12‑1 TTR计算的部分技术指标
Moving Averages | Oscillators | Volatility | Trend Detection / Strength | Volume Studies | Misc. |
Simple | MA Convergence / Divergence | Garman- Klass | Aroon | On-Balance Volume | Bollinger Bands |
Exponential | Stochastics | Parkinson | Commodity Channel Index | Money Flow Index | Parabolic Stop and Reverse |
Weighted VWAP | Relative Strength Index | Rogers- Satchell | Vertical Horizontal Filter | Chaikin Money Flow | Zig-Zag |
Zero-Lag | TRIX | (Average) True Range | Trend Detection Index | Chaikin Accumulation / Distribution | Close Location Value |
Elastic, Volume- Weighted | Stochastic Momentum Index | Close Price Volatility | Average Directional Index | William's Accumulation / Distribution | Split / Dividend Adjustments |
上表中的技术指标分为6类:
第一类为移动平均,包括简单移动平均,指数移动平均等。
第二类为震荡指标(Oscillators),包括MACD,随机指数等。
第三类为波动率指标,包括Garman-Klass波动率,Parkinson波动率等。
第四类为趋势检测或强度指标。
第五类为成交量指标。
第六类为其它未归入上面分类的指标。
TTR的指标和quantmod的指标的对应关系可以参考下表:
表格12‑2 TTR的技术指标和quantmod指标的名称对比
Indicator | TTR Name | quantmod Name |
Welles Wilder's Directional Movement Indicator | ADX | addADX |
Average True Range | ATR | addATR |
Bollinger Bands | BBands | addBBands |
Bollinger Band Width | N/A | addBBands |
Bollinger %b | N/A | addBBands |
Commodity Channel Index | CCI | addCCI |
Chaiken Money Flow | CMF | addCMF |
Chande Momentum Oscillator | CMO | addCMO |
Double Exponential Moving Average | DEMA | addDEMA |
Detrended Price Oscillator | DPO | addDPO |
Exponential Moving Average | EMA | addEMA |
Price Envelope | N/A | addEnvelope |
Exponential Volume Weigthed Moving Average | EVWMA | addEVWMA |
Options and Futures Expiration | N/A | addExpiry |
Moving Average Convergence Divergence | MACD | addMACD |
Momentum | momentum | addMomentum |
Rate of Change | ROC | addROC |
Relative Strength Indicator | RSI | addRSI |
Parabolic Stop and Reverse | SAR | addSAR |
Simple Moving Average | SMA | addSMA |
Stocastic Momentum Index | SMI | addSMI |
Triple Smoothed Exponential Oscillator | TRIX | addTRIX |
Volume | N/A | addVo |
Weighted Moving Average | WMA | addWMA |
Williams %R | WPR | addWPR |
ZLEMA | ZLEMA | addZLEMA |
TTR还有自己的获取金融数据的方法,包括两个函数:
stockSymbols(exchange= c("AMEX", "NASDAQ", "NYSE"),
sort.by = c("Exchange","Symbol"), quiet = FALSE)
getYahooData(symbol,start, end, freq = "daily",
type ="price", adjust = TRUE, quiet = FALSE)
参数说明:
2 symbol: 雅虎金融工具符号。
2 start: 起始日期,格式为YYYYMMDD。
2 end: 结束日期,格式为YYYYMMDD。
2 freq: 三种数据频率之一:"daily","weekly", "monthly"。
2 type: 返回值类型;可以是"price"或者"split";前者会返回OHLC等价格数据,而后者则返回经过调整的分股数据。
2 adjust: 这是一个逻辑值,若为TRUE,OHLC价格数据和成交量数据都是经过调整的。
2 quiet: 逻辑值,若为TRUE,状态信息将显示在console终端上。
2 exchange: 所要交易的金融工具的交易所名称。
2 sort.by:数据排序的列;从下面四种中选取:"Name","Symbol", "Market.Cap", or "Exchange"。
TTR包为我们计算和分析技术分析指标提供了非常方便的途径。例如,MACD指标(MAConvergence / Divergence)的计算,以收盘价进行并绘图,可以使用下面代码:
#chap12_macd.R
#library(TTR)
ibm <-getYahooData("IBM", start=20120101)
macd=MACD(ibm[,'Close'])
#调整绘图参数,在1列内绘制2个图形
par(mfrow=c(2,1),mar=c(2,5,2,5))
plot(ibm[,'Close'],main='IBM')
plot(macd[,1],xlab='',main='MACD')
图表12‑4 IBM和其CDMA指标线
本节我们以对“标准普尔500指数”投资为例,在一个关于DVI指数的简化模型上进行量化投资回测。
补充:标准普尔500指数:
标准普尔500指数(Standard& Poor's 500 Index,或S&P500 Index),是记录美国500家上市公司的一个股票指数;该指数由标准普尔公司创建并维护。
标准普尔500指数覆盖的所有公司,都是在美国主要交易所,如纽约证券交易所、Nasdaq交易所的上市公司。与道琼斯指数相比,标准普尔500指数包含的公司更多,因此风险更为分散,具有采样面广、代表性强、精确度高、连续性好等特点,被普遍认为是一种理想的股票指数期货合约的标的。S&P500在芝加哥交易所交易。
补充:DVI指数:
DVI指数是一种比较新的指数,它包含两个方面的计算:1)不同时间窗上的收益平滑后的结果;2)不同时间窗上涨和跌的相对周期。DVI是一种平滑的动量震荡指数,并可用于趋势的发现。由于比较平滑,基于DVI指数的操作也比较简明,不需要时刻盯盘。例如,你可以基于200日均线和DVI制定一个简单的策略:在200日均线之上买入,并在;DVI>0.5时卖出,在200日均线之下卖空及在DVI<0.5时平仓。
有了上面的知识积累,回测一个简单的投资策略就是一件比较简单地工作了;我们可以把它分为3个步骤,算是“三板斧”吧:
(1)在历史数据上计算技术指标的值
以S&P500为例,其雅虎代码为^GSPC;我们要使用DVI指标的函数就是DVI(),因此下面的指令先获取S&P500的交易数据,然后根据其收盘价(由函数Cl()抽取)计算其DVI值:
> getSymbols('^GSPC')#S&P500 OHLC data
> dvi =DVI(Cl(GSPC))
(2)构建交易策略的信号
我们的策略很简单,即当DVI值>0.5的时候卖出,<0.5的时候买入。
> sig =ifelse(dvi$dvi<0.5, 1, -1)
> sig = Lag(sig) #将该序列向“过去”延迟一天
上面使用Lag()将信号序列向“过去”推迟一天的目的,是将昨天的信号,应用到今天。我们分别使用1和-1表示买入和卖出,以便于下一步计算。
(3)计算收益序列
> ret =ROC(Cl(GSPC)) * sig
ROC()函数获取的是观测点之间的相对差值(或称“相对动量差”,Rate of Change / Momentum),也就是今天的观测值减去昨天的观测值。由于sig对于买入的信号为1,卖出的信号为-1,因此与ROC相乘后,可以作为衡量收益的数值;例如,当ROC为负值下跌,若sig为卖出,即-1,则乘积为正,即按信号交易可获利;而若sig为买入,则乘积为负数,表示根据这样的信号交易将亏损。
有了上面“三板斧”计算的数据,我们就可以使用PerformanceAnalytics包提供的方法来查看我们的策略的效果了。
>table.Drawdowns(ret, top=10)
From Trough To Depth Length ToTrough Recovery
1 2008-10-01 2008-10-27 2009-01-12-0.2888 71 19 52
2 2009-02-18 2009-05-08 2009-09-28-0.2326 155 57 98
3 2010-09-08 2011-08-10 2011-09-02-0.1873 251 234 17
4 2009-12-18 2010-05-26 2010-07-22-0.1602 148 109 39
5 2013-04-29 2013-10-08 2014-07-25-0.1463 314 114 200
6 2008-06-06 2008-07-15 2008-09-30-0.1367 81 27 54
7 2011-10-12 2011-11-25 2011-12-28-0.1136 54 32 22
8 2008-01-04 2008-01-22 2008-02-05-0.0959 22 12 10
9 2009-01-13 2009-01-20 2009-01-29-0.0800 12 5 7
10 2011-09-282011-10-03 2011-10-10 -0.0657 9 4 5
table.Drawdowns()展示最为“糟糕”的下跌行情;其输出的信息包括:从何时开始下跌,到什么时候结束,中间的低点在什么时间,下跌深度Depth,经历的天数Length,以及恢复所经历的时间等。
另一个函数table.DownsideRisk()则显示有关下跌的风险度量的估计:
>table.DownsideRisk(ret)
GSPC.Close
Semi Deviation 0.0103
Gain Deviation 0.0116
Loss Deviation 0.0111
Downside Deviation(MAR=210%) 0.0146
Downside Deviation(Rf=0%) 0.0100
Downside Deviation(0%) 0.0100
Maximum Drawdown 0.2888
Historical VaR(95%) -0.0210
Historical ES(95%) -0.0350
Modified VaR(95%) -0.0196
Modified ES (95%) -0.0196
读者可能对上面信息所涉及的指标不太熟悉,但是没有关系,我们可以用直观的形式来观察策略的表现:
charts.PerformanceSummary(ret)
图表12‑5策略表现综述图
上图分为三个板块:最上面的板块是积累收益,相当于对cumsum(ret)的绘图;第二个是日收益,相当于对ret原始收益数据的绘图;最下面的是下跌图(又称“水下图”),将下跌成分独立绘出,有助于我们分析亏损状况和研究弥补措施。
上述回测工作因为是完全在历史数据上进行的,因此还不能算是完整的量化投资过程,可以看作是量化投资的前期工作,即“策略检验”的过程。如果策略在历史数据上获得了较好的表现,就可以将该策略应用到实际投资中以进一步实验;但应记住:在历史数据上表现良好的策略,在真实数据上不一定有同样的表现。另外,注意上述例子中完全忽略了交易成本和时间延迟等因素,只是一个简单模型的示例,不应当也不能作为实际的投资策略来应用。如果读者希望进行基于数据分析的量化投资,应该在全面综合地考虑各种因素的基础上,设计更为完整的回测检验方案,并使用大量的数据(包括使用多种不同的金融工具交易数据、设置不同的参数范围、设计不同的信号生成机制等)进行全面的回测检验。即便你已经进行了上述的严谨回测,在实际应用时也需要谨慎从事,采取严格的止损机制,并尽可能的寻找策略优化机会。
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-9-27 10:09
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社