ores.trading.trade_booking
Table of Contents
A trade's booking: the book that holds it, the netting set it is filed in, the date it was agreed and the time it was executed. It is a component of the trade anchor, keyed by the trade id, and versions on its own timeline: a book move or a re-papering into another netting set cuts a new version of the booking and leaves the anchor alone.
The booking copies the anchor's party and counterparty. The copies are pinned to the anchor, so they cannot drift, and they are what the other pins and row-level security read: the book must belong to the trade's party, and the netting set to its counterparty and party.
A booking names a virtual book, one inside a sandbox, only while its trade is a pre-agreement draft, a test or a hypothetical. An actual trade going live needs a real book: the booking is written before the state that takes the trade live, in the same transaction.
1. Flags
2. Columns
2.1. trade_id
The trade this booking belongs to.
ctx.generate_uuid()
2.2. trade_activity_id
The activity that wrote this version.
2.3. book_id
The book that holds the trade.
ctx.generate_uuid()
2.4. netting_set_id
The netting set the trade is filed in.
std::nullopt
2.5. counterparty_identifier_id
The identifier the trade's source named its counterparty by.
An ORE document names a counterparty by an alias, and two aliases may name
one counterparty, as CP and CPTY do in the ORE samples. The import keeps
the identifier it resolved, so an export writes back the name the document
used.
std::nullopt
2.6. netting_set_identifier_id
The identifier the trade's source named its netting set by, kept for the same reason as the counterparty's.
std::nullopt
2.7. trade_date
The date the trade was agreed. Absent when the source does not state it, as an ORE document does not.
std::chrono::year_month_day{std::chrono::year{2025}/1/15}
2.8. execution_timestamp
The time the trade was executed.
std::nullopt
3. SQL
3.1. Flags
3.2. Virtual books
A virtual book holds no position of the firm, so an actual trade may sit in one only while it is a draft. The check reads the trade's current state; a booking written before any state is allowed, because the state that follows checks the booking in turn.
if ores_trading_book_is_virtual_fn(NEW.tenant_id, NEW.book_id) and not ores_trading_trade_may_be_virtual_fn(NEW.tenant_id, NEW.trade_id) then raise exception 'Invalid book_id: %. A virtual book holds only drafts, tests and hypotheticals.', NEW.book_id using errcode = '23514'; end if; -- The booking holds no party of its own. The party and the counterparty -- are the deal's, so the book, the netting set and the counterparty -- identifier are checked against the trade the booking names rather than -- against a copy that could drift from it. if not exists ( select 1 from ores_refdata_books_tbl b join ores_trading_trades_tbl t on t.tenant_id = b.tenant_id and t.party_id = b.party_id where b.tenant_id = NEW.tenant_id and b.id = NEW.book_id and b.valid_to = ores_utility_infinity_timestamp_fn() and t.id = NEW.trade_id and t.valid_to = ores_utility_infinity_timestamp_fn() ) then raise exception 'Invalid book_id: %. The book must belong to the trade''s party.', NEW.book_id using errcode = '23514'; end if; if NEW.netting_set_id is not null and not exists ( select 1 from ores_refdata_netting_sets_tbl s join ores_trading_trades_tbl t on t.tenant_id = s.tenant_id and t.party_id = s.party_id and t.counterparty_id = s.counterparty_id where s.tenant_id = NEW.tenant_id and s.id = NEW.netting_set_id and s.valid_to = ores_utility_infinity_timestamp_fn() and t.id = NEW.trade_id and t.valid_to = ores_utility_infinity_timestamp_fn() ) then raise exception 'Invalid netting_set_id: %. The set must be the trade''s counterparty''s and party''s.', NEW.netting_set_id using errcode = '23514'; end if; if NEW.counterparty_identifier_id is not null and not exists ( select 1 from ores_refdata_counterparty_identifiers_tbl ci join ores_trading_trades_tbl t on t.tenant_id = ci.tenant_id and t.counterparty_id = ci.counterparty_id where ci.tenant_id = NEW.tenant_id and ci.id = NEW.counterparty_identifier_id and ci.valid_to = ores_utility_infinity_timestamp_fn() and t.id = NEW.trade_id and t.valid_to = ores_utility_infinity_timestamp_fn() ) then raise exception 'Invalid counterparty_identifier_id: %. The identifier must be the trade''s counterparty''s.', NEW.counterparty_identifier_id using errcode = '23514'; end if; if NEW.netting_set_identifier_id is not null and not exists ( select 1 from ores_refdata_netting_set_identifiers_tbl si where si.tenant_id = NEW.tenant_id and si.id = NEW.netting_set_identifier_id and si.netting_set_id = NEW.netting_set_id and si.valid_to = ores_utility_infinity_timestamp_fn() ) then raise exception 'Invalid netting_set_identifier_id: %. The identifier must be the netting set''s.', NEW.netting_set_identifier_id using errcode = '23514'; end if;
3.3. Indexes
| name | columns | unique | current_only | where_extra |
|---|---|---|---|---|
| book | tenant_id, book_id | false | true |
4. Foreign keys
4.1. trade_id
A database foreign key: the anchor is immutable.
#include "ores.trading.api/generators/trade_generator.hpp" #include "ores.trading.core/repository/trade_repository.hpp" #include <optional>
{
auto anchor = ores::trading::generators::generate_synthetic_trade(ctx);
anchor.party_id = *party_ctx.party_id();
ores::trading::repository::trade_repository().write(party_ctx, anchor);
v.trade_id = anchor.id;
}
4.2. trade_activity_id
The activity that wrote this version. A database foreign key: the activity is immutable.
#include "ores.trading.api/generators/trade_activity_generator.hpp" #include "ores.trading.core/repository/trade_activity_repository.hpp"
{
auto activity = ores::trading::generators::generate_synthetic_trade_activity(ctx);
activity.party_id = *party_ctx.party_id();
ores::trading::repository::trade_activity_repository().write(party_ctx, activity);
v.trade_activity_id = activity.id;
}
4.3. book_id
The book. Temporal, so a trigger check. The seed books into a book of the session party, which the book pin requires.
#include "ores.refdata.api/generators/book_generator.hpp" #include "ores.refdata.api/generators/currency_generator.hpp" #include "ores.refdata.api/generators/portfolio_generator.hpp" #include "ores.refdata.core/repository/book_repository.hpp" #include "ores.refdata.core/repository/currency_repository.hpp" #include "ores.refdata.core/repository/portfolio_repository.hpp"
{
namespace gen = ores::refdata::generators;
namespace repo = ores::refdata::repository;
auto currency = gen::generate_synthetic_currency(ctx);
repo::currency_repository().write(party_ctx, {currency});
auto portfolio = gen::generate_synthetic_portfolio(ctx);
portfolio.party_id = *party_ctx.party_id();
portfolio.change_reason_code = "system.test";
repo::portfolio_repository().write(party_ctx, portfolio);
auto book = gen::generate_synthetic_book(ctx);
book.party_id = *party_ctx.party_id();
book.parent_portfolio_id = portfolio.id;
book.functional_currency = currency.iso_code;
book.change_reason_code = "system.test";
repo::book_repository().write(party_ctx, book);
v.book_id = book.id;
}
4.4. netting_set_id
The netting set. Temporal, so a trigger check.
4.5. counterparty_identifier_id
The counterparty identifier. Temporal, so a trigger check.
4.6. netting_set_identifier_id
The netting set identifier. Temporal, so a trigger check.
5. C++
5.1. Flags
5.2. Repository
5.3. Domain includes
#include <optional> #include <boost/uuid/uuid.hpp>
5.4. Conventions
5.5. Table display
| column | header |
|---|---|
| trade_id | Trade Id |
| book_id | Book |
| trade_date | Trade Date |
| version | Version |
6. See also
- ores.trading — component group overview.
- ores.trading.trade — the anchor this booking belongs to.