SPL 量化系列实践:趋势交易策略

股价在上涨时通常会形成趋势,如果能抓住这些趋势,通常会带来不错的收益,本文就介绍一种常见的趋势交易策略。

在介绍买入策略之前先定义一些名词:

1. 最近的波谷:股价低于之前和之后 N 天的股价。

2. 波谷前的波峰:最近的波谷之前股价高于之前和之后 N 天的股价。

买入策略:

1. 最近的波谷低于最近 M 天股价的 5 分位;

2. 当天的股价高于波谷前的波峰;

同时满足上述两个条件,买入信号 signal=1。

..

卖出策略:

1. 股价低于最近的波谷。

2. 收益率超过 R。

满足上述两个条件中的任何一个,卖出信号 signal=-1。

..

SPL 代码


A B C
1 =file("daily/300750.csv").import@tc()
2 =A1.select(trade_date>=20200101&&trade_date<=20240506)
3 =A2.derive(if(#>1, close/ pre_close *factor[-1], close/pre_close):factor)
4 =hfq_fst=A3(1),A3.derive(round(factor/hfq_fst.factor*hfq_fst.close,2): hfq_close)
5 =A4.(hfq_close)
6 =windown=252
7 =extrem_itv=3
8 =inrate=0.5
9 =to(windown+1,A4.len())
10 =[]
11 for A9 =A5.to(A11-windown+1,A11)
12
=B11.median(:5).~
13
=B11.pselect@z1(#<=windown-extrem_itv&&~<~[-extrem_itv:-1].min()&&~<=~[1,extrem_itv].min())
14
=B11(B13)
15
=B11.pselect@z1(#<=B13&&~>~[-extrem_itv:-1].max()&&~>=~[1:extrem_itv].max())
16
=B11(B15)
17
=A5(A11)
18
if B14<B12&&B17>B16 =A10.insert(0,1)
19
else if B17<B14 =A10.insert(0,-1)
20
else =A10.insert(0,0)
21 =ps=0,bprice=0,A4(A9).derive(A10(#):signal,if(ps==0&&signal==1,(ps=1,bprice=hfq_close,1),if(ps!=0&&(signal==-1||hfq_close/bprice>1+inrate),(ps=0,-1),0)):flag,if(flag!=0,100,0):shares)

A4:复权收盘价。

..

A6-A8:设置参数,本例中N=3M=252R=0.5

A11代码块:从第253天循环,当满足买入条件时,记录signal=1,满足卖出条件时,记录signal=-1,因为这里无法确定具体的买入点,所以无法计算收益率,signal这一信号不包含收益率超过R的卖出点。

A21:利用买卖信号signal,并计算出下单信号flag和下单量(100股),当空仓且signal=1时,flag=1买入;当signal=-1或收益率超过50%且有仓位时,flag=-1卖出。

..

SPL不仅拥有书写便捷的循环函数,也可以像PythonJava等语言那样用for循环完成复杂的循环计算,比如本例中的A11代码块,可以在循环中清楚的写出每一个计算步骤,完成计算任务。

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

..

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

过滤出A21数据中flag不为0的行,调用回测接口即可得到回测收益率图和回测指标。

回测收益率图:

..

回测指标:

indicators value
累计收益率 (cumulative rate of return) 6.78%
年化收益率 (annualized rate of return) 3.5%
年化波动率 (annual volatility) 23.08%
夏普比率 (sharpe ratio) 0.02
最大回撤 (maximum drawdown) 37.34%
投入现金 (cash invested) 43355.99
总资产 (total assets) 46294.99
仓位占比 (stock holding ratio) 83.11%
盈利次数 (profit times) 2
亏损次数 (losses times) 8