BlackLittermanCombinationEngine.java

  1. package org.drip.portfolioconstruction.bayesian;

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

  77. /**
  78.  * <i>BlackLittermanCombinationEngine</i> implements the Engine that generates the Combined/Posterior
  79.  * Distributions from the Prior and the Conditional Joint R<sup>1</sup> Multivariate Normal Distributions.
  80.  * The References are:
  81.  *  
  82.  *  <br><br>
  83.  *      <ul>
  84.  *          <li>
  85.  *              He. G., and R. Litterman (1999): <i>The Intuition behind the Black-Litterman Model
  86.  *                  Portfolios</i> <b>Goldman Sachs Asset Management</b>
  87.  *          </li>
  88.  *          <li>
  89.  *              Idzorek, T. (2005): <i>A Step-by-Step Guide to the Black-Litterman Model: Incorporating
  90.  *                  User-Specified Confidence Levels</i> <b>Ibbotson Associates</b> Chicago, IL
  91.  *          </li>
  92.  *      </ul>
  93.  *
  94.  *  <br><br>
  95.  *  <ul>
  96.  *      <li><b>Module </b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/PortfolioCore.md">Portfolio Core Module</a></li>
  97.  *      <li><b>Library</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/AssetAllocationAnalyticsLibrary.md">Asset Allocation Analytics</a></li>
  98.  *      <li><b>Project</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/portfolioconstruction/README.md">Portfolio Construction under Allocation Constraints</a></li>
  99.  *      <li><b>Package</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/portfolioconstruction/bayesian/README.md">Black Litterman Bayesian Portfolio Construction</a></li>
  100.  *  </ul>
  101.  *
  102.  * @author Lakshmi Krishnamurthy
  103.  */

  104. public class BlackLittermanCombinationEngine
  105. {
  106.     private org.drip.portfolioconstruction.bayesian.ProjectionSpecification _projectionSpecification = null;
  107.     private org.drip.portfolioconstruction.bayesian.PriorControlSpecification _priorControlSpecification =
  108.         null;
  109.     private org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation
  110.         _forwardReverseOptimizationOutputUnadjusted = null;

  111.     private org.drip.measure.bayesian.ScopingProjectionVariateDistribution
  112.         scopingProjectionVariateDistribution()
  113.     {
  114.         double[][] assetExcessReturnsCovarianceMatrix =
  115.             _forwardReverseOptimizationOutputUnadjusted.assetExcessReturnsCovarianceMatrix();

  116.         double[] priorExpectedAssetReturnsArray =
  117.             _forwardReverseOptimizationOutputUnadjusted.expectedAssetExcessReturnsArray();

  118.         int assetCount = assetExcessReturnsCovarianceMatrix.length;
  119.         double[][] priorCovarianceMatrix = new double[assetCount][assetCount];

  120.         double riskFreeRate = _priorControlSpecification.riskFreeRate();

  121.         double tau = _priorControlSpecification.tau();

  122.         for (int assetIndexI = 0; assetIndexI < assetCount; ++assetIndexI)
  123.         {
  124.             priorExpectedAssetReturnsArray[assetIndexI] = priorExpectedAssetReturnsArray[assetIndexI] +
  125.                 riskFreeRate;

  126.             for (int assetIndexJ = 0; assetIndexJ < assetCount; ++assetIndexJ)
  127.             {
  128.                 priorCovarianceMatrix[assetIndexI][assetIndexJ] =
  129.                     assetExcessReturnsCovarianceMatrix[assetIndexI][assetIndexJ] * tau;
  130.             }
  131.         }

  132.         try
  133.         {
  134.             org.drip.measure.bayesian.ScopingProjectionVariateDistribution
  135.                 scopingProjectionVariateDistribution =
  136.                     new org.drip.measure.bayesian.ScopingProjectionVariateDistribution (
  137.                         org.drip.measure.gaussian.R1MultivariateNormal.Standard (
  138.                             _forwardReverseOptimizationOutputUnadjusted.optimalPortfolio().meta(),
  139.                             priorExpectedAssetReturnsArray,
  140.                             priorCovarianceMatrix
  141.                         )
  142.                     );

  143.             return scopingProjectionVariateDistribution.addProjectionDistributionLoading (
  144.                 "VIEW",
  145.                 new org.drip.measure.bayesian.ProjectionDistributionLoading (
  146.                     _projectionSpecification.excessReturnsDistribution(),
  147.                     _projectionSpecification.assetSpaceLoadingMatrix()
  148.                 )
  149.             ) ? scopingProjectionVariateDistribution : null;
  150.         }
  151.         catch (java.lang.Exception e)
  152.         {
  153.             e.printStackTrace();
  154.         }

  155.         return null;
  156.     }

  157.     private double[] allocationTiltArray (
  158.         final org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation
  159.             forwardReverseOptimizationOutputAdjusted)
  160.     {
  161.         double[] adjustedWeightArray =
  162.             forwardReverseOptimizationOutputAdjusted.optimalPortfolio().weightArray();

  163.         double[] unAdjustedWeightArray =
  164.             _forwardReverseOptimizationOutputUnadjusted.optimalPortfolio().weightArray();

  165.         int assetCount = unAdjustedWeightArray.length;
  166.         double[] allocationTiltArray = new double[assetCount];

  167.         for (int assetIndex = 0; assetIndex < assetCount; ++assetIndex)
  168.         {
  169.             allocationTiltArray[assetIndex] = adjustedWeightArray[assetIndex] -
  170.                 unAdjustedWeightArray[assetIndex];
  171.         }

  172.         return allocationTiltArray;
  173.     }

  174.     /**
  175.      * BlackLittermanCombinationEngine Construction
  176.      *
  177.      * @param forwardReverseOptimizationOutputUnadjusted The Unadjusted Instance of
  178.      *  ForwardReverseOptimizationOutput
  179.      * @param priorControlSpecification The Prior Control Specification Instance
  180.      * @param projectionSpecification The View Projection Specification Settings
  181.      *
  182.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  183.      */

  184.     public BlackLittermanCombinationEngine (
  185.         final org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation
  186.             forwardReverseOptimizationOutputUnadjusted,
  187.         final org.drip.portfolioconstruction.bayesian.PriorControlSpecification priorControlSpecification,
  188.         final org.drip.portfolioconstruction.bayesian.ProjectionSpecification projectionSpecification)
  189.         throws java.lang.Exception
  190.     {
  191.         if (null == (_forwardReverseOptimizationOutputUnadjusted =
  192.                 forwardReverseOptimizationOutputUnadjusted) ||
  193.             null == (_priorControlSpecification = priorControlSpecification) ||
  194.             null == (_projectionSpecification = projectionSpecification))
  195.         {
  196.             throw new java.lang.Exception ("BlackLittermanCombinationEngine Constructor => Invalid Inputs");
  197.         }
  198.     }

  199.     /**
  200.      * Conduct a Black Litterman Run using a Theil-like Mixed Model Estimator for 0% Confidence in the
  201.      *  Projection
  202.      *
  203.      * @return Output of the Black Litterman Run
  204.      */

  205.     public org.drip.portfolioconstruction.bayesian.BlackLittermanOutput noConfidenceRun()
  206.     {
  207.         double tau = _priorControlSpecification.tau();

  208.         double[][] assetExcessReturnsCovarianceMatrix =
  209.             _forwardReverseOptimizationOutputUnadjusted.assetExcessReturnsCovarianceMatrix();

  210.         int assetCount = assetExcessReturnsCovarianceMatrix.length;
  211.         double[][] assetBayesianExcessReturnsCovarianceMatrix = new double[assetCount][assetCount];

  212.         for (int i = 0; i < assetCount; ++i)
  213.         {
  214.             for (int j = 0; j < assetCount; ++j)
  215.             {
  216.                 assetBayesianExcessReturnsCovarianceMatrix[i][j] = assetExcessReturnsCovarianceMatrix[i][j] *
  217.                     tau;
  218.             }
  219.         }

  220.         org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation
  221.             forwardReverseOptimizationOutputAdjusted =
  222.                 org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation.Forward (
  223.                     _forwardReverseOptimizationOutputUnadjusted.optimalPortfolio().meta().names(),
  224.                     _forwardReverseOptimizationOutputUnadjusted.expectedAssetExcessReturnsArray(),
  225.                     assetBayesianExcessReturnsCovarianceMatrix,
  226.                     _forwardReverseOptimizationOutputUnadjusted.riskAversion()
  227.                 );

  228.         try
  229.         {
  230.             return null == forwardReverseOptimizationOutputAdjusted ? null :
  231.                 new org.drip.portfolioconstruction.bayesian.BlackLittermanOutput (
  232.                     forwardReverseOptimizationOutputAdjusted,
  233.                     allocationTiltArray (
  234.                         forwardReverseOptimizationOutputAdjusted
  235.                     )
  236.                 );
  237.         }
  238.         catch (java.lang.Exception e)
  239.         {
  240.             e.printStackTrace();
  241.         }

  242.         return null;
  243.     }

  244.     /**
  245.      * Conduct a Black Litterman Run using a Theil-like Mixed Model Estimator Using the specified Confidence
  246.      *  Level
  247.      *
  248.      * @return Output of the Black Litterman Run
  249.      */

  250.     public org.drip.portfolioconstruction.bayesian.BlackLittermanCustomConfidenceOutput customConfidenceRun()
  251.     {
  252.         double[][] assetExcessReturnsCovarianceMatrix =
  253.             _forwardReverseOptimizationOutputUnadjusted.assetExcessReturnsCovarianceMatrix();

  254.         org.drip.measure.continuous.MultivariateMeta portfolioMeta =
  255.             _forwardReverseOptimizationOutputUnadjusted.optimalPortfolio().meta();

  256.         org.drip.measure.bayesian.ScopingProjectionVariateDistribution scopingProjectionVariateDistribution =
  257.             scopingProjectionVariateDistribution();

  258.         if (null == scopingProjectionVariateDistribution)
  259.         {
  260.             return null;
  261.         }

  262.         org.drip.measure.bayesian.R1MultivariateConvolutionMetrics jointPosteriorMetrics =
  263.             org.drip.measure.bayesian.TheilMixedEstimationModel.GenerateComposite (
  264.                 scopingProjectionVariateDistribution,
  265.                 "VIEW",
  266.                 org.drip.measure.gaussian.R1MultivariateNormal.Standard (
  267.                     portfolioMeta,
  268.                     scopingProjectionVariateDistribution.scopingDistribution().mean(),
  269.                     assetExcessReturnsCovarianceMatrix
  270.                 )
  271.             );

  272.         if (null == jointPosteriorMetrics)
  273.         {
  274.             return null;
  275.         }

  276.         org.drip.measure.continuous.R1Multivariate r1mPosterior = jointPosteriorMetrics.posterior();

  277.         org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation
  278.             forwardReverseOptimizationOutputAdjusted =
  279.                 org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation.Forward (
  280.                     portfolioMeta.names(),
  281.                     r1mPosterior.mean(),
  282.                     _priorControlSpecification.useAlternateReferenceModel() ?
  283.                         assetExcessReturnsCovarianceMatrix :
  284.                         ((org.drip.measure.gaussian.R1MultivariateNormal)
  285.                             r1mPosterior).covariance().covarianceMatrix(),
  286.                     _forwardReverseOptimizationOutputUnadjusted.riskAversion()
  287.                 );

  288.         if (null == forwardReverseOptimizationOutputAdjusted)
  289.         {
  290.             return null;
  291.         }

  292.         try {
  293.             return new org.drip.portfolioconstruction.bayesian.BlackLittermanCustomConfidenceOutput (
  294.                 forwardReverseOptimizationOutputAdjusted,
  295.                 allocationTiltArray (
  296.                     forwardReverseOptimizationOutputAdjusted
  297.                 ),
  298.                 jointPosteriorMetrics
  299.             );
  300.         }
  301.         catch (java.lang.Exception e)
  302.         {
  303.             e.printStackTrace();
  304.         }

  305.         return null;
  306.     }

  307.     /**
  308.      * Conduct a Black Litterman Run using a Theil-like Mixed Model Estimator For 100% Confidence in the
  309.      *  Projection
  310.      *
  311.      * @return Output of the Black Litterman Run
  312.      */

  313.     public org.drip.portfolioconstruction.bayesian.BlackLittermanOutput fullConfidenceRun()
  314.     {
  315.         org.drip.measure.continuous.MultivariateMeta portfolioMeta =
  316.             _forwardReverseOptimizationOutputUnadjusted.optimalPortfolio().meta();

  317.         double[][] assetExcessReturnsCovarianceMatrix =
  318.             _forwardReverseOptimizationOutputUnadjusted.assetExcessReturnsCovarianceMatrix();

  319.         double riskAversion = _forwardReverseOptimizationOutputUnadjusted.riskAversion();

  320.         java.lang.String[] assetIDArray = portfolioMeta.names();

  321.         org.drip.measure.bayesian.ScopingProjectionVariateDistribution scopingProjectionVariateDistribution =
  322.             scopingProjectionVariateDistribution();

  323.         if (null == scopingProjectionVariateDistribution)
  324.         {
  325.             return null;
  326.         }

  327.         org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation
  328.             forwardReverseOptimizationOutputAdjusted = null;

  329.         if (_priorControlSpecification.useAlternateReferenceModel())
  330.         {
  331.             forwardReverseOptimizationOutputAdjusted =
  332.                 org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation.Forward (
  333.                     assetIDArray,
  334.                     org.drip.measure.bayesian.TheilMixedEstimationModel.ProjectionInducedScopingMean (
  335.                         scopingProjectionVariateDistribution,
  336.                         "VIEW"
  337.                     ),
  338.                     assetExcessReturnsCovarianceMatrix,
  339.                     riskAversion
  340.                 );
  341.         }
  342.         else
  343.         {
  344.             org.drip.measure.gaussian.R1MultivariateNormal combinedDistribution =
  345.                 org.drip.measure.bayesian.TheilMixedEstimationModel.ProjectionInducedScopingDistribution (
  346.                     scopingProjectionVariateDistribution,
  347.                     "VIEW",
  348.                     org.drip.measure.gaussian.R1MultivariateNormal.Standard (
  349.                         portfolioMeta,
  350.                         scopingProjectionVariateDistribution.scopingDistribution().mean(),
  351.                         assetExcessReturnsCovarianceMatrix
  352.                     )
  353.                 );

  354.             forwardReverseOptimizationOutputAdjusted = null == combinedDistribution ? null :
  355.                 org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation.Forward (
  356.                     assetIDArray,
  357.                     combinedDistribution.mean(),
  358.                     assetExcessReturnsCovarianceMatrix,
  359.                     riskAversion
  360.                 );
  361.         }

  362.         try
  363.         {
  364.             return null == forwardReverseOptimizationOutputAdjusted ? null :
  365.                 new org.drip.portfolioconstruction.bayesian.BlackLittermanOutput (
  366.                     forwardReverseOptimizationOutputAdjusted,
  367.                     allocationTiltArray (
  368.                         forwardReverseOptimizationOutputAdjusted
  369.                     )
  370.                 );
  371.         }
  372.         catch (java.lang.Exception e)
  373.         {
  374.             e.printStackTrace();
  375.         }

  376.         return null;
  377.     }

  378.     /**
  379.      * Compute the Idzorek Implied Projection Confidence Level
  380.      *
  381.      * @return The Idzorek Implied Projection Confidence Level
  382.      */

  383.     public org.drip.portfolioconstruction.bayesian.ProjectionImpliedConfidenceOutput impliedConfidenceRun()
  384.     {
  385.         double[][] assetExcessReturnsCovarianceMatrix =
  386.             _forwardReverseOptimizationOutputUnadjusted.assetExcessReturnsCovarianceMatrix();

  387.         org.drip.portfolioconstruction.asset.Portfolio unadjustedPortfolio =
  388.             _forwardReverseOptimizationOutputUnadjusted.optimalPortfolio();

  389.         org.drip.measure.bayesian.ScopingProjectionVariateDistribution scopingProjectionVariateDistribution =
  390.             scopingProjectionVariateDistribution();

  391.         boolean useAlternateReferenceModel = _priorControlSpecification.useAlternateReferenceModel();

  392.         org.drip.measure.continuous.MultivariateMeta portfolioMeta = unadjustedPortfolio.meta();

  393.         double riskAversion = _forwardReverseOptimizationOutputUnadjusted.riskAversion();

  394.         java.lang.String[] assetIDArray = portfolioMeta.names();

  395.         if (null == scopingProjectionVariateDistribution)
  396.         {
  397.             return null;
  398.         }

  399.         org.drip.measure.bayesian.R1MultivariateConvolutionMetrics jointPosteriorMetrics =
  400.             org.drip.measure.bayesian.TheilMixedEstimationModel.GenerateComposite (
  401.                 scopingProjectionVariateDistribution,
  402.                 "VIEW",
  403.                 org.drip.measure.gaussian.R1MultivariateNormal.Standard (
  404.                     portfolioMeta,
  405.                     scopingProjectionVariateDistribution.scopingDistribution().mean(),
  406.                     assetExcessReturnsCovarianceMatrix
  407.                 )
  408.             );

  409.         if (null == jointPosteriorMetrics)
  410.         {
  411.             return null;
  412.         }

  413.         org.drip.measure.continuous.R1Multivariate posteriorDistribution = jointPosteriorMetrics.posterior();

  414.         org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation
  415.             forwardReverseOptimizationOutputCustomConfidence =
  416.                 org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation.Forward (
  417.                     assetIDArray,
  418.                     posteriorDistribution.mean(),
  419.                     useAlternateReferenceModel ? assetExcessReturnsCovarianceMatrix :
  420.                         ((org.drip.measure.gaussian.R1MultivariateNormal)
  421.                             posteriorDistribution).covariance().covarianceMatrix(),
  422.                     riskAversion
  423.                 );

  424.         if (null == forwardReverseOptimizationOutputCustomConfidence)
  425.         {
  426.             return null;
  427.         }

  428.         org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation
  429.             forwardReverseOptimizationOutputFullConfidence = null;

  430.         if (useAlternateReferenceModel)
  431.         {
  432.             forwardReverseOptimizationOutputFullConfidence =
  433.                 org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation.Forward (
  434.                     assetIDArray,
  435.                     org.drip.measure.bayesian.TheilMixedEstimationModel.ProjectionInducedScopingMean (
  436.                         scopingProjectionVariateDistribution,
  437.                         "VIEW"
  438.                     ),
  439.                     assetExcessReturnsCovarianceMatrix,
  440.                     riskAversion
  441.                 );
  442.         }
  443.         else
  444.         {
  445.             org.drip.measure.gaussian.R1MultivariateNormal combinedDistribution =
  446.                 org.drip.measure.bayesian.TheilMixedEstimationModel.ProjectionInducedScopingDistribution (
  447.                     scopingProjectionVariateDistribution,
  448.                     "VIEW",
  449.                     org.drip.measure.gaussian.R1MultivariateNormal.Standard (
  450.                         portfolioMeta,
  451.                         scopingProjectionVariateDistribution.scopingDistribution().mean(),
  452.                         assetExcessReturnsCovarianceMatrix
  453.                     )
  454.                 );

  455.             forwardReverseOptimizationOutputFullConfidence = null == combinedDistribution ? null :
  456.                 org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation.Forward (
  457.                     assetIDArray,
  458.                     combinedDistribution.mean(),
  459.                     assetExcessReturnsCovarianceMatrix,
  460.                     riskAversion
  461.                 );
  462.         }

  463.         try
  464.         {
  465.             return new org.drip.portfolioconstruction.bayesian.ProjectionImpliedConfidenceOutput (
  466.                 unadjustedPortfolio.weightArray(),
  467.                 new org.drip.portfolioconstruction.bayesian.BlackLittermanCustomConfidenceOutput (
  468.                     forwardReverseOptimizationOutputCustomConfidence,
  469.                     allocationTiltArray (
  470.                         forwardReverseOptimizationOutputCustomConfidence
  471.                     ),
  472.                     jointPosteriorMetrics
  473.                 ), new org.drip.portfolioconstruction.bayesian.BlackLittermanOutput (
  474.                     forwardReverseOptimizationOutputFullConfidence,
  475.                     allocationTiltArray (
  476.                         forwardReverseOptimizationOutputFullConfidence
  477.                     )
  478.                 )
  479.             );
  480.         }
  481.         catch (java.lang.Exception e)
  482.         {
  483.             e.printStackTrace();
  484.         }

  485.         return null;
  486.     }

  487.     /**
  488.      * Compute the Exposure Loadings Attribution on a per-Projection Basis
  489.      *
  490.      * @return The Exposure Loadings Attribution on a per-Projection Basis
  491.      */

  492.     public org.drip.portfolioconstruction.bayesian.ProjectionExposure projectionExposureAttribution()
  493.     {
  494.         org.drip.measure.bayesian.ScopingProjectionVariateDistribution scopingProjectionVariateDistribution =
  495.             scopingProjectionVariateDistribution();

  496.         if (null == scopingProjectionVariateDistribution)
  497.         {
  498.             return null;
  499.         }

  500.         double[] intraViewComponentArray =
  501.             org.drip.measure.bayesian.TheilMixedEstimationModel.ProjectionPrecisionMeanProduct (
  502.                 scopingProjectionVariateDistribution,
  503.                 "VIEW"
  504.             );

  505.         if (null == intraViewComponentArray)
  506.         {
  507.             return null;
  508.         }

  509.         double tau = _priorControlSpecification.tau();

  510.         double riskAversion = _forwardReverseOptimizationOutputUnadjusted.riskAversion();

  511.         double[][] assetSpaceLoadingMatrix = _projectionSpecification.assetSpaceLoadingMatrix();

  512.         double[][] assetExcessReturnsCovarianceMatrix =
  513.             _forwardReverseOptimizationOutputUnadjusted.assetExcessReturnsCovarianceMatrix();

  514.         double projectionConfidenceScaler = 1. / tau;
  515.         int viewCount = intraViewComponentArray.length;
  516.         double assetConfidenceScaler = 1. / (1. + tau);
  517.         int assetCount = assetExcessReturnsCovarianceMatrix.length;
  518.         double[][] compositeConfidenceCovarianceMatrix = new double[viewCount][viewCount];

  519.         for (int viewIndex = 0; viewIndex < viewCount; ++viewIndex)
  520.         {
  521.             intraViewComponentArray[viewIndex] = intraViewComponentArray[viewIndex] * tau / riskAversion;
  522.         }

  523.         double[][] projectionSpaceAssetLoadingsMatrix = org.drip.numerical.linearalgebra.Matrix.Product (
  524.             org.drip.numerical.linearalgebra.Matrix.Product (
  525.                 assetSpaceLoadingMatrix,
  526.                 assetExcessReturnsCovarianceMatrix
  527.             ),
  528.             org.drip.numerical.linearalgebra.Matrix.Transpose (
  529.                 assetSpaceLoadingMatrix
  530.             )
  531.         );

  532.         if (null == projectionSpaceAssetLoadingsMatrix)
  533.         {
  534.             return null;
  535.         }

  536.         double[][] projectionCovarianceMatrix =
  537.             _projectionSpecification.excessReturnsDistribution().covariance().covarianceMatrix();

  538.         for (int viewIndexI = 0; viewIndexI < viewCount; ++viewIndexI)
  539.         {
  540.             for (int viewIndexJ = 0; viewIndexJ < viewCount; ++viewIndexJ)
  541.             {
  542.                 compositeConfidenceCovarianceMatrix[viewIndexI][viewIndexJ] =
  543.                     projectionCovarianceMatrix[viewIndexI][viewIndexJ] * projectionConfidenceScaler +
  544.                     projectionSpaceAssetLoadingsMatrix[viewIndexI][viewIndexJ] * assetConfidenceScaler;
  545.             }
  546.         }

  547.         double[][] compositePrecisionProjectionScoping = org.drip.numerical.linearalgebra.Matrix.Product (
  548.             org.drip.numerical.linearalgebra.Matrix.Product (
  549.                 org.drip.numerical.linearalgebra.Matrix.InvertUsingGaussianElimination (
  550.                     compositeConfidenceCovarianceMatrix
  551.                 ),
  552.                 assetSpaceLoadingMatrix
  553.             ),
  554.             assetExcessReturnsCovarianceMatrix
  555.         );

  556.         if (null == compositePrecisionProjectionScoping)
  557.         {
  558.             return null;
  559.         }

  560.         for (int viewIndexI = 0; viewIndexI < viewCount; ++viewIndexI)
  561.         {
  562.             for (int viewIndexJ = 0; viewIndexJ < assetCount; ++viewIndexJ)
  563.             {
  564.                 compositePrecisionProjectionScoping[viewIndexI][viewIndexJ] = -1. * assetConfidenceScaler *
  565.                     compositePrecisionProjectionScoping[viewIndexI][viewIndexJ];
  566.             }
  567.         }

  568.         try
  569.         {
  570.             return new org.drip.portfolioconstruction.bayesian.ProjectionExposure (
  571.                 intraViewComponentArray,
  572.                 org.drip.numerical.linearalgebra.Matrix.Product (
  573.                     compositePrecisionProjectionScoping,
  574.                     _forwardReverseOptimizationOutputUnadjusted.optimalPortfolio().weightArray()
  575.                 ),
  576.                 org.drip.numerical.linearalgebra.Matrix.Product (
  577.                     org.drip.numerical.linearalgebra.Matrix.Product (
  578.                         compositePrecisionProjectionScoping,
  579.                         org.drip.numerical.linearalgebra.Matrix.Transpose (
  580.                             assetSpaceLoadingMatrix
  581.                         )
  582.                     ),
  583.                     intraViewComponentArray
  584.                 ),
  585.                 compositeConfidenceCovarianceMatrix
  586.             );
  587.         }
  588.         catch (java.lang.Exception e)
  589.         {
  590.             e.printStackTrace();
  591.         }

  592.         return null;
  593.     }

  594.     /**
  595.      * Compute the Idzorek Implied Tilt Matrix from the User Projection Confidence Level
  596.      *
  597.      * @param userSpecifiedProjectionConfidenceArray Array of User-specified Projection Confidence
  598.      *
  599.      * @return The Idzorek Implied Tilt Matric from the Projection Confidence Level
  600.      */

  601.     public double[][] userConfidenceProjectionTitMatrix (
  602.         final double[] userSpecifiedProjectionConfidenceArray)
  603.     {
  604.         if (null == userSpecifiedProjectionConfidenceArray)
  605.         {
  606.             return null;
  607.         }

  608.         double[][] assetSpaceLoadingMatrix = _projectionSpecification.assetSpaceLoadingMatrix();

  609.         int assetCount = assetSpaceLoadingMatrix[0].length;
  610.         int projectionCount = assetSpaceLoadingMatrix.length;
  611.         double[][] userConfidenceProjectionTitMatrix = new double[projectionCount][assetCount];

  612.         if (projectionCount != userSpecifiedProjectionConfidenceArray.length)
  613.         {
  614.             return null;
  615.         }

  616.         org.drip.portfolioconstruction.bayesian.BlackLittermanOutput fullConfidenceOutput =
  617.             fullConfidenceRun();

  618.         if (null == fullConfidenceOutput)
  619.         {
  620.             return null;
  621.         }

  622.         double[] fullConfidenceWeightsDeviationArray = fullConfidenceOutput.allocationAdjustmentTiltArray();

  623.         for (int projectionIndex = 0; projectionIndex < projectionCount; ++projectionIndex)
  624.         {
  625.             for (int assetIndex = 0; assetIndex < assetCount; ++assetIndex)
  626.             {
  627.                 userConfidenceProjectionTitMatrix[projectionIndex][assetIndex] =
  628.                     fullConfidenceWeightsDeviationArray[assetIndex] *
  629.                     assetSpaceLoadingMatrix[projectionIndex][assetIndex] *
  630.                     userSpecifiedProjectionConfidenceArray[projectionIndex];
  631.             }
  632.         }

  633.         return userConfidenceProjectionTitMatrix;
  634.     }

  635.     /**
  636.      * Compute the Mismatch between the User Specified Projection and the Custom Confidence Implied Tilts
  637.      *
  638.      * @param userConfidenceProjectionTiltArray Array of the User Confidence induced Projection Tilts
  639.      * @param projectionIndex The Index into the Projection Meta
  640.      * @param projectionVariance The Projection Variance
  641.      *
  642.      * @return The Squared Mismatch
  643.      *
  644.      * @throws java.lang.Exception Thrown if the Squared Mismatch cannot be calculated
  645.      */

  646.     public double tiltMismatchSquared (
  647.         final double[] userConfidenceProjectionTiltArray,
  648.         final int projectionIndex,
  649.         final double projectionVariance)
  650.         throws java.lang.Exception
  651.     {
  652.         if (null == userConfidenceProjectionTiltArray ||
  653.             !org.drip.numerical.common.NumberUtil.IsValid (
  654.                 projectionVariance
  655.             ))
  656.         {
  657.             throw new java.lang.Exception
  658.                 ("BlackLittermanCombinationEngine::tiltMismatchSquared => Invalid Inputs");
  659.         }

  660.         org.drip.measure.gaussian.R1MultivariateNormal totalExcessReturnsDistribution =
  661.             _projectionSpecification.excessReturnsDistribution();

  662.         org.drip.measure.gaussian.R1MultivariateNormal projectionDistribution =
  663.             org.drip.measure.gaussian.R1MultivariateNormal.Standard (
  664.                 new java.lang.String[] {
  665.                     totalExcessReturnsDistribution.meta().names()[projectionIndex]
  666.                 },
  667.                 new double[] {
  668.                     totalExcessReturnsDistribution.mean()[projectionIndex]
  669.                 },
  670.                 new double[][]
  671.                 {
  672.                     {
  673.                         projectionVariance
  674.                     }
  675.                 }
  676.             );

  677.         if (null == projectionDistribution)
  678.         {
  679.             throw new java.lang.Exception
  680.                 ("BlackLittermanCombinationEngine::tiltMismatchSquared => Invalid Inputs");
  681.         }

  682.         BlackLittermanCombinationEngine projectionEngine =
  683.             new BlackLittermanCombinationEngine (
  684.                 _forwardReverseOptimizationOutputUnadjusted,
  685.                 _priorControlSpecification,
  686.                 new org.drip.portfolioconstruction.bayesian.ProjectionSpecification (
  687.                     projectionDistribution,
  688.                     new double[][]
  689.                     {
  690.                         _projectionSpecification.assetSpaceLoadingMatrix()[projectionIndex]
  691.                     }
  692.                 )
  693.             );

  694.         org.drip.portfolioconstruction.bayesian.BlackLittermanCustomConfidenceOutput customConfidenceOuput =
  695.             projectionEngine.customConfidenceRun();

  696.         if (null == customConfidenceOuput)
  697.         {
  698.             throw new java.lang.Exception
  699.                 ("BlackLittermanCombinationEngine::tiltMismatchSquared => Invalid Inputs");
  700.         }

  701.         double[] posteriorTiltArray = customConfidenceOuput.allocationAdjustmentTiltArray();

  702.         int assetCount = posteriorTiltArray.length;
  703.         double tiltMismatchSquared = 0.;

  704.         if (assetCount != userConfidenceProjectionTiltArray.length)
  705.         {
  706.             throw new java.lang.Exception
  707.                 ("BlackLittermanCombinationEngine::tiltMismatchSquared => Invalid Inputs");
  708.         }

  709.         for (int assetIndex = 0; assetIndex < assetCount; ++assetIndex)
  710.         {
  711.             if (!org.drip.numerical.common.NumberUtil.IsValid (
  712.                 userConfidenceProjectionTiltArray[assetIndex]
  713.             ))
  714.             {
  715.                 throw new java.lang.Exception
  716.                     ("BlackLittermanCombinationEngine::tiltMismatchSquared => Invalid Inputs");
  717.             }

  718.             double dblAssetTiltGap = posteriorTiltArray[assetIndex] -
  719.                 userConfidenceProjectionTiltArray[assetIndex];
  720.             tiltMismatchSquared = tiltMismatchSquared + dblAssetTiltGap * dblAssetTiltGap;
  721.         }

  722.         return tiltMismatchSquared;
  723.     }

  724.     /**
  725.      * Generate the Squared Tilt Departure R<sup>1</sup> To R<sup>1</sup>
  726.      *
  727.      * @param userConfidenceProjectionTiltArray Array of the User Confidence induced Projection Tilts
  728.      * @param projectionIndex The Index into the Projection Meta
  729.      * @param generateDerivative TRUE - Generate the Derivative of the Tilt Departure
  730.      *
  731.      * @return The Squared Tilt Departure R<sup>1</sup> To R<sup>1</sup>
  732.      */

  733.     public org.drip.function.definition.R1ToR1 tiltDepartureR1ToR1 (
  734.         final double[] userConfidenceProjectionTiltArray,
  735.         final int projectionIndex,
  736.         final boolean generateDerivative)
  737.     {
  738.         final org.drip.function.definition.R1ToR1 tiltDepartureFunction =
  739.             new org.drip.function.definition.R1ToR1 (
  740.                 null
  741.             )
  742.         {
  743.             @Override public double evaluate (
  744.                 final double projectionVariance)
  745.                 throws java.lang.Exception
  746.             {
  747.                 return tiltMismatchSquared (
  748.                     userConfidenceProjectionTiltArray,
  749.                     projectionIndex,
  750.                     projectionVariance
  751.                 );
  752.             }
  753.         };

  754.         if (!generateDerivative)
  755.         {
  756.             return tiltDepartureFunction;
  757.         }

  758.         return new org.drip.function.definition.R1ToR1 (
  759.             null
  760.         )
  761.         {
  762.             @Override public double evaluate (
  763.                 final double projectionVariance)
  764.                 throws java.lang.Exception
  765.             {
  766.                 return tiltDepartureFunction.derivative (
  767.                     projectionVariance,
  768.                     1
  769.                 );
  770.             }
  771.         };
  772.     }
  773. }