/*
         * public static double NetExpectedReturn(MarketData state, double expectedReturn, RebalancingCosts rebalancingCosts)
         * {
         *  double transactionCost = rebalancingCosts.TotalRebalancingCostInPercentage(state);
         *  if (transactionCost >= 0.01)
         *  {
         *      //Console.WriteLine("transaction cost: {0}", transactionCost);
         *  }
         *  return expectedReturn - transactionCost - (expectedReturn * transactionCost);
         * }
         */
        public static double ExpectedReturn(MarketData state, double[] currentStocksallocation, double[] newStocksAllocation, RebalancingCosts rebalancingCosts)
        {
            var oldPortfolioValue = state.StocksValue(currentStocksallocation);
            var stocksValue       = VectorOp.DotProduct(newStocksAllocation, state.AvgPrices);
            var newValue          = VectorOp.DotProduct(stocksValue, VectorOp.Addition(state.ExpectedReturns, 1.0)).Sum();
            var expectedReturn    = ((newValue + rebalancingCosts.SharesBuySell) / oldPortfolioValue - 1);

            //return NetExpectedReturn(state, expectedReturn, rebalancingCosts);
            return(expectedReturn);
        }
        public static ValuationResult ValuePortfolio(MarketData state, double[] currentStocksAllocation, double[] newStocksAllocation)
        {
            var valueAllocation = VectorOp.DotProduct(newStocksAllocation, state.AvgPrices);
            var weights         = VectorOp.normalize(valueAllocation);

            double[,] xsMatrix = MatrixOp.matrixFromRow(weights);

            RebalancingCosts rebalancingCost   = CostForNewStocksAllocation(state, currentStocksAllocation, newStocksAllocation);
            double           netExpectedReturn = ExpectedReturn(state, currentStocksAllocation, newStocksAllocation, rebalancingCost);
            double           stdDev            =
                Math.Sqrt(
                    MatrixOp.mmult(MatrixOp.mmult(xsMatrix, state.Omega), MatrixOp.transpose(xsMatrix))[0, 0]
                    );


            return(new ValuationResult
            {
                StocksAllocation = newStocksAllocation,
                ExpectedReturn = netExpectedReturn,
                StdDev = stdDev,
                RebalancingCost = rebalancingCost,
            });
        }