Task: Resolve ORE portfolio ids to portfolios
Table of Contents
This page documents a task in the Split the trade into an anchor and its components story. It captures the goal, current status, acceptance, and any notes or results.
1. Goal
An ORE import records each PortfolioId as a portfolio of the trade's party and rejects one that names no portfolio; the export regenerates PortfolioIds from those rows; the envelope tables are no longer written.
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Split the trade into an anchor and its components |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-10-04 |
3. Acceptance
- trade_portfolio (trade, ordinal, portfolio) references the anchor and a portfolio of the trade's party.
- The ORE sample portfolios PF1 and PF2 are published to Acme Corporation Plc through DQ.
- The import resolves PortfolioIds by name and writes no envelope rows; the export regenerates them; a portfolio with PortfolioIds round trips with no in-scope loss.
- Build, ctest, pgTAP and the local check set pass.
4. Plan
An ORE PortfolioId is a portfolio's name, and a portfolio's natural key is its party and name, so the import resolves each id by name among the importing party's portfolios and rejects a trade whose id names none, as it does a counterparty or netting set that resolves to none.
trade_portfolio(trade, ordinal, portfolio) is a trade component keyed by the anchor with a database foreign key, its party pinned to the anchor and to the portfolio, so a trade is reported only in its own party's portfolios.- The ORE sample portfolios PF1 and PF2 are the dataset
ore.sample_portfolioswith its own methodology, published by the artefact typenamed_portfolios. It reuses the portfolio staging table, but its publish adds top-level portfolios by name to a party that already has portfolios, which the portfolio tree publish refuses to do. The bundleore_sample_nettingbecomesore_samplesand carries it. - The import resolves PortfolioIds before it books, writes
trade_portfoliorows after, and writes no envelope rows at all. - The export reads a booked trade's PortfolioIds through
ores_trading_trade_portfolio_names_fn, which runs as the owner for the same reason as the envelope names function.
5. Measurements
Every number this task claims about a tree, with the command that produced it
and the commit it was measured at. A number without both is not a measurement,
because a clean-up record describes a tree and trunk moves under a branch: a
consumer count, a gate's component count and a suite's size all change with no
code changing, and the reader of a bare number cannot tell which tree it came
from. Where the raw output matters, put it in an evidence/ file beside the
task and name that file in the Command column.
| What | Value | Command | Commit |
|---|---|---|---|
| Round trip with PortfolioIds, in-scope pairs | lost 0, unexplained 0; 13 of 13 envelopes as stated | reset_and_roundtrip.sh, in evidence/ore_portfolio_ids.txt |
branch head before commit |
| Unknown PortfolioId | the trade is rejected with one reason | the same evidence file | branch head before commit |
| ctest suites | 90/90 pass | compass test run --preset linux-clang-debug-make |
branch head before commit |
| pgTAP envelope names cases | 11/11 pass | pg_prove projects/ores.sql/test/trading_trade_envelope_names_test.sql |
branch head before commit |
6. Notes
- Seen, not changed: the instrument step refuses Example_39's composite with "Invalid modified_by: ores" from the composite leg insert, and the swaption, commodity and CDS instruments on their tenor, unit and leg checks. The instrument step is out of this task's scope.
- After this task the ORE import writes nothing to the envelope tables; only trades with no anchor still read them.
7. Test Scenarios
Manual QA scenarios (scaffolded via compass add test_scenario)
that verify this task. Link
new ones here as they're created; the scenario doc itself links back
via its "Verifies task" field.
| Scenario | State | Notes |
|---|---|---|
8. PRs
| PR | Title |
|---|---|
| #2610 | [trading] Resolve ORE portfolio ids to portfolios |
9. Review
| # | Comment summary | File | Decision | Notes |
|---|---|---|---|---|
| 1 | The portfolio tree publish skips a party that already has portfolios, so it cannot add PF1 and PF2 to ACME. | refdata_publish_from_dq_create.sql | Accept | A named portfolio publish over the same staging table. |
| 2 | PR 2610 review 1: the security definer names functions filter only by tenant. | trading_trade_components_functions_create.sql | Accept | Both now hold rows to the caller's visible parties too; pgTAP case 11. |
| 3 | PR 2610 review 2: is the portfolio lookup scoped and deterministic? | ore_import_execute_handler.cpp | Decline | A portfolio's party and name are its natural key; the read runs under the caller's party visibility and the pin refuses another party's portfolio. |
| 4 | PR 2610 review 3: a failed portfolio row leaves a partial list on a booked trade. | ore_import_execute_handler.cpp | Decline | As before for the envelope; recorded on the import task. |
| 5 | PR 2610 review 4: the skipped count covers held and duplicate names. | refdata_publish_from_dq_create.sql | Decline | The count is correct. |
| 6 | PR 2610 review 5: include order; a redundant generated trigger check. | ore_import_execute_handler.cpp | Accept / Decline | Include moved; the check is generated. |
10. Result
ORE's Envelope/PortfolioIds now resolve to portfolios. An ORE import records
each id as a trade_portfolio row pointing at a portfolio of the importing
party, and rejects a trade whose id names none; the export regenerates the ids
in order. The ORE sample portfolios PF1 and PF2 reach Acme Corporation Plc
through the ore_samples bundle. The import no longer writes the envelope
tables, and a portfolio with PortfolioIds round trips with no in-scope loss.