AnyMath 文档
Notebook

信贷计算器

本文讨论了通用信用计算器的软件实现。 主要重点是模块的内部结构,关键算法,数据结构和方法,以确保准确性,灵活性和易于与代码单元掩码接口集成。

1. 一般架构

该模块围绕一个中心功能构建 CreditCalculator,其作为两个独立的计算算法的门面:年金和微分。 所有辅助函数都被封装,返回的数据以命名元组的形式标准化(NamedTuple)及表格 DataFrame 从包 DataFrames.jl.

主要组件:
-CreditCalculator是一个调度程序,它验证输入参数并选择一个方法。
-calculate_annuity/calculate_differentiated-实现财务公式的纯函数。
-compare_payment_types是用于比较两个方案的服务函数。
-print_payment_schedule是格式化显示的输出函数(副作用)。

这种设计提供了职责分离:计算与输入/输出分离,返回的结构可用于后续分析或可视化。

In [ ]:
include("lib.jl")

2. 输入参数和验证

功能 CreditCalculator 在键入时使用命名参数,这增加了代码的可读性,并允许您以任何顺序设置值。:

function CreditCalculator(; amount::Float64, rate::Float64, term::Int, 
                          payment_type::String="annuity", 
                          start_date::Date=today(), 
                          loan_type::String="consumer")

验证在入口处执行:
-核实金额、出价及期限是否为正数。
-检查一下 payment_type 属于集 {"annuity", "differentiated"}.

这可以防止在早期阶段进行错误的计算,并提供清晰的错误消息。

3. 计算算法

3.1. 年金付款

年金比率是用经典公式计算的:

image.png

其中r=利率/(100*n)是月利率,n是以月为单位的期限。

实现功能:
-每月付款计算为 amount * coef.
-每个月,计算余额的利息和本金债务的偿还金额。
-最后付款的更正:由于四舍五入,可能会累积错误,因此,在最后一步,本金债务的金额被强制设置等于余额,并重新计算付款。 这可确保最终余额为零。
-所有金额均四舍五入至小数点后两位 round(..., digits=2).
-数据累积在 DataFrame 连续打电话 push!.

3.2. 差异化付款

在这里,本金债务的每月部分是固定的:

image.png

每月利息是从当前余额计算的. 支付线性下降。

特点:
-与年金不同,不需要调整最后一次付款,因为余额会在最后一次付款后重置(前提是金额准确地除以整数个月)。
-为了便于比较,保存了第一次和最后一次付款。
-建造桌子时 principal_part 它仅在输出期间被舍入,但在计算中使用全精度以避免误差累积。

4. 返回数据的结构

两个选项都返回 NamedTuple 使用相同的字段,这允许您编写通用代码。:

(loan_type = ..., payment_type = ..., amount = ..., rate = ..., term = ...,
 total_payment = ..., total_interest = ..., overpayment_percent = ...,
 payments_table = DataFrame(...))

年金还有一个额外的字段 monthly_payment,对于差异化 – first_paymentlast_payment. 这种结构便于后续加工。

付款表 payments_table 包含列:

  • month -月号(Int)
  • date -付款日期(Date)
  • payment -付款金额(Float64)
  • principal -主要债务的部分(Float64)
  • interest -百分比部分(Float64)
  • remaining_debt -付款后的债务余额(Float64)

使用 DataFrame 允许您将包的所有功能应用于结果。 DataFrames.jl (过滤,聚合,合并),而无需额外的转换。

5. 处理边界条件

该代码提供了以下边缘情况:
-零或负参数-抛出错误。
-不正确的付款类型是一个错误与明确的消息。
-年金在 term = 1 年金比率公式仍在工作,最后一次付款的修正保证了准确性。
-具有差异化计算 principal_part 它不是四舍五入以避免在长时间内累积错误。

6. 测试和使用示例

草图中呈现的四个例子不仅可以作为演示,还可以作为隐式测试。 让我们看看他们检查哪些方面。

例1。 年金贷款

-检查年金系数计算的正确性。
-确保最后一次付款调整,余额重置为零。
-显示四舍五入到便士。

In [ ]:
Ставка = 9.01 # @param {type:"slider",min:0,max:100,step:0.01}
Срок = 12 # @param {type:"slider",min:1,max:240,step:1}
Сумма = 2151100 # @param {type:"slider",min:100,max:50000000,step:1000}
consumer_loan = CreditCalculator(amount=Float64(Сумма), rate=Ставка, term=Срок, payment_type="annuity", loan_type="consumer")
println(consumer_loan.payments_table)
12×6 DataFrame
 Row │ month  date        payment    principal  interest  remaining_debt
 Int64  Date        Float64    Float64    Float64   Float64
─────┼───────────────────────────────────────────────────────────────────
   1 │     1  2026-03-30  1.88127e5  1.71976e5  16151.2        1.97912e6
   2 │     2  2026-04-30  1.88127e5  1.73267e5  14859.9        1.80586e6
   3 │     3  2026-05-30  1.88127e5  1.74568e5  13559.0        1.63129e6
   4 │     4  2026-06-30  1.88127e5  1.75879e5  12248.3        1.45541e6
   5 │     5  2026-07-30  1.88127e5  1.77199e5  10927.7        1.27821e6
   6 │     6  2026-08-30  1.88127e5  1.7853e5    9597.24       1.09968e6
   7 │     7  2026-09-30  1.88127e5  1.7987e5    8256.78       9.19812e5
   8 │     8  2026-10-30  1.88127e5  1.81221e5   6906.26       7.38592e5
   9 │     9  2026-11-30  1.88127e5  1.82581e5   5545.59       5.5601e5
  10 │    10  2026-12-30  1.88127e5  1.83952e5   4174.71       3.72058e5
  11 │    11  2027-01-30  1.88127e5  1.85333e5   2793.54       1.86725e5
  12 │    12  2027-02-28  1.88127e5  1.86725e5   1401.99       0.0

例2。 按揭(差异付款)

-检查工作与日期(转移 start_date 并通过以下方式计算日期 Dates.Month).
-通过输出完整的图表 print_payment_schedule,确认格式化正确。
-比较第一次和最后一次付款,以确保线性下降。

print_payment_schedule -付款时间表输出。 功能 print_payment_schedule 接受结果作为输入 CreditCalculator 并输出格式化报告。 其实现使用字符串操作(rpad, Dates.format)并遍历行 DataFrame. 这种方法将表示与计算逻辑分开。 如有必要,可以很容易地将输出替换为另一个输出(例如,在文件或HTML中)。

In [ ]:
start_date = "2026-03-30" # @param {type:"date"}
Ставка = 9.01 # @param {type:"slider",min:0,max:100,step:0.01}
Срок = 12 # @param {type:"slider",min:1,max:240,step:1}
Сумма = 2151100 # @param {type:"slider",min:100,max:50000000,step:1000}
mortgage = CreditCalculator(amount=Float64(Сумма), rate=Ставка, term=Срок, payment_type="differentiated", loan_type="mortgage", start_date=Date(start_date))
print_payment_schedule(mortgage)
График платежей по кредиту:
Тип кредита: mortgage
Тип платежей: differentiated
Сумма: 2.1511e6 руб.
Ставка: 9.01% годовых
Срок: 12 мес.
----------------------------------------------------------------------------------------------------
Первый платеж: 195409.51 руб.
Последний платеж: 180604.26 руб.
Общая сумма выплат: 2.25608264e6 руб.
Переплата: 104982.64 руб. (4.88%)
----------------------------------------------------------------------------------------------------
Месяц | Дата       | Платеж   | Осн.долг | Проценты | Остаток
----------------------------------------------------------------------------------------------------
1     | 30.03.2026| 195409.51| 179258.33| 16151.18 | 1.97184167e6
2     | 30.04.2026| 194063.58| 179258.33| 14805.24 | 1.79258333e6
3     | 30.05.2026| 192717.65| 179258.33| 13459.31 | 1.613325e6
4     | 30.06.2026| 191371.72| 179258.33| 12113.38 | 1.43406667e6
5     | 30.07.2026| 190025.78| 179258.33| 10767.45 | 1.25480833e6
6     | 30.08.2026| 188679.85| 179258.33| 9421.52  | 1.07555e6
7     | 30.09.2026| 187333.92| 179258.33| 8075.59  | 896291.67
8     | 30.10.2026| 185987.99| 179258.33| 6729.66  | 717033.33
9     | 30.11.2026| 184642.06| 179258.33| 5383.73  | 537775.0
10    | 30.12.2026| 183296.13| 179258.33| 4037.79  | 358516.67
11    | 30.01.2027| 181950.2 | 179258.33| 2691.86  | 179258.33
12    | 28.02.2027| 180604.26| 179258.33| 1345.93  | 0.0

例3。 付款类别比较

-检查功能 compare_payment_types 返回包含三个字段的结构。
-比较多付的数值,确认年金提供了一个略高的多付与相同的参数。

compare_payment_types -比较功能,它调用两次 CreditCalculator 与不同的 payment_type 并生成最终表。 该表创建为 DataFrame 有三列:指标,年金值和差异化值。 这演示了如何使用单个模块的结果来构建更复杂的报告。

In [ ]:
Ставка = 9.01 # @param {type:"slider",min:0,max:100,step:0.01}
Срок = 12 # @param {type:"slider",min:1,max:240,step:1}
Сумма = 2151100 # @param {type:"slider",min:100,max:50000000,step:1000}
comparison_result=compare_payment_types(金额=Float64(金额),费率=出价,期限=期限)
println(comparison_result.comparison)
4×3 DataFrame
 Row │ Показатель                         Аннуитетный            Дифференцированный
 String                             Any                    Any
─────┼─────────────────────────────────────────────────────────────────────────────────
   1 │ Ежемесячный платеж (первый/после…  188126.85 / 188126.85  195409.51 / 180604.26
   2 │ Общая сумма выплат                 2.25752e6              2.25608e6
   3 │ Переплата (абс.)                   1.06422e5              1.04983e5
   4 │ Переплата (%)                      4.95                   4.88

例4。 付款表数据分析

-显示如何提取前五行(first).
-计算利息的最大值,最小值和金额-从而验证列 paymentinterest 它们包含正确的数字数据。
-证明返回的 DataFrame 它功能齐全,可用于统计分析。

In [ ]:
first_payments = first(mortgage.payments_table, 5)
Out[0]:
5×6 DataFrame
Rowmonthdatepaymentprincipalinterestremaining_debt
Int64DateFloat64Float64Float64Float64
112026-03-301.9541e51.79258e516151.21.97184e6
222026-04-301.94064e51.79258e514805.21.79258e6
332026-05-301.92718e51.79258e513459.31.61332e6
442026-06-301.91372e51.79258e512113.41.43407e6
552026-07-301.90026e51.79258e510767.51.25481e6
In [ ]:
println("首5个按揭付款:")
println(first_payments)
println("\付款统计:")
println("最高付款额: ", maximum(mortgage.payments_table.payment))
println("最低付款额: ", minimum(mortgage.payments_table.payment))
println("第一年的利息金额: ", sum(mortgage.payments_table.interest[1:12]))
Первые 5 платежей по ипотеке:
5×6 DataFrame
 Row │ month  date        payment    principal  interest  remaining_debt
 Int64  Date        Float64    Float64    Float64   Float64
─────┼───────────────────────────────────────────────────────────────────
   1 │     1  2026-03-30  1.9541e5   1.79258e5   16151.2       1.97184e6
   2 │     2  2026-04-30  1.94064e5  1.79258e5   14805.2       1.79258e6
   3 │     3  2026-05-30  1.92718e5  1.79258e5   13459.3       1.61332e6
   4 │     4  2026-06-30  1.91372e5  1.79258e5   12113.4       1.43407e6
   5 │     5  2026-07-30  1.90026e5  1.79258e5   10767.5       1.25481e6

Статистика по платежам:
Максимальный платеж: 195409.51
Минимальный платеж: 180604.26
Сумма процентов за первый год: 104982.63999999998

结论

开发的模块演示了Julia功能的有效使用:通过命名参数进行多次调度,类型安全和方便的数据结构(NamedTuple, DataFrame)和功能性组合物。 这种方法可以轻松维护代码,添加新类型的计算(例如,考虑到提前还款)并将计算器集成到更大的财务应用程序中。 测试用例同时作为算法正确性的文档和确认.