Skip to main content

tontine-core

Build a simple, transparent, auditable, and reusable Python engine for community tontines.

Package Identity

  • Distribution name: tontine-core
  • Python import name: tontine
  • Supported Python: 3.12+

Development

This repository uses uv to create the isolated environment, resolve dependencies, run tools, and build the package.

uv sync
uv run pytest
uv run pytest --cov=tontine --cov-report=html --cov-report=term
uv run ruff check src tests
uv run mypy src
uv build

Import the package with:

import tontine

The core package is framework-independent and has no runtime dependency on a database, web framework, payment provider, or financial institution.

Capabilities

The package provides focused, composable domain primitives rather than one large application object:

  • Groups and members: validated groups, optional jurisdiction metadata, member roles, residence metadata, membership start dates, and lifecycle transitions.
  • Contributions: daily, weekly, and monthly rules; contribution cycles; pending, paid, partial, late, and missed statuses; outstanding totals; and separate fixed penalty assessments.
  • Classic tontines: deterministic member rotations, expected payouts, duplicate-payout protection, and configurable unpaid-contribution policy.
  • Investment tracking: allocation schedules, asset definitions, manual valuations, purchases, sales, income, fees, and supplied FX-rate records.
  • Ownership and liabilities: Decimal member-unit issuance and redemption, ownership percentages, member values, and manually supplied liability records aggregated by currency.
  • Ledger and audit: balanced double-entry journals, derived balances, reversals, adjustments, immutable audit events, and provenance fields.
  • Governance: versioned rulesets, rotation proposals, one-member-one-vote decisions, approval thresholds, and effective rotations.
  • Reporting and repositories: structured member/group statements and typed in-memory repository implementations suitable for application adapters.

Quick Start

Create a group and a cycle through the top-level API:

from datetime import date

import tontine

group = tontine.create_group(
	"tokyo-cameroon",
	"Tokyo Cameroon Circle",
	"JPY",
	jurisdiction="JP",
)
cycle = tontine.create_contribution_cycle(
	"2027-01",
	date(2027, 1, 1),
	date(2027, 1, 31),
	"Asia/Tokyo",
)

Members and contributions

from datetime import date, datetime, timezone
from decimal import Decimal

from tontine.contributions import ContributionCycle
from tontine.members import Member, MemberRole

member = Member.create(
	"member-001",
	"Amina",
	MemberRole.MEMBER,
	date(2027, 1, 1),
	residence_country="CM",
)

cycle = ContributionCycle(
	"2027-02",
	date(2027, 2, 1),
	date(2027, 2, 15),
	"Africa/Lagos",
	grace_period_days=2,
	late_penalty=Decimal("500"),
)
cycle.add_expected_contribution(member.member_id, Decimal("30000"))
record = cycle.record_contribution(
	member.member_id,
	Decimal("30000"),
	payment_date=datetime(2027, 2, 18, tzinfo=timezone.utc),
)
assert record.penalty == Decimal("500")
assert record.penalty_record.destination.value == "common_reserve"

Penalties are group money, separate from contributions, and do not create investment units. The default destination is COMMON_RESERVE.

Classic rotation

from tontine.classic import ClassicRotation

rotation = ClassicRotation.from_active_members(("member-001", "member-002"))
assert rotation.recipient_for_cycle(1) == "member-001"
expected_pool = rotation.expected_payout(
	{"member-001": Decimal("30000"), "member-002": Decimal("30000")}
)

Investment ownership and liabilities

from tontine.investments import (
	InvestmentValuation,
	Liability,
	LiabilityRegistry,
	MemberUnitLedger,
)

liabilities = LiabilityRegistry()
liabilities.record(
	Liability("fee-001", Decimal("100"), "JPY", date(2027, 2, 1), "invoice")
)
valuation = InvestmentValuation.from_liabilities(
	assets=Decimal("10000"),
	liabilities=liabilities,
	currency="JPY",
	units_outstanding=Decimal("100"),
	asset_currency="JPY",
)

units = MemberUnitLedger()
member_units = units.issue("member-001", Decimal("3000"), valuation.unit_price, "issue-001")
ownership = valuation.member_ownership_percentage(member_units)
value = valuation.member_value(member_units)

The valuation derives NAV = assets - liabilities, unit price, ownership percentage, and member value from explicit Decimal inputs. Asset and activity aggregation remains the responsibility of the consuming application.

Structured reporting

from tontine.reporting import InvestmentSummary, build_member_statement

investment = InvestmentSummary.from_valuation(valuation, member_units, "JPY")
statement = build_member_statement(
	"member-001",
	"Amina",
	"JPY",
	contributions=(),
	payouts=(),
	investment=investment,
)
assert statement.investment.ownership_percentage == ownership

Application layers can turn these structured records into web pages, exports, or other user interfaces without adding presentation dependencies to the core.

Structured Reporting

Reporting APIs expose structured member and group statement data, including contribution history, outstanding amounts, payouts, investment units, ownership, cash, investments, liabilities, NAV, and proposals. For example, a consumer can use a MemberStatement as the source for a web view or export. PDF, Excel, HTML, and web rendering remain application-layer responsibilities.

Financial Account Registry

The account registry records external custody context only. For example, a bank account may be represented with ****1234, NG, and a logical ledger identifier such as ledger-cash-ngn. The package does not store credentials, connect to institutions, retrieve live balances, initiate payments, or move real money.

Metadata

Release files for tontine-core 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tontine-core 0.1.0
File Size Uploaded Provenance Actions
tontine_core-0.1.0.tar.gz 29.7 kB With provenance Details for tontine_core-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for tontine-core 0.1.0
File Interpreter ABI Platform Actions
tontine_core-0.1.0-py3-none-any.whl Python 3 none any Details for tontine_core-0.1.0-py3-none-any.whl

Total release size: 64.1 kB

Release files / tontine_core-0.1.0.tar.gz

Download URL tontine_core-0.1.0.tar.gz
Size 29.7 kB
Tags Source
SHA-256 checksum
How to use checksums
33b56b2cf3734ec092f70dc153965c5739444457b44cb58a96026cd84503e50c
BLAKE2b-256 checksum
How to use checksums
e4d5d0f0cdacff5d9714fb9d69ada2e8f275e2d3fcb26f1c97a11910859e700c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 13, 2026.

Transparency log

Release files / tontine_core-0.1.0-py3-none-any.whl

Download URL tontine_core-0.1.0-py3-none-any.whl
Size 34.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a9379f309174a40fbc155ef08d5684c3b79d0e13c8797184e9970856ca2bedf6
BLAKE2b-256 checksum
How to use checksums
71e216ee934ab984875313a26ac6da82a0d22a7cf73c28246d1925a8a144aeff
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 13, 2026.

Transparency log

Security for tontine-core 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for tontine_core-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 13, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page