3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
使用 networkx 分析股票间的关联是量化金融中“复杂网络”分析的一种常见应用。通过将股票视为节点(Nodes),将股票间的相关性(如收益率相关系数)视为边(Edges),我们可以构建一个市场网络图,从而识别出市场中的核心资产、板块轮动效应或潜在的风险传导路径。
以下是在 PTrade 平台中使用 networkx 进行股票关联分析的完整策略示例。
import networkx as nx
import pandas as pd
import numpy as np
def initialize(context):
"""
初始化函数
"""
# 设定股票池,这里以上证50为例,代表大盘蓝筹
# 注意:get_index_stocks 建议在 before_trading_start 调用,但为了初始化方便,
# 这里先定义一个全局变量存储代码,实际获取在盘前进行
g.index_code = '000016.SH'
g.stocks = []
# 设定相关系数阈值,只有相关性高于此值的股票才会被连接
g.corr_threshold = 0.6
# 设定持仓股票数量
g.target_hold_count = 5
# 设定历史数据窗口长度(用于计算相关性)
g.history_days = 60
# 每日运行一次
run_daily(context, trade_func, time='10:00')
def before_trading_start(context, data):
"""
盘前处理:获取成分股,构建网络,计算中心性
"""
# 获取上证50成分股
g.stocks = get_index_stocks(g.index_code)
if not g.stocks:
log.info("未获取到成分股信息")
return
# 1. 获取历史收盘价数据
# PTrade中,get_history获取多只股票单字段时,返回DataFrame,列名为股票代码
history_data = get_history(g.history_days, '1d', 'close', g.stocks, fq='pre', include=False)
if history_data is None or history_data.empty:
log.info("历史数据获取失败")
g.centrality_ranking = []
return
# 2. 计算日收益率
# pct_change() 计算 (现价-前价)/前价
returns_df = history_data.pct_change().dropna()
# 3. 计算相关系数矩阵
corr_matrix = returns_df.corr()
# 4. 构建 NetworkX 图
G = nx.Graph()
# 添加节点
G.add_nodes_from(g.stocks)
# 添加边:遍历相关系数矩阵
# 注意:矩阵是对称的,且对角线为1,我们需要过滤掉重复的和自身的
columns = corr_matrix.columns
for i in range(len(columns)):
for j in range(i + 1, len(columns)):
stock_a = columns[i]
stock_b = columns[j]
correlation = corr_matrix.iloc[i, j]
# 如果相关性大于阈值,则添加边
if correlation > g.corr_threshold:
# 将相关系数作为权重(可选)
G.add_edge(stock_a, stock_b, weight=correlation)
# 5. 分析网络:计算度中心性 (Degree Centrality)
# 度中心性越高,说明该股票与板块内其他股票的联动性越强
if len(G.nodes()) > 0:
degree_dict = nx.degree_centrality(G)
# 将字典转换为列表并排序 [(股票代码, 中心性数值), ...]
# Python 3.5 兼容写法
sorted_centrality = sorted(degree_dict.items(), key=lambda x: x[1], reverse=True)
# 提取排名靠前的股票代码
g.centrality_ranking = [item[0] for item in sorted_centrality]
log.info("今日网络关联度最高的股票前三名: %s" % str(g.centrality_ranking[:3]))
else:
g.centrality_ranking = []
def trade_func(context):
"""
交易函数
"""
if not g.centrality_ranking:
return
# 选取中心性最高的前N只股票
target_stocks = g.centrality_ranking[:g.target_hold_count]
# 获取当前持仓
current_positions = list(context.portfolio.positions.keys())
# 1. 卖出不在目标列表中的股票
for stock in current_positions:
if stock not in target_stocks:
order_target_value(stock, 0)
log.info("卖出非核心关联股票: %s" % stock)
# 2. 买入目标股票
# 简单的等权重分配资金
if len(target_stocks) > 0:
cash_per_stock = context.portfolio.portfolio_value / len(target_stocks)
for stock in target_stocks:
order_target_value(stock, cash_per_stock)
log.info("买入高关联度核心股票: %s" % stock)
def handle_data(context, data):
"""
盘中运行函数(本策略主要逻辑在 run_daily 中执行)
"""
pass
库的导入:
import networkx as nx:这是核心库。PTrade 环境通常内置了 networkx(文档显示版本为 1.9.1),该版本较老,因此代码中使用了兼容性较好的基础方法(如 G.add_nodes_from)。数据处理:
get_history:一次性获取多只股票的收盘价。在 Python 3.5 环境下,当 field 为单个字段(如 'close')时,返回的是 DataFrame,列索引为股票代码,这非常适合直接计算相关性。returns_df.corr():Pandas 内置方法,快速计算皮尔逊相关系数矩阵。图的构建 (Graph Construction):
nx.Graph() 创建无向图。A-B 和 B-A),只有当 correlation > g.corr_threshold 时才添加边。这意味着我们只关注强相关的股票对。中心性指标 (Centrality):
nx.degree_centrality(G):计算节点的度中心性。在股票网络中,度中心性高的节点意味着它与大量其他股票同涨同跌,通常被视为市场风格的代表或系统性风险的敏感点。除了上述代码中的度中心性,您还可以利用 networkx 进行更深度的分析:
nx.minimum_spanning_tree(G)。在金融中,MST 常用于去噪,构建市场的骨干结构,观察资金如何在板块间流动。nx.pagerank(G)。不仅考虑连接的数量,还考虑连接对象的质量(即与重要股票关联的股票更重要)。Q1: 为什么选择相关系数作为边的权重?
A1: 相关系数直接反映了资产价格变动的同步性。正相关表示同涨同跌,负相关表示对冲。在构建网络时,通常关注高正相关性来寻找核心资产,或关注低/负相关性来构建分散化投资组合。
Q2: 阈值 g.corr_threshold 设置多少合适?
A2: 这取决于市场环境和股票池的大小。
Q3: PTrade 中的 networkx 版本较老有什么影响?
A3: PTrade 文档显示支持 networkx 1.9.1。新版(2.x+)中很多方法的返回值从列表(List)变成了迭代器(Iterator/View),例如 G.nodes()。在编写代码时,尽量使用基础的图论方法,避免使用新版特有的语法。上述示例代码已考虑到这一点,使用了通用的写法。