3. 成本预测核心指标:CPI、SPI、EAC、ETC 的计算公式与业务含义
在挣值管理(EVM)体系中,成本绩效指数(CPI)、进度绩效指数(SPI)、完工估算(EAC)和完工尚需估算(ETC)是四个最核心的量化指标。它们将原始测量数据(PV、EV、AC)转化为可决策的预测信号,是成本偏差分析与纠偏的“仪表盘”。
3.1 核心绩效指数:CPI 与 SPI
CPI 和 SPI 是衡量项目当前“成本效率”和“进度效率”的无量纲比率,通常以周或月为周期滚动计算。
| 指标 | 计算公式 | 业务含义 | 临界值解读 |
|---|---|---|---|
| CPI | CPI = EV / AC |
每实际花费 1 元,完成了多少预算价值的工作。 | CPI > 1:成本节约;CPI = 1:按预算;CPI < 1:成本超支。 |
| SPI | SPI = EV / PV |
按计划进度,实际完成了多少比例的工作。 | SPI > 1:进度超前;SPI = 1:按计划;SPI < 1:进度滞后。 |
实战经验:CPI 和 SPI 应结合“趋势线”而非单点值判断。连续 3 个报告周期 CPI < 0.9 且 SPI < 0.9,通常触发项目预警,需启动纠偏计划。
3.2 完工估算(EAC)与完工尚需估算(ETC)
EAC 和 ETC 是项目成本预测的“终点线”指标。EAC 代表项目完工时的总成本预测,ETC 代表从当前时点开始还需要多少成本才能完成剩余工作。根据项目实际绩效与未来假设,EAC 有四种典型算法。
| 预测场景 | EAC 公式 | ETC 公式 | 适用条件 |
|---|---|---|---|
| 典型偏差(按当前 CPI 继续) | EAC = BAC / CPI |
ETC = EAC - AC |
成本偏差由普遍性效率问题导致,未来不会改善 |
| 非典型偏差(仅过去偏差,未来按计划) | EAC = AC + (BAC - EV) |
ETC = BAC - EV |
成本偏差由一次性事件导致,未来回归预算效率 |
| 同时考虑 CPI 和 SPI | EAC = AC + (BAC - EV) / (CPI × SPI) |
ETC = (BAC - EV) / (CPI × SPI) |
成本与进度均存在偏差,且相互影响 |
| 重估(自下而上估算) | EAC = AC + 自下而上 ETC |
重新估算剩余工作 | 项目发生重大变更或原始估算失效 |
关键决策点:选择哪种 EAC 公式,取决于项目经理对“未来绩效是否与过去一致”的判断。在实战中,典型偏差模型(EAC = BAC / CPI)是最常用的保守预测,因为它假设低效率将持续到项目结束。
3.3 指标联动与业务决策
四个指标不是孤立存在的,它们共同构成一个“测量 → 分析 → 预测 → 决策”的闭环。以下是一个典型的联动分析场景:
- 测量阶段:获取 PV、EV、AC 原始数据。
- 效率分析:计算 CPI 和 SPI,判断成本与进度偏差的性质(典型/非典型)。
- 预测阶段:根据偏差性质选择 EAC 公式,计算 EAC 和 ETC。
- 决策阶段:对比 EAC 与 BAC,计算完工偏差(VAC = BAC - EAC)。若 VAC 为负,说明预测超支,需启动纠偏。
常见误区:不要将 ETC 简单理解为“剩余预算”。ETC 是基于当前绩效的预测值,而剩余预算(BAC - EV)是理想值。当 CPI < 1 时,ETC 通常大于剩余预算,这才是真实的资金需求。
3.4 实战代码示例:Python 计算核心指标
以下代码演示如何根据 PV、EV、AC 和 BAC 批量计算 CPI、SPI、EAC 和 ETC,并输出预测报告。
import pandas as pd
def calculate_evm_metrics(pv, ev, ac, bac, scenario='typical'):
"""
计算 EVM 核心指标
:param pv: 计划价值
:param ev: 挣值
:param ac: 实际成本
:param bac: 完工预算
:param scenario: 预测场景 ('typical', 'atypical', 'composite')
:return: 包含所有指标的字典
"""
# 绩效指数
cpi = ev / ac if ac != 0 else 0
spi = ev / pv if pv != 0 else 0
# 完工估算与完工尚需估算
if scenario == 'typical':
eac = bac / cpi if cpi != 0 else 0
etc = eac - ac
elif scenario == 'atypical':
eac = ac + (bac - ev)
etc = bac - ev
elif scenario == 'composite':
eac = ac + (bac - ev) / (cpi * spi) if (cpi * spi) != 0 else 0
etc = (bac - ev) / (cpi * spi) if (cpi * spi) != 0 else 0
else:
raise ValueError("scenario must be 'typical', 'atypical', or 'composite'")
# 完工偏差
vac = bac - eac
return {
'CPI': round(cpi, 3),
'SPI': round(spi, 3),
'EAC': round(eac, 2),
'ETC': round(etc, 2),
'VAC': round(vac, 2)
}
# 示例数据
data = {
'PV': [1000, 2000, 3000, 4000],
'EV': [900, 1800, 2800, 3500],
'AC': [1100, 2100, 3200, 3800],
'BAC': [5000, 5000, 5000, 5000]
}
df = pd.DataFrame(data)
# 批量计算(典型偏差场景)
results = df.apply(lambda row: calculate_evm_metrics(
row['PV'], row['EV'], row['AC'], row['BAC'], scenario='typical'
), axis=1, result_type='expand')
df = pd.concat([df, results], axis=1)
print(df.to_string(index=False))
输出示例(第 4 周期):
PV EV AC BAC CPI SPI EAC ETC VAC
1000 900 1100 5000 0.818 0.900 6111.11 5011.11 -1111.11
2000 1800 2100 5000 0.857 0.900 5833.33 3733.33 -833.33
3000 2800 3200 5000 0.875 0.933 5714.29 2514.29 -714.29
4000 3500 3800 5000 0.921 0.875 5428.57 1628.57 -428.57
解读:第 4 周期 CPI = 0.921,SPI = 0.875,成本超支且进度滞后。按典型偏差预测,EAC = 5428.57,超出 BAC 约 428.57 元(VAC 为负)。项目经理需立即分析超支原因,并考虑是否切换为“自下而上重估”场景。