SPL 量化系列实践:KNN 简单策略

交易策略如下:

1. 把第二天是否上涨作为目标(target),收盘价大于前一天,target1,否则target-1

2. 增加两个特征,最高价减最低价(max_dif,收盘价减开盘价(co_dif)。

3. 选择2023年的股价作为预测对象,计算当天的两个特征(max_difco_dif)与之前660个交易日的特征距离,找到距离最近的95个交易日,把这95个交易日的target的众数作为第二天涨跌的预测结果(predict),预测涨则为1,否则为-1

4. predict=1且空仓时,下买入订单;predict=-1且有持仓股票时,下卖出订单。据此生成下单信号(flag),flag=1为买入,flag=-1为卖出,flag=0为不操作。

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

=A4.derive(round(hfq_high-hfq_open,2):max_dif,round(hfq_close-hfq_open,2):co_dif,if(!hfq_close[1],,if(hfq_close[1]>hfq_close,1,-1)):target)

6

=n=95

7

=ps=0

8

=A5.derive(if(trade_date<20230101,null,(train=~[-660,-1].([max_dif,co_dif]),rtarget=~[-660:-1].(target),v=[max_dif,co_dif],rtarget(train.ptop(n,dis(~,v))).mode())):predict,if(ps==0&&predict==1,(ps=1,1),if(ps!=0&&predict==-1,(ps=0,-1),0)):flag,if(flag!=0,100,0):shares)

9

=A8.select(predict)

A4:对股价进行复权,包括开、高、低、收。

..

A5:计算2个特征和目标变量。

..

A8:计算2023年的预测结果(predict),并根据预测结果和是否有仓位确定买卖信号(flag),每次买卖都是100股。

..

A9:筛选出predict不为null的数据。

SPL虽然没有提供现成的KNN算法,但实现起来并不复杂,只要一句话rtarget(train.ptop(n,dis(~,v)).mode()就能实现,像KNN这种简单的算法,SPL虽然要手动编码,但好在自由,能够根据需要设置参数和优化算法,而Python的第三方库是现成的算法库,参数设置有点烦,想要优化算法几乎不可能,还是要自己编码来完成。

根据A9的数据画出买卖信号图:

..

红色圆点是买入点,绿色方点是卖出点。

和《海龟策略》一样,计算出flag后就可以回测了,过滤出A13数据中flag不为0的行,调用回测接口即可。

回测收益率图如下:

..

回测指标见下表:

indicators

value

累计收益率 (cumulative rate of return)

5.54%

年化收益率 (annualized rate of return)

5.77%

年化波动率 (annual volatility)

15.59%

夏普比率 (sharpe ratio)

0.18

最大回撤 (maximum drawdown)

14.63%

投入现金 (cash invested)

40425.29

总资产 (total assets)

42664.29

仓位占比 (stock holding ratio)

0.0%

盈利次数 (profit times)

18

亏损次数 (losses times)

18

这里要说明一下,年化收益率是按每年252个交易日来算的,具体到某一年可能少几天也可能多几天,而且本例中第一次买入的时间是2023120日,所以年化收益率和累计收益率不同。