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.
Related¶
- Accounts: the accounts a book is kept for, and what bounds a plugin's reach.
- Booking: an order's executions booked to its accounts.
- The custodian's activity: the custodian's record of what happened, which explains a break and proposes its entry.
- Record a holdings statement: how the custodian's view reaches the street store.
- Prove your plugin against a released runtime: print the book from a plugin's e2e, and compare it with what you expect.