Bullet.java

  1. package org.drip.analytics.cashflow;

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

  79. /**
  80.  * <i>Bullet</i> is designed to hold the Point Realizations of the Latent States relevant to Terminal
  81.  * Valuation of a Bullet Cash Flow. Current it contains the Period Dates, Period Latent State Identifiers,
  82.  * and the "Extensive" Fields.
  83.  *
  84.  *  <br><br>
  85.  *  <ul>
  86.  *      <li><b>Module </b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/ProductCore.md">Product Core Module</a></li>
  87.  *      <li><b>Library</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/FixedIncomeAnalyticsLibrary.md">Fixed Income Analytics</a></li>
  88.  *      <li><b>Project</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/analytics/README.md">Date, Cash Flow, and Cash Flow Period Measure Generation Utilities</a></li>
  89.  *      <li><b>Package</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/analytics/cashflow/README.md">Unit and Composite Cash Flow Periods</a></li>
  90.  *  </ul>
  91.  *
  92.  * @author Lakshmi Krishnamurthy
  93.  */

  94. public class Bullet {

  95.     /*
  96.      * Date Fields
  97.      */

  98.     private int _iPayDate = java.lang.Integer.MIN_VALUE;
  99.     private int _iFXFixingDate = java.lang.Integer.MIN_VALUE;
  100.     private int _iTerminalDate = java.lang.Integer.MIN_VALUE;

  101.     /*
  102.      * Period Latent State Identification Support Fields
  103.      */

  104.     private java.lang.String _strPayCurrency = "";
  105.     private java.lang.String _strCouponCurrency = "";
  106.     private org.drip.state.identifier.EntityCDSLabel _creditLabel = null;

  107.     /*
  108.      * Period Cash Extensive Fields
  109.      */

  110.     private double _dblBaseNotional = java.lang.Double.NaN;
  111.     private org.drip.numerical.common.Array2D _a2DNotionalSchedule = null;

  112.     private org.drip.analytics.output.ConvexityAdjustment convexityAdjustment (
  113.         final int iValueDate,
  114.         final org.drip.param.market.CurveSurfaceQuoteContainer csqc)
  115.     {
  116.         org.drip.state.identifier.FXLabel fxLabel = fxLabel();

  117.         org.drip.state.identifier.EntityCDSLabel creditLabel = creditLabel();

  118.         org.drip.state.identifier.FundingLabel fundingLabel = fundingLabel();

  119.         org.drip.analytics.output.ConvexityAdjustment convAdj = new
  120.             org.drip.analytics.output.ConvexityAdjustment();

  121.         try {
  122.             if (
  123.                 !convAdj.setCreditFunding (
  124.                     null != csqc ? java.lang.Math.exp (
  125.                         org.drip.analytics.support.OptionHelper.IntegratedCrossVolQuanto (
  126.                             csqc.creditVolatility (creditLabel),
  127.                             csqc.fundingVolatility (fundingLabel),
  128.                             csqc.creditFundingCorrelation (
  129.                                 creditLabel,
  130.                                 fundingLabel
  131.                             ),
  132.                             iValueDate,
  133.                             _iPayDate
  134.                         )
  135.                     ) : 1.
  136.                 ))
  137.                 return null;

  138.             if (
  139.                 !convAdj.setCreditFX (
  140.                     null != csqc && isFXMTM() ? java.lang.Math.exp (
  141.                         org.drip.analytics.support.OptionHelper.IntegratedCrossVolQuanto (
  142.                             csqc.creditVolatility (creditLabel),
  143.                             csqc.fxVolatility (fxLabel),
  144.                             csqc.creditFXCorrelation (
  145.                                 creditLabel,
  146.                                 fxLabel
  147.                             ),
  148.                             iValueDate,
  149.                             _iPayDate
  150.                         )
  151.                     ) : 1.
  152.                 ))
  153.                 return null;

  154.             if (
  155.                 !convAdj.setFundingFX (
  156.                     null != csqc && isFXMTM() ? java.lang.Math.exp (
  157.                         org.drip.analytics.support.OptionHelper.IntegratedCrossVolQuanto (
  158.                             csqc.fundingVolatility (fundingLabel),
  159.                             csqc.fxVolatility (fxLabel),
  160.                             csqc.fundingFXCorrelation (
  161.                                 fundingLabel,
  162.                                 fxLabel
  163.                             ),
  164.                             iValueDate,
  165.                             _iPayDate
  166.                         )
  167.                     ) : 1.
  168.                 ))
  169.                 return null;

  170.             return convAdj;
  171.         } catch (java.lang.Exception e) {
  172.             e.printStackTrace();
  173.         }

  174.         return null;
  175.     }

  176.     /**
  177.      * Construct a Bullet Instance from the specified Parameters
  178.      *
  179.      * @param iTerminalDate Period End Date
  180.      * @param iPayDate Period Pay Date
  181.      * @param iFXFixingDate FX Fixing Date for non-MTM Cash-flow
  182.      * @param dblBaseNotional Coupon Period Base Notional
  183.      * @param a2DNotionalSchedule Coupon Period Notional Schedule
  184.      * @param strPayCurrency Pay Currency
  185.      * @param strCouponCurrency Coupon Currency
  186.      * @param creditLabel Credit Label
  187.      *
  188.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  189.      */

  190.     public Bullet (
  191.         final int iTerminalDate,
  192.         final int iPayDate,
  193.         final int iFXFixingDate,
  194.         final double dblBaseNotional,
  195.         final org.drip.numerical.common.Array2D a2DNotionalSchedule,
  196.         final java.lang.String strPayCurrency,
  197.         final java.lang.String strCouponCurrency,
  198.         final org.drip.state.identifier.EntityCDSLabel creditLabel)
  199.         throws java.lang.Exception
  200.     {
  201.         if (!org.drip.numerical.common.NumberUtil.IsValid (_dblBaseNotional = dblBaseNotional) ||
  202.             null == (_strPayCurrency = strPayCurrency) || _strPayCurrency.isEmpty() ||
  203.             null == (_strCouponCurrency = strCouponCurrency) || _strCouponCurrency.isEmpty())
  204.         throw new java.lang.Exception ("Bullet Constructor => Invalid inputs");

  205.         _iPayDate = iPayDate;
  206.         _creditLabel = creditLabel;
  207.         _iFXFixingDate = iFXFixingDate;
  208.         _iTerminalDate = iTerminalDate;

  209.         if (null == (_a2DNotionalSchedule = a2DNotionalSchedule))
  210.             _a2DNotionalSchedule = org.drip.numerical.common.Array2D.BulletSchedule();
  211.     }

  212.     /**
  213.      * Retrieve the Terminal Date
  214.      *
  215.      * @return Terminal Date
  216.      */

  217.     public int terminalDate()
  218.     {
  219.         return _iTerminalDate;
  220.     }

  221.     /**
  222.      * Retrieve the Period Pay Date
  223.      *
  224.      * @return Period Pay Date
  225.      */

  226.     public int payDate()
  227.     {
  228.         return _iPayDate;
  229.     }

  230.     /**
  231.      * Retrieve the Period FX Fixing Date
  232.      *
  233.      * @return Period FX Fixing Date
  234.      */

  235.     public int fxFixingDate()
  236.     {
  237.         return _iFXFixingDate;
  238.     }

  239.     /**
  240.      * Coupon Period FX
  241.      *
  242.      * @param csqc Market Parameters
  243.      *
  244.      * @return Period FX
  245.      *
  246.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  247.      */

  248.     public double fx (
  249.         final org.drip.param.market.CurveSurfaceQuoteContainer csqc)
  250.         throws java.lang.Exception
  251.     {
  252.         org.drip.state.identifier.FXLabel fxLabel = fxLabel();

  253.         if (null == fxLabel) return 1.;

  254.         if (null == csqc) throw new java.lang.Exception ("Bullet::fx => Invalid Inputs");

  255.         if (!isFXMTM()) return csqc.fixing (_iFXFixingDate, fxLabel);

  256.         org.drip.state.fx.FXCurve fxfc = csqc.fxState (fxLabel);

  257.         if (null == fxfc)
  258.             throw new java.lang.Exception ("Bullet::fx => No Curve for " + fxLabel.fullyQualifiedName());

  259.         return fxfc.fx (_iPayDate);
  260.     }

  261.     /**
  262.      * Is the Cash Flow FX MTM?
  263.      *
  264.      * @return true - FX MTM is on (i.e., FX is not driven by FX Fixing)
  265.      */

  266.     public boolean isFXMTM()
  267.     {
  268.         return java.lang.Integer.MIN_VALUE != _iFXFixingDate;
  269.     }

  270.     /**
  271.      * Retrieve the Pay Currency
  272.      *
  273.      * @return The Pay Currency
  274.      */

  275.     public java.lang.String payCurrency()
  276.     {
  277.         return _strPayCurrency;
  278.     }

  279.     /**
  280.      * Retrieve the Coupon Currency
  281.      *
  282.      * @return The Coupon Currency
  283.      */

  284.     public java.lang.String couponCurrency()
  285.     {
  286.         return _strCouponCurrency;
  287.     }

  288.     /**
  289.      * Get the Base Notional
  290.      *
  291.      * @return Base Notional
  292.      */

  293.     public double baseNotional()
  294.     {
  295.         return _dblBaseNotional;
  296.     }

  297.     /**
  298.      * Get the Notional Schedule
  299.      *
  300.      * @return Notional Schedule
  301.      */

  302.     public org.drip.numerical.common.Array2D notionalSchedule()
  303.     {
  304.         return _a2DNotionalSchedule;
  305.     }

  306.     /**
  307.      * Notional corresponding to the specified Date
  308.      *
  309.      * @param iDate The Specified Date
  310.      *
  311.      * @return The Corresponding to the specified Date
  312.      *
  313.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  314.      */

  315.     public double notional (
  316.         final int iDate)
  317.         throws java.lang.Exception
  318.     {
  319.         return _dblBaseNotional * (null == _a2DNotionalSchedule ? 1. : _a2DNotionalSchedule.y (iDate));
  320.     }

  321.     /**
  322.      * Notional Aggregated over the specified Dates
  323.      *
  324.      * @param iDate1 The Date #1
  325.      * @param iDate2 The Date #2
  326.      *
  327.      * @return The Notional Aggregated over the specified Dates
  328.      *
  329.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  330.      */

  331.     public double notional (
  332.         final int iDate1,
  333.         final int iDate2)
  334.         throws java.lang.Exception
  335.     {
  336.         return _dblBaseNotional * (
  337.             null == _a2DNotionalSchedule ? 1. : _a2DNotionalSchedule.y (
  338.                 iDate1,
  339.                 iDate2
  340.             )
  341.         );
  342.     }

  343.     /**
  344.      * Return the Collateral Label
  345.      *
  346.      * @return The Collateral Label
  347.      */

  348.     public org.drip.state.identifier.CollateralLabel collateralLabel()
  349.     {
  350.         return org.drip.state.identifier.CollateralLabel.Standard (_strPayCurrency);
  351.     }

  352.     /**
  353.      * Return the Credit Label
  354.      *
  355.      * @return The Credit Label
  356.      */

  357.     public org.drip.state.identifier.EntityCDSLabel creditLabel()
  358.     {
  359.         return _creditLabel;
  360.     }

  361.     /**
  362.      * Return the Funding Label
  363.      *
  364.      * @return The Funding Label
  365.      */

  366.     public org.drip.state.identifier.FundingLabel fundingLabel()
  367.     {
  368.         return org.drip.state.identifier.FundingLabel.Standard (_strPayCurrency);
  369.     }

  370.     /**
  371.      * Return the FX Label
  372.      *
  373.      * @return The FX Label
  374.      */

  375.     public org.drip.state.identifier.FXLabel fxLabel()
  376.     {
  377.         return _strPayCurrency.equalsIgnoreCase (_strCouponCurrency) ? null :
  378.             org.drip.state.identifier.FXLabel.Standard (_strPayCurrency + "/" + _strCouponCurrency);
  379.     }

  380.     /**
  381.      * Compute the Metrics at the specified Valuation Date
  382.      *
  383.      * @param iValueDate Valuation Date
  384.      * @param csqc The Market Curve Surface/Quote Set
  385.      *
  386.      * @return The Metrics at the specified Valuation Date
  387.      */

  388.     public org.drip.analytics.output.BulletMetrics metrics (
  389.         final int iValueDate,
  390.         final org.drip.param.market.CurveSurfaceQuoteContainer csqc)
  391.     {
  392.         double dblDF = 1.;
  393.         double dblSurvival = 1.;

  394.         org.drip.state.identifier.FXLabel fxLabel = fxLabel();

  395.         org.drip.state.identifier.FundingLabel fundingLabel = fundingLabel();

  396.         org.drip.state.credit.CreditCurve cc = null == csqc ? null :
  397.             csqc.creditState (_creditLabel);

  398.         org.drip.state.discount.MergedDiscountForwardCurve dcFunding = null == csqc ? null :
  399.             csqc.fundingState (fundingLabel);

  400.         try {
  401.             double dblFX = fx (csqc);

  402.             if (null != dcFunding) dblDF = dcFunding.df (_iPayDate);

  403.             if (null != cc) dblSurvival = cc.survival (_iPayDate);

  404.             return new org.drip.analytics.output.BulletMetrics (
  405.                 _iTerminalDate,
  406.                 _iPayDate,
  407.                 notional (_iTerminalDate),
  408.                 dblSurvival,
  409.                 dblDF,
  410.                 dblFX,
  411.                 convexityAdjustment (
  412.                     iValueDate,
  413.                     csqc
  414.                 ),
  415.                 _creditLabel,
  416.                 fundingLabel,
  417.                 fxLabel
  418.             );
  419.         } catch (java.lang.Exception e) {
  420.             e.printStackTrace();
  421.         }

  422.         return null;
  423.     }

  424.     /**
  425.      * Generate the Funding Predictor/Response Constraint
  426.      *
  427.      * @param iValueDate Valuation Date
  428.      * @param csqc Market Curve Surface/Quote Set
  429.      * @param pqs Calibration Product Quote Set
  430.      *
  431.      * @return The Funding Predictor/Response Constraint
  432.      */

  433.     public org.drip.state.estimator.PredictorResponseWeightConstraint fundingPRWC (
  434.         final int iValueDate,
  435.         final org.drip.param.market.CurveSurfaceQuoteContainer csqc,
  436.         final org.drip.product.calib.ProductQuoteSet pqs)
  437.     {
  438.         if (null == pqs) return null;

  439.         double dblPV = 0.;

  440.         org.drip.state.estimator.PredictorResponseWeightConstraint prwc = new
  441.             org.drip.state.estimator.PredictorResponseWeightConstraint();

  442.         org.drip.analytics.output.BulletMetrics bm = metrics (
  443.             iValueDate,
  444.             csqc
  445.         );

  446.         if (null == bm) return null;

  447.         java.util.Map<java.lang.Integer, java.lang.Double> mapDiscountFactorLoading =
  448.             bm.discountFactorFundingLoading (pqs.fundingLabel());

  449.         if (null != mapDiscountFactorLoading && 0 != mapDiscountFactorLoading.size()) {
  450.             for (java.util.Map.Entry<java.lang.Integer, java.lang.Double> meDiscountFactorLoading :
  451.                 mapDiscountFactorLoading.entrySet()) {
  452.                 int iDateAnchor = meDiscountFactorLoading.getKey();

  453.                 double dblDiscountFactorFundingLoading = meDiscountFactorLoading.getValue();

  454.                 if (
  455.                     !prwc.addPredictorResponseWeight (
  456.                         iDateAnchor,
  457.                         dblDiscountFactorFundingLoading
  458.                     )
  459.                 )
  460.                     return null;

  461.                 if (
  462.                     !prwc.addDResponseWeightDManifestMeasure (
  463.                         "PV",
  464.                         iDateAnchor,
  465.                         dblDiscountFactorFundingLoading
  466.                     )
  467.                 )
  468.                     return null;
  469.             }
  470.         } else
  471.             dblPV -= bm.annuity();

  472.         if (!prwc.updateValue (dblPV)) return null;

  473.         if (
  474.             !prwc.updateDValueDManifestMeasure (
  475.                 "PV",
  476.                 1.
  477.             )
  478.         )
  479.             return null;

  480.         return prwc;
  481.     }
  482. }