敏感性分析表(单变量与双变量)
使用场景
当策略或财务模型有一个关键输出值,并且需要展示该输出值随一个或两个驱动变量在范围内变化时的响应时使用。常见的驱动变量包括价格、销量、折现率、增长率、流失率或单位成本。此技能在 Claude 应用中从头构建一个可下载的 .xlsx 文件(使用 openpyxl 和 numpy),包含实时公式和重新计算验证。它并非 Claude for Excel 插件。
构建内容
一个独立的「敏感性」标签页,附加到现有模型上。它引用模型的输入单元格和输出单元格,布局单变量和双变量网格,并对结果块应用色标。如果源模型位于其他工作表,网格将通过跨工作表引用进行链接,保持实时更新。
构建工作流
- 识别输出单元格(例如
Model!B40存储 NPV)以及一个或两个驱动该输出的输入单元格(例如Model!B6折现率、Model!B7增长率)。 - 确认输出是一个基于这些输入变量的实时公式链。如果输出是硬编码的,请停止并先建立模型公式;在常量上创建数据表将返回常量值。
- 选择围绕基准情况的输入范围(例如基准折现率 10%,扫描范围 6% 到 14%,步长 2%)。
- 构建原生 Excel 数据表结构:拐角公式、输入轴以及
{=TABLE(r,c)}数组(参见规格)。 - 同时构建基于代码计算的备用网格:在 Python 中重新评估每个输入组合下的模型,并将结果值写入带标签的矩阵。
- 对结果块应用三色标度,并用输入单元格名称标注两个轴。
- 添加检查块。
- 在真实引擎(headless LibreOffice)中重新计算工作簿。
- 验证零公式错误(#REF!、#DIV/0!、#VALUE!、#NAME?),确认检查通过,然后交付 .xlsx 文件。
逐标签页规格
敏感性标签页,单变量块
选择布局方向。对于输入沿列向下排列的情况:
B3:输出公式,引用实时输出:=Model!B40。这是拐角单元格。A4:A10:扫描的输入值(蓝色输入),例如 6%、8%、10%、12%、14%。B4:B10:数据表结果列。- 选择
A3:B10,然后数据 > 假设分析 > 数据表,将行输入单元格留空,并将列输入单元格设置为Model!B6。Excel 将{=TABLE(,Model!B6)}写入B4:B10。 - openpyxl 可以将数组公式字符串
=TABLE(,Model!B6)写入块以及=Model!B40拐角,但数值只有在真实引擎中重新计算后才会填充。
同一块的代码计算备用(建议在通过代码生成时使用),写入以下方开始的带标签矩阵,例如从 A14 开始:
A14:标签“折现率”。B14:“NPV(计算值)”。- 对于
A15:A21中的每个输入值,Python 将Model!B6设置为该值,在 numpy 中重新计算模型逻辑,并将结果 NPV 作为普通值写入 B 列。 - 保留两者:原生数据表证明它是实时的;计算矩阵确保即使在用户打开 Excel 之前也有填充好的数字。
敏感性标签页,双变量块
- 拐角单元格
E3:=Model!B40(实时输出)。 E4:E10:沿左边缘向下的行输入值(第一个驱动变量,例如增长率 0%、1%、……6%)。F3:L3:沿顶部行的列输入值(第二个驱动变量,例如折现率 6%……14%)。- 选择
E3:L10,数据 > 假设分析 > 数据表,行输入单元格 =Model!B7(横向驱动变量),列输入单元格 =Model!B6(纵向驱动变量)。Excel 用{=TABLE(Model!B7,Model!B6)}填充F4:L10。 - 注意方向:与顶部行绑定的单元格放在行输入单元格;与左侧列绑定的单元格放在列输入单元格。交换它们会导致结果静默转置。
- 代码计算备用:在 Python 中对两个轴进行双重循环,将值矩阵写入带标签的块(如果轴从模型提取则轴标题为绿色,如果是文字扫描值则为蓝色)。
选择轴范围
- 将每个轴居中于基准值,使基准位于中间行和中间列,从而使中心单元格检查有意义。
- 使用奇数步数(5、7 或 9),使单个中间单元格与基准值精确对齐,而不是落在两个单元格之间。
- 每个轴上的步长保持均匀(恒定增量),以便网格显示为清晰的梯度,色标易于解读。
- 对于比率,以绝对点数(8%、10%、12%)扫描,而不是相对于基准的百分比,以避免读者混淆。
openpyxl 构建说明
- 将拐角写为真实的公式字符串:
ws["B3"] = "=Model!B40"。不要粘贴输出的当前数值。 - 对于原生数据表数组,openpyxl 可以存储
=TABLE(...)文本,但必须由真实引擎重新计算才能填充块;将数组视为占位符,直到重新计算步骤运行。 - 在写入计算备用时,使用 Python 设置数据值(
ws.cell(row=r, column=c, value=float(npv))),并通过标题备注(如“计算快照”)使其在视觉上与实时块区分开来。 - 使用
openpyxl.formatting.rule.ColorScaleRule对结果块应用色标,将最小值映射到一种颜色,最大值映射到另一种颜色,中间有一个中点。
公式与格式约定
- 蓝色字体用于输入(你键入的扫描轴值)。
- 黑色字体用于表中的公式。
- 绿色字体用于跨工作表链接,例如
=Model!B40。 - 公式所在位置不得使用硬编码:拐角单元格必须为
=Model!B40,绝不能键入基准数值。 - 每行或每列使用一个一致的公式:整个数据表块是一个数组;计算备用使用一个应用于整个网格的 Python 表达式。
- 数字格式:比率用
0.0%,货币输出用#,##0,比率用0.00。轴值与它们所替换的输入单元格的单位保持一致。
检查
- 拐角单元格等于实时输出:
=(B3=Model!B40)返回 TRUE。 - 轴已使用输入单元格名称标注(每个轴上方或旁边的文本标签,命名驱动变量及其单元格地址)。
- 网格中心与基准情况匹配:位于基准行和基准列的网格单元格等于模型的当前输出,
=(<center cell>=Model!B40)为 TRUE。 - 对于计算备用,基准输入处的单元格等于相同输入处原生数据表单元格的值(在四舍五入范围内)。
重新计算并验证
使用 openpyxl 保存,然后进行 headless 重新计算(例如 libreoffice --headless --convert-to xlsx),使 =TABLE(...) 和跨工作表链接填充。重新加载并扫描每个单元格,查找 #REF!、#DIV/0!、#VALUE!、#NAME?。确认三个检查返回 TRUE。如果出现任何错误或 FALSE,修复引用或范围并循环直至清除,然后交付。
需要收集的输入
- 源模型的路径以及确切的输出单元格地址。
- 要扫描的一个或两个输入单元格地址。
- 基准值以及每个轴所需的范围和步长。
- 单位和轴及输出的首选数字格式。
示例
假设模型:Model!B40 = 项目 NPV,驱动变量为 Model!B6 折现率(基准 10%)和 Model!B7 收入增长率(基准 3%)。单变量块扫描折现率从 6% 到 14% 步长 2%,得到 NPV 为(假设单位)1,210 / 980 / 760 / 560 / 380。双变量块交叉增长率 0% 到 6% 与折现率 6% 到 14%;中心单元格在增长率 3% 和折现率 10% 处等于 Model!B40 的 760,确认基准情况位于网格中间。