ores.reporting.risk_report_config
Table of Contents
- 1. Flags
- 2. Columns
- 2.1. id
- 2.2. report_definition_id
- 2.3. base_currency
- 2.4. observation_model
- 2.5. n_threads
- 2.6. market_data_type
- 2.7. market_data_date
- 2.8. npv_enabled
- 2.9. cashflow_enabled
- 2.10. curves_enabled
- 2.11. sensitivity_enabled
- 2.12. simulation_enabled
- 2.13. xva_enabled
- 2.14. stress_enabled
- 2.15. parametric_var_enabled
- 2.16. initial_margin_enabled
- 2.17. pfe_enabled
- 2.18. xva_quantile
- 2.19. xva_cva_enabled
- 2.20. xva_dva_enabled
- 2.21. xva_fva_enabled
- 2.22. xva_colva_enabled
- 2.23. xva_dim_enabled
- 2.24. xva_dim_quantile
- 2.25. xva_dim_horizon_calendar_days
- 2.26. xva_dim_regression_order
- 2.27. var_quantiles
- 2.28. var_method
- 2.29. simm_version
- 2.30. simm_calculation_currency
- 3. SQL
- 4. Foreign keys
- 5. Insert trigger
- 6. C++
- 7. Physical space
- 8. See also
The ORE-level parameters for a risk report definition: base currency, observation model, analytics flags, XVA/VaR/SIMM settings and threading.
Each row is owned by exactly one report_definition (1:1, enforced by the
unique index on report_definition_id). Portfolio and book scope live in
separate temporal junction tables; an empty set in either junction means
"all visible to the tenant".
Analytics flags use integer 0/1, not boolean, to match the project
convention. npv and cashflow default to enabled; all others default off.
1. Flags
2. Columns
2.1. id
UUID uniquely identifying this configuration.
2.2. report_definition_id
The report definition this configuration belongs to. Unique per tenant on active records, so a definition has at most one live configuration.
ctx.generate_uuid()
2.3. base_currency
Reporting base currency (ISO 4217 code) that all results are converted to.
std::string(faker::finance::currencyCode())
2.4. observation_model
How the engine handles absent market data: disable, none, move or
defer.
std::string("disable")
2.5. n_threads
Number of worker threads the risk engine may use.
faker::number::integer(1, 8)
2.6. market_data_type
Market data convention: live, eod or date.
std::string("eod")
2.7. market_data_date
As-of date (ISO 8601) used when market_data_type is date. An empty string
is the not-set sentinel: the mapper writes NULL for it, which is what the
CHECK requires while market_data_type stays eod.
std::string("")
2.8. npv_enabled
Enables the NPV analytic.
faker::number::integer(0, 1)
2.9. cashflow_enabled
Enables the cashflow analytic.
faker::number::integer(0, 1)
2.10. curves_enabled
Enables curve analytic output.
faker::number::integer(0, 1)
2.11. sensitivity_enabled
Enables sensitivity analytic output.
faker::number::integer(0, 1)
2.12. simulation_enabled
Enables Monte Carlo simulation output.
faker::number::integer(0, 1)
2.13. xva_enabled
Enables XVA analytics. Gates the xva_* settings below.
faker::number::integer(0, 1)
2.14. stress_enabled
Enables stress test analytics.
faker::number::integer(0, 1)
2.15. parametric_var_enabled
Enables parametric VaR. Gates the var_* settings below.
faker::number::integer(0, 1)
2.16. initial_margin_enabled
Enables initial margin (SIMM) calculation. Gates the simm_* settings.
faker::number::integer(0, 1)
2.17. pfe_enabled
Enables potential future exposure output.
faker::number::integer(0, 1)
2.18. xva_quantile
XVA confidence quantile. NULL means "not set".
faker::number::decimal(0.9, 0.99)
2.19. xva_cva_enabled
Enables the CVA adjustment within XVA.
faker::number::integer(0, 1)
2.20. xva_dva_enabled
Enables the DVA adjustment within XVA.
faker::number::integer(0, 1)
2.21. xva_fva_enabled
Enables the FVA adjustment within XVA.
faker::number::integer(0, 1)
2.22. xva_colva_enabled
Enables the ColVA adjustment within XVA.
faker::number::integer(0, 1)
2.23. xva_dim_enabled
Enables the DIM (dynamic initial margin) calculation within XVA.
faker::number::integer(0, 1)
2.24. xva_dim_quantile
DIM confidence quantile. NULL means "not set".
faker::number::decimal(0.9, 0.99)
2.25. xva_dim_horizon_calendar_days
DIM horizon in calendar days. NULL means "not set".
faker::number::integer(1, 30)
2.26. xva_dim_regression_order
Regression order for the DIM backtest, 1 to 3. NULL means "not set".
faker::number::integer(1, 3)
2.27. var_quantiles
Confidence quantiles for the parametric VaR grid. NULL means "not set".
The column stays in the schema but reaches no C++ layer. sqlgen cannot bind a
Postgres array, so no entity member can carry it, and a member the mapper
cannot persist is worse than no member at all. The field is currently unwired:
nothing reads or writes it, in this model or in the hand-written code this
model replaces. Remove :sql_only: and regenerate once sqlgen, or a
replacement, can bind numeric[].
2.28. var_method
Parametric VaR method: delta, delta_gamma_normal or monte_carlo.
NULL means "not set".
std::string("delta")
2.29. simm_version
SIMM methodology version. NULL means "not set".
std::string("2.6")
2.30. simm_calculation_currency
Currency the SIMM amount is expressed in. NULL means "not set".
std::string(faker::finance::currencyCode())
3. SQL
3.1. Flags
3.2. Checks
Domain constraints beyond the standard temporal, natural-key and nil-uuid checks the template emits on its own.
| expression |
|---|
| "base_currency" <> '' |
| "observation_model" in ('disable', 'none', 'move', 'defer') |
| "n_threads" >= 1 |
| "market_data_type" in ('live', 'eod', 'date') |
| (market_data_type = 'date') = (market_data_date is not null) |
| "npv_enabled" in (0, 1) |
| "cashflow_enabled" in (0, 1) |
| "curves_enabled" in (0, 1) |
| "sensitivity_enabled" in (0, 1) |
| "simulation_enabled" in (0, 1) |
| "xva_enabled" in (0, 1) |
| "stress_enabled" in (0, 1) |
| "parametric_var_enabled" in (0, 1) |
| "initial_margin_enabled" in (0, 1) |
| "pfe_enabled" in (0, 1) |
| "xva_cva_enabled" in (0, 1) |
| "xva_dva_enabled" in (0, 1) |
| "xva_fva_enabled" in (0, 1) |
| "xva_colva_enabled" in (0, 1) |
| "xva_dim_enabled" in (0, 1) |
| "xva_dim_regression_order" is null or "xva_dim_regression_order" between 1 and 3 |
| "var_method" is null or "var_method" in ('delta', 'delta_gamma_normal', 'monte_carlo') |
4. Foreign keys
4.1. report_definition_id
5. Insert trigger
5.1. Validations
| column | validation_function |
6. C++
6.1. Flags
6.2. Repository
6.3. Domain includes
#include <boost/uuid/uuid.hpp> #include <chrono> #include <optional> #include <string>
6.4. Entity includes
#include <optional> #include <ostream> #include <string> #include "sqlgen/Timestamp.hpp" #include <boost/uuid/uuid.hpp>
6.5. Conventions
6.6. Table display
| column | header |
|---|---|
| report_definition_id | Definition |
| base_currency | Base Currency |
| observation_model | Observation Model |
| market_data_type | Market Data |
| npv_enabled | NPV |
| cashflow_enabled | Cashflow |
| xva_enabled | XVA |
| parametric_var_enabled | Parametric VaR |
| initial_margin_enabled | Initial Margin |
| modified_by | Modified By |
| version | Version |
6.7. Paste blocks
6.7.1. Additional class-member declarations
- find_by_definition_id
Reads the current configuration for a report definition. The execution handler needs the config before any CRUD surface exists for it, and the lookup keys on the natural key rather than on
get.std::optional<domain::risk_report_config> find_by_definition_id(context ctx, const std::string& definition_id);
- resolve_book_ids
Resolves the full set of book UUIDs in scope by calling
ores_reporting_resolve_book_ids_for_config_fn, which checks explicit book scope, then portfolio scope with subtree expansion, then falls back to all tenant books. The fallback chain lives in SQL, so it cannot be templated.std::vector<std::string> resolve_book_ids(context ctx, const std::string& config_id);
- get_book_scope
Returns the active book UUIDs explicitly scoped to a configuration. An empty vector means "all books within the selected portfolios".
std::vector<std::string> get_book_scope(context ctx, const std::string& config_id);
- get_portfolio_scope
Returns the active portfolio UUIDs explicitly scoped to a configuration. An empty vector means "all portfolios visible to the tenant".
std::vector<std::string> get_portfolio_scope(context ctx, const std::string& config_id);
6.7.2. Additional out-of-class implementations
- scope_entities
Lightweight row types for the two scope junction tables. Only the columns scope resolution needs are declared; the junction tables have no org model of their own.
Must precede the methods that use them: paste blocks concatenate in sub-heading order.
namespace { struct book_scope_entity { constexpr static const char* schema = "public"; constexpr static const char* tablename = "ores_reporting_risk_report_config_books_tbl"; std::string tenant_id; std::string risk_report_config_id; std::string book_id; std::optional<db_timestamp> valid_from = "9999-12-31 23:59:59"; std::optional<db_timestamp> valid_to = "9999-12-31 23:59:59"; }; struct portfolio_scope_entity { constexpr static const char* schema = "public"; constexpr static const char* tablename = "ores_reporting_risk_report_config_portfolios_tbl"; std::string tenant_id; std::string risk_report_config_id; std::string portfolio_id; std::optional<db_timestamp> valid_from = "9999-12-31 23:59:59"; std::optional<db_timestamp> valid_to = "9999-12-31 23:59:59"; }; }
- find_by_definition_id
std::optional<domain::risk_report_config> risk_report_config_repository::find_by_definition_id(context ctx, const std::string& definition_id) { BOOST_LOG_SEV(lg(), debug) << "Finding risk_report_config by definition_id: " << definition_id; static auto max(make_timestamp(MAX_TIMESTAMP, lg())); const auto tid = ctx.tenant_id().to_string(); const auto query = sqlgen::read<std::vector<risk_report_config_entity>> | where("tenant_id"_c == tid && "report_definition_id"_c == definition_id && "valid_to"_c == max.value()); auto results = execute_read_query<risk_report_config_entity, domain::risk_report_config>( ctx, query, [](const auto& entities) { return risk_report_config_mapper::map(entities); }, lg(), "Finding risk_report_config by definition_id"); if (results.empty()) return std::nullopt; return results.front(); }
- resolve_book_ids
std::vector<std::string> risk_report_config_repository::resolve_book_ids(context ctx, const std::string& config_id) { BOOST_LOG_SEV(lg(), debug) << "Resolving book IDs for config: " << config_id; const auto tid = ctx.tenant_id().to_string(); const std::string sql = "SELECT id::text FROM " "ores_reporting_resolve_book_ids_for_config_fn($1::uuid, $2::uuid) AS t(id)"; return execute_parameterized_string_query( ctx, sql, {tid, config_id}, lg(), "Resolving book IDs for risk_report_config"); }
- get_book_scope
std::vector<std::string> risk_report_config_repository::get_book_scope(context ctx, const std::string& config_id) { BOOST_LOG_SEV(lg(), debug) << "Reading book scope for config: " << config_id; static auto max(make_timestamp(MAX_TIMESTAMP, lg())); const auto tid = ctx.tenant_id().to_string(); const auto query = sqlgen::read<std::vector<book_scope_entity>> | where("tenant_id"_c == tid && "risk_report_config_id"_c == config_id && "valid_to"_c == max.value()); auto rows = execute_read_query<book_scope_entity, book_scope_entity>( ctx, query, [](const auto& entities) { return entities; }, lg(), "Reading book scope"); std::vector<std::string> book_ids; book_ids.reserve(rows.size()); for (const auto& row : rows) book_ids.push_back(row.book_id); BOOST_LOG_SEV(lg(), debug) << "Found " << book_ids.size() << " book(s) in scope"; return book_ids; }
- get_portfolio_scope
std::vector<std::string> risk_report_config_repository::get_portfolio_scope(context ctx, const std::string& config_id) { BOOST_LOG_SEV(lg(), debug) << "Reading portfolio scope for config: " << config_id; static auto max(make_timestamp(MAX_TIMESTAMP, lg())); const auto tid = ctx.tenant_id().to_string(); const auto query = sqlgen::read<std::vector<portfolio_scope_entity>> | where("tenant_id"_c == tid && "risk_report_config_id"_c == config_id && "valid_to"_c == max.value()); auto rows = execute_read_query<portfolio_scope_entity, portfolio_scope_entity>( ctx, query, [](const auto& entities) { return entities; }, lg(), "Reading portfolio scope"); std::vector<std::string> portfolio_ids; portfolio_ids.reserve(rows.size()); for (const auto& row : rows) portfolio_ids.push_back(row.portfolio_id); BOOST_LOG_SEV(lg(), debug) << "Found " << portfolio_ids.size() << " portfolio(s) in scope"; return portfolio_ids; }
7. Physical space
The messaging, eventing and history surface is deliberately not generated
yet. Nothing writes a risk report config today: the only consumer is
report_execution_handler, which reads one through
find_by_definition_id and never saves. Generating the surface would add a
NATS handler, a sub-registrar, a history provider registrar, an event
registrar and a service that no composition point calls.
ores.reporting/core/src/messaging/registrar.cpp is a hand-written fan-out,
not a per-entity registrar aggregator, so a generated registrar has nowhere
to join. It builds each *_handler directly. Its siblings
report_definition, report_instance, report_type and
concurrency_policy already carry two orphaned families on main: the four
*_registrar classes and the four *_history_provider_registrar classes.
Nothing calls either family. The measurement and the repair are their own
task; this model does not add a fifth orphan.
The *_event_registrar family is composed, so it is not part of the finding.
ores.reporting/service/src/app/application.cpp calls all four
register_*_event_mapping functions.
The data layer — domain, generator, entity, mapper, repository — plus the SQL schema is generated.
| Address | Enabled |
|---|---|
| ores.cpp.service | false |
| ores.cpp.protocol | false |
| ores.cpp.nats-handler | false |
| ores.cpp.nats-sub-registrar | false |
| ores.cpp.nats-event-registrar | false |
| ores.cpp.nats-eventing | false |
| ores.cpp.nats-event-cache | false |
| ores.cpp.history-provider-registrar | false |
| ores.cpp.presentation | false |
| ores.cpp.eventing-integration-test | false |
8. See also
- ores.reporting — component group overview.
- ores.reporting.report_instance — executions of the definition this configures.