主要内容

交易信号的反馈投资策略

这个例子展示了如何对交易策略中包含投资信号的投资组合策略进行回溯测试。这个词信号包括策略作者在资产价格历史记录之外就交易决策所需的任何信息。此类信息可以包括技术指标、机器学习模型的输出、情绪数据、宏观经济数据等。本例使用三种基于衍生工具的简单投资策略e信号数据:

  • 移动平均线跨界车

  • 移动平均收敛/散度

  • 相对强度指数

在此示例中,您可以在一年的股票数据中使用这些策略来运行一个逆端。然后,您分析结果以比较每个策略的性能。

尽管技术指标通常不作为独立交易策略使用,但本示例使用这些策略来演示如何在使用背测发动机在MATLAB®对象。

加载数据

为2006年加载15股股票的调整后的价格数据。此示例使用一小组可投资资产进行可读性。

阅读2006年道琼斯工业平均指数股票每日调整收盘价表。

T=可读性(“dowPortfolio.xlsx”);

为了可读性,仅使用30个DJI组件库存中的15个。

符号= [“AA”“猫”“说”“通用汽车”“hp”“jnj”“力”“嗯”“莫”“MRK”“微软”“工业”“PG”“T”“XOM”];

修剪表,只保存日期和选定的股票。

timeColumn =“日期”;T=T(:,[timeColumn符号]);

将数据转换为时间表。

价格stt=表2可计量(T,“划船时间”“日期”);

查看价格的结构时间表。

总经理(价格)
ans=8×15时间表日期AA猫说通用hp JNJ MCD嗯莫merck microsoft pfizer PG T XOM  ___________ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ 03 - 1月- 2006 28.72 55.86 24.18 17.82 28.35 59.08 32.72 75.93 52.27 30.73 26.19 22.16 56.38 22.7 56.64 04 -简- 2006 28.89 57.29 23.77 18.3 29.18 59.99 33.01 75.54 52.65 31.08 26.32 22.8856.48 22.87 56.74 05 - 1月- 2006 29.12 57.29 24.19 19.34 28.97 59.74 33.05 74.85 52.52 31.13 26.34 22.9 56.3 22.92 56.45 06 - 1月- 2006 29.02 58.43 24.52 19.61 29.8 60.01 33.25 75.47 52.95 31.08 26.26 23.16 56.24 23.21 57.57 09 - 1月- 2006 29.37 59.49 24.78 21.12 30.17 60.38 33.88 75.84 53.11 31.58 26.21 23.16 56.67 23.3 57.54 10 - 1月- 2006 28.44 59.25 25.0920.79 30.33 60.49 33.91 75.37 53.04 31.27 26.35 22.77 56.45 23.16 57.99 2006年1月11日28.05 59.28 25.33 20.61 30.88 59.91 34.5 75.22 53.31 31.39 26.63 23.06 56.65 23.34 58.38 2006年1月12日27.68 60.13 25.41 19.76 30.57 59.63 33.96 74.57 53.23 31.41 26.48 22.9 56.02 23.24 57.77

检查数据集

可视化数据集中每只股票的相关性和总回报。

想象一下这15只股票之间的相关性。returns=tick2ret(pricesTT);stockCorr=corr(returns.Variables);heatmap(symbols,symbols,stockCorr,“彩色地图”, parula);

图中包含一个热图类型的对象。

%在价格数据范围内可视化每股库存的性能。totalret = ret2tick(返回);绘图(totalret.dates,totalret.variables);传说(符号,“位置”“西北”);头衔(“每股增长1美元”) ylabel ('$'

图中包含一个Axis对象。每个股票的标题增长为$1的Axis对象包含15个line类型的对象。这些对象表示AA、CAT、DIS、GM、HPQ、JNJ、MCD、MMM、MO、MRK、MSFT、PFE、PG、T、XOM。

%获取数据集期间每个股票的总收益。totalRet(最终,:)
ans=1×15时刻表一只猫一只猫一只猫一只猫一只猫一只猫一只狗一只猫一只猫一只狗一只猫一只猫一只猫一只狗一只猫一只猫一只猫一只猫一只猫一只猫一只猫一只猫一只猫一只猫一只狗一只猫一只猫一只猫一只猫一只猫一只猫一猫一只猫一只猫一只猫一只猫一只猫一只猫一只猫一只猫一只猫一只猫一猫一猫一只猫一猫一猫一只猫一只猫一只猫一只猫一只猫一只猫一只猫一只猫一只猫一只猫一只猫一对对对对对狗狗一只狗狗一一一一只狗狗一一一只狗狗一一一一一一一一一一只狗狗一一只狗狗一只狗狗一一一只狗狗一一一一一一一一只狗狗,一一一一一一一2007年12月29日1.0254 1.0781 1.4173 1.6852 1.4451 1.0965 1.3548 1.0087 1.1946 1.3856 1.1287 1.1304 1.1164 1.5181 1.336

建立信号表

除了历史调整后的资产价格,回溯测试框架还允许您选择性地指定信号运行reaktest时的数据。通过使用MATLAB®以与价格类似的方式指定信号数据时间表这个"time" dimension of the信号时间表必须与价格时间表-也就是说,每个表的行必须具有与时间

这个例子构建了一个信号时间表来支持这三种投资策略:万博1manbetx

  • 简单移动平均交叉(SMA)策略

  • 移动均线趋同/背离策略

  • 相对强度指数(RSI)策略

每个策略都有一个预先计算的信号的时间表。在运行后退之前,将三个单独的信号时间表合并到用于逆端的单个聚合信号时间表。

SMA:简单移动平均交叉

SMA指标使用5天和20天的简单移动平均线来做买入和卖出的决定。当5日移动平均线越过20日移动平均线(向上移动)时,股票被买入。当5日移动平均线穿过20日移动平均线时,该股票被卖出。

%使用movavg函数创建SMA时间表。sma5 = movavg(pricestt,'简单的'5);SMA20 = MOVAVG(PRICESTT,'简单的', 20);

创建SMA指示信号时间表。

smasignalnamesing =“20岁以上”;smaSignal =时间表;I = 1:numel(symbols) symi = symbols(I);为每个符号建立一个时间表,然后将它们聚集在一起。(pricesTT smaSignali =时间表。日期,......双(sma5。(symi) > sma20。(symi)),......'variablenames'{sprintf (' % s % s '、symi smaSignalNameEnding)});%使用同步函数将时间表合并在一起。smaSignal =同步(smaSignal smaSignali);结束

SMA信号时间表包含一个值的指示1当每项资产的5天移动平均线高于20天移动平均线时,a0否则。每个股票指标的列名为[股票代码Sma5超过20这个backtestStrategyObject基于这些交叉事件做出交易决策。

查看SMA信号时间表的结构。

头部(SMA信号)
ans=8×15时间表时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间,时间UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU______________UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU二零零六年一月零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零11111-Jan-2006 01101101101112-Jan-2006 01111111

绘制单个资产的信号以预览交易频率。

plot(smasignal.time,smasignal.cat_sma5over20);ylim([ -  0.5,1.5]);ylabel(' sma 5 > sma 20');头衔(sprintf(SMA 5 over 20 for CAT));

图中包含一个轴对象。CAT的标题为SMA 5 / 20的轴对象包含一个类型line的对象。

MACD指标:趋同/背离的移动平均线

你可以用多种方式使用MACD指标。通常,MACD与其自身的指数移动均线相比较,但在本例中,MACD在MACD高于该水平时作为买入信号的触发点0.当MACD回到下方时,售出一个位置0

%使用MACD函数创建MACD指标的时间表。macdTT = macd (pricesTT);

创建MACD指示器信号时间表。

macdSignalNameEnding ='_macd';macdsignal =时间表;I = 1:numel(symbols) symi = symbols(I);%构建每个符号的时间表,然后将符号聚合在一起。(pricesTT macdSignali =时间表。日期,......双(macdTT。(symi) > 0),......'variablenames'{sprintf (' % s % s '、symi macdSignalNameEnding)});macdSignal =同步(macdSignal macdSignali);结束

MACD信号表包含每个资产的一列,列的名称为[股票代码MACD.每个信号的值为1当MACD高于该股票时0这个信号has a value of0当股票的MACD降至以下时0

头(MacDSignal)
ans=8×15时间表时间AA_MACD CAT_MACD DIS_MACD GM_MACD HPQ_MACD JNJ_MACD MCD_MACD MMM_MACD MO_MACD MRK_MACD MSFT_MACD PFE_MACD PG_MACD T_MACD XOM_MACD ___________ _______ ________ ________ _______ ________ ________ ________ ________ _______ ________ _________ ________ _______ ______ ________ 03-JAN-2006 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 04-Jan-2006 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 06-jan-2006 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 09-JAN-2006 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10-JAN-2006 0 0 0 0 0 0 0 0 0 0 0 0 00 0 11-Jan-2006 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12-jan-2006 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

类似于SMA,绘制单个资产的信号以预览交易频率。

绘图(macdSignal.Time,macdSignal.CAT_MACD)ylim([-0.5,1.5]);ylabel('MACD>0');头衔(sprintf('MACD > 0 for CAT'));

图中包含一个轴对象。具有标题Macd> 0的轴对象包含类型线的对象。

RSI:相对强度指数

RSI是捕捉动量的度量。一个常见的启发是当相对强弱指数低于时购买30.并在相对强弱指数上升时卖出70

rsisignalnameInning =.“_RSI”;rsisignal =时间表;I = 1:numel(symbols) symi = symbols(I);rsiValues = rsindex (pricesTT。(symi));rsiBuySell = 0(大小(rsiValues));rsiBuySell(rsiValues < 30) = 1;rsiBuySell(rsiValues > 70) = -1; / /买入%构建每个符号的时间表,然后将符号聚合在一起。rsiSignali=时间表(价格、日期、,......rsiBuySell,......'variablenames'{sprintf (' % s % s '、symi rsiSignalNameEnding)});rsiSignal =同步(rsiSignal rsiSignali);结束

RSI信号的值为1(表示买入信号)当股票的RSI值低于该值时30.这个信号takes a value of-1(表示卖出信号)当股票的相对强弱指数高于该值时70。否则,信号的值为0,表示没有动作。

绘制单个资产的信号以预览交易频率。

绘图(rsiSignal.Time,rsiSignal.CAT_RSI)ylim([-1.5,1.5]);ylabel(“RSI买入/卖出信号”);头衔(sprintf(CAT的RSI买入/卖出信号));

图中包含一个轴对象。标题为“CAT的RSI买/卖信号”的轴对象包含一个类型为line的对象。

制定战略

建立战略backtestStrategy对象中定义的rebalance函数本地函数部分。每种策略都使用再平衡函数,根据适当的信号做出交易决定。

信号需要足够的跟踪数据来计算交易信号(例如,计算SMA20为一天X要求价格从20天前的一天X).所有的跟踪数据都被捕捉到预先计算的交易信号中。因此,实际的策略只需要一个2天的回顾窗口来做出交易决策,以评估信号何时越过交易阈值。

所有的策略在买卖时都要支付25个基点的交易成本。

初始权值是根据20个交易日后的信号值计算的。回溯测试在20天初始化周期之后开始。

tradingCosts = 0.0025;%对两个SMA使用CrossOverRebalance功能%策略以及MACD策略。这是因为他们都是交易%在他们各自的信号相同的方式(当信号从% 0->1,当信号从1->0上升时卖出)。建立一个匿名方法调用的策略的rebalance函数% shared crossoverRebalanceFcn() with适当的信号名称字符串每个策略的百分比。%每个匿名函数取当前权重(w)、价格(p),来自反向发动机的%和信号数据并将其传递给带有信号名称字符串的% crosoverrebalancefcn函数。: smaInitWeights = computeInitialWeights (smaSignal(20日));smaRebalanceFcn = @(w,p,s) crossoverRebalanceFcn(w,p,s,smaSignalNameEnding); / /设置smaRebalanceFcn = @(w,p,s);smaStrategy = backtestStrategy ('sma'smaRebalanceFcn,......“TransactionCosts”tradingCosts,......“LookbackWindow”2.......“InitialWeights”, smaInitWeights);: macdInitWeights = computeInitialWeights (macdSignal(20日));macdRebalanceFcn = @(w,p,s) crossoverRebalanceFcn(w,p,s,macdSignalNameEnding); / /指定数据macdStrategy = backtestStrategy (MACD的,macdRebalanceFcn,......“TransactionCosts”tradingCosts,......“LookbackWindow”2.......“InitialWeights”,麦呢项链);%RSI策略使用其信号不同,在0-> 1上购买%过渡和卖出在0->-1过渡。这个逻辑被捕获%本地函数部分定义的rsiRebalanceFcn函数。rsiinitweights = computuminitialwuights(rsisignal(20,:));Rsistrategy = backteststygy(“肢体重复性劳损症”@rsiRebalanceFcn,......“TransactionCosts”tradingCosts,......“LookbackWindow”2.......“InitialWeights”,rsiinitweights);

设置,val

作为基准,该示例还运行一个简单的等权策略,以确定交易信号是否为资产的未来回报提供了有价值的见解。基准策略每四周重新平衡一次。

%相等权重策略不需要历史记录,因此将LookbackWindow设置为0。Benchmarkstrategy = BreaktestStaregy('基准',@equalWeightFcn,......“TransactionCosts”tradingCosts,......“RebalanceFrequency”, 20岁,......“LookbackWindow”, 0);

将每个单独的信号时间表聚合成一个单一的回测信号时间表。

结合三个信号时间表。signalTT =时间表;signalTT = synchronize(signalTT, smsignal); / /同步signalTT = synchronize(signalTT, macdSignal); / /同步signalTT = synchronize(signalTT, rssignal); / /同步

使用背测发动机要创建回溯测试引擎,然后使用runbacktest.运行回测。未投资现金的无风险收益率年化为1%。

%将基准策略和三个信号策略放入阵列中。=[基准策略smaStrategy macdStrategy rsiStrategy];%创建后台测试引擎。bt = backtestEngine(策略,“RiskFreeRate”,0.01)
bt = backtestEngine with properties:策略:[1x4 backtestStrategy] RiskFreeRate: 0.0100 CashBorrowRate: 0 rate convention: "Annualized" Basis: 0 InitialPortfolioValue: 10000 NumAssets: [] Returns: [] Positions: [] Turnover: [] BuyCost: [] SellCost: []

回溯测试策略

%在初始权重计算热身期结束时开始。startIdx = 20;%运行backtest。bt = runBacktest (bt、pricesTT signalTT,“开始”,startidx);

检查反向效果

使用杠杆绘制战略权益曲线,以可视化其在回溯测试中的表现。

Equitycurve(BT)

图中包含一个轴对象。标题为Equity Curve的轴对象包含4个类型为line的对象。这些对象代表基准、SMA、MACD、RSI。

如前所述,这些策略通常不是作为单独的交易信号使用的。事实上,这三种策略在2006年的表现要比简单的基准策略差。您可以使用每日资产头寸的区域图来可视化策略配置如何随时间变化。要做到这一点,使用assetAreaPlothelper函数,在本地函数部分。

strategyName ='基准';Assetareaplot(BT,StrategyName)

图中包含一个轴对象。具有标题基准位置的轴对象包含16个类型区域的对象。这些对象代表现金,AA,CAT,DIS,GM,HPQ,JNJ,MCD,MMM,MO,MRK,MSFT,PFE,PG,T,XOM。

结论

2006年下半年,广阔的股票市场有一个很好的看涨6个月,所有这三个战略都未能完全捕捉到现金的资本过多的资本。虽然这些策略都不是自己的策略,但这个例子演示了如何构建基于信号的交易策略并反向他们评估其性能。

本地函数

初始权重计算功能以及策略重新平衡功能遵循。

函数initial_weights = computeinitialwuights(信号)%根据最近的信号计算初始权重。Nassets =尺寸(信号,2);final_signal =信号{end ,:};buys = final_signal == 1;initial_weights = zeros(1,绞纱);initial_weights(buys)= 1/1/1/1/1。结束
函数new_weights = cross - verrebalancefcn (current_weights, pricesTT, signalTT, signalNameEnding)%信号交叉平衡功能。%构建与交叉信号对应的信号名称单元格数组。符号= pricesTT.Properties.VariableNames;= cellfun(@(s) sprintf()' % s % s ',s,signalNameEnding),符号,'统一输出', 错误的);%拿出策略的相关信号数据。crossoverSignals = signalTT (:, signalNames);%从我们当前的权重开始。new_weights = current_weights;卖出任何信号变为0的现有多头仓位。idx = cross cross signals {end,:} == 0;new_weights (idx) = 0;%找到新的交叉点(信号从0变为1)。idx=交叉信号{end,:}==1&交叉信号{end-1,:}==0;%打赌大小,分割可用资本在所有剩余资产,然后%仅投资新的积极交叉资产。这离开了一些未予投资之资金量,以供日后投资%零重量资产。availableCapital=1-总和(新权重);未投资资产=总和(新权重==0);新权重(idx)=availableCapital/未投资资产;结束
函数新加权=RSI再平衡FCN(当前加权、价格、信号)%买卖在1和-1平衡功能。signalNameEnding =“_RSI”%构建与交叉信号对应的信号名称单元格数组。符号= pricesTT.Properties.VariableNames;= cellfun(@(s) sprintf()' % s % s ',s,signalNameEnding),符号,'统一输出', 错误的);%拿出策略的相关信号数据。buySellSignals = signalTT (:, signalNames);%以当前的权重开始。new_weights = current_weights;卖出任何信号变为-1的现有多头仓位。idx = buysellsignals {end ,:} == -1;new_weights (idx) = 0;%找到新的购买(信号是1,而且当前0)。idx = new_weights == 0 & buySellSignals{end,:} == 1;%打赌大小,分割可用资本在所有剩余资产,然后%仅投资新的积极交叉资产。这离开了一些未予投资之资金量,以供日后投资%零重量资产。availableCapital=1-总和(新权重);未投资资产=总和(新权重==0);新权重(idx)=availableCapital/未投资资产;结束
函数new_weights =相等的frccn(current_weights,〜)%相等加权的投资组合分配。nAssets =元素个数(current_weights);nAssets new_weights = 1 (1);New_weights = New_weights / sum(New_weights);结束
函数资产批次(backtester,strategyName)%绘制资产分配面积图。t=backtester.Positions.(strategyName).Time;Positions=backtester.Positions.(strategyName).变量;h=区域(t,Positions);标题(sprintf('%s职位',strrep(StrategyName,“_”''))); xlabel(“日期”);ylabel('资产职位');dateTick(“x”'mm / dd''保持');Xlim ([t(1) t(end)]) oldylim = ylim;ylim ([0 oldylim (2)]);厘米= parula(元素个数(h));I = 1:numel(h) set(h(I),“FaceColor”厘米(我:));结束传奇(backtester.Positions (strategyName) .Properties.VariableNames)。结束

另请参阅

|||

相关的话题