想法产生
对于股票,交易数据是时间序列的数据。在我看来,要将交易过程量化,就是通过一系列的手段,寻找市场规律,帮助人类自己做决策。这也是机器学习能够发挥作用的地方。如何帮助人类做决策呢?接下来我就举个简单的例子。
通常来看,如果两只或几只股票的涨跌情况很相似的时候,那么就可以认为这几家公司的业务类型有很高的相似性,或者他们之间有一些不可告人的小秘密。
股票聚类的基本原因就是从股市中选取一部股票进行投资。对一般的投资模型来说300条股票也太多了,当然我们这样做,只是为了验证假设。
按照投资组合优化理论选取标准为:
(1)资产数越多越好
(2)资产之间相关系数越低越好(实验目的)
实施过程
在计算机中如何表示这一现象呢?首先我会通过python来获取一些股票的交易数据,之后会计算出一些指标,然后用机器学习中的聚类算法,将其分为几类。
当然,最主要的是能够将结果可视化,这样也会加强结果的可解释性。
如何获取股票数据呢?现在网络上有很多现成的并且非常好用的API,比如tushare,其可以获取各种财经类数据,比较有趣的是它还可以获取一些基本面数据,比如新浪中的新闻,甚至电影的票房数据也可以通过它来获取:
# 首先我需要定义下获取股票数据的区间
start_date = "2014-01-01"
end_date = "2018-01-01"
如果此时我手动去上网查看有哪些公司的股票处于交易状态,并且还得将它们整理成python中的字典类型,最后再通过request来一个个爬取数据,设计规则......那样就太浪费时间了,有了tushare,妈妈再也不用担心我的数据源
# 查看股票列表,选取一些作为实验对象
import tushare as ts
stocks = ts.get_stock_basics()
stocks['code'] = stocks.index
此时stocks对象中包含了很多列
['name', 'industry', 'area', 'pe', 'outstanding', 'totals',
'totalAssets', 'liquidAssets', 'fixedAssets', 'reserved',
'reservedPerShare', 'esp', 'bvps', 'pb', 'timeToMarket', 'undp',
'perundp', 'rev', 'profit', 'gpr', 'npr', 'holders', 'code']
这些我就不一一解释了,通过字面我们就可以看出一些端倪,其中有个字段叫做‘timeToMarket’,它代表着公司股票允许在交易所进行交易的开始日期,我看了下这个字段的类型,竟然是 int 类型。哈哈,tushare的作者太有心了,这样我们在选取区域的时候就不用再写函数将日期转来转去的。
由于tushare无法获取到时间太早的交易数据(印象中好像是2013年左右),所以,在这里我打算选取2014年之后允许交易的企业,并且随机选取300只股票作为实验对象。
select_stock = stocks[stocks['timeToMarket'] < 20140101]
select_stock = select_stock.sample(300)
这时候,为了后面能够让公司的股票代码与名称很好的对应起来,建立一个字典来存储它们
symbol_dict = {item['code']:item['name'] for _, item in select_stock.iterrows()}
symbols, names = np.array(sorted(symbol_dict.items())).T
我发现所选的这些股票中,虽然交易区间都是从20140101至20180101,但是交易时长并不一致,得到的结果为:
均值:883.2633333333333
最大值:977
最小值:365
故接下来我们只选择交易市场大于882天的股票,所以
quotes = {}
newDict = {}
for symbol in symbols:
print('Fethching quote history for {}'.format(symbol))
data = ts.get_k_data(code=symbol, start=start_date, end=end_date) # 获取单只股票的历史交易数据
# data.to_csv('./data/{}.csv'.format(symbol),index=None) # 存储起来以便循环利用
if len(data) > 882:
quotes[symbol] = data
newDict[symbol] = symbol_dict[symbol]
time.sleep(np.random.rand(1))
ok,到此为止,我们手上已经有了300只股票的历史交易数据。由于这些股票的交易时长并不一致,在这里方便起见,选择平均值处理,也就是说,只要交易时长如果大于882天,那么我就选取它作为实验对象,并且选取最后的882组交易数据。
# open 为第2列, close 为第3列
close_prices = np.vstack([q.iloc[-882:, 2] for _, q in quotes.items()])
open_prices = np.vstack([q.iloc[-882:, 1] for _, q in quotes.items()])
# 计算出每天的涨跌值
variation = close_prices - open_prices
利用GraphLasso在少数样本中学习协方差和稀疏精度。
edge_model = covariance.GraphLassoCV() # GraphLasso 会自动调节alpha值
X = variation.copy().T
X /= X.std(axis=0)
edge_model.fit(X)
接下来就要用到聚类方法了,这里选用的是AP聚类,此聚类方法是在07年被提出的,一般被翻译为近邻传播聚类。
它有以下优点:
不需要制定最终聚类族的个数
已有的数据点作为最终的聚类中心,而不是新生成一个族中心。
模型对数据的初始值不敏感。
对初始相似度矩阵数据的对称性没有要求。
相比与k-means聚类方法,其结果的平方差误差较小。
当然,在这里,你不能用kmeans聚类方法,因为你不确定中心点数。你也可以在这里用基于密度的聚类方法,比如DBSCAN,但在高维度数据中,其分布是非常稀疏的,密度也就难以定义了。
除了这种聚类算法,这里还可以延伸一下,利用t检验来检验两只股票的相关性,其算法也可以通过sklearn实现。后续有时间我会加个实验。
_, labels = cluster.affinity_propagation(edge_model.covariance_)
n_labels = labels.max()
for i in range(n_labels + 1):
print('Cluster {}: {}'.format(i+1, ', '.join(selectNames[labels == i])))
输出结果为:
Cluster 1: 富奥股份, 中钢国际, 奥克股份
Cluster 2: 华意压缩, 雪迪龙, 华平股份, 海泰发展
Cluster 3: 小天鹅A, 老板电器, 浙江广厦, 烽火通信
Cluster 4: 高新发展, 漳州发展, 云投生态, 世联行
Cluster 5: 韶钢松山, 广联达, 迪威迅, 申通地铁
Cluster 6: 华侨城A, 威孚高科, 德美化工, 粤 水 电, 紫鑫药业, 佛慈制药, 美亚光电, *ST沪科, 四川长虹, 岳阳林纸
Cluster 7: 大港股份, 西南证券
Cluster 8: 巨轮智能, 立讯精密, 同花顺
Cluster 9: 亚太股份, 顺灏股份, 长荣股份, 中路股份
Cluster 10: 粤高速A, 恒邦股份, 泰和新材, 双星新材, 华泰股份, *ST厦工, 中国中铁
Cluster 11: 利君股份, 南方航空, 卧龙电气
Cluster 12: 东方海洋, 南风股份, 潜能恒信, 东睦股份, 华发股份, 新五丰
Cluster 13: 湖北宜化, 双成药业, 万邦达, 唐山港
Cluster 14: 赣锋锂业, 蓝色光标
Cluster 15: 数字政通, 秋林集团
Cluster 16: 顺络电子, 奥飞娱乐, 新联电子, 思创医惠, 聚龙股份, 聚光科技, 澄星股份
Cluster 17: 银禧科技, 新莱应材, 隆华节能
Cluster 18: 精艺股份, 天汽模, 民生银行, 中国石化, 新华保险, 中国交建
Cluster 19: 深圳能源, 长安汽车, 浙江震元, 贵州百灵, 中直股份, 中国卫星, 航天动力, 西昌电力, 隧道股份
Cluster 20: 二六三, 以岭药业, 开山股份, 瑞茂通
Cluster 21: 中金岭南, 闽东电力, 嘉欣丝绸, 福建金森, 福日电子
Cluster 22: 冀中能源, 海鸥住工, 阳泉煤业, 精伦电子, 恒源煤电
Cluster 23: 深圳机场, 天健集团, 大冷股份, 新华联, 三木集团, 友阿股份, 天喻信息, 西藏天路, 国机汽车, 亚宝药业
Cluster 24: 通润装备, 安诺其, 鲁商置业, 江西铜业, 新钢股份
Cluster 25: ST成城, 京能电力
Cluster 26: 九阳股份, 哈尔斯, 外高桥, 天地源
Cluster 27: 中集集团, 中联重科, 柳 工, 江铃汽车, 泰山石油, 顺发恒业, *ST南风, 普洛药业, 承德露露, 大亚圣象, 金陵药业, 华润三九, 黔源电力, 广百股份, 福晶科技, 恩华药业, 东方雨虹, 西部建设, 大北农, 长青股份, 巨星科技, 天业通联, 东软载波, 舒泰神, 明星电力, 三峡水利, 生益科技, 两面针, 外运发展, 华丽家族, 法拉电子, 京投发展, 珠江实业, 首商股份, 一汽富维, 安徽合力, 悦达投资, 宏发股份, 航民股份, 四川成渝
Cluster 28: 北方导航, 深高速, 鲁信创投, 博闻科技
Cluster 29: 轴研科技, 银鸽投资, 君正集团
Cluster 30: 美好置业, 双箭股份, 新南洋, 宏昌电子
这么看,我们难以看出不同的cluster之间的相关性差距有多远,那么,为了更加方便我们做决策,可以将其进行可视化展示: