<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Konstantin E.</title>
    <description>The latest articles on Forem by Konstantin E. (@konstantin_e_ca6078bb6a2).</description>
    <link>https://forem.com/konstantin_e_ca6078bb6a2</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3621683%2Ffff21f2d-a059-468b-a2e7-9b3f82c0c877.jpg</url>
      <title>Forem: Konstantin E.</title>
      <link>https://forem.com/konstantin_e_ca6078bb6a2</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/konstantin_e_ca6078bb6a2"/>
    <language>en</language>
    <item>
      <title>Building a Monte Carlo Risk Engine in PyTorch: Pricing, xVA, Exposure Simulation &amp; Wrong-Way Risk</title>
      <dc:creator>Konstantin E.</dc:creator>
      <pubDate>Thu, 20 Nov 2025 21:23:35 +0000</pubDate>
      <link>https://forem.com/konstantin_e_ca6078bb6a2/building-a-monte-carlo-risk-engine-in-pytorch-pricing-xva-exposure-simulation-wrong-way-risk-24e5</link>
      <guid>https://forem.com/konstantin_e_ca6078bb6a2/building-a-monte-carlo-risk-engine-in-pytorch-pricing-xva-exposure-simulation-wrong-way-risk-24e5</guid>
      <description>&lt;p&gt;Quantitative finance relies heavily on Monte Carlo simulation engines to value derivatives, measure exposures, and compute xVA metrics like CVA, DVA, or MVA.&lt;/p&gt;

&lt;p&gt;While many libraries exist for basic option pricing, very few open-source tools provide a full multi-model, multi-factor risk engine that can simulate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;interest rates&lt;/li&gt;
&lt;li&gt;equity prices&lt;/li&gt;
&lt;li&gt;stochastic default intensities&lt;/li&gt;
&lt;li&gt;hybrid correlated factors&lt;/li&gt;
&lt;li&gt;exposure profiles (EE, EPE, ENE, EEPE, PFE)&lt;/li&gt;
&lt;li&gt;xVA metrics (CVA implemented, extendable to FVA/MVA/KVA)&lt;/li&gt;
&lt;li&gt;adjoint algorithmic differentiation (AAD)&lt;/li&gt;
&lt;li&gt;regression for American/Bermudan options&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article introduces the Monte Carlo Risk Engine, a PyTorch-powered framework for financial modeling, exposure simulation, and xVA.&lt;/p&gt;

&lt;p&gt;All code is open source:&lt;br&gt;
👉 &lt;a href="https://github.com/konstantineder/montecarlo-risk-engine" rel="noopener noreferrer"&gt;https://github.com/konstantineder/montecarlo-risk-engine&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Why Another Monte Carlo Engine?
&lt;/h1&gt;

&lt;p&gt;Banks rely on complex XVA engines. Academia uses theory-heavy models. Python has many pricing libraries — but they:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rarely support &lt;strong&gt;multi-factor correlated risk&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;almost never include &lt;strong&gt;credit models (CIR++)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;don’t compute &lt;strong&gt;exposures&lt;/strong&gt; or &lt;strong&gt;xVA&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;don’t allow &lt;strong&gt;AAD&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;don’t offer &lt;strong&gt;American option valuation&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;lack &lt;strong&gt;wrong-way risk (WWR) analysis&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted a framework that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;is &lt;strong&gt;modular&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;supports &lt;strong&gt;any number of risk models&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;allows &lt;strong&gt;correlation between factors&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;runs &lt;strong&gt;fast&lt;/strong&gt; thanks to PyTorch vectorization&lt;/li&gt;
&lt;li&gt;supports &lt;strong&gt;AAD&lt;/strong&gt;, regression, and early exercise&lt;/li&gt;
&lt;li&gt;works as a true &lt;strong&gt;risk engine&lt;/strong&gt;, not just a toy pricer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I built one.&lt;/p&gt;
&lt;h1&gt;
  
  
  Architecture Overview
&lt;/h1&gt;

&lt;p&gt;The engine consists of several core components:&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;SimulationController&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Runs Monte Carlo paths, orchestrates model evolution, handles time stepping.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;ModelConfig&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Combines multiple stochastic models into a &lt;strong&gt;joint hybrid model&lt;/strong&gt; with a correlation matrix (e.g., Vasicek interest rates + CIR++ intensity to simulate CVA).&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Metrics&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A pluggable API that includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PV
&lt;/li&gt;
&lt;li&gt;EE, EPE, ENE
&lt;/li&gt;
&lt;li&gt;EEPE
&lt;/li&gt;
&lt;li&gt;CE
&lt;/li&gt;
&lt;li&gt;PFE
&lt;/li&gt;
&lt;li&gt;CVA
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each metric returns **both the estimate and its Monte Carlo standard error.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Products&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Supports a wide range of instruments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;European, Bermudan, American options
&lt;/li&gt;
&lt;li&gt;Bond options
&lt;/li&gt;
&lt;li&gt;Bermudan swaptions&lt;/li&gt;
&lt;li&gt;Interest rate swaps
&lt;/li&gt;
&lt;li&gt;Zero, coupon, and floating-rate bonds
&lt;/li&gt;
&lt;li&gt;Basket options
&lt;/li&gt;
&lt;li&gt;Barrier and binary options
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Regression-based continuation value estimation (Longstaff–Schwartz) is built in.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Stochastic Models&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Black–Scholes (single-asset &amp;amp; multi-asset)
&lt;/li&gt;
&lt;li&gt;Vasicek
&lt;/li&gt;
&lt;li&gt;Hull–White
&lt;/li&gt;
&lt;li&gt;CIR++
&lt;/li&gt;
&lt;li&gt;Bootstrapped hazard rates from CDS data
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All models are implemented in vectorized PyTorch.&lt;/p&gt;
&lt;h1&gt;
  
  
  Example: Exposure Profile of a Bermudan Swaption
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4pduxcmh8rcr505jbp3k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4pduxcmh8rcr505jbp3k.png" alt=" " width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This figure shows &lt;strong&gt;Expected Exposure (EE)&lt;/strong&gt; and &lt;strong&gt;Potential Future Exposure (PFE)&lt;/strong&gt; for a Bermudan swaption computed across 100,000 paths.&lt;/p&gt;

&lt;p&gt;The pull-to-par behavior, early exercise shaping, and long-tail exposure are all captured correctly.&lt;/p&gt;
&lt;h1&gt;
  
  
  Wrong-Way Risk Example: CVA vs Correlation for a Zero-Coupon Bond
&lt;/h1&gt;

&lt;p&gt;One of the most powerful features of a hybrid engine is analyzing &lt;strong&gt;xVA&lt;/strong&gt; and &lt;strong&gt;WWR (wrong-way risk)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Consider a 10Y payer swap. CVA depends on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;exposure (increase when interest rates rise).&lt;/li&gt;
&lt;li&gt;default intensity (CIR++)&lt;/li&gt;
&lt;li&gt;correlation between short rate and intensity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If interest rates and intensity are &lt;strong&gt;positively correlated&lt;/strong&gt;, we get &lt;strong&gt;wrong-way risk&lt;/strong&gt; → CVA increases. If negatively correlated → &lt;strong&gt;right-way risk&lt;/strong&gt; → CVA increases.&lt;/p&gt;
&lt;h3&gt;
  
  
  Result:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4w9hf75le7pd8fnhj57k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4w9hf75le7pd8fnhj57k.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This reflects exactly the expected economic behavior!&lt;/p&gt;
&lt;h3&gt;
  
  
  Example: CVA under Wrong-Way Risk for a 10Y Payer IRS
&lt;/h3&gt;

&lt;p&gt;The following code computes the CVA of a 10-year payer interest rate swap using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vasicek for stochastic interest rates
&lt;/li&gt;
&lt;li&gt;CIR++ for stochastic credit intensities
&lt;/li&gt;
&lt;li&gt;strong positive correlation (high WWR)
&lt;/li&gt;
&lt;li&gt;A baseline CVA from an uncorrelated simulation
&lt;/li&gt;
&lt;li&gt;A statistical significance test comparing the two (3-sigma rule)
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;common.packages&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;common.enums&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SimulationScheme&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;controller.controller&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SimulationController&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;models.vasicek&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;VasicekModel&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;models.cirpp&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CIRPPModel&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;models.model_config&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ModelConfig&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;products.bond&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Bond&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;products.swap&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;InterestRateSwap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IRSType&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;metrics.cva_metric&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CVAMetric&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;metrics.risk_metrics&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;RiskMetrics&lt;/span&gt;


&lt;span class="c1"&gt;# ----------------------------
# Interest Rate Model (Vasicek)
# ----------------------------
&lt;/span&gt;&lt;span class="n"&gt;interest_rate_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;VasicekModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;calibration_date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.03&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;mean&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;mean_reversion_speed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.02&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;volatility&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;asset_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;irs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="c1"&gt;# ----------------------------
# Bootstrapped Hazard Rates
# ----------------------------
&lt;/span&gt;&lt;span class="n"&gt;hazard_rates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.006402303360855854&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.01553038972325307&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.009729741230773657&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.015552544648116201&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.021196186202801115&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.02284319986706472&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mf"&gt;7.0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.010111423894480876&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.00613267811172937&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mf"&gt;15.0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.0036969930706003337&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mf"&gt;20.0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.003791311459217732&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;counterparty_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;General Motors Co&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;intensity_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CIRPPModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;calibration_date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;y0&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;theta&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;kappa&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;volatility&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.02&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;hazard_rates&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;hazard_rates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;asset_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;counterparty_id&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="c1"&gt;# -------------------------------------------
# Hybrid Model Configuration (with WWR: ρ≈1)
# -------------------------------------------
&lt;/span&gt;&lt;span class="n"&gt;inter_correlation_matrix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;0.99999&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;model_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ModelConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;interest_rate_model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;intensity_model&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;inter_asset_correlation_matrix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;inter_correlation_matrix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="c1"&gt;# ----------------------------
# Payer Interest Rate Swap
# ----------------------------
&lt;/span&gt;&lt;span class="n"&gt;maturity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;10.0&lt;/span&gt;
&lt;span class="n"&gt;irs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;InterestRateSwap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;startdate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;enddate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;maturity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;notional&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;fixed_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.03&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tenor_fixed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tenor_float&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;irs_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;IRSType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PAYER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;asset_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;irs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;portfolio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;irs&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="c1"&gt;# ----------------------------
# CVA Metric Setup
# ----------------------------
&lt;/span&gt;&lt;span class="n"&gt;exposure_timeline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;linspace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;maturity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cva_metric&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CVAMetric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counterparty_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;counterparty_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recovery_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;risk_metrics&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RiskMetrics&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cva_metric&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;exposure_timeline&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;exposure_timeline&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="c1"&gt;# ----------------------------
# Monte Carlo Simulation
# ----------------------------
&lt;/span&gt;&lt;span class="n"&gt;num_paths_mainsim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100000&lt;/span&gt;
&lt;span class="n"&gt;num_paths_presim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100000&lt;/span&gt;
&lt;span class="n"&gt;num_steps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;

&lt;span class="n"&gt;sc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SimulationController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;portfolio&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;portfolio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model_config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;risk_metrics&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;risk_metrics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;num_paths_mainsim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;num_paths_mainsim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;num_paths_presim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;num_paths_presim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;num_steps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;num_steps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;simulation_scheme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;SimulationScheme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EULER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;differentiate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;sim_results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run_simulation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="c1"&gt;# ----------------------------
# CVA Estimate + MC Error
# ----------------------------
&lt;/span&gt;&lt;span class="n"&gt;cva_irs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sim_results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_results&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;cva_irs_error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sim_results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_mc_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="c1"&gt;# --------------------------------------------------------------
# Baseline CVA (uncorrelated case), from reference simulation
# --------------------------------------------------------------
&lt;/span&gt;&lt;span class="n"&gt;cva_uncorr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.114576156484541&lt;/span&gt;
&lt;span class="n"&gt;cva_uncorr_error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0024446898428056294&lt;/span&gt;


&lt;span class="c1"&gt;# --------------------------------------------------------------
# Statistical Test: Is WWR CVA &amp;gt; Uncorrelated CVA?
# Uses 3-sigma significance test on the difference.
# --------------------------------------------------------------
&lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cva_irs&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;cva_uncorr&lt;/span&gt;
&lt;span class="n"&gt;se_diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cva_irs_error&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;cva_uncorr_error&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;

&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;diff&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;se_diff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WWR CVA is not significantly higher than baseline&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  AAD: Sensitivities With PyTorch Autodiff
&lt;/h2&gt;

&lt;p&gt;The engine supports adjoint algorithmic differentiation, made possible by PyTorch’s computation graph.&lt;br&gt;
You can compute Greeks (sensitivities) by enabling differentiation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="n"&gt;sc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SimulationController&lt;/span&gt;&lt;span class="p"&gt;(...,&lt;/span&gt; &lt;span class="n"&gt;differentiate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pathwise sensitivities&lt;/li&gt;
&lt;li&gt;efficient Reverse-Mode differentiation&lt;/li&gt;
&lt;li&gt;differentiable regression layers for Bermudan options&lt;/li&gt;
&lt;li&gt;differentiable risk metrics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are advanced capabilities typical of bank-level xVA systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example:
&lt;/h3&gt;

&lt;p&gt;As an example, the following plots demonstrate &lt;strong&gt;pathwise sensitivities (Greeks)&lt;/strong&gt; computed via AAD.&lt;br&gt;&lt;br&gt;
Each line shows the derivative of the option value with respect to a chosen model parameter (e.g., spot, volatility, interest rate). These sensitivities were obtained in a &lt;strong&gt;single backward pass&lt;/strong&gt; thanks to reverse-mode autodiff — something that would require &lt;em&gt;multiple&lt;/em&gt; full re-valuations in traditional bump-and-revalue Monte Carlo.&lt;/p&gt;

&lt;p&gt;This highlights three important points:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Efficiency&lt;/strong&gt;
Reverse-mode AAD computes &lt;em&gt;all&lt;/em&gt; Greeks at roughly the cost of a single simulation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stability&lt;/strong&gt;
Sensitivities are smooth and differentiable, avoiding the noise of bump-and-revalue methods.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generality&lt;/strong&gt;
The same mechanism works for:

&lt;ul&gt;
&lt;li&gt;Bermudan/early exercise products (via differentiable regression),&lt;/li&gt;
&lt;li&gt;CVA and exposure metrics,&lt;/li&gt;
&lt;li&gt;Multi-factor hybrid SDE models,&lt;/li&gt;
&lt;li&gt;Discontinuous payoffs when smoothing is enabled.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Below is an example sensitivity plot produced by the engine:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff4xyrtwu06yucubaz2vf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff4xyrtwu06yucubaz2vf.png" alt=" " width="800" height="685"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  🐳 Docker Support
&lt;/h2&gt;

&lt;p&gt;A full environment is available via Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; mcengine &lt;span class="nb"&gt;.&lt;/span&gt;
docker run &lt;span class="nt"&gt;-it&lt;/span&gt; mcengine python tests/pv_tests/pv_european_option.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No dependencies, no headaches — runs out of the box.&lt;/p&gt;

&lt;h2&gt;
  
  
  Source Code
&lt;/h2&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/konstantineder/montecarlo-risk-engine" rel="noopener noreferrer"&gt;https://github.com/konstantineder/montecarlo-risk-engine&lt;/a&gt;&lt;br&gt;
If you like the engine, consider ⭐ starring the repo or opening issues/suggestions!&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This project aims to provide a research-grade, production-style Monte Carlo engine that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;is transparent&lt;/li&gt;
&lt;li&gt;is extendable&lt;/li&gt;
&lt;li&gt;supports hybrid multi-factor models&lt;/li&gt;
&lt;li&gt;runs on PyTorch for speed &amp;amp; autodiff&lt;/li&gt;
&lt;li&gt;handles real-world xVA phenomena like WWR&lt;/li&gt;
&lt;li&gt;produces correct, validated numerical results&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're a quant, quant dev, fintech engineer, or researcher, I hope you'll find it useful.&lt;/p&gt;

&lt;p&gt;If you'd like a deep dive into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;American Option pricing (American Monte Carlo via Longstaff-Schwartz; new approaches using Machine Learning techniques (reinforcement learning))&lt;/li&gt;
&lt;li&gt;AAD functionalities and implementation details&lt;/li&gt;
&lt;li&gt;Exposure and/or CVA analytics&lt;/li&gt;
&lt;li&gt;or any other fascinating topic covered by the engine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;let me know in the comments!&lt;/p&gt;

</description>
      <category>python</category>
      <category>quantfinance</category>
      <category>xva</category>
      <category>montecarlo</category>
    </item>
  </channel>
</rss>
