ores.trading.bond_instrument
Table of Contents
- 1. Flags
- 2. Natural keys
- 3. Columns
- 4. Foreign keys
- 5. Delete cascade
- 5.1. bond_legs
- 5.2. bond_leg_amounts
- 5.3. bond_leg_rates
- 5.4. bond_leg_amortizations
- 5.5. instrument_schedules
- 5.6. instrument_schedule_dates
- 5.7. instrument_underlyings
- 5.8. instrument_options
- 5.9. instrument_option_premiums
- 5.10. instrument_option_exercise_fees
- 5.11. instrument_option_payment_dates
- 5.12. instrument_strikes
- 5.13. bond_forwards
- 5.14. bond_futures
- 5.15. bond_options
- 5.16. bond_repos
- 5.17. bond_trs
- 5.18. ascots
- 6. SQL
- 7. C++
- 8. See also
One row per bond trade, reshaped from the wide legacy table per the
bond relational model deliverable
(doc/agile/versions/v0/sprint_25/data-oriented-trading-model/design_bond_relational_model.org). The
row carries the instrument's identity only: trade_id, the trade that
identifies both the trade and its instrument, trade_type_code over the
ten bond codes, party_id, and issue_id, the NOT NULL foreign key to the
bond issue row that holds every term of the bond. The economics
moved to the issue (one row per ISIN, shared by every instrument of
it), so an amendment to a term touches the issue row once, not every
open instrument (finding B11 of the deliverable). A product change is
a cancel and a rebook: the service closes the row's validity and
inserts a new instrument row with its fact rows; trade_type_code
never changes in place (review answer 2).
The ten codes, in seed order (trading_trade_types_populate.sql):
Bond, ForwardBond, BondFuture, BondOption, BondRepo, BondTRS,
BondPosition, CallableBond, ConvertibleBond, Ascot. The trade_type_code
check is the in-list coverage check over the ten codes below, which is
the schema's statement of the closed set; the real foreign key to
ores_trading_trade_types_tbl is PR 4's (defect 7). For Bond, ForwardBond, CallableBond,
ConvertibleBond and BondPosition the issue is the bond itself; for
BondRepo the issue is the collateral the financing runs against; for
BondOption, BondFuture, BondTRS and Ascot the issue is the bond the
product is written on (review answers 3 and 4).
1. Flags
2. Natural keys
3. Columns
3.1. trade_type_code
Trade type code (soft FK to ores_trading_trade_types_tbl).
One of the ten bond codes; the coverage check below lists all of them. Never amended in place: a product change closes this row and rebooks a new one.
std::string("Bond")
3.2. party_id
Party that owns this instrument.
Set from session variable app.current_party_id.
3.3. trade_id
The trade this instrument belongs to, and the instrument's own key.
The trade id identifies both the trade and its instrument, so the instrument carries no identity of its own: this column is the key, and the trade it names gives the instrument its scope.
3.4. trade_activity_id
The activity that wrote this version.
3.5. issue_id
UUID of the bond issue this instrument trades (FK to
ores_trading_bond_issues_tbl).
A bond product row states its issue: a row with no issue is not a bond product. The one exception is a bond position on a basket, which holds several bonds and states them as instrument_underlying rows, so it names no single issue. The issue holds the bond's terms; the instrument row reads them through a temporal join on this key, so an amended term reads as of the instrument row's own validity.
ctx.generate_uuid()
3.6. position_identifier
The name a bond position gives its basket, as BondBasketData/Identifier
states it.
3.7. notional
The trade's own amount for its bond, which ORE holds on bondData and
we keep on the bond instrument.
std::make_optional(ores::utility::decimal::decimal::from_string("1000000").value())
4. Foreign keys
4.1. trade_id
The trade that carries this instrument. An instrument is written beside its trade, so a row cannot exist without one.
#include "ores.trading.api/generators/trade_generator.hpp" #include "ores.trading.core/repository/trade_repository.hpp"
{
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.identity.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.identity.trade_activity_id = activity.id;
}
4.3. issue_id
The issue whose terms this instrument's bond carries.
:cascade_orphan: asks the delete rule to take the issue with the
instrument when the instrument was the last row to name it. The issue is
shared by security id, so an unconditional delete would take another
instrument's terms with it, and no delete at all would leave an orphan.
5. Delete cascade
The rows a bond instrument owns. Each is keyed by the instrument's own trade id, so the delete rule closes them all with one statement per table and the family does not outlive its header.
The issue-keyed rows are not here: the issue owns them, and its own cascade closes them when the last instrument of the issue is deleted.
5.1. bond_legs
5.2. bond_leg_amounts
5.3. bond_leg_rates
5.4. bond_leg_amortizations
5.5. instrument_schedules
5.6. instrument_schedule_dates
5.7. instrument_underlyings
5.8. instrument_options
5.9. instrument_option_premiums
5.10. instrument_option_exercise_fees
5.11. instrument_option_payment_dates
5.12. instrument_strikes
5.13. bond_forwards
5.14. bond_futures
5.15. bond_options
5.16. bond_repos
5.17. bond_trs
5.18. ascots
6. SQL
6.1. Flags
6.2. Indexes
| name | columns | unique | current_only | where_extra |
|---|---|---|---|---|
| party | tenant_id, party_id | false | true | |
| trade_type | tenant_id, trade_type_code | false | true |
6.3. Checks
| expression |
|---|
| "issue_id" is not null or "trade_type_code" = 'BondPosition' |
7. C++
The C++ domain class nests the scaffolding columns and the columns
marked :group: identity below into an instrument_identity identity;
member (see the ores.trading.instrument_identity field-group model),
the implicit audit columns fold into an ores::dq::domain::audit_record
audit; member (see the ores.dq.audit_record field-group model), and
issue_id stays flat in between, the vanilla_swap_instrument shape
probed for this entity in wave 1.2. The SQL schema, DB entity and
column lists are unaffected. The entity templates consume these
annotations; domain and repository profiles regenerate correctly.
7.1. Flags
7.2. Repository
7.3. Domain includes
#include <string> #include <boost/uuid/uuid.hpp> #include "ores.utility/decimal/decimal.hpp"
7.4. Conventions
7.5. Table display
| column | header |
|---|---|
| identity.trade_id | ID |
| identity.trade_type_code | Type |
| issue_id | Issue ID |
| identity.version | Version |
| audit.recorded_at | Recorded At |
7.6. Custom repository methods
7.7. Write observation
The trade's economic digest observes every write of this component. The observer's specialisation must be visible where the repository writes, so the repository includes it.
#include "ores.trading.core/repository/trade_write_observation.hpp"
8. See also
- ores.trading — component group overview.