Skip to main content

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

repaykit-1.0.0.tar.gz (27.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

repaykit-1.0.0-py3-none-any.whl (30.5 kB view details)

Uploaded Python 3

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

Hashes for repaykit-1.0.0.tar.gz
Algorithm Hash digest
SHA256 d5f9654753e1ecc28efbbc29eeae23b1e628312c989b0ae384902c96165e1456
MD5 b1468a76f8af757a1ba75aac55cceed0
BLAKE2b-256 af6a44288ea7a1936954f3f252b32107baf271f49436c582378725907301ae28

See more details on using hashes here.

Provenance

The following attestation bundles were made for repaykit-1.0.0.tar.gz:

Publisher: publish.yml on finsure-techlab/repaykit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for repaykit-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a186ed93c2af294d4c381870a0e9e427c55ca1806e9bfb16af867b6babf80be4
MD5 00666de4ee3607f043ddc145b08d1655
BLAKE2b-256 5cfdcf706d115c04b498f8f542d4cc475e59af2fad7fddc72619ad312f5cc89b

See more details on using hashes here.

Provenance

The following attestation bundles were made for repaykit-1.0.0-py3-none-any.whl:

Publisher: publish.yml on finsure-techlab/repaykit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page