TreasuryFuturesAPI.java

  1. package org.drip.service.product;

  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>TreasuryFuturesAPI</i> demonstrates the Details behind the Pricing and the Scenario Runs behind a
  80.  * Treasury Futures Contract.
  81.  *
  82.  * <br><br>
  83.  *  <ul>
  84.  *      <li><b>Module </b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/ComputationalCore.md">Computational Core Module</a></li>
  85.  *      <li><b>Library</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/ComputationSupportLibrary.md">Computation Support</a></li>
  86.  *      <li><b>Project</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/service/README.md">Environment, Product/Definition Containers, and Scenario/State Manipulation APIs</a></li>
  87.  *      <li><b>Package</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/service/product/README.md">Product Horizon PnL Attribution Decomposition</a></li>
  88.  *  </ul>
  89.  * <br><br>
  90.  *
  91.  * @author Lakshmi Krishnamurthy
  92.  */

  93. public class TreasuryFuturesAPI {

  94.     /**
  95.      * Generate a Full Map Invocation of the Treasury Futures Run Use Case
  96.      *
  97.      * @param strFuturesCode The Treasury Futures Code
  98.      * @param aiFuturesComponentTreasuryEffectiveDate Array of the Treasury Futures Component Effective Date
  99.      * @param aiFuturesComponentTreasuryMaturityDate Array of the Treasury Futures Component Maturity Date
  100.      * @param adblFuturesComponentTreasuryCoupon Array of the Treasury Futures Component Coupon
  101.      * @param adblFuturesComponentConversionFactor Array of the Treasury Futures Component Conversion Factor
  102.      * @param iSpotDate Spot Date
  103.      * @param astrFundingCurveDepositTenor Deposit Instruments Tenor (for Funding Curve)
  104.      * @param adblFundingCurveDepositQuote Deposit Instruments Quote (for Funding Curve)
  105.      * @param strFundingCurveDepositMeasure Deposit Instruments Measure (for Funding Curve)
  106.      * @param adblFundingCurveFuturesQuote Futures Instruments Tenor (for Funding Curve)
  107.      * @param strFundingCurveFuturesMeasure Futures Instruments Measure (for Funding Curve)
  108.      * @param astrFundingCurveFixFloatTenor Fix-Float Instruments Tenor (for Funding Curve)
  109.      * @param adblFundingCurveFixFloatQuote Fix-Float Instruments Quote (for Funding Curve)
  110.      * @param strFundingFixFloatMeasure Fix-Float Instruments Tenor (for Funding Curve)
  111.      * @param aiGovvieCurveTreasuryEffectiveDate Array of the Treasury Instrument Effective Date (for Treasury
  112.      *      Curve)
  113.      * @param aiGovvieCurveTreasuryMaturityDate Array of the Treasury Instrument Maturity Date (for Treasury
  114.      *      Curve)
  115.      * @param adblGovvieCurveTreasuryCoupon Array of the Treasury Instrument Coupon (for Treasury Curve)
  116.      * @param adblGovvieCurveTreasuryYield Array of the Treasury Instrument Yield (for Treasury Curve)
  117.      * @param strGovvieCurveTreasuryMeasure Treasury Instrument Measure (for Govvie Curve)
  118.      * @param adblFuturesComponentTreasuryPrice Array of the Treasury Futures Component Clean Prices
  119.      *
  120.      * @return The Output Measure Map
  121.      */

  122.     public static final java.util.Map<java.lang.String, java.lang.Double> ValuationMetrics (
  123.         final java.lang.String strFuturesCode,
  124.         final int[] aiFuturesComponentTreasuryEffectiveDate,
  125.         final int[] aiFuturesComponentTreasuryMaturityDate,
  126.         final double[] adblFuturesComponentTreasuryCoupon,
  127.         final double[] adblFuturesComponentConversionFactor,
  128.         final int iSpotDate,
  129.         final java.lang.String[] astrFundingCurveDepositTenor,
  130.         final double[] adblFundingCurveDepositQuote,
  131.         final java.lang.String strFundingCurveDepositMeasure,
  132.         final double[] adblFundingCurveFuturesQuote,
  133.         final java.lang.String strFundingCurveFuturesMeasure,
  134.         final java.lang.String[] astrFundingCurveFixFloatTenor,
  135.         final double[] adblFundingCurveFixFloatQuote,
  136.         final java.lang.String strFundingFixFloatMeasure,
  137.         final int[] aiGovvieCurveTreasuryEffectiveDate,
  138.         final int[] aiGovvieCurveTreasuryMaturityDate,
  139.         final double[] adblGovvieCurveTreasuryCoupon,
  140.         final double[] adblGovvieCurveTreasuryYield,
  141.         final java.lang.String strGovvieCurveTreasuryMeasure,
  142.         final double[] adblFuturesComponentTreasuryPrice)
  143.     {
  144.         org.drip.analytics.date.JulianDate dtSpot = null;
  145.         org.drip.analytics.date.JulianDate[] adtGovvieCurveTreasuryMaturity = null;
  146.         org.drip.analytics.date.JulianDate[] adtGovvieCurveTreasuryEffective = null;
  147.         int iNumGovvieCurveMaturity = null == aiGovvieCurveTreasuryMaturityDate ? 0 :
  148.             aiGovvieCurveTreasuryMaturityDate.length;
  149.         int iNumGovvieCurveEffective = null == aiGovvieCurveTreasuryEffectiveDate ? 0 :
  150.             aiGovvieCurveTreasuryEffectiveDate.length;
  151.         java.lang.String[] astrTreasuryBenchmarkCode = new java.lang.String[] {"01YON", "02YON", "03YON",
  152.             "05YON", "07YON", "10YON", "30YON"};
  153.         int iNumTreasuryBenchmark = astrTreasuryBenchmarkCode.length;

  154.         if (null == adblFuturesComponentTreasuryPrice) return null;

  155.         if (0 != iNumGovvieCurveMaturity)
  156.             adtGovvieCurveTreasuryMaturity = new org.drip.analytics.date.JulianDate[iNumGovvieCurveMaturity];

  157.         if (0 != iNumGovvieCurveEffective)
  158.             adtGovvieCurveTreasuryEffective = new
  159.                 org.drip.analytics.date.JulianDate[iNumGovvieCurveEffective];

  160.         org.drip.param.market.CurveSurfaceQuoteContainer csqc = new
  161.             org.drip.param.market.CurveSurfaceQuoteContainer();

  162.         try {
  163.             dtSpot = new org.drip.analytics.date.JulianDate (iSpotDate);

  164.             for (int i = 0; i < iNumGovvieCurveMaturity; ++i)
  165.                 adtGovvieCurveTreasuryMaturity[i] = new org.drip.analytics.date.JulianDate
  166.                     (aiGovvieCurveTreasuryMaturityDate[i]);

  167.             for (int i = 0; i < iNumGovvieCurveEffective; ++i)
  168.                 adtGovvieCurveTreasuryEffective[i] = new org.drip.analytics.date.JulianDate
  169.                     (aiGovvieCurveTreasuryEffectiveDate[i]);

  170.             if (null != adblGovvieCurveTreasuryYield && adblGovvieCurveTreasuryYield.length ==
  171.                 iNumTreasuryBenchmark) {
  172.                 for (int i = 0; i < iNumTreasuryBenchmark; ++i) {
  173.                     org.drip.param.quote.ProductMultiMeasure pmm = new
  174.                         org.drip.param.quote.ProductMultiMeasure();

  175.                     pmm.addQuote ("Yield", new org.drip.param.quote.MultiSided ("mid",
  176.                         adblGovvieCurveTreasuryYield[i]), true);

  177.                     if (!csqc.setProductQuote (astrTreasuryBenchmarkCode[i], pmm)) return null;
  178.                 }
  179.             }
  180.         } catch (java.lang.Exception e) {
  181.             e.printStackTrace();

  182.             return null;
  183.         }

  184.         org.drip.product.govvie.TreasuryFutures tsyFut =
  185.             org.drip.service.template.ExchangeInstrumentBuilder.TreasuryFutures (dtSpot, strFuturesCode,
  186.                 aiFuturesComponentTreasuryEffectiveDate, aiFuturesComponentTreasuryMaturityDate,
  187.                     adblFuturesComponentTreasuryCoupon, adblFuturesComponentConversionFactor);

  188.         if (null == tsyFut) return null;

  189.         org.drip.product.definition.Bond[] aBond = tsyFut.basket();

  190.         int iNumFuturesComponent = adblFuturesComponentTreasuryPrice.length;

  191.         for (int i = 0; i < iNumFuturesComponent; ++i) {
  192.             org.drip.param.quote.ProductMultiMeasure pmm = new org.drip.param.quote.ProductMultiMeasure();

  193.             try {
  194.                 pmm.addQuote ("Price", new org.drip.param.quote.MultiSided ("mid",
  195.                     adblFuturesComponentTreasuryPrice[i]), true);
  196.             } catch (java.lang.Exception e) {
  197.                 e.printStackTrace();

  198.                 return null;
  199.             }

  200.             csqc.setProductQuote (aBond[i].name(), pmm);
  201.         }

  202.         org.drip.state.discount.MergedDiscountForwardCurve dcFunding =
  203.             org.drip.service.template.LatentMarketStateBuilder.SmoothFundingCurve (dtSpot,
  204.                 aBond[0].currency(), astrFundingCurveDepositTenor, adblFundingCurveDepositQuote,
  205.                     strFundingCurveDepositMeasure, adblFundingCurveFuturesQuote,
  206.                         strFundingCurveFuturesMeasure, astrFundingCurveFixFloatTenor,
  207.                             adblFundingCurveFixFloatQuote, strFundingFixFloatMeasure);

  208.         csqc.setFundingState (dcFunding);

  209.         org.drip.state.govvie.GovvieCurve gc =
  210.             org.drip.service.template.LatentMarketStateBuilder.ShapePreservingGovvieCurve (tsyFut.type(),
  211.                 dtSpot, adtGovvieCurveTreasuryEffective, adtGovvieCurveTreasuryMaturity,
  212.                     adblGovvieCurveTreasuryCoupon, adblGovvieCurveTreasuryYield,
  213.                         strGovvieCurveTreasuryMeasure);

  214.         csqc.setGovvieState (gc);

  215.         return tsyFut.value (org.drip.param.valuation.ValuationParams.Spot (dtSpot.julian()), null, csqc,
  216.             null);
  217.     }

  218.     /**
  219.      * Generate the Treasury Curve Tenor Key Rate Sensitivity/Duration
  220.      *
  221.      * @param strFuturesCode The Treasury Futures Code
  222.      * @param aiFuturesComponentTreasuryEffectiveDate Array of the Treasury Futures Component Effective Date
  223.      * @param aiFuturesComponentTreasuryMaturityDate Array of the Treasury Futures Component Maturity Date
  224.      * @param adblFuturesComponentTreasuryCoupon Array of the Treasury Futures Component Coupon
  225.      * @param adblFuturesComponentConversionFactor Array of the Treasury Futures Component Conversion Factor
  226.      * @param iSpotDate Spot Date
  227.      * @param aiGovvieCurveTreasuryEffectiveDate Array of the Treasury Instrument Effective Date (for Treasury
  228.      *      Curve)
  229.      * @param aiGovvieCurveTreasuryMaturityDate Array of the Treasury Instrument Maturity Date (for Treasury
  230.      *      Curve)
  231.      * @param adblGovvieCurveTreasuryCoupon Array of the Treasury Instrument Coupon (for Treasury Curve)
  232.      * @param adblGovvieCurveTreasuryYield Array of the Treasury Instrument Yield (for Treasury Curve)
  233.      * @param strGovvieCurveTreasuryMeasure Treasury Instrument Measure (for Govvie Curve)
  234.      * @param adblFuturesComponentTreasuryPrice Array of the Treasury Futures Component Clean Prices
  235.      *
  236.      * @return The Treasury Curve Tenor Sensitivity/Duration
  237.      */

  238.     public static final java.util.Map<java.lang.String, java.lang.Double> KeyRateDuration (
  239.         final java.lang.String strFuturesCode,
  240.         final int[] aiFuturesComponentTreasuryEffectiveDate,
  241.         final int[] aiFuturesComponentTreasuryMaturityDate,
  242.         final double[] adblFuturesComponentTreasuryCoupon,
  243.         final double[] adblFuturesComponentConversionFactor,
  244.         final int iSpotDate,
  245.         final int[] aiGovvieCurveTreasuryEffectiveDate,
  246.         final int[] aiGovvieCurveTreasuryMaturityDate,
  247.         final double[] adblGovvieCurveTreasuryCoupon,
  248.         final double[] adblGovvieCurveTreasuryYield,
  249.         final java.lang.String strGovvieCurveTreasuryMeasure,
  250.         final double[] adblFuturesComponentTreasuryPrice)
  251.     {
  252.         double dblBaselineCTDOAS = java.lang.Double.NaN;
  253.         org.drip.analytics.date.JulianDate dtSpot = null;
  254.         org.drip.analytics.date.JulianDate[] adtGovvieCurveTreasuryMaturity = null;
  255.         org.drip.analytics.date.JulianDate[] adtGovvieCurveTreasuryEffective = null;
  256.         int iNumGovvieCurveMaturity = null == aiGovvieCurveTreasuryMaturityDate ? 0 :
  257.             aiGovvieCurveTreasuryMaturityDate.length;
  258.         int iNumGovvieCurveEffective = null == aiGovvieCurveTreasuryEffectiveDate ? 0 :
  259.             aiGovvieCurveTreasuryEffectiveDate.length;
  260.         java.lang.String[] astrTreasuryBenchmarkCode = new java.lang.String[] {"01YON", "02YON", "03YON",
  261.             "05YON", "07YON", "10YON", "30YON"};
  262.         int iNumTreasuryBenchmark = astrTreasuryBenchmarkCode.length;
  263.         int iNumFuturesComponent = null == adblFuturesComponentTreasuryPrice ? 0 :
  264.             adblFuturesComponentTreasuryPrice.length;

  265.         if (0 == iNumFuturesComponent) return null;

  266.         if (0 != iNumGovvieCurveMaturity)
  267.             adtGovvieCurveTreasuryMaturity = new org.drip.analytics.date.JulianDate[iNumGovvieCurveMaturity];

  268.         if (0 != iNumGovvieCurveEffective)
  269.             adtGovvieCurveTreasuryEffective = new
  270.                 org.drip.analytics.date.JulianDate[iNumGovvieCurveEffective];

  271.         org.drip.param.market.CurveSurfaceQuoteContainer csqc = new
  272.             org.drip.param.market.CurveSurfaceQuoteContainer();

  273.         try {
  274.             dtSpot = new org.drip.analytics.date.JulianDate (iSpotDate);

  275.             for (int i = 0; i < iNumGovvieCurveMaturity; ++i)
  276.                 adtGovvieCurveTreasuryMaturity[i] = new org.drip.analytics.date.JulianDate
  277.                     (aiGovvieCurveTreasuryMaturityDate[i]);

  278.             for (int i = 0; i < iNumGovvieCurveEffective; ++i)
  279.                 adtGovvieCurveTreasuryEffective[i] = new org.drip.analytics.date.JulianDate
  280.                     (aiGovvieCurveTreasuryEffectiveDate[i]);

  281.             if (null != adblGovvieCurveTreasuryYield && adblGovvieCurveTreasuryYield.length ==
  282.                 iNumTreasuryBenchmark) {
  283.                 for (int i = 0; i < iNumTreasuryBenchmark; ++i) {
  284.                     org.drip.param.quote.ProductMultiMeasure pmm = new
  285.                         org.drip.param.quote.ProductMultiMeasure();

  286.                     pmm.addQuote ("Yield", new org.drip.param.quote.MultiSided ("mid",
  287.                         adblGovvieCurveTreasuryYield[i]), true);

  288.                     if (!csqc.setProductQuote (astrTreasuryBenchmarkCode[i], pmm)) return null;
  289.                 }
  290.             }
  291.         } catch (java.lang.Exception e) {
  292.             e.printStackTrace();

  293.             return null;
  294.         }

  295.         org.drip.product.govvie.TreasuryFutures tsyFut =
  296.             org.drip.service.template.ExchangeInstrumentBuilder.TreasuryFutures (dtSpot, strFuturesCode,
  297.                 aiFuturesComponentTreasuryEffectiveDate, aiFuturesComponentTreasuryMaturityDate,
  298.                     adblFuturesComponentTreasuryCoupon, adblFuturesComponentConversionFactor);

  299.         if (null == tsyFut) return null;

  300.         org.drip.product.definition.Bond[] aBond = tsyFut.basket();

  301.         for (int i = 0; i < iNumFuturesComponent; ++i) {
  302.             org.drip.param.quote.ProductMultiMeasure pmm = new org.drip.param.quote.ProductMultiMeasure();

  303.             try {
  304.                 pmm.addQuote ("Price", new org.drip.param.quote.MultiSided ("mid",
  305.                     adblFuturesComponentTreasuryPrice[i]), true);
  306.             } catch (java.lang.Exception e) {
  307.                 e.printStackTrace();

  308.                 return null;
  309.             }

  310.             if (!csqc.setProductQuote (aBond[i].name(), pmm)) return null;
  311.         }

  312.         java.lang.String strTreasuryType = tsyFut.type();

  313.         if (!csqc.setGovvieState
  314.             (org.drip.service.template.LatentMarketStateBuilder.ShapePreservingGovvieCurve (strTreasuryType,
  315.                 dtSpot, adtGovvieCurveTreasuryEffective, adtGovvieCurveTreasuryMaturity,
  316.                     adblGovvieCurveTreasuryCoupon, adblGovvieCurveTreasuryYield,
  317.                         strGovvieCurveTreasuryMeasure)))
  318.             return null;

  319.         org.drip.product.params.CTDEntry ctdEntry = tsyFut.cheapestToDeliverYield (iSpotDate,
  320.             adblFuturesComponentTreasuryPrice);

  321.         if (null == ctdEntry) return null;

  322.         org.drip.product.definition.Bond bondCTD = ctdEntry.bond();

  323.         if (null == bondCTD) return null;

  324.         double dblCTDExpiryPrice = ctdEntry.forwardPrice();

  325.         org.drip.param.valuation.ValuationParams valParamsExpiry =
  326.             org.drip.param.valuation.ValuationParams.Spot (tsyFut.expiry().julian());

  327.         try {
  328.             if (!org.drip.numerical.common.NumberUtil.IsValid (dblBaselineCTDOAS = bondCTD.oasFromPrice
  329.                 (valParamsExpiry, csqc, null, dblCTDExpiryPrice)))
  330.                 return null;
  331.         } catch (java.lang.Exception e) {
  332.             e.printStackTrace();

  333.             return null;
  334.         }

  335.         org.drip.analytics.support.CaseInsensitiveTreeMap<org.drip.state.govvie.GovvieCurve>
  336.             mapTenorGovvieCurve = org.drip.service.template.LatentMarketStateBuilder.BumpedGovvieCurve
  337.                 (strTreasuryType, dtSpot, adtGovvieCurveTreasuryEffective, adtGovvieCurveTreasuryMaturity,
  338.                     adblGovvieCurveTreasuryCoupon, adblGovvieCurveTreasuryYield,
  339.                         strGovvieCurveTreasuryMeasure,
  340.                             org.drip.service.template.LatentMarketStateBuilder.SHAPE_PRESERVING, 0.0001,
  341.                                 false);

  342.         if (null == mapTenorGovvieCurve || iNumTreasuryBenchmark > mapTenorGovvieCurve.size()) return null;

  343.         org.drip.analytics.support.CaseInsensitiveTreeMap<java.lang.Double> mapKeyRateDuration = new
  344.             org.drip.analytics.support.CaseInsensitiveTreeMap<java.lang.Double>();

  345.         for (java.util.Map.Entry<java.lang.String, org.drip.state.govvie.GovvieCurve> me :
  346.             mapTenorGovvieCurve.entrySet()) {
  347.             java.lang.String strKey = me.getKey();

  348.             if (!strKey.contains ("tsy")) continue;

  349.             if (!csqc.setGovvieState (me.getValue())) return null;

  350.             org.drip.product.params.CTDEntry tenorCTDEntry = tsyFut.cheapestToDeliverYield (iSpotDate,
  351.                 adblFuturesComponentTreasuryPrice);

  352.             if (null == tenorCTDEntry) return null;

  353.             org.drip.product.definition.Bond tenorBondCTD = tenorCTDEntry.bond();

  354.             if (null == tenorBondCTD) return null;

  355.             try {
  356.                 mapKeyRateDuration.put (strKey, 10000. * (tenorBondCTD.priceFromOAS (valParamsExpiry, csqc,
  357.                     null, dblBaselineCTDOAS) - dblCTDExpiryPrice) / dblCTDExpiryPrice);
  358.             } catch (java.lang.Exception e) {
  359.                 e.printStackTrace();

  360.                 return null;
  361.             }
  362.         }

  363.         return mapKeyRateDuration;
  364.     }

  365.     /**
  366.      * Returns Attribution for the Treasury Futures
  367.      *
  368.      * @param strTreasuryCode The Treasury Code
  369.      * @param adtEffective Array of Effective Dates
  370.      * @param adtMaturity Array of Maturity Dates
  371.      * @param adblCoupon Array of Coupons
  372.      * @param adtExpiry Array of Futures Expiry Dates
  373.      * @param adtSpot Array of Spot Dates
  374.      * @param adblCleanPrice Array of Closing Clean Prices
  375.      * @param adblConversionFactor Array of the Conversion Factor
  376.      *
  377.      * @return List of the Position Change Components
  378.      */

  379.     public static final java.util.List<org.drip.historical.attribution.PositionChangeComponents>
  380.         HorizonChangeAttribution (
  381.             final java.lang.String strTreasuryCode,
  382.             final org.drip.analytics.date.JulianDate[] adtEffective,
  383.             final org.drip.analytics.date.JulianDate[] adtMaturity,
  384.             final double[] adblCoupon,
  385.             final org.drip.analytics.date.JulianDate[] adtExpiry,
  386.             final org.drip.analytics.date.JulianDate[] adtSpot,
  387.             final double[] adblCleanPrice,
  388.             final double[] adblConversionFactor)
  389.     {
  390.         org.drip.product.credit.BondComponent[] aTreasury =
  391.             org.drip.service.template.TreasuryBuilder.FromCode (strTreasuryCode, adtEffective, adtMaturity,
  392.                 adblCoupon);

  393.         if (null == aTreasury || null == adtExpiry || null == adtSpot || null == adblCleanPrice || null ==
  394.             adblConversionFactor)
  395.             return null;

  396.         int iNumCloses = adtSpot.length;
  397.         int[] aiExpiryDate = new int[iNumCloses];
  398.         double[] adblYield = new double[iNumCloses];
  399.         double[] adblForwardAccrued = new double[iNumCloses];
  400.         double[] adblForwardCleanPrice = new double[iNumCloses];
  401.         double[] adblForwardModifiedDuration = new double[iNumCloses];

  402.         if (1 >= iNumCloses || iNumCloses != aTreasury.length || iNumCloses != adblCleanPrice.length ||
  403.             iNumCloses != adtExpiry.length || iNumCloses != adblConversionFactor.length)
  404.             return null;

  405.         java.util.List<org.drip.historical.attribution.PositionChangeComponents> lsPCC = new
  406.             java.util.ArrayList<org.drip.historical.attribution.PositionChangeComponents>();

  407.         for (int i = 0; i < iNumCloses; ++i) {
  408.             if (null == aTreasury[i]) return null;

  409.             org.drip.param.valuation.ValuationParams valParamsSpot =
  410.                 org.drip.param.valuation.ValuationParams.Spot (adtSpot[i].julian());

  411.             org.drip.param.valuation.ValuationParams valParamsExpiry =
  412.                 org.drip.param.valuation.ValuationParams.Spot (aiExpiryDate[i] = adtExpiry[i].julian());

  413.             try {
  414.                 adblForwardAccrued[i] = aTreasury[i].accrued (aiExpiryDate[i], null);

  415.                 adblYield[i] = aTreasury[i].yieldFromPrice (valParamsSpot, null, null, adblCleanPrice[i]);

  416.                 adblForwardCleanPrice[i] = aTreasury[i].priceFromYield (valParamsExpiry, null, null,
  417.                     adblYield[i]);

  418.                 adblForwardModifiedDuration[i] = aTreasury[i].modifiedDurationFromPrice (valParamsExpiry,
  419.                     null, null, adblForwardCleanPrice[i]) * 10000.;
  420.             } catch (java.lang.Exception e) {
  421.                 e.printStackTrace();
  422.             }
  423.         }

  424.         for (int i = 1; i < iNumCloses; ++i) {
  425.             if (adblConversionFactor[i] != adblConversionFactor[i - 1]) continue;

  426.             java.lang.String strCurrentBondName = aTreasury[i].name();

  427.             java.lang.String strPreviousBondName = aTreasury[i - 1].name();

  428.             double dblScaledPrice1 = (adblForwardCleanPrice[i - 1] + adblForwardAccrued[i - 1]) /
  429.                 adblConversionFactor[i - 1];
  430.             double dblScaledPrice2 = (adblForwardCleanPrice[i] + adblForwardAccrued[i]) /
  431.                 adblConversionFactor[i];

  432.             try {
  433.                 org.drip.historical.attribution.TreasuryFuturesMarketSnap tfpms1 = new
  434.                     org.drip.historical.attribution.TreasuryFuturesMarketSnap (adtSpot[i - 1],
  435.                         dblScaledPrice1);

  436.                 if (!tfpms1.setYieldMarketFactor (adblYield[i - 1], -1. * dblScaledPrice1 *
  437.                     adblForwardModifiedDuration[i - 1], 0.) || !tfpms1.setExpiryDate (adtExpiry[i - 1]) ||
  438.                         !tfpms1.setCTDName (strPreviousBondName) || !tfpms1.setCleanExpiryPrice
  439.                             (adblForwardCleanPrice[i - 1]) || !tfpms1.setConversionFactor
  440.                                 (adblConversionFactor[i - 1]))
  441.                     return null;

  442.                 org.drip.historical.attribution.TreasuryFuturesMarketSnap tfpms2 = new
  443.                     org.drip.historical.attribution.TreasuryFuturesMarketSnap (adtSpot[i],
  444.                         dblScaledPrice2);

  445.                 if (!tfpms2.setYieldMarketFactor (adblYield[i], -1. * dblScaledPrice2 *
  446.                     adblForwardModifiedDuration[i], 0.) || !tfpms2.setExpiryDate (adtExpiry[i]) ||
  447.                         !tfpms2.setCTDName (strCurrentBondName) || !tfpms2.setCleanExpiryPrice
  448.                             (adblForwardCleanPrice[i]) || !tfpms2.setConversionFactor
  449.                                 (adblConversionFactor[i]))
  450.                     return null;

  451.                 org.drip.historical.attribution.PositionChangeComponents pcc = new
  452.                     org.drip.historical.attribution.PositionChangeComponents (false, tfpms1, tfpms2, 0.,
  453.                         null);

  454.                 lsPCC.add (pcc);
  455.             } catch (java.lang.Exception e) {
  456.                 e.printStackTrace();
  457.             }
  458.         }

  459.         return lsPCC;
  460.     }

  461.     /**
  462.      * Generate the Horizon Treasury Curve Tenor Key Rate Sensitivity/Duration
  463.      *
  464.      * @param strTreasuryType The Treasury Type
  465.      * @param adtEffective Array of Effective Dates
  466.      * @param adtMaturity Array of Maturity Dates
  467.      * @param adblCoupon Array of Coupons
  468.      * @param adtExpiry Array of Futures Expiry Dates
  469.      * @param adtSpot Array of Spot Dates
  470.      * @param adblCleanPrice Array of Closing Clean Prices
  471.      * @param astrBenchmarkTenor Array of Benchmark Tenors
  472.      * @param aadblGovvieCurveTreasuryYield Array of the Treasury Instrument Yield (for Treasury Curve)
  473.      *
  474.      * @return The Treasury Curve Tenor Sensitivity/Duration
  475.      */

  476.     public static final java.util.List<org.drip.historical.sensitivity.TenorDurationNodeMetrics>
  477.         HorizonKeyRateDuration (
  478.             final java.lang.String strTreasuryType,
  479.             final org.drip.analytics.date.JulianDate[] adtEffective,
  480.             final org.drip.analytics.date.JulianDate[] adtMaturity,
  481.             final double[] adblCoupon,
  482.             final org.drip.analytics.date.JulianDate[] adtExpiry,
  483.             final org.drip.analytics.date.JulianDate[] adtSpot,
  484.             final double[] adblCleanPrice,
  485.             final java.lang.String[] astrBenchmarkTenor,
  486.             final double[][] aadblGovvieCurveTreasuryYield)
  487.     {
  488.         if (null == adtSpot || null == astrBenchmarkTenor || null == aadblGovvieCurveTreasuryYield || null ==
  489.             aadblGovvieCurveTreasuryYield[0])
  490.             return null;

  491.         double dblExpiryCleanPrice = java.lang.Double.NaN;
  492.         double dblExpiryGSpread = java.lang.Double.NaN;
  493.         int iNumBenchmark = astrBenchmarkTenor.length;
  494.         double dblExpiryYield = java.lang.Double.NaN;
  495.         double dblSpotGSpread = java.lang.Double.NaN;
  496.         double dblSpotYield = java.lang.Double.NaN;
  497.         int iNumCloses = adtSpot.length;

  498.         if (0 >= iNumCloses || iNumCloses != aadblGovvieCurveTreasuryYield.length) return null;

  499.         java.util.List<org.drip.historical.sensitivity.TenorDurationNodeMetrics> lsTDNM = new
  500.             java.util.ArrayList<org.drip.historical.sensitivity.TenorDurationNodeMetrics>();

  501.         for (int i = 0; i < iNumCloses; ++i) {
  502.             if (null == aadblGovvieCurveTreasuryYield[i] || iNumBenchmark !=
  503.                 aadblGovvieCurveTreasuryYield[i].length)
  504.                 return null;

  505.             org.drip.analytics.date.JulianDate[] adtGovvieCurveTreasuryEffective = new
  506.                 org.drip.analytics.date.JulianDate[iNumBenchmark];
  507.             org.drip.analytics.date.JulianDate[] adtGovvieCurveTreasuryMaturity = new
  508.                 org.drip.analytics.date.JulianDate[iNumBenchmark];
  509.             org.drip.historical.sensitivity.TenorDurationNodeMetrics tdnm = null;
  510.             double dblParallelKRD = 0.;

  511.             for (int j = 0; j < iNumBenchmark; ++j) {
  512.                 adtGovvieCurveTreasuryEffective[j] = adtSpot[i];

  513.                 adtGovvieCurveTreasuryMaturity[j] = adtSpot[i].addTenor (astrBenchmarkTenor[j]);
  514.             }

  515.             org.drip.state.govvie.GovvieCurve gc =
  516.                 org.drip.service.template.LatentMarketStateBuilder.ShapePreservingGovvieCurve
  517.                     (strTreasuryType, adtSpot[i], adtGovvieCurveTreasuryEffective,
  518.                         adtGovvieCurveTreasuryMaturity, aadblGovvieCurveTreasuryYield[i],
  519.                             aadblGovvieCurveTreasuryYield[i], "Yield");

  520.             org.drip.param.market.CurveSurfaceQuoteContainer csqc = new
  521.                 org.drip.param.market.CurveSurfaceQuoteContainer();

  522.             if (!csqc.setGovvieState (gc)) continue;

  523.             org.drip.param.valuation.ValuationParams valParamsSpot =
  524.                 org.drip.param.valuation.ValuationParams.Spot (adtSpot[i].julian());

  525.             org.drip.param.valuation.ValuationParams valParamsExpiry =
  526.                 org.drip.param.valuation.ValuationParams.Spot (adtExpiry[i].julian());

  527.             org.drip.product.credit.BondComponent bondCTD =
  528.                 org.drip.service.template.TreasuryBuilder.FromCode (strTreasuryType, adtEffective[i],
  529.                     adtMaturity[i], adblCoupon[i]);

  530.             if (null == bondCTD) continue;

  531.             try {
  532.                 dblSpotGSpread = bondCTD.gSpreadFromPrice (valParamsSpot, csqc, null, adblCleanPrice[i]);

  533.                 dblSpotYield = bondCTD.yieldFromPrice (valParamsSpot, csqc, null, adblCleanPrice[i]);

  534.                 dblExpiryCleanPrice = bondCTD.priceFromGSpread (valParamsExpiry, csqc, null, dblSpotGSpread);

  535.                 dblExpiryGSpread = bondCTD.gSpreadFromPrice (valParamsExpiry, csqc, null,
  536.                     dblExpiryCleanPrice);

  537.                 dblExpiryYield = bondCTD.yieldFromPrice (valParamsExpiry, csqc, null, dblExpiryCleanPrice);
  538.             } catch (java.lang.Exception e) {
  539.                 e.printStackTrace();

  540.                 continue;
  541.             }

  542.             org.drip.analytics.support.CaseInsensitiveTreeMap<org.drip.state.govvie.GovvieCurve>
  543.                 mapTenorGovvieCurve = org.drip.service.template.LatentMarketStateBuilder.BumpedGovvieCurve
  544.                     (strTreasuryType, adtSpot[i], adtGovvieCurveTreasuryEffective,
  545.                         adtGovvieCurveTreasuryMaturity, aadblGovvieCurveTreasuryYield[i],
  546.                             aadblGovvieCurveTreasuryYield[i], "Yield",
  547.                                 org.drip.service.template.LatentMarketStateBuilder.SHAPE_PRESERVING, 0.0001,
  548.                                     false);

  549.             if (null == mapTenorGovvieCurve || iNumBenchmark > mapTenorGovvieCurve.size()) continue;

  550.             try {
  551.                 tdnm = new org.drip.historical.sensitivity.TenorDurationNodeMetrics (adtSpot[i]);
  552.             } catch (java.lang.Exception e) {
  553.                 e.printStackTrace();

  554.                 return null;
  555.             }

  556.             tdnm.setR1 ("SpotGSpread", dblSpotGSpread);

  557.             tdnm.setR1 ("ExpiryGSpread", dblExpiryGSpread);

  558.             tdnm.setR1 ("SpotYield", dblSpotYield);

  559.             tdnm.setR1 ("ExpiryYield", dblExpiryYield);

  560.             tdnm.setDate ("ExpiryDate", adtExpiry[i]);

  561.             tdnm.setC1 ("CTDName", bondCTD.name());

  562.             tdnm.setR1 ("SpotCTDCleanPrice", adblCleanPrice[i]);

  563.             tdnm.setR1 ("ExpiryCTDCleanPrice", dblExpiryCleanPrice);

  564.             for (java.util.Map.Entry<java.lang.String, org.drip.state.govvie.GovvieCurve> me :
  565.                 mapTenorGovvieCurve.entrySet()) {
  566.                 java.lang.String strKey = me.getKey();

  567.                 if (!strKey.contains ("tsy")) continue;

  568.                 if (!csqc.setGovvieState (me.getValue())) return null;

  569.                 double dblTenorKRD = java.lang.Double.NaN;

  570.                 try {
  571.                     dblTenorKRD = -10000. * (bondCTD.priceFromGSpread (valParamsExpiry, csqc, null,
  572.                         dblSpotGSpread) - dblExpiryCleanPrice) / dblExpiryCleanPrice;

  573.                     if (!tdnm.addKRDNode (strKey, dblTenorKRD)) continue;

  574.                     dblParallelKRD += dblTenorKRD;
  575.                 } catch (java.lang.Exception e) {
  576.                     e.printStackTrace();

  577.                     return null;
  578.                 }
  579.             }

  580.             tdnm.setR1 ("ParallelKRD", dblParallelKRD);

  581.             lsTDNM.add (tdnm);
  582.         }

  583.         return lsTDNM;
  584.     }
  585. }