背景介绍
投资者通过实战经验,总结出了各种各样的股票价格走势形态以辅助投资决策。比如常见的头肩形、倒头肩形、三重顶、三重底、M头、W底等。
然而投资者的经验是有限的,特别是新进股市的投资者。进一步地,常用的股票形态已经为广大投资者熟知,一定程度上降低了这些形态的有效性。同时,一些新的形态或许隐藏在其中而没有被发现。本策略通过提取价格形态特征,采用聚类分析的方法,对其形态特征数据进行自动聚类分析,并根据聚类的结果计算每类股票未来持有期为一个月的平均收益率。然后将类平均收益率排名前5的股票记为+1类,其余股票记为-1类,作为训练样本,采用KNN模型进行训练。最后,利用训练好的KNN模型对新的股票价格形态特征数据进行预测。如果预测结果为+1,表示该只股票在未来一个月内会得到较好的投资回报率,即设计一个量化投资策略:以未来一个月为持有周期,以期初收盘价买入,期末收盘价卖出,计算其收益率。
特征工程
由于用于聚类的股票价格数据周期取三个月,其交易日期一般都在60个以上,如果以收盘价数据直接进行聚类,则数据维度较高。特别地如果周期取半年、一年或者更长,其维度更高,会严重影响聚类的效果,因此在进行聚类之前需要做降维处理。降维的方法则是取能代表股票价格走势的关键价格点,并基于提取的关键价格点计算股票价格走势形态特征,从而进行聚类。这里关键价格点的提取是关键,下面详细介绍关键价格点的概念、提取算法和形态特征的计算方法。
关键价格点
- 关键价格点的概念和提取方法
- 输入:原始价格序列x=(x1,x2,……,xp),提取关键点个数num
- 输出:关键价格点序列、对应下标序列
step1:对x2,……,x(p-1),按公式计算其与相邻两个价格点均值的绝对值大小,并按从大到小进行排序,取排名前num-2对应的价格点,记为L1,对应的下标序列记为S1.
step2:记x1,xp对应的价格点记为L2,对应的下标序列记为S2;
step3:记L=L1∪L2,S=S1∪S2,并按S进行从小到大进行排序,则L即为关键价格点序列,S即为对应的下标序列。
def getKeyData(price, num):
value = price.values
#计算x2,……,x(p-1)各点减去相邻两点平均值的绝对值
abs_value = abs(value[1:len(value)-1] - (value[0:len(value)-2]+value[2:len(value)])/2)
sd = pd.Series(abs_value, index=range(1, len(value)-1)).sort_values(ascending=False)
l1 = sd[:num-2]
l2 = pd.Series([value[0], value[-1]], index=[0, len(value)-1])
l = l1.append(l2)
keyData = price[l.index].sort_index()
return keyData
# 绘图测试
p = stock[63]['closePrice']
keyData = getKeyData(p, 20)
plt.plot(p)
plt.plot(keyData.index, keyData.values, '-')
plt.scatter(keyData.index, keyData.values)
特征映射
关键价格点的提取降低了维度,但是直接用价格点进行聚类还是存在较大的误差,因此我们需要对关键价格点的走势情况进行特征化表示,采用两个关键价格点之间连线的斜率来确定其涨跌情况,即特征化表示为两个关键点连线之间的夹角的tan值,其映射关系如下:
•上涨幅度大: tan值>0.5
•上涨幅度较大: tan值介于0.2~0.5之间
•上涨: tan值介于0.1~0.2之间
•平缓: tan值介于-0.1~0.1之间
•下跌: tan值介于-0.2~-0.1之间
•下跌幅度较大: tan值介于-0.5~-0.2之间
•下跌幅度大: tan值<-0.5
•分别记为: 7、6、5、4、3、2、1
def getFeature(keyData):
x1 = keyData.index[1:]
x2 = keyData.index[0:-1]
y1 = keyData.values[1:]
y2 = keyData.values[0:-1]
tan = list((y2-y1) / (x2-x1))
tan = np.array(tan)
T = np.where(tan>=0.5, 7
, np.where(tan>=0.2, 6
, np.where(tan>=0.1, 5
, np.where(tan>=-0.1, 4
, np.where(tan>=-0.2, 3
, np.where(tan>=-0.5, 2, 1))))))
return T
对聚类效果的可视化分析
def getKeyDataDF(stock, num):
'''
功能:用于生成训练聚类模型的特征矩阵。
Parameters
----------
stock : dict
{ticker:str : stockPrice:Series}.
num : int
聚类个数。
Returns
-------
keyData_df : DataFrame
列名为[ticker, f1, ..., fnum].
keyData_index : DataFrame
用于绘图.
'''
keyData_df = np.zeros((len(stock.keys()), num))
keyData_index = np.zeros((len(stock.keys()), num+1))
for<