CustomDiscountCurveBuilder.java

  1.    
  2. package org.drip.sample.stretch;

  3. /*
  4.  * Java Imports
  5.  */

  6. import java.util.*;

  7. import org.drip.function.r1tor1.QuadraticRationalShapeControl;
  8. import org.drip.numerical.common.FormatUtil;
  9. import org.drip.spline.basis.*;
  10. import org.drip.spline.params.*;
  11. import org.drip.spline.stretch.*;

  12. /*
  13.  * -*- mode: java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  14.  */

  15. /*!
  16.  * Copyright (C) 2018 Lakshmi Krishnamurthy
  17.  * Copyright (C) 2017 Lakshmi Krishnamurthy
  18.  * Copyright (C) 2016 Lakshmi Krishnamurthy
  19.  * Copyright (C) 2015 Lakshmi Krishnamurthy
  20.  * Copyright (C) 2014 Lakshmi Krishnamurthy
  21.  * Copyright (C) 2013 Lakshmi Krishnamurthy
  22.  *
  23.  *  This file is part of DRIP, a free-software/open-source library for buy/side financial/trading model
  24.  *      libraries targeting analysts and developers
  25.  *      https://lakshmidrip.github.io/DRIP/
  26.  *  
  27.  *  DRIP is composed of four main libraries:
  28.  *  
  29.  *  - DRIP Fixed Income - https://lakshmidrip.github.io/DRIP-Fixed-Income/
  30.  *  - DRIP Asset Allocation - https://lakshmidrip.github.io/DRIP-Asset-Allocation/
  31.  *  - DRIP Numerical Optimizer - https://lakshmidrip.github.io/DRIP-Numerical-Optimizer/
  32.  *  - DRIP Statistical Learning - https://lakshmidrip.github.io/DRIP-Statistical-Learning/
  33.  *
  34.  *  - DRIP Fixed Income: Library for Instrument/Trading Conventions, Treasury Futures/Options,
  35.  *      Funding/Forward/Overnight Curves, Multi-Curve Construction/Valuation, Collateral Valuation and XVA
  36.  *      Metric Generation, Calibration and Hedge Attributions, Statistical Curve Construction, Bond RV
  37.  *      Metrics, Stochastic Evolution and Option Pricing, Interest Rate Dynamics and Option Pricing, LMM
  38.  *      Extensions/Calibrations/Greeks, Algorithmic Differentiation, and Asset Backed Models and Analytics.
  39.  *
  40.  *  - DRIP Asset Allocation: Library for model libraries for MPT framework, Black Litterman Strategy
  41.  *      Incorporator, Holdings Constraint, and Transaction Costs.
  42.  *
  43.  *  - DRIP Numerical Optimizer: Library for Numerical Optimization and Spline Functionality.
  44.  *
  45.  *  - DRIP Statistical Learning: Library for Statistical Evaluation and Machine Learning.
  46.  *
  47.  *  Licensed under the Apache License, Version 2.0 (the "License");
  48.  *      you may not use this file except in compliance with the License.
  49.  *  
  50.  *  You may obtain a copy of the License at
  51.  *      http://www.apache.org/licenses/LICENSE-2.0
  52.  *  
  53.  *  Unless required by applicable law or agreed to in writing, software
  54.  *      distributed under the License is distributed on an "AS IS" BASIS,
  55.  *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  56.  *  
  57.  *  See the License for the specific language governing permissions and
  58.  *      limitations under the License.
  59.  */

  60. /**
  61.  * CustomDiscountCurveBuilder contains samples that demo how to build a discount curve from purely the cash
  62.  *  flows. It provides for elaborate curve builder control, both at the segment level and at the Stretch
  63.  *  level. In particular, it shows the following:
  64.  *  - Construct a discount curve from the discount factors available purely from the cash and the euro-dollar
  65.  *      instruments.
  66.  *  - Construct a discount curve from the cash flows available from the swap instruments.
  67.  *
  68.  * In addition, the sample demonstrates the following ways of controlling curve construction:
  69.  *  - Control over the type of segment basis spline
  70.  *  - Control over the polynomial basis spline order, Ck, and tension parameters
  71.  *  - Provision of custom shape controllers (in this case rational shape controller)
  72.  *  - Calculation of segment monotonicity and convexity
  73.  *
  74.  * @author Lakshmi Krishnamurthy
  75.  */

  76. public class CustomDiscountCurveBuilder {

  77.     /*
  78.      * Sample API demonstrating the creation of the segment builder parameters based on Koch-Lyche-Kvasov tension spline.
  79.      *
  80.      *      USE WITH CARE: This sample ignores errors and does not handle exceptions.
  81.      */

  82.     private static final SegmentCustomBuilderControl MakeKLKTensionSCBC (
  83.         final double dblTension)
  84.         throws Exception
  85.     {
  86.         return new SegmentCustomBuilderControl (
  87.             MultiSegmentSequenceBuilder.BASIS_SPLINE_KLK_HYPERBOLIC_TENSION, // Spline Type KLK Hyperbolic Basis Tension
  88.             new ExponentialTensionSetParams (dblTension), // Segment Tension Parameter Value
  89.             SegmentInelasticDesignControl.Create (2, 2), // Ck = 2; Curvature penalty (if necessary) order: 2
  90.             new ResponseScalingShapeControl (
  91.                 true,
  92.                 new QuadraticRationalShapeControl (0.0)), // Univariate Rational Shape Controller
  93.             null
  94.         );
  95.     }

  96.     /*
  97.      * Sample API demonstrating the creation of the segment builder parameters based on polynomial spline.
  98.      *
  99.      *      USE WITH CARE: This sample ignores errors and does not handle exceptions.
  100.      */

  101.     public static final SegmentCustomBuilderControl MakePolynomialSBP (
  102.         final int iNumDegree)
  103.         throws Exception
  104.     {
  105.         return new SegmentCustomBuilderControl (
  106.             MultiSegmentSequenceBuilder.BASIS_SPLINE_POLYNOMIAL, // Spline Type Polynomial
  107.             new PolynomialFunctionSetParams (iNumDegree + 1), // Polynomial of degree (i.e, cubic would be 3+1; 4 basis functions - 1 "intercept")
  108.             SegmentInelasticDesignControl.Create (2, 2), // Ck = 2; Curvature penalty (if necessary) order: 2
  109.             new ResponseScalingShapeControl (
  110.                 true,
  111.                 new QuadraticRationalShapeControl (0.0)), // Univariate Rational Shape Controller
  112.             null
  113.         );
  114.     }

  115.     /*
  116.      * Sample API demonstrating the creation of the segment builder parameters
  117.      *
  118.      *      USE WITH CARE: This sample ignores errors and does not handle exceptions.
  119.      */

  120.     private static final SegmentCustomBuilderControl MakeSCBC (
  121.         final String strBasisSpline)
  122.         throws Exception
  123.     {
  124.         if (strBasisSpline.equalsIgnoreCase (MultiSegmentSequenceBuilder.BASIS_SPLINE_POLYNOMIAL)) // Polynomial Basis Spline
  125.             return new SegmentCustomBuilderControl (
  126.                 MultiSegmentSequenceBuilder.BASIS_SPLINE_POLYNOMIAL, // Spline Type Polynomial
  127.                 new PolynomialFunctionSetParams (4), // Polynomial of order 3 (i.e, cubic - 4 basis functions - 1 "intercept")
  128.                 SegmentInelasticDesignControl.Create (2, 2), // Ck = 2; Curvature penalty (if necessary) order: 2
  129.                 new ResponseScalingShapeControl (
  130.                     true,
  131.                     new QuadraticRationalShapeControl (0.0)), // Univariate Rational Shape Controller
  132.                 null
  133.             );

  134.         if (strBasisSpline.equalsIgnoreCase (MultiSegmentSequenceBuilder.BASIS_SPLINE_EXPONENTIAL_TENSION)) // Exponential Tension Basis Spline
  135.             return new SegmentCustomBuilderControl (
  136.                 MultiSegmentSequenceBuilder.BASIS_SPLINE_EXPONENTIAL_TENSION, // Spline Type Exponential Basis Tension
  137.                 new ExponentialTensionSetParams (1.), // Segment Tension Parameter Value = 1.
  138.                 SegmentInelasticDesignControl.Create (2, 2), // Ck = 2; Curvature penalty (if necessary) order: 2
  139.                 new ResponseScalingShapeControl (
  140.                     true,
  141.                     new QuadraticRationalShapeControl (0.0)), // Univariate Rational Shape Controller
  142.                 null
  143.             );

  144.         return null;
  145.     }

  146.     /*
  147.      * Generate the sample Swap Cash Flows to a given maturity, for the frequency/coupon.
  148.      *  Cash Flow is in the form of <Date, Cash Amount> Map.
  149.      *
  150.      *      USE WITH CARE: This sample ignores errors and does not handle exceptions.
  151.      */

  152.     private static final TreeMap<Double, Double> SwapCashFlow (
  153.         final double dblCoupon,
  154.         final int iFreq,
  155.         final double dblTenorInYears)
  156.     {
  157.         TreeMap<Double, Double> mapCF = new TreeMap<Double, Double>();

  158.         for (double dblCFDate = 1. / iFreq; dblCFDate < dblTenorInYears; dblCFDate += 1. / iFreq)
  159.             mapCF.put (
  160.                 dblCFDate,
  161.                 dblCoupon / iFreq
  162.             );

  163.         mapCF.put (
  164.             0.,
  165.             -1.
  166.         );

  167.         mapCF.put (
  168.             1. * dblTenorInYears,
  169.             1. + dblCoupon / iFreq
  170.         );

  171.         return mapCF;
  172.     }

  173.     /**
  174.      * Generate the DRIP linear constraint corresponding to an exclusive swap segment. This constraint is
  175.      *  used to calibrate the discount curve in this segment.
  176.      *  
  177.      *      USE WITH CARE: This sample ignores errors and does not handle exceptions.
  178.      */

  179.     private static final SegmentResponseValueConstraint GenerateSegmentConstraint (
  180.         final TreeMap<Double, Double> mapCF,
  181.         final MultiSegmentSequence mssDF)
  182.         throws Exception
  183.     {
  184.         double dblValue = 0.;

  185.         List<Double> lsTime = new ArrayList<Double>();

  186.         List<Double> lsWeight = new ArrayList<Double>();

  187.         for (Map.Entry<Double, Double> me : mapCF.entrySet()) {
  188.             double dblTime = me.getKey();

  189.             if (null != mssDF && mssDF.in (dblTime))
  190.                 dblValue += mssDF.responseValue (dblTime) * me.getValue();
  191.             else {
  192.                 lsTime.add (me.getKey());

  193.                 lsWeight.add (me.getValue());
  194.             }
  195.         }

  196.         int iSize = lsTime.size();

  197.         double[] adblNode = new double[iSize];
  198.         double[] adblNodeWeight = new double[iSize];

  199.         for (int i = 0; i < iSize; ++i) {
  200.             adblNode[i] = lsTime.get (i);

  201.             adblNodeWeight[i] = lsWeight.get (i);
  202.         }

  203.         return new SegmentResponseValueConstraint (
  204.             adblNode,
  205.             adblNodeWeight,
  206.             -dblValue
  207.         );
  208.     }

  209.     /**
  210.      * The set of Par Swap Quotes.
  211.      *
  212.      *      USE WITH CARE: This sample ignores errors and does not handle exceptions.
  213.      */

  214.     private static final Map<Double, Double> SwapQuotes()
  215.     {
  216.         Map<Double, Double> mapSwapQuotes = new TreeMap<Double, Double>();

  217.         mapSwapQuotes.put (4., 0.0166);

  218.         mapSwapQuotes.put (5., 0.0206);

  219.         mapSwapQuotes.put (6., 0.0241);

  220.         mapSwapQuotes.put (7., 0.0269);

  221.         mapSwapQuotes.put (8., 0.0292);

  222.         mapSwapQuotes.put (9., 0.0311);

  223.         mapSwapQuotes.put (10., 0.0326);

  224.         mapSwapQuotes.put (11., 0.0340);

  225.         mapSwapQuotes.put (12., 0.0351);

  226.         mapSwapQuotes.put (15., 0.0375);

  227.         mapSwapQuotes.put (20., 0.0393);

  228.         mapSwapQuotes.put (25., 0.0402);

  229.         mapSwapQuotes.put (30., 0.0407);

  230.         mapSwapQuotes.put (40., 0.0409);

  231.         mapSwapQuotes.put (50., 0.0409);

  232.         return mapSwapQuotes;
  233.     }

  234.     /**
  235.      * Sample Function illustrating the construction of the discount curve off of swap cash flows and
  236.      *  detailed segment level controls for the swap instruments.Further, the Segment Builder Parameters
  237.      *  for the cash/swap bridging stretch shown here illustrate using an exponential/hyperbolic spline with
  238.      *  very high tension (100000.) to "stitch" the cash stretch with the swaps Stretch.
  239.      *
  240.      * Each of the respective stretches have their own tension settings, so the "high" tension
  241.      *  ensures that there is no propagation of derivatives and therefore high locality.
  242.      *  
  243.      *      USE WITH CARE: This sample ignores errors and does not handle exceptions.
  244.      */

  245.     private static final MultiSegmentSequence BuildSwapCurve (
  246.         MultiSegmentSequence mss,
  247.         final BoundarySettings bs,
  248.         final int iCalibrationDetail)
  249.         throws Exception
  250.     {
  251.         boolean bFirstNode = true;

  252.         /*
  253.          * Iterate through the swap instruments and their quotes.
  254.          */

  255.         for (Map.Entry<Double, Double> meSwapQuote : SwapQuotes().entrySet()) {
  256.             double dblTenorInYears = meSwapQuote.getKey(); // Swap Maturity in Years

  257.             double dblQuote = meSwapQuote.getValue(); // Par Swap Quote

  258.             /*
  259.              * Generate the Cash flow for the swap Instrument
  260.              */

  261.             TreeMap<Double, Double> mapCF = SwapCashFlow (
  262.                 dblQuote,
  263.                 2,
  264.                 dblTenorInYears
  265.             );

  266.             /*
  267.              * Convert the Cash flow into a DRIP segment constraint using the "prior" curve stretch
  268.              */

  269.             SegmentResponseValueConstraint srvc = GenerateSegmentConstraint (
  270.                 mapCF,
  271.                 mss
  272.             );

  273.             /*
  274.              * If it is the head segment, create a stretch instance for the discount curve.
  275.              */

  276.             if (null == mss) {
  277.                 /*
  278.                  * Set the Segment Builder Parameters. This may be set on a segment-by-segment basis.
  279.                  */

  280.                 SegmentCustomBuilderControl scbc = MakeSCBC (MultiSegmentSequenceBuilder.BASIS_SPLINE_EXPONENTIAL_TENSION);

  281.                 /*
  282.                  * Start off with a single segment stretch, with the corresponding Builder Parameters
  283.                  */

  284.                 mss = MultiSegmentSequenceBuilder.CreateUncalibratedStretchEstimator (
  285.                     "SWAP",
  286.                     new double[] {0., dblTenorInYears},
  287.                     new SegmentCustomBuilderControl[] {scbc}
  288.                 );

  289.                 /*
  290.                  * Set the stretch up by carrying out a "Natural Boundary" Spline Calibration
  291.                  */

  292.                 mss.setup (
  293.                     1.,
  294.                     new SegmentResponseValueConstraint[] {srvc},
  295.                     null,
  296.                     bs,
  297.                     iCalibrationDetail
  298.                 );
  299.             } else {
  300.                 /*
  301.                  * The Segment Builder Parameters shown here illustrate using an exponential/hyperbolic
  302.                  *  spline with high tension (15.) to "stitch" the cash stretch with the swaps stretch.
  303.                  *  
  304.                  * Each of the respective stretches have their own tension settings, so the "high" tension
  305.                  *  ensures that there is no propagation of derivatives and therefore high locality.
  306.                  */

  307.                 SegmentCustomBuilderControl scbcLocal = null;

  308.                 if (bFirstNode) {
  309.                     bFirstNode = false;

  310.                     scbcLocal = MakeKLKTensionSCBC (1.);
  311.                 } else
  312.                     scbcLocal = MakeKLKTensionSCBC (1.);

  313.                 /*
  314.                  * If not the head segment, just append the exclusive swap instrument segment to the tail of
  315.                  *  the current stretch state, using the constraint generated from the swap cash flow.
  316.                  */

  317.                 mss = org.drip.spline.stretch.MultiSegmentSequenceModifier.AppendSegment (
  318.                     mss,
  319.                     dblTenorInYears,
  320.                     srvc,
  321.                     scbcLocal,
  322.                     bs,
  323.                     iCalibrationDetail
  324.                 );
  325.             }
  326.         }

  327.         return mss;
  328.     }

  329.     /**
  330.      * The set of Cash Discount Factors.
  331.      *
  332.      *      USE WITH CARE: This sample ignores errors and does not handle exceptions.
  333.      */

  334.     private static final Map<Double, Double> CashDFQuotes()
  335.     {
  336.         Map<Double, Double> mapDFCashQuotes = new TreeMap<Double, Double>();

  337.         mapDFCashQuotes.put (0.005556, 0.999991);

  338.         mapDFCashQuotes.put (0.019444, 0.999967);

  339.         mapDFCashQuotes.put (0.038889, 0.999931);

  340.         mapDFCashQuotes.put (0.083333, 0.999836);

  341.         mapDFCashQuotes.put (0.166667, 0.999622);

  342.         mapDFCashQuotes.put (0.250000, 0.999360);

  343.         mapDFCashQuotes.put (0.500000, 0.998686);

  344.         mapDFCashQuotes.put (0.750000, 0.997888);

  345.         mapDFCashQuotes.put (1.000000, 0.996866);

  346.         mapDFCashQuotes.put (1.250000, 0.995522);

  347.         mapDFCashQuotes.put (1.500000, 0.993609);

  348.         mapDFCashQuotes.put (1.750000, 0.991033);

  349.         mapDFCashQuotes.put (2.000000, 0.987724);

  350.         mapDFCashQuotes.put (2.250000, 0.983789);

  351.         return mapDFCashQuotes;
  352.     }

  353.     /**
  354.      * Sample Function illustrating the construction of the discount curve off of discount factors and
  355.      *  detailed segment level controls for the cash instruments.
  356.      *
  357.      *      USE WITH CARE: This sample ignores errors and does not handle exceptions.
  358.      */

  359.     private static final MultiSegmentSequence BuildCashCurve (
  360.         final org.drip.spline.stretch.BoundarySettings bs,
  361.         final int iCalibrationDetail)
  362.         throws Exception
  363.     {
  364.         /*
  365.          * For the head segment, create a calibrated stretch instance for the discount curve.
  366.          */

  367.         MultiSegmentSequence mssCash = MultiSegmentSequenceBuilder.CreateCalibratedStretchEstimator (
  368.             "CASH",
  369.             new double[] {0., 0.002778}, // t0 and t1 for the segment
  370.             new double[] {1., 0.999996}, // the corresponding discount factors
  371.             new SegmentCustomBuilderControl[] {
  372.                 // MakeSCBC (MultiSegmentSequenceBuilder.BASIS_SPLINE_EXPONENTIAL_TENSION)
  373.                 MakeKLKTensionSCBC (1.)
  374.             }, // Exponential Tension Basis Spline
  375.             null,
  376.             bs,
  377.             iCalibrationDetail // "Natural" Spline Boundary Condition + Calibrate the full stretch
  378.         );

  379.         /*
  380.          * Construct the discount curve by iterating through the cash instruments and their discount
  381.          *  factors, and inserting them as "knots" onto the existing stretch.
  382.          */

  383.         for (Map.Entry<Double, Double> meCashDFQuote : CashDFQuotes().entrySet()) {
  384.             double dblTenorInYears = meCashDFQuote.getKey(); // Instrument Tenor in Years

  385.             double dblDF = meCashDFQuote.getValue(); // Discount Factor

  386.             /*
  387.              * Insert the instrument/quote as a "knot" entity into the stretch. Given the "natural" spline
  388.              */

  389.             mssCash = MultiSegmentSequenceModifier.InsertKnot (
  390.                 mssCash,
  391.                 dblTenorInYears,
  392.                 dblDF,
  393.                 bs,
  394.                 iCalibrationDetail
  395.             );
  396.         }

  397.         return mssCash;
  398.     }

  399.     /*
  400.      * This sample demonstrates the usage construction and usage of Custom Curve Building. It shows the following:
  401.      *  - Construct the Cash Curve Sequence with the Standard Natural Boundary Condition.
  402.      *  - Construct the Cash Curve Sequence with the Standard Financial Boundary Condition.
  403.      *  - Construct the Cash Curve Sequence with the Standard Not-A-Knot Boundary Condition.
  404.      *  - Display the DF and the monotonicity for the cash instruments.
  405.      *  - Construct the Swap Curve Sequence with the Standard Natural Boundary Condition.
  406.      *  - Construct the Swap Curve Sequence with the Standard Financial Boundary Condition.
  407.      *  - Construct the Swap Curve Sequence with the Standard Not-A-Knot Boundary Condition.
  408.      *  - Display the DF and the monotonicity for the swap instruments.
  409.      */

  410.     private static final void CustomCurveBuilderTest()
  411.         throws Exception
  412.     {
  413.         /*
  414.          * Construct the Cash Curve Sequence with the Standard Natural Boundary Condition
  415.          */

  416.         MultiSegmentSequence mssNaturalCash = BuildCashCurve (
  417.             BoundarySettings.NaturalStandard(),
  418.             MultiSegmentSequence.CALIBRATE
  419.         );

  420.         /*
  421.          * Construct the Cash Curve Sequence with the Standard Financial Boundary Condition
  422.          */

  423.         MultiSegmentSequence mssFinancialCash = BuildCashCurve (
  424.             BoundarySettings.FinancialStandard(),
  425.             MultiSegmentSequence.CALIBRATE
  426.         );

  427.         /*
  428.          * Construct the Cash Curve Sequence with the Standard Not-A-Knot Boundary Condition
  429.          */

  430.         MultiSegmentSequence mssNotAKnotCash = BuildCashCurve (
  431.             BoundarySettings.NotAKnotStandard (1, 1),
  432.             MultiSegmentSequence.CALIBRATE
  433.         );

  434.         double dblXShift = 0.1 * (mssNaturalCash.getRightPredictorOrdinateEdge() - mssNaturalCash.getLeftPredictorOrdinateEdge());

  435.         System.out.println ("\n\t\t\t----------------       <====>    ------------------       <====>    ------------------");

  436.         System.out.println ("\t\t\tNATURAL BOUNDARY       <====>   NOT A KNOT BOUNDARY       <====>    FINANCIAL BOUNDARY");

  437.         System.out.println ("\t\t\t----------------       <====>    ------------------       <====>    ------------------\n");

  438.         /*
  439.          * Display the DF and the monotonicity for the cash instruments.
  440.          */

  441.         for (double dblX = mssNaturalCash.getLeftPredictorOrdinateEdge(); dblX <= mssNaturalCash.getRightPredictorOrdinateEdge(); dblX = dblX + dblXShift)
  442.             System.out.println ("Cash DF[" +
  443.                 FormatUtil.FormatDouble (dblX, 1, 3, 1.) + "Y] => " +
  444.                 FormatUtil.FormatDouble (mssNaturalCash.responseValue (dblX), 1, 6, 1.) + " | " +
  445.                 mssNaturalCash.monotoneType (dblX) + "  <====>  " +
  446.                 FormatUtil.FormatDouble (mssNotAKnotCash.responseValue (dblX), 1, 6, 1.) + " | " +
  447.                 mssNotAKnotCash.monotoneType (dblX) + "  <====>  " +
  448.                 FormatUtil.FormatDouble (mssFinancialCash.responseValue (dblX), 1, 6, 1.) + " | " +
  449.                 mssNaturalCash.monotoneType (dblX));

  450.         System.out.println ("\n");

  451.         /*
  452.          * Construct the Swap Curve Sequence with the Standard Natural Boundary Condition
  453.          */

  454.         MultiSegmentSequence mssNaturalSwap = BuildSwapCurve (
  455.             mssNaturalCash,
  456.             BoundarySettings.NaturalStandard(),
  457.             MultiSegmentSequence.CALIBRATE
  458.         );

  459.         /*
  460.          * Construct the Swap Curve Sequence with the Standard Financial Boundary Condition
  461.          */

  462.         MultiSegmentSequence mssFinancialSwap = BuildSwapCurve (
  463.             mssFinancialCash,
  464.             BoundarySettings.FinancialStandard(),
  465.             MultiSegmentSequence.CALIBRATE
  466.         );

  467.         /*
  468.          * Construct the Swap Curve Sequence with the Standard Not-A-Knot Boundary Condition
  469.          */

  470.         MultiSegmentSequence mssNotAKnotSwap = BuildSwapCurve (
  471.             mssNotAKnotCash,
  472.             BoundarySettings.NotAKnotStandard (1, 1),
  473.             MultiSegmentSequence.CALIBRATE
  474.         );

  475.         /*
  476.          * Display the DF and the monotonicity for the swaps.
  477.          */

  478.         dblXShift = 0.05 * (mssNaturalSwap.getRightPredictorOrdinateEdge() - mssNaturalSwap.getLeftPredictorOrdinateEdge());

  479.         for (double dblX = mssNaturalSwap.getLeftPredictorOrdinateEdge(); dblX <= mssNaturalSwap.getRightPredictorOrdinateEdge(); dblX = dblX + dblXShift)
  480.             System.out.println (
  481.                 "Swap DF   [" +
  482.                 FormatUtil.FormatDouble (dblX, 2, 0, 1.) + "Y] => " +
  483.                 FormatUtil.FormatDouble (mssNaturalSwap.responseValue (dblX), 1, 6, 1.) + " | " +
  484.                 mssNaturalSwap.monotoneType (dblX) + "  <====>  " +
  485.                 FormatUtil.FormatDouble (mssNotAKnotSwap.responseValue (dblX), 1, 6, 1.) + " | " +
  486.                 mssNotAKnotSwap.monotoneType (dblX) + "  <====>  " +
  487.                 FormatUtil.FormatDouble (mssFinancialSwap.responseValue (dblX), 1, 6, 1.) + " | " +
  488.                 mssFinancialSwap.monotoneType (dblX)
  489.             );
  490.     }

  491.     public static final void main (
  492.         final String[] astrArgs)
  493.         throws Exception
  494.     {
  495.         CustomCurveBuilderTest();
  496.     }
  497. }