ledger-pyreport is a lightweight Flask webapp for generating interactive and printable accounting reports from ledger-cli data.


  • Trial balance, and comparative trial balance
  • Balance sheet, and comparative balance sheet
  • Income statement, and comparative income statement
  • Cash flow statement, and comparative cash flow statement (direct and indirect methods)
  • General ledger
  • Account transactions, with or without itemisation of commodities
  • Transaction detail, with or without itemisation of commodities


  • Correctly values:
  • Correctly computes unrealised gains (even when Ledger does not)
  • Accounts for both profit and loss, and other comprehensive income
  • Simulates annual closing of books, with presentation of income/expenses on the balance sheet as retained earnings and current year earnings
  • Can simulate cash basis accounting, using FIFO methodology to recode transactions involving liabilities and non-cash assets
  • Can separately report specified categories of income and expense, reporting per-category net profit
  • Extensible through custom programming hooks

Background, demo and screenshots

See https://yingtongli.me/blog/2020/03/31/ledger-pyreport.html for further discussion.


Install the dependencies from PyPI, optionally in a virtual environment: (Commands presented for Linux/Mac)

virtualenv -p python3 venv
. venv/bin/activate
pip3 install -r requirements.txt

Copy config.example.yml to config.yml (or set the LEDGER_PYREPORT_CONFIG environment variable to the path to the config file). Edit as required, in particular setting the path of the Ledger journal file, reporting currency and any required Ledger arguments.

Run as per a usual Flask app, for example:

FLASK_APP=ledger_pyreport python3 -m flask run

Notes on Ledger setup

ledger-pyreport expects each of assets, liabilities, equity, income and expenses to be setup in Ledger as a separate top-level account. These accounts should contain a zero balance, with all transactions in child accounts.

Additionally, ledger-pyreport expects the next level of assets and liabilities to be categories of asset and liability (e.g. Assets:Current, Liabilities:Non-current). These, too, should contain a zero balance.

Ledger-pyreport by default observes the convention that positive amounts in Ledger represent debits, and negative amounts in Ledger represent credits.

A commodity which has any price data in Ledger (including those specified through @ or @@, or explicitly through P) will be regarded as a commodity measured at fair market value, and automatically revalued accordingly. A commodity which has no price data in Ledger (i.e. lot prices through {…} or {{…}} only) will be regarded as a commodity measured at historical cost, and will not be subsequently revalued.

Caution on standards compliance

ledger-pyreport is developed with reference to the AASB Australian Accounting Standards and IFRS International Financial Reporting Standards, and we prefer compliance with those standards whenever practical. (We do not specifically consider United States FASB GAAP compliance.)

However, strict compliance with AASB/IFRS is not always practical, and ledger-pyreport departs from AASB/IFRS in a number of material ways – for example, the statement of cash flows generated by ledger-pyreport does not show the detailed subclassifications required by AASB/IFRS, nor does ledger-pyreport produce a statement of changes in equity. In both cases, the background information required to produce the reports accurately is beyond the scope of ledger-pyreport.

Other aspects of AASB/IFRS requirements are the user's responsibility – for example, the selection of an appropriate chart of accounts and appropriate recognition of transactions in those accounts.

Contact (issues, pull requests, etc.) at git@yingtongli.me. Generated by cgit.