DECCF · Cash Flow Modeler and Calculator

Calculation context

Synchronous callbacks for amounts, fields, states, events, options, flow distributors, and custom metrics receive a read-only context for one period.

Metric declarations may set periodLength and frequency, both measured in model periods. ctx.metricPeriod is present while a declared metric runs and contains inclusive startIndex, endIndex, startDate, endDate, and length values. The callback still receives ctx.time for the period at which the metric is emitted.

Time and owner

ctx.time contains index, date, calendar, periodsPerYear, daysInPeriod, and phase (the phase name or null). ctx.owner contains the owner reference when the callback has one.

Read values

  • ctx.get(inputRef) returns the input value. A curve returns its value for the current period.
  • ctx.curveAt(curveRef, date) reads a curve at an explicit date.
  • ctx.get(fieldRef) returns the field's numeric value for the current period.
  • ctx.get(accountRef) returns the account balance after its postings in the current period. A cashflow must list it in readsAccountsFrom; the engine then schedules cashflows that post to it first. Period-closing flows are left for the closing phase. A custom metric sees the final period balance.
  • ctx.previous(fieldRef) returns the previous field value, or the initial value in the first period.
  • ctx.get(flowRef) returns the current period's Money. The source flow must already have run and be listed in the reader's dependsOn.
  • ctx.previous(flowRef) returns the previous period's net amount as a number, or zero in the first period.
  • ctx.sum(flowRef, from?, to?) sums inclusive period indexes. The default range is period 0 through the previous period. It cannot read future periods.
  • ctx.sumAccountPostings(accounts, from?, to?, { excludePeriodClosing? }) sums debit postings as positive and credit postings as negative for the listed accounts over inclusive period indexes. The default range ends at the previous period. A flow that reads only earlier-period postings declares those accounts in readsHistoricalAccountsFrom; this grants historical access without creating same-period dependency edges. A flow reading the current period declares the accounts in readsAccountsFrom, which also orders it after flows that post to them. Set excludePeriodClosing: true to omit closing entries.
  • ctx.sumAccount(accountRef, fromDate, toDate, options?) sums debit-minus-credit postings to the account over inclusive dates. A cashflow must list an account it sums in readsAccountsFrom or readsHistoricalAccountsFrom; the former evaluates same-period posting flows first, while the latter only permits ranges ending before the current period. Set { excludePeriodClosing: true } to sum the original transactions without internal year-end closing entries. A custom metric can read the finalized posting history.
  • ctx.sumInflows(owner, fromDate, toDate, category?) sums the owner's inflows in an inclusive date range. The optional category includes descendants. These inflows are ordered before the reader.
  • ctx.sumCashflows(owner, fromDate, toDate, { direction?, category? }) sums the owner's signed cashflows. Category matching includes descendants; set readsCashflowsFrom: owner to order the reader after that owner's flows.
  • ctx.term(agreementRef, termRef) reads a term belonging to the agreement.
  • In a booking callback, ctx.amount is the cashflow's base amount. It can be split across accounts. For a triggered occurrence, ctx.source is an immutable snapshot containing flow (the source reference), name, optional trigger name, amount, currency, date, and period. ctx.source.amount is from that exact source occurrence.
  • ctx.sumCashflows(..., { category }) can filter posting cashflows by account categories. It uses economic direction for income/expense categories; asset, liability, and equity categories use signed debit/credit movements. See Post cashflows to accounts.

State

ctx.isInState(entityRef, stateRef), ctx.currentState(entityRef), ctx.enteredAt(entityRef, stateRef), and ctx.inPhase(phaseRef) perform reference-based queries. enteredAt returns a period index or null.

Uncertainty

ctx.get(distributionRef) uses the distribution's central value. To draw a value, the callback must call ctx.draw(distributionRef) or ctx.sample(distributionRef).

  • draw takes one pseudorandom sample per input, seed, and trial, then reuses it across periods.
  • sample takes pseudorandom samples keyed by input, seed, trial, owner, and period.

If no seed or trial is set, both return the central value. runMonteCarlo() supplies a seed and trial index while evaluating the stochastic simulations. The engine has no correlation configuration.

Flow distributor steps

A flow distributor step callback receives additional available, remaining, owed(stepRef), and paid(stepRef) helpers. Later steps can use them to calculate requested amounts from available funds and earlier allocations. The TypeScript declaration currently describes owed and paid as maps, unlike their runtime function form.

Ordering and synchronous callbacks

Callbacks run synchronously; asynchronous values are not supported. Avoid network requests and mutation of shared model state. A flow can only read same-period cashflows that have already run according to the compiled dependency order.