R&D LAB Method In use Built for our own financial planning
Chronos Ledger
Liquidity and tax projection for a German GmbH, computed deterministically
How much money sits on which account on a given day, and which taxes fall due by then? Computed under German rules, without a language model.
- 0runtime dependencies, just Node and SQLite
- 1row list every view is computed from
- 12views onto the same projection
- P10to P90: a band around the curve, computed analytically

Every capture in this article shows a separate demo database with invented figures for a Beispiel GmbH. People appear only by their role.
Why this is published
We sell software and automation, including where rules are dense and have consequences. Chronos Ledger shows how we turn tax and accounting rules into code: every rule in one place, the tax arithmetic locked by a self-test, the central totals recomputed by an independent audit script. The application is also a counterexample to the assumption that a language model belongs in everything today. None belongs here, because a liquidity or tax figure has to be the same on every run and has to be checkable step by step.
Bookkeeping looks backwards: it records what has happened. Planning a small company needs the other direction. Chronos Ledger computes forwards and answers how much money will sit on which account on a given day, and what will have fallen due by then in VAT, profit taxes and wages. To do that the application keeps company and private accounts side by side, models VAT under Ist-Versteuerung with a Dauerfristverlängerung, computes Körperschaftsteuer, Solidaritätszuschlag and Gewerbesteuer, projects income tax under § 32a EStG, and moves every deadline to the next working day under § 108 AO. A time slider recomputes every figure for any chosen date. It runs locally on Node and SQLite and files nothing.
The decision
A tax figure that comes out differently the second time is not a figure
For a planning application today the obvious move is to build in a language model: a question in words, an answer in words. Chronos Ledger deliberately has none. A liquidity forecast becomes the basis for decisions about wages, purchases and tax reserves. For that, the same data has to produce the same figure on every run, and every figure has to be traceable to the bookings it came from. A question panel was on the table and was not built; it would have been the first outbound API call this application ever made.
The second decision carries the whole application. For every request the planning horizon is built exactly once as a flat list of dated rows: booked movements, expanded standing orders, payroll runs, the derived VAT and profit tax payments, cleared investments and expected income tax refunds. Every chart and every table is computed from that one list. Two views are never supposed to disagree about the same day. When the header and the curve once did, because two functions walked the same rows separately, the audit script found the difference.
The third concerns tax. What a booking is, what the VAT return sees of it and what the profit calculation sees of it are three separate columns. A single type per booking cannot express a transfer between your own accounts, which moves money on two accounts and is revenue nowhere. Categories preset the three values, but every booking keeps its own copy.
What deliberately does not come out of this is a tax return. The application projects and prepares; it transmits nothing to ELSTER, and every tax view carries the note that it is an estimate.
A forecast that cannot be recomputed is an opinion with decimal places.
From standing order to curve
How a figure for any given day comes about
- 01 Movements and series Booked and planned movements live in the same table, told apart by a status. Standing orders are expanded into dated occurrences and end at their end date, after a fixed number of payments, or at the end of the horizon. A series on the 31st lands on the 28th in February and back on the 31st in March.
- 02 Derived tax payments The rows yield the quarterly Zahllast under Ist-Versteuerung, due with the Dauerfristverlängerung on the 10th of the second following month, and on the next working day if that is a weekend or public holiday. Profit taxes are placed on their statutory prepayment dates. An input VAT surplus does not arrive on the due date but 21 days after it.
- 03 One list Together this makes the one row list. Amounts are whole cents, dates are ISO strings without a time zone. Only the income tax tariff computes in euros, because the statute states its constants in euros.
- 04 Curve and band The list yields the liquidity curve per account and in total. Every planned row is a coin toss at its entered probability; from that follow the expected value, the variance and a P10/P50/P90 band in closed form, without random numbers. The same data always draws the same band.
- 05 Time slider The slider steps between the days on which money actually moves and the month ends. At every point the header, the balances and the claim ledgers are recomputed. The charts, by contrast, are scaled by time, so that the low point appears where it falls in the calendar.
VAT by payment date, and by nothing else
Under Ist-Versteuerung, VAT arises in the period in which the money moves. The application therefore stores a payment date and no invoice date at all. A second date column would sooner or later be used for a total, and then the return no longer adds up.
The same view states what does not happen: a quarterly filer with a Dauerfristverlängerung makes no Sondervorauszahlung, because the one-eleventh applies to monthly filers only. For services from foreign suppliers under § 13b UStG the tax is computed on top of the amount rather than out of it, and recorded on both sides of the return, with no effect on cash or on the Zahllast.
VAT cannot attach to money that is not a supply in the first place. Wages, transfers between your own accounts, tax payments and loans are excluded from input VAT in the calculation, whatever box was ticked in the form.
What is hard-coded
An investment is cleared, not listed
A planned investment gets two conditions: a minimum profit after tax for the financial year, and a liquidity floor that must not be breached over a check horizon after the payment, running monthly costs included. It only turns green when both hold.
The answer is not yes or no, it is a date. The application walks the curve forwards and names the earliest day from which liquidity carries the payment. If an investment has a latest date and misses it, it counts as missed, so that a closed option stops presenting itself as an open one.
Scenarios act on the same calculation. Investments, standing orders and bookings can be assigned to a scenario and switched on and off with it. Taking an item out of a scenario returns it to the baseline rather than deleting it.
Verification
Three ways of distrusting your own figure
A self-test locks the arithmetic: money amounts, deadlines with their shifts, VAT, profit taxes, the zones of the income tax tariff, series, adjustment rows and the uncertainty band. Anyone changing a rate or a tariff constant changes the matching assertion in the same step. A silent constant change is exactly the failure this application cannot absorb.
An audit script recomputes the central totals a second time straight from the raw tables, with its own code: liquidity today, low point, end of horizon, VAT and profit base. It also reports bookings that contradict themselves, such as an outflow classed as revenue. Where the disagreements came from was instructive: more than once the fault lay in the audit script, because it did not yet know a rule the engine already had. Since then every new rule comes with the question of whether the audit script knows it.
And the application records its own forecasts: once a day, month ends only, never overwritten. Later they are scored against what the accounts actually held on booked movements, never against a newer forecast. The error is averaged as an absolute value, so that one figure too high and one too low do not cancel each other out.
What it computes, and what it deliberately does not do
Computed
- Liquidity per account and in total, for every day in the horizon.
- VAT per quarter with deadlines, shifts and reverse charge.
- Körperschaftsteuer, Solidaritätszuschlag, Gewerbesteuer and their prepayment dates.
- A projected income tax under § 32a EStG with its expected refund.
- The earliest day on which an investment meets both conditions.
- A P10/P50/P90 band from entered probabilities.
Deliberately not
- No transmission to ELSTER and no tax advice. Filing happens elsewhere.
- No double-entry bookkeeping. The application projects; it does not book.
- No wage tax computed from gross. The payroll figures are taken over.
- No language model, no simulation with random numbers.
- No correlation between payments inside the band. If defaults are linked, the real spread is wider, and that is stated beside the band.
- No loss carry-forward. A loss currently simply produces no tax.
People and the sheet, on invented data
What this construction is good for
- Small corporations that want to see whether wages, reserves and tax dates fit together over the coming months.
- Purchase decisions tied to profit and liquidity rather than to a feeling.
- Line-of-business applications with dense statutory rules, where every figure has to be reproducible and traceable.
- As a template: a rule set as code, with a self-test and an independent audit script, beyond tax as well.
Why this is published
What this means for your project
More from the lab

Method Event Scout A language model reads the event pages; everything else is fixed code. What remains is a short list of where a day in person is worth it.
Applied Research Vellum Edges, perspective, light and text are all worked out on the phone. A document leaves the device only when someone sends it. Do you have a rule set that currently lives in a spreadsheet and whose figures someone has to be able to check? That is exactly what a pilot is for.
Get in touch