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
Chronos Ledger overview for Beispiel GmbH: the time slider at 11 September 2026 at the top, below it cards for liquidity at the selected date, low point and peak in the horizon, non-liquid position and runway, then the cards Locked in vs modelled, Backtest and Actual balance

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

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.

VAT view with demo data: a note on Ist-Versteuerung, Dauerfristverlängerung and § 108 AO, six figure cards and a bar chart of output VAT, input VAT and Zahllast per quarter from 2026 to 2029
The rules sit above the figures so that nobody reads the cards without them. Every amount is an invented demo value.

What is hard-coded

01 Whole cents, tax in basis points No floating-point amount reaches storage. VAT is computed in basis points: carved out of a gross amount, or added on top of the amount under reverse charge, rounded to whole cents in both cases.
02 A recorded balance wins When someone enters what an account really held on a day, the application books the difference as a visible adjustment row instead of changing the past. That row is neutral for profit and VAT: an unexplained difference becomes neither revenue nor cost.
03 Wallets divide, they never add Reserves inside an account are a division of its balance. Whatever no wallet claims appears as unassigned. There is exactly one liquidity figure.
04 Claims without cash are not liquidity Favours, deferred pay and agreed debts sit on accounts of their own that do not enter liquidity, and are totalled separately.
05 Profit taxes by statute Körperschaftsteuer at 15 percent, Solidaritätszuschlag at 5.5 percent of that, Gewerbesteuer as a base rate of 3.5 percent times the Hebesatz, which is a setting. No allowance for a corporation, and the Gewerbesteuer does not reduce its own base.
06 Income tax under § 32a EStG The 2026 tariff in its five zones, the marginal rate derived analytically rather than by differences, because the tariff rounds down to whole euros. The implementation was cross-checked against an independent calculation. An expected refund is planned as a dated inflow, by default on 30 September of the following year.
07 People: value against cost A person is charged with every outflow assigned to them, fees from standing orders included. The assigned value is entered by hand and requires a stated basis, because there is no honest automatic way to derive it.

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.

Investments view with demo data: three positions, one cleared and two waiting, each with amount, profit threshold, projected profit, minimum liquidity, earliest date and check horizon
Three invented positions. Two are waiting because projected profit sits below their threshold, even though liquidity would carry them.

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

People view with demo data: four figure cards, a scatter plot of assigned value against cost with a diagonal, a credit book and three person cards named only by role
Value against cost per person. Above the diagonal, someone brings in more than they cost; the credit book beside it does not count as liquidity.
Sheet view with demo data: a grid of opening balances for five accounts and below it a grid that divides accounts into named wallets with share and target amount
Entry as in a spreadsheet, pasting from Excel included. The wallets divide an existing account and add no money.

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

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

Grace Hopper

“The most damaging phrase in the language is: it's always been done that way.”