EfronSteinMetrics.java

  1. package org.drip.sequence.functional;

  2. /*
  3.  * -*- mode: java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  4.  */

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

  66. /**
  67.  * <i>EfronSteinMetrics</i> contains the Variance-based non-exponential Sample Distribution/Bounding Metrics
  68.  * and Agnostic Bounds related to the Functional Transformation of the specified Sequence.
  69.  *
  70.  * <br><br>
  71.  *  <ul>
  72.  *      <li><b>Module </b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/NumericalCore.md">Numerical Core Module</a></li>
  73.  *      <li><b>Library</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/StatisticalLearningLibrary.md">Statistical Learning Library</a></li>
  74.  *      <li><b>Project</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/sequence">Sequence</a></li>
  75.  *      <li><b>Package</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/sequence/functional">Functional</a></li>
  76.  *  </ul>
  77.  * <br><br>
  78.  *
  79.  * @author Lakshmi Krishnamurthy
  80.  */

  81. public class EfronSteinMetrics {
  82.     private org.drip.sequence.functional.MultivariateRandom _func = null;
  83.     private org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[] _aSSAM = null;

  84.     private double[] demotedSequence (
  85.         final double[] adblSequence,
  86.         final int iDemoteIndex)
  87.     {
  88.         int iSequenceLength = adblSequence.length;
  89.         double[] adblDemotedSequence = new double[iSequenceLength - 1];

  90.         for (int i = 0; i < iSequenceLength; ++i) {
  91.             if (i < iDemoteIndex)
  92.                 adblDemotedSequence[i] = adblSequence[i];
  93.             else if (i > iDemoteIndex)
  94.                 adblDemotedSequence[i - 1] = adblSequence[i];
  95.         }

  96.         return adblDemotedSequence;
  97.     }

  98.     /**
  99.      * EfronSteinMetrics Constructor
  100.      *
  101.      * @param func Multivariate Objective Function
  102.      * @param aSSAM Array of the individual Single Sequence Metrics
  103.      *
  104.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  105.      */

  106.     public EfronSteinMetrics (
  107.         final org.drip.sequence.functional.MultivariateRandom func,
  108.         final org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[] aSSAM)
  109.         throws java.lang.Exception
  110.     {
  111.         if (null == (_func = func) || null == (_aSSAM = aSSAM))
  112.             throw new java.lang.Exception ("EfronSteinMetrics ctr: Invalid Inputs");

  113.         int iNumVariable = _aSSAM.length;

  114.         if (0 == iNumVariable)
  115.             throw new java.lang.Exception ("EfronSteinMetrics ctr: Invalid Inputs");

  116.         int iSequenceLength = _aSSAM[0].sequence().length;

  117.         for (int i = 1; i < iNumVariable; ++i) {
  118.             if (null == _aSSAM[i] || _aSSAM[i].sequence().length != iSequenceLength)
  119.                 throw new java.lang.Exception ("EfronSteinMetrics ctr: Invalid Inputs");
  120.         }
  121.     }

  122.     /**
  123.      * Retrieve the Multivariate Objective Function
  124.      *
  125.      * @return The Multivariate Objective Function Instance
  126.      */

  127.     public org.drip.function.definition.RdToR1 function()
  128.     {
  129.         return _func;
  130.     }

  131.     /**
  132.      * Retrieve the Array of the Single Sequence Agnostic Metrics
  133.      *
  134.      * @return The Array of the Single Sequence Agnostic Metrics
  135.      */

  136.     public org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[] sequenceMetrics()
  137.     {
  138.         return _aSSAM;
  139.     }

  140.     /**
  141.      * Extract the Full Variate Array Sequence
  142.      *
  143.      * @param aSSAM Array of the individual Single Sequence Metrics
  144.      *
  145.      * @return The Full Variate Array Sequence
  146.      */

  147.     public double[][] variateSequence (
  148.         final org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[] aSSAM)
  149.     {
  150.         int iNumVariate = _aSSAM.length;

  151.         if (null == aSSAM || aSSAM.length != iNumVariate) return null;

  152.         int iSequenceSize = aSSAM[0].sequence().length;

  153.         double[][] aadblVariateSequence = new double[iSequenceSize][iNumVariate];

  154.         for (int iVariateIndex = 0; iVariateIndex < iNumVariate; ++iVariateIndex) {
  155.             double[] adblVariate = aSSAM[iVariateIndex].sequence();

  156.             for (int iSequenceIndex = 0; iSequenceIndex < iSequenceSize; ++iSequenceIndex)
  157.                 aadblVariateSequence[iSequenceIndex][iVariateIndex] = adblVariate[iSequenceIndex];
  158.         }

  159.         return aadblVariateSequence;
  160.     }

  161.     /**
  162.      * Compute the Function Sequence Agnostic Metrics associated with the Variance of each Variate
  163.      *
  164.      * @return The Array of the Associated Sequence Metrics
  165.      */

  166.     public org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[] variateFunctionVarianceMetrics()
  167.     {
  168.         int iNumVariate = _aSSAM.length;
  169.         org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[] aSSAM = new
  170.             org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[iNumVariate];

  171.         for (int i = 0; i < iNumVariate; ++i) {
  172.             if (null == (aSSAM[i] = _func.unconditionalTargetVariateMetrics (_aSSAM, i))) return null;
  173.         }

  174.         return aSSAM;
  175.     }

  176.     /**
  177.      * Compute the Function Sequence Agnostic Metrics associated with the Variance of each Variate Using the
  178.      *  Supplied Ghost Variate Sequence
  179.      *
  180.      * @param aSSAMGhost Array of the Ghost Single Sequence Metrics
  181.      *
  182.      * @return The Array of the Associated Sequence Metrics
  183.      */

  184.     public org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[] ghostVariateVarianceMetrics (
  185.         final org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[] aSSAMGhost)
  186.     {
  187.         if (null == aSSAMGhost) return null;

  188.         int iNumVariate = _aSSAM.length;
  189.         org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[] aSSAM = new
  190.             org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[iNumVariate];

  191.         for (int i = 0; i < iNumVariate; ++i) {
  192.             if (null == aSSAMGhost[i] || null == (aSSAM[i] = _func.ghostTargetVariateMetrics (_aSSAM, i,
  193.                 aSSAMGhost[i].sequence())))
  194.                 return null;
  195.         }

  196.         return aSSAM;
  197.     }

  198.     /**
  199.      * Compute the Function Sequence Agnostic Metrics associated with each Variate using the specified Ghost
  200.      *  Symmetric Variable Copy
  201.      *
  202.      * @param aSSAMGhost Array of the Ghost Single Sequence Metrics
  203.      *
  204.      * @return The Array of the Associated Sequence Metrics
  205.      */

  206.     public org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[] symmetrizedDifferenceSequenceMetrics (
  207.         final org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[] aSSAMGhost)
  208.     {
  209.         double[][] aadblSequenceVariate = variateSequence (_aSSAM);

  210.         double[][] aadblGhostSequenceVariate = variateSequence (aSSAMGhost);

  211.         if (null == aadblGhostSequenceVariate || aadblSequenceVariate.length !=
  212.             aadblGhostSequenceVariate.length || aadblSequenceVariate[0].length !=
  213.                 aadblGhostSequenceVariate[0].length)
  214.             return null;

  215.         int iSequenceSize = _aSSAM[0].sequence().length;

  216.         int iNumVariate = _aSSAM.length;
  217.         org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[] aSSAMFunction = new
  218.             org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[iNumVariate];

  219.         try {
  220.             for (int iVariateIndex = 0; iVariateIndex < iNumVariate; ++iVariateIndex) {
  221.                 double[] adblSymmetrizedFunctionDifference = new double[iSequenceSize];

  222.                 for (int iSequenceIndex = 0; iSequenceIndex < iSequenceSize; ++iSequenceIndex) {
  223.                     double[] adblVariate = aadblSequenceVariate[iSequenceIndex];

  224.                     adblSymmetrizedFunctionDifference[iSequenceIndex] = _func.evaluate (adblVariate);

  225.                     double dblVariateOrig = adblVariate[iVariateIndex];
  226.                     adblVariate[iVariateIndex] = aadblGhostSequenceVariate[iSequenceIndex][iVariateIndex];

  227.                     adblSymmetrizedFunctionDifference[iSequenceIndex] -= _func.evaluate (adblVariate);

  228.                     adblVariate[iVariateIndex] = dblVariateOrig;
  229.                 }

  230.                 aSSAMFunction[iVariateIndex] = new org.drip.sequence.metrics.SingleSequenceAgnosticMetrics
  231.                     (adblSymmetrizedFunctionDifference, null);
  232.             }

  233.             return aSSAMFunction;
  234.         } catch (java.lang.Exception e) {
  235.             e.printStackTrace();
  236.         }

  237.         return null;
  238.     }

  239.     /**
  240.      * Compute the Function Sequence Agnostic Metrics associated with each Variate around the Pivot Point
  241.      *  provided by the Pivot Function
  242.      *
  243.      * @param funcPivot The Pivot Function
  244.      *
  245.      * @return The Array of the Associated Sequence Metrics
  246.      */

  247.     public org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[] pivotedDifferenceSequenceMetrics (
  248.         final org.drip.sequence.functional.MultivariateRandom funcPivot)
  249.     {
  250.         if (null == funcPivot) return null;

  251.         double[][] aadblSequenceVariate = variateSequence (_aSSAM);

  252.         int iSequenceSize = _aSSAM[0].sequence().length;

  253.         int iNumVariate = _aSSAM.length;
  254.         org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[] aSSAMFunction = new
  255.             org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[iNumVariate];

  256.         try {
  257.             for (int iVariateIndex = 0; iVariateIndex < iNumVariate; ++iVariateIndex) {
  258.                 double[] adblSymmetrizedFunctionDifference = new double[iSequenceSize];

  259.                 for (int iSequenceIndex = 0; iSequenceIndex < iSequenceSize; ++iSequenceIndex) {
  260.                     double[] adblVariate = aadblSequenceVariate[iSequenceIndex];

  261.                     adblSymmetrizedFunctionDifference[iSequenceIndex] = _func.evaluate (adblVariate) -
  262.                         funcPivot.evaluate (demotedSequence (adblVariate, iVariateIndex));
  263.                 }

  264.                 aSSAMFunction[iVariateIndex] = new org.drip.sequence.metrics.SingleSequenceAgnosticMetrics
  265.                     (adblSymmetrizedFunctionDifference, null);
  266.             }

  267.             return aSSAMFunction;
  268.         } catch (java.lang.Exception e) {
  269.             e.printStackTrace();
  270.         }

  271.         return null;
  272.     }

  273.     /**
  274.      * Compute the Multivariate Variance Upper Bound using the Martingale Differences Method
  275.      *
  276.      * @return The Multivariate Variance Upper Bound using the Martingale Differences Method
  277.      *
  278.      * @throws java.lang.Exception Thrown if the Upper Bound cannot be calculated
  279.      */

  280.     public double martingaleVarianceUpperBound()
  281.         throws java.lang.Exception
  282.     {
  283.         int iNumVariate = _aSSAM.length;
  284.         double dblVarianceUpperBound = 0.;

  285.         org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[] aSSAM = variateFunctionVarianceMetrics();

  286.         if (null == aSSAM || iNumVariate != aSSAM.length)
  287.             throw new java.lang.Exception
  288.                 ("EfronSteinMetrics::martingaleVarianceUpperBound => Cannot compute Univariate Variance Metrics");

  289.         for (int i = 0; i < iNumVariate; ++i)
  290.             dblVarianceUpperBound += aSSAM[i].empiricalExpectation();

  291.         return dblVarianceUpperBound;
  292.     }

  293.     /**
  294.      * Compute the Variance Upper Bound using the Ghost Variables
  295.      *
  296.      * @param aSSAMGhost Array of the Ghost Single Sequence Metrics
  297.      *
  298.      * @return The Variance Upper Bound using the Ghost Variables
  299.      *
  300.      * @throws java.lang.Exception Thrown if the Upper Bound cannot be calculated
  301.      */

  302.     public double ghostVarianceUpperBound (
  303.         final org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[] aSSAMGhost)
  304.         throws java.lang.Exception
  305.     {
  306.         int iNumVariate = _aSSAM.length;
  307.         double dblVarianceUpperBound = 0.;

  308.         org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[] aSSAM = ghostVariateVarianceMetrics
  309.             (aSSAMGhost);

  310.         if (null == aSSAM || iNumVariate != aSSAM.length)
  311.             throw new java.lang.Exception
  312.                 ("EfronSteinMetrics::ghostVarianceUpperBound => Cannot compute Target Ghost Variance Metrics");

  313.         for (int i = 0; i < iNumVariate; ++i)
  314.             dblVarianceUpperBound += aSSAM[i].empiricalExpectation();

  315.         return dblVarianceUpperBound;
  316.     }

  317.     /**
  318.      * Compute the Efron-Stein-Steele Variance Upper Bound using the Ghost Variables
  319.      *
  320.      * @param aSSAMGhost Array of the Ghost Single Sequence Metrics
  321.      *
  322.      * @return The Efron-Stein-Steele Variance Upper Bound using the Ghost Variables
  323.      *
  324.      * @throws java.lang.Exception Thrown if the Upper Bound cannot be calculated
  325.      */

  326.     public double efronSteinSteeleBound (
  327.         final org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[] aSSAMGhost)
  328.         throws java.lang.Exception
  329.     {
  330.         int iNumVariate = _aSSAM.length;
  331.         double dblVarianceUpperBound = 0.;

  332.         org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[] aSSAM =
  333.             symmetrizedDifferenceSequenceMetrics (aSSAMGhost);

  334.         if (null == aSSAM || iNumVariate != aSSAM.length)
  335.             throw new java.lang.Exception
  336.                 ("EfronSteinMetrics::efronSteinSteeleBound => Cannot compute Symmetrized Difference Metrics");

  337.         for (int i = 0; i < iNumVariate; ++i)
  338.             dblVarianceUpperBound += aSSAM[i].empiricalRawMoment (2, false);

  339.         return 0.5 * dblVarianceUpperBound;
  340.     }

  341.     /**
  342.      * Compute the Function Variance Upper Bound using the supplied Multivariate Pivoting Function
  343.      *
  344.      * @param funcPivot The Custom Multivariate Pivoting Function
  345.      *
  346.      * @return The Function Variance Upper Bound using the supplied Multivariate Pivot Function
  347.      *
  348.      * @throws java.lang.Exception Thrown if the Variance Upper Bound cannot be calculated
  349.      */

  350.     public double pivotVarianceUpperBound (
  351.         final org.drip.sequence.functional.MultivariateRandom funcPivot)
  352.         throws java.lang.Exception
  353.     {
  354.         int iNumVariate = _aSSAM.length;
  355.         double dblVarianceUpperBound = 0.;

  356.         org.drip.sequence.metrics.SingleSequenceAgnosticMetrics[] aSSAM = pivotedDifferenceSequenceMetrics
  357.             (funcPivot);

  358.         if (null == aSSAM || iNumVariate != aSSAM.length)
  359.             throw new java.lang.Exception
  360.                 ("EfronSteinMetrics::pivotVarianceUpperBound => Cannot compute Pivoted Difference Metrics");

  361.         for (int i = 0; i < iNumVariate; ++i)
  362.             dblVarianceUpperBound += aSSAM[i].empiricalRawMoment (2, false);

  363.         return 0.5 * dblVarianceUpperBound;
  364.     }

  365.     /**
  366.      * Compute the Multivariate Variance Upper Bound using the Bounded Differences Support
  367.      *
  368.      * @return The Multivariate Variance Upper Bound using the Bounded Differences Support
  369.      *
  370.      * @throws java.lang.Exception Thrown if the Upper Bound cannot be calculated
  371.      */

  372.     public double boundedVarianceUpperBound()
  373.         throws java.lang.Exception
  374.     {
  375.         if (!(_func instanceof org.drip.sequence.functional.BoundedMultivariateRandom))
  376.             throw new java.lang.Exception
  377.                 ("EfronSteinMetrics::boundedVarianceUpperBound => Invalid Bounded Metrics");

  378.         int iNumVariate = _aSSAM.length;
  379.         double dblVarianceUpperBound = 0.;
  380.         org.drip.sequence.functional.BoundedMultivariateRandom boundedFunc =
  381.             (org.drip.sequence.functional.BoundedMultivariateRandom) _func;

  382.         for (int i = 0; i < iNumVariate; ++i)
  383.             dblVarianceUpperBound += boundedFunc.targetVariateVarianceBound (i);

  384.         return 0.5 * dblVarianceUpperBound;
  385.     }

  386.     /**
  387.      * Compute the Multivariate Variance Upper Bound using the Separable Variance Bound
  388.      *
  389.      * @return The Multivariate Variance Upper Bound using the Separable Variance Bound
  390.      *
  391.      * @throws java.lang.Exception Thrown if the Upper Bound cannot be calculated
  392.      */

  393.     public double separableVarianceUpperBound()
  394.         throws java.lang.Exception
  395.     {
  396.         if (!(_func instanceof org.drip.sequence.functional.SeparableMultivariateRandom))
  397.             throw new java.lang.Exception
  398.                 ("EfronSteinMetrics::separableVarianceUpperBound => Invalid Bounded Metrics");

  399.         int iNumVariate = _aSSAM.length;
  400.         double dblVarianceUpperBound = 0.;
  401.         org.drip.sequence.functional.SeparableMultivariateRandom separableFunc =
  402.             (org.drip.sequence.functional.SeparableMultivariateRandom) _func;

  403.         for (int i = 0; i < iNumVariate; ++i)
  404.             dblVarianceUpperBound += separableFunc.targetVariateVariance (i);

  405.         return 0.5 * dblVarianceUpperBound;
  406.     }
  407. }