ORE Trading Instrument Support — Complete Implementation
Table of Contents
- Overview
- Motivation
- Gaps to Close
- What Already Exists (Do Not Re-Implement)
- PR Organisation
- Phase 1 — Import Pipeline Wire-Up
- Phase 2 — Credit Instrument Mapper
- Phase 3 — Bond Instrument Extensions (BondOption, BondTRS)
- Phase 4 — Equity Instrument Mapper (Vanilla)
- Phase 5 — Equity Instrument Mapper (Exotic Extensions)
- Phase 6 — FX Exotic Extensions
- Phase 7 — Commodity Instrument Mapper
- Phase 8 — Composite / TRS Instrument Mapper
- Phase 9 — Scripted Instrument Mapper
- Cross-Cutting Notes
- New Files Summary
- Modified Files Summary
Overview
This plan completes Layer 2 (ores.trading) instrument mapper coverage for all
131 ORE XML instrument types. Layer 1 (ores.ore xsdcpp-generated types) is
100% complete — 131/131 golden roundtrip tests pass with zero field gaps.
All SQL tables, C++ domain types, NATS messaging, service, and handler layers already exist for every instrument type. The work is exclusively in mappers and the import pipeline.
Motivation
Without Layer 2 mappers, instrument economics are never persisted during import.
The trades table receives the trade envelope (external_id, trade_type,
netting_set_id) but all product-specific data — leg rates, notionals,
barriers, underlyings — is silently discarded. Grid job valuation reconstructs
ORE XML from the relational model; missing fields produce wrong valuations with
no error signal.
Gaps to Close
- Gap 1 — Import pipeline:
trade_import_itemcarries no instrument data.import_portfolio_with_context()never calls any instrument mapper. Nothing is persisted during import — not even for the three already-complete mappers (swap, FX, bond). - Gap 2 — Missing mappers: credit, equity, commodity, composite/TRS, and scripted families. Also FX barrier/exotic extensions and bond option/TRS extensions.
- Gap 3 — Missing Thing 3 tests: mapper fidelity (forward + reverse) tests for all new mapper families.
What Already Exists (Do Not Re-Implement)
Layer 2 mappers
swap_instrument_mapper— Swap, CrossCurrencySwap, InflationSwap, FRA, CapFloor, Swaption, CallableSwap, FlexiSwap, BalanceGuaranteedSwapfx_instrument_mapper— FxForward, FxSwap, FxOptionbond_instrument_mapper— Bond, ForwardBond, CallableBond, ConvertibleBond
Thing 3 tests
xml_ir_mapper_roundtrip_tests.cpp, xml_swaption_mapper_roundtrip_tests.cpp,
xml_fx_mapper_roundtrip_tests.cpp, xml_bond_mapper_roundtrip_tests.cpp
Infrastructure (all exist with full columns/fields)
All SQL tables, C++ domain types, NATS messaging protocol, service layer, and NATS handlers for: instruments/swap_legs, fx_instruments, bond_instruments, credit_instruments, equity_instruments, commodity_instruments, composite_instruments/composite_legs, scripted_instruments.
PR Organisation
Two phases per PR to maximise throughput. Phase 1 goes alone as every subsequent phase depends on it.
| PR | Phases | Contents |
|---|---|---|
| 1 | 1 | Import pipeline wire-up (foundational) |
| 2 | 2+3 | Credit mapper + Bond option/TRS extension |
| 3 | 4+5 | Equity mapper vanilla + exotic |
| 4 | 6+7 | FX exotic extensions + Commodity mapper |
| 5 | 8+9 | Composite/TRS mapper + Scripted mapper |
Phase 1 — Import Pipeline Wire-Up
Goal
Wire the three existing mappers (swap, FX, bond) into
import_portfolio_with_context() so instruments are persisted during import.
No new mappers are written; this is purely an enabling change.
Key invariant
instrument.id must equal trade.id (same UUID) so the database can join them.
Set this immediately after map_instrument() returns.
Dispatch design: instrument_mapping_result variant
Rather than multiple std::optional fields and a growing if/else chain, the
import pipeline uses a single std::variant field and a unified dispatch method.
Type alias (declared in trade_mapper.hpp, starts with three families;
each subsequent phase adds one arm):
using instrument_mapping_result = std::variant< std::monostate, // unmapped (exotic/scripted/unknown at this phase) swap_mapping_result, fx_mapping_result, bond_mapping_result // Phases 2–9 extend: credit_mapping_result, equity_mapping_result, ... >;
New method on trade_mapper:
static instrument_mapping_result map_instrument(const trade& v);
Implementation delegates to the existing per-family methods — four lines:
instrument_mapping_result trade_mapper::map_instrument(const trade& v) { if (auto r = map_swap_instrument(v)) return *r; if (auto r = map_fx_instrument(v)) return *r; if (auto r = map_bond_instrument(v)) return *r; return std::monostate{}; }
Files to modify
projects/ores.ore/include/ores.ore/domain/trade_mapper.hpp — add the
instrument_mapping_result typedef and map_instrument() declaration.
projects/ores.ore/src/domain/trade_mapper.cpp — implement map_instrument()
as above (three delegating lines).
projects/ores.ore/include/ores.ore/xml/importer.hpp — replace any legacy
optional instrument fields with a single field:
instrument_mapping_result instrument; ///< monostate until resolved
projects/ores.ore/src/xml/importer.cpp — in the trade loop inside
import_portfolio_with_context(), after setting item.trade, one call:
item.instrument = domain::trade_mapper::map_instrument(t); // Patch the instrument id — visitors below need it set before any persist. std::visit(overloaded{ [](std::monostate) {}, [&](auto& r) { r.instrument.id = item.trade.id; } }, item.instrument);
Consumers (services, Qt import dialog) use std::visit with an exhaustive
visitor:
std::visit(overloaded{ [](std::monostate) { /* not yet mapped */ }, [&](swap_mapping_result& r) { /* persist swap instrument + legs */ }, [&](fx_mapping_result& r) { /* persist fx instrument */ }, [&](bond_mapping_result& r) { /* persist bond instrument */ }, }, item.instrument);
Extending for new phases
Each subsequent phase adds exactly two changes:
- Append the new family type to the
instrument_mapping_resultvariant. - Add one line to
map_instrument():if (auto r = map_X_instrument(v)) return *r;.
The importer.hpp and importer.cpp files are not modified again after
Phase 1. std::visit call-sites get a new arm for the new variant member.
Tests
Extend existing xml_trade_import_tests.cpp: load a known swap portfolio file,
assert std::holds_alternative<swap_mapping_result>(item.instrument) and
std::get<swap_mapping_result>(item.instrument).instrument.id = item.trade.id=.
Phase 2 — Credit Instrument Mapper
ORE trade types covered
| ORE file | TradeType |
|---|---|
| Credit_Default_Swap.xml | CreditDefaultSwap |
| Credit_Index_Credit_Default_Swap.xml | IndexCreditDefaultSwap |
| Credit_Index_Credit_Default_Swap_Bespoke_Basket.xml | IndexCreditDefaultSwap |
| Credit_Index_CDS_Option.xml | IndexCreditDefaultSwapOption |
| Credit_CreditLinkedSwap.xml | CreditLinkedSwap |
| Credit_RiskParticipationAgreement_on_Vanilla_Swap.xml | RiskParticipationAgreement |
| Credit_RiskParticipationAgreement_on_CallableSwap.xml | RiskParticipationAgreement |
| Credit_Synthetic_CDO_refdata.xml | SyntheticCDO |
Fields to populate (credit_instrument)
trade_type_code,reference_entity(CreditCurveIdorIssuerId)currency,notional— from firstLegDataspread—FixedLegData.Rates.Rate(running premium)start_date,maturity_date,day_count_code,payment_frequency_codeindex_name,index_series,seniority,restructuring— IndexCDSoption_type,option_expiry_date,option_strike— CDSOptionlinked_asset_code— CreditLinkedSwaptranche_attachment,tranche_detachment— SyntheticCDO
Mapping result struct
struct credit_mapping_result { ores::trading::domain::credit_instrument instrument; };
New files
projects/ores.ore/include/ores.ore/domain/credit_instrument_mapper.hpp projects/ores.ore/src/domain/credit_instrument_mapper.cpp projects/ores.ore/tests/xml_credit_mapper_roundtrip_tests.cpp
Files to modify
trade_mapper.hpp— add include +map_credit_instrument()declaration; appendcredit_mapping_resulttoinstrument_mapping_resultvarianttrade_mapper.cpp— implementmap_credit_instrument()dispatch; addif (auto r = map_credit_instrument(v)) return *r;tomap_instrument()
Thing 3 test cases (tags [ore][xml][mapper][roundtrip][credit])
Credit_Default_Swap.xml— asserttrade_type_code ="CreditDefaultSwap", =reference_entitynon-empty,spread > 0; reverse →CreditDefaultSwapDatapopulatedCredit_Index_Credit_Default_Swap.xml— assertindex_namenon-emptyCredit_Index_CDS_Option.xml— assertoption_expiry_datenon-empty,option_strike.has_value()Credit_Synthetic_CDO_refdata.xml— asserttranche_attachment.has_value()
Phase 3 — Bond Instrument Extensions (BondOption, BondTRS)
Goal
Extend the existing bond_instrument_mapper with two new method pairs. The
bond_instrument table already has option_type, option_expiry_date,
option_strike, trs_return_type, trs_funding_leg_code columns.
ORE trade types covered
| ORE file | TradeType |
|---|---|
| BondOption_StrikePrice_StrikeYield.xml | BondOption |
| Credit_BondOption.xml | BondOption |
| Credit_Bond_TRS.xml | TotalReturnSwap |
| Credit_Bond_TRS_with_Indexings.xml | TotalReturnSwap |
TRS routing rule: if TotalReturnSwapData underlying trade type = =Bond →
bond_instrument_mapper::forward_bond_trs(); all other TRS → Phase 8 composite.
Fields for BondOption
Base bond fields + option_type, option_expiry_date, option_strike
Fields for BondTRS
Base bond fields + trs_return_type, trs_funding_leg_code
Files to modify (extend existing — no new header/impl)
bond_instrument_mapper.hpp— addforward_bond_option,forward_bond_trs, two reverse methodsbond_instrument_mapper.cpp— implement the four methodstrade_mapper.cpp— addBondOptionand bond-underlyingTotalReturnSwapbranches tomap_bond_instrument()
New test file
projects/ores.ore/tests/xml_bond_option_mapper_roundtrip_tests.cpp
Tags [ore][xml][mapper][roundtrip][bond]:
Credit_BondOption.xml— asserttrade_type_code ="BondOption", =option_type ="Call", =option_strike.has_value(); reverse →BondOptionDatapopulatedCredit_Bond_TRS.xml— asserttrade_type_code ="TotalReturnSwap", =trs_funding_leg_codenon-empty
Phase 4 — Equity Instrument Mapper (Vanilla)
ORE trade types covered
| ORE file | TradeType |
|---|---|
| Equity_Option_European.xml | EquityOption |
| Equity_Option_European_ISIN_CCY_MIC.xml | EquityOption |
| Equity_Forward.xml | EquityForward |
| Equity_Swap.xml | EquitySwap |
| Equity_Swap_Indexed_Funding_Leg.xml | EquitySwap |
| Equity_Variance_Swap.xml | EquityVarianceSwap |
| Equity_Barrier_Option.xml | EquityBarrierOption |
| Equity_Double_Barrier_Option.xml | EquityBarrierOption |
| Equity_European_Barrier_Option.xml | EquityBarrierOption |
| Equity_Asian_Option.xml | EquityAsianOption |
| Equity_Digital_Option.xml | EquityDigitalOption |
| Equity_OneTouch_Option.xml | EquityTouchOption |
| Equity_OutperformanceOption.xml | EquityOutperformanceOption |
Fields to populate (equity_instrument)
- Common:
trade_type_code,underlying_code,currency,notional,quantity,start_date,maturity_date - Options:
option_type,strike_price,exercise_type - Barriers:
barrier_type,lower_barrier,upper_barrier - Asian:
average_type,averaging_start_date - Variance:
variance_strike - Swaps:
return_type,day_count_code,payment_frequency_code - Outperformance:
basket_json(two underlyings as JSON array)
Mapping result struct
struct equity_mapping_result { ores::trading::domain::equity_instrument instrument; };
New files
projects/ores.ore/include/ores.ore/domain/equity_instrument_mapper.hpp projects/ores.ore/src/domain/equity_instrument_mapper.cpp projects/ores.ore/tests/xml_equity_mapper_roundtrip_tests.cpp
Files to modify
trade_mapper.hpp— add include +map_equity_instrument()declaration; appendequity_mapping_resulttoinstrument_mapping_resultvarianttrade_mapper.cpp— implementmap_equity_instrument()dispatch; addif (auto r = map_equity_instrument(v)) return *r;tomap_instrument()
Thing 3 test cases (tags [ore][xml][mapper][roundtrip][equity])
Equity_Option_European.xml— assertunderlying_codenon-empty,option_type ="Call", =strike_price > 0; reverse →EquityOptionDatapopulatedEquity_Forward.xml— asserttrade_type_code ="EquityForward"=Equity_Swap.xml— assertreturn_typenon-emptyEquity_Barrier_Option.xml— assertbarrier_typenon-emptyEquity_Asian_Option.xml— assertaverage_typenon-emptyEquity_Variance_Swap.xml— assertvariance_strike > 0Equity_OutperformanceOption.xml— assertbasket_jsonparses to array of size 2
Phase 5 — Equity Instrument Mapper (Exotic Extensions)
Goal
Extend equity_instrument_mapper with four exotic types using
accumulation_amount, cliquet_frequency_code, and basket_json.
ORE trade types covered
| ORE file | TradeType |
|---|---|
| Exotic_EquityAccumulator_single_name.xml | EquityAccumulator |
| Exotic_EquityTaRF.xml | EquityTaRF |
| Exotic_Equity_Cliquet_Option.xml | EquityCliquetOption |
| Exotic_EquityWorstOfBasketSwap.xml | EquityWorstOfBasketSwap |
Fields
- Accumulator/TaRF:
accumulation_amount,knock_out_barrier,option_type,strike_price - Cliquet:
cliquet_frequency_code,option_type,lower_barrier,upper_barrier - Worst-of basket:
basket_json(JSON array of underlyings)
Files to modify (extend existing — no new header/impl)
equity_instrument_mapper.hpp— add 4 forward + 4 reverse method pairsequity_instrument_mapper.cpp— implementtrade_mapper.cpp— add 4 new dispatch branches
New test cases (appended to xml_equity_mapper_roundtrip_tests.cpp)
Exotic_EquityAccumulator_single_name.xml— assertaccumulation_amount > 0,knock_out_barrier > 0Exotic_EquityTaRF.xml— assertaccumulation_amount > 0Exotic_Equity_Cliquet_Option.xml— assertcliquet_frequency_codenon-emptyExotic_EquityWorstOfBasketSwap.xml— assertbasket_jsonparses to valid array
Phase 6 — FX Exotic Extensions
Goal
Extend fx_instrument_mapper with barrier/exotic FX trade types. The
fx_instrument table already has barrier_type, lower_barrier,
upper_barrier columns.
ORE trade types covered
| ORE file | TradeType |
|---|---|
| FX_Barrier_Option.xml | FxBarrierOption |
| FX_FxEuropeanBarrierOption.xml | FxBarrierOption |
| FX_DoubleBarrierOption.xml | FxBarrierOption |
| FX_KIKO_Barrier_Option.xml | FxBarrierOption |
| FX_Digital_Option.xml | FxDigitalOption |
| FX_Digital_Barrier_Option.xml | FxDigitalOption |
| FX_OneTouch_option.xml | FxTouchOption |
| FX_DoubleTouch_Option.xml | FxTouchOption |
| FX_NoTouch_option.xml | FxTouchOption |
| FX_Variance_Swap.xml | FxVarianceSwap |
| Exotic_FxAccumulator.xml | FxAccumulator |
| Exotic_FxTaRF.xml | FxTaRF |
| Exotic_FxGenericBarrierOption.xml | FxGenericBarrierOption |
| FX_Average_Forward.xml | FxAverageForward |
| Exotic_FXWorstOfBasketSwap.xml | FxWorstOfBasketSwap |
Note: confirm fx_instrument domain type has barrier_type, lower_barrier,
upper_barrier fields before implementing; add them if missing.
Files to modify (extend existing — no new header/impl)
fx_instrument_mapper.hpp— add ~10 new forward/reverse method pairsfx_instrument_mapper.cpp— implementtrade_mapper.cpp— extendmap_fx_instrument()with all new type branches
New test file
projects/ores.ore/tests/xml_fx_exotic_mapper_roundtrip_tests.cpp
Tags [ore][xml][mapper][roundtrip][fx][exotic]:
FX_Barrier_Option.xml— assertbarrier_typenon-empty,bought_currencynon-empty; reverse →FxBarrierOptionDatapopulatedFX_Digital_Option.xml— asserttrade_type_code ="FxDigitalOption"=FX_OneTouch_option.xml— asserttrade_type_code ="FxTouchOption"=FX_Variance_Swap.xml— asserttrade_type_code ="FxVarianceSwap"=
Phase 7 — Commodity Instrument Mapper
ORE trade types covered
| ORE file | TradeType |
|---|---|
| Commodity_Forward.xml | CommodityForward |
| Commodity_Option.xml | CommodityOption |
| Commodity_Option_Strip_NYMEX_NG.xml | CommodityOptionStrip |
| Commodity_APO_NYMEX_CL.xml | CommodityAveragePriceOption |
| Commodity_APO_Strip_NYMEX_CSX.xml | CommodityAveragePriceOption |
| Commodity_Variance_Swap.xml | CommodityVarianceSwap |
| Commodity_Swaption_NYMEX_NG.xml | CommoditySwaption |
| Commodity_Swap_NYMEX_A7Q.xml | CommoditySwap |
| Commodity_Swap_LME_AL_AVG_ALT.xml | CommoditySwap |
| Commodity_Basis_Swap_NYMEX_CL.xml | CommoditySpreadOption |
Fields to populate (commodity_instrument)
- Common:
trade_type_code,commodity_code,currency,quantity,unit,start_date,maturity_date - Forward:
fixed_price - Option:
option_type,exercise_type,strike_price - Option strip:
strip_frequency_code - APO:
average_type,averaging_start_date,averaging_end_date - Variance:
variance_strike - Swaption:
swaption_expiry_date - Swap:
day_count_code,payment_frequency_code
Mapping result struct
struct commodity_mapping_result { ores::trading::domain::commodity_instrument instrument; };
New files
projects/ores.ore/include/ores.ore/domain/commodity_instrument_mapper.hpp projects/ores.ore/src/domain/commodity_instrument_mapper.cpp projects/ores.ore/tests/xml_commodity_mapper_roundtrip_tests.cpp
Files to modify
trade_mapper.hpp— add include +map_commodity_instrument()declaration; appendcommodity_mapping_resulttoinstrument_mapping_resultvarianttrade_mapper.cpp— implementmap_commodity_instrument()dispatch; addif (auto r = map_commodity_instrument(v)) return *r;tomap_instrument()
Thing 3 test cases (tags [ore][xml][mapper][roundtrip][commodity])
Commodity_Forward.xml— assertcommodity_codenon-empty,fixed_price.has_value(); reverse →CommodityForwardDatapopulatedCommodity_Option.xml— assertoption_typenon-empty,strike_price.has_value()Commodity_APO_NYMEX_CL.xml— assertaverage_typenon-empty,averaging_start_datenon-emptyCommodity_Variance_Swap.xml— assertvariance_strike.has_value()Commodity_Swaption_NYMEX_NG.xml— assertswaption_expiry_datenon-empty
Phase 8 — Composite / TRS Instrument Mapper
Goal
Implement composite_instrument_mapper for CompositeTrade, TotalReturnSwap
with non-bond underlyings, and ContractForDifference. Constituent trade IDs
are stored in composite_leg records.
ORE trade types covered
| ORE file | TradeType |
|---|---|
| Hybrid_CompositeTrade.xml | CompositeTrade |
| Hybrid_CFD.xml | ContractForDifference |
| Hybrid_GenericTRS_with_BondPosition.xml | TotalReturnSwap |
| Hybrid_GenericTRS_with_ConvertibleBond.xml | TotalReturnSwap |
| Hybrid_GenericTRS_with_BondForward_Futures.xml | TotalReturnSwap |
| Hybrid_GenericTRS_with_Derivative.xml | TotalReturnSwap |
| Hybrid_GenericTRS_with_EquityPosition.xml | TotalReturnSwap |
| Hybrid_GenericTRS_with_EquityOptionPosition.xml | TotalReturnSwap |
| Hybrid_GenericTRS_with_MixedBasket.xml | TotalReturnSwap |
| Hybrid_GenericTRS_with_PortfolioIndexTradeData.xml | TotalReturnSwap |
Note: Hybrid_GenericTRS_with_Bond.xml and pure bond TRS go through Phase 3
(bond_instrument_mapper::forward_bond_trs()). TRS routing in
map_composite_instrument(): if underlying is a single Bond trade →
delegate to map_bond_instrument(); otherwise dispatch here.
Fields to populate
composite_instrument: trade_type_code, description (empty), audit fields.
composite_leg (one per constituent): instrument_id, leg_sequence (1-based),
constituent_trade_id — component's ORE id string; if anonymous inline
component, store the component TradeType string as fallback.
Mapping result struct
struct composite_mapping_result { ores::trading::domain::composite_instrument instrument; std::vector<ores::trading::domain::composite_leg> legs; };
New files
projects/ores.ore/include/ores.ore/domain/composite_instrument_mapper.hpp projects/ores.ore/src/domain/composite_instrument_mapper.cpp projects/ores.ore/tests/xml_hybrid_mapper_roundtrip_tests.cpp
Files to modify
trade_mapper.hpp— add include +map_composite_instrument()declaration; appendcomposite_mapping_resulttoinstrument_mapping_resultvarianttrade_mapper.cpp— implementmap_composite_instrument()dispatch (with TRS routing logic); addif (auto r = map_composite_instrument(v)) return *r;tomap_instrument()
Thing 3 test cases (tags [ore][xml][mapper][roundtrip][hybrid])
Hybrid_CompositeTrade.xml— asserttrade_type_code ="CompositeTrade", =legs.size() =2=,legs[0].leg_sequence =1=; reverse →CompositeTradeDatahas 2 componentsHybrid_GenericTRS_with_EquityPosition.xml— asserttrade_type_code ="TotalReturnSwap", =legs.size() >1=Hybrid_CFD.xml— asserttrade_type_code ="ContractForDifference"=
Phase 9 — Scripted Instrument Mapper
Goal
Implement scripted_instrument_mapper for all ScriptedTrade variants and
named script product types. The domain stores script_name, events_json,
underlyings_json, and parameters_json as opaque JSON to avoid modelling
every script's schema.
ORE trade types covered
| ORE file | TradeType/ScriptName |
|---|---|
| Scripted_BasketOption.xml | ScriptedTrade/AsianBasketOption |
| Scripted_BasketOption2.xml | ScriptedTrade/AverageStrikeBasketOption |
| Scripted_BasketOption3.xml | ScriptedTrade/LookbackCallBasketOption |
| Scripted_FlooredAverageCPIZCYYIIS.xml | ScriptedTrade |
| Scripted_IrregularYYIIS.xml | ScriptedTrade |
| Scripted_MovingMaximumYYIIS.xml | ScriptedTrade |
| Exotic_Double_Digital_Option.xml | DoubleDigitalOption |
| Exotic_PerformanceOption_01_FX.xml | PerformanceOption_01 |
| Exotic_PerformanceOption_01_COM.xml | PerformanceOption_01 |
| Exotic_RainbowOption.xml | BestOfAssetOrCashRainbowOption |
| Exotic_KnockOutSwap.xml | KnockOutSwap |
| Exotic_Formula_Based_Coupon.xml | FormulaBasedCoupon |
Mapping strategy
ORE scripted trades have two representations:
- Named sugar syntax (e.g.
AsianBasketOptionData) — inferscript_namefrom the element tag (stripDatasuffix). - Explicit
ScriptedTradeData— readScriptNamedirectly.
Serialise events as events_json ([{"name":"Expiry","value":"2025-08-31"}]),
underlyings as underlyings_json (["EQ-RIC:.SPX","EQ-RIC:.STOXX50E"]), and
parameters as parameters_json ({"Strike":5000.0,"Notional":1.0}). Use
nlohmann/json (already in vcpkg).
Fields to populate (scripted_instrument)
trade_type_code,script_name,script_body(if inline; empty if library)events_json,underlyings_json,parameters_json- Standard audit fields
Mapping result struct
struct scripted_mapping_result { ores::trading::domain::scripted_instrument instrument; };
New files
projects/ores.ore/include/ores.ore/domain/scripted_instrument_mapper.hpp projects/ores.ore/src/domain/scripted_instrument_mapper.cpp projects/ores.ore/tests/xml_scripted_mapper_roundtrip_tests.cpp
Files to modify
trade_mapper.hpp— add include +map_scripted_instrument()declaration; appendscripted_mapping_resulttoinstrument_mapping_resultvarianttrade_mapper.cpp— implementmap_scripted_instrument()(allScriptedTradevariants →forward_scripted_trade();DoubleDigitalOption,PerformanceOption_01→forward_named_scripted_trade()); addif (auto r = map_scripted_instrument(v)) return *r;tomap_instrument()
Thing 3 test cases (tags [ore][xml][mapper][roundtrip][scripted])
Scripted_BasketOption.xml— assertscript_name ="AsianBasketOption", =underlyings_jsonparses to array of size 2,events_jsonnon-empty; reverse →AsianBasketOptionDataorScriptedTradeDatapopulatedExotic_Double_Digital_Option.xml— asserttrade_type_code ="DoubleDigitalOption", =underlyings_jsonnon-emptyExotic_PerformanceOption_01_FX.xml— assertscript_name ="PerformanceOption_01"=
Cross-Cutting Notes
CMakeLists — no changes needed
Both ores.ore/src/CMakeLists.txt and ores.ore/tests/CMakeLists.txt use
file(GLOB_RECURSE ...). New .cpp files are picked up automatically.
Audit fields boilerplate
Every mapper .cpp should have a make_base() helper setting
modified_by = "ores", performed_by = "ores",
change_reason_code = "system.external_data_import",
change_commentary = "Imported from ORE XML". Copy from fx_instrument_mapper.cpp.
JSON serialisation
Use nlohmann/json for basket_json, events_json, underlyings_json,
parameters_json. Keep serialisation in a private helper in the .cpp only.
Commit message format
[ores.ore] Add <asset class> instrument mapper and Thing 3 tests
New Files Summary
| Phase | File |
|---|---|
| 2 | projects/ores.ore/include/ores.ore/domain/credit_instrument_mapper.hpp |
| 2 | projects/ores.ore/src/domain/credit_instrument_mapper.cpp |
| 2 | projects/ores.ore/tests/xml_credit_mapper_roundtrip_tests.cpp |
| 3 | projects/ores.ore/tests/xml_bond_option_mapper_roundtrip_tests.cpp |
| 4–5 | projects/ores.ore/include/ores.ore/domain/equity_instrument_mapper.hpp |
| 4–5 | projects/ores.ore/src/domain/equity_instrument_mapper.cpp |
| 4–5 | projects/ores.ore/tests/xml_equity_mapper_roundtrip_tests.cpp |
| 6 | projects/ores.ore/tests/xml_fx_exotic_mapper_roundtrip_tests.cpp |
| 7 | projects/ores.ore/include/ores.ore/domain/commodity_instrument_mapper.hpp |
| 7 | projects/ores.ore/src/domain/commodity_instrument_mapper.cpp |
| 7 | projects/ores.ore/tests/xml_commodity_mapper_roundtrip_tests.cpp |
| 8 | projects/ores.ore/include/ores.ore/domain/composite_instrument_mapper.hpp |
| 8 | projects/ores.ore/src/domain/composite_instrument_mapper.cpp |
| 8 | projects/ores.ore/tests/xml_hybrid_mapper_roundtrip_tests.cpp |
| 9 | projects/ores.ore/include/ores.ore/domain/scripted_instrument_mapper.hpp |
| 9 | projects/ores.ore/src/domain/scripted_instrument_mapper.cpp |
| 9 | projects/ores.ore/tests/xml_scripted_mapper_roundtrip_tests.cpp |
Modified Files Summary
| Phases | File | Change |
|---|---|---|
| 1 | projects/ores.ore/include/ores.ore/domain/trade_mapper.hpp |
Add instrument_mapping_result variant + map_instrument() |
| 1 | projects/ores.ore/src/domain/trade_mapper.cpp |
Implement map_instrument() (3-line delegate) |
| 1 | projects/ores.ore/include/ores.ore/xml/importer.hpp |
Replace per-family optionals with single instrument field |
| 1 | projects/ores.ore/src/xml/importer.cpp |
Single map_instrument() call + visit for id patching |
| 2,4,7–9 | projects/ores.ore/include/ores.ore/domain/trade_mapper.hpp |
Add new family to variant; add map_X_instrument() decl |
| 2,4,7–9 | projects/ores.ore/src/domain/trade_mapper.cpp |
Add one line to map_instrument() per new family |
| 3 | projects/ores.ore/include/ores.ore/domain/bond_instrument_mapper.hpp |
Add BondOption/BondTRS methods |
| 3 | projects/ores.ore/src/domain/bond_instrument_mapper.cpp |
Implement BondOption/BondTRS |
| 5 | projects/ores.ore/include/ores.ore/domain/equity_instrument_mapper.hpp |
Add exotic method pairs |
| 5 | projects/ores.ore/src/domain/equity_instrument_mapper.cpp |
Implement exotic methods |
| 6 | projects/ores.ore/include/ores.ore/domain/fx_instrument_mapper.hpp |
Add exotic method pairs |
| 6 | projects/ores.ore/src/domain/fx_instrument_mapper.cpp |
Implement exotic methods |