FinRobot 失败案例实验室 / AI4Finance-Foundation

FinRobot 失败案例实验室:报错原文、数字血缘与后验评估

只展示成功截图的项目介绍没有判断价值。本页收集的是「这套系统在什么条件下会自己停下来、会输出什么报错、根因在哪一层」:本站在本机真跑官方确定性算子,触发了四道估值闸门与两类输入校验,并把这些原文报错逐条记下来。全部案例都能用固定 commit 的源码核对,不用相信我转述。

实测基准:commit 2717499案例:报错原文可核对审计:代码算 / LLM 写
输入层取值越界 / NaN
算子层闸门拒绝计算
叙述层数字对不上报警
输出层撤回点目标只给区间
从输入到输出的四层失败拦截示意;本页每个案例都标注了它拦在哪一层、原始输出是什么。
复现方式本机跑官方算子(无 LLM、无网络)
估值闸门四道,触发即拒绝计算
输入校验NaN 与越界参数被拒
核验基准commit 2717499(2026-09-28)
案例一览

这批失败案例分别在什么条件下会被触发?

下表是全页导航。最后一列写清了证据强度:标「本站实测」的是我在本机真跑出来的输出与报错原文;标「源码/注释」的来自仓库代码及其注释,能定位到具体文件。

案例拦截层触发条件证据强度为什么值得你知道
终端增长率 ≥ WACC估值算子模型给的 tg 超过或接近折现率本站实测(报错原文)Gordon 永续式在数学上失效,继续算就是编数字
WACC 与 tg 利差过薄估值算子利差低于 1.5%(低利率、高杠杆标的常见)本站实测(报错原文)乘数会爆炸成几百倍,站内实测出现过 294×
稳态终端自由现金流 ≤ 0估值算子低毛利叠加高资本开支本站实测(报错原文)负现金流会被资本化成负终值,算出负的「每股价值」
净负债超过企业价值估值算子高杠杆或现金流失衡本站实测(报错原文)股本价值为负没有经济含义,代码注释称之为 BUG-074 的镜像
输入里出现 NaN输入校验数据源缺值被原样传进算子本站实测(报错原文)NaN 通过所有比较运算,不拦住就会把 NaN 一路带到结论
ΔNWC 比例越界输入校验营运资本假设超出 ±50% 建模带本站实测(报错原文)坏假设在很早期就被拒绝,而不是算出一个离谱结果
给银行股套 FCF-DCF流程层(类目判断)标的被判为金融业本站实测 + 源码注释代码注释记录了曾出现「DCF 719 对现价 325」的荒谬 2.2 倍估值行
叙述里没有任何数字审计算子LLM 写出「估值有吸引力」这类无据表述本站实测 + 源码注释项目自己的盲审发现过 GOOGL/MSFT/KO 报告出现这类段落
数据缺失后的降级输出与制品层同业数据、历史估值带、前瞻指标缺项本站实测(警告原文)方法行会被隐藏并留下警告,而不是拿占位数据凑数
版本错配(PyPI 装到零依赖 V0)环境层照老教程用 pip install finrobot本站实测(PyPI + sdist 核查)「装上了」与「能用」是两件事,详见安装页与版本页
怎么读这份清单:它不是在说这个项目「bug 多」,恰恰相反——这些拦截点的存在说明系统在无法给出可信数字时会选择停下来。一个不会失败的金融 Agent 才更值得怀疑。真正需要你警惕的是最后一类:环境与版本层面的错配,那一类系统不会替你拦住。
案例组 A

估值算不出来时,系统会怎么拒绝?

下面六条全部是本机真跑官方算子得到的原始报错(合成输入,非真实行情)。它们对应的是同一套估值算子里不同的前置判断,所以报错文本各不相同——这正是你排查时该抓的东西。

触发输入实际输出(原文)根因系统给出的解法残余风险
终端增长率 0.05、折现率被压到 0Terminal growth rate 0.05 must be less than WACC 0.0 (Gordon Growth Model perpetuity is undefined when tg >= wacc)永续增长模型在 tg ≥ WACC 时数学上无定义拒绝计算,由流水线回落到相对估值回落后你拿到的是倍数法区间,不是内在价值
低利率 + 高杠杆,使 WACC 与 tg 利差降到 0.34%WACC−terminal growth spread 0.34% is below the 1.5% minimum — the Gordon multiplier (1/(wacc−tg) = 294×) …乘数被利差放大,0.34% 对应 294 倍以 1.5% 为下限拒绝,提示改用相对估值利差在 1.5%–3% 之间的标的仍会得到很宽的估值区间
EBITDA 利润率降到 2%、资本开支 6%Steady-state terminal FCF is non-positive (-5.94); …a negative implied price. DCF is not applicable…稳态现金流为负,Gordon 会资本化成永续负值拒绝计算,跳过 DCF 章节真处于衰退期的公司本就该用别的框架,这里只是避免输出负价格
净负债放大到 100000(企业价值仅 2510)Equity value is non-positive (-9.75e+04): net debt (1e+05) exceeds the enterprise value (2.51e+03). A negative per-share fair value is not meaningful…股本价值为负没有经济含义(股本更像一个下限为零的期权)拒绝计算,提示改用相对估值或困境/信用分析真实高杠杆标的仍需人工判断是否处于困境
营收基数传入 NaNValidationError: revenue_base / Value error, must be finite — NaN/Inf is not a number, it's missing dataNaN 与任何数比较都为假,会绕过算子里所有区间判断在校验层直接拒绝(带界字段天然拒绝 NaN,无界字段单独加校验)上游数据源若返回空值而非 NaN,仍可能被解释成 0
ΔNWC 占营收 0.9ValidationError: nwc_pct_revenue / Input should be less than or equal to 0.5假设超出建模带,属于口径错误而非极端情形字段级边界拒绝,给出允许区间区间内的坏假设仍会通过,需要你自己把关
复现方式(可自行核对):按固定 commit 2717499 取出 finrobot_desktop/finrobot/engine/compute/operators/ 与 models/,用本机 Python 3.11.9 直接调用 calculate_dcf 即可得到同样文本——这些算子是纯 Python,不需要 LLM,也不需要联网。输入是本站构造的合成数据,仅用于观察行为,不代表任何真实标的。
案例 B

给银行股套 DCF 会发生什么?

这不是数值问题,而是用错方法的问题:银行的「自由现金流」和「净负债」本身定义就不成立——债务是它的原材料,不是融资手段。项目处理方式值得单独看:它按行业类别把方法整体撤下,而不是硬算。

观察点实际行为说明
代码里有没有这类判断有:入参带 financial_sector 标记,估值聚合器按它抑制现金流类方法判断依据来自行业识别原语(是否银行/保险)
本机实测(金融业标记打开)现金流类方法全部被撤下,返回的方法数为 0,point_target 与 confidence 均为空系统没有给出一个「看起来像结论」的数字
同时给出的警告(原文节选)dcf: financial-sector issuer — FCF-DCF does not apply… method withheld、ev_ebitda: …enterprise value is a category error for banks (debt is raw material, not financing) — method withheld不是静默隐藏,而是留下「为什么撤下」的理由
为什么值得警惕代码注释记录了历史现象:某银行标的曾出现 DCF 结果与现价差 2.2 倍(约 719 对 325)那类结果会污染货币权重与分歧判断
正确做法银行/保险改用 P/B、P/E 与股利折现(DDM)为主这是行业惯例,也是项目在代码里写下的取舍
残余风险行业识别本身可能误判(例如金融控股、租赁类)判断错时方法会被错误撤下或错误启用;上线前需人工确认标的类别
这一节真正要学的是思路:多数金融 AI 演示的失败不在算术,而在用错模型。让系统在算之前先判断「这个标的该不该用这套方法」,比算得快更重要。本站把这个案例放在估值闸门之后就因为这一点。
案例 C

「数字由代码算」之外,LLM 写的那部分怎么防?

数字可以交给算子,但叙述仍是模型写的。项目为此加了一个审计算子,专门检查叙述里有没有没有任何数字支撑的段落。它的由来写在源码注释里,是一次真实的盲审。

项目内容
盲审发现的三个实例(源码注释原文转述)GOOGL 用被夸大的头条市盈率为「估值有吸引力」背书,却略过了自己的核心市盈率;MSFT 的多头理由只有「护城河强」这类没有数字的表述;KO 的催化剂条目既没有日期也没有量级
怎么判定「有数字」剔除纯年份(1900–2099)与序数词(1st/2nd…)后,若还剩任意数字才算有支撑——避免把「2025 年」误当成数字依据
本机实测:无据叙述返回告警原文 [NARRATIVE-NUMERIC] 3 narrative field(s) carry no supporting number (narrative, catalysts[0], risks[0]) …
本机实测:带数字叙述同一算子返回 None(无告警)
它不会做什么只产出非阻塞警告,从不修改结论方向、目标价与置信度
设计取舍它是「轻量信号」:不做货币/百分比语义解析,也不逐条比对提示词白名单,宁可漏报也不误报
残余风险句子里碰巧带了个无关数字(例如文件条目号)也会被算作「有支撑」
给你的实用做法:无论用哪套工具,读完一段叙述就回问一句「这句话里的数字在计算输出里能找到吗」。找不到就把它当观点,不当结论。这条检查不需要任何工具,却是防止被流畅文字带偏最有效的一步。
案例组 D

数据缺失时会发生什么?三种降级行为

「取数失败」在多数系统里表现为静默的空表,之后被当成 0 或用别的数据凑上。这里记录三种可核对的降级行为,并标出你要补的输入。

缺失项系统的实际行为你该补什么
同业比较数据(comps 制品)警告原文:comps_pe: no peer_analysis artifact — this row appears after running the full AI report;对应方法行不出现跑完整研报流程,让同业分析制品先产出
历史估值带或 TTM EBITDA警告原文写明「multiple row degraded and hidden」——方法行被降级隐藏,而不是用 0 或均值顶上确认该标的的历史估值数据与 TTM 口径可获取
前瞻自由现金流同样以降级隐藏处理(P/FCF 行缺失并留警告)补齐前瞻指标来源,或接受更少的方法数
蒙特卡洛里的无效路径本机实测 2000 条里 1996 条有效,其余被丢弃;结果只统计有效路径不用处理,但要知道分位数来自有效子集
只有单一估值方法时该方法区间会被标注为占位带,原文:implied_price ± 20% (placeholder band, not a real distribution)补第二种方法,否则不要把这个区间当统计分布
数据提供方整体不可用7 个提供方共用接口、带健康状态(可用/已保存/可选/冷却中),故障时按状态切换至少确认两个提供方可用,避免单点
值得学的一条:把「缺数据」显式化成一条可读的警告 + 少一行结果,而不是一个看起来正常的数字。「placeholder band, not a real distribution」这种自我标注,是判断一套金融 AI 是否诚实的最快线索。
案例组 E

版本与文档错配会怎么失败?系统不会替你拦的那一类

前面几组是系统主动拒绝,这一组是系统不会拒绝、但结果一定不对的情形——它们更常见,也更容易让人误判「这个项目不行」。

现象真实原因核对方式正确做法
pip install finrobot 装完却 ModuleNotFoundError: No module named 'finnhub'PyPI 上是 2024-06-17 的 0.1.5,sdist 里没有依赖清单文件,打包时依赖列表被置空看包元数据里有没有 Requires-Dist;看 sdist 里有没有 requirements.txtV0 走仓库根 pip install -e .;要 V2 走 uv sync
按文章里的目录找不到 notebook教程目录已迁到 finrobot_autogen/,且分为 beginner / advanced 两层在固定 commit 的仓库树里核对路径按当前仓库路径执行
想调用 README 里提到的调度器却发现没有README 的「Research foundation」段保留的是论文期设计说明,当前仓库没有对应实现在仓库里搜索对应模块名按 V2 的类型化流水线思路理解编排
用 3.12 装不上 V0 包PyPI 元数据限定 >=3.10, <3.12;V2 则要求 >=3.11看两边包定义里的 Python 约束V0 用 3.10/3.11 环境,V2 用 3.11+ 环境,分开建
两个版本装在同一环境互相覆盖发布名与导入名都落在 finrobot 上检查同一环境里是否出现两份包记录一个版本一个隔离环境
拿 V0 的输出当研究结论官方明确 V0 没有确定性计算层与溯源跟踪,不保证数字是算出来的看官方 README 对 V0 的定位表述需要可追溯结果就用 V2
这一组案例的共同点:它们不会报错、也不会给你任何提示,只是让你得到一份看起来合理的错误结果。所以建站与用站时,先确认版本,再确认路径,最后才看结果,顺序不要颠倒。
审计方法

数字血缘:怎么判断一个数字是谁产生的?

适用任何金融 AI 输出,不限于本项目。核心是把输出里的每一项拆进三个桶,然后对每个桶采取不同的信任策略。

桶怎么识别信任策略本项目里的对应物
代码算出来的能对应到具体函数调用与入参;改一个假设,数字会按确定规则变化可以复核:重算一遍应得同样结果26 个估值算子(DCF/DDM/LBO/倍数/蒙特卡洛/SOTP/剩余收益等)
模型写出来的段落、观点、定性与因果解释;无法回溯到某个函数当观点处理:不做结论,只做线索研报叙述、催化剂与风险条目、章节小结
两者混合数字来自算子、结论来自模型(例如「目标价 23.1,较现价有 15% 上行空间」)拆开看:数字复核,判断打折投资论点、评级与目标价表述、置信度说明
审计产生的警告、降级标记、撤回决策优先读:它告诉你哪一部分不可信6 个审计算子(币种口径、EV 桥、叙述分歧、数字绑定性、行业符号、TTM 期间)
可复现记录五要素(建议每次都记):① 环境(系统 + Python 版本 + 是否装了 uv/Node)② 版本与提交(release 或 commit 号,本项目本站用 2717499)③ 模型与数据源(模型名、数据来自哪个 provider、有无免费额度限制)④ 命令与输入(完整命令 + 输入参数;合成数据要写明是合成的)⑤ 输出与耗时(原始输出片段 + 单次运行时长)。
本站自己就是按这五要素记录的:环境 Windows 10 / Python 3.11.9;版本 commit 2717499;模型 无(纯算子);输入 本站构造的合成标的;输出 WACC 9.509%、隐含价 23.0774、蒙特卡洛中位 23.11。有了这五行,别人才能真正复核你,而不是只能相信你。
评测与后验

怎么给一次金融 AI 输出打分?

不要只看结果对不对(一次运行说明不了什么),要看它是否具备可复核的结构。下面这张表可以直接当验收清单用。

评测维度通过标准不通过时的表现怎么查
事实准确性公司名、行业、报告期、币种与官方一致币种混用、报告期错位抽一条关键事实回官方披露核对
数字准确性关键数字能被独立重算数字无法回溯到任何计算用同一套假设手算 DCF 的头一段
口径一致性单位、币种、期间在全篇统一同一指标前后单位不同搜币种符号与单位词,看是否漂移
引用完整性数据来源可指名到 provider 与时间只写「根据市场数据」查制品里有没有取数时间戳
可复现性同环境同输入可得到同样结果换个时间跑结果就变,且原因不明固定随机种子重跑(本项目的蒙特卡洛支持 seed)
失败可见性缺数据时给出警告或降级标记缺数据静默填 0 或省略不提看输出里有没有 warning 通道
成本与延迟记录单次运行的模型调用量与耗时只有结果没有账单按任务规模分档记录(单标的/单板块/多标的)
后验校验把「方向性判断」和「实际结果」分开记录,不混着算胜率用后见之明宣布模型很准事前写下判断与依据,事后单独复盘
关于成本与延迟:本项目官方文档没有给出统一的成本表,因为这取决于你选的模型、数据源与任务规模。可行的做法是把它分成三档记录——单标的快问(如查一只股票的估值)、单一板块筛选、完整研报流水线——每档只记「模型调用是否发生、数据源调用次数、耗时、重试次数」。具体单价以各家官方定价页为准,本页不给数字。
最后一句边界:任何历史回测与方向性预测都不构成收益承诺;本页所有数值来自本站构造的合成输入,仅用于观察系统行为,不构成投资建议。
FAQ

FinRobot 失败与审计常见问题

为什么一个估值系统要设计这么多「拒绝计算」?

因为金融模型失效的方式往往不是算错,而是在不适用的情况下仍然给出数字。永续增长、负现金流、负股本价值这几类情形都会产生数学上成立、经济上无意义的解。与其输出一个会被误用的数,不如停下来并告诉调用方「改用相对估值」。官方 README 也是这么定位的:模型负责推理、软件负责计算、系统负责验证。

这些报错原文我能自己复现吗?

可以。相关算子在 finrobot_desktop/finrobot/engine/compute/operators/ 下,是纯 Python,不依赖 LLM 与网络,只需要装了 pydantic 的环境。按固定 commit 取出代码,构造同样的输入即可得到同样文本。本站的实测环境是 Windows + Python 3.11.9,输入是合成数据。

「数字由代码算」之后,我是不是就可以相信结论了?

不是。代码算解决的是数字不被编造,但没有解决假设是否合理、方法是否适用、以及方向性判断是否成立。假设是模型选的或你填的,方法适用性由类目判断决定,方向性结论仍然只是观点。事实底稿、源码路径与固定 commit 都写在页面里,建议你自己抽一两项核对。

审计算子报警了,报告就会被拦下吗?

不会。以叙述数字绑定性这个算子为例,它只产出非阻塞警告,放进输出的警告通道,不会改写结论方向、目标价与置信度。设计上它是「轻量信号」而不是守门人——这一点在源码注释里写得很明确。真正会拦截输出的是前面的估值闸门与输入校验。

缺数据时会不会悄悄用 0 或平均值顶上?

从实测看不会。缺少同业数据、历史估值带或前瞻指标时,对应方法行会被降级隐藏并留下写清原因的警告;方法只有一种时,区间会被标注成「占位带,不是真实分布」。这正是判断一套输出是否诚实的线索:看它缺数据时是沉默还是留痕。

什么样的失败才是真正要担心的?

系统主动拒绝的那些反而不是问题——它们可见、可查、可复现。真正要担心的是不会报错的那一类:版本装错(PyPI 上零依赖的旧包)、路径变了、把论文期设计当成现成实现、用错方法但算得出来。这些只能靠「先确认版本与环境、再确认方法与假设、最后才看结论」的流程来防。

这套审计思路只能用在 FinRobot 上吗?

不是。三个桶(代码算 / 模型写 / 混合)与可复现记录五要素对任何金融 AI 输出都适用。你甚至可以对别的工具用同一套问法:这个数字能回溯到哪一步计算?缺数据时它怎么表现?换一天跑结果会不会变?这三个问题答不上来的工具,输出就只适合当线索。

看清失败方式之后,回去看数字到底怎么算出来的

确定性估值引擎页给出 26 个算子 + 6 个审计算子的分工,以及本站真跑 DCF、敏感性分析与蒙特卡洛的输出。