3.5 交易成本

3.5 交易成本

没有考虑交易成本的回测业绩是不真实的。第2 章谈到了佣金、流动性成本、机会成本、市场冲击及滑价等交易成本,并且举了几个如何在策略回测中处理交易成本的例子。一项高夏普比率的策略,在考虑交易成本后变得无利可图,这是完全可能的,见例3. 7 。

例3.7  交易成本与均值回归模型

麻省理工学院的Amir Khandani 和Andrew Lo 提出了一个简单的均值回归模型〈可参见web. mit. edu/alo/www/Papers/august07. pdf}。策略非常简单z 买入前一交易日日收益最差的股票,卖空前一交易日日收益最好的股暴。在不考虑交易成本的情况下, 1995 年以来,这一简单策咯的业绩一直非常出色( 2006 年的夏普比卒为4. 47 )。我们要研究的是,假定每笔交易成本为5 个基点时,策咯业绩如何变化。〈此处的一笔交易是指一笔买入或一笔卖出,而不是一笔来回交易。〉这个例子不仅向我们展示了交易成本对业绩的影响,也展示了交易多只股票时MATLAB 在模型回测中的强大功能。用Excel 对模型在若干年中的交易进行回测需要设置一大堆标签,十分不便。但使用MATLAB 也会遇到一个问题,即如何在几百个数据标签中检索历史数据,尤其是元存活偏差的数据。此处暂不考虑存活偏差的问题,因为获取无偏差数据十分昂贵,我们只要记得,所得的预测业绩相对实际业绩被高估。

对股票选择策略进行回测时,遇到的第一个问题永远是z 哪些股票可用于回测?标准普尔500 指数成分股通常是首选,因为它的流动性是最好的。标准普尔500 指数的当前成分股可从标准普尔网站下载( www.standardandpoors. com)。由于成分股一直在变化,你下载的名单可能会与我的不同。你可在epchan. com/book/SP500 20071121. xis 找到我的名单。下载所有这些股票的历史数据,最简便的方法是购买一份HQuotePro 的拷贝(可在HQuote. com 下载)。这个软件可以使你很方便地剪切粘贴所需数据的所有标签列。使用软件检索和支新2001 年1 月1 日至今的所有数据,只选择日期、开盘价、最高价、最低价、收盘价和成交量,不含数据名称栏,保存为文件“Export. txt”。通过以下MATLAB 程序将其处理为运算时可使用的数据,在本地目录下保存为二进制文件“SPX_20071123. mat”。

clear;

inputFile=’Export. txt' ; ,

outputFile= 'SPX_2007 l l 23 

[mysym, mytday, myop, my hi, my lo, mycl, myvol] = ..?

textread ( inputFile,’%s %u %f %f %f %f %u’,’delimiter’,’,’>;

%找到不重复的股票集合stocks=unique(mysym);

%找到不重复的日期集合

tday= unique( mytday);

op=NaNOength(tday), length(stocks> g

hi= NaN (length ( tday) , length (stocks)) ;

lo= NaN (length ( tday) , length (stocks> s

cl=NaNOength(tday), length(stocks));

vol=NaNOength(tday), length(stocks> g

for s= 1: length(stocks)stk=stocks{s};

%找到当前股票的下标

idxA=strmatch(stk, mysym,’exact’>;

%找到当前日期集的下标[foo,

idxtA, idxtB]=intersect(mytday(idxA), tday);

%获取当前股票的价格

op(idxtB, s) =myop(idxA(idxtA> g

hi(idxtB, s) = myhi(idxA(idxtA> 3

lo( idxtB, s) = mylo(idxA (idxtA> g

cl(idxtB, s) = mycl(idxA(idxtA));

vol(idxtB, s) = myvol(idxA(idxtA> z

end

save(outputFile ,’ tday’,’ stocks,,’。p’,’ hi’,’ lo’,’ cl’,' vol');

接下来,用这些历史数据来回测不考虑交易成本的均值回归策略z

clear;

startDate= 20060101;

endDate=20061231;

load('SPX 20071123’,’tday', 'stocks', 'cl') ;

%日收益率dailyret= (cl- lagl (cl>. /lagHcD;

%等权重的市场指数收益率

marketDailyret= smartmean(dailyret, 2);

%股票的权重与其离市场收益率的距离的负数成正比

weights= ???

一( dailyret- rep mat ( marketDailyret, [ 1 size( dailyret, 2) J>./

repmat(smartsum(isfinite(cl), 2), [1 size(dailyret, 2) ]) ;

%则除没有有效价格或日收益率的股票

weights(~isfinite(cl) I ~ isfiniteOagl (cl>)=O;

dailypnl =smarts um ( lagl (weights ).骨dailyret, 2);

%删除考虑期外的盈亏

dailypnl( tday < startDate I tday > endDate) = [];

%夏普比率应该是0.25

sharpe= sqrt(252 )铃smartmean( dailypnl, 1) I smartstd ( dailypnl, 1)

这个程序文件包括在epchan. com/book/example3_7. mo 注意, 2006年的夏普比率只有0.25 ,而非原作者所报告的4.47 。业绩的显著降低,是因为本例的回测使用的是标准普尔500 指数所有成分股。如采读了作者的文章,你就会发现绝大部分收益来自小盘股和微盘股。

在上面的MATLAB 程序中,我使用了三个新函数“ smarts um ”、“ smartmean”和“ smartstd”,其功能与“ sum”、“ mean”和“ std”三个常用函数的功能相似,但能自动忽略数据中所有NaN 元素。这些函数在进行回测时非常有用,因为股票的价格序列经常是断断续续的。这些文件在epchan. com/book 都能找到。

”Smartsum. m”

function y = smartsum(x, dim)

% y = smartsum(x, dim)

%对dim 维求和,忽略NaN

hasDa ta= isfini te ( x) ;

x(~hasData) =O;

y=sum(x,dim);

y(all(~hasData, dim>=NaN;

”smartmean. m

function y = smartmean 仗, dim)

% y = smartmean(x, dim)

%对dim 维求均值,忽咯NaN

hasData=isfinite(x);

x(~hasData) = 0;

y=sum(x,dim). /sum(hasData, dim);

y(all(~hasData, dim>=NaN; %若y 的所有元素都是NaN ,则y 取值

为NaN

” smartstd. m”

function y = smartstd(x, dim)

%y = smartstd(x, dim)

%对dim 维求标准差,忽略NaN 和Inf

hasData=isfinite(x);

x(~hasData) = 0;

y=std(x);y(all(~hasData, dim>=NaN;

现在考虑每笔交易成本为5 个基点时的回测。

%减去交易成本后的盈亏

onewaytcost=O. 0005; 

%假设交易成本为5 个基点

%剧除考虑期外的权重

weights( tday < startDate I tday > endDate, : ) = [];

%权重变化时产生交易成本

dailypnlminustcost = ..?

dailypnl - smartsum(abs(weights-lagl(weights)), 2 )*.onewaytcost;

%夏普比率应该为一3. 19

sharpeminustcost= sqrt(252 )*

smartmean( dailypnlminustcost, 1) I ...smartstd(dailypnlminustcost, 1)

现在,这一策略的业绩非常差!