1. 為什麼要對股票進行聚類
1.1 投資組合優化理論
股票聚類的基本原因就是從股市中選取一部股票進行投資。哪怕是上證50對一般的投資模型來說50條股票也太多了。
按照投資組合優化理論選取标準為:
(1)資産數越多越好
(2)資産之間相關系數越低越好
以期望收益E來衡量證券收益,以收益的方差 δ2 表示投資風險
minδ2(rp)=∑∑wiwjcov(ri,rj)
E(rp)=∑wiri
式中:
rp ——組合收益;
ri 、 rj ——第i種、第j種資産的收益;
wi 、 wj ——資産i和資産j在組合中的權重;
δ2(rp) ——組合收益的方差即組合的總體風險;
cov(r,rj) ——兩種資産之間的協方差。
舉個極端的例子:(以後再詳細說吧,搞一個簡單的例子)
有n個不相關的資産,其收益率都是r,風險都是v,優化後的投資比例應該是均分(還用優化嗎……)
那資産組合的
收益:R = r
風險:V = v/n
1.2 聚類
聚類定義就不說了,經過對股票交易資料聚類後,可以将其分為幾個類别,然後從每個類别中選一個樣本,最後組成的樣本可使樣本之間的相關系數降至最低。
這樣保證在一定的風險下使收益更高。
這裡采用sklearn中affinity_propagation算法進行聚類。
2. 讀取上證50成分股
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()
3. 讀取股票交易資料
用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)
4. 聚類
4.1 載入資料
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
4.2 sklearn 聚類
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]])))
5. 聚類因子選擇
這裡比較了幾種因子的聚類結果
(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: 中國中鐵, 中國人壽, 中國重工, 中國鐵建, 中國聯通, 中國建築
![]()
SkLearn 對上證50成分股聚類1. 為什麼要對股票進行聚類2. 讀取上證50成分股3. 讀取股票交易資料4. 聚類4.2 sklearn 聚類5. 聚類因子選擇
(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: 中國中鐵, 中國人壽, 中國中車, 中國重工, 中國聯通, 中國建築
![]()
SkLearn 對上證50成分股聚類1. 為什麼要對股票進行聚類2. 讀取上證50成分股3. 讀取股票交易資料4. 聚類4.2 sklearn 聚類5. 聚類因子選擇
(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: 大秦鐵路, 浦發銀行, 海螺水泥, 興業銀行, 中信銀行, 中國銀行, 光大銀行, 農業銀行, 中國石化, 中國石油, 保利地産, 上港集團, 招商銀行, 交通銀行, 中國神華, 工商銀行, 民生銀行
![]()
SkLearn 對上證50成分股聚類1. 為什麼要對股票進行聚類2. 讀取上證50成分股3. 讀取股票交易資料4. 聚類4.2 sklearn 聚類5. 聚類因子選擇