public ActionResult Optimize(int id, int minimumRateOfReturn = 0, string date = "")
        {
            Portfolio portfolio = db.Portfolios.Include("Assets.Prices").Where(p => p.ID == id).FirstOrDefault();
            List<Double> variances = new List<double>();

            DateTime startDate;
            if (date == "")
                startDate = portfolio.DefaultStartDate;
            else
                startDate = DateTime.Parse(date);

            PortfolioQuadraticOptimizationService service = new PortfolioQuadraticOptimizationService();

            OptimizationData inputData = new OptimizationData();
            inputData.MinimumReturn = minimumRateOfReturn;
            inputData.Step = 0.0001;

            List<AssetData> assetData = new List<AssetData>();
            List<Asset> assets = portfolio.Assets.ToList();

            double[,] covarianceMatrix = new double[assets.Count, assets.Count];
            double[,] correlationMatrix = new double[assets.Count, assets.Count];

            bool meanRateMethodIsSimple = portfolio.isSimple;

            startDate = portfolio.DefaultStartDate;

            for (int i = 0; i < assets.Count; i++)
            {
                for (int j = 0; j < assets.Count; j++)
                {
                    List<AssetPrice> prices_i = assets[i].Prices.Where(p => p.Date >= startDate.AddDays(1)).ToList();
                    List<AssetPrice> prices_j = assets[j].Prices.Where(p => p.Date >= startDate.AddDays(1)).ToList();
                    double covariance = calculateCovariance(prices_i, assets[i].DailyMeanRate, prices_j, assets[j].DailyMeanRate, meanRateMethodIsSimple);

                    covarianceMatrix[i, j] = covariance;
                }
            }

            foreach (Asset a in portfolio.Assets)
            {
                var aPrices = a.Prices.Where(x => x.Date >= startDate).ToList();

                var covariances = new Dictionary<string, double>();
                foreach (Asset a2 in portfolio.Assets)
                {
                    var a2Prices = a2.Prices.Where(x => x.Date >= startDate).ToList();
                    var aExpectedVal = a.DailyMeanRate;
                    var a2ExpecteVal = a2.DailyMeanRate;
                    covariances.Add(a2.Symbol, calculateCovariance(aPrices, aExpectedVal, a2Prices, a2ExpecteVal, true));
                }

                assetData.Add(new AssetData
                {
                    Symbol = a.Symbol,
                    MeanReturnRate = a.AnnualizedMeanRate,
                    Covariances = covariances
                });
                variances.Add(a.AnnualizedVariance);
            }

            inputData.Stocks = assetData;

            //OptimizationResult result = service.OptimizePortfolioAllocation(inputData);

            var request = WebRequest.Create("http://optimization.andrewgaspar.com/api/optimize");
            request.ContentType = "application/json";
            request.Method = "POST";
            StreamWriter writer = new StreamWriter(request.GetRequestStream());
            string json = JsonConvert.SerializeObject(inputData);
            writer.Write(json);
            writer.Close();

            OptimizationResult result = new OptimizationResult();

            try
            {
                using (var response = request.GetResponse())
                {
                    request.GetRequestStream().Close();
                    if (response != null)
                    {
                        using (var answerReader = new StreamReader(response.GetResponseStream()))
                        {
                            var readString = answerReader.ReadToEnd();
                            result = JsonConvert.DeserializeObject<OptimizationResult>(readString);
                        }
                    }
                }
            }
            catch (WebException e)
            {
                return RedirectToAction("Index");
            }

            var request2 = WebRequest.Create("http://optimization.andrewgaspar.com/api/frontier");
            request2.ContentType = "application/json";
            request2.Method = "POST";
            writer = new StreamWriter(request2.GetRequestStream());
            json = JsonConvert.SerializeObject(inputData);
            writer.Write(json);
            writer.Close();

            OptimizationResult[] efficientFrontier = null;
            try
            {
                using (var response = request2.GetResponse())
                {
                    request2.GetRequestStream().Close();
                    if (response != null)
                    {
                        using (var answerReader = new StreamReader(response.GetResponseStream()))
                        {
                            var readString = answerReader.ReadToEnd();
                            efficientFrontier = JsonConvert.DeserializeObject<OptimizationResult[]>(readString);
                        }
                    }
                }
            }
            catch (WebException e)
            {
                efficientFrontier = new OptimizationResult[0];
            }

            foreach (var solution in efficientFrontier)
            {
                double portfolioVariance = 0;
                for (int i = 0; i < solution.Results.Count; i++)
                {
                    for (int j = 0; j < solution.Results.Count; j++)
                    {
                        portfolioVariance += solution.Results.ElementAt(i).Allocation * solution.Results.ElementAt(j).Allocation * covarianceMatrix[i, j];
                    }
                }
                solution.StandardDeviation = Math.Sqrt(portfolioVariance * 252);
            }

            ViewBag.Results = result.Results.ToDictionary(r => r.Symbol, r => r.Allocation);
            ViewBag.Feasible = result.Feasible;
            ViewBag.Optimal = result.Optimal;
            ViewBag.ExpectedRateOfReturn = result.ExpectedReturn;
            ViewBag.EfficientFrontier = efficientFrontier;

            return View();
        }
        public OptimizationResult OptimizePortfolioAllocation(OptimizationData data)
        {
            int assetCount = data.Stocks.Count;

            InteriorPointSolver solver = new InteriorPointSolver();
            int[] allocations = new int[assetCount];

            for (int i = 0; i < assetCount; i++)
            {
                solver.AddVariable(data.Stocks[i].Symbol, out allocations[i]);
                if (data.Stocks[i].Symbol == "SPY")
                    solver.SetBounds(allocations[i], 0, 0);
                else
                    solver.SetBounds(allocations[i], 0, 1);
            }

            int expectedRateOfReturn;
            solver.AddRow("expectedRateOfReturn", out expectedRateOfReturn);
            solver.SetBounds(expectedRateOfReturn, data.MinimumReturn, double.PositiveInfinity);

            int unity;
            solver.AddRow("Investments sum to one", out unity);
            solver.SetBounds(unity, 1, 1);

            for (int i = 0; i < assetCount; i++)
            {
                solver.SetCoefficient(expectedRateOfReturn, allocations[i], data.Stocks[i].MeanReturnRate);
                solver.SetCoefficient(unity, allocations[i], 1);
            }

            int variance;
            solver.AddRow("variance", out variance);
            for (int i = 0; i < assetCount; i++)
            {
                for (int j = 0; j < assetCount; j++)
                {
                    solver.SetCoefficient(variance, data.Stocks[i].Covariances[data.Stocks[j].Symbol], allocations[i], allocations[j]);
                }
            }

            solver.AddGoal(variance, 0, true);

            InteriorPointSolverParams lpParams = new InteriorPointSolverParams();

            solver.Solve(lpParams);

            bool optimal = false;
            bool feasible = false;
            if (solver.Result == LinearResult.Optimal)
            {
                optimal = feasible = true;
            }
            else if (solver.Result == LinearResult.Feasible)
            {
                optimal = false;
                feasible = true;
            }

            List<AssetResult> assetResults = new List<AssetResult>();
            for (int i = 0; i < assetCount; i++)
            {
                assetResults.Add(new AssetResult
                {
                    Symbol = data.Stocks[i].Symbol,
                    Allocation = (double)solver.GetValue(allocations[i])
                });
            }

            OptimizationResult result = new OptimizationResult
            {
                Optimal = optimal,
                Feasible = feasible,
                ExpectedReturn = (double)solver.GetValue(expectedRateOfReturn),
                Results = assetResults
            };

            return result;
        }