Skip to content

The book of record

There are two beliefs about what an account holds: the firm's and the custodian's. The custodian's arrives in the street store, as custody plugins report it. A deployment also keeps the firm's own: the book of record, a core component, bor, with its own store. An account enters the book once, with an opening balance a person answers for; after that the book changes only by its own entries; and an operations plugin reconciles it with the street on every statement, recording each difference as a break.

The rule is short. The street is what custodians say. The book is verified against it, and never overwritten by it. No statement is ever applied to the book.

The edge, the street and the book

What is held is recorded in three places, by three owners, and no one of them is a copy of another.

What it holds Who writes it
The edge A plugin's raw records, as it received them from outside: a vendor's responses, a statement as sent The edge plugin alone, in storage of its own. Core never reads it, and no other plugin does
The street The custodian's view, as reported: statements, holdings and custodial positions, each statement's figures, and what of each holding is available and what cannot move; each activity on the account and each sync status Custody plugins, through the street store. See Record a holdings statement and The custodian's activity
The book The firm's view: positions, lots, pending settlements, encumbrances, breaks, figures and each account's attributes, every change a journalled entry An operations plugin, through the book; the dashboard sets an account's attributes

A custody plugin converts what its vendor sends into the street's terms at the edge, and may keep the raw records to debug a difference between what the vendor said and what it recorded: the SnapTrade plugin keeps its raw responses for a stated time and shows them on its own Raw responses tab. The deployment giving an edge plugin storage of its own for them is specified and not built yet, so such a plugin keeps them where its pod lets it, for as long as the pod lasts.

The book and the street share no key, join or transaction. A break, or an opening balance, names the street record it came from by value: the statement, the custodial position's change, the custodian's as-of date.

What the book holds

Every quantity is an exact decimal, and every amount carries its currency. A value a source did not state is unset, never zero.

Record What it is
Position An instrument and a side in one account, and a sleeve, a part of the account, empty for its unsleeved part. Its trade-date quantity is its settled quantity plus what is pending on each value date, by construction. A position held under a placeholder instrument is flagged. A position under a provisional instrument record is a local line: recorded and reconciled, never priced (see One ID per instrument).
Lot The book's own record of how a position was acquired: its open and original quantity, its cost and currency, its acquisition date, and where it came from. A position's open lots sum to its trade-date quantity; cash in the base currency has none. Every lot the book opens carries its cost and its acquisition date.
Pending settlement Quantity pending on a value date, which may be years out, with whether it is failing and its new expected date where the source reports a fail.
Encumbrance What of a position cannot move, as the latest statement states it: its kind (pledged, posted, on loan, blocked, restricted, in transit, or other with the source's own code), its quantity, to whom and where, and the margin agreement where the source names one. An attribute of the position, never a movement: its quantities do not change.
Free quantity Derived, never reported: the settled quantity less the encumbrances. Unset while the settled quantity is unknown. It is what is free to trade.
Break A difference between the book and the street, open, resolved or closed. See Breaks.
Figures The account's figures for a business date, one set per margin agreement, as the street recorded them, with the collateral held under it and the custodian's own value and margin requirement for each position, labelled as the custodian's. A series, never a figure the book computed.
Attributes The account's base currency, its default method of relieving lots when a sale names none, and its standing opening balance; and whether its releases wait for compliance.
Orders and executions Each order, its placements, executions and charges, the facts the book could not place, the locates, and the trading instructions, an order's state derived from its journal. Reported fills move the account's trade-date position at once; a fill the venue originated waits unmatched, moving no position until the ems accepts it, and then as of its trade date; a venue's daily roll of a spot FX position moves its pending lines to the next value date by an entry of its own, the trade-date position unchanged. See The order lifecycle.
Bookings and alerts Each booking of an order's executions to its accounts, its allocations and its state, and the alerts the book and compliance raise on them. See Booking.

The book records; it does not police. It computes no margin, no projection, no scenario and no return, and converts nothing with the base currency. Plugins that read it derive those, joined to reference and market data.

Every change is an entry

The book is an append-only journal, partitioned by account. An entry is never updated or deleted: a correction is a later entry naming what it corrects. Every entry that moves a position is a set of movement lines, and a position is its account's opening balance plus every entry's lines since. Each entry records its kind (opening-balance, adjustment, reversal, break-recorded and others, an open list), its cause, who made it (a person, a service account with its owner, or the plugin itself for a finding), the plugin instance that sent it, when it was sent, received and committed, and the business date it stands for. Every record an entry changes is numbered from the account's partition, with no holes, so a reader that misses one can tell.

The positions, breaks and figures a plugin reads are projections of the journal, and meridian-bor rebuild makes them again from the journal alone.

How an account enters the book

An account enters once, with an opening balance: as of a business date, what it holds, position by position, with each position's trade-date quantity, its settled quantity, its pending settlements by value date, and its lots, each with its quantity, cost and acquisition date, as the custodian or the prior system reports them and a person completes them. It names its source, the date the source's figures are as of, whether they are trade-date or settled, and the street records it was composed from. An account holding nothing enters with an empty balance.

An opening balance is the fact every later break inherits, so a person confirms it. An operations plugin composes it, typically from the account's first completed statement, and may propose a position's lots from the custodian's activity (the opening balance's lots), and shows it on its own page; a person granted write on the account through the plugin confirms it there, with a reason, and the book records that person as having made it. The book refuses:

  • an opening balance with no person (REFUSAL_REASON_ACTOR_REQUIRED) or no reason (REFUSAL_REASON_REASON_REQUIRED);
  • a second one for an account that has one standing (REFUSAL_REASON_OPENING_BALANCE_RECORDED);
  • one missing anything the book requires (REFUSAL_REASON_INCOMPLETE), naming each missing field: see What the book requires;
  • lots that do not sum to their position (REFUSAL_REASON_LOTS_UNBALANCED).

A holding the street records under a placeholder enters under that placeholder, flagged, and does not hold the confirmation up; when the instrument is identified, the book moves what it holds under the placeholder onto the instrument, as an entry of its own. An error in an opening balance is corrected by an adjustment with its reason, or, while no later entry moves the account's positions, by reversing it and recording a new one naming the reversed one.

What the book requires

The edge keeps what the custodian sent as it was sent, and the street keeps the custodian's view as reported, gaps and all. The book alone holds the minimum that what comes after it needs: tax tracking, valuation, confirmation and settlement. It refuses an entry missing any of it, with REFUSAL_REASON_INCOMPLETE, records nothing, and names every missing field by its path in the command, such as positions[0].settled_quantity or positions[1].lots[0].terms.cost, so the plugin can show, position by position, what is missing.

Of every position, whatever its asset class:

  • the instrument and the side, and the trade-date quantity, as of the opening balance's date;
  • the settled quantity. Where the source states none, a person supplies it;
  • each pending quantity, with its value date. The settled quantity and the pending quantities account for the whole trade-date quantity: a remainder neither settled nor pending on a date is missing;
  • where it is held: the account the opening balance is for, and a named source, the custodian or the prior system.

And its lots, by asset class:

Asset class Lots
Equity, fund and ETF; crypto; option At least one. Each with its quantity, its cost in all, and its acquisition date. They sum to the trade-date quantity.
Money market fund One lot at its stable value: cost is the quantity × 1. A lot like any other here.
Cash None in the account's base currency. A position in any other currency carries lots, each with its cost in the base currency and its acquisition date.

The book reads whether an instrument is cash from its record: its asset class, or a currency identifier. Where the record cannot say, because the position is held under a placeholder, the record names no asset class and no currency identifier, or the instrument store does not answer in time, the book does not require the position's lots, for now, and still refuses any lot sent incomplete. An operations plugin flags such a position, and it does not hold the confirmation back; the security master completing its records removes the cause.

The same holds after the opening balance: a lot an adjustment opens carries its cost and acquisition date, or the adjustment is refused (adjustment.lines[0].opens_lot.cost).

An operations plugin gates Confirm. It offers a person the opening balance to confirm only when every required field is populated and validated, and shows, per position, what is missing. The person supplies what the source lacks, typed, or loaded from a cost-basis export or a statement, each value recorded with its source and the person; the plugin checks it: the lots sum to the quantity, the dates fall on or before the opening balance's, the costs are plausible. The book's refusal is the second line, not the form.

Older records

The book admits no lot of unknown cost and no settlement bucket "not stated". They stay on the wire for older records: a position's not-stated quantity is zero on every position the book records now, and its settled quantity is set. A lot an older opening balance opened with its cost unknown is given its cost by an adjustment, once it is known.

Reconciling each statement

On every completed statement after the opening balance, an operations plugin compares the book with the street, account by account and margin agreement by agreement: trade-date and settled quantities, cost and lots, settled against pending, a position on one side only, and what cannot move. When and how it compares is the plugin's behaviour; what it records is the book's. From each statement it records:

  • each difference, as a break;
  • the account's figures, as the street recorded them;
  • each position's encumbrances, as the statement states them.

These are findings, so the plugin may send them as itself, acting for nobody. Every difference is a break: core has no tolerance, and a plugin may rank or group breaks for its people but never drop one. A break that persists is one break, brought up to date, not another each day. Until orders are booked on the platform, every trade made away from it and every corporate action shows as a break until it is resolved.

Breaks

A break records the account, the position or account-level figure it concerns, its category (trade-date quantity, settled quantity, cost or lots, settled against pending, on the book's side only, on the street's side only, or a figure), each differing field with the book's value and the street's, what was compared, and the business dates it was first and last seen. Its age is derived from those dates, never stored.

The plugin's matching offers candidate causes: an unbooked trade, settlement timing, a cost or price difference, a corporate action, a fail, a custodian error, unknown, income the custodian reinvested, or a value date that is not a business day, linked to the date read's check (the date, the calendars and their versions, and why the day is closed), each with the item found to cause it. That item may be the custodian's own activity: a reinvestment, a split, a trade made away from the platform, linked by value, from which the plugin proposes the adjustment. See The custodian's activity. A person confirms one, and sets who owns the break, its escalation level and its due date. Then a person ends it, with a reason, in one of three ways:

  • Resolved, by the entry that corrects the book in the same act: an adjustment with its movement lines, each lot it opens with its cost and acquisition date, or a reversal of an entry. The book moves only by that entry, which names the break, so a correction traces back to what caused it.
  • Closed with an explanation, moving nothing: a custodian's error, say.
  • Closed as cleared, citing the statement where the difference was gone, moving nothing: a settlement landing, or the custodian catching up.

A break is never closed by silence, and a statement never overwrites the book.

An unrecognized security. A statement line too thin to make an instrument record -- less than an identifier, a description and a currency -- is kept in the street as a placeholder, outside the book. The operations plugin records it as a break of its own category, BREAK_CATEGORY_UNRECOGNIZED_SECURITY, naming no instrument and the street record by its identifiers, brought up to date while it persists. A local line, a position under a provisional record, is reconciled as any position. See One ID per instrument.

A person, or a service account

The book's justified acts -- an opening balance, a break's cause and handling, its resolution, closing it as cleared -- are a user's: a person, or a service account a plugin's autonomous work acted as, through the plugin's own act. The reason is still required, and the book refuses either act sent for nobody (REFUSAL_REASON_ACTOR_REQUIRED). Whether a service account may make an act is the admins' levels and its own setting, which by default only prepare it for a person to make: the book records, and does not police. An entry a service account made names it, by its SA- ID, and its owner when it acted, so it never reads as a person's act nor as the plugin's own finding. The sample operations plugin's close of cleared breaks is one (see Using an operations plugin).

Who reads the book

A plugin reads and hears the book only within its read scope, as it reads the street; see Accounts.

Record Written by Read and heard by
Positions operations portfolio, reporting, compliance, oms, operations
Breaks operations operations, oms, compliance, portfolio, reporting
Figures operations operations, portfolio, compliance, reporting
Attributes the dashboard, for a deployment admin; the standing opening balance by the book, when operations records one portfolio, reporting, compliance, oms, operations, ems, connectivity, and the dashboard
Orders, placements, executions portfolio, oms and ems propose; the oms releases; the ems places; connectivity plugins report the venue's facts oms, ems, compliance, portfolio, operations, reporting; a placement's connectivity plugin alone of its role
Trading instructions the dashboard, for a deployment admin or a plugin's admin oms, ems, connectivity, portfolio, compliance, whatever their accounts

A position is delivered whole, its lots and pending settlements included, so a plugin that hears it needs no second read.

An account's attributes, on the Accounts tab

A deployment admin sees the book's attributes of each account on the Accounts tab of the dashboard's Settings, with the account itself: there is one book per deployment, so they sit with the account they belong to. Each account's row has two columns from the book:

Column What it shows
Base currency The account's base currency in the book
Lot relief The method a sale relieves lots by when it names none: first in, first out; last in, first out; highest cost; lowest cost; or average cost
Compliance Waits where the account's releases wait for every covering compliance plugin's verdict, as a new account's do, or Does not wait; set under In the book as Releases

An account's Edit has a section of its own, In the book, beside Account. Beside its title it says since when the account is in the book, the date its opening balance stands for, or not yet before it has one. It sets the Base currency, three capital letters, and Lot relief, when a sale names none, and asks for a Reason, with its own Save. Each attribute you change is its own entry in the account's journal, with your reason and you as the one who made it; saving with nothing changed is refused, saying the book holds these already. An account may have attributes before its opening balance. If the book does not answer, the tab says so above the accounts, and the rest is drawn without it. See In the book.

The tab shows no position, lot or break. The dashboard reads every account's attributes and no account's data, as a deployment admin reaches no account's data: positions and breaks are for the plugins that read them, shown on their own pages to the people granted access to them.

The book's resources

The book replays an account's journal for each command and each dated read, so its pod is given more room than core's other components. The chart sets it apart, under bor in its values:

Value Default What it does
bor.resources a request of 50m CPU and 128Mi of memory, a limit of 512Mi of memory The book's own requests and limits, in place of the shared resources
bor.mallocArenaMax 2 Sets MALLOC_ARENA_MAX in the book's container: at most this many of the allocator's arenas, so a burst of requests answered on many threads does not keep an arena's memory per thread

Each of core's components answers at most 16 requests at once; the rest wait their turn. A component's environment variable MERIDIAN_HANDLERS_AT_ONCE, a positive whole number, sets another bound for that component alone, so a deployment can lower one component's without a new release.