问题描述
解决方案
在 JoinQuant(聚宽)平台中,获取历史行情时跳过停牌股票主要通过设置数据获取函数的 skip_paused 参数来实现。此外,在实盘或回测交易逻辑中,通常结合 get_current_data() 来判断当前是否停牌。
以下是具体的实现方法和代码示例:
1. 使用数据获取函数的 skip_paused 参数
大多数获取历史数据的 API(如 get_price, attribute_history, history)都包含 skip_paused 参数。
- skip_paused=True: 跳过停牌日期(即只返回有实际交易的数据)。
- skip_paused=False (默认): 不跳过。停牌期间的数据会用前一交易日的收盘价填充,成交量为0。
示例 A: 使用 get_price
# 获取平安银行 2023年1月1日 到 2023年2月1日 的数据
# 开启 skip_paused=True,停牌期间的行将被剔除
df = get_price('000001.XSHE',
start_date='2023-01-01',
end_date='2023-02-01',
frequency='daily',
fields=['open', 'close', 'volume'],
skip_paused=True)
print(df)
示例 B: 使用 attribute_history (常用于策略中获取过去N天数据)
def handle_data(context, data):
# 获取过去5个交易日的数据,跳过停牌
# 如果某天停牌,这天的数据不会被计入 count,系统会继续向前寻找直到凑齐5条实际交易数据
h = attribute_history('000001.XSHE', 5, '1d', ['close', 'volume'], skip_paused=True)
log.info(h)
示例 C: 使用 history
def handle_data(context, data):
# 获取股票池中所有股票过去5天的数据,跳过停牌
# 注意:如果获取多只股票且 skip_paused=True,返回的 DataFrame 索引可能不再是统一的日期
h = history(5, '1d', 'close', ['000001.XSHE', '600519.XSHG'], skip_paused=True)
2. 关于 get_bars 的特殊说明
get_bars 函数没有 skip_paused 选项。
get_bars获取的数据本身就是不包含停牌数据的(即只返回有成交的 Bar)。- 如果请求
count=5,它会返回最近的5条有交易的记录。如果中间有停牌,它会自动跨过停牌期去取更早的数据,实际上等同于跳过了停牌。
# 获取最近5条数据,如果中间有停牌,会自动取更早的实际交易日数据
bars = get_bars('000001.XSHE', count=5, unit='1d', fields=['date', 'close'])
3. 在交易逻辑中手动过滤(推荐)
在编写策略(如 handle_data 或 before_trading_start)准备下单时,通常需要判断当前是否停牌,以避免无效下单或错误计算。这时应使用 get_current_data()。
def handle_data(context, data):
security = '000001.XSHE'
# 获取当前数据快照
current_data = get_current_data()
# 判断是否停牌
if current_data[security].paused:
log.info(f"{security} 今日停牌,跳过交易")
return
# 如果未停牌,继续执行策略逻辑
close_price = data[security].close
# ... 下单逻辑 ...
总结
| API 函数 | 默认行为 | 如何跳过停牌 | 备注 |
|---|---|---|---|
| get_price | 填充停牌数据 | 设置 skip_paused=True |
获取指定时间段数据时常用 |
| attribute_history | 填充停牌数据 | 设置 skip_paused=True |
策略中获取单只股票历史常用 |
| history | 填充停牌数据 | 设置 skip_paused=True |
策略中获取多只股票历史常用 |
| get_bars | 自动跳过 | 无需设置 | 返回的数据不包含停牌时的填充数据 |
| get_current_data | N/A | 检查 .paused 属性 |
用于判断当前时刻是否停牌 |
Q&A
Q: 如果我在 attribute_history 中设置了 skip_paused=True,获取 count=5 的数据,返回的行数一定是5吗?
A: 是的。系统会忽略停牌的日期,一直向前追溯,直到凑齐 5 个实际交易日的数据为止(除非该股票上市时间太短,总交易天数不足5天)。
Q: get_price 获取多只股票时,设置 skip_paused=True 会有什么影响?
A: 如果获取多只股票且设置了跳过停牌,由于不同股票的停牌日期不同,返回的 Panel 或 DataFrame 可能会出现对齐问题。在旧版 Pandas Panel 中,索引不再是统一的日期;在 DataFrame 模式下,可能会导致数据长度不一致或包含 NaN(取决于具体的 panel 参数设置)。建议对多只股票处理时,如果需要严格对齐日期,使用默认的 skip_paused=False(使用前值填充),或者分别获取后再进行数据清洗。
Q: 为什么 get_bars 没有 skip_paused 参数?
A: 因为 get_bars 的设计初衷是获取实际存在的 K 线(Bar)。停牌期间没有交易,自然没有 K 线生成,因此它返回的数据天然就是跳过停牌的。