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; }