问题描述
因子看板里可以对单因子进行过滤停牌和涨停股分析。
请问在用 analyze_factor 进行单因子分析时
如何过滤停牌和涨停股呢?
参数里没有发现相关选项。
解决方案
在 JoinQuant 平台使用 analyze_factor 进行单因子分析时,关于过滤停牌和涨停股,有以下几点需要注意和相应的解决办法:
1. 关于过滤停牌股 (skip_paused 参数)
实际上,analyze_factor 函数是有过滤停牌股的参数的,即 skip_paused。但是它有一个重要的限制条件:
skip_paused参数:默认为False。设置为True时可以跳过停牌股。- 限制条件:当
factor参数输入为已经计算好的因子值(DataFrame 或 Series)时,这个参数会失效。只有当factor参数传入的是Factor的子类(即因子定义类)时,skip_paused=True才会生效。
2. 关于过滤涨停股
analyze_factor 函数本身没有直接提供过滤涨停股的参数。
3. 终极解决方案:在传入前手动清洗因子值
由于上述限制(传入因子值时 skip_paused 失效,且无涨停过滤参数),最通用且灵活的做法是:在将因子值传入 analyze_factor 之前,先通过代码找出停牌和涨停的股票,并将它们对应的因子值设置为 NaN。analyze_factor 在处理时会自动忽略值为 NaN 的数据。
代码示例:手动过滤停牌与涨停股
假设你已经获取了因子值 factor_df (DataFrame 格式,index 为日期,columns 为股票代码),你可以按如下方式进行清洗:
import pandas as pd
import numpy as np
from jqdata import *
from jqfactor import analyze_factor
# 假设 factor_df 是你已经计算好的因子值 DataFrame
# factor_df = ...
# 获取因子值的日期列表和股票池
dates = factor_df.index.tolist()
stocks = factor_df.columns.tolist()
# 遍历每一天,进行过滤
for date in dates:
# 获取当天的行情数据,包含是否停牌、最高价、涨停价等
# 注意:为了避免未来函数,通常使用前一天的因子值预测当天的收益,
# 所以这里的过滤条件(如是否一字涨停买不进)需要根据你的具体回测逻辑来定。
# 这里以过滤当天的停牌和涨停为例:
# 获取当天的价格数据
price_data = get_price(stocks, end_date=date, count=1, fields=['close', 'high_limit', 'paused'], panel=False)
if not price_data.empty:
# 找出停牌的股票
paused_stocks = price_data[price_data['paused'] == 1]['code'].tolist()
# 找出涨停的股票 (收盘价 >= 涨停价)
# 注意:实盘中通常是过滤开盘即涨停(一字板)买不进的股票,这里以收盘涨停为例,可根据需求修改为 open >= high_limit
limit_up_stocks = price_data[price_data['close'] >= price_data['high_limit']]['code'].tolist()
# 需要过滤的股票集合
stocks_to_filter = set(paused_stocks + limit_up_stocks)
# 将这些股票在当天的因子值设为 NaN
for stock in stocks_to_filter:
if stock in factor_df.columns:
factor_df.loc[date, stock] = np.nan
# 清洗完成后,再传入 analyze_factor 进行分析
far = analyze_factor(
factor=factor_df,
# start_date 和 end_date 默认会使用 factor_df 的日期范围
weight_method='mktcap',
industry='jq_l1',
quantiles=5,
periods=(1, 5, 10)
)
总结
- 如果你传入的是因子定义类,可以直接使用
skip_paused=True过滤停牌。 - 如果你需要过滤涨停,或者你传入的是已经计算好的因子值 DataFrame,请务必在调用
analyze_factor之前,利用get_price等 API 获取停牌和涨跌停状态,将不需要的股票因子值替换为np.nan。