MergedDiscountForwardCurve.java

  1. package org.drip.state.discount;

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

  80. /**
  81.  * <i>MergedDiscountForwardCurve</i> is the Stub for the Merged Discount and Forward Curve Functionality. It
  82.  * extends the both the Curve and the DiscountFactorEstimator instances by implementing their functions, and
  83.  * exposing the following:
  84.  *
  85.  *  <br><br>
  86.  *  <ul>
  87.  *      <li>
  88.  *          Forward Rate to a specific date/tenor, and effective rate between a date interval
  89.  *      </li>
  90.  *      <li>
  91.  *          Discount Factor to a specific date/tenor, and effective discount factor between a date interval
  92.  *      </li>
  93.  *      <li>
  94.  *          Zero Rate to a specific date/tenor
  95.  *      </li>
  96.  *      <li>
  97.  *          Value Jacobian for Forward rate, discount factor, and zero rate
  98.  *      </li>
  99.  *      <li>
  100.  *          Cross Jacobian between each of Forward rate, discount factor, and zero rate
  101.  *      </li>
  102.  *      <li>
  103.  *          Quote Jacobian to Forward rate, discount factor, and zero rate
  104.  *      </li>
  105.  *      <li>
  106.  *          QM (DF/Zero/Forward) to Quote Jacobian
  107.  *      </li>
  108.  *      <li>
  109.  *          Latent State Quantification Metric, and the canonical truthness transformations
  110.  *      </li>
  111.  *      <li>
  112.  *          Implied/embedded ForwardRateEstimator
  113.  *      </li>
  114.  *      <li>
  115.  *          Turns set/unset/adjust
  116.  *      </li>
  117.  *  </ul>
  118.  *
  119.  *  <br><br>
  120.  *  <ul>
  121.  *      <li><b>Module </b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/ProductCore.md">Product Core Module</a></li>
  122.  *      <li><b>Library</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/FixedIncomeAnalyticsLibrary.md">Fixed Income Analytics</a></li>
  123.  *      <li><b>Project</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/state/README.md">Latent State Inference and Creation Utilities</a></li>
  124.  *      <li><b>Package</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/state/discount/README.md">Discount Curve Spline Latent State</a></li>
  125.  *  </ul>
  126.  * <br><br>
  127.  *
  128.  * @author Lakshmi Krishnamurthy
  129.  */

  130. public abstract class MergedDiscountForwardCurve extends org.drip.state.discount.DiscountCurve {
  131.     private static final int NUM_DF_QUADRATURES = 5;

  132.     protected java.lang.String _strCurrency = "";
  133.     protected int _iEpochDate = java.lang.Integer.MIN_VALUE;
  134.     protected org.drip.state.discount.TurnListDiscountFactor _tldf = null;
  135.     protected org.drip.analytics.input.CurveConstructionInputSet _ccis = null;

  136.     protected MergedDiscountForwardCurve (
  137.         final int iEpochDate,
  138.         final java.lang.String strCurrency,
  139.         final org.drip.state.discount.TurnListDiscountFactor tldf)
  140.         throws java.lang.Exception
  141.     {
  142.         if (null == (_strCurrency = strCurrency) || _strCurrency.isEmpty() ||
  143.             !org.drip.numerical.common.NumberUtil.IsValid (_iEpochDate = iEpochDate))
  144.             throw new java.lang.Exception ("MergedDiscountForwardCurve ctr: Invalid Inputs");

  145.         _tldf = tldf;
  146.     }

  147.     @Override public org.drip.state.identifier.LatentStateLabel label()
  148.     {
  149.         return org.drip.state.identifier.FundingLabel.Standard (_strCurrency);
  150.     }

  151.     @Override public java.lang.String currency()
  152.     {
  153.         return _strCurrency;
  154.     }

  155.     @Override public org.drip.analytics.date.JulianDate epoch()
  156.     {
  157.         try {
  158.             return new org.drip.analytics.date.JulianDate (_iEpochDate);
  159.         } catch (java.lang.Exception e) {
  160.             e.printStackTrace();
  161.         }

  162.         return null;
  163.     }

  164.     /**
  165.      * Set the Discount Curve Turns'
  166.      *
  167.      * @param tldf Turn List Discount Factor
  168.      *
  169.      * @return TRUE - Valid Turn List Discount Factor Set
  170.      */

  171.     public boolean setTurns (
  172.         final org.drip.state.discount.TurnListDiscountFactor tldf)
  173.     {
  174.         return null != (_tldf = tldf);
  175.     }

  176.     /**
  177.      * Apply the Turns' DF Adjustment
  178.      *
  179.      * @param iStartDate Turn Start Date
  180.      * @param iFinishDate Turn Finish Date
  181.      *
  182.      * @return Turns' DF Adjustment
  183.      *
  184.      * @throws java.lang.Exception Thrown if the Inputs are invalid
  185.      */

  186.     public double turnAdjust (
  187.         final int iStartDate,
  188.         final int iFinishDate)
  189.         throws java.lang.Exception
  190.     {
  191.         return null == _tldf ? 1. : _tldf.turnAdjust (iStartDate, iFinishDate);
  192.     }

  193.     /**
  194.      * Apply the Turns' DF Adjustment
  195.      *
  196.      * @param iFinishDate Turn Finish Date
  197.      *
  198.      * @return Turns' DF Adjustment
  199.      *
  200.      * @throws java.lang.Exception Thrown if the Inputs are invalid
  201.      */

  202.     protected double turnAdjust (
  203.         final int iFinishDate)
  204.         throws java.lang.Exception
  205.     {
  206.         return turnAdjust (epoch().julian(), iFinishDate);
  207.     }

  208.     /**
  209.      * Construct the Native Forward Curve for the given Tenor from the Discount Curve
  210.      *
  211.      * @param strTenor The Tenor
  212.      *
  213.      * @return The Tenor-Native Forward Curve
  214.      */

  215.     public org.drip.state.forward.ForwardCurve nativeForwardCurve (
  216.         final java.lang.String strTenor)
  217.     {
  218.         if (null == strTenor || strTenor.isEmpty()) return null;

  219.         try {
  220.             org.drip.state.forward.ForwardCurve fcNative = new org.drip.state.forward.ForwardCurve
  221.                 (epoch().julian(), org.drip.state.identifier.ForwardLabel.Standard (_strCurrency + "-" +
  222.                     strTenor)) {
  223.                 @Override public double forward (
  224.                     final int iDate)
  225.                     throws java.lang.Exception
  226.                 {
  227.                     return forward (new org.drip.analytics.date.JulianDate (iDate));
  228.                 }

  229.                 @Override public double forward (
  230.                     final org.drip.analytics.date.JulianDate dt)
  231.                     throws java.lang.Exception
  232.                 {
  233.                     if (null == dt)
  234.                         throw new java.lang.Exception
  235.                             ("MergedDiscountForwardCurve::nativeForwardCurve => Invalid Input");

  236.                     return libor (dt.subtractTenor (strTenor).julian(), strTenor);
  237.                 }

  238.                 @Override public double forward (
  239.                     final java.lang.String strTenor)
  240.                     throws java.lang.Exception
  241.                 {
  242.                     if (null == strTenor || strTenor.isEmpty())
  243.                         throw new java.lang.Exception
  244.                             ("MergedDiscountForwardCurve::nativeForwardCurve => Invalid Input");

  245.                     return forward (epoch().addTenor (strTenor));
  246.                 }

  247.                 @Override public org.drip.numerical.differentiation.WengertJacobian jackDForwardDManifestMeasure (
  248.                     final java.lang.String strManifestMeasure,
  249.                     final int iDate)
  250.                 {
  251.                     return null;
  252.                 }
  253.             };

  254.             return fcNative;
  255.         } catch (java.lang.Exception e) {
  256.             e.printStackTrace();
  257.         }

  258.         return null;
  259.     }

  260.     @Override public double df (
  261.         final org.drip.analytics.date.JulianDate dt)
  262.         throws java.lang.Exception
  263.     {
  264.         if (null == dt) throw new java.lang.Exception ("MergedDiscountForwardCurve::df got null for date");

  265.         return df (dt.julian());
  266.     }

  267.     @Override public double df (
  268.         final java.lang.String strTenor)
  269.         throws java.lang.Exception
  270.     {
  271.         if (null == strTenor || strTenor.isEmpty())
  272.             throw new java.lang.Exception ("MergedDiscountForwardCurve::df got bad tenor");

  273.         return df (epoch().addTenor (strTenor));
  274.     }

  275.     @Override public double effectiveDF (
  276.         final int iDate1,
  277.         final int iDate2)
  278.         throws java.lang.Exception
  279.     {
  280.         if (iDate1 == iDate2) return df (iDate1);

  281.         int iNumQuadratures = 0;
  282.         double dblEffectiveDF = 0.;
  283.         int iQuadratureWidth = (iDate2 - iDate1) / NUM_DF_QUADRATURES;

  284.         if (0 == iQuadratureWidth) iQuadratureWidth = 1;

  285.         for (int iDate = iDate1; iDate <= iDate2; iDate += iQuadratureWidth) {
  286.             ++iNumQuadratures;

  287.             dblEffectiveDF += (df (iDate) + df (iDate + iQuadratureWidth));
  288.         }

  289.         return dblEffectiveDF / (2. * iNumQuadratures);
  290.     }

  291.     @Override public double effectiveDF (
  292.         final org.drip.analytics.date.JulianDate dt1,
  293.         final org.drip.analytics.date.JulianDate dt2)
  294.         throws java.lang.Exception
  295.     {
  296.         if (null == dt1 || null == dt2)
  297.             throw new java.lang.Exception ("MergedDiscountForwardCurve::effectiveDF => Got null for date");

  298.         return effectiveDF (dt1.julian(), dt2.julian());
  299.     }

  300.     @Override public double effectiveDF (
  301.         final java.lang.String strTenor1,
  302.         final java.lang.String strTenor2)
  303.         throws java.lang.Exception
  304.     {
  305.         if (null == strTenor1 || strTenor1.isEmpty() || null == strTenor2 || strTenor2.isEmpty())
  306.             throw new java.lang.Exception ("MergedDiscountForwardCurve::effectiveDF => Got bad tenor");

  307.         org.drip.analytics.date.JulianDate dtStart = epoch();

  308.         return effectiveDF (dtStart.addTenor (strTenor1), dtStart.addTenor (strTenor2));
  309.     }

  310.     /**
  311.      * Compute the Forward Rate between two Dates
  312.      *
  313.      * @param iDate1 First Date
  314.      * @param iDate2 Second Date
  315.      *
  316.      * @return The Forward Rate
  317.      *
  318.      * @throws java.lang.Exception Thrown if the Forward Rate cannot be calculated
  319.      */

  320.     public abstract double forward (
  321.         final int iDate1,
  322.         final int iDate2)
  323.         throws java.lang.Exception;

  324.     /**
  325.      * Compute the Forward Rate between two Tenors
  326.      *
  327.      * @param strTenor1 Tenor Start
  328.      * @param strTenor2 Tenor End
  329.      *
  330.      * @return The Forward Rate
  331.      *
  332.      * @throws java.lang.Exception Thrown if the Forward Rate cannot be calculated
  333.      */

  334.     public double forward (
  335.         final java.lang.String strTenor1,
  336.         final java.lang.String strTenor2)
  337.         throws java.lang.Exception
  338.     {
  339.         if (null == strTenor1 || strTenor1.isEmpty() || null == strTenor2 || strTenor2.isEmpty())
  340.             throw new java.lang.Exception ("MergedDiscountForwardCurve::forward => Invalid Date");

  341.         org.drip.analytics.date.JulianDate dtStart = epoch();

  342.         return forward (dtStart.addTenor (strTenor1).julian(), dtStart.addTenor (strTenor2).julian());
  343.     }

  344.     /**
  345.      * Calculate the implied rate to the given date
  346.      *
  347.      * @param iDate Date
  348.      *
  349.      * @return Implied rate
  350.      *
  351.      * @throws java.lang.Exception Thrown if the discount factor cannot be calculated
  352.      */

  353.     public abstract double zero (
  354.         final int iDate)
  355.         throws java.lang.Exception;

  356.     /**
  357.      * Calculate the implied rate to the given tenor
  358.      *
  359.      * @param strTenor Tenor
  360.      *
  361.      * @return Implied rate
  362.      *
  363.      * @throws java.lang.Exception Thrown if the discount factor cannot be calculated
  364.      */

  365.     public double zero (
  366.         final java.lang.String strTenor)
  367.         throws java.lang.Exception
  368.     {
  369.         if (null == strTenor || strTenor.isEmpty())
  370.             throw new java.lang.Exception ("MergedDiscountForwardCurve::zero => Invalid date");

  371.         org.drip.analytics.date.JulianDate dtStart = epoch();

  372.         return forward (dtStart.julian(), dtStart.addTenor (strTenor).julian());
  373.     }

  374.     /**
  375.      * Compute the LIBOR between 2 dates given the Day Count
  376.      *
  377.      * @param iDate1 First Date
  378.      * @param iDate2 Second Date
  379.      * @param dblDCF Day Count Fraction
  380.      *
  381.      * @return LIBOR
  382.      *
  383.      * @throws java.lang.Exception Thrown if the discount factor cannot be calculated
  384.      */

  385.     public double libor (
  386.         final int iDate1,
  387.         final int iDate2,
  388.         final double dblDCF)
  389.         throws java.lang.Exception
  390.     {
  391.         if (iDate1 == iDate2 || !org.drip.numerical.common.NumberUtil.IsValid (dblDCF) || 0. == dblDCF)
  392.             throw new java.lang.Exception ("MergedDiscountForwardCurve::libor => Invalid input dates");

  393.         return ((df (iDate1) / df (iDate2)) - 1.) / dblDCF;
  394.     }

  395.     /**
  396.      * Compute the LIBOR between 2 dates
  397.      *
  398.      * @param iDate1 First Date
  399.      * @param iDate2 Second Date
  400.      *
  401.      * @return LIBOR
  402.      *
  403.      * @throws java.lang.Exception Thrown if the discount factor cannot be calculated
  404.      */

  405.     public double libor (
  406.         final int iDate1,
  407.         final int iDate2)
  408.         throws java.lang.Exception
  409.     {
  410.         if (iDate1 == iDate2)
  411.             throw new java.lang.Exception ("MergedDiscountForwardCurve::libor => Invalid input dates");

  412.         return libor (iDate1, iDate2, org.drip.analytics.daycount.Convention.YearFraction (iDate1, iDate2,
  413.             "Act/360", false, null, ""));
  414.     }

  415.     /**
  416.      * Calculate the LIBOR to the given tenor at the specified date
  417.      *
  418.      * @param iStartDate Start Date
  419.      * @param strTenor Tenor
  420.      *
  421.      * @return LIBOR
  422.      *
  423.      * @throws java.lang.Exception Thrown if LIBOR cannot be calculated
  424.      */

  425.     public double libor (
  426.         final int iStartDate,
  427.         final java.lang.String strTenor)
  428.         throws java.lang.Exception
  429.     {
  430.         if (!org.drip.numerical.common.NumberUtil.IsValid (iStartDate) || null == strTenor || strTenor.isEmpty())
  431.             throw new java.lang.Exception ("MergedDiscountForwardCurve::libor => Invalid Inputs");

  432.         return libor (iStartDate, new org.drip.analytics.date.JulianDate (iStartDate).addTenor
  433.             (strTenor).julian());
  434.     }

  435.     /**
  436.      * Calculate the LIBOR to the given tenor at the specified Julian Date
  437.      *
  438.      * @param dt Julian Date
  439.      * @param strTenor Tenor
  440.      *
  441.      * @return LIBOR
  442.      *
  443.      * @throws java.lang.Exception Thrown if LIBOR cannot be calculated
  444.      */

  445.     public double libor (
  446.         final org.drip.analytics.date.JulianDate dt,
  447.         final java.lang.String strTenor)
  448.         throws java.lang.Exception
  449.     {
  450.         if (null == dt)
  451.             throw new java.lang.Exception ("MergedDiscountForwardCurve::libor => Invalid Inputs");

  452.         return libor (dt.julian(), strTenor);
  453.     }

  454.     /**
  455.      * Calculate the DV01 of the Par Swap that Matures at the given date
  456.      *
  457.      * @param iDate Date
  458.      *
  459.      * @return DV01 of the Par Swap that Matures at the given date
  460.      *
  461.      * @throws java.lang.Exception Thrown if DV01 cannot be calculated
  462.      */

  463.     public double parSwapDV01 (
  464.         final int iDate)
  465.         throws java.lang.Exception
  466.     {
  467.         java.lang.String strCurrency = currency();

  468.         org.drip.analytics.date.JulianDate dtStart = epoch().addDays (2);

  469.         org.drip.param.period.UnitCouponAccrualSetting ucasFixed = new
  470.             org.drip.param.period.UnitCouponAccrualSetting (2, "Act/360", false, "Act/360", false,
  471.                 strCurrency, true,
  472.                     org.drip.analytics.support.CompositePeriodBuilder.ACCRUAL_COMPOUNDING_RULE_GEOMETRIC);

  473.         org.drip.param.period.ComposableFixedUnitSetting cfusFixed = new
  474.             org.drip.param.period.ComposableFixedUnitSetting ("6M",
  475.                 org.drip.analytics.support.CompositePeriodBuilder.EDGE_DATE_SEQUENCE_REGULAR, null, 0., 0.,
  476.                     strCurrency);

  477.         org.drip.param.period.CompositePeriodSetting cpsFixed = new
  478.             org.drip.param.period.CompositePeriodSetting (2, "6M", strCurrency, null, 1., null, null, null,
  479.                 null);

  480.         java.util.List<java.lang.Integer> lsFixedStreamEdgeDate =
  481.             org.drip.analytics.support.CompositePeriodBuilder.BackwardEdgeDates (dtStart, new
  482.                 org.drip.analytics.date.JulianDate (iDate), "6M", null,
  483.                     org.drip.analytics.support.CompositePeriodBuilder.SHORT_STUB);

  484.         org.drip.product.rates.Stream fixedStream = new org.drip.product.rates.Stream
  485.             (org.drip.analytics.support.CompositePeriodBuilder.FixedCompositeUnit (lsFixedStreamEdgeDate,
  486.                 cpsFixed, ucasFixed, cfusFixed));

  487.         org.drip.param.market.CurveSurfaceQuoteContainer csqs =
  488.             org.drip.param.creator.MarketParamsBuilder.Create (this, null, null, null, null, null, null,
  489.                 null);

  490.         java.util.Map<java.lang.String, java.lang.Double> mapFixStream = fixedStream.value
  491.             (org.drip.param.valuation.ValuationParams.Spot (dtStart, 0, "",
  492.                 org.drip.analytics.daycount.Convention.DATE_ROLL_ACTUAL), null, csqs, null);

  493.         return mapFixStream.get ("DV01");
  494.     }

  495.     /**
  496.      * Estimate the manifest measure value for the given date
  497.      *
  498.      * @param strManifestMeasure The Manifest Measure to be Estimated
  499.      * @param iDate Date
  500.      *
  501.      * @return The estimated calibrated measure value
  502.      *
  503.      * @throws java.lang.Exception Thrown if the estimated manifest measure cannot be computed
  504.      */

  505.     public double estimateManifestMeasure (
  506.         final java.lang.String strManifestMeasure,
  507.         final int iDate)
  508.         throws java.lang.Exception
  509.     {
  510.         if (null == strManifestMeasure || strManifestMeasure.isEmpty())
  511.             throw new java.lang.Exception
  512.                 ("MergedDiscountForwardCurve::estimateManifestMeasure => Invalid input");

  513.         org.drip.product.definition.CalibratableComponent[] aCalibComp = calibComp();

  514.         if (null == aCalibComp)
  515.             throw new java.lang.Exception
  516.                 ("MergedDiscountForwardCurve::estimateManifestMeasure => Calib Components not available");

  517.         int iNumComponent = aCalibComp.length;

  518.         if (0 == iNumComponent)
  519.             throw new java.lang.Exception
  520.                 ("MergedDiscountForwardCurve::estimateManifestMeasure => Calib Components not available");

  521.         java.util.List<java.lang.Integer> lsDate = new java.util.ArrayList<java.lang.Integer>();

  522.         java.util.List<java.lang.Double> lsQuote = new java.util.ArrayList<java.lang.Double>();

  523.         for (int i = 0; i < iNumComponent; ++i) {
  524.             if (null == aCalibComp[i])
  525.                 throw new java.lang.Exception
  526.                     ("MergedDiscountForwardCurve::estimateManifestMeasure => Cannot locate a component");

  527.             org.drip.analytics.support.CaseInsensitiveTreeMap<java.lang.Double> mapManifestMeasure =
  528.                 manifestMeasure (aCalibComp[i].primaryCode());

  529.             if (mapManifestMeasure.containsKey (strManifestMeasure)) {
  530.                 lsDate.add (aCalibComp[i].maturityDate().julian());

  531.                 lsQuote.add (mapManifestMeasure.get (strManifestMeasure));
  532.             }
  533.         }

  534.         int iNumEstimationComponent = lsDate.size();

  535.         if (0 == iNumEstimationComponent)
  536.             throw new java.lang.Exception
  537.                 ("MergedDiscountForwardCurve::estimateManifestMeasure => Estimation Components not available");

  538.         int[] aiDate = new int[iNumEstimationComponent];
  539.         double[] adblQuote = new double[iNumEstimationComponent];
  540.         org.drip.spline.params.SegmentCustomBuilderControl[] aSBP = new
  541.             org.drip.spline.params.SegmentCustomBuilderControl[iNumEstimationComponent - 1];

  542.         if (1 == iNumEstimationComponent) return lsQuote.get (0);

  543.         org.drip.spline.params.SegmentCustomBuilderControl sbp = new
  544.             org.drip.spline.params.SegmentCustomBuilderControl
  545.                 (org.drip.spline.stretch.MultiSegmentSequenceBuilder.BASIS_SPLINE_POLYNOMIAL, new
  546.                     org.drip.spline.basis.PolynomialFunctionSetParams (4),
  547.                         org.drip.spline.params.SegmentInelasticDesignControl.Create (2, 2), null, null);

  548.         for (int i = 0; i < iNumEstimationComponent; ++i) {
  549.             if (0 != i) aSBP[i - 1] = sbp;

  550.             aiDate[i] = lsDate.get (i);

  551.             adblQuote[i] = lsQuote.get (i);
  552.         }

  553.         org.drip.spline.stretch.MultiSegmentSequence regime =
  554.             org.drip.spline.stretch.MultiSegmentSequenceBuilder.CreateCalibratedStretchEstimator
  555.                 ("DISC_CURVE_REGIME", aiDate, adblQuote, aSBP, null,
  556.                     org.drip.spline.stretch.BoundarySettings.NaturalStandard(),
  557.                         org.drip.spline.stretch.MultiSegmentSequence.CALIBRATE);

  558.         if (null == regime)
  559.             throw new java.lang.Exception
  560.                 ("MergedDiscountForwardCurve::estimateManifestMeasure => Cannot create Spline Stretch");

  561.         double dblRegimeLeftExtreme = regime.getLeftPredictorOrdinateEdge();

  562.         if (iDate <= dblRegimeLeftExtreme) return regime.responseValue (dblRegimeLeftExtreme);

  563.         double dblRegimeRightExtreme = regime.getRightPredictorOrdinateEdge();

  564.         if (iDate >= dblRegimeRightExtreme) return regime.responseValue (dblRegimeRightExtreme);

  565.         return regime.responseValue (iDate);
  566.     }

  567.     /**
  568.      * Proxy the Manifest Measure Value using the Closest Node for the given Date
  569.      *
  570.      * @param strManifestMeasure The Manifest Measure to be Proxied
  571.      * @param iDate Date
  572.      *
  573.      * @return The Measure Value Proxy
  574.      *
  575.      * @throws java.lang.Exception Thrown if the Manifest Measure Proxy cannot be computed
  576.      */

  577.     public double proxyManifestMeasure (
  578.         final java.lang.String strManifestMeasure,
  579.         final int iDate)
  580.         throws java.lang.Exception
  581.     {
  582.         if (null == strManifestMeasure || strManifestMeasure.isEmpty())
  583.             throw new java.lang.Exception
  584.                 ("MergedDiscountForwardCurve::proxyManifestMeasure => Invalid input");

  585.         org.drip.product.definition.CalibratableComponent[] aCalibComp = calibComp();

  586.         if (null == aCalibComp)
  587.             throw new java.lang.Exception
  588.                 ("MergedDiscountForwardCurve::proxyManifestMeasure => Calib Components not available");

  589.         int iNumComponent = aCalibComp.length;

  590.         if (0 == iNumComponent)
  591.             throw new java.lang.Exception
  592.                 ("MergedDiscountForwardCurve::proxyManifestMeasure => Calib Components not available");

  593.         java.util.List<java.lang.Integer> lsDate = new java.util.ArrayList<java.lang.Integer>();

  594.         java.util.List<java.lang.Double> lsQuote = new java.util.ArrayList<java.lang.Double>();

  595.         for (int i = 0; i < iNumComponent; ++i) {
  596.             if (null == aCalibComp[i])
  597.                 throw new java.lang.Exception
  598.                     ("MergedDiscountForwardCurve::proxyManifestMeasure => Cannot locate a component");

  599.             org.drip.analytics.support.CaseInsensitiveTreeMap<java.lang.Double> mapManifestMeasure =
  600.                 manifestMeasure (aCalibComp[i].primaryCode());

  601.             if (mapManifestMeasure.containsKey (strManifestMeasure)) {
  602.                 lsDate.add (aCalibComp[i].maturityDate().julian());

  603.                 lsQuote.add (mapManifestMeasure.get (strManifestMeasure));
  604.             }
  605.         }

  606.         int iNumEstimationComponent = lsDate.size();

  607.         if (0 == iNumEstimationComponent)
  608.             throw new java.lang.Exception
  609.                 ("MergedDiscountForwardCurve::proxyManifestMeasure => Estimation Components not available");

  610.         if (1 == iNumEstimationComponent) return lsQuote.get (0);

  611.         int iDatePrev = lsDate.get (0);

  612.         if (iDate <= iDatePrev) return lsQuote.get (0);

  613.         for (int i = 1; i < iNumEstimationComponent; ++i) {
  614.             int iDateCurr = lsDate.get (i);

  615.             if (iDatePrev <= iDate && iDate < iDateCurr)
  616.                 return iDate - iDatePrev > iDateCurr - iDate ? lsQuote.get (i) : lsQuote.get (i - 1);

  617.             iDatePrev = iDateCurr;
  618.         }

  619.         return lsQuote.get (iNumEstimationComponent - 1);
  620.     }

  621.     @Override public boolean setCCIS (
  622.         final org.drip.analytics.input.CurveConstructionInputSet ccis)
  623.     {
  624.         if (null == ccis) return false;

  625.         _ccis = ccis;
  626.         return true;
  627.     }

  628.     /**
  629.      * Retrieve the Forward Curve that might be implied by the Latent State of this Discount Curve Instance
  630.      *  corresponding to the specified Floating Rate Index
  631.      *
  632.      * @param iDate The Date
  633.      * @param fri The Floating Rate Index
  634.      *
  635.      * @return The Forward Curve Implied by the Discount Curve Latent State
  636.      */

  637.     public abstract org.drip.state.forward.ForwardRateEstimator forwardRateEstimator (
  638.         final int iDate,
  639.         final org.drip.state.identifier.ForwardLabel fri);

  640.     /**
  641.      * Retrieve the Latent State Quantification Metric
  642.      *
  643.      * @return The Latent State Quantification Metric
  644.      */

  645.     public abstract java.lang.String latentStateQuantificationMetric();

  646.     /**
  647.      * Retrieve the Manifest Measure Jacobian of the Discount Factor to the given date
  648.      *
  649.      * @param iDate Date
  650.      * @param strManifestMeasure Manifest Measure
  651.      *
  652.      * @return The Manifest Measure Jacobian of the Discount Factor to the given date
  653.      */

  654.     public abstract org.drip.numerical.differentiation.WengertJacobian jackDDFDManifestMeasure (
  655.         final int iDate,
  656.         final java.lang.String strManifestMeasure);

  657.     /**
  658.      * Retrieve the Manifest Measure Jacobian of the Discount Factor to the given date
  659.      *
  660.      * @param dt Date
  661.      * @param strManifestMeasure Manifest Measure
  662.      *
  663.      * @return The Manifest Measure Jacobian of the Discount Factor to the given date
  664.      */

  665.     public org.drip.numerical.differentiation.WengertJacobian jackDDFDManifestMeasure (
  666.         final org.drip.analytics.date.JulianDate dt,
  667.         final java.lang.String strManifestMeasure)
  668.     {
  669.         if (null == dt) return null;

  670.         return jackDDFDManifestMeasure (dt.julian(), strManifestMeasure);
  671.     }

  672.     /**
  673.      * Retrieve the Manifest Measure Jacobian of the Discount Factor to the date implied by the given Tenor
  674.      *
  675.      * @param strTenor Tenor
  676.      * @param strManifestMeasure Manifest Measure
  677.      *
  678.      * @return The Manifest Measure Jacobian of the Discount Factor to the date implied by the given Tenor
  679.      */

  680.     public org.drip.numerical.differentiation.WengertJacobian jackDDFDManifestMeasure (
  681.         final java.lang.String strTenor,
  682.         final java.lang.String strManifestMeasure)
  683.     {
  684.         if (null == strTenor || strTenor.isEmpty()) return null;

  685.         try {
  686.             return jackDDFDManifestMeasure (epoch().addTenor (strTenor), strManifestMeasure);
  687.         } catch (java.lang.Exception e) {
  688.             e.printStackTrace();
  689.         }

  690.         return null;
  691.     }

  692.     /**
  693.      * Calculate the Jacobian of PV at the given date to the Manifest Measure of each component in the
  694.      *  calibration set to the DF
  695.      *
  696.      * @param iDate Date for which the Jacobian is needed
  697.      *
  698.      * @return The Jacobian
  699.      */

  700.     public org.drip.numerical.differentiation.WengertJacobian compJackDPVDManifestMeasure (
  701.         final int iDate)
  702.     {
  703.         if (!org.drip.numerical.common.NumberUtil.IsValid (iDate)) return null;

  704.         org.drip.product.definition.CalibratableComponent[] aCalibComp = calibComp();

  705.         if (null == aCalibComp || 0 == aCalibComp.length) return null;

  706.         int iNumParameters = 0;
  707.         int iNumComponents = aCalibComp.length;
  708.         org.drip.numerical.differentiation.WengertJacobian wjCompPVDF = null;

  709.         org.drip.param.valuation.ValuationParams valParams = org.drip.param.valuation.ValuationParams.Spot
  710.             (iDate);

  711.         org.drip.param.market.CurveSurfaceQuoteContainer csqs =
  712.             org.drip.param.creator.MarketParamsBuilder.Create (this, null, null, null, null, null,
  713.                 null, null == _ccis ? null : _ccis.fixing());

  714.         for (int i = 0; i < iNumComponents; ++i) {
  715.             org.drip.numerical.differentiation.WengertJacobian wjCompDDirtyPVDManifestMeasure =
  716.                 aCalibComp[i].jackDDirtyPVDManifestMeasure (valParams, null, csqs, null);

  717.             if (null == wjCompDDirtyPVDManifestMeasure) return null;

  718.             iNumParameters = wjCompDDirtyPVDManifestMeasure.numParameters();

  719.             if (null == wjCompPVDF) {
  720.                 try {
  721.                     wjCompPVDF = new org.drip.numerical.differentiation.WengertJacobian (iNumComponents,
  722.                         iNumParameters);
  723.                 } catch (java.lang.Exception e) {
  724.                     e.printStackTrace();

  725.                     return null;
  726.                 }
  727.             }

  728.             for (int k = 0; k < iNumParameters; ++k) {
  729.                 if (!wjCompPVDF.accumulatePartialFirstDerivative (i, k,
  730.                     wjCompDDirtyPVDManifestMeasure.firstDerivative (0, k)))
  731.                     return null;
  732.             }
  733.         }

  734.         return wjCompPVDF;
  735.     }

  736.     /**
  737.      * Calculate the Jacobian of PV at the given date to the Manifest Measure of each component in the
  738.      *  calibration set to the DF
  739.      *
  740.      * @param dt Date for which the Jacobian is needed
  741.      *
  742.      * @return The Jacobian
  743.      */

  744.     public org.drip.numerical.differentiation.WengertJacobian compJackDPVDManifestMeasure (
  745.         final org.drip.analytics.date.JulianDate dt)
  746.     {
  747.         return null == dt ? null : compJackDPVDManifestMeasure (dt.julian());
  748.     }

  749.     /**
  750.      * Retrieve the Jacobian of the Forward Rate to the Manifest Measure between the given dates
  751.      *
  752.      * @param iDate1 Date 1
  753.      * @param iDate2 Date 2
  754.      * @param strManifestMeasure Manifest Measure
  755.      * @param dblElapsedYear The Elapsed Year (in the appropriate Day Count) between dates 1 and 2
  756.      *
  757.      * @return The Jacobian
  758.      */

  759.     public org.drip.numerical.differentiation.WengertJacobian jackDForwardDManifestMeasure (
  760.         final int iDate1,
  761.         final int iDate2,
  762.         final java.lang.String strManifestMeasure,
  763.         final double dblElapsedYear)
  764.     {
  765.         if (iDate1 == iDate2) return null;

  766.         org.drip.numerical.differentiation.WengertJacobian wjDDFDManifestMeasureDate1 = jackDDFDManifestMeasure
  767.             (iDate1, strManifestMeasure);

  768.         if (null == wjDDFDManifestMeasureDate1) return null;

  769.         int iNumQuote = wjDDFDManifestMeasureDate1.numParameters();

  770.         if (0 == iNumQuote) return null;

  771.         org.drip.numerical.differentiation.WengertJacobian wjDDFDManifestMeasureDate2 = jackDDFDManifestMeasure
  772.             (iDate2, strManifestMeasure);

  773.         if (null == wjDDFDManifestMeasureDate2 || iNumQuote != wjDDFDManifestMeasureDate2.numParameters())
  774.             return null;

  775.         double dblDF1 = java.lang.Double.NaN;
  776.         double dblDF2 = java.lang.Double.NaN;
  777.         org.drip.numerical.differentiation.WengertJacobian wjDForwardDManifestMeasure = null;

  778.         try {
  779.             dblDF1 = df (iDate1);

  780.             dblDF2 = df (iDate2);

  781.             wjDForwardDManifestMeasure = new org.drip.numerical.differentiation.WengertJacobian (1, iNumQuote);
  782.         } catch (java.lang.Exception e) {
  783.             e.printStackTrace();

  784.             return null;
  785.         }

  786.         double dblDForwardDManifestMeasure1iScale = 1. / dblDF2;
  787.         double dblDForwardDManifestMeasure2iScale = dblDF1 / (dblDF2 * dblDF2);
  788.         double dblInverseAnnualizedTenorLength = 1. / dblElapsedYear;

  789.         for (int i = 0; i < iNumQuote; ++i) {
  790.             double dblDForwardDQManifestMeasurei = ((wjDDFDManifestMeasureDate1.firstDerivative (0, i) *
  791.                 dblDForwardDManifestMeasure1iScale) - (wjDDFDManifestMeasureDate2.firstDerivative (0, i) *
  792.                     dblDForwardDManifestMeasure2iScale)) * dblInverseAnnualizedTenorLength;

  793.             if (!wjDForwardDManifestMeasure.accumulatePartialFirstDerivative (0, i,
  794.                 dblDForwardDQManifestMeasurei))
  795.                 return null;
  796.         }

  797.         return wjDForwardDManifestMeasure;
  798.     }

  799.     /**
  800.      * Retrieve the Jacobian of the Forward Rate to the Manifest Measure between the given dates
  801.      *
  802.      * @param dt1 Julian Date 1
  803.      * @param dt2 Julian Date 2
  804.      * @param strManifestMeasure Manifest Measure
  805.      * @param dblElapsedYear The Elapsed Year (in the appropriate Day Count) between dates 1 and 2
  806.      *
  807.      * @return The Jacobian
  808.      */

  809.     public org.drip.numerical.differentiation.WengertJacobian jackDForwardDManifestMeasure (
  810.         final org.drip.analytics.date.JulianDate dt1,
  811.         final org.drip.analytics.date.JulianDate dt2,
  812.         final java.lang.String strManifestMeasure,
  813.         final double dblElapsedYear)
  814.     {
  815.         if (null == dt1 || null == dt2) return null;

  816.         return jackDForwardDManifestMeasure (dt1.julian(), dt2.julian(), strManifestMeasure, dblElapsedYear);
  817.     }

  818.     /**
  819.      * Retrieve the Jacobian of the Forward Rate to the Manifest Measure at the given date
  820.      *
  821.      * @param dt Given Julian Date
  822.      * @param strTenor Tenor
  823.      * @param strManifestMeasure Manifest Measure
  824.      * @param dblElapsedYear The Elapsed Year (in the appropriate Day Count) implied by the Tenor
  825.      *
  826.      * @return The Jacobian
  827.      */

  828.     public org.drip.numerical.differentiation.WengertJacobian jackDForwardDManifestMeasure (
  829.         final org.drip.analytics.date.JulianDate dt,
  830.         final java.lang.String strTenor,
  831.         final java.lang.String strManifestMeasure,
  832.         final double dblElapsedYear)
  833.     {
  834.         if (null == dt || null == strTenor || strTenor.isEmpty()) return null;

  835.         return jackDForwardDManifestMeasure (dt.julian(), dt.addTenor (strTenor).julian(),
  836.             strManifestMeasure, dblElapsedYear);
  837.     }

  838.     /**
  839.      * Retrieve the Jacobian for the Zero Rate to the given date
  840.      *
  841.      * @param iDate Date
  842.      * @param strManifestMeasure Manifest Measure
  843.      *
  844.      * @return The Jacobian
  845.      */

  846.     public org.drip.numerical.differentiation.WengertJacobian zeroRateJack (
  847.         final int iDate,
  848.         final java.lang.String strManifestMeasure)
  849.     {
  850.         int iEpochDate = epoch().julian();

  851.         return jackDForwardDManifestMeasure (iEpochDate, iDate, strManifestMeasure, 1. * (iDate - iEpochDate) /
  852.             365.25);
  853.     }

  854.     /**
  855.      * Retrieve the Jacobian for the Zero Rate to the given date
  856.      *
  857.      * @param dt Julian Date
  858.      * @param strManifestMeasure Manifest Measure
  859.      *
  860.      * @return The Jacobian
  861.      */

  862.     public org.drip.numerical.differentiation.WengertJacobian zeroRateJack (
  863.         final org.drip.analytics.date.JulianDate dt,
  864.         final java.lang.String strManifestMeasure)
  865.     {
  866.         return null == dt? null : zeroRateJack (dt.julian(), strManifestMeasure);
  867.     }

  868.     /**
  869.      * Convert the inferred Formulation Constraint into a "Truthness" Entity
  870.      *
  871.      * @param strLatentStateQuantificationMetric Latent State Quantification Metric
  872.      *
  873.      * @return Map of the Truthness Entities
  874.      */

  875.     public java.util.Map<java.lang.Integer, java.lang.Double> canonicalTruthness (
  876.         final java.lang.String strLatentStateQuantificationMetric)
  877.     {
  878.         if (null == strLatentStateQuantificationMetric ||
  879.             (!org.drip.analytics.definition.LatentStateStatic.DISCOUNT_QM_ZERO_RATE.equalsIgnoreCase
  880.                 (strLatentStateQuantificationMetric) && !
  881.                     org.drip.analytics.definition.LatentStateStatic.DISCOUNT_QM_DISCOUNT_FACTOR.equalsIgnoreCase
  882.             (strLatentStateQuantificationMetric)))
  883.             return null;

  884.         org.drip.product.definition.CalibratableComponent[] aCC = calibComp();

  885.         if (null == aCC) return null;

  886.         int iNumComp = aCC.length;
  887.         boolean bFirstCashFlow = true;

  888.         if (0 == iNumComp) return null;

  889.         java.util.Map<java.lang.Integer, java.lang.Double> mapCanonicalTruthness = new
  890.             java.util.TreeMap<java.lang.Integer, java.lang.Double>();

  891.         if (org.drip.analytics.definition.LatentStateStatic.DISCOUNT_QM_DISCOUNT_FACTOR.equalsIgnoreCase
  892.             (strLatentStateQuantificationMetric))
  893.             mapCanonicalTruthness.put (_iEpochDate, 1.);

  894.         for (org.drip.product.definition.CalibratableComponent cc : aCC) {
  895.             if (null == cc) continue;

  896.             java.util.List<org.drip.analytics.cashflow.CompositePeriod> lsCouponPeriod = cc.couponPeriods();

  897.             if (null == lsCouponPeriod || 0 == lsCouponPeriod.size()) continue;

  898.             for (org.drip.analytics.cashflow.CompositePeriod cpnPeriod : lsCouponPeriod) {
  899.                 if (null == cpnPeriod) continue;

  900.                 int iPeriodPayDate = cpnPeriod.payDate();

  901.                 if (iPeriodPayDate >= _iEpochDate) {
  902.                     try {
  903.                         if (org.drip.analytics.definition.LatentStateStatic.DISCOUNT_QM_DISCOUNT_FACTOR.equalsIgnoreCase
  904.                             (strLatentStateQuantificationMetric))
  905.                             mapCanonicalTruthness.put (iPeriodPayDate, df (iPeriodPayDate));
  906.                         else if (org.drip.analytics.definition.LatentStateStatic.DISCOUNT_QM_ZERO_RATE.equalsIgnoreCase
  907.                             (strLatentStateQuantificationMetric)) {
  908.                             if (bFirstCashFlow) {
  909.                                 bFirstCashFlow = false;

  910.                                 mapCanonicalTruthness.put (_iEpochDate, zero (iPeriodPayDate));
  911.                             }

  912.                             mapCanonicalTruthness.put (iPeriodPayDate, zero (iPeriodPayDate));
  913.                         }
  914.                     } catch (java.lang.Exception e) {
  915.                         e.printStackTrace();

  916.                         return null;
  917.                     }
  918.                 }
  919.             }
  920.         }

  921.         return mapCanonicalTruthness;
  922.     }
  923. }