用 TypeScript 实现贷款 IRR:从还款现金流计算年化利率

简介: 本文详解如何用 TypeScript 实现贷款真实年化利率(IRR)计算:基于实际到账金额与各期还款现金流,通过二分法求解月度 IRR,并换算为复利年化利率((1+r)¹²−1),强调手续费、时间价值与监管口径(央行〔2021〕3号文),避免常见误算。

用 TypeScript 实现贷款 IRR:从还款现金流计算年化利率

贷款计算器里,一个容易写错的功能是“年化利率”。

假设借款 10,000 元,分 12 个月偿还,每月还 900 元。不考虑其他费用,总还款为 10,800 元。

直接计算:

(10800 - 10000) / 10000 = 8%

这只能得到总利息与初始本金的比例,不能直接当作这笔分期贷款的年化利率。因为借款人在逐月归还本金,并没有完整占用 10,000 元一整年。

如果放款时还扣了手续费,计算结果又会不同。

本文用一个具体例子,说明如何整理还款现金流,再用 TypeScript 求出月度 IRR 和复利口径的年化利率。

一、先确定计算口径

“真实年化率”是常见说法,但在程序界面和计算结果里,最好明确标注口径,例如:

  • 月度 IRR;
  • 月度 IRR × 12,线性年化口径;
  • (1 + 月度 IRR)^12 - 1,复利年化口径。

这几项不能混着展示。

中国人民银行公告〔2021〕第3号指出,贷款成本应包括利息及与贷款直接相关的各类费用;年化利率可以采用复利或单利方法计算,采用单利方法的应说明是单利。公告附件也提供了内部收益率法的计算示例。来源:中国人民银行

本文计算的是:根据输入的借款和还款现金流,先求月度 IRR,再换算为复利年化利率。是否遗漏费用,会直接影响结果。

二、把借款拆成现金流

以下是一组假设数据:

项目 金额或安排
合同本金 10,000 元
放款时扣除的手续费 200 元
实际到账 9,800 元
还款期数 12 期
每期还款 900 元
首期还款时间 放款后一个月末

从借款人视角看,收到的钱是正数,支付的钱是负数:

第 0 期:+9800
第 1 期:-900
第 2 期:-900
……
第 12 期:-900

这里有两个细节。

第一,初始现金流用的是实际到账的 9,800 元,而不是合同本金 10,000 元。

第二,200 元手续费已经从初始现金流里扣除,后续不能再加一次,否则会重复计费。如果还有每月收取的贷款相关费用,应计入对应月份的还款金额。

三、IRR 求解的是什么

设实际到账金额为 P,第 t 个月的还款金额为 Aₜ,月度 IRR 为 r,需要求解:

P = A₁ / (1+r) + A₂ / (1+r)² + … + Aₙ / (1+r)ⁿ

也就是寻找一个月利率,让所有未来还款折算到放款时点后的现值,等于实际到账金额。

求出 r 后:

线性年化 = r × 12

复利年化 = (1 + r)¹² - 1

这里的复利换算是统一年化口径,不表示合同一定按“利滚利”收款。

四、用二分法实现

对于“一次到账、之后只还款”的现金流,随着折现率提高,还款现值会下降,可以用二分法求解。

下面的函数限定为:

  • 每期代表一个月,首期在一个月末;
  • 只有一次初始到账,后续还款金额不能为负;
  • 总还款不少于实际到账,即只处理非负利率;
  • 最多支持 1,200 期,并设置求解边界。

它不是适用于任意投资现金流的通用 IRR 函数。

/**
 * 返回月度 IRR,例如 0.015 表示月度 1.5%。
 * payments 为每个月末支付的金额,使用正数。
 */
function monthlyIrr(
  netReceived: number,
  payments: readonly number[]
): number {
   
  if (!Number.isFinite(netReceived) || netReceived <= 0) {
   
    throw new Error("实际到账金额必须大于 0");
  }

  if (payments.length === 0 || payments.length > 1200) {
   
    throw new Error("还款期数必须在 1~1200 之间");
  }

  let total = 0;

  for (const amount of payments) {
   
    if (!Number.isFinite(amount) || amount < 0) {
   
      throw new Error("还款金额必须是非负有限数");
    }
    total += amount;
  }

  if (!Number.isFinite(total)) {
   
    throw new Error("金额超出计算范围");
  }

  if (total < netReceived) {
   
    throw new Error("此示例不支持负利率");
  }

  if (total === netReceived) return 0;

  // 未来还款现值减去实际到账金额。
  const residual = (rate: number): number => {
   
    let pv = 0;
    let discount = 1;

    for (const amount of payments) {
   
      discount /= 1 + rate;
      pv += amount * discount;
    }

    return pv - netReceived;
  };

  let low = 0;
  let high = 1;

  // 扩大上界,直到覆盖根;上界设置硬限制。
  while (residual(high) > 0 && high < 1048576) {
   
    high *= 2;
  }

  if (residual(high) > 0) {
   
    throw new Error("利率超出求解范围");
  }

  for (let i = 0; i < 160; i++) {
   
    const mid = (low + high) / 2;

    if (residual(mid) > 0) {
   
      low = mid;
    } else {
   
      high = mid;
    }
  }

  return (low + high) / 2;
}

二分法每轮都要遍历一次还款数组。固定迭代次数后,计算量随期数线性增长,适合这种规模较小的计算器功能。

五、运行前面的例子

const payments = Array<number>(12).fill(900);

const monthlyRate = monthlyIrr(9800, payments);
const linearAnnualRate = monthlyRate * 12;
const effectiveAnnualRate = (1 + monthlyRate) ** 12 - 1;

console.log(`月度 IRR:${
     (monthlyRate * 100).toFixed(4)}%`);
console.log(`线性年化:${
     (linearAnnualRate * 100).toFixed(4)}%`);
console.log(`复利年化:${
     (effectiveAnnualRate * 100).toFixed(4)}%`);

这组数据的计算结果为:

月度 IRR:1.5274%
线性年化:18.3292%
复利年化:19.9502%

为什么和最开始的 8% 差这么多?

8% 没有考虑本金逐月归还,也没有计入放款时扣除的 200 元手续费。IRR 则同时考虑了实际到账金额、每次还款金额和还款时点。

因此,不能只看“总共多还了多少钱”,还要看“这笔钱实际用了多久”。

六、给计算结果做交叉检查

除了检查显示出来的百分比,还可以把求得的利率代回原方程:

const presentValue = payments.reduce(
  (sum, amount, index) =>
    sum + amount / (1 + monthlyRate) ** (index + 1),
  0
);

console.log(presentValue.toFixed(2)); // 9800.00

console.assert(
  Math.abs(presentValue - 9800) < 0.000001,
  "现值校验未通过"
);

console.assert(
  monthlyIrr(1200, Array<number>(12).fill(100)) === 0,
  "零利率测试未通过"
);

console.assert(
  Math.abs(monthlyIrr(1000, [1100]) - 0.1) < 1e-10,
  "单期测试未通过"
);

单期测试很直观:到账 1,000 元,一个月后还 1,100 元,对应月度利率就是 10%。

计算过程中保留精度,最后展示时再调用 toFixed()。不要每轮迭代都四舍五入。

七、接入实际业务时的边界

不规则日期不能直接套用月度 IRR。

如果首期只有 15 天,或中途提前还款,就不再符合这里的等月间隔假设。需要使用按实际日期折现的模型,并明确一年按多少天计算。

还款数组必须包含完整现金流。

到账时收取的费用调整初始净到账;以后收取的费用放到实际支付的期次。缺少一笔费用,结果就只代表已输入的部分成本。

金额处理和利率求解分开。

业务账单可以使用整数分或十进制定点运算管理金额。将实际应付金额确定到分后,再送入求解函数。number 适合这里的数值求解,但不应承担所有账务精度处理。

不要用这个函数处理反复借还的现金流。

多次提款、退款或正负现金流多次交替,不满足本文的单调性前提,可能出现多个 IRR 或无解,需要另外设计。

结语

做贷款年化计算器,难点不只是把公式写进代码,更在于把钱的流向和时间安排放对。

先整理实际到账与每期支出,再求月度 IRR,最后明确年化口径,计算结果才方便核对和比较。结果也不能单独用于判断收费是否合法。

相关工具入口:第三方贷款计算器。这是我维护的网站;本文代码是独立教学示例,使用时应按具体还款安排核对输入和计算口径。

相关文章
|
1月前
|
存储 弹性计算 运维
什么是阿里云服务器ECS,及其优势、购买、使用方式和部署建议与实操命令教程
在云计算技术普及的时代,传统自建机房模式面临硬件采购成本高、部署周期漫长、硬件维护繁琐、资源弹性不足等诸多现实痛点。企业想要搭建业务系统,需要采购服务器硬件、搭建机房环境、部署供电与网络设施,前期投入巨大,业务流量波动时,硬件资源很难快速扩缩容。而云服务器ECS(Elastic Compute Service)作为IaaS层级的核心云计算服务,把计算资源转变为可按需取用的公共基础设施,如同日常使用水电燃气,用户无需采购实体IT硬件,就可以获取虚拟服务器能力,实现资源分钟级交付、弹性伸缩,广泛适配个人开发者、中小企业、大型企业的各类业务场景。本文将完整讲解ECS产品定义、核心优势、产品架构组件、
584 1
|
1月前
|
人工智能 自然语言处理 机器人
阿里云百炼文本生成模型解析:适合AI智能体、聊天机器人、文档处理等场景
本文介绍了阿里云百炼平台的文本大模型选型体系,针对开发者面对多类模型难以精准匹配场景的痛点展开系统解析。文章覆盖AI编程与Agent开发、通用聊天与内容生成、日常办公等主流场景的定向推荐方案,提供GPT、Claude、Gemini等主流闭源模型向百炼生态平滑迁移的对位对照表,同时拆解上下文窗口、思考模式、Function Calling、结构化输出等核心能力的选型逻辑,汇总平台核心推荐模型的能力矩阵,最终帮助开发者在不同使用强度与成本约束下,快速锁定适配自身业务的最优模型。
|
2月前
|
人工智能 编解码 数据可视化
AI 漫剧本地部署实战|AI 音色克隆集成,漫剧配音素材与工程落地
本文详解AI漫剧本地化量产方案,聚焦语音配音短板,提供1000+克隆必备音色素材合集(含青年/少年/中老年/情绪向等分类),配套预训练音色调用与AI声音克隆双模式Python工程代码,支持ComfyUI集成、显存优化及版权合规指南,实现端到端离线漫剧全自动生产。
|
3月前
|
机器学习/深度学习 缓存 人工智能
月之暗面 Kimi K3 接入百炼平台:100 万 Token 长文本,缓存仅 2 元 / 百万输入
全球首个开源3万亿级大模型Kimi K3(2.8万亿参数)正式上线阿里云百炼平台,支持100万Token超长上下文、原生视觉理解与深度推理。文本生成、多模态分析、复杂逻辑任务表现卓越,输入20元/百万Token(缓存命中仅2元),面向长程编程、知识工作等高阶场景。在阿里云百炼官网:https://t.aliyun.com/U/fPVHqY 免费领取千万Tokens
383 3
|
1月前
Qoder 国际版:「经济」档位面向所有付费用户开放免费使用
Qoder国际版推出付费用户专享福利:即日起,“经济”档位免费畅用(计费系数0.0x),原生多模态,满足日常开发需求。覆盖所有个人、Teams及企业版订阅。叠加9月限时大促:新订Pro/Pro+ Credits买一送一,续费升级加赠1000 Credits,截止9月30日。
492 0
|
15天前
|
存储 弹性计算 缓存
阿里云四款价格最便宜云服务器指南:2核2G、2核4G、4核8G配置,38元起,配置与价格全对比
针对阿里云四款常见低成本云服务器,本文从配置结构、适用边界、成本周期与运维复杂度四个维度展开严谨评估:轻量应用服务器2核2G、200M峰值带宽、40GB ESSD盘约38元/年;经济型e实例2核2G、3M带宽约99元/年;通用算力型u1实例2核4G、5M带宽约199元/年;u1实例4核8G、5M带宽约925.95元/年。文章提醒活动价受地域、周期、优惠券等影响,应以购买页为准,助读者按业务阶段理性选型。
|
1月前
|
人工智能 算法
3个月,520万播放,6666个粉丝,普通人如何用AI搞副业?
AI时代,普通人也能轻松做自媒体!本文揭秘“AI自动变现”全流程:从0搭建账号、AI批量生产内容、多平台自动分发,到广告/带货/IP多元变现。无需天赋团队,7天起号,日更3-5条,小投入撬动长期收益。方法已验证,人人可复制。
|
2月前
|
人工智能 自然语言处理 数据可视化
QwenWork 千问办公完整评测:阿里一站式 AI 办公平台,一句话生成 PPT / 网页 / 数据分析
千问办公是阿里巴巴推出的AI原生办公平台,基于Qwen3.8大模型,支持一句话交付PPT、文档、视频、网页等成果;深度整合钉钉生态,覆盖桌面端、网页端及本地文件系统,真正实现“对话即执行、生成即所得”。
|
1月前
|
弹性计算 安全 Linux
新手如何选购并配置阿里云服务器保姆级教程,实例选型、参数解读、远程连接、安全加固全流程教学
对于绝大多数刚接触云计算的新手来说,挑选并配置第一台云服务器往往会遇到大量困惑。面对控制台密密麻麻的参数选项,分不清轻量应用服务器和ECS之间的差异,看不懂计费模式,购买之后不知道如何登录、如何做安全设置,经常出现买完服务器无法访问、服务器被恶意扫描攻击、资源规格和业务需求不匹配造成资源浪费等一系列问题。本文面向零基础使用者,完整梳理从前期账号准备、产品选型、参数筛选、下单购买,再到远程登录、系统初始化、安全加固、基础环境调试的全部流程,同时提供可直接复制运行的实操命令,帮助新手顺利完成第一台云服务器的搭建,规避新手高频踩坑点,理清不同业务场景下的选型逻辑,让服务器真正可以投入业务使用。
248 3

热门文章

最新文章