Risk Classes

Table of Contents

1. Summary

A risk class is an asset class a product is sensitive to. A product has one asset class and many risk classes, and that difference in cardinality is why the two are separate attributes rather than one.

A fixed-rate bond is one product whose asset class is Bond. Its risk classes are InterestRate and Credit, because its value moves with a discount curve and with an issuer spread. Neither risk class is its asset class, and neither can be derived from it by a rule.

Both attributes draw their values from the same tree. Asset classes sets out that taxonomy. This page is about the second way of referencing it.

2. Why this is a separate attribute

The test is cardinality, and it is decisive.

A product has exactly one asset class, because the asset class says what kind of thing it is. A product has as many risk classes as it has kinds of sensitivity, because each sensitivity is to a different market.

  • A fixed-rate bond: asset class Bond, risk classes InterestRate and Credit.
  • A cross-currency swap: asset class InterestRate, risk classes InterestRate and ForeignExchange.
  • An equity option struck in a foreign currency: asset class Equity, risk classes Equity, InterestRate and ForeignExchange.

One-to-one against one-to-many is a structural difference. A single field cannot hold both, so a model that tries will be wrong for one of them.

Two independent sources corroborate this rather than merely allowing it.

ORE states it in a signature. Trade::underlyingIndices() returns std::map<AssetClass, std::set<std::string>> — a map keyed by class, because one trade reaches into several. A classification that was a property of the trade would have returned a single value.

ISDA SIMM states it by holding both at once. ProductClass and RiskClass are separate enumerations over the same trades in the same framework, and the framework needs both. One that could collapse them would have.

3. The model

3.1. A join between product type and asset class

The risk classes of a product are a set, so they are a join.

risk_class
  product_type   -> trade_type.code
  asset_class    -> asset_class.code

One row per sensitivity kind. A bond product type contributes two rows, one for InterestRate and one for Credit. A vanilla interest rate swap contributes one.

The asset class of the product stays where it is, as a single-valued attribute of the product type. The join adds the second reference without disturbing the first.

3.2. What sits within a class

A risk class names a market, not a particular curve or surface. Within InterestRate sit the individual risk factors: the USD SOFR curve, the EUR ESTR curve, each with its own tenor points. Within Equity sit the individual spot prices and volatility surfaces.

Those individual factors are market data requirements, and the relation between a trade and its requirements is the finer statement of the join described here. A risk class is the asset class a requirement projects onto, so the set of risk classes a trade carries is the projection of its requirement set. Whether the join is held directly or derived from that relation is treated in the open questions below.

Those instances are market data rather than taxonomy, and asset classes records that market data series carry an asset class of their own. A sensitivity therefore resolves through two steps: the risk class says which market, and the risk factor says which series within it.

3.3. Why the values are the same tree

Risk classes are asset classes. They are not a parallel vocabulary, and giving them one would mean maintaining two lists that have to agree.

3.4. ISDA SIMM

SIMM holds three enumerations, and reading all three shows that its apparent extra asset classes are not asset classes at all.

ProductClass carries RatesFX, Credit, Equity and Commodity as its substantive values, with Rates and FX separately for the IM Schedule extension.

RiskClass carries InterestRate, CreditQualifying, CreditNonQualifying, Equity, Commodity and FX.

RiskType is the one that explains the other two. Its SIMM values are Commodity, CommodityVol, CreditNonQ, CreditQ, CreditVol, CreditVolNonQ, Equity, EquityVol, FX, FXVol, Inflation, IRCurve, IRVol and InflationVol, alongside framework mechanics such as BaseCorr, XCcyBasis, Notional and PV.

3.4.1. The values decompose

Those risk types are not fourteen kinds of thing. They are a cross-product of three smaller ideas.

Dimension Values
Asset class Commodity, Credit, Equity, FX, interest rate, inflation
Greek delta, written unsuffixed, and vega, written Vol
Qualifier qualifying or non-qualifying, on credit only

CommodityVol is commodity vega. CreditVolNonQ is credit vega, non-qualifying. Nothing in the list is a market that the asset class taxonomy lacks.

FRTB, whose risk types sit in the same enumeration, drops the implicit spelling and names both segments: GIRR_DELTA, EQ_VEGA, FX_CURV. The greeks sets out the decomposition and the greeks themselves.

So SIMM's CreditQualifying and CreditNonQualifying are not subclasses of credit. They are credit carrying an additional property. Qualifying status describes the reference entity's eligibility under the framework's rules; it does not name a different market, is not observed from different data, and exists only because SIMM assigns the two different risk weights and correlations.

RiskClass is then a flattening of asset class against that qualifier, built for one purpose: its declaration warns that "the ordering here matters. It is used in indexing in to correlation matrices for the correlation between risk classes". It is an index, not a taxonomy.

RatesFX is a grouping for the same reason, because margin is computed on the pair together.

3.4.2. What SIMM says about inflation

The RiskType declaration carries a note: "the risk type inflation has to be treated as an additional, single tenor bucket in IRCurve".

SIMM therefore treats inflation as a point on the interest rate curve rather than as a market beside it. That is the sharpest statement of the inflation question found in any of the surveyed material. Asset classes reads it as a projection SIMM applies when it charges the exposure, not as a parent-child relation in the taxonomy, which holds inflation beside interest rate.

4. Prior art

4.1. ISDA SIMM

SIMM holds three enumerations, and reading all three shows that its apparent extra asset classes are not asset classes at all.

ProductClass carries RatesFX, Credit, Equity and Commodity as its substantive values, with Rates and FX separately for the IM Schedule extension.

RiskClass carries InterestRate, CreditQualifying, CreditNonQualifying, Equity, Commodity and FX.

RiskType is the one that explains the other two. Its SIMM values are Commodity, CommodityVol, CreditNonQ, CreditQ, CreditVol, CreditVolNonQ, Equity, EquityVol, FX, FXVol, Inflation, IRCurve, IRVol and InflationVol, alongside framework mechanics such as BaseCorr, XCcyBasis, Notional and PV.

4.1.1. The values decompose

Those risk types are not fourteen kinds of thing. They are a cross-product of three smaller ideas.

Dimension Values
Asset class Commodity, Credit, Equity, FX, interest rate, inflation
Sensitivity kind delta (unsuffixed) and vol; MarginType adds curvature
Qualifier qualifying or non-qualifying, on credit only

CommodityVol is commodity with a vol sensitivity. CreditVolNonQ is credit, vol, non-qualifying. Nothing in the list is a market that the asset class taxonomy lacks.

So SIMM's CreditQualifying and CreditNonQualifying are not subclasses of credit. They are credit carrying an additional property. Qualifying status describes the reference entity's eligibility under the framework's rules; it does not name a different market, is not observed from different data, and exists only because SIMM assigns the two different risk weights and correlations.

RiskClass is then a flattening of asset class against that qualifier, built for one purpose: its declaration warns that "the ordering here matters. It is used in indexing in to correlation matrices for the correlation between risk classes". It is an index, not a taxonomy.

RatesFX is a grouping for the same reason, because margin is computed on the pair together.

4.1.2. What SIMM says about inflation

The RiskType declaration carries a note: "the risk type inflation has to be treated as an additional, single tenor bucket in IRCurve".

SIMM therefore treats inflation as a point on the interest rate curve rather than as a market beside it. That is the sharpest statement of the inflation question found in any of the surveyed material. Asset classes reads it as a projection SIMM applies when it charges the exposure, not as a parent-child relation in the taxonomy, which holds inflation beside interest rate.

4.2. FRTB

The Basel market risk framework classifies sensitivities for regulatory capital, using six risk classes in its sensitivities-based method: GIRR, CSR, EQ, COMM and FX, with credit spread split three ways into non-securitisation, securitisation outside the correlation trading portfolio, and securitisation within it.

It is the second framework to subdivide credit, and it does so along a different axis from SIMM: securitisation status rather than qualifying status. Two frameworks needing two incompatible subdivisions of one class is what settles the question. Neither subdivision is a subclass, and both are properties of the exposure.

FRTB treats them that way itself. A CRIF row carries creditQuality, longShortInd, coveredBondInd, trancheThickness and bb_rw as fields alongside the risk type, so the framework already puts this kind of attribute in a column.

Its greeks are named rather than implied, and curvature is not one number: CurvatureScenario carries an up shift and a down shift, because FRTB requires both.

FRTB also carries two charges that are not sensitivities at all: the default risk charge, split the same three ways as credit spread, and the residual risk add-on. Neither belongs in a classification of sensitivities.

4.3. ORE

orea/engine/riskfilter.hpp holds enum class RiskClass { All, InterestRate, Inflation, Credit, Equity, FX, Commodity }, used to filter sensitivities for reporting.

Its six substantive values are a strict coarsening of ORE's AssetClass. Bond and bond index disappear, because a bond's sensitivity decomposes; portfolio details disappear, because they carry no risk. Inflation survives as a sibling of interest rate.

ORE therefore takes the opposite position to SIMM on inflation, and the two agree that a risk classification is coarser than a product classification at the bond node.

Note that ORE holds two enumerations named RiskClass, this one and SIMM's, with different values. The name predicts nothing; the header does.

5. Open questions

  • Is the join keyed by product type or by trade? Keying by product type makes the risk classes a catalogue fact, known before pricing and the same for every trade of that kind. That is true of most cases, and false for at least one: an equity option carries FX risk only relative to the book's base currency, so the same product type is sensitive to ForeignExchange for one book and not for another. Either the join is keyed by product type and accepts a conservative superset, or it is keyed lower and stops being a catalogue fact.
  • Is the set stored or derived? A sensitivity run computes exactly this set. Storing it duplicates the computation and risks disagreement; deriving it means the classification is unavailable before pricing, which defeats using it to route or to filter.
  • Is the join a separate relation at all? A trade's requirements are known once it is booked, without a valuation date and without analytics, and each projects onto an asset class. The join described here may therefore be a view over that relation rather than a table of its own, in which case it needs to exist independently only to answer the question for a product type that has no trades yet. Market data requirement sets out the relation this depends on.
  • How is a merged grouping expressed? SIMM's RatesFX combines two nodes. A cut selects nodes rather than combining them, so this needs a grouping declared over the tree, or SIMM's product side is treated as outside the taxonomy.
  • Does the join need a degree? A bond is sensitive to interest rate and credit, but not equally. Nothing here records materiality, and a consumer wanting principal risk rather than all risk cannot get it.
  • Where do the framework properties live? Qualifying status is a SIMM concept, and sensitivity kind is common to every framework. The first argues for a per-framework extension rather than a column on the join; the second argues for a column. Nothing here settles which of the two shapes a given property takes.

6. Sources

The FRTB risk types, the CRIF record fields and the curvature scenario are read from OREAnalytics/orea/simm/crifrecord.hpp.

ORE's enumerations are read from OREAnalytics/orea/engine/riskfilter.hpp, OREAnalytics/orea/simm/simmconfiguration.hpp, OREAnalytics/orea/simm/crifrecord.hpp and OREData/ored/portfolio/trade.hpp.

No ORE or ISDA source defines the relationship between a product's class and its risk classes. The cardinality argument on this page is drawn from the signatures and enumerations rather than from a stated rationale.

7. See also

Emacs 29.3 (Org mode 9.6.15)