Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Entries

An entry (also called a flow) is a transaction that fires on a schedule. Each time it fires, it moves money between accounts according to a list of postings. All postings in one firing must balance to zero.

Syntax

entry <schedule> "<label>" {
  <account> [= <amount>] [as <leg>]
  ...
} [as <alias>]

Postings

Each line inside the braces is a posting: an account and an optional amount.

Fixed amount

Assets:Cash = 5_000
Expenses:Rent = 3_915.30

The account balance is increased by the given amount. Use a negative expression to decrease a balance.

Auto-balance

Omit = on exactly one posting per entry. saldo calculates the amount that makes all postings sum to zero:

entry monthly "Jim's paycheck" {
  Assets:Retirement:Jim = 1_500
  Assets:Cash           = 7_500
  Income:Gross:Salary:Jim          // auto-balanced: receives -9_000
}

Because income accounts carry a negative balance by convention, the auto-balanced posting receives the negation of the net inflow.

Clearing a balance (all)

Use = all to move the entire current balance of an account:

entry monthly "Loan payment" {
  Liabilities:AccruedInterest = all   // clears whatever has accrued
  Liabilities:Loan            = 2_000
  Assets:Cash
}

Named legs

Append as <name> to a posting to give it a leg name. The leg accumulates into period-to-date totals that can be read in later expressions within the same simulation day:

entry semi_monthly "Seb's paycheck" {
  Assets:Retirement:Seb = min(max_401k - retirement_contribution.ytd,
                              max_401k / 24 + 0.01)  as retirement_contribution
  Assets:Cash           = seb_salary / 24 - retirement_contribution
  Income:Gross:Salary:Seb                            as gross_income
} as seb_paycheck

retirement_contribution.ytd is the running year-to-date sum of every retirement_contribution leg across all firings so far this year. Once a leg name is established, you can reference it in the same entry on subsequent posting lines (as retirement_contribution above, without .ytd), which gives you the value from the current firing.

Available aggregation suffixes:

SuffixResets
.ytdJanuary 1
.qtdFirst day of each quarter
.mtdFirst day of each month

Flow alias

The optional as <alias> at the end of the block gives the flow a name for use in scoped aggregations:

} as seb_paycheck

Reference a leg scoped to this flow with <alias>.<leg>.ytd:

assert that seb_paycheck.retirement_contribution.ytd <= 24_500

Without an alias, leg aggregations are unscoped and can be referenced directly by leg name.

Complete example

param max_401k       : usd/year = 24_500
param jim_salary     : usd/year {
  from 2025-12-31 to 2026-04-01 = 115_000
  from 2026-04-01               = 130_000
}
param retirement_rate = 0.16

entry monthly "Jim's paycheck" {
  Assets:Retirement:Jim = min(max_401k - retirement_contribution.ytd,
                              jim_salary * retirement_rate / 12)  as retirement_contribution
  Assets:Cash           = jim_salary / 12 - retirement_contribution
  Income:Gross:Salary:Jim
} as jim_paycheck

entry daily "Interest accrual" {
  Liabilities:AccruedInterest = Liabilities:Loan * interest_rate / 365
  Expenses:Interest
}