第 13 章 KNN 简单策略
机器学习算法是近年量化策略的热点,我们在这一章中通过一个简单的例子感受一下。
KNN 是机器学习中的一种算法,它的核心思想是:如果一个样本在特征空间中的 K 个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别。更通俗点说,KNN 可以找到和目标样本最相似的 K 个样本,然后根据其中的大多数来预测目标样本。
我们也可以用这种方法来预测股票的涨跌,构造一个特征空间然后在历史数据中找到和当日特征最相似的 K 个交易日数据,然后根据这 K 个交易日第二天的涨跌情况来预测第二天的涨跌(大多数涨就预测为涨,大多数跌就预测为跌)。
KNN 简单策略的具体方法如下:
1. 将第二天是否上涨作为预测目标,即计算收盘 [1]- 收盘,大于 0 时目标值为 1,小于 0 时为 -1,其余为 0。
2. 增加两个特征,最高价 - 最低价和收盘价 - 开盘价作为特征空间
3. 计算历史数据和当日样本特征之间的距离,距离越近越相似。具体为:计算当天样本特征和之前 n 个交易日的特征距离,找到距离最近的 m 个交易日数据,把这 m 个交易日目标值的众数作为第二天的预测结果。
计算距离的常用的方法有欧式距离和马氏距离,在 SPL 里有现成的函数 dis()和 dism(),这里我们用欧式距离来计算。
需要注意的是,在使用一些比较专业的数学函数时,需要打开 SPL 里的数学库。
工具→选项:
可以在文档外部库 -Math里查看数学库有哪些函数。
言归正传,我们同样先将 KNN 的计算方便编写为指标,再用指标写策略。
定义指标参数:
A |
序表,K线数据 |
y |
指标返回列。1上涨信号,-1下跌信号 |
n |
数字,计算和前n个交易日的特征距离 |
m |
数字,前m个距离最近的数据 |
在indicator.splx中编写指标函数:
A |
B |
|
… |
…… |
…… |
47 |
func KNNDIF(A, $y, n, m) |
=A.derive@o( [最高-最低,收盘-开盘]:KNNDIF1, sign(收盘[1]-收盘):KNNDIF2) |
48 |
=A.run(${y}=~[-n:-1].top(m; dis( KNNDIF1, A.KNNDIF1) ).(KNNDIF2).mode() ) |
|
49 |
=A.alter(; KNNDIF1, KNNDIF2) |
当 KNN 指标结果为 1 且空仓时,下买入订单;指标结果为 -1 且有持仓股票时,下卖出订单。n 和 m 分别取 100 和 20:
A |
B |
|
1 |
>call("init.splx") |
|
2 |
2024 |
=date(A2,1,1) |
3 |
=workday(B2,-110,HOLIDAY) |
=date(A2,12,31) |
4 |
600690 |
=Load@C(A4, A3,B3) |
5 |
||
6 |
=B4.derive(:KNN) |
|
7 |
=KNNDIF(A6, KNN, 100, 20) |
|
8 |
||
9 |
=Begin(A6) |
|
10 |
=A9.select(日期>=B2) |
|
11 |
for A10 |
=H=昨日.持仓 |
12 |
=卖出=if(昨日.KNN==-1,SellOff( ~, H,收盘 ) ) |
|
13 |
=if(昨日.KNN==1 && H.len()<=0, 买入|=Buy( ~,100,收盘)) |
|
14 |
=Loop() |
|
15 |
=Summary(A10) |
=Display(A15) |
回测结果:
看起来先进技术的效果也不见得更好。