🚀 AI 一键生成 joinquant 策略代码

JoinQuant量化平台可转债数据除零报错(divide by zero)原因分析与解决指南

joinquant | 发布时间: 2026/5/27
以下内容由 EasyQuant 生成。

问题描述

老出现除零报错提示...

/opt/conda/lib/python3.6/site-packages/ipykernel_launcher.py:183: RuntimeWarning: divide by zero encountered in double_scalars


df1 = bond.run_query(query(bond.CONBOND_DAILY_PRICE).filter(
bond.CONBOND_DAILY_PRICE.date == run_date))
之前这样调去可转债历史行情的时候
出现过有的可转债收盘价为0的情况~

后面写的程序较大~不知道是否可转债转股价也会出现0的情况~
还有正股的收盘价是否也会出现0的情况....

老出现这种情况真是不好处理啊...
想问问数据到底咋了?是因为停牌 强赎出现收盘价为零吗?

解决方案

在量化回测和数据处理中,遇到 RuntimeWarning: divide by zero encountered in double_scalars 是非常常见的现象。针对您在 JoinQuant 平台查询可转债数据(如 CONBOND_DAILY_PRICE)时遇到的收盘价、转股价或正股价格为 0 的问题,以下是详细的原因分析及处理方案:\n\n### 一、 为什么数据中会出现 0?\n\n1. 停牌(Suspension):部分数据表中,如果某只可转债或正股在特定日期全天停牌,且没有产生成交,其当天的收盘价、最高价、最低价等字段可能会被记录为 0 或 NaN(取决于具体底层表的处理逻辑)。\n2. 退市与强赎(Delisting / Forced Redemption):当可转债触发强赎并最终摘牌退市后,如果您依然在查询该代码退市后的日期,行情数据通常会缺失,部分字段可能会以 0 填充。\n3. 未上市或未进入转股期:对于转股价而言,如果可转债刚刚发行尚未进入转股期,或者数据源在某些特定历史区间存在缺失,转股价字段可能会出现 0 或空值。\n4. 正股价格:正股的收盘价在极少数极端停牌或退市情况下也可能为 0。不过,如果您使用的是 JoinQuant 的 get_price API 且设置了 skip_paused=False,系统通常会用停牌前一天的价格进行前向填充(Forward Fill),从而避免 0 的出现。但直接查底层 SQL 表(如 run_query)时,获取的是最原始的数据,0 或 NaN 出现的概率更高。\n\n### 二、 如何在代码中优雅地处理除零异常?\n\n为了保证大型程序的健壮性,不能假设获取到的价格数据永远大于 0。建议在进行除法运算前,进行严格的数据清洗和异常值处理。\n\n#### 1. 数据过滤(剔除 0 和 NaN)\n在获取到 DataFrame 后,第一时间过滤掉价格为 0 或缺失的行:\n\npython\nimport pandas as pd\nimport numpy as np\n\n# 假设 df1 是您通过 run_query 获取的数据\ndf1 = bond.run_query(query(bond.CONBOND_DAILY_PRICE).filter(\n bond.CONBOND_DAILY_PRICE.date == run_date))\n\n# 剔除收盘价为0或NaN的异常数据\ndf1 = df1[df1['close'].notnull() & (df1['close'] > 0)]\n\n\n#### 2. 安全除法(Safe Division)\n如果您需要保留这些行(例如为了保持矩阵维度),但在计算时不希望报错,可以使用 numpy.where 或 Pandas 的内置方法来进行安全除法:\n\npython\n# 假设要计算 某指标 = 100 / close\n# 当 close 为 0 时,将其替换为 NaN,避免除零报错\ndf1['close_safe'] = df1['close'].replace(0, np.nan)\ndf1['indicator'] = 100 / df1['close_safe']\n\n# 或者使用 np.where\ndf1['indicator'] = np.where(df1['close'] > 0, 100 / df1['close'], np.nan)\n\n\n#### 3. 结合停牌与退市信息\n在编写策略时,建议结合可转债和正股的停牌状态以及退市日期进行双重过滤。不要对已经退市或正在停牌的标的进行交易计算。\n\n### 总结\n底层数据库(尤其是直接通过 run_query 查询的表)保留了最原始的市场状态,停牌、强赎退市、未上市等都会导致价格字段为 0。在量化投研中,标准的数据处理流程必须包含“异常值清洗(去极值、去零、去空值)”这一环。 养成在除法分母处加一个极小数(如 1e-9)或使用 replace(0, np.nan) 的习惯,可以彻底根除此类报错。