Portfolio.java

  1. package org.drip.portfolioconstruction.asset;

  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>Portfolio</i> implements an Instance of the Portfolio of Assets.
  79.  *
  80.  *  <br><br>
  81.  *  <ul>
  82.  *      <li><b>Module </b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/PortfolioCore.md">Portfolio Core Module</a></li>
  83.  *      <li><b>Library</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/AssetAllocationAnalyticsLibrary.md">Asset Allocation Analytics</a></li>
  84.  *      <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>
  85.  *      <li><b>Package</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/portfolioconstruction/asset/README.md">Asset Characteristics, Bounds, Portfolio Benchmarks</a></li>
  86.  *  </ul>
  87.  *
  88.  * @author Lakshmi Krishnamurthy
  89.  */

  90. public class Portfolio
  91. {
  92.     private org.drip.portfolioconstruction.asset.AssetComponent[] _assetComponentArray = null;

  93.     /**
  94.      * Construct a Portfolio Instance from the Array of Asset ID's and their Amounts
  95.      *
  96.      * @param assetIDArray Array of Asset IDs
  97.      * @param amountArray Array of Amounts
  98.      *
  99.      * @return The Portfolio Instance
  100.      */

  101.     public static final Portfolio Standard (
  102.         final java.lang.String[] assetIDArray,
  103.         final double[] amountArray)
  104.     {
  105.         if (null == assetIDArray || null == amountArray)
  106.         {
  107.             return null;
  108.         }

  109.         int assetCount = assetIDArray.length;
  110.         org.drip.portfolioconstruction.asset.AssetComponent[] assetComponentArray = 0 == assetCount ?
  111.             null : new org.drip.portfolioconstruction.asset.AssetComponent[assetCount];

  112.         if (0 == assetCount || assetCount != amountArray.length)
  113.         {
  114.             return null;
  115.         }

  116.         try
  117.         {
  118.             for (int assetIndex = 0; assetIndex < assetCount; ++assetIndex)
  119.             {
  120.                 assetComponentArray[assetIndex] = new org.drip.portfolioconstruction.asset.AssetComponent (
  121.                     assetIDArray[assetIndex],
  122.                     amountArray[assetIndex]
  123.                 );
  124.             }

  125.             return new Portfolio (assetComponentArray);
  126.         }
  127.         catch (java.lang.Exception e)
  128.         {
  129.             e.printStackTrace();
  130.         }

  131.         return null;
  132.     }

  133.     /**
  134.      * Portfolio Constructor
  135.      *
  136.      * @param assetComponentArray Array of the Asset Components
  137.      *
  138.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  139.      */

  140.     public Portfolio (
  141.         final org.drip.portfolioconstruction.asset.AssetComponent[] assetComponentArray)
  142.         throws java.lang.Exception
  143.     {
  144.         if (null == (_assetComponentArray = assetComponentArray))
  145.         {
  146.             throw new java.lang.Exception ("Portfolio Constructor => Invalid Inputs");
  147.         }

  148.         int assetCount = _assetComponentArray.length;

  149.         if (0 == assetCount)
  150.         {
  151.             throw new java.lang.Exception ("Portfolio Constructor => Invalid Inputs");
  152.         }

  153.         for (int assetIndex = 0; assetIndex < assetCount; ++assetIndex)
  154.         {
  155.             if (null == _assetComponentArray[assetIndex])
  156.             {
  157.                 throw new java.lang.Exception ("Portfolio Constructor => Invalid Inputs");
  158.             }
  159.         }
  160.     }

  161.     /**
  162.      * Retrieve the Array of the Asset Components
  163.      *
  164.      * @return Array of the Asset Components
  165.      */

  166.     public org.drip.portfolioconstruction.asset.AssetComponent[] assetComponentArray()
  167.     {
  168.         return _assetComponentArray;
  169.     }

  170.     /**
  171.      * Retrieve the Notional of the Portfolio
  172.      *
  173.      * @return Notional of the Portfolio
  174.      */

  175.     public double notional()
  176.     {
  177.         double notional = 0.;
  178.         int assetCount = _assetComponentArray.length;

  179.         for (int assetIndex = 0; assetIndex < assetCount; ++assetIndex)
  180.         {
  181.             notional += _assetComponentArray[assetIndex].amount();
  182.         }

  183.         return notional;
  184.     }

  185.     /**
  186.      * Retrieve the Array of Asset IDs
  187.      *
  188.      * @return The Array of Asset IDs
  189.      */

  190.     public java.lang.String[] assetIDArray()
  191.     {
  192.         int assetCount = _assetComponentArray.length;
  193.         java.lang.String[] assetIDArray = new java.lang.String[assetCount];

  194.         for (int assetIndex = 0; assetIndex < assetCount; ++assetIndex)
  195.         {
  196.             assetIDArray[assetIndex] = _assetComponentArray[assetIndex].id();
  197.         }

  198.         return assetIDArray;
  199.     }

  200.     /**
  201.      * Retrieve the Multivariate Meta Instance around the Assets
  202.      *
  203.      * @return The Multivariate Meta Instance around the Assets
  204.      */

  205.     public org.drip.measure.continuous.MultivariateMeta meta()
  206.     {
  207.         try
  208.         {
  209.             return new org.drip.measure.continuous.MultivariateMeta (assetIDArray());
  210.         }
  211.         catch (java.lang.Exception e)
  212.         {
  213.             e.printStackTrace();
  214.         }

  215.         return null;
  216.     }

  217.     /**
  218.      * Retrieve the Array of Asset Weights
  219.      *
  220.      * @return The Array of Asset Weights
  221.      */

  222.     public double[] weightArray()
  223.     {
  224.         int assetCount = _assetComponentArray.length;
  225.         double[] weightArray = new double[assetCount];

  226.         for (int assetIndex = 0; assetIndex < assetCount; ++assetIndex)
  227.         {
  228.             weightArray[assetIndex] = _assetComponentArray[assetIndex].amount();
  229.         }

  230.         return weightArray;
  231.     }

  232.     /**
  233.      * Retrieve the Asset Component with the Lowest Weight
  234.      *
  235.      * @return The Asset Component with the Lowest Weight
  236.      */

  237.     public org.drip.portfolioconstruction.asset.AssetComponent lowestWeightAsset()
  238.     {
  239.         int assetCount = _assetComponentArray.length;
  240.         org.drip.portfolioconstruction.asset.AssetComponent lowestWeightAsset = _assetComponentArray[0];

  241.         double lowestWeight = _assetComponentArray[0].amount();

  242.         for (int assetIndex = 0; assetIndex < assetCount; ++assetIndex)
  243.         {
  244.             double amount = _assetComponentArray[assetIndex].amount();

  245.             if (amount < lowestWeight)
  246.             {
  247.                 lowestWeightAsset = _assetComponentArray[assetIndex];
  248.                 lowestWeight = amount;
  249.             }
  250.         }

  251.         return lowestWeightAsset;
  252.     }

  253.     /**
  254.      * Retrieve the Asset Component with the Highest Weight
  255.      *
  256.      * @return The Asset Component with the Highest Weight
  257.      */

  258.     public org.drip.portfolioconstruction.asset.AssetComponent highestWeightAsset()
  259.     {
  260.         int assetCount = _assetComponentArray.length;
  261.         org.drip.portfolioconstruction.asset.AssetComponent highestWeightAsset = _assetComponentArray[0];

  262.         double highestWeight = _assetComponentArray[0].amount();

  263.         for (int assetIndex = 0; assetIndex < assetCount; ++assetIndex)
  264.         {
  265.             double amount = _assetComponentArray[assetIndex].amount();

  266.             if (amount > highestWeight)
  267.             {
  268.                 highestWeightAsset = _assetComponentArray[assetIndex];
  269.                 highestWeight = amount;
  270.             }
  271.         }

  272.         return highestWeightAsset;
  273.     }

  274.     /**
  275.      * Retrieve the Portfolio Asset Cardinality
  276.      *
  277.      * @return The Portfolio Asset Cardinality
  278.      */

  279.     public int cardinality()
  280.     {
  281.         int cardinality = 0;
  282.         int assetCount = _assetComponentArray.length;

  283.         for (int assetIndex = 0; assetIndex < assetCount; ++assetIndex)
  284.         {
  285.             if (0. !=  _assetComponentArray[assetIndex].amount())
  286.             {
  287.                 ++cardinality;
  288.             }
  289.         }

  290.         return cardinality;
  291.     }

  292.     /**
  293.      * Retrieve the Expected Returns of the Portfolio
  294.      *
  295.      * @param assetUniverseStatisticalProperties The Asset Pool Statistical Properties Instance
  296.      *
  297.      * @return Expected Returns of the Portfolio
  298.      *
  299.      * @throws java.lang.Exception Thrown if the Expected Returns cannot be calculated
  300.      */

  301.     public double expectedReturn (
  302.         final org.drip.portfolioconstruction.params.AssetUniverseStatisticalProperties
  303.             assetUniverseStatisticalProperties)
  304.         throws java.lang.Exception
  305.     {
  306.         int assetCount = _assetComponentArray.length;
  307.         double expectedReturn = 0.;

  308.         for (int assetIndex = 0; assetIndex < assetCount; ++assetIndex)
  309.         {
  310.             org.drip.portfolioconstruction.params.AssetStatisticalProperties assetStatisticalProperties =
  311.                 assetUniverseStatisticalProperties.assetStatisticalProperties
  312.                     (_assetComponentArray[assetIndex].id());

  313.             if (null == assetStatisticalProperties)
  314.             {
  315.                 throw new java.lang.Exception ("Portfolio::expectedReturn => Invalid Inputs");
  316.             }

  317.             expectedReturn += _assetComponentArray[assetIndex].amount() *
  318.                 assetStatisticalProperties.expectedReturn();
  319.         }

  320.         return expectedReturn;
  321.     }

  322.     /**
  323.      * Retrieve the Variance of the Portfolio
  324.      *
  325.      * @param assetUniverseStatisticalProperties The Asset Pool Statistical Properties Instance
  326.      *
  327.      * @return Variance of the Portfolio
  328.      *
  329.      * @throws java.lang.Exception Thrown if the Variance cannot be calculated
  330.      */

  331.     public double variance (
  332.         final org.drip.portfolioconstruction.params.AssetUniverseStatisticalProperties
  333.             assetUniverseStatisticalProperties)
  334.         throws java.lang.Exception
  335.     {
  336.         double variance = 0.;
  337.         int assetCount = _assetComponentArray.length;

  338.         for (int assetIndexI = 0; assetIndexI < assetCount; ++assetIndexI)
  339.         {
  340.             double amountI = _assetComponentArray[assetIndexI].amount();

  341.             java.lang.String idI = _assetComponentArray[assetIndexI].id();

  342.             org.drip.portfolioconstruction.params.AssetStatisticalProperties assetStatisticalPropertiesI =
  343.                 assetUniverseStatisticalProperties.assetStatisticalProperties (idI);

  344.             if (null == assetStatisticalPropertiesI)
  345.             {
  346.                 throw new java.lang.Exception ("Portfolio::variance => Invalid Inputs");
  347.             }

  348.             double varianceI = assetStatisticalPropertiesI.variance();

  349.             for (int assetIndexJ = 0; assetIndexJ < assetCount; ++assetIndexJ)
  350.             {
  351.                 java.lang.String idJ = _assetComponentArray[assetIndexJ].id();

  352.                 org.drip.portfolioconstruction.params.AssetStatisticalProperties assetStatisticalPropertiesJ
  353.                     = assetUniverseStatisticalProperties.assetStatisticalProperties (idJ);

  354.                 if (null == assetStatisticalPropertiesJ)
  355.                 {
  356.                     throw new java.lang.Exception ("Portfolio::variance => Invalid Inputs");
  357.                 }

  358.                 variance += amountI * _assetComponentArray[assetIndexJ].amount() * java.lang.Math.sqrt (
  359.                     varianceI * assetStatisticalPropertiesJ.variance()
  360.                 ) * (
  361.                     assetIndexI == assetIndexJ ? 1. : assetUniverseStatisticalProperties.correlation (
  362.                         idI,
  363.                         idJ
  364.                     )
  365.                 );
  366.             }
  367.         }

  368.         return variance;
  369.     }
  370. }