LognormalLIBORVolatility.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>LognormalLIBORVolatility</i> implements the Multi-Factor Log-normal LIBOR Volatility as formulated in:
  80.  *
  81.  *  <br><br>
  82.  *  <ul>
  83.  *      <li>
  84.  *          Goldys, B., M. Musiela, and D. Sondermann (1994): <i>Log-normality of Rates and Term Structure
  85.  *              Models</i> <b>The University of New South Wales</b>
  86.  *      </li>
  87.  *      <li>
  88.  *          Musiela, M. (1994): <i>Nominal Annual Rates and Log-normal Volatility Structure</i> <b>The
  89.  *              University of New South Wales</b>
  90.  *      </li>
  91.  *      <li>
  92.  *          Brace, A., D. Gatarek, and M. Musiela (1997): The Market Model of Interest Rate Dynamics
  93.  *              <i>Mathematical Finance</i> <b>7 (2)</b> 127-155
  94.  *      </li>
  95.  *  </ul>
  96.  *
  97.  *  <br><br>
  98.  *  <ul>
  99.  *      <li><b>Module </b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/ProductCore.md">Product Core Module</a></li>
  100.  *      <li><b>Library</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/FixedIncomeAnalyticsLibrary.md">Fixed Income Analytics</a></li>
  101.  *      <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>
  102.  *      <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>
  103.  *  </ul>
  104.  *
  105.  * @author Lakshmi Krishnamurthy
  106.  */

  107. public class LognormalLIBORVolatility extends org.drip.dynamics.hjm.MultiFactorVolatility {
  108.     private int _iSpotDate = java.lang.Integer.MIN_VALUE;
  109.     private org.drip.state.identifier.ForwardLabel _lslForward = null;

  110.     /**
  111.      * LognormalLIBORVolatility Constructor
  112.      *
  113.      * @param iSpotDate The Spot Date
  114.      * @param lslForward The Forward Label
  115.      * @param aMSVolatility Array of the Multi-Factor Volatility Surfaces
  116.      * @param pfsg Principal Factor Sequence Generator
  117.      *
  118.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  119.      */

  120.     public LognormalLIBORVolatility (
  121.         final int iSpotDate,
  122.         final org.drip.state.identifier.ForwardLabel lslForward,
  123.         final org.drip.analytics.definition.MarketSurface[] aMSVolatility,
  124.         final org.drip.sequence.random.PrincipalFactorSequenceGenerator pfsg)
  125.         throws java.lang.Exception
  126.     {
  127.         super (aMSVolatility, pfsg);

  128.         if (null == (_lslForward = lslForward))
  129.             throw new java.lang.Exception ("LognormalLIBORVolatility ctr: Invalid Inputs");

  130.         _iSpotDate = iSpotDate;
  131.     }

  132.     /**
  133.      * Retrieve the Spot Date
  134.      *
  135.      * @return The Spot Date
  136.      */

  137.     public int spotDate()
  138.     {
  139.         return _iSpotDate;
  140.     }

  141.     /**
  142.      * Retrieve the Forward Label
  143.      *
  144.      * @return The Forward Label
  145.      */

  146.     public org.drip.state.identifier.ForwardLabel forwardLabel()
  147.     {
  148.         return _lslForward;
  149.     }

  150.     /**
  151.      * Compute the Constraint in the Difference in the Volatility of the Continuously Compounded Forward Rate
  152.      *  between the Target Date and the Target Date + Forward Tenor
  153.      *
  154.      * @param fc The Forward Curve Instance
  155.      * @param iTargetDate The Target Date
  156.      *
  157.      * @return The Constraint in the Difference in the Volatility of the Continuously Compounded Forward Rate
  158.      */

  159.     public double[] continuousForwardVolatilityConstraint (
  160.         final org.drip.state.forward.ForwardCurve fc,
  161.         final int iTargetDate)
  162.     {
  163.         if (null == fc || iTargetDate <= _iSpotDate) return null;

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

  165.         org.drip.analytics.definition.MarketSurface[] aMS = volatilitySurface();

  166.         try {
  167.             double dblLIBORDCF = fc.forward (new org.drip.analytics.date.JulianDate (iTargetDate).addTenor
  168.                 (strTenor)) * org.drip.analytics.support.Helper.TenorToYearFraction (strTenor);

  169.             int iNumSurface = aMS.length;
  170.             double dblConstraintWeight = dblLIBORDCF / (1. + dblLIBORDCF);
  171.             double[] adblContinuousForwardVolatilityConstraint = new double[iNumSurface];

  172.             for (int i = 0; i < iNumSurface; ++i)
  173.                 adblContinuousForwardVolatilityConstraint[i] = dblConstraintWeight * aMS[i].node (_iSpotDate,
  174.                     iTargetDate);

  175.             return adblContinuousForwardVolatilityConstraint;
  176.         } catch (java.lang.Exception e) {
  177.             e.printStackTrace();
  178.         }

  179.         return null;
  180.     }

  181.     /**
  182.      * Compute the Volatility of the Continuously Compounded Forward Rate Up to the Target Date
  183.      *
  184.      * @param iTargetDate The Target Date
  185.      * @param fc The Forward Curve Instance
  186.      *
  187.      * @return The Volatility of the Continuously Compounded Forward Rate Up to the Target Date
  188.      */

  189.     public double[] continuousForwardVolatility (
  190.         final int iTargetDate,
  191.         final org.drip.state.forward.ForwardCurve fc)
  192.     {
  193.         if (iTargetDate <= _iSpotDate || null == fc) return null;

  194.         org.drip.sequence.random.PrincipalFactorSequenceGenerator pfsg = msg();

  195.         int iNumFactor = pfsg.numFactor();

  196.         boolean bLoop = true;
  197.         int iEndDate = _iSpotDate;
  198.         double dblTenorDCF = java.lang.Double.NaN;
  199.         double[] adblContinuousForwardVolatility = new double[iNumFactor];

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

  201.         try {
  202.             dblTenorDCF = org.drip.analytics.support.Helper.TenorToYearFraction (strTenor);
  203.         } catch (java.lang.Exception e) {
  204.             e.printStackTrace();

  205.             return null;
  206.         }

  207.         for (int i = 0; i < iNumFactor; ++i)
  208.             adblContinuousForwardVolatility[i] = 0.;

  209.         double[] adblFactorPointVolatility = factorPointVolatility (_iSpotDate, iEndDate);

  210.         while (bLoop) {
  211.             try {
  212.                 if ((iEndDate = new org.drip.analytics.date.JulianDate (iEndDate).addTenor
  213.                     (strTenor).julian()) > iTargetDate)
  214.                     bLoop = false;

  215.                 double dblLIBORTenorDCF = fc.forward (iEndDate) * dblTenorDCF;

  216.                 double dblLIBORLognormalVolatilityScaler = dblLIBORTenorDCF / (1. + dblLIBORTenorDCF);

  217.                 for (int i = 0; i < iNumFactor; ++i)
  218.                     adblContinuousForwardVolatility[i] += dblLIBORLognormalVolatilityScaler *
  219.                         adblFactorPointVolatility[i];
  220.             } catch (java.lang.Exception e) {
  221.                 e.printStackTrace();

  222.                 return null;
  223.             }
  224.         }

  225.         return adblContinuousForwardVolatility;
  226.     }

  227.     /**
  228.      * Compute the Volatility of the Continuously Compounded Forward Rate Up to the Target Date
  229.      *
  230.      * @param iTargetDate The Target Date
  231.      * @param dc The Discount Curve Instance
  232.      *
  233.      * @return The Volatility of the Continuously Compounded Forward Rate Up to the Target Date
  234.      */

  235.     public double[] continuousForwardVolatility (
  236.         final int iTargetDate,
  237.         final org.drip.state.discount.MergedDiscountForwardCurve dc)
  238.     {
  239.         if (iTargetDate <= _iSpotDate || null == dc) return null;

  240.         org.drip.sequence.random.PrincipalFactorSequenceGenerator pfsg = msg();

  241.         int iNumFactor = pfsg.numFactor();

  242.         boolean bLoop = true;
  243.         int iStartDate = _iSpotDate;
  244.         double dblTenorDCF = java.lang.Double.NaN;
  245.         double[] adblContinuousForwardVolatility = new double[iNumFactor];

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

  247.         try {
  248.             dblTenorDCF = org.drip.analytics.support.Helper.TenorToYearFraction (strTenor);
  249.         } catch (java.lang.Exception e) {
  250.             e.printStackTrace();

  251.             return null;
  252.         }

  253.         for (int i = 0; i < iNumFactor; ++i)
  254.             adblContinuousForwardVolatility[i] = 0.;

  255.         double[] adblFactorPointVolatility = factorPointVolatility (_iSpotDate, iStartDate);

  256.         while (bLoop) {
  257.             try {
  258.                 double dblLIBORTenorDCF = dc.libor (iStartDate, strTenor) * dblTenorDCF;

  259.                 double dblLIBORLognormalVolatilityScaler = dblLIBORTenorDCF / (1. + dblLIBORTenorDCF);

  260.                 for (int i = 0; i < iNumFactor; ++i)
  261.                     adblContinuousForwardVolatility[i] += dblLIBORLognormalVolatilityScaler *
  262.                         adblFactorPointVolatility[i];

  263.                 if ((iStartDate = new org.drip.analytics.date.JulianDate (iStartDate).addTenor
  264.                     (strTenor).julian()) > iTargetDate)
  265.                     bLoop = false;
  266.             } catch (java.lang.Exception e) {
  267.                 e.printStackTrace();

  268.                 return null;
  269.             }
  270.         }

  271.         return adblContinuousForwardVolatility;
  272.     }

  273.     /**
  274.      * Multi-Factor Cross Volatility Integral
  275.      *
  276.      * @param iForwardDate1 Forward Date #1
  277.      * @param iForwardDate2 Forward Date #2
  278.      * @param iTerminalDate The Terminal Date
  279.      *
  280.      * @return The Multi-Factor Cross Volatility Integral
  281.      *
  282.      * @throws java.lang.Exception Thrown if the Multi-Factor Cross Volatility Integral cannot be computed
  283.      */

  284.     public double crossVolatilityIntegralProduct (
  285.         final int iForwardDate1,
  286.         final int iForwardDate2,
  287.         final int iTerminalDate)
  288.         throws java.lang.Exception
  289.     {
  290.         if (iForwardDate1 < iTerminalDate || iForwardDate2 < iTerminalDate)
  291.             throw new java.lang.Exception
  292.                 ("LognormalLIBORVolatility::crossVolatilityIntegralProduct => Invalid Inputs");

  293.         org.drip.function.definition.R1ToR1 crossVolR1ToR1 = new org.drip.function.definition.R1ToR1 (null) {
  294.             @Override public double evaluate (
  295.                 final double dblDate)
  296.                 throws java.lang.Exception
  297.             {
  298.                 double dblCrossVolProduct = 0.;

  299.                 int iNumFactor = msg().numFactor();

  300.                 for (int iFactorIndex = 0; iFactorIndex < iNumFactor; ++iFactorIndex)
  301.                     dblCrossVolProduct += factorPointVolatility (iFactorIndex, (int) dblDate, iForwardDate1)
  302.                         * factorPointVolatility (iFactorIndex, (int) dblDate, iForwardDate2);

  303.                 return dblCrossVolProduct;
  304.             }
  305.         };

  306.         return crossVolR1ToR1.integrate (_iSpotDate, iTerminalDate);
  307.     }
  308. }