股票聚类的基本原因就是从股市中选取一部股票进行投资。哪怕是上证50对一般的投资模型来说50条股票也太多了。
按照投资组合优化理论选取标准为:
(1)资产数越多越好
(2)资产之间相关系数越低越好
以期望收益E来衡量证券收益,以收益的方差
式中:
举个极端的例子:(以后再详细说吧,搞一个简单的例子)
有n个不相关的资产,其收益率都是r,风险都是v,优化后的投资比例应该是均分(还用优化吗……)
那资产组合的
收益:R = r
风险:V = v/n
聚类定义就不说了,经过对股票交易数据聚类后,可以将其分为几个类别,然后从每个类别中选一个样本,最后组成的样本可使样本之间的相关系数降至最低。
这样保证在一定的风险下使收益更高。
这里采用sklearn中affinity_propagation算法进行聚类。
dict_stock = {}
def ReadStocks(stock_file):
print 'read_stocks...'
f = open(stock_file, 'r')
for line in f.readlines():
# str_line = str(line)
item = line.strip().split(' ')
dict_stock[item[0]] = item[1]
f.close()
用QSTK API获取股票交易数据。
之前的文件已经介绍过了,这里提2点:
(1)验证股票代码是否正确,移除异常股票,不然QSTK会报错
db = DataAccess.DataAccess('Yahoo')
ls_all_syms = db.get_all_symbols()
ls_bad_syms = list(set(ls_stock_code) - set(ls_all_syms))
print 'Bad Stock Code : ', ls_bad_syms
for sym in ls_bad_syms:
ls_stock_code.remove(sym)
(2)对获取的数据进行清理,不然SKLearn会报错
# Filling the data for NAN
for s_key in ls_keys:
dict_data[s_key] = dict_data[s_key].fillna(method='ffill') dict_data[s_key] = dict_data[s_key].fillna(method='bfill') dict_data[s_key] = dict_data[s_key].fillna(1.0)
open = stock_data['open']
close = stock_data['close']
var = close - open
open, close, var的数据类型都是pandas DataFrame类型。
print type(open)
<class 'pandas.core.frame.DataFrame'>
print open.iloc[:3, 1:3]
600837.SS 600000.SS
2015-01-02 16:00:00 24.06 15.69
2015-01-05 16:00:00 23.82 15.94
2015-01-06 16:00:00 23.30 16.00
关于pandas的使用参考下:
十分钟搞定pandas
from sklearn import covariance, cluster
x = var/var.std(0)
edge_model = covariance.GraphLassoCV()
edge_model.fit(x)
centers, labels = cluster.affinity_propagation(edge_model.covariance_)
结果输出
n_labels = labels.max()
print 'Centers : \n', ', '.join( np.array(dict_stock.values())[centers] )
for i in range(n_labels + 1):
print('Cluster %i: %s' %
((i + 1), ', '.join([dict_stock[key]
for key in var.columns[labels == i]])))
这里比较了几种因子的聚类结果
(1)x = var*vol*10e-9/var.std(0)
Covariance : 1.26342386383e-04
海螺水泥, 东方明珠, 中国平安, 中国交建, 中航动力, 包钢股份, 民生银行, 青岛海尔
Cluster 1: 大秦铁路, 海螺水泥, 贵州茅台, 华泰证券, 中国太保, 伊利股份, 中国石油, 中国神华
Cluster 2: 东方明珠, 保利地产, 特变电工
Cluster 3: 中国交建, 广汇能源
Cluster 4: 海通证券, 浦发银行, 招商证券, 兴业银行, 中信银行, 中国中车, 中国银行, 光大银行, 农业银行, 中国石化, 北京银行, 中信证券, 招商银行, 交通银行, 包钢股份, 工商银行, 民生银行
Cluster 5: 上港集团, 康美药业, 方正证券, 中国船舶
Cluster 6: 海油工程, 中航动力, 东方证券, 华夏银行, 国电南瑞, 上汽集团
Cluster 7: 北方稀土, 国金证券, 青岛海尔
Cluster 8: 中国中铁, 中国人寿, 中国重工, 中国铁建, 中国联通, 中国建筑
(2)x = var*np.sqrt(vol*10e-8)/(var.std(0)*np.log2(close))
Covariance : 1.16200812467e-04
海螺水泥, 东方明珠, 中国平安, 光大银行, 中航动力, 包钢股份, 民生银行, 青岛海尔
Cluster 1: 大秦铁路, 海螺水泥, 华泰证券, 中国太保, 伊利股份, 中国石油, 中信证券, 中国神华
Cluster 2: 东方明珠, 保利地产, 特变电工
Cluster 3: 中国交建, 广汇能源, 中国铁建, 包钢股份
Cluster 4: 浦发银行, 兴业银行, 贵州茅台, 中信银行, 中国银行, 光大银行, 农业银行, 中国石化, 北京银行, 招商银行, 交通银行, 华夏银行, 工商银行, 民生银行
Cluster 5: 上港集团, 康美药业, 方正证券, 中国船舶
Cluster 6: 海通证券, 招商证券, 海油工程, 中航动力, 东方证券, 国电南瑞, 上汽集团
Cluster 7: 北方稀土, 国金证券, 青岛海尔
Cluster 8: 中国中铁, 中国人寿, 中国中车, 中国重工, 中国联通, 中国建筑
(3)x = var/var.std(0)
Covariance : 2.42169315704e-04
Cluster 1: 中国中车
Cluster 2: 海油工程, 中国重工, 中航动力, 中国船舶
Cluster 3: 东方明珠, 广汇能源, 特变电工, 国电南瑞
Cluster 4: 北方稀土, 贵州茅台, 伊利股份, 北京银行, 康美药业, 华夏银行, 上汽集团, 青岛海尔
Cluster 5: 中国中铁, 中国交建, 中国铁建, 中国联通, 中国建筑
Cluster 6: 海通证券, 招商证券, 中国人寿, 华泰证券, 中国太保, 中信证券, 方正证券
Cluster 7: 包钢股份, 国金证券
Cluster 8: 东方证券
Cluster 9: 大秦铁路, 浦发银行, 海螺水泥, 兴业银行, 中信银行, 中国银行, 光大银行, 农业银行, 中国石化, 中国石油, 保利地产, 上港集团, 招商银行, 交通银行, 中国神华, 工商银行, 民生银行