static void CreateSolver() { StaticReset(); solver = new InteriorPointSolver(); solver.AddRow("goal", out goal); solver.AddGoal(goal, 0, true); //minimizing the goal }
static void StaticReset() { #if SIMPLESOLVER solver = null; goal = 0; numOfRows = -1; #else // SIMPLESOLVER solution = null; Context.ClearModel(); model = Context.CreateModel(); Constraints.Clear(); goalTerm = null; solution = null; goal = null; #endif // SIMPLESOLVER }
/// <summary> Build and run the risk model in multiple iterations. /// Put the results into the plan. /// </summary> public bool BuildRiskModel(DataTable plan, int iterations) { int m = _stockNames.Length; for (int reqIx = 0; reqIx < iterations; reqIx++) { InteriorPointSolver solver = new InteriorPointSolver(); int[] allocations = new int[m]; for (int invest = 0; invest < m; invest++) { string name = _stockNames[invest]; solver.AddVariable(name, out allocations[invest]); solver.SetBounds(allocations[invest], 0, 1); } int expectedReturn; solver.AddRow("expectedReturn", out expectedReturn); // expected return must beat the minimum asked solver.SetBounds(expectedReturn, (double)plan.Rows[reqIx]["minimum"], double.PositiveInfinity); int unity; solver.AddRow("Investments sum to one", out unity); solver.SetBounds(unity, 1, 1); // expected return is a weighted linear combination of investments. // unity is a simple sum of the investments for (int invest = m; 0 <= --invest; ) { solver.SetCoefficient(expectedReturn, allocations[invest], _means[invest]); solver.SetCoefficient(unity, allocations[invest], 1); } // The variance of the result is a quadratic combination of the covariants and allocations. int variance; solver.AddRow("variance", out variance); for (int invest = m; 0 <= --invest; ) { for (int jnvest = m; 0 <= --jnvest; ) { solver.SetCoefficient(variance, _covariance[invest, jnvest], allocations[invest], allocations[jnvest]); } } // the goal is to minimize the variance, given the linear lower bound on asked return. solver.AddGoal(variance, 0, true); InteriorPointSolverParams lpParams = new InteriorPointSolverParams(); solver.Solve(lpParams); if (solver.Result != LinearResult.Optimal) return false; for (int invest = m; 0 <= --invest; ) { plan.Rows[reqIx][_stockNames[invest]] = (double)solver.GetValue(allocations[invest]); } plan.Rows[reqIx]["actual"] = (double)solver.GetValue(expectedReturn); plan.Rows[reqIx]["Std.Dev."] = Math.Sqrt((double)solver.Statistics.Primal); plan.Rows[reqIx]["variance"] = (double)solver.GetValue(variance); } return true; }
public void SolveQuadratic(RvolSolveModel model_) { int m = model_.CurrencyLines.Length; //int iterations = 1; //for (int reqIx = 0; reqIx < iterations; ++reqIx) { InteriorPointSolver solver = new InteriorPointSolver(); int[] allocations = new int[m]; for (int invest = 0; invest < m; ++invest) { string name = model_.CurrencyLines[invest].Ccy.Code; solver.AddVariable(name, out allocations[invest]); solver.SetBounds(allocations[invest], model_.CurrencyLines[invest].MinWeight, model_.CurrencyLines[invest].MaxWeight); } int expectedReturn; solver.AddRow("expectedReturn", out expectedReturn); //int sumZero; //solver.AddRow("sumZero", out sumZero); for (int invest = 0; invest < m; ++invest) { solver.SetCoefficient(expectedReturn, allocations[invest], model_.CurrencyLines[invest].ExpectedReturn); //solver.SetCoefficient(sumZero, allocations[invest], 0); } int variance; solver.AddRow("variance", out variance); for (int invest = 0; invest < m; ++invest) { for (int jnvest = 0; jnvest < m; ++jnvest) { solver.SetCoefficient(variance, model_.Covar.Data[invest, jnvest], allocations[invest], allocations[jnvest]); } } var varianceTarget = Math.Pow(model_.TargetVol, 2d); solver.SetBounds(variance, double.NegativeInfinity, varianceTarget); // max expected return solver.AddGoal(expectedReturn, 1, false); InteriorPointSolverParams lpParams = new InteriorPointSolverParams(); solver.Solve(lpParams); //if (solver.Result != LinearResult.Optimal) for (int invest = m; 0 <= --invest;) { model_.CurrencyLines[invest].Weight = (double) solver.GetValue(allocations[invest]); } } }
public bool ModeloRiesgo(DataTable plan, int iterations) { int m = Companias.Length; for (int reqIx = 0; reqIx < iterations; reqIx++) { InteriorPointSolver solver = new InteriorPointSolver(); int[] asignaciones = new int[m]; for (int i = 0; i < m; i++) { solver.AddVariable(Companias[i], out asignaciones[i]); solver.SetBounds(asignaciones[i], 0, 1); } int rentabilidad; solver.AddRow("rentabilidad", out rentabilidad); // La rentabilidad debe superar el minimo pedido solver.SetBounds(rentabilidad, (double)plan.Rows[reqIx]["minimum"], double.PositiveInfinity); int unity; solver.AddRow("Invertir la suma a", out unity); solver.SetBounds(unity, 1, 1); // El rendimiento esperado es una combinacion lineal ponderada de las inversiones // unity = suma de inversiones for (int invest = m; 0 <= --invest;) { solver.SetCoefficient(rentabilidad, asignaciones[invest], media[invest]); solver.SetCoefficient(unity, asignaciones[invest], 1); } // The variance of the result is a quadratic combination of the covariants and allocations. int varianza; solver.AddRow("varianza", out varianza); for (int invest = m; 0 <= --invest;) { for (int jnvest = m; 0 <= --jnvest;) { solver.SetCoefficient(varianza, covarianza[invest, jnvest], asignaciones[invest], asignaciones[jnvest]); } } // the goal is to minimize the variance, given the linear lower bound on asked return. solver.AddGoal(varianza, 0, true); InteriorPointSolverParams lpParams = new InteriorPointSolverParams(); solver.Solve(lpParams); if (solver.Result != LinearResult.Optimal) { return(false); } for (int invest = m; 0 <= --invest;) { plan.Rows[reqIx][Companias[invest]] = (double)solver.GetValue(asignaciones[invest]); } plan.Rows[reqIx]["actual"] = (double)solver.GetValue(rentabilidad); plan.Rows[reqIx]["Std.Dev."] = Math.Sqrt((double)solver.Statistics.Primal); } return(true); }
static void Main(string[] args) { var wTarget = (new[] { Rational.Get(6, 10), Rational.Get(8, 10), Rational.Get(-5,10) }); var C = Rational.Get(10,1); var w0Target = Rational.Get(1,10); var rightness = 0.0; var successful = 0.0; Datum[] classified={}; var dump = new Rational[TRIALS,TRIALS]; for (int experiment = 0; experiment < EXPERIMENTS; experiment++) { try { classified = Generate(TRIALS, w0Target, wTarget); var testData = Generate(TRIALS * 10, w0Target, wTarget); var solver = new InteriorPointSolver(); Func<Rational[], Rational[], Rational> kernel = Dot; int goal; solver.AddRow("dual", out goal); solver.AddGoal(goal, 0, false);//false to maximize //make alphas var alphas = classified.Select((_, i) => { int tmp; solver.AddVariable("alpha" + i, out tmp); solver.SetBounds(tmp, Rational.Zero, C); return tmp; }).ToArray(); int sumConstraint; solver.AddRow("sumConstraint", out sumConstraint); //solver.SetBounds(sumConstraint, Rational.Zero, Rational.Zero); //TODO: maybe I'm running into numeric issues? solver.SetBounds(sumConstraint, Rational.Get(-1, THRESH), Rational.Get(1, THRESH)); for (int i = 0; i < classified.Length; i++) { //sum_n (alpha_n*y_n) == 0 solver.SetCoefficient(sumConstraint, alphas[i], classified[i].y); solver.SetCoefficient(goal, alphas[i], 1); //the sum_n (alpha_n) part of the lagrangian ////quadratic terms. sometimes not convex, and I don't know why for (int j = 0; j <= i; j++) { // coef = y_i * y_j * Kernel(x_i, x_j). Note that the diagonal is half: the other terms appear twice and are thus doubled var coef = (i == j ? -0.5 : -1.0) * classified[i].y * classified[j].y * kernel(classified[i].x, classified[j].x); solver.SetCoefficient(goal, coef, alphas[i], alphas[j]); dump[i, j] = coef; dump[j, i] = coef; } //This gives better results, but it isn't actually right. :-( //for (int j = 0; j < classified.Length; j++) //{ // // coef = y_i * y_j * Kernel(x_i, x_j). Note that the diagonal is half: the other terms appear twice and are thus doubled // var coef = -0.5 * classified[i].y * classified[j].y * kernel(classified[i].x, classified[j].x); // solver.SetCoefficient(goal, coef, alphas[i], alphas[j]); //} } //now solve solver.Solve(new InteriorPointSolverParams()); var alphaVals = Enumerable.Range(0, classified.Length) .Select(i => solver.GetValue(alphas[i])) //using alphas[i] instead of 1..N here .ToArray(); //Console.WriteLine("goal={0}", solver.GetValue(0)); //get the SVs var maxAlpha = alphaVals.Max(); var threshold = maxAlpha / THRESH; var sVecs = alphaVals.Where(a => a > threshold) //.Where(a => a + threshold < C) //This may be wrong... yep .Select((a, i) => new SVInfo { y = classified[i].y, x = classified[i].x, alpha = a }) .ToArray(); //w0, aka b var w0s = sVecs.Where(sv => sv.alpha + threshold < C) //this must not be right? .Select(sv1 => //note that the inner loop gets alphas == C. Not sure if that's right. sv1.y - sVecs.Select(sv2 => sv2.alpha * sv2.y * kernel(sv1.x, sv2.x)).Aggregate((acc, r) => acc + r) ).ToArray(); var w0 = w0s.OrderBy(lf => lf.ToDouble()).ToArray()[w0s.Length / 2]; //too widely dispersed... median here //so what does w look like here...? List<Rational> wTmp = (new List<Rational> { w0 }); wTmp.AddRange( sVecs.Select(sv => { var tmp = sv.alpha * sv.y; return sv.x.Select(x => x * tmp); }).Aggregate((acc, xs) => acc.Zip(xs, (a, b) => a + b))); var wOut = Norm(wTmp.ToArray()); var classifiedTests = Classify(sVecs, testData, kernel, w0);//They filter out things athat are = C //var classifiedTests = Classify(sVecs.Where(sv => sv.alpha + threshold < C).ToArray(), testData, kernel, w0); var right = 100.0 * (classifiedTests.Count(b => b)) / (classifiedTests.Length); Console.Write("."); //Console.WriteLine("Correctly classified {0}%", right); rightness += right; successful += 1.0; } catch (Exception ex) { var sb = new StringBuilder(); for (int i = 0; i < TRIALS; i++) { for (int j = 0; j < TRIALS-1; j++) { sb.Append(dump[i, j]); sb.Append(","); } sb.AppendLine(dump[i, TRIALS - 1].ToString()); } sb.AppendLine(); foreach (var item in classified) sb.AppendLine(item.ToString()); var p = Path.Combine(Environment.GetFolderPath( Environment.SpecialFolder.CommonApplicationData), "SV2", DateTime.Now.ToString("yyyyMMdd-HHmmss-") + experiment + ".csv"); Directory.CreateDirectory(Path.GetDirectoryName(p)); Console.WriteLine(p); using (var sr = new StreamWriter(p)) sr.Write(sb.ToString()); } } Console.WriteLine("Total rightness {0}%", rightness/successful); Console.ReadKey(true); }
static void Main(string[] args) { var wTarget = (new[] { Rational.Get(6, 10), Rational.Get(8, 10), Rational.Get(-5, 10) }); var C = Rational.Get(10, 1); var w0Target = Rational.Get(1, 10); var rightness = 0.0; var successful = 0.0; Datum[] classified = {}; var dump = new Rational[TRIALS, TRIALS]; for (int experiment = 0; experiment < EXPERIMENTS; experiment++) { try { classified = Generate(TRIALS, w0Target, wTarget); var testData = Generate(TRIALS * 10, w0Target, wTarget); var solver = new InteriorPointSolver(); Func <Rational[], Rational[], Rational> kernel = Dot; int goal; solver.AddRow("dual", out goal); solver.AddGoal(goal, 0, false);//false to maximize //make alphas var alphas = classified.Select((_, i) => { int tmp; solver.AddVariable("alpha" + i, out tmp); solver.SetBounds(tmp, Rational.Zero, C); return(tmp); }).ToArray(); int sumConstraint; solver.AddRow("sumConstraint", out sumConstraint); //solver.SetBounds(sumConstraint, Rational.Zero, Rational.Zero); //TODO: maybe I'm running into numeric issues? solver.SetBounds(sumConstraint, Rational.Get(-1, THRESH), Rational.Get(1, THRESH)); for (int i = 0; i < classified.Length; i++) { //sum_n (alpha_n*y_n) == 0 solver.SetCoefficient(sumConstraint, alphas[i], classified[i].y); solver.SetCoefficient(goal, alphas[i], 1); //the sum_n (alpha_n) part of the lagrangian ////quadratic terms. sometimes not convex, and I don't know why for (int j = 0; j <= i; j++) { // coef = y_i * y_j * Kernel(x_i, x_j). Note that the diagonal is half: the other terms appear twice and are thus doubled var coef = (i == j ? -0.5 : -1.0) * classified[i].y * classified[j].y * kernel(classified[i].x, classified[j].x); solver.SetCoefficient(goal, coef, alphas[i], alphas[j]); dump[i, j] = coef; dump[j, i] = coef; } //This gives better results, but it isn't actually right. :-( //for (int j = 0; j < classified.Length; j++) //{ // // coef = y_i * y_j * Kernel(x_i, x_j). Note that the diagonal is half: the other terms appear twice and are thus doubled // var coef = -0.5 * classified[i].y * classified[j].y * kernel(classified[i].x, classified[j].x); // solver.SetCoefficient(goal, coef, alphas[i], alphas[j]); //} } //now solve solver.Solve(new InteriorPointSolverParams()); var alphaVals = Enumerable.Range(0, classified.Length) .Select(i => solver.GetValue(alphas[i])) //using alphas[i] instead of 1..N here .ToArray(); //Console.WriteLine("goal={0}", solver.GetValue(0)); //get the SVs var maxAlpha = alphaVals.Max(); var threshold = maxAlpha / THRESH; var sVecs = alphaVals.Where(a => a > threshold) //.Where(a => a + threshold < C) //This may be wrong... yep .Select((a, i) => new SVInfo { y = classified[i].y, x = classified[i].x, alpha = a }) .ToArray(); //w0, aka b var w0s = sVecs.Where(sv => sv.alpha + threshold < C) //this must not be right? .Select(sv1 => //note that the inner loop gets alphas == C. Not sure if that's right. sv1.y - sVecs.Select(sv2 => sv2.alpha * sv2.y * kernel(sv1.x, sv2.x)).Aggregate((acc, r) => acc + r) ).ToArray(); var w0 = w0s.OrderBy(lf => lf.ToDouble()).ToArray()[w0s.Length / 2]; //too widely dispersed... median here //so what does w look like here...? List <Rational> wTmp = (new List <Rational> { w0 }); wTmp.AddRange( sVecs.Select(sv => { var tmp = sv.alpha * sv.y; return(sv.x.Select(x => x * tmp)); }).Aggregate((acc, xs) => acc.Zip(xs, (a, b) => a + b))); var wOut = Norm(wTmp.ToArray()); var classifiedTests = Classify(sVecs, testData, kernel, w0);//They filter out things athat are = C //var classifiedTests = Classify(sVecs.Where(sv => sv.alpha + threshold < C).ToArray(), testData, kernel, w0); var right = 100.0 * (classifiedTests.Count(b => b)) / (classifiedTests.Length); Console.Write("."); //Console.WriteLine("Correctly classified {0}%", right); rightness += right; successful += 1.0; } catch (Exception ex) { var sb = new StringBuilder(); for (int i = 0; i < TRIALS; i++) { for (int j = 0; j < TRIALS - 1; j++) { sb.Append(dump[i, j]); sb.Append(","); } sb.AppendLine(dump[i, TRIALS - 1].ToString()); } sb.AppendLine(); foreach (var item in classified) { sb.AppendLine(item.ToString()); } var p = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "SV2", DateTime.Now.ToString("yyyyMMdd-HHmmss-") + experiment + ".csv"); Directory.CreateDirectory(Path.GetDirectoryName(p)); Console.WriteLine(p); using (var sr = new StreamWriter(p)) sr.Write(sb.ToString()); } } Console.WriteLine("Total rightness {0}%", rightness / successful); Console.ReadKey(true); }
public bool BuildRiskModel() { int m = portfolio.NumPositions; InteriorPointSolver solver = new InteriorPointSolver(); int[] allocations = new int[m]; int counter = 0; foreach (Position p in portfolio.Positions.Values) { solver.AddVariable(p.Symbol, out allocations[counter]); solver.SetBounds(allocations[counter], -1, 1); counter++; } int expectedReturn; solver.AddRow("expectedReturn", out expectedReturn); // expected return must beat the minimum asked solver.SetBounds(expectedReturn, minReturn, double.PositiveInfinity); int unity; solver.AddRow("Investments sum to one", out unity); solver.SetBounds(unity, -1, 1); // expected return is a weighted linear combination of investments. // unity is a simple sum of the investments for (int invest = m; 0 <= --invest;) { solver.SetCoefficient(expectedReturn, allocations[invest], returns[invest]); solver.SetCoefficient(unity, allocations[invest], 1); } // The variance of the result is a quadratic combination of the covariants and allocations. int variance; solver.AddRow("variance", out variance); for (int invest = m; 0 <= --invest;) { for (int jnvest = m; 0 <= --jnvest;) { solver.SetCoefficient(variance, covariance[invest, jnvest], allocations[invest], allocations[jnvest]); } } // the goal is to minimize the variance, given the linear lower bound on asked return. solver.AddGoal(variance, 0, true); InteriorPointSolverParams lpParams = new InteriorPointSolverParams(); solver.Solve(lpParams); if (solver.Result != LinearResult.Optimal) return false; for (int i = 0; i < m; i++) { } counter = 0; foreach (Position p in portfolio.Positions.Values) { Console.Write(p.Symbol + " " + (double)solver.GetValue(allocations[counter++]) + " "); Console.WriteLine(); } Console.WriteLine((double) solver.GetValue(expectedReturn) + " " + Math.Sqrt((double) solver.Statistics.Primal) + "\n"); return true; }
public bool BuildRiskModel() { int m = portfolio.NumPositions; InteriorPointSolver solver = new InteriorPointSolver(); int[] allocations = new int[m]; int counter = 0; foreach (Position p in portfolio.Positions.Values) { solver.AddVariable(p.Symbol, out allocations[counter]); solver.SetBounds(allocations[counter], -1, 1); counter++; } int expectedReturn; solver.AddRow("expectedReturn", out expectedReturn); // expected return must beat the minimum asked solver.SetBounds(expectedReturn, minReturn, double.PositiveInfinity); int unity; solver.AddRow("Investments sum to one", out unity); solver.SetBounds(unity, -1, 1); // expected return is a weighted linear combination of investments. // unity is a simple sum of the investments for (int invest = m; 0 <= --invest;) { solver.SetCoefficient(expectedReturn, allocations[invest], returns[invest]); solver.SetCoefficient(unity, allocations[invest], 1); } // The variance of the result is a quadratic combination of the covariants and allocations. int variance; solver.AddRow("variance", out variance); for (int invest = m; 0 <= --invest;) { for (int jnvest = m; 0 <= --jnvest;) { solver.SetCoefficient(variance, covariance[invest, jnvest], allocations[invest], allocations[jnvest]); } } // the goal is to minimize the variance, given the linear lower bound on asked return. solver.AddGoal(variance, 0, true); InteriorPointSolverParams lpParams = new InteriorPointSolverParams(); solver.Solve(lpParams); if (solver.Result != LinearResult.Optimal) { return(false); } for (int i = 0; i < m; i++) { } counter = 0; foreach (Position p in portfolio.Positions.Values) { Console.Write(p.Symbol + " " + (double)solver.GetValue(allocations[counter++]) + " "); Console.WriteLine(); } Console.WriteLine((double)solver.GetValue(expectedReturn) + " " + Math.Sqrt((double)solver.Statistics.Primal) + "\n"); return(true); }
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; }