SPL 量化系列实践:线性回归策略
股市中,当天的股价和前几天的股价可能存在线性关系,据此我们制定策略如下:
1. 把当天之前100天的数据作为训练数据;
2. 训练数据中,每天的后一天的收盘价作为目标变量;
3. 训练数据中,每天的最近的M天开、高、低、收价作为特征;
4. 对这些特征做PCA主成分分析,提取前4个主要成分;
5. 用训练数据中的主成分和目标变量做线性回归,得到线性模型;
6. 用线性模型对最近M天的数据的主成分进行预测,得到y_predict;
7. 如果y_predict>当天的收盘价,则标记为买入信号(signal=1);否则标记为卖出信号(signal=-1);
8. 当signal=1且空仓时,下买入订单;signal=-1且有持仓股票时,下卖出订单。据此生成下单信号(flag),flag=1为买入,flag=-1为卖出,flag=0为不操作。
本例中M取5。
SPL代码
A |
|
1 |
=file("daily/300750.csv").import@tc() |
2 |
=A1.select(trade_date>20200101&&trade_date<=20231231) |
3 |
=A2.derive(if(#>1, close/ pre_close *factor[-1], close/pre_close):factor) |
4 |
=hfq_fst=A3(1),A3.derive((fcls=factor/hfq_fst.factor*hfq_fst.close,c=fcls/close,round(c*open,2)): hfq_open,round(c*high,2): hfq_high,round(c*low,2): hfq_low,round(fcls,2): hfq_close) |
5 |
=M=5 |
6 |
=trdata=100 |
7 |
=A4.([~[-M+1:0].conj([hfq_open,hfq_high,hfq_low,hfq_close]),~[1].hfq_close]) |
8 |
=A4.pselect@a(trade_date>=20230101) |
9 |
=A7.calc(A8,(data=~[-trdata,-1],train=data.(~(1)),pc_res=pca(train,4),pc=pca(train,pc_res),target=data.(~(2)),model=linefit(pc.(~|1),target),pdata=[~(1)],pc_pdata=pca(pdata,pc_res),round(mul(pc_pdata.(~|1),model),2))) |
10 |
=ps=0,A4(A8).derive(A9(#):predict,if(predict>hfq_close,1,-1):signal,if(ps==0&&signal==1,(ps=1,1),if(ps!=0&&signal==-1,(ps=0,-1),0)):flag,if(flag!=0,100,0):shares) |
A4:对股价进行复权,包括开、高、低、收。
A7:整理特征数据和目标变量。
A9:时间滚动计算,用之前100天的数据训练,包括PCA主成分分析和线性回归,然后用前M天的数据预测,得到后一天的预测股价。
注意:SPL对序运算进行了精心设计,比如A9中的calc()方法就是在找到2023年的索引后,对每一天的数据进行PCA分析并建立模型,从而预测出后一天的收盘价。这一过程中还用到了[]获取相邻数据,可以便捷的完成算法的书写,避免书写繁杂的for循环,这是Python等语言所不能的。
A10:利用预测股价计算买卖信号signal,并计算出下单信号flag和下单量(100股)。
根据A10的数据画出买卖信号图:
红色圆点是买入点,绿色方点是卖出点。
和《海龟策略》一样,计算出flag后就可以回测了,过滤出A10数据中flag不为0的行,调用回测接口即可。
回测收益率图如下:
回测指标见下表:
indicators |
value |
累计收益率 (cumulative rate of return) |
-6.24% |
年化收益率 (annualized rate of return) |
-6.52% |
年化波动率 (annual volatility) |
18.4% |
夏普比率 (sharpe ratio) |
-0.52 |
最大回撤 (maximum drawdown) |
22.35% |
投入现金 (cash invested) |
44255.45 |
总资产 (total assets) |
41493.28 |
仓位占比 (stock holding ratio) |
71.29% |
盈利次数 (profit times) |
29 |
亏损次数 (losses times) |
30 |