static void Main(string[] args) { try { fReturn = PrepareReturnFunction(); fStDev = PrepareStDevFunction(); /**********/ double[] bndl = new double[] { 0, 0, 0, 0, 0 }; double[] bndu = new double[] { +1, +1, +1, +1, +1 }; double[,] c = { { 1, 1, 1, 1, 1, 1 } }; int[] ct = { 0 }; double[] w = new double[5]; alglib.minbleicstate state; alglib.minbleicreport rep; double epsg = 0.000001; double epsf = 0; double epsx = 0; int maxits = 0; for (int i = 0; i < 100; ++i) { GenerateRandomWeights(w); alglib.minbleiccreate(w, out state); alglib.minbleicsetbc(state, bndl, bndu); alglib.minbleicsetlc(state, c, ct); alglib.minbleicsetcond(state, epsg, epsf, epsx, maxits); alglib.minbleicoptimize(state, FunReturn, null, null); alglib.minbleicresults(state, out w, out rep); } double maxstDev = 0.10; TPortfolio bestPortfolio = portfolios.Where(p => p.StDev <= maxstDev).OrderByDescending(x => x.Return).FirstOrDefault(); } catch (Exception ex) { Console.WriteLine(ex.Message); } }
private void FunReturn(double[] weights, ref double func, double[] grad, object obj) { func = fReturn.Evaluate(variables.Values.ToArray(), weights.ToArray()); double stdev = fStDev.Evaluate(variables.Values.ToArray(), weights.ToArray()); TPortfolio newPortfolio = new TPortfolio(); newPortfolio.Weights.AddRange(weights); newPortfolio.Return = func * -1; newPortfolio.StDev = stdev; portfolios.Add(newPortfolio); var gradient = fReturn.Differentiate(variables.Values.ToArray(), weights.ToArray()); for (int g = 0; g < gradient.Count(); ++g) { grad[g] = gradient[g]; } }
public IPortfolioBuilderBuildResult Build(IPortfolioBuilderBuildParams buildParams) { IPortfolioBuilderBuildResult result = null; PrepareStatData(buildParams); fReturn = PrepareReturnFunction(); fStDev = PrepareStDevFunction(); //lower bound is 0 - we cannot have negative weights double[] bndl = new double[buildParams.Instruments.Count]; for (int i = 0; i < buildParams.Instruments.Count; ++i) { string symbol = buildParams.Instruments[i]; IPortfolioBuilderConstraint constr = buildParams.Constraints.FirstOrDefault(x => x.Property == EProtfolioProperty.Instrument && x.Ticker == symbol && (x.Operation == EConstraintOp.Greater || x.Operation == EConstraintOp.GreaterOrEqual || x.Operation == EConstraintOp.Equal)); bndl[i] = constr != null ? (constr.Value >= 0 ? (double)constr.Value : 0) : 0; } //upper bound double[] bndu = new double[buildParams.Instruments.Count]; for (int i = 0; i < buildParams.Instruments.Count; ++i) { string symbol = buildParams.Instruments[i]; IPortfolioBuilderConstraint constr = buildParams.Constraints.FirstOrDefault(x => x.Property == EProtfolioProperty.Instrument && x.Ticker == symbol && (x.Operation == EConstraintOp.Less || x.Operation == EConstraintOp.LessOrEqual || x.Operation == EConstraintOp.Equal)); bndu[i] = constr != null ? (constr.Value >= 0 ? (double)constr.Value : 1) : 1; } // constraining weights' sum to 100% double[,] c = new double[1, buildParams.Instruments.Count + 1]; //{ 1, 1, 1, 1, 1, 1 } for (int i = 0; i < buildParams.Instruments.Count + 1; ++i) { c[0, i] = 1; } int[] ct = { 0 }; // array to hold weights double[] w = new double[buildParams.Instruments.Count]; alglib.minbleicstate state; alglib.minbleicreport rep; double epsg = 0.000001; double epsf = 0; double epsx = 0; int maxits = 0; for (int i = 0; i < buildParams.MaxIterations; ++i) { GenerateRandomWeights(w); alglib.minbleiccreate(w, out state); alglib.minbleicsetbc(state, bndl, bndu); alglib.minbleicsetlc(state, c, ct); alglib.minbleicsetcond(state, epsg, epsf, epsx, maxits); switch (buildParams.OptimizationTarget) { case EProtfolioProperty.Return: alglib.minbleicoptimize(state, FunReturn, null, null); break; default: throw new InvalidOperationException(string.Format("Optimization for {0} is not supported", buildParams.OptimizationTarget.ToString())); } alglib.minbleicresults(state, out w, out rep); } TPortfolio bestPortfolio = null; switch (buildParams.OptimizationTarget) { case EProtfolioProperty.Return: IPortfolioBuilderConstraint stDevConstr = buildParams.Constraints.FirstOrDefault(x => x.Property == EProtfolioProperty.StDev); IEnumerable <TPortfolio> orderedPortfolios = null; switch (buildParams.Goal) { case EOptimizationGoal.Max: orderedPortfolios = portfolios.OrderByDescending(x => x.Return); break; case EOptimizationGoal.Min: orderedPortfolios = portfolios.OrderBy(x => x.Return); break; } if (stDevConstr != null) { switch (stDevConstr.Operation) { case EConstraintOp.Greater: orderedPortfolios = orderedPortfolios.Where(x => x.StDev > (double)stDevConstr.Value); break; case EConstraintOp.Equal: orderedPortfolios = orderedPortfolios.Where(x => Double.Equals(x.StDev, (double)stDevConstr.Value)); break; case EConstraintOp.GreaterOrEqual: orderedPortfolios = orderedPortfolios.Where(x => x.StDev >= (double)stDevConstr.Value); break; case EConstraintOp.Less: orderedPortfolios = orderedPortfolios.Where(x => x.StDev < (double)stDevConstr.Value); break; case EConstraintOp.LessOrEqual: orderedPortfolios = orderedPortfolios.Where(x => x.StDev <= (double)stDevConstr.Value); break; } } bestPortfolio = orderedPortfolios.FirstOrDefault(); break; } // getting result result = new PortfolioBuilderBuildResult(); if (bestPortfolio != null) { result.Success = true; result.Portfolio = new Portfolio(); for (int i = 0; i < bestPortfolio.Weights.Count; ++i) { result.Portfolio.Instruments.Add(buildParams.Instruments[i], Math.Round((decimal)bestPortfolio.Weights[i], 4)); } result.Return = (decimal)bestPortfolio.Return; result.StDev = (decimal)bestPortfolio.StDev; } else { result.Success = false; } return(result); }