🚀 AI 一键生成 joinquant 策略代码

JoinQuant Alpha191 因子库实战教程:构建多因子选股策略

joinquant | 发布时间: 2025/11/28
以下内容由 EasyQuant 生成。

问题描述

如何使用 Alpha191 因子库来选股?

解决方案

在聚宽(JoinQuant)平台上使用 Alpha191 因子库进行选股,主要依赖于 jqlib.alpha191 库。该库内置了国泰君安研报中的191个短周期量价因子。

使用 Alpha191 进行选股的核心流程通常如下:

  1. 确定股票池:如沪深300、中证500等。
  2. 获取因子值:调用 alpha_XXX 函数获取指定日期的因子数据。
  3. 数据清洗:剔除停牌、ST股、涨跌停股票,处理因子缺失值。
  4. 排序选股:根据因子值大小进行排序(正向或反向),选取头部股票。
  5. 交易执行:调仓买入目标股票,卖出不在目标列表中的持仓。

下面是一个完整的单因子选股策略示例。该策略以 Alpha_001 为例,在沪深300成分股中选取因子值最大的前10只股票进行每日调仓。

策略代码示例

# -*- coding: utf-8 -*-
from jqdata import *
# 导入 Alpha191 库
from jqlib.alpha191 import *

def initialize(context):
    """
    初始化函数,设定基准、手续费、滑点等
    """
    # 设定沪深300作为基准
    set_benchmark('000300.XSHG')
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    # 过滤掉order系列API产生的比error级别低的log
    log.set_level('order', 'error')
    
    # 设定股票池:沪深300
    g.index = '000300.XSHG'
    # 设定持仓数量
    g.stock_num = 10
    
    # 设定交易费率(股票:买入万三,卖出万三加千一印花税)
    set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003, close_commission=0.0003, close_today_commission=0, min_commission=5), type='stock')
    
    # 每日开盘时运行选股和交易逻辑
    run_daily(trade_func, time='09:30')

def trade_func(context):
    """
    交易主逻辑
    """
    # 1. 获取股票池(沪深300)
    stocks = get_index_stocks(g.index)
    
    # 2. 过滤掉停牌、ST、退市的股票
    stocks = filter_stocks(stocks)
    if not stocks:
        return

    # 3. 获取 Alpha191 中的 Alpha_001 因子值
    # 注意:因子计算通常基于收盘后数据,所以使用 context.previous_date
    # alpha_001 公式: (-1 * CORR(RANK(DELTA(LOG(VOLUME),1)),RANK(((CLOSE-OPEN)/OPEN)),6)
    factor_data = alpha_001(stocks, end_date=context.previous_date)
    
    # 4. 处理因子数据
    # 去除 NaN 值
    factor_data = factor_data.dropna()
    
    # 5. 选股逻辑
    # 这里假设因子值越大越好(具体方向需根据每个因子的定义来判断)
    # 对因子值进行降序排列,取前 g.stock_num 只股票
    target_list = factor_data.sort_values(ascending=False).head(g.stock_num).index.tolist()
    
    # 6. 执行交易
    rebalance(context, target_list)

def filter_stocks(stock_list):
    """
    过滤停牌、ST、退市股票
    """
    curr_data = get_current_data()
    return [stock for stock in stock_list if 
            not curr_data[stock].paused and 
            not curr_data[stock].is_st and 
            'ST' not in curr_data[stock].name and 
            '*' not in curr_data[stock].name and 
            not curr_data[stock].day_open == curr_data[stock].high_limit and # 过滤涨停
            not curr_data[stock].day_open == curr_data[stock].low_limit    # 过滤跌停
           ]

def rebalance(context, target_list):
    """
    调仓函数
    """
    # 获取当前持仓
    current_holdings = list(context.portfolio.positions.keys())
    
    # 卖出不在目标列表中的股票
    for stock in current_holdings:
        if stock not in target_list:
            order_target_value(stock, 0)
    
    # 买入目标列表中的股票
    if len(target_list) > 0:
        # 等权重分配资金
        value_per_stock = context.portfolio.total_value / len(target_list)
        for stock in target_list:
            order_target_value(stock, value_per_stock)

关键点说明

  1. 库的导入
    必须使用 from jqlib.alpha191 import * 才能直接调用 alpha_001alpha_191 这些函数。

  2. 日期参数
    调用因子函数时(如 alpha_001(stocks, end_date=...)),end_date 通常传入 context.previous_date。因为 Alpha191 多为日线级别的量价因子,需要在前一交易日收盘后计算,用于指导当天的交易。

  3. 因子方向
    Alpha191 中的因子有些是动量型的(值越大越好),有些是反转型的(值越小越好),还有些可能需要取绝对值。在使用具体因子前,建议查阅 Alpha191 的因子公式说明或进行简单的 IC 测试来确定排序方向(ascending=True 还是 False)。

  4. 多因子组合
    上述代码仅演示了单因子选股。如果需要使用多个因子,可以获取多个因子的 Series,将其合并为 DataFrame,进行标准化(Z-Score)处理后,加权求和得到综合得分,再进行排序选股。

Q&A

Q1: 如何查看 Alpha191 中某个具体因子的公式含义?
A1: 在聚宽的研究环境中,导入库后可以使用 ? 查看文档字符串。例如输入 alpha_001? 并运行,系统会显示该因子的计算公式和输入输出说明。

Q2: Alpha191 因子可以直接用于实盘吗?
A2: Alpha191 是短周期量价因子,换手率通常较高。直接使用原始因子可能面临较高的交易成本和滑点影响。建议在实盘前进行充分的回测,并考虑加入换手率限制、平滑处理或结合基本面因子使用。

Q3: 为什么有些因子计算结果全是 NaN?
A3: 这通常是因为计算该因子所需的历史数据长度不足。例如某些因子需要过去20天的移动平均,如果股票刚上市不足20天,或者传入的股票池中有停牌导致数据缺失,计算结果就会是 NaN。代码中应包含 dropna() 处理。