LognormalLIBORPointEvolver.java

  1. package org.drip.dynamics.lmm;

  2. /*
  3.  * -*- mode: java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  4.  */

  5. /*!
  6.  * Copyright (C) 2020 Lakshmi Krishnamurthy
  7.  * Copyright (C) 2019 Lakshmi Krishnamurthy
  8.  * Copyright (C) 2018 Lakshmi Krishnamurthy
  9.  * Copyright (C) 2017 Lakshmi Krishnamurthy
  10.  * Copyright (C) 2016 Lakshmi Krishnamurthy
  11.  * Copyright (C) 2015 Lakshmi Krishnamurthy
  12.  *
  13.  *  This file is part of DROP, an open-source library targeting analytics/risk, transaction cost analytics,
  14.  *      asset liability management analytics, capital, exposure, and margin analytics, valuation adjustment
  15.  *      analytics, and portfolio construction analytics within and across fixed income, credit, commodity,
  16.  *      equity, FX, and structured products. It also includes auxiliary libraries for algorithm support,
  17.  *      numerical analysis, numerical optimization, spline builder, model validation, statistical learning,
  18.  *      and computational support.
  19.  *  
  20.  *      https://lakshmidrip.github.io/DROP/
  21.  *  
  22.  *  DROP is composed of three modules:
  23.  *  
  24.  *  - DROP Product Core - https://lakshmidrip.github.io/DROP-Product-Core/
  25.  *  - DROP Portfolio Core - https://lakshmidrip.github.io/DROP-Portfolio-Core/
  26.  *  - DROP Computational Core - https://lakshmidrip.github.io/DROP-Computational-Core/
  27.  *
  28.  *  DROP Product Core implements libraries for the following:
  29.  *  - Fixed Income Analytics
  30.  *  - Loan Analytics
  31.  *  - Transaction Cost Analytics
  32.  *
  33.  *  DROP Portfolio Core implements libraries for the following:
  34.  *  - Asset Allocation Analytics
  35.  *  - Asset Liability Management Analytics
  36.  *  - Capital Estimation Analytics
  37.  *  - Exposure Analytics
  38.  *  - Margin Analytics
  39.  *  - XVA Analytics
  40.  *
  41.  *  DROP Computational Core implements libraries for the following:
  42.  *  - Algorithm Support
  43.  *  - Computation Support
  44.  *  - Function Analysis
  45.  *  - Model Validation
  46.  *  - Numerical Analysis
  47.  *  - Numerical Optimizer
  48.  *  - Spline Builder
  49.  *  - Statistical Learning
  50.  *
  51.  *  Documentation for DROP is Spread Over:
  52.  *
  53.  *  - Main                     => https://lakshmidrip.github.io/DROP/
  54.  *  - Wiki                     => https://github.com/lakshmiDRIP/DROP/wiki
  55.  *  - GitHub                   => https://github.com/lakshmiDRIP/DROP
  56.  *  - Repo Layout Taxonomy     => https://github.com/lakshmiDRIP/DROP/blob/master/Taxonomy.md
  57.  *  - Javadoc                  => https://lakshmidrip.github.io/DROP/Javadoc/index.html
  58.  *  - Technical Specifications => https://github.com/lakshmiDRIP/DROP/tree/master/Docs/Internal
  59.  *  - Release Versions         => https://lakshmidrip.github.io/DROP/version.html
  60.  *  - Community Credits        => https://lakshmidrip.github.io/DROP/credits.html
  61.  *  - Issues Catalog           => https://github.com/lakshmiDRIP/DROP/issues
  62.  *  - JUnit                    => https://lakshmidrip.github.io/DROP/junit/index.html
  63.  *  - Jacoco                   => https://lakshmidrip.github.io/DROP/jacoco/index.html
  64.  *
  65.  *  Licensed under the Apache License, Version 2.0 (the "License");
  66.  *      you may not use this file except in compliance with the License.
  67.  *  
  68.  *  You may obtain a copy of the License at
  69.  *      http://www.apache.org/licenses/LICENSE-2.0
  70.  *  
  71.  *  Unless required by applicable law or agreed to in writing, software
  72.  *      distributed under the License is distributed on an "AS IS" BASIS,
  73.  *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  74.  *  
  75.  *  See the License for the specific language governing permissions and
  76.  *      limitations under the License.
  77.  */

  78. /**
  79.  * <i>LognormalLIBORPointEvolver</i> sets up and implements the Multi-Factor No-arbitrage Dynamics of the
  80.  * Point Rates State Quantifiers traced from the Evolution of the LIBOR Forward Rate as formulated in:
  81.  *
  82.  *  <br><br>
  83.  *  <ul>
  84.  *      <li>
  85.  *          Goldys, B., M. Musiela, and D. Sondermann (1994): <i>Log-normality of Rates and Term Structure
  86.  *              Models</i> <b>The University of New South Wales</b>
  87.  *      </li>
  88.  *      <li>
  89.  *          Musiela, M. (1994): <i>Nominal Annual Rates and Log-normal Volatility Structure</i> <b>The
  90.  *              University of New South Wales</b>
  91.  *      </li>
  92.  *      <li>
  93.  *          Brace, A., D. Gatarek, and M. Musiela (1997): The Market Model of Interest Rate Dynamics
  94.  *              <i>Mathematical Finance</i> <b>7 (2)</b> 127-155
  95.  *      </li>
  96.  *  </ul>
  97.  *
  98.  *  <br><br>
  99.  *  <ul>
  100.  *      <li><b>Module </b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/ProductCore.md">Product Core Module</a></li>
  101.  *      <li><b>Library</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/FixedIncomeAnalyticsLibrary.md">Fixed Income Analytics</a></li>
  102.  *      <li><b>Project</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/dynamics/README.md">HJM, Hull White, LMM, and SABR Dynamic Evolution Models</a></li>
  103.  *      <li><b>Package</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/dynamics/lmm/README.md">LMM Based Latent State Evolution</a></li>
  104.  *  </ul>
  105.  *
  106.  * @author Lakshmi Krishnamurthy
  107.  */

  108. public class LognormalLIBORPointEvolver implements org.drip.dynamics.evolution.PointStateEvolver {
  109.     private org.drip.state.forward.ForwardCurve _fc = null;
  110.     private org.drip.state.discount.MergedDiscountForwardCurve _dc = null;
  111.     private org.drip.state.identifier.ForwardLabel _lslForward = null;
  112.     private org.drip.state.identifier.FundingLabel _lslFunding = null;
  113.     private org.drip.dynamics.lmm.LognormalLIBORVolatility _llv = null;

  114.     private double forwardDerivative (
  115.         final int iViewDate)
  116.         throws java.lang.Exception
  117.     {
  118.         org.drip.function.definition.R1ToR1 freR1ToR1 = new org.drip.function.definition.R1ToR1 (null)
  119.         {
  120.             @Override public double evaluate (
  121.                 final double dblDate)
  122.                 throws java.lang.Exception
  123.             {
  124.                 return _fc.forward ((int) dblDate);
  125.             }
  126.         };

  127.         return freR1ToR1.derivative (iViewDate, 1);
  128.     }

  129.     private double continuousForwardRateIncrement (
  130.         final int iViewDate,
  131.         final double dblAnnualizedIncrement,
  132.         final double[] adblMultivariateRandom)
  133.         throws java.lang.Exception
  134.     {
  135.         final int iNumFactor = adblMultivariateRandom.length;

  136.         final double dblSpotTimeIncrementSQRT = java.lang.Math.sqrt (dblAnnualizedIncrement);

  137.         org.drip.function.definition.R1ToR1 continuousForwardRateR1ToR1 = new
  138.             org.drip.function.definition.R1ToR1 (null) {
  139.             @Override public double evaluate (
  140.                 final double dblDate)
  141.                 throws java.lang.Exception
  142.             {
  143.                 double dblForwardPointVolatilityModulus = 0.;
  144.                 double dblPointVolatilityMultifactorRandom = 0.;

  145.                 double[] adblContinuousForwardVolatility = _llv.continuousForwardVolatility ((int) dblDate,
  146.                     _fc);

  147.                 if (null != adblContinuousForwardVolatility) {
  148.                     for (int i = 0; i < iNumFactor; ++i) {
  149.                         dblForwardPointVolatilityModulus += adblContinuousForwardVolatility[i] *
  150.                             adblContinuousForwardVolatility[i];
  151.                         dblPointVolatilityMultifactorRandom += adblContinuousForwardVolatility[i] *
  152.                             adblMultivariateRandom[i];
  153.                     }
  154.                 }

  155.                 return (_fc.forward ((int) dblDate) + 0.5 * dblForwardPointVolatilityModulus) *
  156.                     dblAnnualizedIncrement + dblPointVolatilityMultifactorRandom * dblSpotTimeIncrementSQRT;
  157.             }
  158.         };

  159.         return continuousForwardRateR1ToR1.derivative (iViewDate, 1);
  160.     }

  161.     private double spotRateIncrement (
  162.         final double dblSpotDate,
  163.         final double dblViewDate,
  164.         final double dblAnnualizedIncrement,
  165.         final double[] adblMultivariateRandom)
  166.         throws java.lang.Exception
  167.     {
  168.         final int iNumFactor = adblMultivariateRandom.length;

  169.         final double dblAnnualizedIncrementSQRT = java.lang.Math.sqrt (dblAnnualizedIncrement);

  170.         org.drip.function.definition.R1ToR1 spotRateR1ToR1 = new org.drip.function.definition.R1ToR1
  171.             (null) {
  172.             @Override public double evaluate (
  173.                 final double dblDate)
  174.                 throws java.lang.Exception
  175.             {
  176.                 double dblPointVolatilityMultifactorRandom = 0.;

  177.                 double[] adblContinuousForwardVolatility = _llv.continuousForwardVolatility ((int) dblDate,
  178.                     _fc);

  179.                 if (null != adblContinuousForwardVolatility) {
  180.                     for (int i = 0; i < iNumFactor; ++i)
  181.                         dblPointVolatilityMultifactorRandom += adblContinuousForwardVolatility[i] *
  182.                             adblMultivariateRandom[i];
  183.                 }

  184.                 return _fc.forward ((int) dblDate) * dblAnnualizedIncrement +
  185.                     dblPointVolatilityMultifactorRandom * dblAnnualizedIncrementSQRT;
  186.             }
  187.         };

  188.         return spotRateR1ToR1.derivative (dblViewDate, 1);
  189.     }

  190.     /**
  191.      * LognormalLIBORPointEvolver Constructor
  192.      *
  193.      * @param lslFunding The Funding Latent State Label
  194.      * @param lslForward The Forward Latent State Label
  195.      * @param llv The Log-normal LIBOR Volatility Instance
  196.      * @param fc The Forward Curve Instance
  197.      * @param dc The Discount Curve Instance
  198.      *
  199.      * @throws java.lang.Exception Thrown if Inputs are Invalid
  200.      */

  201.     public LognormalLIBORPointEvolver (
  202.         final org.drip.state.identifier.FundingLabel lslFunding,
  203.         final org.drip.state.identifier.ForwardLabel lslForward,
  204.         final org.drip.dynamics.lmm.LognormalLIBORVolatility llv,
  205.         final org.drip.state.forward.ForwardCurve fc,
  206.         final org.drip.state.discount.MergedDiscountForwardCurve dc)
  207.         throws java.lang.Exception
  208.     {
  209.         if (null == (_lslFunding = lslFunding) || null == (_lslForward = lslForward) || null == (_llv = llv)
  210.             || null == (_fc = fc) || null == (_dc = dc))
  211.             throw new java.lang.Exception ("LognormalLIBORPointEvolver ctr: Invalid Inputs");
  212.     }

  213.     /**
  214.      * Retrieve the Funding Label
  215.      *
  216.      * @return The Funding Label
  217.      */

  218.     public org.drip.state.identifier.FundingLabel fundingLabel()
  219.     {
  220.         return _lslFunding;
  221.     }

  222.     /**
  223.      * Retrieve the Forward Label
  224.      *
  225.      * @return The Forward Label
  226.      */

  227.     public org.drip.state.identifier.ForwardLabel forwardLabel()
  228.     {
  229.         return _lslForward;
  230.     }

  231.     /**
  232.      * Retrieve the Log-normal LIBOR Volatility Instance
  233.      *
  234.      * @return The Log-normal LIBOR Volatility Instance
  235.      */

  236.     public org.drip.dynamics.lmm.LognormalLIBORVolatility llv()
  237.     {
  238.         return _llv;
  239.     }

  240.     /**
  241.      * Retrieve the Forward Curve Instance
  242.      *
  243.      * @return The Forward Curve Instance
  244.      */

  245.     public org.drip.state.forward.ForwardCurve forwardCurve()
  246.     {
  247.         return _fc;
  248.     }

  249.     /**
  250.      * Retrieve the Discount Curve Instance
  251.      *
  252.      * @return The Discount Curve Instance
  253.      */

  254.     public org.drip.state.discount.MergedDiscountForwardCurve discountCurve()
  255.     {
  256.         return _dc;
  257.     }

  258.     @Override public org.drip.dynamics.lmm.BGMPointUpdate evolve (
  259.         final int iSpotDate,
  260.         final int iViewDate,
  261.         final int iSpotTimeIncrement,
  262.         final org.drip.dynamics.evolution.LSQMPointUpdate lsqmPrev)
  263.     {
  264.         if (iSpotDate > iViewDate || (null != lsqmPrev && !(lsqmPrev instanceof
  265.             org.drip.dynamics.lmm.BGMPointUpdate)))
  266.             return null;

  267.         double dblAnnualizedIncrement = 1. * iSpotTimeIncrement / 365.25;

  268.         double dblAnnualizedIncrementSQRT = java.lang.Math.sqrt (dblAnnualizedIncrement);

  269.         double[] adblMultivariateRandom = _llv.msg().random();

  270.         java.lang.String strTenor = _lslForward.tenor();

  271.         double dblLIBOR = java.lang.Double.NaN;
  272.         double dblSpotRate = java.lang.Double.NaN;
  273.         double dblDiscountFactor = java.lang.Double.NaN;
  274.         double dblContinuouslyCompoundedForwardRate = java.lang.Double.NaN;
  275.         org.drip.dynamics.lmm.BGMPointUpdate bgmPrev = null == lsqmPrev ? null :
  276.             (org.drip.dynamics.lmm.BGMPointUpdate) lsqmPrev;

  277.         int iForwardDate = new org.drip.analytics.date.JulianDate (iViewDate).addTenor (strTenor).julian();

  278.         try {
  279.             if (null == bgmPrev) {
  280.                 dblLIBOR = _fc.forward (iForwardDate);

  281.                 dblDiscountFactor = _dc.df (iViewDate);

  282.                 dblSpotRate = _dc.forward (iSpotDate, iSpotDate + 1);

  283.                 dblContinuouslyCompoundedForwardRate = _dc.forward (iViewDate, iViewDate + 1);
  284.             } else {
  285.                 dblLIBOR = bgmPrev.libor();

  286.                 dblSpotRate = bgmPrev.spotRate();

  287.                 dblDiscountFactor = bgmPrev.discountFactor();

  288.                 dblContinuouslyCompoundedForwardRate = bgmPrev.continuousForwardRate();
  289.             }

  290.             double[] adblLognormalFactorPointVolatility = _llv.factorPointVolatility (iSpotDate, iViewDate);

  291.             double[] adblContinuousForwardVolatility = _llv.continuousForwardVolatility (iViewDate, _fc);

  292.             double dblCrossVolatilityDotProduct = 0.;
  293.             double dblLognormalPointVolatilityModulus = 0.;
  294.             double dblLIBORVolatilityMultiFactorRandom = 0.;
  295.             double dblContinuousForwardVolatilityModulus = 0.;
  296.             double dblForwardVolatilityMultiFactorRandom = 0.;
  297.             int iNumFactor = adblLognormalFactorPointVolatility.length;

  298.             for (int i = 0; i < iNumFactor; ++i) {
  299.                 dblLognormalPointVolatilityModulus += adblLognormalFactorPointVolatility[i] *
  300.                     adblLognormalFactorPointVolatility[i];
  301.                 dblCrossVolatilityDotProduct += adblLognormalFactorPointVolatility[i] *
  302.                     adblContinuousForwardVolatility[i];
  303.                 dblLIBORVolatilityMultiFactorRandom += adblLognormalFactorPointVolatility[i] *
  304.                     adblMultivariateRandom[i] * dblAnnualizedIncrementSQRT;
  305.                 dblContinuousForwardVolatilityModulus += adblContinuousForwardVolatility[i] *
  306.                     adblContinuousForwardVolatility[i];
  307.                 dblForwardVolatilityMultiFactorRandom += adblContinuousForwardVolatility[i] *
  308.                     adblMultivariateRandom[i] * dblAnnualizedIncrementSQRT;
  309.             }

  310.             double dblDCF = org.drip.analytics.support.Helper.TenorToYearFraction (strTenor);

  311.             double dblLIBORDCF = dblDCF * dblLIBOR;

  312.             double dblLIBORIncrement = dblAnnualizedIncrement * (forwardDerivative (iForwardDate) + dblLIBOR
  313.                 * dblCrossVolatilityDotProduct + (dblLognormalPointVolatilityModulus * dblLIBOR * dblLIBORDCF
  314.                     / (1. + dblLIBORDCF))) + dblLIBOR * dblLIBORVolatilityMultiFactorRandom;

  315.             double dblContinuousForwardRateIncrement = continuousForwardRateIncrement (iViewDate,
  316.                 dblAnnualizedIncrement, adblMultivariateRandom);

  317.             double dblSpotRateIncrement = spotRateIncrement (iSpotDate, iViewDate, dblAnnualizedIncrement,
  318.                 adblMultivariateRandom);

  319.             double dblEvolvedContinuousForwardRate = dblContinuouslyCompoundedForwardRate +
  320.                 dblContinuousForwardRateIncrement;
  321.             double dblDiscountFactorIncrement = dblDiscountFactor * (dblSpotRate -
  322.                 dblContinuouslyCompoundedForwardRate) * dblAnnualizedIncrement -
  323.                     dblForwardVolatilityMultiFactorRandom;

  324.             return org.drip.dynamics.lmm.BGMPointUpdate.Create (_lslFunding, _lslForward, iSpotDate,
  325.                 iSpotDate + iSpotTimeIncrement, iViewDate, dblLIBOR + dblLIBORIncrement, dblLIBORIncrement,
  326.                     dblEvolvedContinuousForwardRate, dblContinuousForwardRateIncrement, dblSpotRate +
  327.                         dblSpotRateIncrement, dblSpotRateIncrement, dblDiscountFactor +
  328.                             dblDiscountFactorIncrement, dblDiscountFactorIncrement, java.lang.Math.exp
  329.                                 (dblEvolvedContinuousForwardRate) - 1., (java.lang.Math.exp (dblDCF *
  330.                                     dblEvolvedContinuousForwardRate) - 1.) / dblDCF, java.lang.Math.sqrt
  331.                                         (dblLognormalPointVolatilityModulus), java.lang.Math.sqrt
  332.                                             (dblContinuousForwardVolatilityModulus));
  333.         } catch (java.lang.Exception e) {
  334.             e.printStackTrace();
  335.         }

  336.         return null;
  337.     }
  338. }