LognormalLIBORCurveEvolver.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>LognormalLIBORCurveEvolver</i> sets up and implements the Multi-Factor No-arbitrage Dynamics of the
  80.  * full Curve 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 LognormalLIBORCurveEvolver implements org.drip.dynamics.evolution.CurveStateEvolver {
  109.     private int _iNumForwardTenor = -1;
  110.     private org.drip.state.identifier.ForwardLabel _lslForward = null;
  111.     private org.drip.state.identifier.FundingLabel _lslFunding = null;
  112.     private org.drip.spline.params.SegmentCustomBuilderControl[] _aSCBCLIBOR = null;
  113.     private org.drip.spline.params.SegmentCustomBuilderControl[] _aSCBCDiscountFactor = null;
  114.     private org.drip.spline.params.SegmentCustomBuilderControl[] _aSCBCLIBORIncrement = null;
  115.     private org.drip.spline.params.SegmentCustomBuilderControl[] _aSCBCSpotRateIncrement = null;
  116.     private org.drip.spline.params.SegmentCustomBuilderControl[] _aSCBCDiscountFactorIncrement = null;
  117.     private org.drip.spline.params.SegmentCustomBuilderControl[] _aSCBCContinuousForwardIncrement = null;
  118.     private org.drip.spline.params.SegmentCustomBuilderControl[] _aSCBCInstantaneousNominalForward = null;
  119.     private org.drip.spline.params.SegmentCustomBuilderControl[] _aSCBCInstantaneousEffectiveForward = null;

  120.     /**
  121.      * Create a LognormalLIBORCurveEvolver Instance
  122.      *
  123.      * @param lslFunding The Funding Latent State Label
  124.      * @param lslForward The Forward Latent State Label
  125.      * @param iNumForwardTenor Number of Forward Tenors to Build the Span
  126.      * @param scbc The Common Span Segment Custom Builder Control Instance
  127.      *
  128.      * @return The LognormalLIBORCurveEvolver Instance
  129.      */

  130.     public static final LognormalLIBORCurveEvolver Create (
  131.         final org.drip.state.identifier.FundingLabel lslFunding,
  132.         final org.drip.state.identifier.ForwardLabel lslForward,
  133.         final int iNumForwardTenor,
  134.         final org.drip.spline.params.SegmentCustomBuilderControl scbc)
  135.     {
  136.         try {
  137.             return new LognormalLIBORCurveEvolver (lslFunding, lslForward, iNumForwardTenor, scbc, scbc,
  138.                 scbc, scbc, scbc, scbc, scbc, scbc);
  139.         } catch (java.lang.Exception e) {
  140.             e.printStackTrace();
  141.         }

  142.         return null;
  143.     }

  144.     private double forwardDerivative (
  145.         final org.drip.state.forward.ForwardCurve fc,
  146.         final int iTargetPointDate)
  147.         throws java.lang.Exception
  148.     {
  149.         org.drip.function.definition.R1ToR1 freR1ToR1 = new org.drip.function.definition.R1ToR1 (null) {
  150.             @Override public double evaluate (
  151.                 final double dblDate)
  152.                 throws java.lang.Exception
  153.             {
  154.                 return fc.forward ((int) dblDate);
  155.             }
  156.         };

  157.         return freR1ToR1.derivative (iTargetPointDate, 1);
  158.     }

  159.     private double continuousForwardRateIncrement (
  160.         final int iViewDate,
  161.         final double dblAnnualizedIncrement,
  162.         final double dblAnnualizedIncrementSQRT,
  163.         final org.drip.state.forward.ForwardCurve fc,
  164.         final double[] adblMultivariateRandom,
  165.         final org.drip.dynamics.lmm.LognormalLIBORVolatility llv)
  166.         throws java.lang.Exception
  167.     {
  168.         final int iNumFactor = adblMultivariateRandom.length;

  169.         org.drip.function.definition.R1ToR1 continuousForwardRateR1ToR1 = new
  170.             org.drip.function.definition.R1ToR1 (null) {
  171.             @Override public double evaluate (
  172.                 final double dblDate)
  173.                 throws java.lang.Exception
  174.             {
  175.                 double dblForwardPointVolatilityModulus = 0.;
  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.                         dblForwardPointVolatilityModulus += adblContinuousForwardVolatility[i] *
  182.                             adblContinuousForwardVolatility[i];
  183.                         dblPointVolatilityMultifactorRandom += adblContinuousForwardVolatility[i] *
  184.                             adblMultivariateRandom[i];
  185.                     }
  186.                 }

  187.                 return (fc.forward ((int) dblDate) + 0.5 * dblForwardPointVolatilityModulus) *
  188.                     dblAnnualizedIncrement + dblPointVolatilityMultifactorRandom *
  189.                         dblAnnualizedIncrementSQRT;
  190.             }
  191.         };

  192.         return continuousForwardRateR1ToR1.derivative (iViewDate, 1);
  193.     }

  194.     private double spotRateIncrement (
  195.         final int iViewDate,
  196.         final double dblAnnualizedIncrement,
  197.         final double dblAnnualizedIncrementSQRT,
  198.         final org.drip.state.discount.MergedDiscountForwardCurve dc,
  199.         final double[] adblMultivariateRandom,
  200.         final org.drip.dynamics.lmm.LognormalLIBORVolatility llv)
  201.         throws java.lang.Exception
  202.     {
  203.         final int iNumFactor = adblMultivariateRandom.length;

  204.         org.drip.function.definition.R1ToR1 spotRateR1ToR1 = new org.drip.function.definition.R1ToR1 (null) {
  205.             @Override public double evaluate (
  206.                 final double dblDate)
  207.                 throws java.lang.Exception
  208.             {
  209.                 int iDate = (int) dblDate;
  210.                 double dblPointVolatilityMultifactorRandom = 0.;

  211.                 double[] adblContinuousForwardVolatility = llv.continuousForwardVolatility (iDate, dc);

  212.                 if (null != adblContinuousForwardVolatility) {
  213.                     for (int i = 0; i < iNumFactor; ++i)
  214.                         dblPointVolatilityMultifactorRandom += adblContinuousForwardVolatility[i] *
  215.                             adblMultivariateRandom[i];
  216.                 }

  217.                 return dc.forward (iDate, iDate + 1) * dblAnnualizedIncrement +
  218.                     dblPointVolatilityMultifactorRandom * dblAnnualizedIncrementSQRT;
  219.             }
  220.         };

  221.         return spotRateR1ToR1.derivative (iViewDate, 1);
  222.     }

  223.     private org.drip.dynamics.lmm.BGMForwardTenorSnap timeSnap (
  224.         final int iSpotDate,
  225.         final int iTargetPointDate,
  226.         final double dblAnnualizedIncrement,
  227.         final double dblAnnualizedIncrementSQRT,
  228.         final java.lang.String strForwardTenor,
  229.         final org.drip.state.forward.ForwardCurve fc,
  230.         final org.drip.state.discount.MergedDiscountForwardCurve dc,
  231.         final org.drip.dynamics.lmm.LognormalLIBORVolatility llv)
  232.     {
  233.         double[] adblLognormalFactorPointVolatility = llv.factorPointVolatility (iSpotDate,
  234.             iTargetPointDate);

  235.         double[] adblContinuousForwardVolatility = llv.continuousForwardVolatility (iTargetPointDate, fc);

  236.         double[] adblMultivariateRandom = llv.msg().random();

  237.         double dblCrossVolatilityDotProduct = 0.;
  238.         double dblLognormalPointVolatilityModulus = 0.;
  239.         double dblLIBORVolatilityMultiFactorRandom = 0.;
  240.         double dblContinuousForwardVolatilityModulus = 0.;
  241.         double dblForwardVolatilityMultiFactorRandom = 0.;
  242.         int iNumFactor = adblLognormalFactorPointVolatility.length;

  243.         for (int i = 0; i < iNumFactor; ++i) {
  244.             dblLognormalPointVolatilityModulus += adblLognormalFactorPointVolatility[i] *
  245.                 adblLognormalFactorPointVolatility[i];
  246.             dblCrossVolatilityDotProduct += adblLognormalFactorPointVolatility[i] *
  247.                 adblContinuousForwardVolatility[i];
  248.             dblLIBORVolatilityMultiFactorRandom += adblLognormalFactorPointVolatility[i] *
  249.                 adblMultivariateRandom[i] * dblAnnualizedIncrementSQRT;
  250.             dblContinuousForwardVolatilityModulus += adblContinuousForwardVolatility[i] *
  251.                 adblContinuousForwardVolatility[i];
  252.             dblForwardVolatilityMultiFactorRandom += adblContinuousForwardVolatility[i] *
  253.                 adblMultivariateRandom[i] * dblAnnualizedIncrementSQRT;
  254.         }

  255.         try {
  256.             double dblLIBOR = fc.forward (iTargetPointDate);

  257.             double dblDiscountFactor = dc.df (iTargetPointDate);

  258.             double dblSpotRate = dc.forward (iSpotDate, iSpotDate + 1);

  259.             double dblContinuousForwardRate = fc.forward (iTargetPointDate);

  260.             double dblDCF = org.drip.analytics.support.Helper.TenorToYearFraction (strForwardTenor);

  261.             double dblLIBORDCF = dblDCF * dblLIBOR;

  262.             double dblLIBORIncrement = dblAnnualizedIncrement * (forwardDerivative (fc, iTargetPointDate) +
  263.                 dblLIBOR * dblCrossVolatilityDotProduct + (dblLognormalPointVolatilityModulus * dblLIBOR *
  264.                     dblLIBORDCF / (1. + dblLIBORDCF))) + dblLIBOR * dblLIBORVolatilityMultiFactorRandom;

  265.             double dblDiscountFactorIncrement = dblDiscountFactor * (dblSpotRate - dblContinuousForwardRate)
  266.                 * dblAnnualizedIncrement - dblForwardVolatilityMultiFactorRandom;

  267.             double dblContinuousForwardRateIncrement = continuousForwardRateIncrement (iTargetPointDate,
  268.                 dblAnnualizedIncrement, dblAnnualizedIncrementSQRT, fc, adblMultivariateRandom, llv);

  269.             double dblSpotRateIncrement = spotRateIncrement (iTargetPointDate, dblAnnualizedIncrement,
  270.                 dblAnnualizedIncrementSQRT, dc, adblMultivariateRandom, llv);

  271.             double dblContinuousForwardRateEvolved = dblContinuousForwardRate +
  272.                 dblContinuousForwardRateIncrement;

  273.             return new org.drip.dynamics.lmm.BGMForwardTenorSnap (iTargetPointDate, dblLIBOR +
  274.                 dblLIBORIncrement, dblLIBORIncrement, dblDiscountFactor + dblDiscountFactorIncrement,
  275.                     dblDiscountFactorIncrement, dblContinuousForwardRateIncrement, dblSpotRateIncrement,
  276.                         java.lang.Math.exp (dblContinuousForwardRateEvolved) - 1., (java.lang.Math.exp
  277.                             (dblDCF * dblContinuousForwardRateEvolved) - 1.) / dblDCF, java.lang.Math.sqrt
  278.                                 (dblLognormalPointVolatilityModulus), java.lang.Math.sqrt
  279.                                     (dblContinuousForwardVolatilityModulus));
  280.         } catch (java.lang.Exception e) {
  281.             e.printStackTrace();
  282.         }

  283.         return null;
  284.     }

  285.     private org.drip.dynamics.lmm.PathwiseQMRealization simulateLIBOR (
  286.         final int iEvolutionDate,
  287.         final int iViewDate,
  288.         final double dblAnnualizedIncrement,
  289.         final double dblAnnualizedIncrementSQRT,
  290.         final org.drip.state.forward.ForwardCurve fc,
  291.         final java.lang.String strForwardTenor,
  292.         final double dblForwardDCF,
  293.         final org.drip.dynamics.lmm.LognormalLIBORVolatility llv)
  294.     {
  295.         int[] aiTenorDate = new int[_iNumForwardTenor + 1];
  296.         double[] adblLIBOR = new double[_iNumForwardTenor + 1];

  297.         double[] adblMultivariateRandom = llv.msg().random();

  298.         org.drip.analytics.date.JulianDate dtTargetPoint = new org.drip.analytics.date.JulianDate
  299.             (iViewDate);

  300.         try {
  301.             for (int i = 0; i <= _iNumForwardTenor; ++i) {
  302.                 int iTargetPointDate = dtTargetPoint.julian();

  303.                 double[] adblLognormalFactorPointVolatility = llv.factorPointVolatility (iEvolutionDate,
  304.                     iTargetPointDate);

  305.                 double[] adblContinuousForwardVolatility = llv.continuousForwardVolatility (iTargetPointDate,
  306.                     fc);

  307.                 double dblLIBOR = fc.forward (iTargetPointDate);

  308.                 aiTenorDate[i] = iTargetPointDate;
  309.                 double dblCrossVolatilityDotProduct = 0.;
  310.                 double dblLIBORDCF = dblForwardDCF * dblLIBOR;
  311.                 double dblLognormalPointVolatilityModulus = 0.;
  312.                 double dblLIBORVolatilityMultiFactorRandom = 0.;
  313.                 int iNumFactor = adblLognormalFactorPointVolatility.length;

  314.                 for (int j = 0; j < iNumFactor; ++j) {
  315.                     dblLognormalPointVolatilityModulus += adblLognormalFactorPointVolatility[j] *
  316.                         adblLognormalFactorPointVolatility[j];
  317.                     dblCrossVolatilityDotProduct += adblLognormalFactorPointVolatility[j] *
  318.                         adblContinuousForwardVolatility[j];
  319.                     dblLIBORVolatilityMultiFactorRandom += adblLognormalFactorPointVolatility[j] *
  320.                         adblMultivariateRandom[j] * dblAnnualizedIncrementSQRT;
  321.                 }

  322.                 adblLIBOR[i] = dblLIBOR + dblAnnualizedIncrement * (forwardDerivative (fc, iTargetPointDate)
  323.                     + dblLIBOR * dblCrossVolatilityDotProduct + (dblLognormalPointVolatilityModulus *
  324.                         dblLIBOR * dblLIBORDCF / (1. + dblLIBORDCF))) + dblLIBOR *
  325.                             dblLIBORVolatilityMultiFactorRandom;

  326.                 dtTargetPoint = dtTargetPoint.addTenor (strForwardTenor);
  327.             }

  328.             return new org.drip.dynamics.lmm.PathwiseQMRealization (aiTenorDate, adblLIBOR);
  329.         } catch (java.lang.Exception e) {
  330.             e.printStackTrace();
  331.         }

  332.         return null;
  333.     }

  334.     /**
  335.      * LognormalLIBORCurveEvolver Constructor
  336.      *
  337.      * @param lslFunding The Funding Latent State Label
  338.      * @param lslForward The Forward Latent State Label
  339.      * @param iNumForwardTenor Number of Forward Tenors to Build the Span
  340.      * @param scbcLIBOR LIBOR Span Segment Custom Builder Control Instance
  341.      * @param scbcDiscountFactor Discount Factor Span Segment Custom Builder Control Instance
  342.      * @param scbcLIBORIncrement LIBOR Increment Span Segment Custom Builder Control Instance
  343.      * @param scbcDiscountFactorIncrement Discount Factor Increment Span Segment Custom Builder Control
  344.      *      Instance
  345.      * @param scbcContinuousForwardIncrement Instantaneous Continuously Compounded Forward Rate Increment
  346.      *      Span Segment Custom Builder Control Instance
  347.      * @param scbcSpotRateIncrement Spot Rate Increment Span Segment Custom Builder Control Instance
  348.      * @param scbcInstantaneousEffectiveForward Instantaneous Effective Annual Forward Rate Span Segment
  349.      *      Custom Builder Control Instance
  350.      * @param scbcInstantaneousNominalForward Instantaneous Nominal Annual Forward Rate Span Segment Custom
  351.      *      Builder Control Instance
  352.      *
  353.      * @throws java.lang.Exception Thrown if Inputs are Invalid
  354.      */

  355.     public LognormalLIBORCurveEvolver (
  356.         final org.drip.state.identifier.FundingLabel lslFunding,
  357.         final org.drip.state.identifier.ForwardLabel lslForward,
  358.         final int iNumForwardTenor,
  359.         final org.drip.spline.params.SegmentCustomBuilderControl scbcLIBOR,
  360.         final org.drip.spline.params.SegmentCustomBuilderControl scbcDiscountFactor,
  361.         final org.drip.spline.params.SegmentCustomBuilderControl scbcLIBORIncrement,
  362.         final org.drip.spline.params.SegmentCustomBuilderControl scbcDiscountFactorIncrement,
  363.         final org.drip.spline.params.SegmentCustomBuilderControl scbcContinuousForwardIncrement,
  364.         final org.drip.spline.params.SegmentCustomBuilderControl scbcSpotRateIncrement,
  365.         final org.drip.spline.params.SegmentCustomBuilderControl scbcInstantaneousEffectiveForward,
  366.         final org.drip.spline.params.SegmentCustomBuilderControl scbcInstantaneousNominalForward)
  367.         throws java.lang.Exception
  368.     {
  369.         if (null == (_lslFunding = lslFunding) || null == (_lslForward = lslForward) || 1 >=
  370.             (_iNumForwardTenor = iNumForwardTenor) || null == scbcLIBOR || null == scbcLIBORIncrement || null
  371.                 == scbcDiscountFactor || null == scbcDiscountFactorIncrement || null ==
  372.                     scbcContinuousForwardIncrement || null == scbcSpotRateIncrement || null ==
  373.                         scbcInstantaneousEffectiveForward)
  374.             throw new java.lang.Exception ("LognormalLIBORCurveEvolver ctr: Invalid Inputs");

  375.         _aSCBCLIBOR = new org.drip.spline.params.SegmentCustomBuilderControl[iNumForwardTenor];
  376.         _aSCBCDiscountFactor = new org.drip.spline.params.SegmentCustomBuilderControl[iNumForwardTenor];
  377.         _aSCBCLIBORIncrement = new org.drip.spline.params.SegmentCustomBuilderControl[iNumForwardTenor];
  378.         _aSCBCDiscountFactorIncrement = new
  379.             org.drip.spline.params.SegmentCustomBuilderControl[iNumForwardTenor];
  380.         _aSCBCContinuousForwardIncrement = new
  381.             org.drip.spline.params.SegmentCustomBuilderControl[iNumForwardTenor];
  382.         _aSCBCSpotRateIncrement = new org.drip.spline.params.SegmentCustomBuilderControl[iNumForwardTenor];
  383.         _aSCBCInstantaneousNominalForward = new
  384.             org.drip.spline.params.SegmentCustomBuilderControl[iNumForwardTenor];
  385.         _aSCBCInstantaneousEffectiveForward = new
  386.             org.drip.spline.params.SegmentCustomBuilderControl[iNumForwardTenor];

  387.         for (int i = 0; i < iNumForwardTenor; ++i) {
  388.             _aSCBCLIBOR[i] = scbcLIBOR;
  389.             _aSCBCDiscountFactor[i] = scbcDiscountFactor;
  390.             _aSCBCLIBORIncrement[i] = scbcLIBORIncrement;
  391.             _aSCBCDiscountFactorIncrement[i] = scbcDiscountFactorIncrement;
  392.             _aSCBCContinuousForwardIncrement[i] = scbcContinuousForwardIncrement;
  393.             _aSCBCSpotRateIncrement[i] = scbcSpotRateIncrement;
  394.             _aSCBCInstantaneousEffectiveForward[i] = scbcInstantaneousEffectiveForward;
  395.             _aSCBCInstantaneousNominalForward[i] = scbcInstantaneousNominalForward;
  396.         }
  397.     }

  398.     /**
  399.      * Retrieve the Funding Label
  400.      *
  401.      * @return The Funding Label
  402.      */

  403.     public org.drip.state.identifier.FundingLabel fundingLabel()
  404.     {
  405.         return _lslFunding;
  406.     }

  407.     /**
  408.      * Retrieve the Forward Label
  409.      *
  410.      * @return The Forward Label
  411.      */

  412.     public org.drip.state.identifier.ForwardLabel forwardLabel()
  413.     {
  414.         return _lslForward;
  415.     }

  416.     /**
  417.      * Retrieve the Number of Forward Tenors comprising the Span Tenor
  418.      *
  419.      * @return Number of Forward Tenors comprising the Span Tenor
  420.      */

  421.     public int spanTenor()
  422.     {
  423.         return _iNumForwardTenor;
  424.     }

  425.     /**
  426.      * Retrieve the LIBOR Curve Segment Custom Builder Control Instance
  427.      *
  428.      * @return The LIBOR Curve Segment Custom Builder Control Instance
  429.      */

  430.     public org.drip.spline.params.SegmentCustomBuilderControl scbcLIBOR()
  431.     {
  432.         return _aSCBCLIBOR[0];
  433.     }

  434.     /**
  435.      * Retrieve the Discount Factor Segment Custom Builder Control Instance
  436.      *
  437.      * @return The Discount Factor Segment Custom Builder Control Instance
  438.      */

  439.     public org.drip.spline.params.SegmentCustomBuilderControl scbcDiscountFactor()
  440.     {
  441.         return _aSCBCDiscountFactor[0];
  442.     }

  443.     /**
  444.      * Retrieve the LIBOR Increment Segment Custom Builder Control Instance
  445.      *
  446.      * @return The LIBOR Increment Segment Custom Builder Control Instance
  447.      */

  448.     public org.drip.spline.params.SegmentCustomBuilderControl scbcLIBORIncrement()
  449.     {
  450.         return _aSCBCLIBORIncrement[0];
  451.     }

  452.     /**
  453.      * Retrieve the Discount Factor Increment Segment Custom Builder Control Instance
  454.      *
  455.      * @return The Discount Factor Increment Segment Custom Builder Control Instance
  456.      */

  457.     public org.drip.spline.params.SegmentCustomBuilderControl scbcDiscountFactorIncrement()
  458.     {
  459.         return _aSCBCDiscountFactorIncrement[0];
  460.     }

  461.     /**
  462.      * Retrieve the Instantaneous Continuously Compounded Forward Rate Increment Segment Custom Builder
  463.      *  Control Instance
  464.      *
  465.      * @return The Instantaneous Continuously Compounded Forward Rate Increment Segment Custom Builder
  466.      *  Control Instance
  467.      */

  468.     public org.drip.spline.params.SegmentCustomBuilderControl scbcContinuousForwardIncrement()
  469.     {
  470.         return _aSCBCContinuousForwardIncrement[0];
  471.     }

  472.     /**
  473.      * Retrieve the Spot Rate Increment Segment Custom Builder Control Instance
  474.      *
  475.      * @return The Spot Rate Increment Segment Custom Builder Control Instance
  476.      */

  477.     public org.drip.spline.params.SegmentCustomBuilderControl scbcSpotRateIncrement()
  478.     {
  479.         return _aSCBCSpotRateIncrement[0];
  480.     }

  481.     /**
  482.      * Retrieve the Instantaneous Effective Annual Forward Rate Increment Segment Custom Builder Control
  483.      *  Instance
  484.      *
  485.      * @return The Instantaneous Effective Annual Forward Rate Increment Segment Custom Builder Control
  486.      *  Instance
  487.      */

  488.     public org.drip.spline.params.SegmentCustomBuilderControl scbcInstantaneousEffectiveForward()
  489.     {
  490.         return _aSCBCInstantaneousEffectiveForward[0];
  491.     }

  492.     /**
  493.      * Retrieve the Instantaneous Nominal Annual Forward Rate Increment Segment Custom Builder Control
  494.      *  Instance
  495.      *
  496.      * @return The Instantaneous Nominal Annual Forward Rate Increment Segment Custom Builder Control
  497.      *  Instance
  498.      */

  499.     public org.drip.spline.params.SegmentCustomBuilderControl scbcInstantaneousNominalForward()
  500.     {
  501.         return _aSCBCInstantaneousNominalForward[0];
  502.     }

  503.     @Override public org.drip.dynamics.lmm.BGMCurveUpdate evolve (
  504.         final int iSpotDate,
  505.         final int iViewDate,
  506.         final int iSpotTimeIncrement,
  507.         final org.drip.dynamics.evolution.LSQMCurveUpdate lsqmPrev)
  508.     {
  509.         if (iSpotDate > iViewDate || null == lsqmPrev || !(lsqmPrev instanceof
  510.             org.drip.dynamics.lmm.BGMCurveUpdate))
  511.             return null;

  512.         org.drip.dynamics.lmm.BGMCurveUpdate bgmPrev = (org.drip.dynamics.lmm.BGMCurveUpdate) lsqmPrev;
  513.         org.drip.dynamics.lmm.BGMForwardTenorSnap[] aBGMTS = new
  514.             org.drip.dynamics.lmm.BGMForwardTenorSnap[_iNumForwardTenor + 1];
  515.         double dblAnnualizedIncrement = 1. * iSpotTimeIncrement / 365.25;

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

  517.         org.drip.state.forward.ForwardCurve fc = bgmPrev.forwardCurve();

  518.         org.drip.state.discount.MergedDiscountForwardCurve dc = bgmPrev.discountCurve();

  519.         org.drip.dynamics.lmm.LognormalLIBORVolatility llv = bgmPrev.lognormalLIBORVolatility();

  520.         java.lang.String strForwardTenor = _lslForward.tenor();

  521.         org.drip.analytics.date.JulianDate dtTargetPoint = new org.drip.analytics.date.JulianDate
  522.             (iViewDate);

  523.         try {
  524.             for (int i = 0; i <= _iNumForwardTenor; ++i) {
  525.                 if (null == (aBGMTS[i] = timeSnap (iSpotDate, dtTargetPoint.julian(), iSpotTimeIncrement,
  526.                     dblAnnualizedIncrementSQRT, strForwardTenor, fc, dc, llv)) || null == (dtTargetPoint =
  527.                         dtTargetPoint.addTenor (strForwardTenor)))
  528.                     return null;
  529.             }

  530.             org.drip.dynamics.lmm.BGMTenorNodeSequence btns = new org.drip.dynamics.lmm.BGMTenorNodeSequence
  531.                 (aBGMTS);

  532.             org.drip.spline.stretch.BoundarySettings bs =
  533.                 org.drip.spline.stretch.BoundarySettings.NaturalStandard();

  534.             java.lang.String strForwardLabelName = _lslForward.fullyQualifiedName();

  535.             java.lang.String strFundingLabelName = _lslFunding.fullyQualifiedName();

  536.             int[] aiTenorDate = btns.dates();

  537.             org.drip.state.curve.BasisSplineForwardRate fcLIBOR = new
  538.                 org.drip.state.curve.BasisSplineForwardRate (_lslForward, new
  539.                     org.drip.spline.grid.OverlappingStretchSpan
  540.                         (org.drip.spline.stretch.MultiSegmentSequenceBuilder.CreateCalibratedStretchEstimator
  541.                             (strForwardLabelName + "_QM_LIBOR", aiTenorDate, btns.liborRates(), _aSCBCLIBOR,
  542.                                 null, bs, org.drip.spline.stretch.MultiSegmentSequence.CALIBRATE)));

  543.             org.drip.state.curve.DiscountFactorDiscountCurve dcDiscountFactor = new
  544.                 org.drip.state.curve.DiscountFactorDiscountCurve (_lslForward.currency(), new
  545.                     org.drip.spline.grid.OverlappingStretchSpan
  546.                         (org.drip.spline.stretch.MultiSegmentSequenceBuilder.CreateCalibratedStretchEstimator
  547.                             (strFundingLabelName + "_QM_DISCOUNTFACTOR", aiTenorDate, btns.discountFactors(),
  548.                                 _aSCBCDiscountFactor, null, bs,
  549.                                     org.drip.spline.stretch.MultiSegmentSequence.CALIBRATE)));

  550.             org.drip.spline.stretch.MultiSegmentSequence mssDiscountFactorIncrement =
  551.                 org.drip.spline.stretch.MultiSegmentSequenceBuilder.CreateCalibratedStretchEstimator
  552.                     (strFundingLabelName + "_INCREMENT", aiTenorDate, btns.discountFactorIncrements(),
  553.                         _aSCBCDiscountFactorIncrement, null, bs,
  554.                             org.drip.spline.stretch.MultiSegmentSequence.CALIBRATE);

  555.             org.drip.spline.stretch.MultiSegmentSequence mssContinuousForwardRateIncrement =
  556.                 org.drip.spline.stretch.MultiSegmentSequenceBuilder.CreateCalibratedStretchEstimator
  557.                     (strForwardLabelName + "_CONT_FWD_INCREMENT", aiTenorDate,
  558.                         btns.continuousForwardRateIncrements(), _aSCBCContinuousForwardIncrement, null, bs,
  559.                             org.drip.spline.stretch.MultiSegmentSequence.CALIBRATE);

  560.             org.drip.spline.stretch.MultiSegmentSequence mssSpotRateIncrement =
  561.                 org.drip.spline.stretch.MultiSegmentSequenceBuilder.CreateCalibratedStretchEstimator
  562.                     (strForwardLabelName + "_SPOT_RATE_INCREMENT", aiTenorDate, btns.spotRateIncrements(),
  563.                         _aSCBCSpotRateIncrement, null, bs,
  564.                             org.drip.spline.stretch.MultiSegmentSequence.CALIBRATE);

  565.             org.drip.spline.stretch.MultiSegmentSequence mssInstantaneousEffectiveForwardRate =
  566.                 org.drip.spline.stretch.MultiSegmentSequenceBuilder.CreateCalibratedStretchEstimator
  567.                     (strForwardLabelName + "_EFFECTIVE_ANNUAL_FORWARD", aiTenorDate,
  568.                         btns.instantaneousEffectiveForwardRates(), _aSCBCInstantaneousEffectiveForward, null,
  569.                             bs, org.drip.spline.stretch.MultiSegmentSequence.CALIBRATE);

  570.             org.drip.spline.stretch.MultiSegmentSequence mssInstantaneousNominalForwardRate =
  571.                 org.drip.spline.stretch.MultiSegmentSequenceBuilder.CreateCalibratedStretchEstimator
  572.                     (strForwardLabelName + "_NOMINAL_ANNUAL_FORWARD", aiTenorDate,
  573.                         btns.instantaneousNominalForwardRates(), _aSCBCInstantaneousNominalForward, null, bs,
  574.                             org.drip.spline.stretch.MultiSegmentSequence.CALIBRATE);

  575.             return org.drip.dynamics.lmm.BGMCurveUpdate.Create (_lslFunding, _lslForward, iSpotDate,
  576.                 iSpotDate + iSpotTimeIncrement, fcLIBOR, new org.drip.spline.grid.OverlappingStretchSpan
  577.                     (org.drip.spline.stretch.MultiSegmentSequenceBuilder.CreateCalibratedStretchEstimator
  578.                         (strForwardLabelName + "_INCREMENT", aiTenorDate, btns.liborRateIncrements(),
  579.                             _aSCBCLIBORIncrement, null, bs,
  580.                                 org.drip.spline.stretch.MultiSegmentSequence.CALIBRATE)), dcDiscountFactor,
  581.                                     new org.drip.spline.grid.OverlappingStretchSpan
  582.                                         (mssDiscountFactorIncrement), new
  583.                                             org.drip.spline.grid.OverlappingStretchSpan
  584.                                                 (mssContinuousForwardRateIncrement), new
  585.                                                     org.drip.spline.grid.OverlappingStretchSpan
  586.                                                         (mssSpotRateIncrement), new
  587.                                                             org.drip.spline.grid.OverlappingStretchSpan
  588.                                                                 (mssInstantaneousEffectiveForwardRate), new
  589.                                                                     org.drip.spline.grid.OverlappingStretchSpan
  590.                 (mssInstantaneousNominalForwardRate), bgmPrev.lognormalLIBORVolatility());
  591.         } catch (java.lang.Exception e) {
  592.             e.printStackTrace();
  593.         }

  594.         return null;
  595.     }

  596.     @Override public double[][] simulatePrincipalMetric (
  597.         final int iEvolutionStartDate,
  598.         final int iEvolutionFinishDate,
  599.         final int iEvolutionIncrement,
  600.         final int iViewDate,
  601.         final org.drip.dynamics.evolution.LSQMCurveUpdate lsqmStart,
  602.         final int iNumSimulation)
  603.     {
  604.         if (iEvolutionStartDate > iViewDate || iEvolutionFinishDate <= iEvolutionStartDate ||
  605.             iEvolutionFinishDate > iViewDate || iEvolutionIncrement <= 0. || null == lsqmStart || !(lsqmStart
  606.                 instanceof org.drip.dynamics.lmm.BGMCurveUpdate) || 1 >= iNumSimulation)
  607.             return null;

  608.         org.drip.dynamics.lmm.BGMCurveUpdate bgmMetrics = (org.drip.dynamics.lmm.BGMCurveUpdate) lsqmStart;

  609.         org.drip.dynamics.lmm.LognormalLIBORVolatility llv = bgmMetrics.lognormalLIBORVolatility();

  610.         java.lang.String strForwardLabel = _lslForward.fullyQualifiedName() + "_QM_LIBOR";

  611.         org.drip.state.forward.ForwardCurve fc = bgmMetrics.forwardCurve();

  612.         java.lang.String strForwardTenor = _lslForward.tenor();

  613.         int iNumTimeStep = ((iEvolutionFinishDate - iEvolutionStartDate) / iEvolutionIncrement) + 1;
  614.         double[][] aadblTenorLIBOR = new double[iNumTimeStep][_iNumForwardTenor + 1];
  615.         double dblAnnualizedIncrement = 1. * iEvolutionIncrement / 365.25;
  616.         double dblForwardDCF = java.lang.Double.NaN;

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

  618.         org.drip.spline.stretch.BoundarySettings bs =
  619.             org.drip.spline.stretch.BoundarySettings.NaturalStandard();

  620.         try {
  621.             dblForwardDCF = org.drip.analytics.support.Helper.TenorToYearFraction (strForwardTenor);
  622.         } catch (java.lang.Exception e) {
  623.             e.printStackTrace();

  624.             return null;
  625.         }

  626.         for (int i = 0 ; i < iNumTimeStep; ++i) {
  627.             for (int j = 0 ; j <= _iNumForwardTenor; ++j)
  628.                 aadblTenorLIBOR[i][j] = 0.;
  629.         }

  630.         for (int iSimulationIndex = 0; iSimulationIndex < iNumSimulation; ++iSimulationIndex) {
  631.             int iEvolutionTimeIndex = 0;
  632.             org.drip.state.forward.ForwardCurve fcLIBOR = fc;

  633.             for (int iEvolutionDate = iEvolutionStartDate; iEvolutionDate <= iEvolutionFinishDate;
  634.                 iEvolutionDate += iEvolutionIncrement) {
  635.                 org.drip.dynamics.lmm.PathwiseQMRealization pqmr = simulateLIBOR (iEvolutionDate, iViewDate,
  636.                     dblAnnualizedIncrement, dblAnnualizedIncrementSQRT, fcLIBOR, strForwardTenor,
  637.                         dblForwardDCF, llv);

  638.                 if (null == pqmr) return null;

  639.                 double[] adblSimulatedLIBOR = pqmr.realizedQM();

  640.                 try {
  641.                     fcLIBOR = new org.drip.state.curve.BasisSplineForwardRate (_lslForward, new
  642.                         org.drip.spline.grid.OverlappingStretchSpan
  643.                             (org.drip.spline.stretch.MultiSegmentSequenceBuilder.CreateCalibratedStretchEstimator
  644.                         (strForwardLabel + "_QM_LIBOR", pqmr.targetDate(), adblSimulatedLIBOR, _aSCBCLIBOR,
  645.                             null, bs, org.drip.spline.stretch.MultiSegmentSequence.CALIBRATE)));
  646.                 } catch (java.lang.Exception e) {
  647.                     e.printStackTrace();

  648.                     return null;
  649.                 }

  650.                 for (int j = 0 ; j <= _iNumForwardTenor; ++j)
  651.                     aadblTenorLIBOR[iEvolutionTimeIndex][j] += adblSimulatedLIBOR[j];

  652.                 iEvolutionTimeIndex++;
  653.             }
  654.         }

  655.         for (int i = 0 ; i < iNumTimeStep; ++i) {
  656.             for (int j = 0 ; j <= _iNumForwardTenor; ++j)
  657.                 aadblTenorLIBOR[i][j] /= iNumSimulation;
  658.         }

  659.         return aadblTenorLIBOR;
  660.     }

  661.     /**
  662.      * Construct an Array of Forward Curves that Result from the Simulation
  663.      *
  664.      * @param iEvolutionStartDate The Start Date of the Simulation
  665.      * @param iEvolutionFinishDate The Finish Date of the Simulation
  666.      * @param iEvolutionIncrement The Simulation Evolution Increment
  667.      * @param iViewDate The Forward View Date
  668.      * @param lsqmStart The Initial/Starting LSQM State
  669.      * @param iNumSimulation Number of Simulations
  670.      *
  671.      * @return The Array of Forward Curves that Result from the Simulation
  672.      */

  673.     public org.drip.state.forward.ForwardCurve[] simulateTerminalLatentState (
  674.         final int iEvolutionStartDate,
  675.         final int iEvolutionFinishDate,
  676.         final int iEvolutionIncrement,
  677.         final int iViewDate,
  678.         final org.drip.dynamics.evolution.LSQMCurveUpdate lsqmStart,
  679.         final int iNumSimulation)
  680.     {
  681.         if (iEvolutionStartDate > iViewDate || iEvolutionFinishDate <= iEvolutionStartDate ||
  682.             iEvolutionFinishDate > iViewDate || iEvolutionIncrement <= 0. || null == lsqmStart || !(lsqmStart
  683.                 instanceof org.drip.dynamics.lmm.BGMCurveUpdate) || 1 >= iNumSimulation)
  684.             return null;

  685.         org.drip.dynamics.lmm.BGMCurveUpdate bgmMetrics = (org.drip.dynamics.lmm.BGMCurveUpdate) lsqmStart;

  686.         org.drip.dynamics.lmm.LognormalLIBORVolatility llv = bgmMetrics.lognormalLIBORVolatility();

  687.         java.lang.String strForwardLabel = _lslForward.fullyQualifiedName() + "_QM_LIBOR";

  688.         org.drip.state.forward.ForwardCurve fc = bgmMetrics.forwardCurve();

  689.         java.lang.String strForwardTenor = _lslForward.tenor();

  690.         org.drip.state.forward.ForwardCurve[] aFCLIBOR = new
  691.             org.drip.state.forward.ForwardCurve[iNumSimulation];
  692.         double dblAnnualizedIncrement = 1. * iEvolutionIncrement / 365.25;
  693.         double dblForwardDCF = java.lang.Double.NaN;

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

  695.         org.drip.spline.stretch.BoundarySettings bs =
  696.             org.drip.spline.stretch.BoundarySettings.NaturalStandard();

  697.         try {
  698.             dblForwardDCF = org.drip.analytics.support.Helper.TenorToYearFraction (strForwardTenor);
  699.         } catch (java.lang.Exception e) {
  700.             e.printStackTrace();

  701.             return null;
  702.         }

  703.         for (int iSimulationIndex = 0; iSimulationIndex < iNumSimulation; ++iSimulationIndex) {
  704.             System.out.println ("\t\tSimulation #" + (iSimulationIndex + 1));

  705.             org.drip.state.forward.ForwardCurve fcLIBOR = fc;

  706.             for (int iEvolutionDate = iEvolutionStartDate; iEvolutionDate <= iEvolutionFinishDate;
  707.                 iEvolutionDate += iEvolutionIncrement) {
  708.                 org.drip.dynamics.lmm.PathwiseQMRealization pqmr = simulateLIBOR (iEvolutionDate, iViewDate,
  709.                     dblAnnualizedIncrement, dblAnnualizedIncrementSQRT, fcLIBOR, strForwardTenor,
  710.                         dblForwardDCF, llv);

  711.                 if (null == pqmr) return null;

  712.                 try {
  713.                     fcLIBOR = new org.drip.state.curve.BasisSplineForwardRate (_lslForward, new
  714.                         org.drip.spline.grid.OverlappingStretchSpan
  715.                             (org.drip.spline.stretch.MultiSegmentSequenceBuilder.CreateCalibratedStretchEstimator
  716.                         (strForwardLabel + "_QM_LIBOR", pqmr.targetDate(), pqmr.realizedQM(), _aSCBCLIBOR,
  717.                             null, bs, org.drip.spline.stretch.MultiSegmentSequence.CALIBRATE)));
  718.                 } catch (java.lang.Exception e) {
  719.                     e.printStackTrace();

  720.                     return null;
  721.                 }
  722.             }

  723.             aFCLIBOR[iSimulationIndex] = fcLIBOR;
  724.         }

  725.         return aFCLIBOR;
  726.     }
  727. }