股票策略回测的框架、实现、测试——以动量策略为例
2015-06-29 10:28阅读:
股票策略回测的框架、实现、测试——以动量策略为例
不同于期货品种(国内目前大概上市的期货品种50个左右),股票的标的众多(A股目前大概2700只左右),然而不管说选股还是择时,交易策略都可以抽象为一个从行情序列到资金曲线的映射:
f(ts,para) = E
即f是一种规则,给出了一些交易信号规定了在T时刻使用P价格买卖Amount数量的某种投资标的ts,para是交易系统的参数组(规则的生成方式),E是资金曲线。
股票的回测框架可以如下描述:
Data Generator -> Singal Generator
-> BackTest Modular -> Investment Performance
Metrics
细节层面,其中:
r>
数据Data
Generator模块中,需要支持不同种类、不同来源、不同格式的数据,在Data
Generator中将数据格式统一定义,方便后续模块的调用。
信号Singal
Generator模块中,这块是开放给用户自行开发的,无外乎按照其交易规则产生买卖信号(比如1买、-1卖、0空仓或其他确定的量化定义)。
回测BackTest
Modular模块中,先回想回测的目的:尽可能真实地还原实际交易过程,进而检测策略的表现!回测中一定要避免未来数据的使用(即要用T日之前产生的信号来指导T日的交易),还有进行买卖时,对于涨停、跌停、停牌等状态,需要按照交易实际做一些相关处理,这里给出一种参考的处理方式:
(1)“买入时涨停状态”:若某只股票当天需要买入时,产生了某种定义的涨停状态(比如一字涨停或者开盘涨幅超过9.8%),实际交易中大概率是买不到的,所以在回测中需要剔除该只股票。
(2)“买入时跌停状态”:若某只股票当天需要买入时,产生了某种定义的跌停状态,实际交易中是不应该买的,所以在回测中需要剔除该只股票。
(3)“买入时停牌状态”:若某只股票当天需要买入时,当日停牌,这种情况可以设定一个时间参数N1,允许推迟买入,如果停牌交易天数超过N1,则剔除此股票。
(4)“卖出时涨停状态”:若某只股票当天需要卖出时,产生了某种定义的涨停状态,这种情况可以设定一个时间参数N2,即延迟卖出,多持有几天,以期再抓几个涨停;若在延迟卖出N2天数内,发生了跌停或停牌状态,则进行“卖出时跌停状态”或“卖出时停牌状态”处理方式(见下面)。
(5)“卖出时跌停状态”:
若某只股票当天需要卖出时,产生了某种定义的跌停状态,则只能延迟卖出,一旦跌停打开就卖出;但若出现涨停状态,则进入“卖出时涨停状态”处理方式。
(6)“卖出时停牌状态”:
若某只股票当天需要卖出时,当日停牌,则只能延迟卖出,一旦复牌就卖出;但若出现复牌涨停状态,则进入“卖出时涨停状态”处理方式。
上面的处理方式仅作参考,且后面的(4)(5)(6)有一定的逻辑缺陷,即若一只股票出现涨停、跌停、涨停、跌停或涨停、停牌、涨停、停牌等等几种“变态”模式时,(4)(5)(6)会出现一定的逻辑死循环,但事实上上面的几种“变态”模式,实际中几乎不会出现,但为了避免这种死循环,可以适定一个持股时间阈值来跳出死循环。
绩效指标Investment Performance
Metrics模块中,需要实现多种评价指标的计算,且图形和数据可以自动保存至指定的文件夹,方便回测结果的后续查看对比。
还有其他一些细节的东西,比如回测BackTest
Modular模块中,需要给出一个AcountTotal来记录整体组合的绩效收益情况用来监控整体风险,还需要给出AcountSub来记录初始股票池中每一只股票的绩效收益情况用来监控单一个股的风险。
手续费和冲击成本的默认设置为:
手续费(包括印花税等等)双边分别计算千分之一(即入场千分之一,离场千分之一);
冲击成本双边分别计算1bp(即入场1bp,离场1bp)。
下面以一个动量策略为例,看下回测平台的实现结果。
测试策略:动量策略
策略简介:按照过去LookBack(20)个交易日收益率排序,并且选择前Snum(50)个的股票作为买入候选,调仓频率RefreshRate(20)个交易日。
测试股票池:沪深300。
测试对比标的:000300.SH。
测试周期:2010年至今
测试代码:
%% Main_FQBKT_Momentum %
按照过去LookBack日收益率排序,并且选择前Snum个的股票作为买入候选 % by
LiYang_faruto % Email:farutoliyang@foxmail.com
% 2015/07/01 %% A Little Clean Work
tic; % clear; %
clc; % close all; format
compact; %% FQBKT
fBKT = FQBKT();
%% GetData run =
1; if 1
== run
fBKT.Benchmark
= '000300.SH';
fBKT.Universe_Mode
= 0;
fBKT.Universe =
{'HS300';};
Flag = 0;
[PoolFileStr,BenmarkFileStr]
=
fBKT.SaveData2Local(Flag);
load(PoolFileStr);
load(BenmarkFileStr);
end %% 参数设置
fBKT.ParaStra_StraName
= '测试策略-Momentum'; % %
离场模式参数选择 % 0 RefreshRate通过定期调仓离场 % 1
使用InputSignal自带的离场信号离场 %
InputSignal:1-做多;-1-做空;0-空仓
fBKT.Exist_Mode
= 1;
fBKT.isDebug =
1; % 初始资金
fBKT.Capital_base
= 1e6;
fBKT.RiskFreeRate
= 4e-2; % 调仓频率
fBKT.RefreshRate
= 20;
fBKT.StockNumMax
= 50;
fBKT.SimPara_SusDayMax
= 5;
fBKT.SimPara_SellUpLimitDayOffset
= 10; %%
数据清洗、时间轴对齐
fBKT.StartDateTest
= '20100101';
[tStockData,tBenchmarkData]
= ...
fBKT.DataCleanCalibration(StockDataRaw,BenchmarkData);
%% 初始交易信号生成
fBKT.isPlot =
0;
Para.LookBack =
20;
Para.Snum =
fBKT.StockNumMax;
TSignal =
fBKT.SignalMomentum(tStockData,
Para); %% 进行回测 % %
离场模式参数选择
fBKT.Exist_Mode
= 0 % 调仓频率
fBKT.RefreshRate
= 20;
fBKT.ParaStra_StraName
=
['测试策略-Momentum-LookBack',num2str(Para.LookBack),
...
'Hold',num2str(fBKT.RefreshRate),'-',fBKT.StartDateTest,'-',fBKT.EndDateTest];
InputSignal =
TSignal; InputStockData
= tStockData;
InputBenchmarkData =
tBenchmarkData; bktTradeStat
= ...
fBKT.BackTest(InputSignal,InputStockData,InputBenchmarkData);
%% 回测报告生成
fBKT.isPlot =
1;
fBKT.isSave =
0; % fBKT.XDateFormat =
'DateTime';
fBKT.XDateFormat
= 'PureDouble';
bktReport =
fBKT.Report(bktTradeStat);
%% Record Time toc;
displayEndOfDemoMessage(mfilename);
测试结果:
整体的测试结果的图片和数据会自动保存至FQReport文件夹内按照策略名字生成的一个文件夹内:
通过可以看到动量因子还是蛮有效的,但每一个因子都有其轮动周期和强弱区间,动量因子也不例外,在其局部失效期,动量因子整体的回测也是挺大的。
至此本篇结束,大致介绍了股票策略回测的框架、实现细节,并用一个动量策略为例展示了回测平台的实现结果。