- 修复 data_loader.py 财务数据日期过滤,支持按范围加载 - 优化 MADClipper 使用窗口函数替代 join,提升性能 - 修复训练日期边界问题,添加1天间隔避免数据泄露 - 新增 .gitignore 规则忽略训练输出目录
25 KiB
Classify2_load_model.ipynb 代码流程详解文档
概述
本文档详细描述了 Classify2_load_model.ipynb 文件中完整的代码流程,该notebook实现了一个股票分类模型的特征工程与数据预处理流程。整个流程涵盖了从原始数据加载、多源数据合并、因子计算、数据清洗、特征标准化等多个环节,最终输出可供机器学习模型使用的特征矩阵。
第一部分:环境配置与初始化
1.1 基础环境设置
notebook开头的第一个代码单元负责基础的开发环境配置。首先启用Jupyter的自动重载功能,通过%load_ext autoreload和%autoreload 2指令,使得在修改导入的模块后能够自动重新加载,这对于开发调试阶段非常实用。随后进行垃圾回收机制的相关设置,导入gc模块用于手动管理内存,因为后续处理的数据量较大(数GB级别),及时释放不需要的对象可以避免内存溢出。
系统路径的配置通过sys.path.append完成,将项目根目录添加到Python的模块搜索路径中,这样可以直接导入项目内的自定义模块。打印工作目录用于确认当前运行环境。数据处理的核心库pandas被导入用于表格数据处理,同时导入项目内部的因子模块和工具函数,包括get_rolling_factor和get_simple_factor用于计算技术因子,read_industry_data用于读取行业分类数据,calculate_score用于计算目标变量。最后通过warnings.filterwarnings("ignore")忽略所有警告信息,保持输出界面的整洁。
1.2 并行计算配置
第二个代码单元配置了Modin框架的并行计算参数。通过设置环境变量os.environ["MODIN_CPUS"] = "4",指定使用4个CPU核心进行并行计算。Modin是一个pandas的并行替代库,能够在多核CPU上并行执行pandas操作,显著加速大规模数据的处理速度。这一配置对于后续处理数千万条记录的数据框至关重要。
第二部分:核心数据加载与合并
2.1 日线数据加载
第三个代码单元是整个流程中最关键的数据加载步骤,依次从HDF5文件中读取多个数据源并合并。HDF5是一种高效的分块压缩存储格式,非常适合存储大规模数值型数据。
第一步:加载日线行情数据
使用read_and_merge_h5_data函数从daily_data.h5文件中读取日线行情数据。该函数是项目自定义的工具函数,其核心逻辑在main/utils/utils.py中实现。读取的字段包括股票代码ts_code、交易日期trade_date、开盘价open、收盘价close、最高价high、最低价low、成交量vol、成交额amount以及涨跌幅pct_chg。这些字段构成分析的基础价格信息。首次调用该函数时df参数为空,因此直接返回读取的数据作为初始数据框。
第二步:加载日线基础数据
继续调用read_and_merge_h5_data读取daily_basic.h5文件,获取每日股票的基础财务指标。本次读取使用内连接(inner join)方式与已有数据进行合并,这意味着只保留两个数据集中都存在的股票记录。读取的字段包括turnover_rate(换手率)、pe_ttm(滚动市盈率)、circ_mv(流通市值)、total_mv(总市值)以及volume_ratio(量比)。这些指标对于评估股票的流动性和估值水平非常重要。
第三步:加载涨跌停限制数据
从stk_limit.h5文件中读取股票的涨跌停价格信息。读取的字段包括pre_close(前一日收盘价)、up_limit(涨停价)和down_limit(跌停价)。这些信息用于后续识别股票的涨停状态,是构建目标变量的重要依据。
第四步:加载资金流数据
从money_flow.h5文件中读取资金流信息,这是计算资金流因子的基础数据。读取的字段包括各类成交量的分解:buy_sm_vol和sell_sm_vol代表小单买卖成交量、buy_lg_vol和sell_lg_vol代表大单买卖成交量、buy_elg_vol和sell_elg_vol代表超大单买卖成交量,以及net_mf_vol(净资金流成交量)。通过分析这些不同档位的资金流向,可以判断机构投资者和散户的交易行为。
第五步:加载筹码分布数据
最后从cyq_perf.h5文件中读取筹码分布相关指标。这些数据反映的是股票持仓成本分布情况,包括历史最低价his_low、历史最高价his_high、不同成本分位线的价格(cost_5pct、cost_15pct、cost_50pct、cost_85pct、cost_95pct)、加权平均成本weight_avg以及获利盘比例winner_rate。这些指标是计算筹码分布因子的核心数据。
经过上述五个步骤的依次合并,最终生成的数据框包含9436343条记录、33个字段,占用内存约2.3GB。
2.2 行业数据加载与合并
第四个代码单元处理行业分类数据的加载与合并。首先使用read_and_merge_h5_data函数从industry_data.h5文件中读取行业分类数据,提取股票代码、二级行业代码l2_code以及行业纳入日期in_date。
随后定义了merge_with_industry_data函数,用于将行业数据与主数据框进行时间匹配合并。该函数的核心逻辑分为以下几个步骤:首先确保日期字段转换为datetime类型;然后分别对行业数据和主数据按股票代码和日期排序;接着使用pd.merge_asof函数进行向后合并(direction='backward'),这意味着对于每一股票的每一个交易日,会匹配该日之前(包括当日)最近的行业变更记录;对于交易日期早于所有行业变更日期的记录,使用每个股票的最早行业代码进行填充。
这一合并策略的设计目的是确保在任意交易日期都能获取到该股票当前所属的行业分类,这对于后续进行行业中性化处理至关重要。
第三部分:指数数据处理
3.1 指数数据读取
第五个代码单元实现指数数据的读取与指标计算。定义了两个核心函数:calculate_indicators用于计算单个指数的技术指标,generate_index_indicators用于批量处理多个指数。
在calculate_indicators函数中,首先对数据按交易日期排序,然后计算以下指标:
当日涨跌幅:通过(close - pre_close) / pre_close * 100计算,这是最基础的收益率指标。
RSI指标:相对强弱指数,计算过程包括首先计算价格变动delta,然后分离上涨和下跌部分,分别计算14日滚动平均,最后通过公式100 - (100 / (1 + rs))得到RSI值。RSI是衡量股票近期涨跌动能的经典技术指标。
MACD指标:移动平均收敛发散指标,计算过程包括12日EMA减去26日EMA得到MACD线,9日EMA得到信号线,MACD与信号线的差值得到MACD柱。MACD是判断趋势方向和动量变化的重要工具。
情绪因子:
- 上涨比例(up_ratio_20d):过去20天上涨天数占比,反映市场整体情绪
- 成交量变化率(volume_change_rate):当日成交量与20日均量的比率,反映成交量异常变化
- 波动率(volatility):过去20天日收益率的标准差,反映市场波动程度
- 成交额变化率(amount_change_rate):当日成交额与20日均额的比率
generate_index_indicators函数则对所有指数分别计算上述指标,然后将结果透视为宽表格式,使每个指数的指标成为独立的列。最终输出包含多个指数技术指标的数据框,这些指标可以作为市场情绪的代理变量加入模型。
3.2 行业指数数据处理
第六个代码单元使用talib库和numpy库进行更专业的技术指标计算。talib是专业的技术分析库,包含数百种经典技术指标的实现。
从sw_daily.h5文件读取行业日线数据后,依次计算:
OBV(能量潮指标):通过talib.OBV函数计算,将成交量与价格变动方向结合,衡量资金流入流出的强度。
短期收益率(return_5):5日收益率,计算公式为x / x.shift(5) - 1。
中期收益率(return_20):20日收益率,用于捕捉中短期动量。
动量因子(act_factor):通过get_act_factor函数计算,该函数对不同周期的EMA(指数移动平均)进行arctan变换,得到平滑的动量因子。这是项目自定义的核心因子之一。
收益率分位数排名:将收益率在截面内转换为百分位排名,消除不同行业间的基数差异,便于跨行业比较。
最终对所有新增字段添加industry_前缀,并重命名ts_code为cat_l2_code,形成行业级别的因子数据,可用于后续的行业对标分析。
第四部分:财务数据加载
4.1 财务指标数据
第九至十一个代码单元负责加载各类财务数据,为模型增加基本面因子。
财务指标数据(fina_indicator):从fina_indicator.h5文件读取,包含undist_profit_ps(每股未分配利润)、ocfps(每股经营现金流)、bps(每股净资产)、roa(资产收益率)和roe(净资产收益率)。这些指标反映企业的盈利能力和财务健康状况。
现金流数据(cashflow):从cashflow.h5文件读取,包含n_cashflow_act(经营活动净现金流),用于评估企业现金流的真实状况。
资产负债表数据(balancesheet):从balancesheet.h5文件读取,包含money_cap(货币资金)和total_liab(总负债),用于计算企业的偿债能力。
这些财务数据通过ann_date(公告日期)与交易数据进行时间匹配,确保使用最新披露的财务信息。需要注意的是,财务数据存在滞后性,通常季报在季度结束后一段时间才披露,因此在匹配时使用向后合并策略。
第五部分:数据过滤与清洗
5.1 数据过滤规则
第十一个代码单元定义了filter_data函数,应用一系列过滤规则清理数据:
排除ST股票:df[~df['is_st']]过滤掉所有ST(特别处理)股票,这类股票存在较大风险。
排除北京股票:df[~df['ts_code'].str.endswith('BJ')]排除北京交易所的股票。
排除创业板和科创板:df[~df['ts_code'].str.startswith('30')]排除创业板股票,df[~df['ts_code'].str.startswith('68')]排除科创板股票。这一设计可能是因为这两个板块的股票特性与主板有较大差异。
排除ST类代码:df[~df['ts_code'].str.startswith('8')]排除了以8开头的股票代码,通常这类代码也属于风险警示类。
时间范围过滤:df[df['trade_date'] >= '2019-01-01']]只保留2019年及以后的数据,确保数据质量和一致性。
删除冗余列:如果存在in_date列则删除,避免与交易日期混淆。
过滤后的数据量从9436343条减少到5087384条,约减少46%。
第六部分:因子计算
6.1 财务因子计算
第十二个代码单元是因子计算的核心部分,首先计算一系列财务相关因子:
现金流因子(cashflow_to_ev_factor):将现金流数据与企业价值进行对比,计算企业现金流的相对估值水平。
市净率因子(book_to_price_ratio):通过caculate_book_to_price_ratio函数计算,每股净资产与股价的比值,是价值投资的经典指标。
6.2 基础技术因子
继续计算各类技术因子:
换手率均值(turnover_rate_mean_5):5日平均换手率,反映股票的交易活跃程度。
收益率方差(variance_20):20日收益率方差,衡量短期波动性。
BBI比率因子(bbi_ratio_factor):BBI是多空指数的简称,通过不同周期均线的组合判断多空趋势。
日偏离度(daily_deviation):当日涨跌幅与市场平均涨跌幅的差异,反映个股的相对强弱。
日行业偏离度(daily_industry_deviation):相对于所在行业平均涨跌幅的偏离,反映行业内相对表现。
6.3 滚动因子与简单因子
调用get_rolling_factor和get_simple_factor函数批量计算大量因子。这两个函数定义在main/factor/factor.py中,是项目最核心的因子计算模块。
get_rolling_factor函数主要计算的因子包括:
资金流因子组:
lg_elg_net_buy_vol:超大单加大单的净买入量flow_lg_elg_intensity:主力资金流强度,等于净买入量除以成交量sm_net_buy_vol:散户净买入量flow_divergence_diff:散户与主力背离度,主力净买入减去散户净买入flow_divergence_ratio:背离比率形式lg_elg_buy_prop:主力买入占比flow_struct_buy_change:资金流结构变动,1日变化率flow_lg_elg_accel:资金流加速度,二阶导数
筹码分布因子组:
chip_concentration_range:(95%成本价 - 5%成本价)/ 当前价格,反映筹码集中程度chip_skewness:(加权平均成本 - 50%成本价)/ 50%成本价,反映成本分布偏斜方向floating_chip_proxy:浮筹比例,结合获利盘和价格位置cost_support_15pct_change:15%成本线变化率,反映支撑位变动cat_winner_price_zone:获利盘价格区域分类
资金与筹码结合因子:
flow_chip_consistency:资金流与筹码结构一致性profit_taking_vs_absorb:获利了结压力与承接盘强度
收益率分布因子:
upside_vol和downside_vol:上涨和下跌方向的标准差vol_ratio:上下波动率比值return_skew和return_kurtosis:收益率的偏度和峰度
成交量因子:
volume_change_rate:成交量变化率cat_volume_breakout:成交量突破信号turnover_deviation:换手率偏离度cat_turnover_spike:换手率激增信号avg_volume_ratio和cat_volume_ratio_breakout:量比相关因子
talib技术指标:
atr_14和atr_6:14日和6日平均真实波幅obv和maobv_6:能量潮及其6日均线rsi_3:3日RSI
收益率因子:
return_5和return_20:5日和20日收益率std_return_5、std_return_90、std_return_90_2:不同周期的收益率标准差
EMA与动量因子:
- 各周期EMA(5、13、20、60日)
act_factor1到act_factor4:基于EMA的动量因子
协方差因子:
cov:高价与成交量的滚动协方差delta_cov:协方差差分alpha_22_improved:改进的alpha因子
其他因子:
alpha_003:收盘价与开盘价的相对位置alpha_007:收盘价与成交量的5日滚动相关性alpha_013:5日与20日累计收益差值vol_break:价格突破85%成本线且量比大于2的信号weight_roc5:加权成本5日变化率price_cost_divergence:价格与成本相关性smallcap_concentration:小盘股筹码集中度cost_stability:筹码稳定性指数liquidity_risk:筹码流动性风险
get_simple_factor函数在滚动因子的基础上进一步计算衍生因子:
momentum_factor:动量因子,等于成交量变化率加0.5倍换手率偏离度resonance_factor:共振因子,量比乘以涨跌幅log_close:收盘价对数cat_vol_spike:成交量激增分类变量up和down:上下影线比例obv_maobv_6:OBV与6日均线差值std_return_5_over_std_return_90:短期与长期波动率比值act_factor5和act_factor6:综合动量因子active_buy_volume_*:各档位主动买入占比ctrl_strength:控制强度,反映成本区间与历史区间的比值low_cost_dev、asymmetry、lock_factor:各类筹码特征因子cat_golden_resonance:黄金共振信号
6.4 资金流因子
第十三个代码单元继续计算money_factor.py中定义的各类资金流相关因子。这些因子主要分析大单资金的流动特征和动量属性。
lg_flow_mom_corr:大单资金流与20至60日滚动窗口的动量相关性,衡量资金流趋势的持续性。
lg_flow_accel:大单资金流加速度,捕捉资金流入流出的加速变化。
profit_pressure:盈利压力因子,结合价格位置和资金流向。
underwater_resistance:水下阻力因子,分析亏损区域的支持强度。
cost_conc_std_20:20日成本集中度标准差,反映筹码分布的稳定程度。
profit_decay_20:20日盈利衰减因子,衡量获利盘随时间的减少程度。
vol_amp_loss_20:20日波动幅度损失因子。
vol_drop_profit_cnt_5:5日内量价齐升计数。
lg_flow_vol_interact_20:20日大单资金流与成交量交互因子。
cost_break_confirm_cnt_5:5日内成本突破确认计数。
atr_norm_channel_pos_14:14日ATR标准化通道位置。
turnover_diff_skew_20:20日换手率差值偏度。
lg_sm_flow_diverge_20:20日大小单资金流背离。
pullback_strong_20_20:20日回撤强度因子。
vol_wgt_hist_pos_20:20日成交量加权历史位置。
vol_adj_roc_20:20日成交量调整变动率。
6.5 截面排名因子
第十三个代码单元的后半部分定义了一系列cs_rank_*开头的截面排名因子,这些因子都是通过截面排名方式计算得出,可以消除不同股票间的基数差异。
cs_rank_net_lg_flow_val:大单净流入值截面排名
cs_rank_flow_divergence:资金流背离截面排名
cs_rank_industry_adj_lg_flow:行业调整后大单资金流截面排名
cs_rank_elg_buy_ratio:超大单买入占比截面排名
cs_rank_rel_profit_margin:相对盈利-margin截面排名
cs_rank_cost_breadth:成本宽度截面排名
cs_rank_dist_to_upper_cost:到上方成本距离截面排名
cs_rank_winner_rate:获利盘比例截面排名
cs_rank_intraday_range:日内振幅截面排名
cs_rank_close_pos_in_range:收盘价在成本区间位置截面排名
cs_rank_opening_gap:跳空缺口截面排名(需要前收盘价)
cs_rank_pos_in_hist_range:历史区间位置截面排名
cs_rank_vol_x_profit_margin:成交量与盈利margin交互截面排名
cs_rank_lg_flow_price_concordance:大单资金流与价格一致性截面排名
cs_rank_turnover_per_winner:单位获利盘换手率截面排名
cs_rank_ind_cap_neutral_pe:行业市值中性市盈率截面排名
cs_rank_volume_ratio:量比截面排名
cs_rank_elg_buy_sell_sm_ratio:超大单买卖与小单比值截面排名
cs_rank_cost_dist_vol_ratio:成本分布成交量比值截面排名
cs_rank_size:市值规模截面排名
经过上述所有因子计算,数据框最终包含181个字段,内存占用约6.5GB。
第七部分:数据预处理函数定义
7.1 特征漂移检测
第十四个代码单元定义了remove_shifted_features函数,用于检测训练集和测试集之间是否存在特征分布漂移。漂移检测使用两种统计方法:
KS检验(Kolmogorov-Smirnov检验):比较两个分布是否来自同一分布,通过p值判断,p值小于阈值(默认0.05)则认为存在显著差异。
Wasserstein距离:衡量两个分布之间的Earth Mover距离,距离大于阈值(默认0.1)则认为漂移严重。
如果特征同时满足两个条件,则认为该特征存在漂移并将其移除。这一步骤对于确保模型在测试集上的泛化能力非常重要。
7.2 标准化处理函数
第十五个代码单元定义了三个核心的标准化处理函数:
cs_mad_filter(截面MAD去极值函数):
MAD(Median Absolute Deviation,中位绝对偏差)是一种稳健的极值检测方法。具体步骤包括:按日期分组计算每列的中位数,然后计算每个值与中位数的绝对偏差,再次取中位数得到MAD,最后将超出[median - k * MAD, median + k * MAD]范围的值截断到边界。默认k=3,scale_factor=1.4826使得MAD约等于正态分布的标准差。
cs_neutralize_market_cap_numpy(市值中性化函数):
对每个交易日的每只股票,使用OLS回归将因子值对市值(取对数)进行回归,提取残差作为中性化后的因子值。这一步骤消除因子中与市值相关的系统性偏差,使因子更能反映股票的真实特性而非市值效应。
cs_zscore_standardize(截面Z-Score标准化函数):
对每个截面(每日)计算各因子的均值和标准差,然后进行Z-Score变换:Z = (value - mean) / (std + epsilon)。这使得不同量纲的因子具有可比性,且均值为0、标准差为1。
fill_nan_with_daily_median(截面中位数填充函数):
对每个交易日分别计算各因子的中位数,用该中位数填充该日内的缺失值。这一方法比全局中位数填充更能反映数据的时间特性。
7.3 其他预处理函数
第十五个代码单元还定义了其他辅助预处理函数:
remove_outliers_label_percentile:对标签进行百分位去极值,默认保留1%到99%分位之间的数据。
calculate_risk_adjusted_target:计算风险调整后的目标变量,结合未来收益率和未来波动性。
calculate_score:计算综合评分目标,考虑未来收益减去风险惩罚(最大回撤)。
remove_highly_correlated_features:移除高度相关的特征,避免多重共线性问题。
cross_sectional_standardization:截面标准化,使用StandardScaler进行标准化。
neutralize_manual_revised:手动实现的行业市值中性化函数,对每个行业分别进行回归取残差。
mad_filter:全局MAD去极值函数(简化版)。
percentile_filter:百分位去极值函数。
iqr_filter:四分位距标准化函数。
quantile_filter:滚动分位数去极值函数。
select_top_features_by_rankic:基于RankIC选择最优特征。
create_deviation_within_dates:创建截面偏差特征,计算行业内各因子与均值的偏差。
第八部分:目标变量构建
8.1 未来收益率计算
第十六个代码单元负责构建预测目标变量。
未来收益率:通过df.groupby('ts_code')['close'].shift(-days) / df['close'] - 1计算,days默认为5,即预测未来5日的收益率。shift(-days)表示向后移动获取未来价格。
涨停标签:构建分类目标变量,首先识别当日涨幅超过5%的股票(cat_up_limit),然后计算过去5日内是否存在涨停(通过rolling窗口的max函数),再向后shift(5)避免未来信息泄露,最后fillna(0)并转换为整数类型。
过滤异常收益率:使用between方法保留1%到99%分位之间的收益率,去除极端值。
第九部分:特征列筛选
9.1 特征列筛选逻辑
第十七个代码单元进行特征列的最终筛选。通过一系列排除规则,从所有可用列中筛选出建模所需的特征列:
排除非特征列:排除trade_date、ts_code、label等标识列;排除包含future、label、score、gen、is_st、pe_ttm、circ_mv、code等关键词的列;排除原始基础数据列origin_columns;排除下划线开头的临时列。
排除特定特征:手动排除存在问题的特征如intraday_lg_flow_corr_20、cap_neutral_cost_metric、hurst_net_mf_vol_60等;排除财务因子roa和roe。
最终筛选出191个特征列用于建模。
第十部分:缺失值处理与标准化流程
10.1 缺失值填充
第十八个代码单元将所有特征的缺失值填充为0。这一简化处理的假设是:缺失值可能代表数据不可用或极小概率事件,用0填充对模型影响相对中性。
10.2 完整的预处理流水线
第十九个代码单元展示了完整的预处理流程执行:
第一步:特征列确定——合并行业数据、指数数据后确定最终特征列表。
第二步:MAD去极值——执行第一轮截面MAD去极值,处理全量特征。
第三步:市值中性化——对第一轮去极值后的特征进行截面市值中性化。
第四步:第二轮MAD去极值——对中性化后的特征再次进行去极值处理。
第五步:Z-Score标准化——最后对所有特征进行截面Z-Score标准化。
整个流水线确保了最终进入模型的特征具有:稳定的分布(去极值)、去除市值偏差(中性化)、可比性(标准化)。
总结
Classify2_load_model.ipynb实现了一个完整、规范的量化因子工程流程。整个流程涵盖了数据加载、多源数据合并、因子计算、特征筛选、预处理标准化等关键步骤。
数据层面:整合了日线行情、资金流、筹码分布、财务指标、行业分类、指数数据等多维度数据源,形成了超过180个特征的基础特征池。
因子层面:因子体系覆盖了资金流因子、筹码分布因子、技术指标因子、动量因子、波动率因子、截面排名因子等多个类别,形成了多角度、全方位的特征体系。
预处理层面:建立了完整的预处理流水线,包括MAD去极值、市值中性化、Z-Score标准化等标准化步骤,确保特征的质量和稳定性。
整个notebook的设计体现了量化投资特征工程的最佳实践,为后续的机器学习模型训练提供了高质量的数据基础。