CapitalSegmentPnLAttribution.java

  1. package org.drip.capital.explain;

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

  74. /**
  75.  * <i>CapitalSegmentPnLAttribution</i> holds the Scenario-Level Cumulative Capital Attributions from the
  76.  *  Contributing Paths of the Stand-alone Capital Units corresponding to a Capital Segment. The References
  77.  *  are:
  78.  *
  79.  * <br><br>
  80.  *  <ul>
  81.  *      <li>
  82.  *          Bank for International Supervision (2005): Stress Testing at Major Financial Institutions: Survey
  83.  *              Results and Practice https://www.bis.org/publ/cgfs24.htm
  84.  *      </li>
  85.  *      <li>
  86.  *          Glasserman, P. (2004): <i>Monte Carlo Methods in Financial Engineering</i> <b>Springer</b>
  87.  *      </li>
  88.  *      <li>
  89.  *          Kupiec, P. H. (2000): Stress Tests and Risk Capital <i>Risk</i> <b>2 (4)</b> 27-39
  90.  *      </li>
  91.  *  </ul>
  92.  *
  93.  *  <br><br>
  94.  *  <ul>
  95.  *      <li><b>Module </b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/PortfolioCore.md">Portfolio Core Module</a></li>
  96.  *      <li><b>Library</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/CapitalAnalyticsLibrary.md">Capital Analytics</a></li>
  97.  *      <li><b>Project</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/capital/README.md">Basel Market Risk and Operational Capital</a></li>
  98.  *      <li><b>Package</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/capital/explain/README.md">Economic Risk Capital Attribution Explain</a></li>
  99.  *  </ul>
  100.  *
  101.  * @author Lakshmi Krishnamurthy
  102.  */

  103. public class CapitalSegmentPnLAttribution
  104.     extends org.drip.capital.explain.PnLAttribution
  105. {
  106.     private int _pathCount = -1;
  107.     private java.util.List<java.lang.Integer> _pathIndexList = null;

  108.     private boolean updateFSDecompositionExplainMap (
  109.         final java.util.Map<java.lang.String, java.lang.Double> unitFSPnLDecompositionExplainMap)
  110.     {
  111.         if (null == unitFSPnLDecompositionExplainMap)
  112.         {
  113.             return true;
  114.         }

  115.         if (null == _fsPnLDecompositionExplainMap)
  116.         {
  117.             _fsPnLDecompositionExplainMap = new
  118.                 org.drip.analytics.support.CaseInsensitiveHashMap<java.lang.Double>();
  119.         }

  120.         for (java.util.Map.Entry<java.lang.String, java.lang.Double> fsPnLDecompositionExplainEntry :
  121.             unitFSPnLDecompositionExplainMap.entrySet())
  122.         {
  123.             java.lang.String fsType = fsPnLDecompositionExplainEntry.getKey();

  124.             if (_fsPnLDecompositionExplainMap.containsKey (
  125.                 fsType
  126.             ))
  127.             {
  128.                 _fsPnLDecompositionExplainMap.put (
  129.                     fsType,
  130.                     _fsPnLDecompositionExplainMap.get (
  131.                         fsType
  132.                     ) + fsPnLDecompositionExplainEntry.getValue()
  133.                 );
  134.             }
  135.             else
  136.             {
  137.                 _fsPnLDecompositionExplainMap.put (
  138.                     fsType,
  139.                     fsPnLDecompositionExplainEntry.getValue()
  140.                 );
  141.             }
  142.         }

  143.         return true;
  144.     }

  145.     private boolean updateSystemicEventNamePnLExplainMap (
  146.         final java.util.Map<java.lang.String, java.lang.Double> unitSystemicPnLExplainMap)
  147.     {
  148.         if (null == unitSystemicPnLExplainMap)
  149.         {
  150.             return true;
  151.         }

  152.         if (null == _systemicPnLExplainMap)
  153.         {
  154.             _systemicPnLExplainMap = new
  155.                 org.drip.analytics.support.CaseInsensitiveHashMap<java.lang.Double>();
  156.         }

  157.         for (java.util.Map.Entry<java.lang.String, java.lang.Double> systemicExplainEntry :
  158.             unitSystemicPnLExplainMap.entrySet())
  159.         {
  160.             java.lang.String systemicEventName = systemicExplainEntry.getKey();

  161.             if (_systemicPnLExplainMap.containsKey (
  162.                 systemicEventName
  163.             ))
  164.             {
  165.                 _systemicPnLExplainMap.put (
  166.                     systemicEventName,
  167.                     _systemicPnLExplainMap.get (
  168.                         systemicEventName
  169.                     ) + systemicExplainEntry.getValue()
  170.                 );
  171.             }
  172.             else
  173.             {
  174.                 _systemicPnLExplainMap.put (
  175.                     systemicEventName,
  176.                     systemicExplainEntry.getValue()
  177.                 );
  178.             }
  179.         }

  180.         return true;
  181.     }

  182.     private boolean updateSystemicGrossPnLExplainMap (
  183.         final java.util.Map<java.lang.String, java.lang.Double> unitSystemicGrossPnLExplainMap)
  184.     {
  185.         if (null == unitSystemicGrossPnLExplainMap)
  186.         {
  187.             return true;
  188.         }

  189.         if (null == _systemicGrossPnLExplainMap)
  190.         {
  191.             _systemicGrossPnLExplainMap = new
  192.                 org.drip.analytics.support.CaseInsensitiveHashMap<java.lang.Double>();
  193.         }

  194.         for (java.util.Map.Entry<java.lang.String, java.lang.Double> systemicGrossExplainEntry :
  195.             unitSystemicGrossPnLExplainMap.entrySet())
  196.         {
  197.             java.lang.String systemicEventName = systemicGrossExplainEntry.getKey();

  198.             if (_systemicGrossPnLExplainMap.containsKey (
  199.                 systemicEventName
  200.             ))
  201.             {
  202.                 _systemicGrossPnLExplainMap.put (
  203.                     systemicEventName,
  204.                     _systemicGrossPnLExplainMap.get (
  205.                         systemicEventName
  206.                     ) + systemicGrossExplainEntry.getValue()
  207.                 );
  208.             }
  209.             else
  210.             {
  211.                 _systemicGrossPnLExplainMap.put (
  212.                     systemicEventName,
  213.                     systemicGrossExplainEntry.getValue()
  214.                 );
  215.             }
  216.         }

  217.         return true;
  218.     }

  219.     private boolean updateSystemicInstanceCountMap (
  220.         final java.util.Map<java.lang.String, java.lang.Integer> unitSystemicInstanceCountMap)
  221.     {
  222.         if (null == unitSystemicInstanceCountMap)
  223.         {
  224.             return true;
  225.         }

  226.         if (null == _systemicInstanceCountMap)
  227.         {
  228.             _systemicInstanceCountMap = new
  229.                 org.drip.analytics.support.CaseInsensitiveHashMap<java.lang.Integer>();
  230.         }

  231.         for (java.util.Map.Entry<java.lang.String, java.lang.Integer> systemicInstanceCountEntry :
  232.             unitSystemicInstanceCountMap.entrySet())
  233.         {
  234.             java.lang.String systemicEventName = systemicInstanceCountEntry.getKey();

  235.             if (_systemicInstanceCountMap.containsKey (
  236.                 systemicEventName
  237.             ))
  238.             {
  239.                 _systemicInstanceCountMap.put (
  240.                     systemicEventName,
  241.                     _systemicInstanceCountMap.get (
  242.                         systemicEventName
  243.                     ) + systemicInstanceCountEntry.getValue()
  244.                 );
  245.             }
  246.             else
  247.             {
  248.                 _systemicInstanceCountMap.put (
  249.                     systemicEventName,
  250.                     systemicInstanceCountEntry.getValue()
  251.                 );
  252.             }
  253.         }

  254.         return true;
  255.     }

  256.     private boolean updateCorrelatedPnLExplainMap (
  257.         final java.util.Map<java.lang.String, java.lang.Double> unitCorrelatedPnLExplainMap)
  258.     {
  259.         if (null == unitCorrelatedPnLExplainMap)
  260.         {
  261.             return true;
  262.         }

  263.         if (null == _correlatedPnLExplainMap)
  264.         {
  265.             _correlatedPnLExplainMap = new
  266.                 org.drip.analytics.support.CaseInsensitiveHashMap<java.lang.Double>();
  267.         }

  268.         for (java.util.Map.Entry<java.lang.String, java.lang.Double> correlatedExplainEntry :
  269.             unitCorrelatedPnLExplainMap.entrySet())
  270.         {
  271.             java.lang.String correlatedEventName = correlatedExplainEntry.getKey();

  272.             if (_correlatedPnLExplainMap.containsKey (
  273.                 correlatedEventName
  274.             ))
  275.             {
  276.                 _correlatedPnLExplainMap.put (
  277.                     correlatedEventName,
  278.                     _correlatedPnLExplainMap.get (
  279.                         correlatedEventName
  280.                     ) + correlatedExplainEntry.getValue()
  281.                 );
  282.             }
  283.             else
  284.             {
  285.                 _correlatedPnLExplainMap.put (
  286.                     correlatedEventName,
  287.                     correlatedExplainEntry.getValue()
  288.                 );
  289.             }
  290.         }

  291.         return true;
  292.     }

  293.     private boolean updateCorrelatedInstanceCountMap (
  294.         final java.util.Map<java.lang.String, java.lang.Integer> unitCorrelatedInstanceCountMap)
  295.     {
  296.         if (null == unitCorrelatedInstanceCountMap)
  297.         {
  298.             return true;
  299.         }

  300.         if (null == _correlatedInstanceCountMap)
  301.         {
  302.             _correlatedInstanceCountMap = new
  303.                 org.drip.analytics.support.CaseInsensitiveHashMap<java.lang.Integer>();
  304.         }

  305.         for (java.util.Map.Entry<java.lang.String, java.lang.Integer> correlatedInstanceCountEntry :
  306.             unitCorrelatedInstanceCountMap.entrySet())
  307.         {
  308.             java.lang.String correlatedEventName = correlatedInstanceCountEntry.getKey();

  309.             if (_correlatedInstanceCountMap.containsKey (
  310.                 correlatedEventName
  311.             ))
  312.             {
  313.                 _correlatedInstanceCountMap.put (
  314.                     correlatedEventName,
  315.                     _correlatedInstanceCountMap.get (
  316.                         correlatedEventName
  317.                     ) + correlatedInstanceCountEntry.getValue()
  318.                 );
  319.             }
  320.             else
  321.             {
  322.                 _correlatedInstanceCountMap.put (
  323.                     correlatedEventName,
  324.                     correlatedInstanceCountEntry.getValue()
  325.                 );
  326.             }
  327.         }

  328.         return true;
  329.     }

  330.     private boolean updateIdiosyncraticPnLExplainMap (
  331.         final java.util.Map<java.lang.String, java.lang.Double> unitIdiosyncraticPnLExplainMap)
  332.     {
  333.         if (null == unitIdiosyncraticPnLExplainMap)
  334.         {
  335.             return true;
  336.         }

  337.         if (null == _idiosyncraticPnLExplainMap)
  338.         {
  339.             _idiosyncraticPnLExplainMap = new
  340.                 org.drip.analytics.support.CaseInsensitiveHashMap<java.lang.Double>();
  341.         }

  342.         for (java.util.Map.Entry<java.lang.String, java.lang.Double> idiosyncraticExplainEntry :
  343.             unitIdiosyncraticPnLExplainMap.entrySet())
  344.         {
  345.             java.lang.String idiosyncraticEventName = idiosyncraticExplainEntry.getKey();

  346.             if (_idiosyncraticPnLExplainMap.containsKey (
  347.                 idiosyncraticEventName
  348.             ))
  349.             {
  350.                 _idiosyncraticPnLExplainMap.put (
  351.                     idiosyncraticEventName,
  352.                     _idiosyncraticPnLExplainMap.get (
  353.                         idiosyncraticEventName
  354.                     ) + idiosyncraticExplainEntry.getValue()
  355.                 );
  356.             }
  357.             else
  358.             {
  359.                 _idiosyncraticPnLExplainMap.put (
  360.                     idiosyncraticEventName,
  361.                     idiosyncraticExplainEntry.getValue()
  362.                 );
  363.             }
  364.         }

  365.         return true;
  366.     }

  367.     private boolean updateIdiosyncraticInstanceCountMap (
  368.         final java.util.Map<java.lang.String, java.lang.Integer> unitIdiosyncraticInstanceCountMap)
  369.     {
  370.         if (null == unitIdiosyncraticInstanceCountMap)
  371.         {
  372.             return true;
  373.         }

  374.         if (null == _idiosyncraticInstanceCountMap)
  375.         {
  376.             _idiosyncraticInstanceCountMap = new
  377.                 org.drip.analytics.support.CaseInsensitiveHashMap<java.lang.Integer>();
  378.         }

  379.         for (java.util.Map.Entry<java.lang.String, java.lang.Integer> idiosyncraticInstanceCountEntry :
  380.             unitIdiosyncraticInstanceCountMap.entrySet())
  381.         {
  382.             java.lang.String idiosyncraticEventName = idiosyncraticInstanceCountEntry.getKey();

  383.             if (_idiosyncraticInstanceCountMap.containsKey (
  384.                 idiosyncraticEventName
  385.             ))
  386.             {
  387.                 _idiosyncraticInstanceCountMap.put (
  388.                     idiosyncraticEventName,
  389.                     _idiosyncraticInstanceCountMap.get (
  390.                         idiosyncraticEventName
  391.                     ) + idiosyncraticInstanceCountEntry.getValue()
  392.                 );
  393.             }
  394.             else
  395.             {
  396.                 _idiosyncraticInstanceCountMap.put (
  397.                     idiosyncraticEventName,
  398.                     idiosyncraticInstanceCountEntry.getValue()
  399.                 );
  400.             }
  401.         }

  402.         return true;
  403.     }

  404.     private boolean accumulateUnitAttribution (
  405.         final org.drip.capital.explain.PnLAttribution pnlAttribution)
  406.     {
  407.         if (!updateFSDecompositionExplainMap (
  408.             pnlAttribution.fsPnLDecompositionExplainMap()
  409.         ))
  410.         {
  411.             return false;
  412.         }

  413.         if (!updateSystemicEventNamePnLExplainMap (
  414.             pnlAttribution.systemicPnLExplainMap()
  415.         ))
  416.         {
  417.             return false;
  418.         }

  419.         if (!updateSystemicGrossPnLExplainMap (
  420.             pnlAttribution.systemicGrossPnLExplainMap()
  421.         ))
  422.         {
  423.             return false;
  424.         }

  425.         if (!updateSystemicInstanceCountMap (
  426.             pnlAttribution.systemicInstanceCountMap()
  427.         ))
  428.         {
  429.             return false;
  430.         }

  431.         if (!updateCorrelatedPnLExplainMap (
  432.             pnlAttribution.correlatedPnLExplainMap()
  433.         ))
  434.         {
  435.             return false;
  436.         }

  437.         if (!updateCorrelatedInstanceCountMap (
  438.             pnlAttribution.correlatedInstanceCountMap()
  439.         ))
  440.         {
  441.             return false;
  442.         }

  443.         if (!updateIdiosyncraticPnLExplainMap (
  444.             pnlAttribution.idiosyncraticPnLExplainMap()
  445.         ))
  446.         {
  447.             return false;
  448.         }

  449.         if (!updateIdiosyncraticInstanceCountMap (
  450.             pnlAttribution.idiosyncraticInstanceCountMap()
  451.         ))
  452.         {
  453.             return false;
  454.         }

  455.         return true;
  456.     }

  457.     /**
  458.      * CapitalSegmentPnLAttribution Constructor
  459.      *
  460.      * @param pnlAttributionArray Array of PnL Attributions
  461.      *
  462.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  463.      */

  464.     public CapitalSegmentPnLAttribution (
  465.         final org.drip.capital.explain.PnLAttribution[] pnlAttributionArray)
  466.         throws java.lang.Exception
  467.     {
  468.         if (null == pnlAttributionArray)
  469.         {
  470.             throw new java.lang.Exception (
  471.                 "CapitalSegmentPnLAttribution Constructor => Invalid Inputs"
  472.             );
  473.         }

  474.         int capitalUnitCount = pnlAttributionArray.length;

  475.         if (0 >= capitalUnitCount)
  476.         {
  477.             throw new java.lang.Exception (
  478.                 "CapitalSegmentPnLAttribution Constructor => Invalid Inputs"
  479.             );
  480.         }

  481.         _var = 0.;
  482.         _expectedShortfall = 0.;

  483.         _pathCount = pnlAttributionArray[0].pathCount();

  484.         for (int capitalUnitIndex = 0; capitalUnitIndex < capitalUnitCount; ++capitalUnitIndex)
  485.         {
  486.             if (null == pnlAttributionArray[capitalUnitIndex])
  487.             {
  488.                 throw new java.lang.Exception (
  489.                     "CapitalSegmentPnLAttribution Constructor => Invalid Inputs"
  490.                 );
  491.             }

  492.             _var = _var + pnlAttributionArray[capitalUnitIndex].var();

  493.             _expectedShortfall = _expectedShortfall +
  494.                 pnlAttributionArray[capitalUnitIndex].expectedShortfall();

  495.             if (!accumulateUnitAttribution (
  496.                 pnlAttributionArray[capitalUnitIndex]
  497.             ))
  498.             {
  499.                 throw new java.lang.Exception (
  500.                     "CapitalSegmentPnLAttribution Constructor => Invalid Inputs"
  501.                 );
  502.             }
  503.         }

  504.         _pathIndexList = pnlAttributionArray[0].pathIndexList();
  505.     }

  506.     @Override public java.util.List<java.lang.Integer> pathIndexList()
  507.     {
  508.         return _pathIndexList;
  509.     }

  510.     @Override public int pathCount()
  511.     {
  512.         return _pathCount;
  513.     }
  514. }