1

我正在尝试在 C# 中编写一个 markowitz 优化类,但优化结果不够好。投资组合权重与 matlab 和 excel 的解决方案平均相差 0.2%。我检查了我的协方差矩阵计算和其他计算,发现它们是正确的。有没有办法校准模型的公差或其他方法以获得更好的结果?有我的代码。

    public List<OptimalWeight> CalcOptimalWeights(bool isNegativeAllowed,string method)
    {
        List<OptimalWeight> weightsResult = new List<OptimalWeight>();

        List<List<CovarItem>> covariances = new List<List<CovarItem>>();

        covariances = CalcCovariances();

        int n = this.AssetReturnList.Count();

        SolverContext solver = SolverContext.GetContext();

        Model model = solver.CreateModel();



        if(isNegativeAllowed == false)
        {                
            Decision[] weights = new Decision[n];
            for (int i = 0; i < n; i++)
            {
                model.AddDecision(weights[i] = new Decision(Domain.RealNonnegative, null));
            }

            model.AddConstraint("SumWeights", Model.Sum(weights) == 1);

            if(this.Constraints.Count() == 0)
            {
                if (method == "MinVar")
                {
                    Term portVar = 0.0;

                    for (int i = 0; i < n; i++)
                    {
                        for (int j = 0; j < n; j++)
                        {
                            portVar += weights[j] * covariances[j][i].Covar * weights[i];
                        }
                    }

                    model.AddGoal("MinVarPort", GoalKind.Minimize, portVar);

                    Solution solution = solver.Solve();

                    var report = solution.GetReport();

                    var decisions = solution.Decisions;
                    List<double> d = decisions.Select(x => x.GetDouble()).ToList();

                    for(int i = 0 ; i < n; i++)
                    {
                        weightsResult.Add(new OptimalWeight {AssetId = AssetReturnList[i].AssetId,
                            Symbol = AssetReturnList[i].Symbol,
                            Weight = d[i] });
                    }

                    double pvar = solution.Goals.First().ToDouble();
                }
            }
        }

        return weightsResult;
    }
4

0 回答 0