BlackLittermanCombinationEngine.java
package org.drip.portfolioconstruction.bayesian;
/*
* -*- mode: java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*/
/*!
* Copyright (C) 2020 Lakshmi Krishnamurthy
* Copyright (C) 2019 Lakshmi Krishnamurthy
* Copyright (C) 2018 Lakshmi Krishnamurthy
* Copyright (C) 2017 Lakshmi Krishnamurthy
* Copyright (C) 2016 Lakshmi Krishnamurthy
*
* This file is part of DROP, an open-source library targeting analytics/risk, transaction cost analytics,
* asset liability management analytics, capital, exposure, and margin analytics, valuation adjustment
* analytics, and portfolio construction analytics within and across fixed income, credit, commodity,
* equity, FX, and structured products. It also includes auxiliary libraries for algorithm support,
* numerical analysis, numerical optimization, spline builder, model validation, statistical learning,
* and computational support.
*
* https://lakshmidrip.github.io/DROP/
*
* DROP is composed of three modules:
*
* - DROP Product Core - https://lakshmidrip.github.io/DROP-Product-Core/
* - DROP Portfolio Core - https://lakshmidrip.github.io/DROP-Portfolio-Core/
* - DROP Computational Core - https://lakshmidrip.github.io/DROP-Computational-Core/
*
* DROP Product Core implements libraries for the following:
* - Fixed Income Analytics
* - Loan Analytics
* - Transaction Cost Analytics
*
* DROP Portfolio Core implements libraries for the following:
* - Asset Allocation Analytics
* - Asset Liability Management Analytics
* - Capital Estimation Analytics
* - Exposure Analytics
* - Margin Analytics
* - XVA Analytics
*
* DROP Computational Core implements libraries for the following:
* - Algorithm Support
* - Computation Support
* - Function Analysis
* - Model Validation
* - Numerical Analysis
* - Numerical Optimizer
* - Spline Builder
* - Statistical Learning
*
* Documentation for DROP is Spread Over:
*
* - Main => https://lakshmidrip.github.io/DROP/
* - Wiki => https://github.com/lakshmiDRIP/DROP/wiki
* - GitHub => https://github.com/lakshmiDRIP/DROP
* - Repo Layout Taxonomy => https://github.com/lakshmiDRIP/DROP/blob/master/Taxonomy.md
* - Javadoc => https://lakshmidrip.github.io/DROP/Javadoc/index.html
* - Technical Specifications => https://github.com/lakshmiDRIP/DROP/tree/master/Docs/Internal
* - Release Versions => https://lakshmidrip.github.io/DROP/version.html
* - Community Credits => https://lakshmidrip.github.io/DROP/credits.html
* - Issues Catalog => https://github.com/lakshmiDRIP/DROP/issues
* - JUnit => https://lakshmidrip.github.io/DROP/junit/index.html
* - Jacoco => https://lakshmidrip.github.io/DROP/jacoco/index.html
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* <i>BlackLittermanCombinationEngine</i> implements the Engine that generates the Combined/Posterior
* Distributions from the Prior and the Conditional Joint R<sup>1</sup> Multivariate Normal Distributions.
* The References are:
*
* <br><br>
* <ul>
* <li>
* He. G., and R. Litterman (1999): <i>The Intuition behind the Black-Litterman Model
* Portfolios</i> <b>Goldman Sachs Asset Management</b>
* </li>
* <li>
* Idzorek, T. (2005): <i>A Step-by-Step Guide to the Black-Litterman Model: Incorporating
* User-Specified Confidence Levels</i> <b>Ibbotson Associates</b> Chicago, IL
* </li>
* </ul>
*
* <br><br>
* <ul>
* <li><b>Module </b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/PortfolioCore.md">Portfolio Core Module</a></li>
* <li><b>Library</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/AssetAllocationAnalyticsLibrary.md">Asset Allocation Analytics</a></li>
* <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>
* <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>
* </ul>
*
* @author Lakshmi Krishnamurthy
*/
public class BlackLittermanCombinationEngine
{
private org.drip.portfolioconstruction.bayesian.ProjectionSpecification _projectionSpecification = null;
private org.drip.portfolioconstruction.bayesian.PriorControlSpecification _priorControlSpecification =
null;
private org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation
_forwardReverseOptimizationOutputUnadjusted = null;
private org.drip.measure.bayesian.ScopingProjectionVariateDistribution
scopingProjectionVariateDistribution()
{
double[][] assetExcessReturnsCovarianceMatrix =
_forwardReverseOptimizationOutputUnadjusted.assetExcessReturnsCovarianceMatrix();
double[] priorExpectedAssetReturnsArray =
_forwardReverseOptimizationOutputUnadjusted.expectedAssetExcessReturnsArray();
int assetCount = assetExcessReturnsCovarianceMatrix.length;
double[][] priorCovarianceMatrix = new double[assetCount][assetCount];
double riskFreeRate = _priorControlSpecification.riskFreeRate();
double tau = _priorControlSpecification.tau();
for (int assetIndexI = 0; assetIndexI < assetCount; ++assetIndexI)
{
priorExpectedAssetReturnsArray[assetIndexI] = priorExpectedAssetReturnsArray[assetIndexI] +
riskFreeRate;
for (int assetIndexJ = 0; assetIndexJ < assetCount; ++assetIndexJ)
{
priorCovarianceMatrix[assetIndexI][assetIndexJ] =
assetExcessReturnsCovarianceMatrix[assetIndexI][assetIndexJ] * tau;
}
}
try
{
org.drip.measure.bayesian.ScopingProjectionVariateDistribution
scopingProjectionVariateDistribution =
new org.drip.measure.bayesian.ScopingProjectionVariateDistribution (
org.drip.measure.gaussian.R1MultivariateNormal.Standard (
_forwardReverseOptimizationOutputUnadjusted.optimalPortfolio().meta(),
priorExpectedAssetReturnsArray,
priorCovarianceMatrix
)
);
return scopingProjectionVariateDistribution.addProjectionDistributionLoading (
"VIEW",
new org.drip.measure.bayesian.ProjectionDistributionLoading (
_projectionSpecification.excessReturnsDistribution(),
_projectionSpecification.assetSpaceLoadingMatrix()
)
) ? scopingProjectionVariateDistribution : null;
}
catch (java.lang.Exception e)
{
e.printStackTrace();
}
return null;
}
private double[] allocationTiltArray (
final org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation
forwardReverseOptimizationOutputAdjusted)
{
double[] adjustedWeightArray =
forwardReverseOptimizationOutputAdjusted.optimalPortfolio().weightArray();
double[] unAdjustedWeightArray =
_forwardReverseOptimizationOutputUnadjusted.optimalPortfolio().weightArray();
int assetCount = unAdjustedWeightArray.length;
double[] allocationTiltArray = new double[assetCount];
for (int assetIndex = 0; assetIndex < assetCount; ++assetIndex)
{
allocationTiltArray[assetIndex] = adjustedWeightArray[assetIndex] -
unAdjustedWeightArray[assetIndex];
}
return allocationTiltArray;
}
/**
* BlackLittermanCombinationEngine Construction
*
* @param forwardReverseOptimizationOutputUnadjusted The Unadjusted Instance of
* ForwardReverseOptimizationOutput
* @param priorControlSpecification The Prior Control Specification Instance
* @param projectionSpecification The View Projection Specification Settings
*
* @throws java.lang.Exception Thrown if the Inputs are Invalid
*/
public BlackLittermanCombinationEngine (
final org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation
forwardReverseOptimizationOutputUnadjusted,
final org.drip.portfolioconstruction.bayesian.PriorControlSpecification priorControlSpecification,
final org.drip.portfolioconstruction.bayesian.ProjectionSpecification projectionSpecification)
throws java.lang.Exception
{
if (null == (_forwardReverseOptimizationOutputUnadjusted =
forwardReverseOptimizationOutputUnadjusted) ||
null == (_priorControlSpecification = priorControlSpecification) ||
null == (_projectionSpecification = projectionSpecification))
{
throw new java.lang.Exception ("BlackLittermanCombinationEngine Constructor => Invalid Inputs");
}
}
/**
* Conduct a Black Litterman Run using a Theil-like Mixed Model Estimator for 0% Confidence in the
* Projection
*
* @return Output of the Black Litterman Run
*/
public org.drip.portfolioconstruction.bayesian.BlackLittermanOutput noConfidenceRun()
{
double tau = _priorControlSpecification.tau();
double[][] assetExcessReturnsCovarianceMatrix =
_forwardReverseOptimizationOutputUnadjusted.assetExcessReturnsCovarianceMatrix();
int assetCount = assetExcessReturnsCovarianceMatrix.length;
double[][] assetBayesianExcessReturnsCovarianceMatrix = new double[assetCount][assetCount];
for (int i = 0; i < assetCount; ++i)
{
for (int j = 0; j < assetCount; ++j)
{
assetBayesianExcessReturnsCovarianceMatrix[i][j] = assetExcessReturnsCovarianceMatrix[i][j] *
tau;
}
}
org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation
forwardReverseOptimizationOutputAdjusted =
org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation.Forward (
_forwardReverseOptimizationOutputUnadjusted.optimalPortfolio().meta().names(),
_forwardReverseOptimizationOutputUnadjusted.expectedAssetExcessReturnsArray(),
assetBayesianExcessReturnsCovarianceMatrix,
_forwardReverseOptimizationOutputUnadjusted.riskAversion()
);
try
{
return null == forwardReverseOptimizationOutputAdjusted ? null :
new org.drip.portfolioconstruction.bayesian.BlackLittermanOutput (
forwardReverseOptimizationOutputAdjusted,
allocationTiltArray (
forwardReverseOptimizationOutputAdjusted
)
);
}
catch (java.lang.Exception e)
{
e.printStackTrace();
}
return null;
}
/**
* Conduct a Black Litterman Run using a Theil-like Mixed Model Estimator Using the specified Confidence
* Level
*
* @return Output of the Black Litterman Run
*/
public org.drip.portfolioconstruction.bayesian.BlackLittermanCustomConfidenceOutput customConfidenceRun()
{
double[][] assetExcessReturnsCovarianceMatrix =
_forwardReverseOptimizationOutputUnadjusted.assetExcessReturnsCovarianceMatrix();
org.drip.measure.continuous.MultivariateMeta portfolioMeta =
_forwardReverseOptimizationOutputUnadjusted.optimalPortfolio().meta();
org.drip.measure.bayesian.ScopingProjectionVariateDistribution scopingProjectionVariateDistribution =
scopingProjectionVariateDistribution();
if (null == scopingProjectionVariateDistribution)
{
return null;
}
org.drip.measure.bayesian.R1MultivariateConvolutionMetrics jointPosteriorMetrics =
org.drip.measure.bayesian.TheilMixedEstimationModel.GenerateComposite (
scopingProjectionVariateDistribution,
"VIEW",
org.drip.measure.gaussian.R1MultivariateNormal.Standard (
portfolioMeta,
scopingProjectionVariateDistribution.scopingDistribution().mean(),
assetExcessReturnsCovarianceMatrix
)
);
if (null == jointPosteriorMetrics)
{
return null;
}
org.drip.measure.continuous.R1Multivariate r1mPosterior = jointPosteriorMetrics.posterior();
org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation
forwardReverseOptimizationOutputAdjusted =
org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation.Forward (
portfolioMeta.names(),
r1mPosterior.mean(),
_priorControlSpecification.useAlternateReferenceModel() ?
assetExcessReturnsCovarianceMatrix :
((org.drip.measure.gaussian.R1MultivariateNormal)
r1mPosterior).covariance().covarianceMatrix(),
_forwardReverseOptimizationOutputUnadjusted.riskAversion()
);
if (null == forwardReverseOptimizationOutputAdjusted)
{
return null;
}
try {
return new org.drip.portfolioconstruction.bayesian.BlackLittermanCustomConfidenceOutput (
forwardReverseOptimizationOutputAdjusted,
allocationTiltArray (
forwardReverseOptimizationOutputAdjusted
),
jointPosteriorMetrics
);
}
catch (java.lang.Exception e)
{
e.printStackTrace();
}
return null;
}
/**
* Conduct a Black Litterman Run using a Theil-like Mixed Model Estimator For 100% Confidence in the
* Projection
*
* @return Output of the Black Litterman Run
*/
public org.drip.portfolioconstruction.bayesian.BlackLittermanOutput fullConfidenceRun()
{
org.drip.measure.continuous.MultivariateMeta portfolioMeta =
_forwardReverseOptimizationOutputUnadjusted.optimalPortfolio().meta();
double[][] assetExcessReturnsCovarianceMatrix =
_forwardReverseOptimizationOutputUnadjusted.assetExcessReturnsCovarianceMatrix();
double riskAversion = _forwardReverseOptimizationOutputUnadjusted.riskAversion();
java.lang.String[] assetIDArray = portfolioMeta.names();
org.drip.measure.bayesian.ScopingProjectionVariateDistribution scopingProjectionVariateDistribution =
scopingProjectionVariateDistribution();
if (null == scopingProjectionVariateDistribution)
{
return null;
}
org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation
forwardReverseOptimizationOutputAdjusted = null;
if (_priorControlSpecification.useAlternateReferenceModel())
{
forwardReverseOptimizationOutputAdjusted =
org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation.Forward (
assetIDArray,
org.drip.measure.bayesian.TheilMixedEstimationModel.ProjectionInducedScopingMean (
scopingProjectionVariateDistribution,
"VIEW"
),
assetExcessReturnsCovarianceMatrix,
riskAversion
);
}
else
{
org.drip.measure.gaussian.R1MultivariateNormal combinedDistribution =
org.drip.measure.bayesian.TheilMixedEstimationModel.ProjectionInducedScopingDistribution (
scopingProjectionVariateDistribution,
"VIEW",
org.drip.measure.gaussian.R1MultivariateNormal.Standard (
portfolioMeta,
scopingProjectionVariateDistribution.scopingDistribution().mean(),
assetExcessReturnsCovarianceMatrix
)
);
forwardReverseOptimizationOutputAdjusted = null == combinedDistribution ? null :
org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation.Forward (
assetIDArray,
combinedDistribution.mean(),
assetExcessReturnsCovarianceMatrix,
riskAversion
);
}
try
{
return null == forwardReverseOptimizationOutputAdjusted ? null :
new org.drip.portfolioconstruction.bayesian.BlackLittermanOutput (
forwardReverseOptimizationOutputAdjusted,
allocationTiltArray (
forwardReverseOptimizationOutputAdjusted
)
);
}
catch (java.lang.Exception e)
{
e.printStackTrace();
}
return null;
}
/**
* Compute the Idzorek Implied Projection Confidence Level
*
* @return The Idzorek Implied Projection Confidence Level
*/
public org.drip.portfolioconstruction.bayesian.ProjectionImpliedConfidenceOutput impliedConfidenceRun()
{
double[][] assetExcessReturnsCovarianceMatrix =
_forwardReverseOptimizationOutputUnadjusted.assetExcessReturnsCovarianceMatrix();
org.drip.portfolioconstruction.asset.Portfolio unadjustedPortfolio =
_forwardReverseOptimizationOutputUnadjusted.optimalPortfolio();
org.drip.measure.bayesian.ScopingProjectionVariateDistribution scopingProjectionVariateDistribution =
scopingProjectionVariateDistribution();
boolean useAlternateReferenceModel = _priorControlSpecification.useAlternateReferenceModel();
org.drip.measure.continuous.MultivariateMeta portfolioMeta = unadjustedPortfolio.meta();
double riskAversion = _forwardReverseOptimizationOutputUnadjusted.riskAversion();
java.lang.String[] assetIDArray = portfolioMeta.names();
if (null == scopingProjectionVariateDistribution)
{
return null;
}
org.drip.measure.bayesian.R1MultivariateConvolutionMetrics jointPosteriorMetrics =
org.drip.measure.bayesian.TheilMixedEstimationModel.GenerateComposite (
scopingProjectionVariateDistribution,
"VIEW",
org.drip.measure.gaussian.R1MultivariateNormal.Standard (
portfolioMeta,
scopingProjectionVariateDistribution.scopingDistribution().mean(),
assetExcessReturnsCovarianceMatrix
)
);
if (null == jointPosteriorMetrics)
{
return null;
}
org.drip.measure.continuous.R1Multivariate posteriorDistribution = jointPosteriorMetrics.posterior();
org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation
forwardReverseOptimizationOutputCustomConfidence =
org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation.Forward (
assetIDArray,
posteriorDistribution.mean(),
useAlternateReferenceModel ? assetExcessReturnsCovarianceMatrix :
((org.drip.measure.gaussian.R1MultivariateNormal)
posteriorDistribution).covariance().covarianceMatrix(),
riskAversion
);
if (null == forwardReverseOptimizationOutputCustomConfidence)
{
return null;
}
org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation
forwardReverseOptimizationOutputFullConfidence = null;
if (useAlternateReferenceModel)
{
forwardReverseOptimizationOutputFullConfidence =
org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation.Forward (
assetIDArray,
org.drip.measure.bayesian.TheilMixedEstimationModel.ProjectionInducedScopingMean (
scopingProjectionVariateDistribution,
"VIEW"
),
assetExcessReturnsCovarianceMatrix,
riskAversion
);
}
else
{
org.drip.measure.gaussian.R1MultivariateNormal combinedDistribution =
org.drip.measure.bayesian.TheilMixedEstimationModel.ProjectionInducedScopingDistribution (
scopingProjectionVariateDistribution,
"VIEW",
org.drip.measure.gaussian.R1MultivariateNormal.Standard (
portfolioMeta,
scopingProjectionVariateDistribution.scopingDistribution().mean(),
assetExcessReturnsCovarianceMatrix
)
);
forwardReverseOptimizationOutputFullConfidence = null == combinedDistribution ? null :
org.drip.portfolioconstruction.allocator.ForwardReverseHoldingsAllocation.Forward (
assetIDArray,
combinedDistribution.mean(),
assetExcessReturnsCovarianceMatrix,
riskAversion
);
}
try
{
return new org.drip.portfolioconstruction.bayesian.ProjectionImpliedConfidenceOutput (
unadjustedPortfolio.weightArray(),
new org.drip.portfolioconstruction.bayesian.BlackLittermanCustomConfidenceOutput (
forwardReverseOptimizationOutputCustomConfidence,
allocationTiltArray (
forwardReverseOptimizationOutputCustomConfidence
),
jointPosteriorMetrics
), new org.drip.portfolioconstruction.bayesian.BlackLittermanOutput (
forwardReverseOptimizationOutputFullConfidence,
allocationTiltArray (
forwardReverseOptimizationOutputFullConfidence
)
)
);
}
catch (java.lang.Exception e)
{
e.printStackTrace();
}
return null;
}
/**
* Compute the Exposure Loadings Attribution on a per-Projection Basis
*
* @return The Exposure Loadings Attribution on a per-Projection Basis
*/
public org.drip.portfolioconstruction.bayesian.ProjectionExposure projectionExposureAttribution()
{
org.drip.measure.bayesian.ScopingProjectionVariateDistribution scopingProjectionVariateDistribution =
scopingProjectionVariateDistribution();
if (null == scopingProjectionVariateDistribution)
{
return null;
}
double[] intraViewComponentArray =
org.drip.measure.bayesian.TheilMixedEstimationModel.ProjectionPrecisionMeanProduct (
scopingProjectionVariateDistribution,
"VIEW"
);
if (null == intraViewComponentArray)
{
return null;
}
double tau = _priorControlSpecification.tau();
double riskAversion = _forwardReverseOptimizationOutputUnadjusted.riskAversion();
double[][] assetSpaceLoadingMatrix = _projectionSpecification.assetSpaceLoadingMatrix();
double[][] assetExcessReturnsCovarianceMatrix =
_forwardReverseOptimizationOutputUnadjusted.assetExcessReturnsCovarianceMatrix();
double projectionConfidenceScaler = 1. / tau;
int viewCount = intraViewComponentArray.length;
double assetConfidenceScaler = 1. / (1. + tau);
int assetCount = assetExcessReturnsCovarianceMatrix.length;
double[][] compositeConfidenceCovarianceMatrix = new double[viewCount][viewCount];
for (int viewIndex = 0; viewIndex < viewCount; ++viewIndex)
{
intraViewComponentArray[viewIndex] = intraViewComponentArray[viewIndex] * tau / riskAversion;
}
double[][] projectionSpaceAssetLoadingsMatrix = org.drip.numerical.linearalgebra.Matrix.Product (
org.drip.numerical.linearalgebra.Matrix.Product (
assetSpaceLoadingMatrix,
assetExcessReturnsCovarianceMatrix
),
org.drip.numerical.linearalgebra.Matrix.Transpose (
assetSpaceLoadingMatrix
)
);
if (null == projectionSpaceAssetLoadingsMatrix)
{
return null;
}
double[][] projectionCovarianceMatrix =
_projectionSpecification.excessReturnsDistribution().covariance().covarianceMatrix();
for (int viewIndexI = 0; viewIndexI < viewCount; ++viewIndexI)
{
for (int viewIndexJ = 0; viewIndexJ < viewCount; ++viewIndexJ)
{
compositeConfidenceCovarianceMatrix[viewIndexI][viewIndexJ] =
projectionCovarianceMatrix[viewIndexI][viewIndexJ] * projectionConfidenceScaler +
projectionSpaceAssetLoadingsMatrix[viewIndexI][viewIndexJ] * assetConfidenceScaler;
}
}
double[][] compositePrecisionProjectionScoping = org.drip.numerical.linearalgebra.Matrix.Product (
org.drip.numerical.linearalgebra.Matrix.Product (
org.drip.numerical.linearalgebra.Matrix.InvertUsingGaussianElimination (
compositeConfidenceCovarianceMatrix
),
assetSpaceLoadingMatrix
),
assetExcessReturnsCovarianceMatrix
);
if (null == compositePrecisionProjectionScoping)
{
return null;
}
for (int viewIndexI = 0; viewIndexI < viewCount; ++viewIndexI)
{
for (int viewIndexJ = 0; viewIndexJ < assetCount; ++viewIndexJ)
{
compositePrecisionProjectionScoping[viewIndexI][viewIndexJ] = -1. * assetConfidenceScaler *
compositePrecisionProjectionScoping[viewIndexI][viewIndexJ];
}
}
try
{
return new org.drip.portfolioconstruction.bayesian.ProjectionExposure (
intraViewComponentArray,
org.drip.numerical.linearalgebra.Matrix.Product (
compositePrecisionProjectionScoping,
_forwardReverseOptimizationOutputUnadjusted.optimalPortfolio().weightArray()
),
org.drip.numerical.linearalgebra.Matrix.Product (
org.drip.numerical.linearalgebra.Matrix.Product (
compositePrecisionProjectionScoping,
org.drip.numerical.linearalgebra.Matrix.Transpose (
assetSpaceLoadingMatrix
)
),
intraViewComponentArray
),
compositeConfidenceCovarianceMatrix
);
}
catch (java.lang.Exception e)
{
e.printStackTrace();
}
return null;
}
/**
* Compute the Idzorek Implied Tilt Matrix from the User Projection Confidence Level
*
* @param userSpecifiedProjectionConfidenceArray Array of User-specified Projection Confidence
*
* @return The Idzorek Implied Tilt Matric from the Projection Confidence Level
*/
public double[][] userConfidenceProjectionTitMatrix (
final double[] userSpecifiedProjectionConfidenceArray)
{
if (null == userSpecifiedProjectionConfidenceArray)
{
return null;
}
double[][] assetSpaceLoadingMatrix = _projectionSpecification.assetSpaceLoadingMatrix();
int assetCount = assetSpaceLoadingMatrix[0].length;
int projectionCount = assetSpaceLoadingMatrix.length;
double[][] userConfidenceProjectionTitMatrix = new double[projectionCount][assetCount];
if (projectionCount != userSpecifiedProjectionConfidenceArray.length)
{
return null;
}
org.drip.portfolioconstruction.bayesian.BlackLittermanOutput fullConfidenceOutput =
fullConfidenceRun();
if (null == fullConfidenceOutput)
{
return null;
}
double[] fullConfidenceWeightsDeviationArray = fullConfidenceOutput.allocationAdjustmentTiltArray();
for (int projectionIndex = 0; projectionIndex < projectionCount; ++projectionIndex)
{
for (int assetIndex = 0; assetIndex < assetCount; ++assetIndex)
{
userConfidenceProjectionTitMatrix[projectionIndex][assetIndex] =
fullConfidenceWeightsDeviationArray[assetIndex] *
assetSpaceLoadingMatrix[projectionIndex][assetIndex] *
userSpecifiedProjectionConfidenceArray[projectionIndex];
}
}
return userConfidenceProjectionTitMatrix;
}
/**
* Compute the Mismatch between the User Specified Projection and the Custom Confidence Implied Tilts
*
* @param userConfidenceProjectionTiltArray Array of the User Confidence induced Projection Tilts
* @param projectionIndex The Index into the Projection Meta
* @param projectionVariance The Projection Variance
*
* @return The Squared Mismatch
*
* @throws java.lang.Exception Thrown if the Squared Mismatch cannot be calculated
*/
public double tiltMismatchSquared (
final double[] userConfidenceProjectionTiltArray,
final int projectionIndex,
final double projectionVariance)
throws java.lang.Exception
{
if (null == userConfidenceProjectionTiltArray ||
!org.drip.numerical.common.NumberUtil.IsValid (
projectionVariance
))
{
throw new java.lang.Exception
("BlackLittermanCombinationEngine::tiltMismatchSquared => Invalid Inputs");
}
org.drip.measure.gaussian.R1MultivariateNormal totalExcessReturnsDistribution =
_projectionSpecification.excessReturnsDistribution();
org.drip.measure.gaussian.R1MultivariateNormal projectionDistribution =
org.drip.measure.gaussian.R1MultivariateNormal.Standard (
new java.lang.String[] {
totalExcessReturnsDistribution.meta().names()[projectionIndex]
},
new double[] {
totalExcessReturnsDistribution.mean()[projectionIndex]
},
new double[][]
{
{
projectionVariance
}
}
);
if (null == projectionDistribution)
{
throw new java.lang.Exception
("BlackLittermanCombinationEngine::tiltMismatchSquared => Invalid Inputs");
}
BlackLittermanCombinationEngine projectionEngine =
new BlackLittermanCombinationEngine (
_forwardReverseOptimizationOutputUnadjusted,
_priorControlSpecification,
new org.drip.portfolioconstruction.bayesian.ProjectionSpecification (
projectionDistribution,
new double[][]
{
_projectionSpecification.assetSpaceLoadingMatrix()[projectionIndex]
}
)
);
org.drip.portfolioconstruction.bayesian.BlackLittermanCustomConfidenceOutput customConfidenceOuput =
projectionEngine.customConfidenceRun();
if (null == customConfidenceOuput)
{
throw new java.lang.Exception
("BlackLittermanCombinationEngine::tiltMismatchSquared => Invalid Inputs");
}
double[] posteriorTiltArray = customConfidenceOuput.allocationAdjustmentTiltArray();
int assetCount = posteriorTiltArray.length;
double tiltMismatchSquared = 0.;
if (assetCount != userConfidenceProjectionTiltArray.length)
{
throw new java.lang.Exception
("BlackLittermanCombinationEngine::tiltMismatchSquared => Invalid Inputs");
}
for (int assetIndex = 0; assetIndex < assetCount; ++assetIndex)
{
if (!org.drip.numerical.common.NumberUtil.IsValid (
userConfidenceProjectionTiltArray[assetIndex]
))
{
throw new java.lang.Exception
("BlackLittermanCombinationEngine::tiltMismatchSquared => Invalid Inputs");
}
double dblAssetTiltGap = posteriorTiltArray[assetIndex] -
userConfidenceProjectionTiltArray[assetIndex];
tiltMismatchSquared = tiltMismatchSquared + dblAssetTiltGap * dblAssetTiltGap;
}
return tiltMismatchSquared;
}
/**
* Generate the Squared Tilt Departure R<sup>1</sup> To R<sup>1</sup>
*
* @param userConfidenceProjectionTiltArray Array of the User Confidence induced Projection Tilts
* @param projectionIndex The Index into the Projection Meta
* @param generateDerivative TRUE - Generate the Derivative of the Tilt Departure
*
* @return The Squared Tilt Departure R<sup>1</sup> To R<sup>1</sup>
*/
public org.drip.function.definition.R1ToR1 tiltDepartureR1ToR1 (
final double[] userConfidenceProjectionTiltArray,
final int projectionIndex,
final boolean generateDerivative)
{
final org.drip.function.definition.R1ToR1 tiltDepartureFunction =
new org.drip.function.definition.R1ToR1 (
null
)
{
@Override public double evaluate (
final double projectionVariance)
throws java.lang.Exception
{
return tiltMismatchSquared (
userConfidenceProjectionTiltArray,
projectionIndex,
projectionVariance
);
}
};
if (!generateDerivative)
{
return tiltDepartureFunction;
}
return new org.drip.function.definition.R1ToR1 (
null
)
{
@Override public double evaluate (
final double projectionVariance)
throws java.lang.Exception
{
return tiltDepartureFunction.derivative (
projectionVariance,
1
);
}
};
}
}