问题描述
解决方案
在PTrade中,要获取市场上所有可转债代码并过滤掉停牌的标的,主要需要结合使用以下两个接口:
get_cb_list():用于获取当前市场上所有的可转债代码(包含停牌的)。get_snapshot(security_list):用于获取标的的实时行情快照,其中包含trade_status(交易状态)字段,通过该字段可以判断是否停牌。
实现逻辑
- 在
initialize中设置定时任务或在before_trading_start中执行。 - 调用
get_cb_list()获取全量可转债代码。 - 调用
get_snapshot()获取这些代码的状态。 - 遍历快照数据,剔除状态为
HALT(暂停交易)、SUSP(停盘)、STOPT(长期停盘) 或DELISTED(退市) 的代码。
以下是完整的策略代码示例:
def initialize(context):
# 初始化全局变量
g.trade_cb_list = []
# 设定每天9:30开盘后执行一次筛选(确保能获取到当天的准确状态)
# 注意:如果在盘前(before_trading_start)调用get_snapshot,部分状态可能未更新
run_daily(context, filter_tradable_bonds, time='9:30')
def filter_tradable_bonds(context):
"""
获取所有可转债并过滤掉停牌标的
"""
# 1. 获取当前市场所有可转债代码
all_cb_list = get_cb_list()
if not all_cb_list:
log.info("未获取到可转债代码列表")
return
# 2. 获取行情快照
# 注意:一次性获取大量标的快照可能会比较慢,实盘中如果数量巨大建议分批获取
cb_snapshot = get_snapshot(all_cb_list)
# 3. 过滤停牌标的
# trade_status 状态说明:
# HALT: 暂停交易, SUSP: 停盘, STOPT: 长期停盘, DELISTED: 退市
# None: 获取失败或无数据
tradable_list = []
for code in all_cb_list:
# 获取单只标的的快照信息,如果获取不到默认为空字典
info = cb_snapshot.get(code, {})
status = info.get("trade_status")
# 判断状态是否正常
if status not in [None, "HALT", "SUSP", "STOPT", "DELISTED"]:
tradable_list.append(code)
# 更新到全局变量
g.trade_cb_list = tradable_list
log.info("当前市场可转债总数: %d" % len(all_cb_list))
log.info("剔除停牌后可交易数量: %d" % len(g.trade_cb_list))
# 打印前10个可交易代码示例
log.info("可交易代码示例(前10): %s" % g.trade_cb_list[:10])
def handle_data(context, data):
# 在这里进行具体的交易逻辑
# 示例:遍历筛选后的可交易列表
if g.trade_cb_list:
# 仅作演示:获取第一个可交易转债的最新价
first_cb = g.trade_cb_list[0]
if first_cb in data:
price = data[first_cb]['close']
# log.info("%s 当前价格: %s" % (first_cb, price))
pass
代码关键点说明
-
get_cb_list():- 该函数仅在交易模块可用(回测和实盘)。它返回的是一个包含所有可转债代码的列表,例如
['110033.SS', '128010.SZ', ...]。
- 该函数仅在交易模块可用(回测和实盘)。它返回的是一个包含所有可转债代码的列表,例如
-
get_snapshot():- 这是判断停牌最准确的方法。返回的字典中
trade_status字段代表当前状态。 - 重要提示:在回测模式下,
get_snapshot可能无法使用或返回模拟数据。如果在回测中需要过滤停牌,通常使用get_stock_status(stocks, query_type='HALT')替代,或者利用get_history获取数据,如果成交量为0通常意味着停牌。但在实盘交易中,get_snapshot是标准做法。
- 这是判断停牌最准确的方法。返回的字典中
-
执行时间:
- 代码中使用了
run_daily(..., time='9:30')。这是因为在早盘集合竞价结束进入连续竞价后,交易状态(trade_status)是最准确的。如果在before_trading_start(通常是9:00前)调用,交易所可能尚未推送当天的停牌信息,导致数据不准。
- 代码中使用了
-
状态过滤:
- 代码显式排除了
['HALT', 'SUSP', 'STOPT', 'DELISTED']以及None。这确保了g.trade_cb_list中只包含当前正常交易(如TRADE或START状态)的标的。
- 代码显式排除了
Q&A
Q1: 为什么不直接在 before_trading_start 里调用 get_snapshot?
A1: 在实盘交易中,before_trading_start 通常在 9:00 之前运行。此时交易所可能还没有推送完整的当日停牌信息,或者行情服务尚未连接到实时流,导致 get_snapshot 返回的数据大部分是 0 或状态不准确。建议在 9:15 之后或 9:30 使用 run_daily 调用。
Q2: 回测模式下可以使用 get_snapshot 吗?
A2: 根据 PTrade 文档,get_snapshot 仅在交易模块可用。在回测模式下,建议使用 get_stock_status(code_list, 'HALT') 来判断是否停牌,或者通过 get_history 获取日线数据,判断成交量是否为 0。
Q3: get_cb_list 返回的代码包含退市的转债吗?
A3: get_cb_list 返回的是当前市场上的代码表。如果转债已经完全退市(摘牌),通常不会出现在列表中。但如果处于退市整理期或刚停牌等待退市,可能会出现在列表中,因此必须结合 trade_status 进行过滤。