一、聚类(无监督学习)
相信每一个投资者都明白“不要把鸡蛋放在同一个篮子”的投资道理。股市看似“各自为政”,但实际上,看似完全无关的股票是相关的。那么为了规避风险,将相关性极强的股票加以归类则十分重要。
选择对多支股票数据聚类分析,意义:经过对股票交易数据聚类(把整体形态比较相似的聚为一类)后,可以将其分为几个类别,然后从每个类别中选一个样本,最后组成的样本可使样本之间的相关系数降至最低。 这样保证在一定的风险下使收益更高。
按照投资组合优化理论选取标准为:
(1)资产数越多越好
(2)资产之间相关系数越低越好
以期望收益E来衡量证券收益,以收益的方差δ^2表示投资风险
minδ2(rp)=∑∑wiwjcov(ri,rj)minδ2(rp)=∑∑wiwjcov(ri,rj)
E(rp)=∑wiriE(rp)=∑wiri
式中:
rp——组合收益;
riri——第i种、第j种资产的收益;
wiwi——资产i和资产j在组合中的权重;
δ2(rp)——组合收益的方差即组合的总体风险;
cov(r,rj)——两种资产之间的协方差。
二、思路
- 研究聚类方法,寻找适合处理自己数据的聚类方法,最终敲定DBSCAN
- 基于DBSCAN对于参数设定的敏感性,参考知网论文《DBSCAN 聚类算法的参数配置方法研究》
- 对聚类结果分析并应用于自己的数据
三、数据预处理
- 对多只股票对应的csv文件进行合并 merging.csv
from numpy import nan as NA
import numpy as np
import pandas as pd
import glob
csv_list = glob.glob('*.csv')
for i in csv_list:
fr = open(i,'rb').read()
with open('result.csv','ab') as f:
f.write(fr)
注意合并后的result.csv文件含有多个表头行,可以利用excel的筛选功能对多余的表头行进行删除
- 合并后产生result.csv文件,依次运行data_clustering_parameter.py(确定两个重要阈值Eps、Minpts)和data_cluser.py(查看聚类结果)
- 聚类因子——以name为groupby单位,每支股票的收盘价和成交量方差
四、聚类分析(对某支股票其中两列——开盘价、成交量进行聚类分析)
- 对DBSCAN参数探索的源码data_clustering_parameter.py(参考知网论文《DBSCAN 聚类算法的参数配置方法研究》)
import numpy as np
import numpy.linalg as la
import pandas as pd
import seaborn as sns
#import matplotlib.pyplot as plt
import datetime
#分块读入文件避免Memory Error
#f = open('result.csv',mode = 'r+',encoding = 'UTF-8')
#data = pd.read_csv(f,sep=',',engine = 'python',iterator=True,parse_dates = True)
#loop = True
#chunksize = 1000
#chunks = []
#index=0
#while loop:
# try:
# print(index)
# chunk = data.get_chunk(chunksize)
# chunks.append(chunk)
## print(chunks)
# index+=1
#
# except StopIteration:
# loop = False
# print("Iteration is stopped.")
#print('开始合并')
#data0 = pd.concat(chunks)
#data0 = pd.DataFrame(data0,columns = ['日期','股票代码','名称','收盘价','最高价','最低价','开盘价','前收盘','涨跌额','涨跌幅','换手率','成交量','成交金额','总市值','流通市值'])
#print(data0) #日期是float64类型
f = open('result.csv',encoding = 'UTF-8')
data0 = pd.read_csv(f,header = 0)
start = datetime.datetime.now()
data = np.array(data0[['name','close','volume']])
print(data)
#求收盘价一列以及成交量一列的协方差
df = pd.DataFrame(data,columns=["name", "close", "volume"])
#df.set_index(["名称"], inplace=True)
df = df.convert_objects(convert_numeric=True)
print(df)
#grouped = df['close'].groupby(df['name'])
grouped1 = df.groupby('name').close.var()
grouped2 = df.groupby('name').volume.var()
print(grouped1)
print(grouped2)
#print(grouped.dtype)
#元组为元素的列表
#data = [(data[i][0],data[i][1]) for i in range(0,len(data))]
data = pd.DataFrame([grouped1,grouped2]).T
data = np.array(data)
#data0 = data0.convert_objects(convert_numeric=True) #把dataframe各列由object转换为各自对应的数据类型
#print(data0.dtypes)
#data = np.array(data0[['收盘价','成交量']])
#计算距离矩阵
def compute_squared_ED_method(X):
m,n = X.shape
#初始化距离矩阵
D = np.zeros([m, m])
for i in range(m):
for j in range(i, m):
D[i,j] = la.norm(X[i] - X[j])
D[j,i]