Deterministic integrity checks for financial statements: does the balance sheet balance, does the cash flow tie out, do the three statements articulate. Verifies, does not parse or build.
Project description
finvariant
Deterministic integrity checks for financial statements.
Give finvariant income statement, balance sheet and cash flow data; it verifies the accounting invariants - the balance sheet balances, the cash flow ties to the balance sheet, subtotals foot, and the three statements articulate - and returns a structured, auditable report. It verifies; it does not parse, fetch or build statements.
Motivation
Python has plenty of libraries to retrieve statements (financetoolkit, the SEC tools) and to build models (DCF templates, FP&A scripts). What none of them do is check that a set of statements or a model is internally consistent: that assets equal liabilities plus equity, that the cash flow's ending cash matches the balance sheet, that retained earnings roll forward by net income less dividends, that every subtotal foots. That check is exactly what a spreadsheet silently gets wrong - and surveys put an error in the large majority of business spreadsheets.
finvariant encodes those invariants as deterministic, testable rules. The same thing a large language model cannot be trusted to get right (consistent arithmetic across linked statements), a small library can guarantee. Every result is one report: a verdict, the exact failing checks with expected vs actual, and provenance, so a verification can be reproduced and audited later.
pip install finvariant
No runtime dependencies.
Usage
Catch an error:
import finvariant as fv
s = fv.Statements(
periods=["FY2024"],
balance_sheet={"FY2024": {
"total_assets": 540, # should be 538
"total_liabilities": 158,
"total_equity": 380,
}},
)
r = fv.check(s)
r.ok # False
print(r.summary())
# finvariant audit - 2026-...
# 1 checks run, 0 passed, 1 failed, 0 skipped
# [ERROR] EQ.accounting_equation assets = liabilities + equity (FY2024): expected 538, got 540, off by 2
# Verdict: FAIL - statements do not tie out
Real statements tie out (Apple FY2024, from the 10-K):
s = fv.Statements(
periods=["FY2024"],
income_statement={"FY2024": {
"revenue": 391035, "cogs": 210352, "gross_profit": 180683,
"operating_expenses": 57467, "operating_income": 123216,
"other_income": 269, "pretax_income": 123485, "tax": 29749,
"net_income": 93736,
}},
balance_sheet={"FY2024": {
"total_current_assets": 152987, "total_non_current_assets": 211993,
"total_assets": 364980,
"total_current_liabilities": 176392, "total_non_current_liabilities": 131638,
"total_liabilities": 308030,
"common_stock": 83276, "retained_earnings": -19154,
"accumulated_oci": -7172, "total_equity": 56950,
}},
)
fv.check(s).ok # True
The report carries named findings, counts, ok, summary() and a JSON-safe
to_dict() with provenance (version, input hash, timestamp).
What it checks
| Group | Invariant |
|---|---|
| Footing | every subtotal equals the sum of its line items (all three statements) |
| Equation | total assets = total liabilities + total equity |
| Cash | net change = cfo + cfi + cff; ending cash ties to the balance sheet; beginning cash ties to the prior period |
| Articulation | net income agrees across statements; retained earnings roll forward by net income less dividends |
Provide only the fields you have: a check whose inputs are missing is reported as skipped, never failed. Tolerances absorb the rounding in statements reported in whole millions.
Status
Version 0.1.0. Single entity, single currency, one or more periods, in a
canonical schema. The Statements input and AuditReport output are the
contract and are append-only from here.
Roadmap
| Version | Scope |
|---|---|
| 0.2 | roll-forward checks (PP&E = opening + capex - depreciation - disposals; debt; equity); working-capital changes reconciled to operating cash flow |
| 0.3 | an MCP server so an agent can verify financial statements it reads or generates |
| 0.4 | optional readers to map common export formats into the canonical schema |
Out of scope: retrieving statements (see financetoolkit, the SEC tools), building or forecasting models, ratio analysis, consolidation and currency translation.
License
MIT. Written and maintained by Atakan Arikan, MSc Student at Tsinghua University and Politecnico di Milano.
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 finvariant-0.1.0.tar.gz.
File metadata
- Download URL: finvariant-0.1.0.tar.gz
- Upload date:
- Size: 14.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aa3cf507573c142ce33f90300444b699a663b8ded566fd2b9ebbbe01851983ed
|
|
| MD5 |
6b99800e8c876d5a938c184fe8e7dd3d
|
|
| BLAKE2b-256 |
cafa87f6c540602144543cca481da5544b5400417ef4153ab93ea14648ec4c2d
|
Provenance
The following attestation bundles were made for finvariant-0.1.0.tar.gz:
Publisher:
release.yml on arikanatakan/finvariant
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
finvariant-0.1.0.tar.gz -
Subject digest:
aa3cf507573c142ce33f90300444b699a663b8ded566fd2b9ebbbe01851983ed - Sigstore transparency entry: 1823333274
- Sigstore integration time:
-
Permalink:
arikanatakan/finvariant@3bcc902b0f0c6f0c7dff7fcce837e7aae443e5e7 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/arikanatakan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3bcc902b0f0c6f0c7dff7fcce837e7aae443e5e7 -
Trigger Event:
release
-
Statement type:
File details
Details for the file finvariant-0.1.0-py3-none-any.whl.
File metadata
- Download URL: finvariant-0.1.0-py3-none-any.whl
- Upload date:
- Size: 12.4 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 |
88e7435493e0b40aa19b825e1d2de880d469e61762119abdcaa2db1634c99726
|
|
| MD5 |
0dc14b895357e781057ca84e662fb458
|
|
| BLAKE2b-256 |
b8fac712193d826664fc83086c61715bbe364ef5bcdf0677967c9575bd8b8dae
|
Provenance
The following attestation bundles were made for finvariant-0.1.0-py3-none-any.whl:
Publisher:
release.yml on arikanatakan/finvariant
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
finvariant-0.1.0-py3-none-any.whl -
Subject digest:
88e7435493e0b40aa19b825e1d2de880d469e61762119abdcaa2db1634c99726 - Sigstore transparency entry: 1823333310
- Sigstore integration time:
-
Permalink:
arikanatakan/finvariant@3bcc902b0f0c6f0c7dff7fcce837e7aae443e5e7 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/arikanatakan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3bcc902b0f0c6f0c7dff7fcce837e7aae443e5e7 -
Trigger Event:
release
-
Statement type: