使用tushare我们可以获取上证50成分股历史数据,使用covariance对其历史数据进行聚类分析,我们可以得到其相关强度,对此,在其相关股价显著变化的时候,我们就可以根据其相关性进行套利赚钱。当然这只是理论分析而已。
tushare工具:http://tushare.org/
结果分析:
Cluster 1: 中国石化, 中国石油
Cluster 2: 保利地产, 华夏幸福
Cluster 3: 山东黄金
Cluster 4: 恒瑞医药, 贵州茅台, 青岛海尔, 伊利股份
Cluster 5: 中信证券, 万华化学, 东方证券, 招商证券, 国泰君安, 华泰证券
Cluster 6: 宝钢股份, 海螺水泥, 中国神华
Cluster 7: 中国联通, 中国铁建, 中国中铁, 中国建筑, 中国中车, 中国交建
Cluster 8: 上海银行
Cluster 9: 三六零
Cluster 10: 招商银行, 中国平安, 新华保险, 中国太保, 中国人寿
Cluster 11: 浦发银行, 民生银行, 上汽集团, 大秦铁路, 兴业银行, 北京银行, 农业银行, 交通银行, 工商银行, 光大银行, 中国银行
Cluster 12: 浙商证券, 中国银河
Cluster 13: 南方航空, 北方稀土, 绿地控股, 三安光电, 中国重工, 洛阳钼业结果分析:
绘图:
源码(供参考):
from __future__ import print_function import sqlite3 import sys from datetime import datetime import time import pandas as pd import numpy as np import matplotlib.pyplot as plt from matplotlib.collections import LineCollection from six.moves.urllib.request import urlopen from six.moves.urllib.parse import urlencode from sklearn import cluster, covariance, manifold global eng plt.rcParams['font.sans-serif'] = u'STKAITI' plt.rcParams['axes.unicode_minus'] = False start_date = datetime.strptime("2015-06-29", "%Y-%m-%d") end_date = datetime.strptime("2018-06-29", "%Y-%m-%d") eng = sqlite3.connect("C:\\Users\\humingj\\Desktop\\jhm\\scrapetest\\mydb.db") symbol_dict = pd.read_sql('select code,name from list_shang_zheng_50', eng) #symbol_dict = pd.read_sql('select code,name from list_hu_shen_300', eng) symbols, names = np.array(symbol_dict[['code','name']].values).T quotes = [] for symbol in symbols: #print('Fetching quote history for %r' % symbol) try: quotes.append(quotes_historical_google(symbol , start_date, end_date)) except Exception as e: print(e) pass close_prices = np.vstack([q['close'] for q in quotes]) open_prices = np.vstack([q['open'] for q in quotes]) # The daily variations of the quotes are what carry most information variation = close_prices - open_prices # Learn a graphical structure from the correlations edge_model = covariance.GraphLassoCV() # standardize the time series: using correlations rather than covariance # is more efficient for structure recovery X = variation.copy().T X /= X.std(axis=0) edge_model.fit(X) # Cluster using affinity propagation _, labels = cluster.affinity_propagation(edge_model.covariance_) n_labels = labels.max() for i in range(n_labels + 1): print('Cluster %i: %s' % ((i + 1), ', '.join(names[labels == i]))) # ############################################################################# # Find a low-dimension embedding for visualization: find the best position of # the nodes (the stocks) on a 2D plane # We use a dense eigen_solver to achieve reproducibility (arpack is # initiated with random vectors that we don't control). In addition, we # use a large number of neighbors to capture the large-scale structure. node_position_model = manifold.LocallyLinearEmbedding( n_components=2, eigen_solver='dense', n_neighbors=6) embedding = node_position_model.fit_transform(X.T).T # ############################################################################# # Visualization plt.figure(1, facecolor='w', figsize=(10, 8)) plt.clf() ax = plt.axes([0., 0., 1., 1.]) plt.axis('off') # Display a graph of the partial correlations partial_correlations = edge_model.precision_.copy() d = 1 / np.sqrt(np.diag(partial_correlations)) partial_correlations *= d partial_correlations *= d[:, np.newaxis] non_zero = (np.abs(np.triu(partial_correlations, k=1)) > 0.02) # Plot the nodes using the coordinates of our embedding plt.scatter(embedding[0], embedding[1], s=100 * d ** 2, c=labels, cmap=plt.cm.Spectral) # Plot the edges start_idx, end_idx = np.where(non_zero) # a sequence of (*line0*, *line1*, *line2*), where:: # linen = (x0, y0), (x1, y1), ... (xm, ym) segments = [[embedding[:, start], embedding[:, stop]] for start, stop in zip(start_idx, end_idx)] values = np.abs(partial_correlations[non_zero]) lc = LineCollection(segments, zorder=0, cmap=plt.cm.hot_r, norm=plt.Normalize(0, .7 * values.max())) lc.set_array(values) lc.set_linewidths(15 * values) ax.add_collection(lc) # Add a label to each node. The challenge here is that we want to # position the labels to avoid overlap with other labels for index, (name, label, (x, y)) in enumerate( zip(names, labels, embedding.T)): dx = x - embedding[0] dx[index] = 1 dy = y - embedding[1] dy[index] = 1 this_dx = dx[np.argmin(np.abs(dy))] this_dy = dy[np.argmin(np.abs(dx))] if this_dx > 0: horizontalalignment = 'left' x = x + .002 else: horizontalalignment = 'right' x = x - .002 if this_dy > 0: verticalalignment = 'bottom' y = y + .002 else: verticalalignment = 'top' y = y - .002 plt.text(x, y, name, size=10, horizontalalignment=horizontalalignment, verticalalignment=verticalalignment, bbox=dict(facecolor='w', edgecolor=plt.cm.Spectral(label / float(n_labels)), alpha=.6)) plt.xlim(embedding[0].min() - .15 * embedding[0].ptp(), embedding[0].max() + .10 * embedding[0].ptp(),) plt.ylim(embedding[1].min() - .03 * embedding[1].ptp(), embedding[1].max() + .03 * embedding[1].ptp()) plt.show()
如果大家有什么问题,欢迎评论,我会一一回复。