MultiCurveFRAStandard.java

  1. package org.drip.sample.fra;

  2. import java.util.*;

  3. import org.drip.analytics.date.*;
  4. import org.drip.function.r1tor1.FlatUnivariate;
  5. import org.drip.market.otc.*;
  6. import org.drip.param.creator.*;
  7. import org.drip.param.market.CurveSurfaceQuoteContainer;
  8. import org.drip.param.valuation.*;
  9. import org.drip.product.creator.*;
  10. import org.drip.product.definition.*;
  11. import org.drip.product.fra.FRAStandardComponent;
  12. import org.drip.product.rates.*;
  13. import org.drip.service.env.EnvManager;
  14. import org.drip.spline.basis.PolynomialFunctionSetParams;
  15. import org.drip.spline.stretch.MultiSegmentSequenceBuilder;
  16. import org.drip.state.creator.*;
  17. import org.drip.state.discount.*;
  18. import org.drip.state.forward.ForwardCurve;
  19. import org.drip.state.identifier.*;

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

  23. /*!
  24.  * Copyright (C) 2019 Lakshmi Krishnamurthy
  25.  * Copyright (C) 2018 Lakshmi Krishnamurthy
  26.  * Copyright (C) 2017 Lakshmi Krishnamurthy
  27.  * Copyright (C) 2016 Lakshmi Krishnamurthy
  28.  * Copyright (C) 2015 Lakshmi Krishnamurthy
  29.  * Copyright (C) 2014 Lakshmi Krishnamurthy
  30.  *
  31.  *  This file is part of DROP, an open-source library targeting risk, transaction costs, exposure, margin
  32.  *      calculations, valuation adjustment, and portfolio construction within and across fixed income,
  33.  *      credit, commodity, equity, FX, and structured products.
  34.  *  
  35.  *      https://lakshmidrip.github.io/DROP/
  36.  *  
  37.  *  DROP is composed of three modules:
  38.  *  
  39.  *  - DROP Analytics Core - https://lakshmidrip.github.io/DROP-Analytics-Core/
  40.  *  - DROP Portfolio Core - https://lakshmidrip.github.io/DROP-Portfolio-Core/
  41.  *  - DROP Numerical Core - https://lakshmidrip.github.io/DROP-Numerical-Core/
  42.  *
  43.  *  DROP Analytics Core implements libraries for the following:
  44.  *  - Fixed Income Analytics
  45.  *  - Asset Backed Analytics
  46.  *  - XVA Analytics
  47.  *  - Exposure and Margin Analytics
  48.  *
  49.  *  DROP Portfolio Core implements libraries for the following:
  50.  *  - Asset Allocation Analytics
  51.  *  - Transaction Cost Analytics
  52.  *
  53.  *  DROP Numerical Core implements libraries for the following:
  54.  *  - Statistical Learning
  55.  *  - Numerical Optimizer
  56.  *  - Spline Builder
  57.  *  - Algorithm Support
  58.  *
  59.  *  Documentation for DROP is Spread Over:
  60.  *
  61.  *  - Main                     => https://lakshmidrip.github.io/DROP/
  62.  *  - Wiki                     => https://github.com/lakshmiDRIP/DROP/wiki
  63.  *  - GitHub                   => https://github.com/lakshmiDRIP/DROP
  64.  *  - Repo Layout Taxonomy     => https://github.com/lakshmiDRIP/DROP/blob/master/Taxonomy.md
  65.  *  - Javadoc                  => https://lakshmidrip.github.io/DROP/Javadoc/index.html
  66.  *  - Technical Specifications => https://github.com/lakshmiDRIP/DROP/tree/master/Docs/Internal
  67.  *  - Release Versions         => https://lakshmidrip.github.io/DROP/version.html
  68.  *  - Community Credits        => https://lakshmidrip.github.io/DROP/credits.html
  69.  *  - Issues Catalog           => https://github.com/lakshmiDRIP/DROP/issues
  70.  *  - JUnit                    => https://lakshmidrip.github.io/DROP/junit/index.html
  71.  *  - Jacoco                   => https://lakshmidrip.github.io/DROP/jacoco/index.html
  72.  *
  73.  *  Licensed under the Apache License, Version 2.0 (the "License");
  74.  *      you may not use this file except in compliance with the License.
  75.  *  
  76.  *  You may obtain a copy of the License at
  77.  *      http://www.apache.org/licenses/LICENSE-2.0
  78.  *  
  79.  *  Unless required by applicable law or agreed to in writing, software
  80.  *      distributed under the License is distributed on an "AS IS" BASIS,
  81.  *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  82.  *  
  83.  *  See the License for the specific language governing permissions and
  84.  *      limitations under the License.
  85.  */

  86. /**
  87.  * <i>MultiCurveFRAStandard</i> contains the demonstration of the Standard Multi-Curve FRA product sample.
  88.  *  
  89.  * <br><br>
  90.  *  <ul>
  91.  *      <li><b>Module </b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/AnalyticsCore.md">Analytics Core Module</a></li>
  92.  *      <li><b>Library</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/FixedIncomeAnalyticsLibrary.md">Fixed Income Analytics Library</a></li>
  93.  *      <li><b>Project</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/sample/README.md">Sample</a></li>
  94.  *      <li><b>Package</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/sample/fra/README.md">FRA Analytics</a></li>
  95.  *  </ul>
  96.  * <br><br>
  97.  *
  98.  * @author Lakshmi Krishnamurthy
  99.  */

  100. public class MultiCurveFRAStandard {

  101.     private static final FixFloatComponent OTCFixFloat (
  102.         final JulianDate dtSpot,
  103.         final String strCurrency,
  104.         final String strMaturityTenor,
  105.         final double dblCoupon)
  106.     {
  107.         FixedFloatSwapConvention ffConv = IBORFixedFloatContainer.ConventionFromJurisdiction (
  108.             strCurrency,
  109.             "ALL",
  110.             strMaturityTenor,
  111.             "MAIN"
  112.         );

  113.         return ffConv.createFixFloatComponent (
  114.             dtSpot,
  115.             strMaturityTenor,
  116.             dblCoupon,
  117.             0.,
  118.             1.
  119.         );
  120.     }

  121.     private static final FloatFloatComponent OTCFloatFloat (
  122.         final JulianDate dtSpot,
  123.         final String strCurrency,
  124.         final String strDerivedTenor,
  125.         final String strMaturityTenor,
  126.         final double dblBasis)
  127.     {
  128.         FloatFloatSwapConvention ffConv = IBORFloatFloatContainer.ConventionFromJurisdiction (strCurrency);

  129.         return ffConv.createFloatFloatComponent (
  130.             dtSpot,
  131.             strDerivedTenor,
  132.             strMaturityTenor,
  133.             dblBasis,
  134.             1.
  135.         );
  136.     }

  137.     /*
  138.      * Construct the Array of Deposit Instruments from the given set of parameters
  139.      *
  140.      *      USE WITH CARE: This sample ignores errors and does not handle exceptions.
  141.      */

  142.     private static final CalibratableComponent[] DepositInstrumentsFromMaturityDays (
  143.         final JulianDate dtEffective,
  144.         final int[] aiDay,
  145.         final int iNumFuture,
  146.         final String strCurrency)
  147.         throws Exception
  148.     {
  149.         CalibratableComponent[] aCalibComp = new CalibratableComponent[aiDay.length + iNumFuture];

  150.         for (int i = 0; i < aiDay.length; ++i)
  151.             aCalibComp[i] = SingleStreamComponentBuilder.Deposit (
  152.                 dtEffective,
  153.                 dtEffective.addBusDays (
  154.                     aiDay[i],
  155.                     strCurrency
  156.                 ),
  157.                 ForwardLabel.Create (
  158.                     strCurrency,
  159.                     "3M"
  160.                 )
  161.             );

  162.         CalibratableComponent[] aEDF = SingleStreamComponentBuilder.ForwardRateFuturesPack (
  163.             dtEffective,
  164.             iNumFuture,
  165.             strCurrency
  166.         );

  167.         for (int i = aiDay.length; i < aiDay.length + iNumFuture; ++i)
  168.             aCalibComp[i] = aEDF[i - aiDay.length];

  169.         return aCalibComp;
  170.     }

  171.     /*
  172.      * Construct the Array of Swap Instruments from the given set of parameters
  173.      *
  174.      *      USE WITH CARE: This sample ignores errors and does not handle exceptions.
  175.      */

  176.     private static final FixFloatComponent[] SwapInstrumentsFromMaturityTenor (
  177.         final JulianDate dtSpot,
  178.         final String strCurrency,
  179.         final String[] astrMaturityTenor,
  180.         final double[] adblCoupon)
  181.         throws Exception
  182.     {
  183.         FixFloatComponent[] aIRS = new FixFloatComponent[astrMaturityTenor.length];

  184.         for (int i = 0; i < astrMaturityTenor.length; ++i)
  185.             aIRS[i] = OTCFixFloat (
  186.                 dtSpot,
  187.                 strCurrency,
  188.                 astrMaturityTenor[i],
  189.                 adblCoupon[i]
  190.             );

  191.         return aIRS;
  192.     }

  193.     /*
  194.      * Construct the discount curve using the following steps:
  195.      *  - Construct the array of cash instruments and their quotes.
  196.      *  - Construct the array of swap instruments and their quotes.
  197.      *  - Construct a shape preserving and smoothing KLK Hyperbolic Spline from the cash/swap instruments.
  198.      *
  199.      *      USE WITH CARE: This sample ignores errors and does not handle exceptions.
  200.      */

  201.     private static final MergedDiscountForwardCurve MakeDC (
  202.         final JulianDate dtSpot,
  203.         final String strCurrency)
  204.         throws Exception
  205.     {
  206.         /*
  207.          * Construct the array of Deposit instruments and their quotes.
  208.          */

  209.         CalibratableComponent[] aDepositComp = DepositInstrumentsFromMaturityDays (
  210.             dtSpot,
  211.             new int[] {
  212.                 1, 2, 3, 7, 14, 21, 30, 60
  213.             },
  214.             0,
  215.             strCurrency
  216.         );

  217.         double[] adblDepositQuote = new double[] {
  218.             0.01200, 0.01200, 0.01200, 0.01450, 0.01550, 0.01600, 0.01660, 0.01850
  219.         };

  220.         String[] astrDepositManifestMeasure = new String[] {
  221.             "ForwardRate",
  222.             "ForwardRate",
  223.             "ForwardRate",
  224.             "ForwardRate",
  225.             "ForwardRate",
  226.             "ForwardRate",
  227.             "ForwardRate",
  228.             "ForwardRate"
  229.         };

  230.         /*
  231.          * Construct the array of Swap instruments and their quotes.
  232.          */

  233.         double[] adblSwapQuote = new double[] {
  234.             0.02604,    //  4Y
  235.             0.02808,    //  5Y
  236.             0.02983,    //  6Y
  237.             0.03136,    //  7Y
  238.             0.03268,    //  8Y
  239.             0.03383,    //  9Y
  240.             0.03488,    // 10Y
  241.             0.03583,    // 11Y
  242.             0.03668,    // 12Y
  243.             0.03833,    // 15Y
  244.             0.03854,    // 20Y
  245.             0.03672,    // 25Y
  246.             0.03510,    // 30Y
  247.             0.03266,    // 40Y
  248.             0.03145     // 50Y
  249.         };

  250.         String[] astrSwapManifestMeasure = new String[] {
  251.             "SwapRate",    //  4Y
  252.             "SwapRate",    //  5Y
  253.             "SwapRate",    //  6Y
  254.             "SwapRate",    //  7Y
  255.             "SwapRate",    //  8Y
  256.             "SwapRate",    //  9Y
  257.             "SwapRate",    // 10Y
  258.             "SwapRate",    // 11Y
  259.             "SwapRate",    // 12Y
  260.             "SwapRate",    // 15Y
  261.             "SwapRate",    // 20Y
  262.             "SwapRate",    // 25Y
  263.             "SwapRate",    // 30Y
  264.             "SwapRate",    // 40Y
  265.             "SwapRate"     // 50Y
  266.         };

  267.         CalibratableComponent[] aSwapComp = SwapInstrumentsFromMaturityTenor (
  268.             dtSpot,
  269.             strCurrency,
  270.             new java.lang.String[] {
  271.                 "4Y", "5Y", "6Y", "7Y", "8Y", "9Y", "10Y", "11Y", "12Y", "15Y", "20Y", "25Y", "30Y", "40Y", "50Y"
  272.             },
  273.             adblSwapQuote
  274.         );

  275.         /*
  276.          * Construct a shape preserving and smoothing KLK Hyperbolic Spline from the cash/swap instruments.
  277.          */

  278.         return ScenarioDiscountCurveBuilder.CubicKLKHyperbolicDFRateShapePreserver (
  279.             "KLK_HYPERBOLIC_SHAPE_TEMPLATE",
  280.             new ValuationParams (
  281.                 dtSpot,
  282.                 dtSpot,
  283.                 strCurrency
  284.             ),
  285.             aDepositComp,
  286.             adblDepositQuote,
  287.             astrDepositManifestMeasure,
  288.             aSwapComp,
  289.             adblSwapQuote,
  290.             astrSwapManifestMeasure,
  291.             false
  292.         );
  293.     }

  294.     /*
  295.      * Construct an array of float-float swaps from the corresponding reference (6M) and the derived legs.
  296.      *
  297.      *      USE WITH CARE: This sample ignores errors and does not handle exceptions.
  298.      */

  299.     private static final FloatFloatComponent[] MakexM6MBasisSwap (
  300.         final JulianDate dtSpot,
  301.         final String strCurrency,
  302.         final String[] astrMaturityTenor,
  303.         final int iTenorInMonths)
  304.         throws Exception
  305.     {
  306.         FloatFloatComponent[] aFFC = new FloatFloatComponent[astrMaturityTenor.length];

  307.         for (int i = 0; i < astrMaturityTenor.length; ++i)
  308.             aFFC[i] = OTCFloatFloat (
  309.                 dtSpot,
  310.                 strCurrency,
  311.                 iTenorInMonths + "M",
  312.                 astrMaturityTenor[i],
  313.                 0.
  314.             );

  315.         return aFFC;
  316.     }

  317.     private static final ForwardCurve MakeFC (
  318.         final JulianDate dtSpot,
  319.         final String strCurrency,
  320.         final MergedDiscountForwardCurve dc,
  321.         final int iTenorInMonths,
  322.         final String[] astrxM6MFwdTenor,
  323.         final double[] adblxM6MBasisSwapQuote)
  324.         throws Exception
  325.     {
  326.         /*
  327.          * Construct the 6M-xM float-float basis swap.
  328.          */

  329.         FloatFloatComponent[] aFFC = MakexM6MBasisSwap (
  330.             dtSpot,
  331.             strCurrency,
  332.             astrxM6MFwdTenor,
  333.             iTenorInMonths
  334.         );

  335.         String strBasisTenor = iTenorInMonths + "M";

  336.         ValuationParams valParams = new ValuationParams (
  337.             dtSpot,
  338.             dtSpot,
  339.             strCurrency
  340.         );

  341.         /*
  342.          * Calculate the starting forward rate off of the discount curve.
  343.          */

  344.         double dblStartingFwd = dc.forward (
  345.             dtSpot.julian(),
  346.             dtSpot.addTenor (strBasisTenor).julian()
  347.         );

  348.         /*
  349.          * Set the discount curve based component market parameters.
  350.          */

  351.         CurveSurfaceQuoteContainer mktParams = MarketParamsBuilder.Create (dc, null, null, null, null, null, null);

  352.         /*
  353.          * Construct the shape preserving forward curve off of Quartic Polynomial Basis Spline.
  354.          */

  355.         return ScenarioForwardCurveBuilder.ShapePreservingForwardCurve (
  356.             "QUARTIC_FWD" + strBasisTenor,
  357.             ForwardLabel.Create (
  358.                 strCurrency,
  359.                 strBasisTenor
  360.             ),
  361.             valParams,
  362.             null,
  363.             mktParams,
  364.             null,
  365.             MultiSegmentSequenceBuilder.BASIS_SPLINE_POLYNOMIAL,
  366.             new PolynomialFunctionSetParams (5),
  367.             aFFC,
  368.             "DerivedParBasisSpread",
  369.             adblxM6MBasisSwapQuote,
  370.             dblStartingFwd
  371.         );
  372.     }

  373.     private static final Map<String, ForwardCurve> MakeFC (
  374.         final JulianDate dt,
  375.         final String strCurrency,
  376.         final MergedDiscountForwardCurve dc)
  377.         throws Exception
  378.     {
  379.         Map<String, ForwardCurve> mapFC = new HashMap<String, ForwardCurve>();

  380.         /*
  381.          * Build and run the sampling for the 1M-6M Tenor Basis Swap from its instruments and quotes.
  382.          */

  383.         ForwardCurve fc1M = MakeFC (
  384.             dt,
  385.             strCurrency,
  386.             dc,
  387.             1,
  388.             new String[] {
  389.                 "1Y", "2Y", "3Y", "4Y", "5Y", "6Y", "7Y", "8Y", "9Y", "10Y", "11Y", "12Y", "15Y", "20Y", "25Y", "30Y"
  390.             },
  391.             new double[] {
  392.                 0.00551,    //  1Y
  393.                 0.00387,    //  2Y
  394.                 0.00298,    //  3Y
  395.                 0.00247,    //  4Y
  396.                 0.00211,    //  5Y
  397.                 0.00185,    //  6Y
  398.                 0.00165,    //  7Y
  399.                 0.00150,    //  8Y
  400.                 0.00137,    //  9Y
  401.                 0.00127,    // 10Y
  402.                 0.00119,    // 11Y
  403.                 0.00112,    // 12Y
  404.                 0.00096,    // 15Y
  405.                 0.00079,    // 20Y
  406.                 0.00069,    // 25Y
  407.                 0.00062     // 30Y
  408.                 }
  409.             );

  410.         mapFC.put (
  411.             "1M",
  412.             fc1M
  413.         );

  414.         /*
  415.          * Build and run the sampling for the 3M-6M Tenor Basis Swap from its instruments and quotes.
  416.          */

  417.         ForwardCurve fc3M = MakeFC (
  418.             dt,
  419.             strCurrency,
  420.             dc,
  421.             3,
  422.             new String[] {
  423.                 "1Y", "2Y", "3Y", "4Y", "5Y", "6Y", "7Y", "8Y", "9Y", "10Y", "11Y", "12Y", "15Y", "20Y", "25Y", "30Y"
  424.             },
  425.             new double[] {
  426.                 0.00186,    //  1Y
  427.                 0.00127,    //  2Y
  428.                 0.00097,    //  3Y
  429.                 0.00080,    //  4Y
  430.                 0.00067,    //  5Y
  431.                 0.00058,    //  6Y
  432.                 0.00051,    //  7Y
  433.                 0.00046,    //  8Y
  434.                 0.00042,    //  9Y
  435.                 0.00038,    // 10Y
  436.                 0.00035,    // 11Y
  437.                 0.00033,    // 12Y
  438.                 0.00028,    // 15Y
  439.                 0.00022,    // 20Y
  440.                 0.00020,    // 25Y
  441.                 0.00018     // 30Y
  442.                 }
  443.             );

  444.         mapFC.put (
  445.             "3M",
  446.             fc3M
  447.         );

  448.         /*
  449.          * Build and run the sampling for the 12M-6M Tenor Basis Swap from its instruments and quotes.
  450.          */

  451.         ForwardCurve fc12M = MakeFC (
  452.             dt,
  453.             strCurrency,
  454.             dc,
  455.             12,
  456.             new String[] {
  457.                 "1Y", "2Y", "3Y", "4Y", "5Y", "6Y", "7Y", "8Y", "9Y", "10Y", "11Y", "12Y", "15Y", "20Y", "25Y", "30Y",
  458.                 "35Y", "40Y" // Extrapolated
  459.             },
  460.             new double[] {
  461.                 -0.00212,    //  1Y
  462.                 -0.00152,    //  2Y
  463.                 -0.00117,    //  3Y
  464.                 -0.00097,    //  4Y
  465.                 -0.00082,    //  5Y
  466.                 -0.00072,    //  6Y
  467.                 -0.00063,    //  7Y
  468.                 -0.00057,    //  8Y
  469.                 -0.00051,    //  9Y
  470.                 -0.00047,    // 10Y
  471.                 -0.00044,    // 11Y
  472.                 -0.00041,    // 12Y
  473.                 -0.00035,    // 15Y
  474.                 -0.00028,    // 20Y
  475.                 -0.00025,    // 25Y
  476.                 -0.00022,    // 30Y
  477.                 -0.00022,    // 35Y Extrapolated
  478.                 -0.00022,    // 40Y Extrapolated
  479.                 }
  480.             );

  481.         mapFC.put (
  482.             "12M",
  483.             fc12M
  484.         );

  485.         return mapFC;
  486.     }

  487.     public static final void main (
  488.         final String[] astrArgs)
  489.         throws Exception
  490.     {
  491.         /*
  492.          * Initialize the Credit Analytics Library
  493.          */

  494.         EnvManager.InitEnv ("");

  495.         String strTenor = "3M";
  496.         String strCurrency = "CAD";
  497.         double dblForwardVol = 0.3;
  498.         double dblFundingVol = 0.1;
  499.         double dblForwardFundingCorr = 0.2;

  500.         JulianDate dtToday = DateUtil.Today().addTenorAndAdjust (
  501.             "0D",
  502.             strCurrency
  503.         );

  504.         /*
  505.          * Construct the Discount Curve using its instruments and quotes
  506.          */

  507.         MergedDiscountForwardCurve dc = MakeDC (
  508.             dtToday,
  509.             strCurrency
  510.         );

  511.         Map<String, ForwardCurve> mapFC = MakeFC (
  512.             dtToday,
  513.             strCurrency,
  514.             dc
  515.         );

  516.         ForwardLabel fri = ForwardLabel.Create (
  517.             strCurrency,
  518.             strTenor
  519.         );

  520.         JulianDate dtForwardStart = dtToday.addTenor (strTenor);

  521.         FRAStandardComponent fra = SingleStreamComponentBuilder.FRAStandard (
  522.             dtForwardStart,
  523.             fri,
  524.             0.006
  525.         );

  526.         CurveSurfaceQuoteContainer mktParams = MarketParamsBuilder.Create (
  527.             dc,
  528.             mapFC.get (strTenor),
  529.             null,
  530.             null,
  531.             null,
  532.             null,
  533.             null,
  534.             null
  535.         );

  536.         ValuationParams valParams = new ValuationParams (
  537.             dtToday,
  538.             dtToday,
  539.             strCurrency
  540.         );

  541.         FundingLabel fundingLabel = FundingLabel.Standard (fri.currency());

  542.         mktParams.setForwardVolatility (
  543.             ScenarioDeterministicVolatilityBuilder.FlatForward (
  544.                 dtToday.julian(),
  545.                 VolatilityLabel.Standard (fri),
  546.                 fri.currency(),
  547.                 dblForwardVol
  548.             )
  549.         );

  550.         mktParams.setFundingVolatility (
  551.             ScenarioDeterministicVolatilityBuilder.FlatForward (
  552.                 dtToday.julian(),
  553.                 VolatilityLabel.Standard (fundingLabel),
  554.                 fri.currency(),
  555.                 dblFundingVol
  556.             )
  557.         );

  558.         mktParams.setForwardFundingCorrelation (
  559.             fri,
  560.             fundingLabel,
  561.             new FlatUnivariate (dblForwardFundingCorr)
  562.         );

  563.         Map<String, Double> mapFRAOutput = fra.value (
  564.             valParams,
  565.             null,
  566.             mktParams,
  567.             null
  568.         );

  569.         for (Map.Entry<String, Double> me : mapFRAOutput.entrySet())
  570.             System.out.println ("\t" + me.getKey() + " => " + me.getValue());

  571.         EnvManager.TerminateEnv();
  572.     }
  573. }