股票价格走势的行业关联性

前言:

市场行情概览一般是从各行业指数/ETF的涨跌开始研究,行业内部各股票价格涨跌有较强的一致性,只是强弱有所差异,本文对A股上市股票基于申万行业分级进行分组,对各组内的个股研究两两相关性,供股票交易参考。

股票申万分级:

申万分级是申万宏源证券对A股上市公司根据其经营业务进行的行业划分,划分粒度分为一二三级。具体分类方式隔几年有所微调,链接是已经爬取好的A股申万分级结果,无需积分C币即可下载:
https://download.csdn.net/download/weixin_37598719/85238607

A股上市公司股价获取:

可以通过安装tushare模块并注册,即可进行包括但不限于股价的上市公司各种资料的获取,具体注册、使用教程见tushare官网网站链接:https://tushare.pro/register?reg=510562

关联性分析:

主要包括
1.动态时间扭曲(DTW):可以对不同长度的序列分析(用距离d表示,d越小则相关性越强)
2.斯皮尔曼相关系数:对秩分析(值域[-1,1],为正表示正相关,越大则相关性越强,下同)
3.皮尔逊相关系数:对离群点敏感,先对数据进行标准化
以上方法的具体原理自行百度,python代码如下:

相关性实现函数:

def pearsonr_spearman_cor(df, fill=True, standard=True):
    """计算df列之间的pearsonr、spearman相关系数"""
    # 空值填充(计算DTW可以不用填充)
    if fill:
        df.fillna(method='ffill', inplace=True)
        df.fillna(method='bfill', inplace=True)
    # 按列标准化(计算pearsonr要进行标准化)
    if standard:
        for col in df:
            if col != "trade_date":
                df[[col]] = StandardScaler().fit_transform(df[[col]])
    # 计算相关系数
    print(df.corr())
    # sns.heatmap(df.corr(), annot=True)
    # plt.show()
    print(df.corr(method="spearman"))
    # sns.heatmap(df.corr(method="spearman"), annot=True)
    # plt.show()


def dtw_cor(df, fill=True, standard=True):
    """计算df列之间的dtw距离"""
    # 空值填充(计算DTW可以不用填充)
    if fill:
        df.fillna(method='ffill', inplace=True)
        df.fillna(method='bfill', inplace=True)
    # 按列标准化(计算pearsonr要进行标准化)
    if standard:
        for col in df:
            if col != "trade_date":
                df[[col]] = StandardScaler().fit_transform(df[[col]])
    # 计算相关系数
    columns = [col for col in df.columns if col !="trade_date"]
    res_lst = {}
    for col1, col2 in itertools.combinations(columns, 2):
        d, cost_matrix, acc_cost_matrix, path = accelerated_dtw(df[[col1]], df[[col2]], dist='euclidean')
        # plt.imshow(acc_cost_matrix.T, origin='lower', cmap='gray', interpolation='nearest')
        # plt.plot(path[0], path[1], 'w')
        # plt.xlabel(col1)
        # plt.ylabel(col2)
        # plt.title(f'DTW Minimum Path with minimum distance: {np.round(d,2)}')
        # plt.show()
        # print("{} and {} DTW distance:".format(col1, col2), round(d, 2))
        res_lst.update({"{}_{}".format(col1, col2): round(d, 2)})
    # 将距离d从小到大缩放到[1,-1]
    srcRange = (min(res_lst.values()), max(res_lst.values()))  # 原始范围
    dstRange = (1, -1)  # 对应的目标范围
    for key, val in res_lst.items():
        res_lst[key] = (res_lst[key] - srcRange[0]) * (dstRange[1] - dstRange[0]) / (srcRange[1] - srcRange[0]) + dstRange[0]
    # 以矩阵的形式打印
    res_df = pd.DataFrame(columns=columns, index=columns)
    for key, val in res_lst.items():
        res_df.loc[key.split("_")[0], key.split("_")[1]] = val
        res_df.loc[key.split("_")[1], key.split("_")[0]] = val
    print(res_df)

完整代码如下:

import pandas as pd
import itertools
import seaborn as sns
from sklearn.preprocessing import StandardScaler
from scipy import stats
import numpy as np
from dtw import dtw, accelerated_dtw
from industry_index import sw_class

# 读取日线数据
total_daily_df = pd.read_csv('daily_price.csv', usecols=["ts_code", "trade_date", "close"])
# 获取股票申万分级信息
# sw1_class sw2_class sw3_class code  name
sw_filepath = "sw3.txt"
df_sw = sw_class(sw_filepath)
# merge
total_daily_df["code"] = total_daily_df["ts_code"].apply(lambda x: x[:-3])
total_daily_df = total_daily_df.merge(df_sw, on='code', how="left")
total_daily_df.sort_values(["ts_code", "trade_date"], inplace=True)
total_daily_df.drop_duplicates(subset=["ts_code", "trade_date"], inplace=True)

"""对每个行业进行相关性分析"""
for sw_code, daily_df in total_daily_df.groupby(["sw3_class"], as_index=False):  # 此处按申万三级行业分类进行分组
    # 数据行转列
    daily_df_T = pd.DataFrame()
    for ts_code, sub_df in daily_df.groupby(["ts_code"], as_index=False):
        sub_df = sub_df[["trade_date", "close"]]
        sub_df.rename(columns={'close': ts_code}, inplace=True)
        if daily_df_T.shape[0] == 0:
            daily_df_T = sub_df
        else:
            daily_df_T = daily_df_T.merge(sub_df, on="trade_date", how="outer")

    # 按时间排序
    daily_df_T.sort_values(["trade_date"], inplace=True)
    # 删除日期列
    del daily_df_T["trade_date"]

    try:
        # pearsonr_spearman相关性分析
        pearsonr_spearman_cor(daily_df_T, fill=True, standard=True)
        # DTW相关性分析
        dtw_cor(daily_df_T, fill=True, standard=True)
        print("*********** end sw3 industry {} ***********".format(sw_code))
    except:
        continue
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值