Regulatory Capital

ISDA SIMM Initial Margin Calculator

Explore how the Standard Initial Margin Model combines delta, vega and curvature sensitivities into initial margin. Edit a demonstration portfolio and compare risk-class and product-class contributions.

How to use the SIMM calculator

ISDA SIMM stands for Standard Initial Margin Model, a methodology for calculating initial margin on non-cleared derivatives. This educational calculator illustrates sensitivity weighting, concentration and correlation with indicative demonstration parameters.

Edit the trade ID, counterparty label, product class, notional and long/short side. Set the simulation scenarios and seed, then choose “Compute SIMM”. The results split margin into delta, vega and curvature across six risk classes, then combine it into four product classes and a total in USD millions.

The book generates synthetic sensitivities, with a European call proxy repriced for one selected trade. Trade IDs do not select instrument pricing models. The controls do not import a CRIF file or market data. Counterparty names are labels: this demo aggregates the whole book without separate counterparty or legal netting-set margins. It does not calculate an approved collateral requirement.

Non-cleared book
Trade IDCounterpartyProduct classNotionalSide

The first equity-class trade (or first trade if none exists) gets the real option repricing; product class determines the synthetic risk classes.

Simulation (the real repricing)Optional
Java source
IsdaSimmRiskStudio.java

This exact source runs in TeaVM. Form changes update its Java literals and reset manual edits.

import com.nablatensor.engine.Nabla;
import com.nablatensor.quant.EquityMarket;
import com.nablatensor.quant.MonteCarlo;
import com.nablatensor.quant.Products;
import com.nablatensor.risk.NestedAggregation;
import com.nablatensor.risk.RiskClassEnum;
import com.nablatensor.risk.RiskFactor;
import com.nablatensor.risk.RiskMeasureEnum;
import com.nablatensor.risk.Sensitivities;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Objects;
import java.util.List;
import java.util.EnumMap;

public final class IsdaSimmRiskStudio {
  // Product classes define which risk classes receive each trade's synthetic sensitivities.
  enum ProductClass {
    RATES_FX(RiskClassEnum.GIRR, RiskClassEnum.FX), CREDIT(RiskClassEnum.CSR_NON_SEC, RiskClassEnum.CSR_SEC),
        EQUITY(RiskClassEnum.EQUITY), COMMODITY(RiskClassEnum.COMMODITY);
    final List<RiskClassEnum> riskClasses;
    ProductClass(RiskClassEnum...riskClasses) {
      this.riskClasses = List.of(riskClasses);
    }
  }
  enum Side {
    LONG(1), SHORT(-1);
    final int sign;
    Side(int sign) {
      this.sign = sign;
    }
  }
  // Demo portfolio input, kept separate from the generated risk sensitivities.
  record Trade(String id, String counterparty, ProductClass productClass, double notional, Side side) {
    Trade {
      Objects.requireNonNull(id, "id");
      Objects.requireNonNull(counterparty, "counterparty");
      Objects.requireNonNull(productClass, "productClass");
      Objects.requireNonNull(side, "side");
      if (!Double.isFinite(notional)) throw new IllegalArgumentException("notional must be finite");
    }
    static Builder builder() {
      return new Builder();
    }
    static final class Builder {
      private String id;
      private String counterparty;
      private ProductClass productClass;
      private double notional = Double.NaN;
      private Side side;
      Builder id(String id) {
        this.id = id;
        return this;
      }
      Builder counterparty(String counterparty) {
        this.counterparty = counterparty;
        return this;
      }
      Builder productClass(ProductClass productClass) {
        this.productClass = productClass;
        return this;
      }
      Builder notional(double notional) {
        this.notional = notional;
        return this;
      }
      Builder side(Side side) {
        this.side = side;
        return this;
      }
      Trade build() {
        return new Trade(id, counterparty, productClass, notional, side);
      }
    }
  }
  // Simplified demo parameters; thresholds and sensitivities are in USD millions.
  record RiskClassParameters(RiskClassEnum riskClass, List<String> buckets, double deltaRiskWeight,
      double vegaRiskWeight, double withinBucketCorrelation, double betweenBucketCorrelation, double deltaConcentrationThreshold,
      double vegaConcentrationThreshold) {
    RiskClassParameters {
      Objects.requireNonNull(riskClass, "riskClass");
      buckets = List.copyOf(buckets);
      if (buckets.isEmpty()) throw new IllegalArgumentException("buckets must not be empty");
      for (double value : new double[] {
        deltaRiskWeight, vegaRiskWeight, withinBucketCorrelation, betweenBucketCorrelation, deltaConcentrationThreshold,
            vegaConcentrationThreshold
      }) {
        if (!Double.isFinite(value)) throw new IllegalArgumentException("all parameters must be finite");
      }
      if (deltaConcentrationThreshold <= 0 || vegaConcentrationThreshold <= 0) throw new IllegalArgumentException("concentration thresholds must be positive");
    }
    static Builder builder() {
      return new Builder();
    }
    static final class Builder {
      private RiskClassEnum riskClass;
      private List<String> buckets;
      private double deltaRiskWeight = Double.NaN;
      private double vegaRiskWeight = Double.NaN;
      private double withinBucketCorrelation = Double.NaN;
      private double betweenBucketCorrelation = Double.NaN;
      private double deltaConcentrationThreshold = Double.NaN;
      private double vegaConcentrationThreshold = Double.NaN;
      Builder riskClass(RiskClassEnum riskClass) {
        this.riskClass = riskClass;
        return this;
      }
      Builder buckets(String...buckets) {
        this.buckets = List.of(buckets);
        return this;
      }
      Builder deltaRiskWeight(double deltaRiskWeight) {
        this.deltaRiskWeight = deltaRiskWeight;
        return this;
      }
      Builder vegaRiskWeight(double vegaRiskWeight) {
        this.vegaRiskWeight = vegaRiskWeight;
        return this;
      }
      Builder withinBucketCorrelation(double withinBucketCorrelation) {
        this.withinBucketCorrelation = withinBucketCorrelation;
        return this;
      }
      Builder betweenBucketCorrelation(double betweenBucketCorrelation) {
        this.betweenBucketCorrelation = betweenBucketCorrelation;
        return this;
      }
      Builder deltaConcentrationThreshold(double deltaConcentrationThreshold) {
        this.deltaConcentrationThreshold = deltaConcentrationThreshold;
        return this;
      }
      Builder vegaConcentrationThreshold(double vegaConcentrationThreshold) {
        this.vegaConcentrationThreshold = vegaConcentrationThreshold;
        return this;
      }
      RiskClassParameters build() {
        return new RiskClassParameters(riskClass, buckets, deltaRiskWeight, vegaRiskWeight, withinBucketCorrelation,
            betweenBucketCorrelation, deltaConcentrationThreshold, vegaConcentrationThreshold);
      }
    }
  }
  static final RiskClassParameters[] DEMO_PARAMETERS = {
    RiskClassParameters.builder().riskClass(RiskClassEnum.GIRR)
        .buckets("USD", "EUR")
        .deltaRiskWeight(0.011).vegaRiskWeight(0.18)
        .withinBucketCorrelation(0.63).betweenBucketCorrelation(0.24)
        .deltaConcentrationThreshold(330).vegaConcentrationThreshold(130).build(),
    RiskClassParameters.builder().riskClass(RiskClassEnum.CSR_NON_SEC)
        .buckets("1", "4")
        .deltaRiskWeight(0.008).vegaRiskWeight(0.64)
        .withinBucketCorrelation(0.42).betweenBucketCorrelation(0.21)
        .deltaConcentrationThreshold(12).vegaConcentrationThreshold(320).build(),
    RiskClassParameters.builder().riskClass(RiskClassEnum.CSR_SEC)
        .buckets("1", "2")
        .deltaRiskWeight(0.28).vegaRiskWeight(0.64)
        .withinBucketCorrelation(0.27).betweenBucketCorrelation(0.35)
        .deltaConcentrationThreshold(3).vegaConcentrationThreshold(85).build(),
    RiskClassParameters.builder().riskClass(RiskClassEnum.EQUITY)
        .buckets("1", "4")
        .deltaRiskWeight(0.22).vegaRiskWeight(0.28)
        .withinBucketCorrelation(0.16).betweenBucketCorrelation(0.15)
        .deltaConcentrationThreshold(8).vegaConcentrationThreshold(210).build(),
    RiskClassParameters.builder().riskClass(RiskClassEnum.COMMODITY)
        .buckets("1", "5")
        .deltaRiskWeight(0.19).vegaRiskWeight(0.42)
        .withinBucketCorrelation(0.31).betweenBucketCorrelation(0.23)
        .deltaConcentrationThreshold(260).vegaConcentrationThreshold(74).build(),
    RiskClassParameters.builder().riskClass(RiskClassEnum.FX)
        .buckets("USD", "EUR")
        .deltaRiskWeight(0.075).vegaRiskWeight(0.3)
        .withinBucketCorrelation(0.5).betweenBucketCorrelation(0.5)
        .deltaConcentrationThreshold(2400).vegaConcentrationThreshold(480).build()
  };
  static final RiskMeasureEnum[] MEASURES = {
    RiskMeasureEnum.DELTA, RiskMeasureEnum.VEGA, RiskMeasureEnum.CURVATURE
  };
  public static void main(String[] z) {
    Trade[] trades = {
      Trade.builder().id("IRS-USD-10Y")
          .counterparty("CPTY-ALPHA").productClass(ProductClass.RATES_FX)
          .notional(120000000).side(Side.LONG).build(),
      Trade.builder().id("XCCY-EURUSD-5Y")
          .counterparty("CPTY-ALPHA").productClass(ProductClass.RATES_FX)
          .notional(80000000).side(Side.SHORT).build(),
      Trade.builder().id("CDS-IG-CPTY-5Y")
          .counterparty("CPTY-BRAVO").productClass(ProductClass.CREDIT)
          .notional(50000000).side(Side.LONG).build(),
      Trade.builder().id("CDX-HY-INDEX-5Y")
          .counterparty("CPTY-BRAVO").productClass(ProductClass.CREDIT)
          .notional(25000000).side(Side.SHORT).build(),
      Trade.builder().id("EQ-CALL-SX5E-1Y")
          .counterparty("CPTY-CHARLIE").productClass(ProductClass.EQUITY)
          .notional(15000000).side(Side.SHORT).build(),
      Trade.builder().id("EQ-PUT-SPX-1Y")
          .counterparty("CPTY-CHARLIE").productClass(ProductClass.EQUITY)
          .notional(10000000).side(Side.LONG).build(),
      Trade.builder().id("COMDTY-WTI-SWAP-2Y")
          .counterparty("CPTY-DELTA").productClass(ProductClass.COMMODITY)
          .notional(30000000).side(Side.LONG).build()
    };
    long paths = 200000L, seed = 42L;
    // Counterparty labels are counted for the book summary only.
    // This demo aggregates the whole book, without separate counterparty or netting-set margins.
    Set<String> counterparties = new HashSet<>();
    for (Trade trade : trades) counterparties.add(trade.counterparty());
    System.out.println("BOOK|" + trades.length + "|" + counterparties.size());
    // Reprice one representative position: the first equity trade, or the first trade if none exists.
    // Every selected trade uses the same one-year at-the-money European call proxy;
    // its ID does not select an actual instrument model (including IDs that say PUT).
    Trade heavy = trades[0];
    for (Trade trade : trades) if (trade.productClass() == ProductClass.EQUITY) {
      heavy = trade;
      break;
    }
    EquityMarket market = EquityMarket.of()
        .spot(100)
        .strike(100)
        .vol(.2)
        .rate(.03)
        .maturity(1)
        .build();
    double hd, hv, hir, hc;
    try (MonteCarlo<EquityMarket> g = MonteCarlo.of(Products.europeanCall())
        .market(market)
        .steps(1)
        .fp64()
        .greeks()
        .on("cpu")
        .build(); MonteCarlo<EquityMarket> p = MonteCarlo.of(Products.europeanCall())
        .market(market)
        .steps(1)
        .fp64()
        .priceOnly()
        .on("cpu")
        .build()) {
      // The adjoint run supplies Greeks. Base and +/-30% spot valuations supply curvature.
      // Reusing the seed gives common random numbers, reducing noise in price differences.
      Nabla.TypedValuation<EquityMarket> adj = g.run(paths, seed), base = p.run(paths, seed), up = p.run(EquityMarket.of()
          .spot(130)
          .strike(100)
          .vol(.2)
          .rate(.03)
          .maturity(1)
          .build(), paths, seed), down = p.run(EquityMarket.of()
          .spot(70)
          .strike(100)
          .vol(.2)
          .rate(.03)
          .maturity(1)
          .build(), paths, seed);
      // Notional / spot gives option units; /1e6 expresses portfolio values in USD millions.
      // Delta is per spot unit. Vega and rate sensitivity use a one-percentage-point move
      // because volatility and rates in the model are decimal fractions.
      hd = heavy.side()
          .sign * Math.abs(heavy.notional()) / 100.0 / 1e6 * adj.greek(EquityMarket::spot);
      hv = heavy.side()
          .sign * Math.abs(heavy.notional()) / 100.0 / 1e6 * adj.greek(EquityMarket::vol) * .01;
      hir = heavy.side()
          .sign * Math.abs(heavy.notional()) / 100.0 / 1e6 * adj.greek(EquityMarket::rate) * .01;
      // Signed prices retain the long/short position direction for all three valuations.
      double pb = heavy.side()
          .sign * Math.abs(heavy.notional()) / 100.0 / 1e6 * base.price(), pu = heavy.side()
          .sign * Math.abs(heavy.notional()) / 100.0 / 1e6 * up.price(), pd = heavy.side()
          .sign * Math.abs(heavy.notional()) / 100.0 / 1e6 * down.price();
      // Remove the linear delta P&L from each shocked price change.
      // Negating the worse residual gives the curvature loss; 30 is the spot shock from 100.
      // Keep its sign: curvature aggregation handles gains and losses differently.
      hc = -Math.min(pu - pb - 30 * hd, pd - pb + 30 * hd);
    }
    // The remaining risk is constructed for illustration, not obtained from trade pricing.
    // Each trade contributes to two demo buckets per applicable risk class, in USD millions.
    Sensitivities.Builder builder = Sensitivities.builder();
    for (int t = 0; t < trades.length; t++) {
      Trade trade = trades[t];
      double s = trade.side()
          .sign * trade.notional() / 1e6;
      int fi = 0;
      for (RiskClassParameters parameters : DEMO_PARAMETERS) if (trade.productClass()
          .riskClasses.contains(parameters.riskClass())) for (String bucket : parameters.buckets()) {
        // Alternate signs to illustrate offsets. The coefficients and trade-index scaling
        // below are synthetic assumptions, so changing row order can change this demo risk.
        double alt = ((fi++ + t) % 2 == 0) ? 1 : -.6;
        String name = trade.id() + "#" + bucket;
        builder.add(factor(parameters.riskClass(), RiskMeasureEnum.DELTA, bucket, name, 0), s * alt * .02);
        builder.add(factor(parameters.riskClass(), RiskMeasureEnum.VEGA, bucket, name, 1), Math.abs(s) * .004 * (1
            + .1 * t));
        builder.add(factor(parameters.riskClass(), RiskMeasureEnum.CURVATURE, bucket, name, 0),
            Math.abs(s) * alt * .0015);
      }
    }
    // Add the proxy option's computed risks alongside the synthetic book risk.
    // Sensitivities nets equal risk-factor keys; distinct trade IDs remain distinct factors.
    // The computed option entries supplement the synthetic entries, rather than replacing them.
    builder.add(RiskFactor.equityDelta("4", heavy.id()), hd);
    builder.add(factor(RiskClassEnum.EQUITY, RiskMeasureEnum.VEGA, "4", heavy.id(), 1), hv);
    builder.add(RiskFactor.equityDelta("4", heavy.id())
        .asCurvature(), hc);
    builder.add(RiskFactor.girrDelta("USD", 10.0), hir);
    Sensitivities crif = builder.build();
    Map<RiskClassEnum, double[]> result = new EnumMap<>(RiskClassEnum.class);
    // Calculate delta, vega and curvature independently for each risk class.
    for (RiskClassParameters parameters : DEMO_PARAMETERS) {
      double[] margins = new double[MEASURES.length];
      for (int m = 0; m < MEASURES.length; m++) margins[m] = margin(crif, parameters, MEASURES[m]);
      result.put(parameters.riskClass(), margins);
      System.out.println("CLASS|" + parameters.riskClass() + "|" + margins[0] + "|" + margins[1]
          + "|" + margins[2]);
    }
    // Within each product class, combine risk-class margins with a correlation quadratic form.
    // The x/y loop visits both directions, giving the usual 2 * correlation * margin_x * margin_y.
    // Then add the three measures and sum product-class totals without cross-product offsets.
    double total = 0;
    for (ProductClass product : ProductClass.values()) {
      double[] sums = new double[MEASURES.length];
      for (int m = 0; m < MEASURES.length; m++) {
        for (RiskClassEnum x : product.riskClasses) {
          sums[m] += result.get(x)[m] * result.get(x)[m];
          for (RiskClassEnum y : product.riskClasses) if (x != y) sums[m] += productClassCorrelation(x,
              y) * result.get(x)[m] * result.get(y)[m];
        }
        sums[m] = Math.sqrt(Math.max(0, sums[m]));
      }
      double pt = sums[0] + sums[1] + sums[2];
      total += pt;
      System.out.println("PRODUCT|" + product + "|" + sums[0] + "|" + sums[1] + "|" + sums[2] + "|"
          + pt);
    }
    System.out.println("TOTAL|" + total);
  }
  static RiskFactor factor(RiskClassEnum c, RiskMeasureEnum m, String b, String n, double t) {
    return RiskFactor.of()
        .riskClass(c)
        .measure(m)
        .bucket(b)
        .name(n)
        .tenor(t)
        .tenor2(0)
        .build();
  }
  // Apply demo risk weights and bucket correlations to one risk class and one measure.
  static double margin(Sensitivities all, RiskClassParameters parameters, RiskMeasureEnum m) {
    Sensitivities x = all.ofClass(parameters.riskClass())
        .ofMeasure(m);
    if (x.isEmpty()) return 0;
    // Curvature inputs already represent nonlinear losses, so there is no delta/vega risk weight
    // or concentration multiplier here. NestedAggregation squares correlations and excludes
    // cross terms between two negative curvature inputs.
    if (m == RiskMeasureEnum.CURVATURE) return NestedAggregation.curvature((a, b) -> parameters.withinBucketCorrelation(),
        (a, b) -> parameters.betweenBucketCorrelation())
        .aggregate(x)
        .total();
    double threshold = m == RiskMeasureEnum.DELTA ? parameters.deltaConcentrationThreshold() : parameters.vegaConcentrationThreshold();
    // Concentration uses the signed sum of sensitivities in each bucket, before weighting.
    // Offsets reduce this sum. Delta and vega have separate demo thresholds in USD millions.
    Map<String, Double> sums = new HashMap<>();
    for (RiskFactor f : x.asMap()
        .keySet()) sums.put(f.bucket(), sums.getOrDefault(f.bucket(), 0.0) + x.asMap()
        .get(f));
    // CR = max(1, sqrt(abs(bucket sum) / threshold)): small exposures receive no uplift.
    // Every factor in this bucket receives the same CR. The aggregator applies risk weights,
    // concentration scaling, then within-bucket and between-bucket correlations.
    NestedAggregation.ConcentrationFactor cr = (f, s) -> Math.max(1, Math.sqrt(Math.abs(sums.getOrDefault(f.bucket(),
        0.0)) / threshold));
    return NestedAggregation.delta(f -> m == RiskMeasureEnum.DELTA ? parameters.deltaRiskWeight() : parameters.vegaRiskWeight(),
        (a, b) -> parameters.withinBucketCorrelation(), (a, b) -> parameters.betweenBucketCorrelation())
        .withConcentration(cr)
        .aggregate(x)
        .total();
  }
  // Demo correlations between the risk classes belonging to the same product class.
  // These illustrative constants are not a complete versioned ISDA SIMM parameter set.
  static double productClassCorrelation(RiskClassEnum a, RiskClassEnum b) {
    if (a == b) return 1;
    if ((a == RiskClassEnum.GIRR && b == RiskClassEnum.FX) || (a == RiskClassEnum.FX && b == RiskClassEnum.GIRR)) return .28;
    if ((a == RiskClassEnum.CSR_NON_SEC && b == RiskClassEnum.CSR_SEC) || (a == RiskClassEnum.CSR_SEC && b == RiskClassEnum.CSR_NON_SEC)) return .15;
    return 0;
  }
}
TeaVM compiles and runs the Java source above in this browser.

Results from a precomputed Java run.

Product-class margin composition

Delta, vega and curvature add to each product-class margin; product-class totals add to total SIMM. Hover over a segment for its amount. Values use demonstration parameters.

  • Delta
  • Vega
  • Curvature

Scroll the chart horizontally to see all values on narrow screens.

Product-class margins split into delta, vega and curvatureStacked delta, vega and curvature margins in millions of dollars. Each bar sums to its product-class margin. RATES_FX: delta 0.227 $m, vega 0.481 $m, curvature 0.279 $m. CREDIT: delta 0.325 $m, vega 0.481 $m, curvature 0.119 $m. EQUITY: delta 0.090 $m, vega 0.047 $m, curvature 1.335 $m. COMMODITY: delta 0.119 $m, vega 0.126 $m, curvature 0.045 $m.00.511.5RATES_FXRATES_FX — Delta: 0.227 $mRATES_FX — Vega: 0.481 $mRATES_FX — Curvature: 0.279 $m0.987CREDITCREDIT — Delta: 0.325 $mCREDIT — Vega: 0.481 $mCREDIT — Curvature: 0.119 $m0.925EQUITYEQUITY — Delta: 0.090 $mEQUITY — Vega: 0.047 $mEQUITY — Curvature: 1.335 $m1.472COMMODITYCOMMODITY — Delta: 0.119 $mCOMMODITY — Vega: 0.126 $mCOMMODITY — Curvature: 0.045 $m0.290Margin ($m)

Risk-class margin comparison

Compare each measure across risk classes on a shared scale. These are margins before the demo’s within-product risk-class correlation aggregation, so they are not additive contributions to total SIMM. Hover over a bar for its measure and amount.

  • Delta
  • Vega
  • Curvature

Scroll the chart horizontally to see all values on narrow screens.

Delta, vega and curvature margins by risk classSeparate delta, vega and curvature margins for each risk class, in millions of dollars. Risk classes undergo correlation aggregation and are not additive contributions to the portfolio total. GIRR: delta 0.039 $m, vega 0.213 $m, curvature 0.162 $m. CSR_NON_SEC: delta 0.011 $m, vega 0.316 $m, curvature 0.076 $m. CSR_SEC: delta 0.324 $m, vega 0.318 $m, curvature 0.080 $m. EQUITY: delta 0.090 $m, vega 0.047 $m, curvature 1.335 $m. COMMODITY: delta 0.119 $m, vega 0.126 $m, curvature 0.045 $m. FX: delta 0.212 $m, vega 0.376 $m, curvature 0.186 $m.00.511.5GIRRGIRR — Delta: 0.039 $m0.039GIRR — Vega: 0.213 $m0.213GIRR — Curvature: 0.162 $m0.162CSR_NON_SECCSR_NON_SEC — Delta: 0.011 $m0.011CSR_NON_SEC — Vega: 0.316 $m0.316CSR_NON_SEC — Curvature: 0.076 $m0.076CSR_SECCSR_SEC — Delta: 0.324 $m0.324CSR_SEC — Vega: 0.318 $m0.318CSR_SEC — Curvature: 0.080 $m0.080EQUITYEQUITY — Delta: 0.090 $m0.090EQUITY — Vega: 0.047 $m0.047EQUITY — Curvature: 1.335 $m1.335COMMODITYCOMMODITY — Delta: 0.119 $m0.119COMMODITY — Vega: 0.126 $m0.126COMMODITY — Curvature: 0.045 $m0.045FXFX — Delta: 0.212 $m0.212FX — Vega: 0.376 $m0.376FX — Curvature: 0.186 $m0.186Margin ($m)
Margin by risk class
Risk classDeltaVegaCurvature
GIRR0.0390.2130.162
CSR_NON_SEC0.0110.3160.076
CSR_SEC0.3240.3180.080
EQUITY0.0900.0471.335
COMMODITY0.1190.1260.045
FX0.2120.3760.186
Initial margin by product class
RATES_FX0.987 $m
CREDIT0.925 $m
EQUITY1.472 $m
COMMODITY0.290 $m
Total SIMM3.674 $m

SIMM calculation example: the default seven-trade book

Keep the seven default trades and their notionals and sides, 200,000 scenarios, seed 42 and the unedited Java source. This constructed book produces the following demonstration margins. The default results are precomputed; after changing inputs, run the calculator again.

Default Java result, in USD millions; values rounded to three decimals
Product classInitial margin
Rates and FX0.987
Credit0.925
Equity1.472
Commodity0.290
Total demo SIMM3.674

How to read the margin breakdown

Delta measures first-order price sensitivity, vega measures volatility sensitivity, and curvature captures nonlinear price changes. In this demo, correlations combine risk-class margins within each product class; delta, vega and curvature contributions then add to its margin. Product-class margins add to the displayed total. Adding standalone trade margins would miss the sensitivity offsets before aggregation.

The result depends on this demo’s synthetic sensitivities and indicative risk weights, correlations and concentration thresholds. It is not a reproduction of a current official ISDA calibration. The counterparty labels do not establish eligibility to net real trades.

Read how the Standard Initial Margin Model works for the aggregation mechanics, or follow the ISDA SIMM portfolio margin worked example to compare standalone and combined margins using edited Java inputs. For the governed methodology, see ISDA’s official SIMM overview.

Implementation guide

Sensitivity-based initial margin

ISDA SIMM transforms agreed risk sensitivities into an initial-margin estimate for non-cleared derivatives.

Core mechanism

Sensitivities are mapped to risk classes, buckets and tenors, concentration-scaled where required, and aggregated with the methodology's risk weights and correlations. The same trade-level risk data can therefore support desk and margin views.

Practical workflow

Apply the licensed, current SIMM methodology and parameter set; align sensitivities, currencies and conventions with counterparties; then reconcile regularly as portfolios and methodology versions change.

Key details

Sensitivity netting happens before margin aggregation. Entries with identical risk-factor keys combine; distinct trade IDs in this generated book generally create distinct synthetic factors. Opposite long/short sides therefore do not guarantee a perfect offset. The portfolio article shows how to construct shared factors explicitly in the Java editor.

The demonstration maps Rates/FX trades to interest-rate and FX risk, Credit trades to two credit-spread risk classes, and Equity and Commodity trades to their respective classes. Risk weights and concentration factors act inside bucket aggregation; correlations combine buckets and, within product classes, risk-class margins. These are indicative parameters, not an official versioned calibration.

One selected trade is also represented by a one-year at-the-money European call proxy. An adjoint run supplies its Greeks, while base and plus/minus 30% spot repricings supply curvature. These computed sensitivities supplement the synthetic book. Changing simulation scenarios or seed affects this repricing; it does not turn the other trades into full instrument valuations.

This page has no historical margin backtest or counterparty reconciliation. Its total is the sum of the four demonstration product-class margins across the input book; legal netting eligibility and collateral exchange amounts require a separate production workflow.

Scope and review point

This is an educational aggregation. SIMM is a governed industry methodology with versioning, licensing and bilateral operational requirements.