This summer TradeHeader contributed an implementation of the Standardized Schedule Method for calculating Initial Margin (IM) to the Common Domain Model (CDM). This blog post explains our open source contribution, providing background on margin calculation methods, the methodology for implementing this method in CDM, and a detailed breakdown of key functions and processes involved in deriving the final net initial margin.
For further details, visit the CDM Standardized Functions documentation.
The 2007 financial crisis exposed significant weaknesses in the OTC derivatives market. In response, regulators introduced margin requirements to reduce systemic risk. The Basel Committee on Banking Supervision (BCBS) and the International Organization of Securities Commissions (IOSCO) developed guidelines for two key IM calculation methods:
The Standardized Schedule Method calculates margin requirements using fixed rates based on asset class and contract duration, aligning with BCBS-IOSCO’s simplified compliance approach. This method offers a structured process based on predefined margin rates:
Asset Class | Initial Margin Requirement (%) |
---|---|
Credit: 0-2 year duration | 2 |
Credit: 2-5 year duration | 5 |
Credit: +5 year duration | 10 |
Commodity | 15 |
Equity | 15 |
Foreign exchange | 6 |
Interest rate: 0-2 year duration | 1 |
Interest rate: 2-5 year duration | 2 |
Interest rate: +5 year duration | 4 |
Other | 15 |
The net initial margin is calculated using the formula:
Net Standardized IM = (0.4 x Gross IM) + (0.6 x NGR x Gross IM)
Our approach to implementing the Standardized Schedule Method in the CDM framework follows these three steps:
To compute the initial margin using the standardized schedule method, specific inputs need to be identified form each trade:
ISDA guidelines define the notional and duration for each product type, promoting uniformity and transparency in margin calculations across institutions and simplifying regulatory compliance.
The BuildStandardizedSchedule function facilitates the extraction and calculation of key data points required for margin computation. This function internally calls other functions to ensure that relevant trade details are gathered accurately:
The function BuildStandardizedSchedule is structured as follows:
func BuildStandardizedSchedule: inputs: trade Trade (1..1) output: standardizedSchedule StandardizedSchedule (1..1) alias assetClass: StandardizedScheduleAssetClass(trade) alias productClass: StandardizedScheduleProductClass(trade) set standardizedSchedule -> assetClass:assetClass set standardizedSchedule -> productClass: productClass set standardizedSchedule -> notional: StandardizedScheduleNotional(trade, assetClass, productClass) set standardizedSchedule -> notionalCurrency: StandardizedScheduleNotionalCurrency(trade, assetClass, productClass) set standardizedSchedule -> durationInYears: StandardizedScheduleDuration(trade, assetClass, productClass) |
Once the BuildStandardizedSchedule function has gathered the required data, the next step is to calculate the margin rate based on the trade’s asset class and duration, using the GetStandardizedScheduleMarginRate function:
func GetStandardizedScheduleMarginRate: inputs: assetClass StandardizedScheduleAssetClassEnum (1..1) durationInYears number (1..1) output: percentage number (1..1) set percentage: if assetClass = StandardizedScheduleAssetClassEnum -> InterestRates then ( if durationInYears <= 2 then 1.0 else if durationInYears > 2 and durationInYears <= 5 then 2.0 else if durationInYears > 5 then 4.0) else if assetClass = StandardizedScheduleAssetClassEnum -> Credit then ( if durationInYears <= 2 then 2.0 else if durationInYears > 2 and durationInYears <= 5 then 5.0 else if durationInYears > 5 then 10.0) else if assetClass = StandardizedScheduleAssetClassEnum -> ForeignExchange then 6.0 else if assetClass = StandardizedScheduleAssetClassEnum -> Equity then 15.0 else if assetClass = StandardizedScheduleAssetClassEnum -> Commodity then 15.0 |
With the margin rate determined, the GetGrossInitialMarginFromStandardizedSchedule function calculates the gross initial margin by multiplying the notional amount by the margin rate:
func GetGrossInitialMarginFromStandardizedSchedule: inputs: standardizedSchedule StandardizedSchedule (1..1) output: grossInitialMargin Money (0..1) alias initialMarginRequirement: GetStandardizedScheduleMarginRate(standardizedSchedule -> assetClass, standardizedSchedule -> durationInYears) set grossInitialMargin -> value: standardizedSchedule -> notional * initialMarginRequirement * 0.01 set grossInitialMargin -> unit -> currency: standardizedSchedule -> notionalCurrency |
Finally, to calculate the net initial margin, we adjust the gross margin to account for existing exposure in the portfolio using the GetNetInitialMarginFromExposure function. This function adjusts the margin requirement based on net exposures, allowing a refined calculation of initial margin. If no exposure exists, the net initial margin defaults to the gross initial margin.
func GetNetInitialMarginFromExposure: inputs: exposure Exposure (0..1) output: initialMargin StandardizedScheduleInitialMargin (0..1) alias tradePortfolio: exposure -> tradePortfolio alias positions: tradePortfolio -> positions alias tradeInitialMargin: positions extract StandardizedScheduleTradeInfo { assetClass: BuildStandardizedSchedule(item -> tradeReference -> trade) -> assetClass, productClass: BuildStandardizedSchedule(item -> tradeReference -> trade) -> productClass, grossInitialMargin: GetGrossInitialMarginFromStandardizedSchedule (BuildStandardizedSchedule(item -> tradeReference -> trade)), markToMarketValue: item -> tradeReference -> valuationHistory filter method = ValuationTypeEnum -> MarkToMarket then only-element then amount} alias totalGIM: tradeInitialMargin -> grossInitialMargin -> value sum alias netCurrentReplacementCost: tradeInitialMargin -> markToMarketValue -> value sum alias grossCurrentReplacementCost: tradeInitialMargin -> markToMarketValue filter item -> value > 0 then value sum alias netToGrossRatio: netCurrentReplacementCost / grossCurrentReplacementCost add initialMargin -> tradeInfo: tradeInitialMargin set initialMargin -> netInitialMargin -> value: 0.4*totalGIM + 0.6*totalGIM*netToGrossRatio set initialMargin -> netInitialMargin -> unit -> currency: tradeInitialMargin-> markToMarketValue -> unit -> currency distinct only-element |
The final calculation step ensures that the net initial margin is accurately aligned with regulatory standards and internal risk management guidelines, promoting consistency and compliance.
The following table provides a summary of each step in our implementation:
Step | Input | Function | Action | Output | |
---|---|---|---|---|---|
1 |
Build Standardized Schedule |
Trade Data |
Build Standardized Schedule |
Extracts trade information |
Standardized Schedule |
2 |
Infer Margin Rate |
Asset Class, Duration |
Get Standardized Schedule Margin Rate |
Computes margin rate based on asset and duration |
Margin Rate |
3 |
Calculate Gross IM |
Standardized Schedule Margin Rate |
Get Gross Initial Margin |
Multiplies Notional by Margin Rate |
Gross IM |
4 |
Compute Net IM |
Gross IM Exposure Data |
Get Net Initial Margin from Exposure |
Adjusts for exposures to calculate Net IM |
Net Initial Margin |
Implementing the Standardized Schedule Method within the Common Domain Model (CDM) establishes a reliable, structured framework for margin calculations that promotes accuracy, transparency, and regulatory compliance. Key advantages of this contribution include:
Overall, integrating the Standardized Schedule Method in CDM supports robust, standardized processes, advancing both institutional risk management and broader market stability.
Laura, graduated with a degree in Economics and a master's degree in Finance, joined TradeHeader as a consultant. Being part of the payments team, she specializes in the ISO 20022 Standard, analyzing payment flows and messages. Laura also works in risk reporting.
To be informed of more content like this, subscribe to our blog!