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为不操作。

本例中M5

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