|   | |||||||||||
| 
 | |||||||||||
| 
 Folio - Examples from 'Getting Started' Description Different versions of a portfolio optimization problem. Basic modelling and solving tasks: 
 
 
 Source Files By clicking on a file name, a preview is opened at the bottom of this page. FolioQP.cs 
// (c) 2023-2025 Fair Isaac Corporation
using System;
using Optimizer.Objects;
using Optimizer;
using static Optimizer.Objects.Utils;
using static System.Linq.Enumerable;
using QuadExpression = Optimizer.Objects.QuadExpression;
namespace XpressExamples
{
    /// <summary>Modeling a small QP problem to perform portfolio optimization.</summary>
    /// <remarks>
    /// <list type='number'>
    /// <item><description>
    ///   QP: minimize variance
    /// </description></item>
    /// <item><description>
    ///   MIQP: limited number of assets
    /// </description></item>
    /// </remarks>
    class FolioQP
    {
        /* Target yield */
        private static readonly int TARGET = 9;
        /* Max. number of different assets */
        private static readonly int MAXNUM = 4;
        /* Number of shares */
        private static readonly int NSHARES = 10;
        /* Number of high-risk shares */
        private static readonly int NRISK = 5;
        /* Number of North-American shares */
        private static readonly int NNA = 4;
        /* Estimated return in investment  */
        private static readonly double[] RET = new double[] { 5, 17, 26, 12, 8, 9, 7, 6, 31, 21 };
        /* High-risk values among shares */
        private static readonly int[] RISK = new int[] { 1, 2, 3, 8, 9 };
        /* Shares issued in N.-America */
        private static readonly int[] NA = new int[] { 0, 1, 2, 3 };
        /* Variance/covariance matrix of estimated returns */
        private static readonly double[,] VAR = new double[,]{
            // trs  haw  thr  tel  brw  hgw  car  bnk  sof  elc
            {0.1, 0,   0,   0,   0,   0,   0,   0,   0,   0}, // treasury
            {0,  19,  -2,   4,   1,   1,   1, 0.5,  10,   5}, // hardware
            {0,  -2,  28,   1,   2,   1,   1,   0,  -2,  -1}, // theater
            {0,   4,   1,  22,   0,   1,   2,   0,   3,   4}, // telecom
            {0,   1,   2,   0,   4,-1.5,  -2,  -1,   1,   1}, // brewery
            {0,   1,   1,   1,-1.5, 3.5,   2, 0.5,   1, 1.5}, // highways
            {0,   1,   1,   2,  -2,   2,   5, 0.5,   1, 2.5}, // cars
            {0, 0.5,   0,   0,  -1, 0.5, 0.5,   1, 0.5, 0.5}, // bank
            {0,  10,  -2,   3,   1,   1,   1, 0.5,  25,   8}, // software
            {0,   5,  -1,   4,   1, 1.5, 2.5, 0.5,   8,  16}  // electronics
        };
        private static void PrintProblemStatus(XpressProblem prob)
        {
            Console.WriteLine("Problem status:");
            Console.WriteLine($"\tSolve status: {prob.SolveStatus}");
            Console.WriteLine($"\tSol status:   {prob.SolStatus}");
        }
        public static void Main(string[] args)
        {
            using (XpressProblem prob = new XpressProblem())
            {
                // Output all messages.
                prob.callbacks.AddMessageCallback(DefaultMessageListener.Console);
                /****VARIABLES****/
                Variable[] frac = prob.AddVariables(NSHARES)
                    /* Fraction of capital used per share */
                    .WithName(i => $"frac_{i}")
                    /* Upper bounds on the investment per share */
                    .WithUB(0.3)
                    .ToArray();
                /**** CONSTRAINTS ****/
                /* Minimum amount of North-American values */
                prob.AddConstraint(Sum(NNA, i => frac[NA[i]]).Geq(0.5).SetName("NA"));
                /* Spend all the capital */
                prob.AddConstraint(Sum(frac).Eq(1.0).SetName("Cap"));
                /* Target yield */
                prob.AddConstraint(ScalarProduct(frac, RET).Geq(TARGET).SetName("TargetYield"));
                /* Objective: minimize mean variance */
                QuadExpression variance = QuadExpression.Create();
                foreach (int s in Range(0, NSHARES))
                    foreach (int t in Range(0, NSHARES))
                        variance.AddTerm(frac[s], frac[t], VAR[s, t]);
                prob.SetObjective(
                    variance,
                    Optimizer.ObjSense.Minimize
                );
                /* Solve */
                prob.Optimize();
                /* Solution printing */
                PrintProblemStatus(prob);
                double[] sol = prob.GetSolution();
                Console.WriteLine($"With a target of {TARGET} minimum variance is {prob.ObjVal}");
                foreach (Variable f in frac)
                {
                    Console.WriteLine(String.Format("{0} : {1:f2}%", f.GetName(), 100.0 * f.GetValue(sol)));
                }
                Variable[] buy = prob.AddVariables(NSHARES)
                    /* Fraction of capital used per share */
                    .WithName(i => $"buy_{i}")
                    .WithType(ColumnType.Binary)
                    .ToArray();
                /* Limit the total number of assets */
                prob.AddConstraint(Sum(buy).Leq(MAXNUM).SetName("MaxAssets"));
                /* Linking the variables */
                /* frac .<= buy */
                prob.AddConstraints(NSHARES,
                    i => frac[i].Leq(buy[i]).SetName($"link_{i}")
                );
                /* Solve */
                prob.Optimize();
                /* Solution printing */
                Console.WriteLine($"With a target of {TARGET} and at most {MAXNUM} assets, minimum variance is {prob.ObjVal}");
                double[] solmip = prob.GetSolution();
                foreach (String v in frac.Zip(buy, (f, b) => String.Format("{0} : {1:f2}% ({2:f1})", f.GetName(), 100.0 * f.GetValue(solmip), b.GetValue(solmip))))
                {
                    Console.WriteLine(v);
                }
            }
        }
    }
}
 | |||||||||||
| © Copyright 2025 Fair Isaac Corporation. |