推广 热搜: 采购方式  甲带  滤芯  气动隔膜泵  带式称重给煤机  减速机型号  减速机  链式给煤机  履带  无级变速机 

一个年化106%的基于量化报告而生成的行业选股策略(含代码)

   日期:2026-03-05 12:59:17     来源:网络整理    作者:本站编辑    评论:0    
一个年化106%的基于量化报告而生成的行业选股策略(含代码)
《全市场选股方法论与 AI 量化选股模型》报告提出了一种创新型全市场选股框架,构建了AI量化选股模型,采用两阶段选股逻辑实现全市场覆盖与分层优化。第一阶段通过行业主线轮动模型预测行业指数趋势强弱,第二阶段在预测的主线行业内基于个股基本面特征因子筛选标的。模型通过回测验证,各组合均显著跑赢基准万得全A。

模型框架与核心逻辑

  • AI量化选股模型采用两阶段选股逻辑:第一阶段为行业主线轮动模型,聚焦宏观与行业层面,对行业指数趋势强弱进行预测与排序;第二阶段在预测的主线行业内,运用AI量化选股模型,基于个股基本面特征因子完成最终标的筛选。
  • 第二阶段模型的预测目标是个股相对于行业组合的β系数排序,通过选择β系数相对更大的股票,借助其与市场组合的高联动性获取更高的个股收益率。
  • 模型采用两阶段划分的主要原因包括控制模型复杂度、动态适配上市公司数量变化以及选股第二阶段模型可以独立发展成为指数增强模型。

方法论与理论基础

  • 选股模型基于资本资产定价模型(CAPM),通过β系数反映股票收益率对市场收益率变动的敏感性。
  • β系数由上市公司基本面决定,包括经营杠杆、财务杠杆、业务周期属性、资产质量、盈利稳定性、行业、规模、成长性等因素,因此相对稳定,适合作为预测目标。
  • 选股模型通过动态验证和修正β系数的估计值,显著提升了β系数的稳定性和可靠性。

回测结果与表现

def rebalance_portfolio(context):    """核心投资组合再平衡函数"""    # 1. 获取当前总资产    total_value = context.portfolio.total_value    if total_value <= 0:        log.error(f"总资产为 {total_value},无法调仓。")        return    log.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("无法获取足够的交易日数据")        return    prev_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:                continue            start_price = index_df['close'].iloc[0]            end_price = index_df['close'].iloc[-1]            momentum = (end_price / start_price) - 1            index_momentum[index_code] = momentum        except Exception as e:            log.warning(f"计算指数 {index_code} 动量失败: {e}")            continue    if 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[0for 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:                continue            bm_ret = benchmark_prices.loc[common_idx].values            stk_ret = stock_prices.loc[common_idx].values            # 计算Beta            beta = np.polyfit(bm_ret, stk_ret, 1)[0]            beta_list.append((stock, beta))        except:            continue    if not beta_list:        return []    # 按Beta从高到低排序    beta_list.sort(key=lambda x: x[1], reverse=True)    selected = [item[0for item in beta_list[:g.top_stock_per_index]]    return selected

如需要获取该策略完整代码--可后台私信《行业选股》

 
打赏
 
更多>同类资讯
0相关评论

推荐图文
推荐资讯
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报  |  皖ICP备20008326号-18
Powered By DESTOON