问题描述
看好多策略在买入股票的时会取get_current_data()下的last_price,如果last_price小于等于0或者为None的时候就会放弃买入该股票
想问一下为什么会出现last_price为None或者小于等于0的情况?
解决方案
在 JoinQuant (聚宽) 量化平台上,get_current_data() 是一个非常常用的 API,用于获取当前单位时间(当天或当前分钟)的快照数据,包括最新价 (last_price)、涨跌停价、是否停牌等。
在很多严谨的量化策略中,开发者会在买入前检查 last_price 是否大于 0 且不为 None。之所以会出现 last_price 为 None 或 <= 0 的情况,主要有以下几个原因:
1. 股票尚未上市
如果你在策略中生成了一个包含多只股票的股票池(例如通过某些条件筛选出了一批代码),但在回测运行到某一天时,其中某只股票还未正式上市交易。此时系统无法获取到该股票的有效交易价格,last_price 就会返回 None 或 NaN。
2. 股票已经退市
与未上市类似,如果股票池中包含了已经退市的股票,在退市日期之后,该股票不再有交易行情,获取其最新价时也会返回无效值。
3. 长期停牌或数据缺失
虽然通常情况下,股票停牌时 last_price 会返回停牌前的最后一个收盘价,但在某些极端情况下(例如停牌时间过长、跨越了某些数据调整期,或者底层数据源在特定历史日期存在缺失),可能会导致获取到的价格异常(如为 0 或 None)。
4. 集合竞价或首日上市的特殊时段
根据官方文档,在 09:30 之前调用 get_current_data(),last_price 会返回昨日收盘价。但如果是新股上市首日的集合竞价阶段,由于没有“昨日收盘价”,此时获取的价格可能会出现异常。
5. 动态复权导致的计算异常
在开启了动态复权(use_real_price = True)的情况下,如果遇到极端的拆合股或分红事件,历史数据在某些特定时间点的映射可能会出现计算上的极小值甚至异常值。
为什么策略要主动放弃买入?(防御性编程)
在代码中加入 if last_price <= 0 or last_price is None: 的判断,是一种非常好的防御性编程习惯:
- 避免下单报错:如果以
None或0作为价格去计算买入数量(如cash / last_price),会导致ZeroDivisionError或类型错误,直接让整个策略崩溃。 - 避免买入无效标的:过滤掉未上市、已退市或数据异常的股票,确保资金只买入处于正常交易状态的标的。
标准的处理代码示例
def handle_data(context, data):
current_data = get_current_data()
for stock in g.buy_list:
# 获取当前数据对象
stock_data = current_data[stock]
# 1. 检查是否停牌、是否退市/未上市
if stock_data.paused:
continue
# 2. 获取最新价
last_price = stock_data.last_price
# 3. 防御性检查:价格必须有效且大于0
if last_price is None or last_price <= 0:
log.warn(f"股票 {stock} 的最新价无效: {last_price},放弃买入")
continue
# 4. 计算买入数量并下单
cash = context.portfolio.available_cash
if cash > 0:
order_value(stock, cash)
总结来说,出现 None 或 <= 0 主要是因为标的在当前时间点处于非正常交易生命周期(未上市/已退市)或底层数据缺失。加上这层判断可以显著提升策略在长周期回测和实盘模拟中的健壮性。