Pure Python repayment schedule, financing, loan ledger, and settlement calculation toolkit.
Project description
repaykit
Pure Python repayment schedule, financing, loan ledger, and settlement calculation toolkit.
repaykit helps software teams calculate loan and financing schedules, payment ledgers, late
charges, statement balances, and settlement quotes. It is framework-agnostic, uses Decimal for
money and rates, and keeps business rules policy-driven.
What It Is Not
repaykit is not a loan origination system, accounting system, regulatory compliance engine, or
legal opinion. It does not provide legal, accounting, tax, Shariah, regulatory, lending, or
financial advice. Users are responsible for validating calculations, policies, disclosures, and
compliance requirements for their jurisdiction and product.
Installation
pip install repaykit
Supported Methods
- Flat rate
- Sum-of-digits / Rule of 78
- Reducing balance amortization
- Constant principal repayment
Supported Schedules
- Daily, with optional weekend skipping
- Weekly
- Biweekly
- Monthly, with month-end safety
- Quarterly
- Yearly
- Custom explicit due dates
Quickstart
from datetime import date
from decimal import Decimal
from repaykit import Loan
loan = Loan.create(
amount=Decimal("10000.00"),
annual_rate=Decimal("0.08"),
term="24 months",
payment_frequency="monthly",
method="flat_rate",
start_date=date(2026, 6, 1),
)
payment = loan.payment_amount()
rows = loan.schedule()
Use iter_schedule() for lazy row generation, especially for daily schedules.
Expert Mode
from datetime import date
from decimal import Decimal
from repaykit import Loan
from repaykit.accruals import FlatAccrual
from repaykit.methods import FlatRateAllocation
from repaykit.policies import RoundingPolicy
from repaykit.schedules import MonthlySchedule
from repaykit.terms import Term
loan = Loan(
principal=Decimal("10000.00"),
term=Term(months=24),
payment_schedule=MonthlySchedule(day=1),
accrual_policy=FlatAccrual(annual_rate=Decimal("0.08")),
repayment_method=FlatRateAllocation(),
rounding=RoundingPolicy(currency="MYR"),
start_date=date(2026, 6, 1),
)
Flat Rate Example
loan = Loan.create(
amount=Decimal("10000.00"),
annual_rate=Decimal("0.08"),
term="24 months",
payment_frequency="monthly",
method="flat_rate",
start_date=date(2026, 6, 1),
)
Flat-rate total profit is principal * annual_rate * term_in_years. Future scheduled profit is
treated as unearned profit rebate in the default settlement policy.
Sum-of-Digits / Rule of 78 Example
loan = Loan.create(
amount=Decimal("10000.00"),
annual_rate=Decimal("0.08"),
term="12 months",
payment_frequency="monthly",
method="sum_of_digits",
start_date=date(2026, 1, 1),
)
The denominator is generalized as n * (n + 1) / 2, so the method works with non-monthly period
counts such as 52 weekly periods.
Reducing Balance Example
loan = Loan.create(
amount=Decimal("10000.00"),
annual_rate=Decimal("0.08"),
term="24 months",
payment_frequency="monthly",
method="reducing_balance",
start_date=date(2026, 6, 1),
)
Reducing balance uses fixed-payment amortization. Profit is calculated on the outstanding balance for each period.
Constant Principal Example
loan = Loan.create(
amount=Decimal("10000.00"),
annual_rate=Decimal("0.08"),
term="24 months",
payment_frequency="monthly",
method="constant_principal",
start_date=date(2026, 6, 1),
)
The principal component is constant except for the final rounding adjustment; installments decline as profit declines.
Weekly Payment Example
loan = Loan.create(
amount=Decimal("5000.00"),
annual_rate=Decimal("0.10"),
term="52 weeks",
payment_frequency="weekly",
method="constant_principal",
start_date=date(2026, 1, 1),
)
Daily Payment Example
loan = Loan.create(
amount=Decimal("1000.00"),
annual_rate=Decimal("0.12"),
term="30 days",
payment_frequency="daily",
method="reducing_balance",
start_date=date(2026, 1, 1),
)
Payment Ledger Example
from repaykit import LoanAccount
account = LoanAccount(loan)
account.add_payment(
amount=Decimal("500.00"),
paid_at=date(2026, 7, 5),
reference="ANGKASA-JULY-2026",
)
statement = account.statement(as_of=date(2026, 8, 1))
print(statement.total_due)
print(statement.total_paid)
print(statement.arrears)
print(statement.outstanding_balance)
Statements use aggregate oldest-due-first allocation for due installments and late-charge exposure. They do not maintain a double-entry accounting ledger or split each payment into principal/profit transactions.
Late Charge Example
from repaykit.policies import LateChargePolicy
loan.late_charge_policy = LateChargePolicy(
rate=Decimal("0.01"),
grace_days=5,
basis="flat",
minimum_charge=Decimal("0.00"),
)
Supported bases are flat and daily. Negative overdue amounts are treated as zero.
Settlement Example
settlement = account.full_settlement(as_of=date(2026, 12, 15))
print(settlement.outstanding_principal)
print(settlement.unearned_profit_rebate)
print(settlement.late_charges)
print(settlement.amount_payable)
print(settlement.explanation)
Settlement is policy-based. Flat-rate and sum-of-digits methods rebate future scheduled profit by default. Reducing-balance and constant-principal methods have no unearned profit rebate by default. Validate settlement behavior against your contract and regulatory requirements.
Export Example
from repaykit.exporters import schedule_to_csv, schedule_to_dicts
rows = loan.schedule()
data = schedule_to_dicts(rows)
schedule_to_csv(rows, "schedule.csv")
Exporters serialize Decimal values as strings and dates as ISO strings. They never convert money
to floats.
Rounding Warning
The default RoundingPolicy uses half-up money rounding with two decimal places. Different
institutions and jurisdictions may require different rounding points, decimal places, or settlement
rebate rules. Configure and test policies against the governing contract and regulation.
Release Status
Version 1.0.0 declares the public API documented in docs/api.md. Breaking public API changes
after 1.0.0 require a major version bump.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file repaykit-1.0.0.tar.gz.
File metadata
- Download URL: repaykit-1.0.0.tar.gz
- Upload date:
- Size: 27.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d5f9654753e1ecc28efbbc29eeae23b1e628312c989b0ae384902c96165e1456
|
|
| MD5 |
b1468a76f8af757a1ba75aac55cceed0
|
|
| BLAKE2b-256 |
af6a44288ea7a1936954f3f252b32107baf271f49436c582378725907301ae28
|
Provenance
The following attestation bundles were made for repaykit-1.0.0.tar.gz:
Publisher:
publish.yml on finsure-techlab/repaykit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
repaykit-1.0.0.tar.gz -
Subject digest:
d5f9654753e1ecc28efbbc29eeae23b1e628312c989b0ae384902c96165e1456 - Sigstore transparency entry: 1633119488
- Sigstore integration time:
-
Permalink:
finsure-techlab/repaykit@3dc72ed16b55fc461ecf96a10c92281348d55d83 -
Branch / Tag:
refs/tags/v1.0.01 - Owner: https://github.com/finsure-techlab
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3dc72ed16b55fc461ecf96a10c92281348d55d83 -
Trigger Event:
release
-
Statement type:
File details
Details for the file repaykit-1.0.0-py3-none-any.whl.
File metadata
- Download URL: repaykit-1.0.0-py3-none-any.whl
- Upload date:
- Size: 30.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a186ed93c2af294d4c381870a0e9e427c55ca1806e9bfb16af867b6babf80be4
|
|
| MD5 |
00666de4ee3607f043ddc145b08d1655
|
|
| BLAKE2b-256 |
5cfdcf706d115c04b498f8f542d4cc475e59af2fad7fddc72619ad312f5cc89b
|
Provenance
The following attestation bundles were made for repaykit-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on finsure-techlab/repaykit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
repaykit-1.0.0-py3-none-any.whl -
Subject digest:
a186ed93c2af294d4c381870a0e9e427c55ca1806e9bfb16af867b6babf80be4 - Sigstore transparency entry: 1633119508
- Sigstore integration time:
-
Permalink:
finsure-techlab/repaykit@3dc72ed16b55fc461ecf96a10c92281348d55d83 -
Branch / Tag:
refs/tags/v1.0.01 - Owner: https://github.com/finsure-techlab
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3dc72ed16b55fc461ecf96a10c92281348d55d83 -
Trigger Event:
release
-
Statement type: