TrajectoryEvolutionScheme.java

  1. package org.drip.xva.pde;

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

  76. /**
  77.  * <i>TrajectoryEvolutionScheme</i> holds the Evolution Edges of a Trajectory evolved in a Dynamically
  78.  * Adaptive Manner, as laid out in Burgard and Kjaer (2014). The References are:
  79.  *
  80.  *  <br><br>
  81.  *  <ul>
  82.  *      <li>
  83.  *          Burgard, C., and M. Kjaer (2014): PDE Representations of Derivatives with Bilateral Counter-party
  84.  *              Risk and Funding Costs <i>Journal of Credit Risk</i> <b>7 (3)</b> 1-19
  85.  *      </li>
  86.  *      <li>
  87.  *          Cesari, G., J. Aquilina, N. Charpillon, X. Filipovic, G. Lee, and L. Manda (2009): <i>Modeling,
  88.  *              Pricing, and Hedging Counter-party Credit Exposure - A Technical Guide</i> <b>Springer
  89.  *              Finance</b> New York
  90.  *      </li>
  91.  *      <li>
  92.  *          Gregory, J. (2009): Being Two-faced over Counter-party Credit Risk <i>Risk</i> <b>20 (2)</b>
  93.  *              86-90
  94.  *      </li>
  95.  *      <li>
  96.  *          Li, B., and Y. Tang (2007): <i>Quantitative Analysis, Derivatives Modeling, and Trading
  97.  *              Strategies in the Presence of Counter-party Credit Risk for the Fixed Income Market</i>
  98.  *              <b>World Scientific Publishing</b> Singapore
  99.  *      </li>
  100.  *      <li>
  101.  *          Piterbarg, V. (2010): Funding Beyond Discounting: Collateral Agreements and Derivatives Pricing
  102.  *              <i>Risk</i> <b>21 (2)</b> 97-102
  103.  *      </li>
  104.  *  </ul>
  105.  *
  106.  *  <br><br>
  107.  *  <ul>
  108.  *      <li><b>Module </b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/PortfolioCore.md">Portfolio Core Module</a></li>
  109.  *      <li><b>Library</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/XVAAnalyticsLibrary.md">XVA Analytics Library</a></li>
  110.  *      <li><b>Project</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/xva/README.md">Valuation Adjustments that account for Collateral, CC Credit/Debt and Funding Overhead</a></li>
  111.  *      <li><b>Package</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/xva/pde/README.md">Burgard Kjaer PDE Evolution Scheme</a></li>
  112.  *  </ul>
  113.  * <br><br>
  114.  *
  115.  * @author Lakshmi Krishnamurthy
  116.  */

  117. public class TrajectoryEvolutionScheme
  118. {
  119.     private org.drip.xva.definition.PDEEvolutionControl _pdeEvolutionControl = null;
  120.     private org.drip.exposure.evolver.PrimarySecurityDynamicsContainer _tradeablesContainer = null;

  121.     /**
  122.      * TrajectoryEvolutionScheme Constructor
  123.      *
  124.      * @param tradeablesContainer The Universe of Tradeables
  125.      * @param pdeEvolutionControl The XVA PDE Control Settings
  126.      *
  127.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  128.      */

  129.     public TrajectoryEvolutionScheme (
  130.         final org.drip.exposure.evolver.PrimarySecurityDynamicsContainer tradeablesContainer,
  131.         final org.drip.xva.definition.PDEEvolutionControl pdeEvolutionControl)
  132.         throws java.lang.Exception
  133.     {
  134.         if (null == (_tradeablesContainer = tradeablesContainer) ||
  135.             null == (_pdeEvolutionControl = pdeEvolutionControl))
  136.         {
  137.             throw new java.lang.Exception ("TrajectoryEvolutionScheme Constructor => Invalid Inputs");
  138.         }
  139.     }

  140.     /**
  141.      * Retrieve the Universe of Tradeables
  142.      *
  143.      * @return The Universe of Tradeables
  144.      */

  145.     public org.drip.exposure.evolver.PrimarySecurityDynamicsContainer tradeablesContainer()
  146.     {
  147.         return _tradeablesContainer;
  148.     }

  149.     /**
  150.      * Retrieve the XVA PDE Control Settings
  151.      *
  152.      * @return The XVA PDE Control Settings
  153.      */

  154.     public org.drip.xva.definition.PDEEvolutionControl pdeEvolutionControl()
  155.     {
  156.         return _pdeEvolutionControl;
  157.     }

  158.     /**
  159.      * Re-balance the Cash Account and generate the Derivative Value Update
  160.      *
  161.      * @param initialTrajectoryVertex The Starting Evolution Trajectory Vertex
  162.      * @param marketEdge Market Edge Instance
  163.      *
  164.      * @return The CashAccountRebalancer Instance
  165.      */

  166.     public org.drip.xva.derivative.CashAccountRebalancer rebalanceCash (
  167.         final org.drip.xva.derivative.EvolutionTrajectoryVertex initialTrajectoryVertex,
  168.         final org.drip.exposure.universe.MarketEdge marketEdge)
  169.     {
  170.         if (null == initialTrajectoryVertex ||
  171.             null == marketEdge)
  172.         {
  173.             return null;
  174.         }

  175.         org.drip.xva.derivative.ReplicationPortfolioVertex initialReplicationPortfolioVertex =
  176.             initialTrajectoryVertex.replicationPortfolioVertex();

  177.         double initialPortfolioHoldings = initialReplicationPortfolioVertex.positionHoldings();

  178.         double initialDealerSeniorNumeraireHoldings =
  179.             initialReplicationPortfolioVertex.dealerSeniorNumeraireHoldings();

  180.         double initialClientNumeraireHoldings = initialReplicationPortfolioVertex.clientNumeraireHoldings();

  181.         double initialDealerSubordinateNumeraireHoldings =
  182.             initialReplicationPortfolioVertex.dealerSubordinateNumeraireHoldings();

  183.         org.drip.exposure.universe.MarketVertex initialMarketVertex = marketEdge.start();

  184.         org.drip.exposure.universe.MarketVertex finalMarketVertex = marketEdge.finish();

  185.         org.drip.exposure.universe.MarketVertexEntity emvDealerStart = initialMarketVertex.dealer();

  186.         org.drip.exposure.universe.MarketVertexEntity dealerMarketVertex = finalMarketVertex.dealer();

  187.         org.drip.exposure.universe.MarketVertexEntity clientMarketVertex = finalMarketVertex.client();

  188.         double finalDealerSeniorFundingNumeraire = dealerMarketVertex.seniorFundingReplicator();

  189.         double finalClientNumeraire = clientMarketVertex.seniorFundingReplicator();

  190.         double initialDealerSubordinateFundingNumeraire = emvDealerStart.subordinateFundingReplicator();

  191.         double finalDealerSubordinateFundingNumeraire = dealerMarketVertex.subordinateFundingReplicator();

  192.         double timeIncrement = marketEdge.vertexIncrement() / 365.25;

  193.         org.drip.exposure.evolver.PrimarySecurity clientFundingTradeable = _tradeablesContainer.clientFunding();

  194.         double clientCashAccumulation = initialClientNumeraireHoldings *
  195.             clientFundingTradeable.cashAccumulationRate() * finalClientNumeraire * timeIncrement;

  196.         double clientHoldingsValueChange = initialClientNumeraireHoldings * (finalClientNumeraire -
  197.             initialMarketVertex.client().seniorFundingReplicator());

  198.         double cashAccountBalance = -1. * initialTrajectoryVertex.positionGreekVertex().derivativeXVAValue()
  199.             - initialDealerSeniorNumeraireHoldings * finalDealerSeniorFundingNumeraire;

  200.         if (org.drip.numerical.common.NumberUtil.IsValid (finalDealerSubordinateFundingNumeraire))
  201.         {
  202.             cashAccountBalance -= initialDealerSubordinateNumeraireHoldings *
  203.                 finalDealerSubordinateFundingNumeraire;
  204.         }

  205.         org.drip.exposure.evolver.PrimarySecurity csaTradeable = _tradeablesContainer.csa();

  206.         org.drip.exposure.evolver.PrimarySecurity dealerSeniorFundingTradeable =
  207.             _tradeablesContainer.dealerSeniorFunding();

  208.         double dealerCashAccumulation = cashAccountBalance * (cashAccountBalance > 0. ?
  209.             csaTradeable.cashAccumulationRate() : dealerSeniorFundingTradeable.cashAccumulationRate()) *
  210.                 timeIncrement;

  211.         try
  212.         {
  213.             double finalPortfolioValue = finalMarketVertex.latentStateValue
  214.                 (_tradeablesContainer.assetList().get (0).label());

  215.             double portfolioCashChange = initialPortfolioHoldings *
  216.                 _tradeablesContainer.assetList().get (0).cashAccumulationRate() * finalPortfolioValue *
  217.                     timeIncrement;

  218.             double derivativeXVAValueChange = -1. * (initialPortfolioHoldings * (finalPortfolioValue -
  219.                 initialMarketVertex.latentStateValue (_tradeablesContainer.assetList().get (0).label())) +
  220.                     initialDealerSeniorNumeraireHoldings * (finalDealerSeniorFundingNumeraire -
  221.                         emvDealerStart.seniorFundingReplicator()) + clientHoldingsValueChange +
  222.                             (portfolioCashChange + clientCashAccumulation + dealerCashAccumulation) *
  223.                                 timeIncrement);

  224.             if (org.drip.numerical.common.NumberUtil.IsValid (initialDealerSubordinateFundingNumeraire) &&
  225.                 org.drip.numerical.common.NumberUtil.IsValid (finalDealerSubordinateFundingNumeraire))
  226.             {
  227.                 derivativeXVAValueChange += initialDealerSubordinateNumeraireHoldings *
  228.                     (finalDealerSubordinateFundingNumeraire - initialDealerSubordinateFundingNumeraire);
  229.             }

  230.             return new org.drip.xva.derivative.CashAccountRebalancer (
  231.                 new org.drip.xva.derivative.CashAccountEdge (
  232.                     portfolioCashChange,
  233.                     dealerCashAccumulation * timeIncrement,
  234.                     clientCashAccumulation * timeIncrement
  235.                 ),
  236.                 derivativeXVAValueChange
  237.             );
  238.         }
  239.         catch (java.lang.Exception e)
  240.         {
  241.             e.printStackTrace();
  242.         }

  243.         return null;
  244.     }

  245.     /**
  246.      * Execute a Single Euler Time Step Walk
  247.      *
  248.      * @param marketEdge Market Edge Instance
  249.      * @param burgardKjaerOperator The Burgard Kjaer Operator Instance
  250.      * @param initialTrajectoryVertex The Starting ETV Instance
  251.      * @param collateral The Applicable Collateral
  252.      *
  253.      * @return The Evolution Trajectory Edge
  254.      */

  255.     public org.drip.xva.derivative.EvolutionTrajectoryEdge eulerWalk (
  256.         final org.drip.exposure.universe.MarketEdge marketEdge,
  257.         final org.drip.xva.pde.BurgardKjaerOperator burgardKjaerOperator,
  258.         final org.drip.xva.derivative.EvolutionTrajectoryVertex initialTrajectoryVertex,
  259.         final double collateral)
  260.     {
  261.         if (null == marketEdge ||
  262.             null == burgardKjaerOperator ||
  263.             null == initialTrajectoryVertex)
  264.         {
  265.             return null;
  266.         }

  267.         org.drip.xva.derivative.PositionGreekVertex initialPositionGreekVertex =
  268.             initialTrajectoryVertex.positionGreekVertex();

  269.         org.drip.xva.pde.BurgardKjaerEdgeRun burgardKjaerEdgeRun = burgardKjaerOperator.edgeRun (
  270.             marketEdge,
  271.             initialTrajectoryVertex,
  272.             collateral
  273.         );

  274.         double initialTime = initialTrajectoryVertex.time();

  275.         double timeIncrement = marketEdge.vertexIncrement() / 365.25;

  276.         if (null == burgardKjaerEdgeRun)
  277.         {
  278.             return null;
  279.         }

  280.         double theta = burgardKjaerEdgeRun.theta();

  281.         double positionValueBump = burgardKjaerEdgeRun.positionValueBump();

  282.         double thetaPositionValueUp = burgardKjaerEdgeRun.thetaPositionValueUp();

  283.         double thetaPositionValueDown = burgardKjaerEdgeRun.thetaPositionValueDown();

  284.         org.drip.exposure.universe.MarketVertex finalMarketVertex = marketEdge.finish();

  285.         org.drip.exposure.universe.MarketVertexEntity dealerMarketVertex = finalMarketVertex.dealer();

  286.         org.drip.exposure.universe.MarketVertexEntity clientMarketVertex = finalMarketVertex.client();

  287.         double derivativeXVAValueDeltaFinish =
  288.             initialPositionGreekVertex.derivativeXVAValueDelta() +
  289.             0.5 * (thetaPositionValueUp - thetaPositionValueDown) * timeIncrement / positionValueBump;

  290.         double clientGainOnDealerDefault = java.lang.Double.NaN;
  291.         double finalGainOnClientDefault = java.lang.Double.NaN;

  292.         double derivativeXVAValueFinish = initialPositionGreekVertex.derivativeXVAValue() - theta *
  293.             timeIncrement;

  294.         try
  295.         {
  296.             org.drip.xva.definition.CloseOut closeOutScheme = new
  297.                 org.drip.xva.definition.CloseOutBilateral (
  298.                     dealerMarketVertex.seniorRecoveryRate(),
  299.                     clientMarketVertex.seniorRecoveryRate()
  300.                 );

  301.             clientGainOnDealerDefault = closeOutScheme.dealerDefault (derivativeXVAValueFinish);

  302.             finalGainOnClientDefault = -1. * (derivativeXVAValueFinish - closeOutScheme.clientDefault
  303.                 (derivativeXVAValueFinish));
  304.         }
  305.         catch (java.lang.Exception e)
  306.         {
  307.             e.printStackTrace();

  308.             return null;
  309.         }

  310.         double dealerSubordinateFundingNumeraire = dealerMarketVertex.subordinateFundingReplicator();

  311.         double gainOnDealerDefaultFinish = -1. * (derivativeXVAValueFinish - clientGainOnDealerDefault);

  312.         double finalClientHoldings = finalGainOnClientDefault / clientMarketVertex.seniorFundingReplicator();

  313.         org.drip.xva.derivative.CashAccountRebalancer cashAccountRebalancer = rebalanceCash (
  314.             initialTrajectoryVertex,
  315.             marketEdge
  316.         );

  317.         if (null == cashAccountRebalancer)
  318.         {
  319.             return null;
  320.         }

  321.         org.drip.xva.derivative.CashAccountEdge cashAccountEdge = cashAccountRebalancer.cashAccountEdge();

  322.         double dealerSeniorFundingNumeraire = dealerMarketVertex.seniorFundingReplicator();

  323.         org.drip.exposure.evolver.PrimarySecurity csaTradeable = _tradeablesContainer.csa();

  324.         try
  325.         {
  326.             org.drip.xva.derivative.EvolutionTrajectoryVertex finalTrajectoryVertex = new
  327.                 org.drip.xva.derivative.EvolutionTrajectoryVertex (
  328.                 initialTime + timeIncrement,
  329.                 new org.drip.xva.derivative.ReplicationPortfolioVertex (
  330.                     -1. * derivativeXVAValueDeltaFinish,
  331.                     gainOnDealerDefaultFinish / dealerSeniorFundingNumeraire,
  332.                     !org.drip.numerical.common.NumberUtil.IsValid (dealerSubordinateFundingNumeraire) ? 0. :
  333.                         gainOnDealerDefaultFinish / dealerSubordinateFundingNumeraire,
  334.                     finalClientHoldings,
  335.                     initialTrajectoryVertex.replicationPortfolioVertex().cashAccount() +
  336.                         cashAccountEdge.accumulation()
  337.                 ),
  338.                 new org.drip.xva.derivative.PositionGreekVertex (
  339.                     derivativeXVAValueFinish,
  340.                     derivativeXVAValueDeltaFinish,
  341.                     initialPositionGreekVertex.derivativeXVAValueGamma() +
  342.                         (thetaPositionValueUp + thetaPositionValueDown - 2. * theta) *
  343.                         timeIncrement / (positionValueBump * positionValueBump),
  344.                     initialPositionGreekVertex.derivativeFairValue() * java.lang.Math.exp (
  345.                         -1. * timeIncrement *
  346.                         csaTradeable.evolver().evaluator().drift().value (
  347.                             new org.drip.measure.realization.JumpDiffusionVertex (
  348.                                 initialTime - 0.5 * timeIncrement,
  349.                                 marketEdge.start().csaReplicator(),
  350.                                 0.,
  351.                                 false
  352.                             )
  353.                         )
  354.                     )
  355.                 ),
  356.                 gainOnDealerDefaultFinish,
  357.                 finalGainOnClientDefault,
  358.                 collateral,
  359.                 burgardKjaerEdgeRun.derivativeXVAHedgeErrorGrowth()
  360.             );

  361.             return new org.drip.xva.derivative.EvolutionTrajectoryEdge (
  362.                 initialTrajectoryVertex,
  363.                 finalTrajectoryVertex,
  364.                 cashAccountEdge
  365.             );
  366.         }
  367.         catch (java.lang.Exception e)
  368.         {
  369.             e.printStackTrace();
  370.         }

  371.         return null;
  372.     }

  373.     /**
  374.      * Execute a Sequential Array of Euler Time Step Walks
  375.      *
  376.      * @param marketVertexArray Array of Market Vertexes
  377.      * @param burgardKjaerOperator The Burgard Kjaer Operator Instance
  378.      * @param initialTrajectoryVertex The Starting EET Instance
  379.      * @param collateral The Applicable Collateral
  380.      *
  381.      * @return Array of EvolutionTrajectoryEdge Instances
  382.      */

  383.     public org.drip.xva.derivative.EvolutionTrajectoryEdge[] eulerWalk (
  384.         final org.drip.exposure.universe.MarketVertex[] marketVertexArray,
  385.         final org.drip.xva.pde.BurgardKjaerOperator burgardKjaerOperator,
  386.         final org.drip.xva.derivative.EvolutionTrajectoryVertex initialTrajectoryVertex,
  387.         final double collateral)
  388.     {
  389.         if (null == marketVertexArray)
  390.         {
  391.             return null;
  392.         }

  393.         int vertexCount = marketVertexArray.length;
  394.         org.drip.xva.derivative.EvolutionTrajectoryVertex trajectoryVertex = initialTrajectoryVertex;
  395.         org.drip.xva.derivative.EvolutionTrajectoryEdge[] evolutionTrajectoryEdgeArray = 1 >= vertexCount ?
  396.             null : new org.drip.xva.derivative.EvolutionTrajectoryEdge[vertexCount - 1];

  397.         if (0 == vertexCount)
  398.         {
  399.             return null;
  400.         }

  401.         for (int i = vertexCount - 2; i >= 0; --i)
  402.         {
  403.             try
  404.             {
  405.                 if (null == (evolutionTrajectoryEdgeArray[i] = eulerWalk (
  406.                     new org.drip.exposure.universe.MarketEdge (
  407.                         marketVertexArray[i],
  408.                         marketVertexArray[i + 1]
  409.                     ),
  410.                     burgardKjaerOperator,
  411.                     trajectoryVertex,
  412.                     collateral)))
  413.                 {
  414.                     return null;
  415.                 }
  416.             }
  417.             catch (java.lang.Exception e)
  418.             {
  419.                 e.printStackTrace();
  420.             }

  421.             trajectoryVertex = evolutionTrajectoryEdgeArray[i].vertexFinish();
  422.         }

  423.         return evolutionTrajectoryEdgeArray;
  424.     }
  425. }