基于MATLAB的股票聚类分池

2016-11-24 16:22李汶瑾
2016年32期

李汶瑾

摘 要:本文基于数值分析软件MATLAB采用层次聚类法对股票进行分池,以便指导对强盈利能力对象的投资。通过获取大智慧中的财务数据,以深证A股为例验证了该方法的可行性和有效性。通过分析不同聚类数目的聚类结果簇层次结构图和簇间相似结构图,发现聚成8类时可以较好的对各类股票进行区分。该分析方法对于建立量化投资模型具有较大的实用价值。

关键词:层次聚类;股票分池;量化投资

一、引言

最近数十年,量化投资已经成为全球资本市场发展的一个热点,成为继基本面分析和技术面分析之后的又一主流方法。由于在运用量化投资的过程中只利用公开数据,通过数学建模挖掘出公开数据中的隐藏信息,从而使得杜绝内幕消息、战胜市场成为可能[1]。

聚类是数据分析和量化投资中的一个重要手段和方法论,通过聚类可以对大量的潜在投资对象进行批量评估,从中筛选出盈利能力强的对象进行投资。由于MATLAB具有强大的数据分析能力,近年来常被用于股票分析[2]和风险管理[3]等方面。其统计与机器学习工具箱可以方便地进行聚类分析,因此可将其用于股票分池。

二、数据获取

本文以深证A股为例介绍股票分池的方法,通过MATLAB可以从大智慧中获取深证A股的最新财务数据。安装大智慧后将财务数据下载到本地,然后运行如下MATLAB程序将原始数据导出为Excel格式:

%%将数据读入matlab

file=′D:\\dzh365\\Download\\FIN\\full_sz.FIN′; %大智慧的安装路径‘D:\\dzh365

filesize=dir(file)

filesize=filesize.bytes

k=1847;%公司数目

fileid=fopen(file,′rb′);

fseek(fileid,8,′bof′);

for i=1:k

stkfin(i).code=sprintf(′%s′,fread(fileid,8, ′*char′));

fseek(fileid,4,′cof′);

a=fread(fileid,3,′int32′);

b=fread(fileid,48,′float32′);

stkfin(i).fin=[a;b];

fseek(fileid,8,′cof′);

end

fclose(fileid);

%%将数据转化成excel形式

fValue=zeros(k,51);

for i=1:k

fCode(i,1)={stkfin(i).code};

fValue(i,1:51)=stkfin(i).fin′;

end

%将数据保存到excel

xlswrite(′StockFinanceA.xlsx′,fCode,′sheet1′,[′A2:A′ num2str(i+1)]);

xlswrite(′StockFinanceA.xlsx′,fValue,′sheet1′,[′B2:AZ′ num2str(i+1)]);

%% end

获取的财务数据描述如表1所示。

三、聚类分池

表1从48个指标(列号5-52)对股票的财务状况进行了描述,若转化为数据点则为48维,人们无法直接对上千个股票的高维数据进行观察和判断,因此需要通过聚类算法对数据进行分析,发掘出现有数据中的隐藏信息,从而挑选出升值空间大的一类股票进行投资。层次聚类是通过将数据集划分为若干类并构成一个对应的树以进行聚类,根据层次形成的方向,层次聚类可以分为两类:凝聚型聚类算法和分裂型聚类算法。凝聚型算法为自底而上的策略,首先将每个数据点作为一个单独的簇,然后不断合并它们构成更大的簇,直到所有数据点都在同一个簇中,或者到达某个终止条件。分裂型算法则与凝聚型算法相反,将所有数据点归于一个簇中,然后逐步细分为多个小簇。本文拟采用凝聚型算法,通过MATLAB统计与机器学习工具箱的内置函数进行编程,代码如下:

%%读取数据

clc, clear all, close all

X0= xlsread(′StockFinance.xlsx′,′Sheet1′,′E2:N1848′);

%%数据归一化

[rn,cn]=size(X0);

X=zeros(rn,cn);

for k=1:cn

%基于均值方差的离群点数据归一化

xm=mean(X0(:,k));

xs=std(X0(:,k));

for j=1:rn

if X0(j,k)>xm+2*xs

X(j,k)=1;

elseif X0(j,k)

X(j,k)=0;

else

X(j,k)=(X0(j,k)-(xm-2*xs))/(4*xs);

end

end

end

xlswrite(′norm_data.xlsx′, X);

%%层次聚类

numClust = 3; %假设聚成3类

dist_h = ′spearman′;

link = ′weighted′;

hidx = clusterdata(X, ′maxclust′, numClust, ′distance′ , dist_h, ′linkage′, link);

%绘制聚类效果图

figure

F2=plot3(X(hidx==1,1), X(hidx==1,2),X(hidx==1,3),′r*′, …

X(hidx==2,1), X(hidx==2,2),X(hidx==2,3), ′bo′, …

X(hidx==3,1), X(hidx==3,2),X(hidx==3,3), ′kd′);

set(gca,′linewidth′,2);

grid on

set(F2,′linewidth′,2, ′MarkerSize′,8);

set(gca,′linewidth′,2);

xlabel(′每股收益′,′fontsize′,12);

ylabel(′每股净资产′,′fontsize′,12);

zlabel(′净资产收益率′,′fontsize′,12);

title(′层次聚类方法聚类结果′)

%评估各类别的相关程度

dist_metric_h = pdist(X,dist_h);

dd_h = squareform(dist_metric_h);

[~,idx]= sort(hidx);

dd_h = dd_h(idx,idx);

figure

imagesc(dd_h)

set(gca,′linewidth′,2);

xlabel(′数据点′, ′fontsize′,12)

ylabel(′数据点′, ′fontsize′,12)

title(′层次聚类结果相关程度图′)

ylabel(colorbar,[′距离矩阵:′, dist_h])

axis square

%计算同型相关系数

Z = linkage(dist_metric_h,link);

cpcc = cophenet(Z,dist_metric_h);

disp(′同表象相关系数:′)

disp(cpcc)

%层次结构图

set(0,′RecursionLimit′,5000)

figure

dendrogram(Z)

set(gca,′linewidth′,2);

set(0,′RecursionLimit′,500)

xlabel(′数据点′, ′fontsize′,12)

ylabel (′距离′, ′fontsize′,12)

title([′CPCC:′ sprintf(′%0.4f′,cpcc)])

运行程序后得到同表象相关系数为0.4371,这个值描述了聚类树信息和原数据距离之间的相关性,值越大越好。簇的层次结构图如图1所示。

从图1可见,聚成6类时距离跨度比较大,聚类效果可能较好。为验证这一点,图2比较了分别聚类为3类、5类、6类和8类时的簇间相似程度图。可见聚为6类时各类别的轮廓更清晰和直观,类间的区分更明显。因此,选择聚类数目为6类。

48个指标对于聚类结果都会产生影响,但每个指标的影响程度有差异。由于无法对超过三维的数据点在三维直角坐标系中进行作图,因此下面只选取3个指标做出聚类结果效果图,以此观察不同指标在聚类中所起的作用大小。图3和图4为聚类效果图,分别选取了不同的Z轴指标。通过比较两图可以发现,图4中股东权益比的维度上可以产生更为显著的分层,聚类的效果更清晰。

四、结论

本文基于MATLAB采集了大智慧深证A股的财务数据,通过层次聚类对股票进行分池,该算法可以清楚地提供股票的层级结构,对于指导中长线股票投资具有较大的参考价值。(作者单位:西南财经大学会计学院)

参考文献:

[1] 卓金武,周英.量化投资——数据挖掘技术与实践(MATLAB版)[M].北京:电子工业出版社,2015.

[2] 段新生.MATLAB股票股价模型研究[J].中国管理信息化,2007(10):78-81.

[3] 基于PCA-BP的PPP基础设施项目风险评价研究[J].会计之友,2016(7):56-59.