模型框架与核心逻辑
AI量化选股模型采用两阶段选股逻辑:第一阶段为行业主线轮动模型,聚焦宏观与行业层面,对行业指数趋势强弱进行预测与排序;第二阶段在预测的主线行业内,运用AI量化选股模型,基于个股基本面特征因子完成最终标的筛选。 第二阶段模型的预测目标是个股相对于行业组合的β系数排序,通过选择β系数相对更大的股票,借助其与市场组合的高联动性获取更高的个股收益率。 模型采用两阶段划分的主要原因包括控制模型复杂度、动态适配上市公司数量变化以及选股第二阶段模型可以独立发展成为指数增强模型。
方法论与理论基础
选股模型基于资本资产定价模型(CAPM),通过β系数反映股票收益率对市场收益率变动的敏感性。 β系数由上市公司基本面决定,包括经营杠杆、财务杠杆、业务周期属性、资产质量、盈利稳定性、行业、规模、成长性等因素,因此相对稳定,适合作为预测目标。 选股模型通过动态验证和修正β系数的估计值,显著提升了β系数的稳定性和可靠性。
回测结果与表现



def rebalance_portfolio(context):"""核心投资组合再平衡函数"""# 1. 获取当前总资产total_value = context.portfolio.total_valueif total_value <= 0:log.error(f"总资产为 {total_value},无法调仓。")returnlog.info(f"当前总资产: {total_value:.2f}")# 2. 获取前一个交易日(避免未来数据问题)# 在开盘前,我们只能使用前一天的数据trade_days = get_trade_days(end_date=context.current_dt, count=2)if len(trade_days) < 2:log.error("无法获取足够的交易日数据")returnprev_date = trade_days[-2] # 前一个交易日# 3. 第一阶段:指数动量轮动(使用前一日数据)index_momentum = {}for index_code in g.index_list:try:# 使用前一个交易日作为结束日期index_df = get_price(index_code,count=g.index_momentum_period+1,end_date=prev_date,frequency='daily',fields=['close'])if index_df is None or len(index_df) < 2:continuestart_price = index_df['close'].iloc[0]end_price = index_df['close'].iloc[-1]momentum = (end_price / start_price) - 1index_momentum[index_code] = momentumexcept Exception as e:log.warning(f"计算指数 {index_code} 动量失败: {e}")continueif not index_momentum:log.warning("所有指数动量计算失败,使用备用选股。")final_stocks = get_fallback_stocks(context, prev_date)else:# 选择动量最强的指数sorted_indices = sorted(index_momentum.items(), key=lambda x: x[1], reverse=True)selected_indices = [item[0] for item in sorted_indices[:g.top_index_count]]log.info(f"本期强势指数: {[g.index_dict.get(c, c) for c in selected_indices]}")# 4. 第二阶段:从强势指数中选股all_candidate_stocks = []for idx_code in selected_indices:# 获取指数成分股(使用前一日数据)idx_stocks = get_index_stocks(idx_code, date=prev_date)if not idx_stocks:continue# 对指数内股票进行可交易性初筛tradable_in_index = filter_stocks_basic(context, idx_stocks, prev_date)if len(tradable_in_index) < 5:continue# 计算Beta并选股selected_from_index = select_high_beta_stocks(context, tradable_in_index, idx_code, prev_date)if selected_from_index:all_candidate_stocks.extend(selected_from_index)log.info(f" 指数 {g.index_dict.get(idx_code, idx_code)} 贡献 {len(selected_from_index)} 只候选股。")if not all_candidate_stocks:log.warning("指数选股未得到候选股,使用备用选股。")final_stocks = get_fallback_stocks(context, prev_date)else:# 对候选股进行最终可交易性确认final_stocks = confirm_tradable_stocks(context, all_candidate_stocks, total_value, prev_date)if not final_stocks:log.warning("候选股可交易性确认失败,使用备用选股。")final_stocks = get_fallback_stocks(context, prev_date)# 5. 执行调仓if final_stocks:execute_rebalance(context, final_stocks, total_value, prev_date)else:log.error("最终选股列表为空,无法调仓。清空现有持仓。")clear_all_positions(context)
def select_high_beta_stocks(context, stock_list, benchmark_code, prev_date):"""从股票列表中选出相对于基准指数Beta最高的股票"""beta_list = []# 获取基准指数收益率(使用prev_date)try:benchmark_prices = get_price(benchmark_code,count=g.beta_calc_period,end_date=prev_date,frequency='daily',fields=['close'])['close'].pct_change().dropna()except:return []if len(benchmark_prices) < 30:return []for stock in stock_list:try:stock_prices = get_price(stock,count=g.beta_calc_period,end_date=prev_date,frequency='daily',fields=['close'])['close'].pct_change().dropna()# 对齐数据common_idx = benchmark_prices.index.intersection(stock_prices.index)if len(common_idx) < 20:continuebm_ret = benchmark_prices.loc[common_idx].valuesstk_ret = stock_prices.loc[common_idx].values# 计算Betabeta = np.polyfit(bm_ret, stk_ret, 1)[0]beta_list.append((stock, beta))except:continueif not beta_list:return []# 按Beta从高到低排序beta_list.sort(key=lambda x: x[1], reverse=True)selected = [item[0] for item in beta_list[:g.top_stock_per_index]]return selected
如需要获取该策略完整代码--可后台私信《行业选股》


