ATMTermStructureSpline.java

  1. package org.drip.sample.option;

  2. import java.util.*;

  3. import org.drip.analytics.date.*;
  4. import org.drip.analytics.definition.NodeStructure;
  5. import org.drip.function.r1tor1.FlatUnivariate;
  6. import org.drip.market.otc.*;
  7. import org.drip.numerical.common.FormatUtil;
  8. import org.drip.param.valuation.*;
  9. import org.drip.pricer.option.BlackScholesAlgorithm;
  10. import org.drip.product.creator.*;
  11. import org.drip.product.definition.CalibratableComponent;
  12. import org.drip.product.option.EuropeanCallPut;
  13. import org.drip.product.rates.*;
  14. import org.drip.service.env.EnvManager;
  15. import org.drip.state.creator.*;
  16. import org.drip.state.discount.MergedDiscountForwardCurve;
  17. import org.drip.state.identifier.ForwardLabel;

  18. /*
  19.  * -*- mode: java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  20.  */

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

  65. /**
  66.  * ATMTermStructureSpline contains an illustration of the Calibration and Extraction of the Deterministic ATM
  67.  *  Price and Volatility Term Structures using Custom Splines. This does not deal with Local Volatility
  68.  *  Surfaces.
  69.  *
  70.  * @author Lakshmi Krishnamurthy
  71.  */

  72. public class ATMTermStructureSpline {

  73.     private static final FixFloatComponent OTCIRS (
  74.         final JulianDate dtSpot,
  75.         final String strCurrency,
  76.         final String strMaturityTenor,
  77.         final double dblCoupon)
  78.     {
  79.         FixedFloatSwapConvention ffConv = IBORFixedFloatContainer.ConventionFromJurisdiction (
  80.             strCurrency,
  81.             "ALL",
  82.             strMaturityTenor,
  83.             "MAIN"
  84.         );

  85.         return ffConv.createFixFloatComponent (
  86.             dtSpot,
  87.             strMaturityTenor,
  88.             dblCoupon,
  89.             0.,
  90.             1.
  91.         );
  92.     }

  93.     /*
  94.      * Construct the Array of Deposit Instruments from the given set of parameters
  95.      *
  96.      *      USE WITH CARE: This sample ignores errors and does not handle exceptions.
  97.      */

  98.     private static final CalibratableComponent[] DepositInstrumentsFromMaturityDays (
  99.         final JulianDate dtEffective,
  100.         final int[] aiDay,
  101.         final int iNumFutures,
  102.         final String strCurrency)
  103.         throws Exception
  104.     {
  105.         CalibratableComponent[] aCalibComp = new CalibratableComponent[aiDay.length + iNumFutures];

  106.         for (int i = 0; i < aiDay.length; ++i)
  107.             aCalibComp[i] = SingleStreamComponentBuilder.Deposit (
  108.                 dtEffective,
  109.                 dtEffective.addBusDays (
  110.                     aiDay[i],
  111.                     strCurrency
  112.                 ),
  113.                 ForwardLabel.Create (
  114.                     strCurrency,
  115.                     "3M"
  116.                 )
  117.             );

  118.         CalibratableComponent[] aEDF = SingleStreamComponentBuilder.ForwardRateFuturesPack (
  119.             dtEffective,
  120.             iNumFutures,
  121.             strCurrency
  122.         );

  123.         for (int i = aiDay.length; i < aiDay.length + iNumFutures; ++i)
  124.             aCalibComp[i] = aEDF[i - aiDay.length];

  125.         return aCalibComp;
  126.     }

  127.     /*
  128.      * Construct the Array of Swap Instruments from the given set of parameters
  129.      *
  130.      *      USE WITH CARE: This sample ignores errors and does not handle exceptions.
  131.      */

  132.     private static final FixFloatComponent[] SwapInstrumentsFromMaturityTenor (
  133.         final JulianDate dtSpot,
  134.         final String strCurrency,
  135.         final String[] astrMaturityTenor,
  136.         final double[] adblCoupon)
  137.         throws Exception
  138.     {
  139.         FixFloatComponent[] aIRS = new FixFloatComponent[astrMaturityTenor.length];

  140.         for (int i = 0; i < astrMaturityTenor.length; ++i) {
  141.             FixFloatComponent irs = OTCIRS (
  142.                 dtSpot,
  143.                 strCurrency,
  144.                 astrMaturityTenor[i],
  145.                 adblCoupon[i]
  146.             );

  147.             irs.setPrimaryCode ("IRS." + astrMaturityTenor[i] + "." + strCurrency);

  148.             aIRS[i] = irs;
  149.         }

  150.         return aIRS;
  151.     }

  152.     /*
  153.      * Construct the discount curve using the following steps:
  154.      *  - Construct the array of cash instruments and their quotes.
  155.      *  - Construct the array of swap instruments and their quotes.
  156.      *  - Construct a shape preserving and smoothing KLK Hyperbolic Spline from the cash/swap instruments.
  157.      *
  158.      *      USE WITH CARE: This sample ignores errors and does not handle exceptions.
  159.      */

  160.     private static final MergedDiscountForwardCurve MakeDC (
  161.         final JulianDate dtSpot,
  162.         final String strCurrency)
  163.         throws Exception
  164.     {
  165.         /*
  166.          * Construct the array of Deposit instruments and their quotes.
  167.          */

  168.         CalibratableComponent[] aDepositComp = DepositInstrumentsFromMaturityDays (
  169.             dtSpot,
  170.             new int[] {
  171.                 1, 2, 3, 7, 14, 21, 30, 60
  172.             },
  173.             0,
  174.             strCurrency
  175.         );

  176.         double[] adblDepositQuote = new double[] {
  177.             0.01200, 0.01200, 0.01200, 0.01450, 0.01550, 0.01600, 0.01660, 0.01850
  178.         };

  179.         String[] astrDepositManifestMeasure = new String[] {
  180.             "ForwardRate", "ForwardRate", "ForwardRate", "ForwardRate", "ForwardRate", "ForwardRate", "ForwardRate", "ForwardRate"
  181.         };

  182.         /*
  183.          * Construct the array of Swap instruments and their quotes.
  184.          */

  185.         double[] adblSwapQuote = new double[] {
  186.             0.02604,    //  4Y
  187.             0.02808,    //  5Y
  188.             0.02983,    //  6Y
  189.             0.03136,    //  7Y
  190.             0.03268,    //  8Y
  191.             0.03383,    //  9Y
  192.             0.03488,    // 10Y
  193.             0.03583,    // 11Y
  194.             0.03668,    // 12Y
  195.             0.03833,    // 15Y
  196.             0.03854,    // 20Y
  197.             0.03672,    // 25Y
  198.             0.03510,    // 30Y
  199.             0.03266,    // 40Y
  200.             0.03145     // 50Y
  201.         };

  202.         String[] astrSwapManifestMeasure = new String[] {
  203.             "SwapRate",    //  4Y
  204.             "SwapRate",    //  5Y
  205.             "SwapRate",    //  6Y
  206.             "SwapRate",    //  7Y
  207.             "SwapRate",    //  8Y
  208.             "SwapRate",    //  9Y
  209.             "SwapRate",    // 10Y
  210.             "SwapRate",    // 11Y
  211.             "SwapRate",    // 12Y
  212.             "SwapRate",    // 15Y
  213.             "SwapRate",    // 20Y
  214.             "SwapRate",    // 25Y
  215.             "SwapRate",    // 30Y
  216.             "SwapRate",    // 40Y
  217.             "SwapRate"     // 50Y
  218.         };

  219.         CalibratableComponent[] aSwapComp = SwapInstrumentsFromMaturityTenor (
  220.             dtSpot,
  221.             strCurrency,
  222.             new java.lang.String[] {
  223.                 "4Y", "5Y", "6Y", "7Y", "8Y", "9Y", "10Y", "11Y", "12Y", "15Y", "20Y", "25Y", "30Y", "40Y", "50Y"
  224.             },
  225.             adblSwapQuote
  226.         );

  227.         /*
  228.          * Construct a shape preserving and smoothing KLK Hyperbolic Spline from the cash/swap instruments.
  229.          */

  230.         return ScenarioDiscountCurveBuilder.CubicKLKHyperbolicDFRateShapePreserver (
  231.             "KLK_HYPERBOLIC_SHAPE_TEMPLATE",
  232.             new ValuationParams (
  233.                 dtSpot,
  234.                 dtSpot,
  235.                 strCurrency
  236.             ),
  237.             aDepositComp,
  238.             adblDepositQuote,
  239.             astrDepositManifestMeasure,
  240.             aSwapComp,
  241.             adblSwapQuote,
  242.             astrSwapManifestMeasure,
  243.             true
  244.         );
  245.     }

  246.     private static final double ATMCall (
  247.         final JulianDate dtMaturity,
  248.         final ValuationParams valParams,
  249.         final MergedDiscountForwardCurve dc,
  250.         final double dblVolatility,
  251.         final String strMeasure)
  252.         throws Exception
  253.     {
  254.         Map<String, Double> mapOptionCalc = new EuropeanCallPut (dtMaturity, 1.).value (
  255.             valParams,
  256.             1.,
  257.             false,
  258.             dc,
  259.             new FlatUnivariate (dblVolatility),
  260.             new BlackScholesAlgorithm()
  261.         );

  262.         return mapOptionCalc.get (strMeasure);
  263.     }

  264.     private static final void InputNodeReplicator (
  265.         final NodeStructure ts,
  266.         final String[] astrMaturityTenor,
  267.         final double[] dblNodeInput)
  268.         throws Exception
  269.     {
  270.         System.out.println ("\n\t" + ts.label());

  271.         System.out.println ("\n\t|--------------------------|");

  272.         System.out.println ("\t| TNR =>   CALC  |  INPUT  |");

  273.         System.out.println ("\t|--------------------------|");

  274.         for (int i = 0; i < astrMaturityTenor.length; ++i)
  275.             System.out.println ("\t| " + astrMaturityTenor[i] + " => " +
  276.                 FormatUtil.FormatDouble (ts.node (astrMaturityTenor[i]), 2, 2, 100.) + "% | " +
  277.                 FormatUtil.FormatDouble (dblNodeInput[i], 2, 2, 100.) + "% |");

  278.         System.out.println ("\t|--------------------------|");
  279.     }

  280.     private static final void OffGrid (
  281.         final String strHeader,
  282.         final String[] astrLabel,
  283.         final NodeStructure[] aTS,
  284.         final String[] astrMaturityTenor)
  285.         throws Exception
  286.     {
  287.         System.out.println ("\n\n\t\t" + strHeader + "\n");

  288.         System.out.print ("\t| TNR =>");

  289.         for (int i = 0; i < aTS.length; ++i)
  290.             System.out.print (" " + astrLabel[i] + " | ");

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

  292.         for (int i = 0; i < astrMaturityTenor.length; ++i) {
  293.             System.out.print ("\t| " + astrMaturityTenor[i] + " =>");

  294.             for (int j = 0; j < aTS.length; ++j)
  295.                 System.out.print ("  " + FormatUtil.FormatDouble (aTS[j].node (astrMaturityTenor[i]), 2, 2, 100.) + "%   | ");

  296.             System.out.print ("\n");
  297.         }

  298.         System.out.println ("\n");
  299.     }

  300.     public static final void main (
  301.         final String[] astrArgs)
  302.         throws Exception
  303.     {
  304.         /*
  305.          * Initialize the Credit Analytics Library
  306.          */

  307.         EnvManager.InitEnv ("");

  308.         JulianDate dtToday = DateUtil.Today();

  309.         ValuationParams valParams = new ValuationParams (
  310.             dtToday,
  311.             dtToday,
  312.             "USD"
  313.         );

  314.         /*
  315.          * Construct the Discount Curve using its instruments and quotes
  316.          */

  317.         MergedDiscountForwardCurve dc = MakeDC (
  318.             dtToday,
  319.             "USD"
  320.         );

  321.         String[] astrMaturityTenor = new String[] {
  322.             "06M", "01Y", "02Y", "03Y", "04Y", "05Y", "07Y", "10Y", "15Y", "20Y"
  323.         };
  324.         double[] adblVolatility = new double[] {
  325.             0.20, 0.23, 0.27, 0.30, 0.33, 0.35, 0.34, 0.29, 0.26, 0.19
  326.         };
  327.         double[] adblCallPrice = new double[adblVolatility.length];
  328.         double[] adblImpliedCallVolatility = new double[adblVolatility.length];

  329.         for (int i = 0; i < astrMaturityTenor.length; ++i) {
  330.             adblCallPrice[i] = ATMCall (
  331.                 dtToday.addTenor (astrMaturityTenor[i]),
  332.                 valParams,
  333.                 dc,
  334.                 adblVolatility[i],
  335.                 "CallPrice");

  336.             adblImpliedCallVolatility[i] = ATMCall (
  337.                 dtToday.addTenor (astrMaturityTenor[i]),
  338.                 valParams,
  339.                 dc,
  340.                 adblVolatility[i],
  341.                 "ImpliedCallVolatility");
  342.         }

  343.         NodeStructure tsCallPriceCubicPoly = ScenarioTermStructureBuilder.CubicPolynomialTermStructure (
  344.             "CUBIC_POLY_CALLPRICE_TERMSTRUCTURE",
  345.             dtToday,
  346.             "USD",
  347.             astrMaturityTenor,
  348.             adblCallPrice
  349.         );

  350.         NodeStructure tsCallPriceQuarticPoly = ScenarioTermStructureBuilder.QuarticPolynomialTermStructure (
  351.             "QUARTIC_POLY_CALLPRICE_TERMSTRUCTURE",
  352.             dtToday,
  353.             "USD",
  354.             astrMaturityTenor,
  355.             adblCallPrice
  356.         );

  357.         NodeStructure tsCallPriceKaklisPandelis = ScenarioTermStructureBuilder.KaklisPandelisTermStructure (
  358.             "KAKLIS_PANDELIS_CALLPRICE_TERMSTRUCTURE",
  359.             dtToday,
  360.             "USD",
  361.             astrMaturityTenor,
  362.             adblCallPrice
  363.         );

  364.         NodeStructure tsCallPriceKLKHyperbolic = ScenarioTermStructureBuilder.KLKHyperbolicTermStructure (
  365.             "KLK_HYPERBOLIC_CALLPRICE_TERMSTRUCTURE",
  366.             dtToday,
  367.             "USD",
  368.             astrMaturityTenor,
  369.             adblCallPrice,
  370.             1.
  371.         );

  372.         NodeStructure tsCallPriceKLKRationalLinear = ScenarioTermStructureBuilder.KLKRationalLinearTermStructure (
  373.             "KLK_RATIONAL_LINEAR_CALLPRICE_TERMSTRUCTURE",
  374.             dtToday,
  375.             "USD",
  376.             astrMaturityTenor,
  377.             adblCallPrice,
  378.             1.
  379.         );

  380.         NodeStructure tsCallPriceKLKRationalQuadratic = ScenarioTermStructureBuilder.KLKRationalQuadraticTermStructure (
  381.             "KLK_RATIONAL_QUADRATIC_CALLPRICE_TERMSTRUCTURE",
  382.             dtToday,
  383.             "USD",
  384.             astrMaturityTenor,
  385.             adblCallPrice,
  386.             0.0001
  387.         );

  388.         InputNodeReplicator (
  389.             tsCallPriceCubicPoly,
  390.             astrMaturityTenor,
  391.             adblCallPrice
  392.         );

  393.         NodeStructure tsCallVolatilityCubicPoly = ScenarioTermStructureBuilder.CubicPolynomialTermStructure (
  394.             "CUBIC_POLY_CALLVOL_TERMSTRUCTURE",
  395.             dtToday,
  396.             "USD",
  397.             astrMaturityTenor,
  398.             adblImpliedCallVolatility
  399.         );

  400.         NodeStructure tsCallVolatilityQuarticPoly = ScenarioTermStructureBuilder.QuarticPolynomialTermStructure (
  401.             "QUARTIC_POLY_CALLVOL_TERMSTRUCTURE",
  402.             dtToday,
  403.             "USD",
  404.             astrMaturityTenor,
  405.             adblImpliedCallVolatility
  406.         );

  407.         NodeStructure tsCallVolatilityKaklisPandelis = ScenarioTermStructureBuilder.KaklisPandelisTermStructure (
  408.             "KAKLIS_PANDELIS_CALLVOL_TERMSTRUCTURE",
  409.             dtToday,
  410.             "USD",
  411.             astrMaturityTenor,
  412.             adblImpliedCallVolatility
  413.         );

  414.         NodeStructure tsCallVolatilityKLKHyperbolic = ScenarioTermStructureBuilder.KLKHyperbolicTermStructure (
  415.             "KLK_HYPERBOLIC_CALLVOL_TERMSTRUCTURE",
  416.             dtToday,
  417.             "USD",
  418.             astrMaturityTenor,
  419.             adblImpliedCallVolatility,
  420.             1.
  421.         );

  422.         NodeStructure tsCallVolatilityKLKRationalLinear = ScenarioTermStructureBuilder.KLKRationalLinearTermStructure (
  423.             "KLK_RATIONAL_LINEAR_CALLVOL_TERMSTRUCTURE",
  424.             dtToday,
  425.             "USD",
  426.             astrMaturityTenor,
  427.             adblImpliedCallVolatility,
  428.             1.
  429.         );

  430.         NodeStructure tsCallVolatilityKLKRationalQuadratic = ScenarioTermStructureBuilder.KLKRationalQuadraticTermStructure (
  431.             "KLK_RATIONAL_QUADRATIC_CALLVOL_TERMSTRUCTURE",
  432.             dtToday,
  433.             "USD",
  434.             astrMaturityTenor,
  435.             adblImpliedCallVolatility,
  436.             0.0001
  437.         );

  438.         InputNodeReplicator (
  439.             tsCallVolatilityCubicPoly,
  440.             astrMaturityTenor,
  441.             adblImpliedCallVolatility
  442.         );

  443.         String[] astrOffGridTenor = new String[] {
  444.             "03M", "09M", "18M", "30Y", "42M", "54M", "06Y", "09Y", "12Y", "18Y", "25Y"
  445.         };

  446.         OffGrid (
  447.             "ATM_CALLPRICE_TERM_STRUCTURE",
  448.             new String[] {
  449.                 "Cubic Poly", "Quart Poly", "KaklisPand", "KLKHyperbl", "KLKRatlLin", "KLKRatlQua"
  450.             },
  451.             new NodeStructure[] {
  452.                 tsCallPriceCubicPoly,
  453.                 tsCallPriceQuarticPoly,
  454.                 tsCallPriceKaklisPandelis,
  455.                 tsCallPriceKLKHyperbolic,
  456.                 tsCallPriceKLKRationalLinear,
  457.                 tsCallPriceKLKRationalQuadratic
  458.             },
  459.             astrOffGridTenor
  460.         );

  461.         OffGrid (
  462.             "ATM_CALLVOL_TERM_STRUCTURE",
  463.             new String[] {
  464.                 "Cubic Poly", "Quart Poly", "KaklisPand", "KLKHyperbl", "KLKRatlLin", "KLKRatlQua"
  465.             },
  466.             new NodeStructure[] {
  467.                 tsCallVolatilityCubicPoly,
  468.                 tsCallVolatilityQuarticPoly,
  469.                 tsCallVolatilityKaklisPandelis,
  470.                 tsCallVolatilityKLKHyperbolic,
  471.                 tsCallVolatilityKLKRationalLinear,
  472.                 tsCallVolatilityKLKRationalQuadratic
  473.             },
  474.             astrOffGridTenor
  475.         );
  476.     }
  477. }