ConstantPaymentBondBuilder.java

  1. package org.drip.product.creator;

  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>ConstantPaymentBondBuilder</i> contains the Suite of Helper Functions for creating Constant Payments
  80.  * Based Bonds.
  81.  *
  82.  *  <br><br>
  83.  *  <ul>
  84.  *      <li><b>Module </b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/ProductCore.md">Product Core Module</a></li>
  85.  *      <li><b>Library</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/FixedIncomeAnalyticsLibrary.md">Fixed Income Analytics</a></li>
  86.  *      <li><b>Project</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/product/README.md">Product Components/Baskets for Credit, FRA, FX, Govvie, Rates, and Option AssetClasses</a></li>
  87.  *      <li><b>Package</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/product/creator/README.md">Streams and Products Construction Utilities</a></li>
  88.  *  </ul>
  89.  * <br><br>
  90.  *
  91.  * @author Lakshmi Krishnamurthy
  92.  */

  93. public class ConstantPaymentBondBuilder {

  94.     /**
  95.      * Construct an Instance of the Constant Payment Bond
  96.      *
  97.      * @param strName Mortgage Bond Instance Name
  98.      * @param dtEffective Effective Date
  99.      * @param strCurrency Currency
  100.      * @param iNumPayment The (Maximum) Number of Payments
  101.      * @param strDayCount Coupon/Accrual Day Count
  102.      * @param iPayFrequency Pay Frequency
  103.      * @param dblCouponRate The Coupon Rate
  104.      * @param dblFeeRate The Fee Rate
  105.      * @param dblConstantAmount The Fixed Monthly Amount
  106.      * @param dblInitialNotional The Initial Bond Notional
  107.      *
  108.      * @return Instance of the Fixed Mortgage Product
  109.      */

  110.     public static final org.drip.product.credit.BondComponent Standard (
  111.         final java.lang.String strName,
  112.         final org.drip.analytics.date.JulianDate dtEffective,
  113.         final java.lang.String strCurrency,
  114.         final int iNumPayment,
  115.         final java.lang.String strDayCount,
  116.         final int iPayFrequency,
  117.         final double dblCouponRate,
  118.         final double dblFeeRate,
  119.         final double dblConstantAmount,
  120.         final double dblInitialNotional)
  121.     {
  122.         if (null == dtEffective || !org.drip.numerical.common.NumberUtil.IsValid (dblCouponRate) ||
  123.             !org.drip.numerical.common.NumberUtil.IsValid (dblFeeRate) || dblFeeRate > dblCouponRate ||
  124.                 !org.drip.numerical.common.NumberUtil.IsValid (dblConstantAmount) ||
  125.                     !org.drip.numerical.common.NumberUtil.IsValid (dblInitialNotional))
  126.             return null;

  127.         double dblOutstandingPrincipal = dblInitialNotional;

  128.         java.util.List<java.lang.Double> lsCouponPayment = new java.util.ArrayList<java.lang.Double>();

  129.         java.util.List<java.lang.Double> lsOutstandingPrincipal = new
  130.             java.util.ArrayList<java.lang.Double>();

  131.         java.util.List<org.drip.analytics.date.JulianDate> lsPaymentDate = new
  132.             java.util.ArrayList<org.drip.analytics.date.JulianDate>();

  133.         for (int i = 0; i < iNumPayment; ++i) {
  134.             double dblCouponPayment = java.lang.Double.NaN;

  135.             org.drip.analytics.date.JulianDate dtPayment = dtEffective.addMonths (i + 1);

  136.             org.drip.analytics.date.JulianDate dtPrev = 0 == i ? dtEffective : lsPaymentDate.get (i - 1);

  137.             try {
  138.                 dblCouponPayment = dblOutstandingPrincipal * (dblCouponRate - dblFeeRate) *
  139.                     org.drip.analytics.daycount.Convention.YearFraction (dtPrev.julian(), dtPayment.julian(),
  140.                         strDayCount, false, null, "");
  141.             } catch (java.lang.Exception e) {
  142.                 e.printStackTrace();

  143.                 return null;
  144.             }

  145.             lsPaymentDate.add (dtPayment);

  146.             lsCouponPayment.add (dblCouponPayment);

  147.             double dblPrincipalPayment = dblConstantAmount - dblCouponPayment;

  148.             if (dblPrincipalPayment > dblOutstandingPrincipal) {
  149.                 lsOutstandingPrincipal.add (0.);

  150.                 break;
  151.             }

  152.             dblOutstandingPrincipal -= dblPrincipalPayment;

  153.             lsOutstandingPrincipal.add (dblOutstandingPrincipal);
  154.         }

  155.         int iNumValidPayment = lsOutstandingPrincipal.size();

  156.         double[] adblCouponPayment = new double[iNumValidPayment];
  157.         double[] adblOutstandingPrincipal = new double[iNumValidPayment];
  158.         org.drip.analytics.date.JulianDate[] adtPayment = new
  159.             org.drip.analytics.date.JulianDate[iNumValidPayment];

  160.         for (int i = 0; i < iNumValidPayment; ++i) {
  161.             adtPayment[i] = lsPaymentDate.get (i);

  162.             adblCouponPayment[i] = lsCouponPayment.get (i);

  163.             adblOutstandingPrincipal[i] = lsOutstandingPrincipal.get (i);
  164.         }

  165.         return org.drip.product.creator.BondBuilder.CreateBondFromCF (strName, dtEffective, strCurrency, "",
  166.             strDayCount, dblInitialNotional, dblCouponRate - dblFeeRate, iPayFrequency, adtPayment,
  167.                 adblCouponPayment, adblOutstandingPrincipal, false);
  168.     }

  169.     /**
  170.      * Construct an Instance of the Constant Payment Bond with a Deterministic Pre-payment Rate
  171.      *
  172.      * @param strName Mortgage Bond Instance Name
  173.      * @param dtEffective Effective Date
  174.      * @param strCurrency Currency
  175.      * @param iNumPayment The (Maximum) Number of Payments
  176.      * @param strDayCount Coupon/Accrual Day Count
  177.      * @param iPayFrequency Pay Frequency
  178.      * @param dblCouponRate The Coupon Rate
  179.      * @param dblFeeRate The Fee Rate
  180.      * @param dblCPR the Constant Pre-payment Rate
  181.      * @param dblConstantAmount The Fixed Monthly Amount
  182.      * @param dblInitialNotional The Initial Bond Notional
  183.      *
  184.      * @return Instance of the Fixed Mortgage Product
  185.      */

  186.     public static final org.drip.product.credit.BondComponent Prepay (
  187.         final java.lang.String strName,
  188.         final org.drip.analytics.date.JulianDate dtEffective,
  189.         final java.lang.String strCurrency,
  190.         final int iNumPayment,
  191.         final java.lang.String strDayCount,
  192.         final int iPayFrequency,
  193.         final double dblCouponRate,
  194.         final double dblFeeRate,
  195.         final double dblCPR,
  196.         final double dblConstantAmount,
  197.         final double dblInitialNotional)
  198.     {
  199.         if (null == dtEffective || !org.drip.numerical.common.NumberUtil.IsValid (dblCouponRate) ||
  200.             !org.drip.numerical.common.NumberUtil.IsValid (dblFeeRate) || dblFeeRate > dblCouponRate ||
  201.                 !org.drip.numerical.common.NumberUtil.IsValid (dblCPR) ||
  202.                     !org.drip.numerical.common.NumberUtil.IsValid (dblConstantAmount) ||
  203.                         !org.drip.numerical.common.NumberUtil.IsValid (dblInitialNotional))
  204.             return null;

  205.         double dblOutstandingPrincipal = dblInitialNotional;

  206.         java.util.List<java.lang.Double> lsCouponPayment = new java.util.ArrayList<java.lang.Double>();

  207.         java.util.List<java.lang.Double> lsOutstandingPrincipal = new
  208.             java.util.ArrayList<java.lang.Double>();

  209.         java.util.List<org.drip.analytics.date.JulianDate> lsPaymentDate = new
  210.             java.util.ArrayList<org.drip.analytics.date.JulianDate>();

  211.         for (int i = 0; i < iNumPayment; ++i) {
  212.             double dblCouponPayment = java.lang.Double.NaN;

  213.             org.drip.analytics.date.JulianDate dtPayment = dtEffective.addMonths (i + 1);

  214.             org.drip.analytics.date.JulianDate dtPrev = 0 == i ? dtEffective : lsPaymentDate.get (i - 1);

  215.             try {
  216.                 dblCouponPayment = dblOutstandingPrincipal * (dblCouponRate - dblFeeRate) *
  217.                     org.drip.analytics.daycount.Convention.YearFraction (dtPrev.julian(), dtPayment.julian(),
  218.                         strDayCount, false, null, "");
  219.             } catch (java.lang.Exception e) {
  220.                 e.printStackTrace();

  221.                 return null;
  222.             }

  223.             lsPaymentDate.add (dtPayment);

  224.             lsCouponPayment.add (dblCouponPayment);

  225.             double dblPrincipalPayment = dblConstantAmount - dblCouponPayment + dblCPR *
  226.                 dblOutstandingPrincipal;

  227.             if (dblPrincipalPayment > dblOutstandingPrincipal) {
  228.                 lsOutstandingPrincipal.add (0.);

  229.                 break;
  230.             }

  231.             dblOutstandingPrincipal -= dblPrincipalPayment;

  232.             lsOutstandingPrincipal.add (dblOutstandingPrincipal);
  233.         }

  234.         int iNumValidPayment = lsOutstandingPrincipal.size();

  235.         double[] adblCouponPayment = new double[iNumValidPayment];
  236.         double[] adblOutstandingPrincipal = new double[iNumValidPayment];
  237.         org.drip.analytics.date.JulianDate[] adtPayment = new
  238.             org.drip.analytics.date.JulianDate[iNumValidPayment];

  239.         for (int i = 0; i < iNumValidPayment; ++i) {
  240.             adtPayment[i] = lsPaymentDate.get (i);

  241.             adblCouponPayment[i] = lsCouponPayment.get (i);

  242.             adblOutstandingPrincipal[i] = lsOutstandingPrincipal.get (i);
  243.         }

  244.         return org.drip.product.creator.BondBuilder.CreateBondFromCF (strName, dtEffective, strCurrency, "",
  245.             strDayCount, dblInitialNotional, dblCouponRate - dblFeeRate, iPayFrequency, adtPayment,
  246.                 adblCouponPayment, adblOutstandingPrincipal, false);
  247.     }

  248.     /**
  249.      * Compute the Constant Uniform Payment Amount for the Parameters of the Specified Mortgage Bond
  250.      *
  251.      * @param dblBondNotional The Current Notional
  252.      * @param dblCouponRate The Coupon Rate
  253.      * @param iTenorInYears Tenor in Years
  254.      *
  255.      * @return The Constant Uniform Payment Amount
  256.      *
  257.      * @throws java.lang.Exception Thrown if the Constant Uniform Payment Amount cannot be computed
  258.      */

  259.     public static final double ConstantUniformPaymentAmount (
  260.         final double dblBondNotional,
  261.         final double dblCouponRate,
  262.         final int iTenorInYears)
  263.         throws java.lang.Exception
  264.     {
  265.         if (!org.drip.numerical.common.NumberUtil.IsValid (dblBondNotional) ||
  266.             !org.drip.numerical.common.NumberUtil.IsValid (dblCouponRate))
  267.                 throw new java.lang.Exception
  268.                     ("ConstantPaymentBondBuilder::ConstantUniformPaymentAmount => Invalid Inputs");

  269.         int iNumPeriod = iTenorInYears * 12;
  270.         double dblPeriodRate = dblCouponRate / 12.;

  271.         return dblPeriodRate * dblBondNotional * java.lang.Math.pow (1. + dblPeriodRate, iNumPeriod - 1) /
  272.             (java.lang.Math.pow (1. + dblPeriodRate, iNumPeriod) - 1.);
  273.     }
  274. }