股票价格形态聚类

本文探讨了如何通过聚类分析股票价格形态,提取关键价格点并进行特征映射,降低数据维度。使用KNN模型进行训练,根据聚类结果设计量化投资策略,实现在优矿平台上的回测显示,相对于基准HS300存在alpha收益。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景介绍

投资者通过实战经验,总结出了各种各样的股票价格走势形态以辅助投资决策。比如常见的头肩形、倒头肩形、三重顶、三重底、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<
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值