Create the Python Project
application.py
to contain the optimization problem. To begin the process, complete the following steps:
- Open Xpress Workbench.
- The landing page is displayed. Select CREATE INSIGHT (PYTHON) PROJECT.
- Select a folder in which to store the project.
A new template project is created containing client_resources, model_resources, and python_source folders, as well as an application.xml file.
- Click python_source folder as
application.py
to overwrite the existing file. . Save the new file in the - We shall start by importing all the libraries that will be used in this tutorial.
import xpressinsight as xi import xpress as xp import pandas as pd import sys
- Below that block, enter the following:
This section declares the parameters that will be used as constraints when performing optimization. The specified default values can be changed for every model execution without any need to edit the model source.@xi.AppConfig(name="Portfolio Optimization", version=xi.AppVersion(1, 0, 0), raise_attach_exceptions=True) class InsightApp(xi.AppBase): # Input entities MaxHighRisk: xi.types.Scalar(default=0.33, alias="Maximum investment into high-risk values") MaxPerShare: xi.types.Scalar(default=0.25, alias="Maximum investment per share") MinNorthAmerica: xi.types.Scalar(default=0.45, alias="Minimum investment into North-American values") ShareIds: xi.types.Index(dtype=xi.string, alias="Shares")
- Below the constraints block, enter the following declarations:
This section of code declares the entities that will be used to store the different data categories.# Input and result entities indexed over ShareIds Shares: xi.types.DataFrame(index="ShareIds", columns=[ xi.Column("Return", dtype=xi.real, format="$ 0.00", alias="Expected Return on Investment"), xi.Column("HighRisk", dtype=xi.boolean, alias="High-risk value"), xi.Column("NorthAmerica", dtype=xi.boolean, alias="Issued in North America"), xi.Column("fraction", dtype=xi.real, format="0.0%", alias="Fraction used", manage=xi.Manage.RESULT) ])
- Below the inputs block, enter the following code snippet:
This section declares and names the data series that will be used to hold the result.# Result entities TotalReturn: xi.types.Scalar(dtype=xi.real, alias="Total expected return on investment", manage=xi.Manage.RESULT) SummaryIds: xi.types.Index(dtype=xi.string, alias="Summary", manage=xi.Manage.RESULT) SummaryValues: xi.types.Series(index="SummaryIds", dtype=xi.real, manage=xi.Manage.RESULT)
- The final declaration specifies the source data file.
# Constant class attribute DATAFILE = "shares.csv"
- Below the result line, add the two required mode functions-These must be included in any Python Insight file.
First declare the
LOAD
mode function.@xi.ExecModeLoad(descr="Load input data and initialize all input entities.") def load(self): print("Loading data.") self.Shares = pd.read_csv(InsightApp.DATAFILE, index_col=['ShareIds'], squeeze=True) self.ShareIds = self.Shares.index print("Loading finished.")
- The largest block of code is the
RUN
mode.@xi.ExecModeRun(descr="Solve problem and initialize all result entities.") def run(self): print('Starting optimization.') # Create Xpress problem and variables p = xp.problem("portfolio") self.Shares['fractionVar'] = \ pd.Series(p.addVariables(self.ShareIds, vartype=xp.continuous, name='fractionVar')) # Objective: expected total return objective = xp.Sum(self.Shares.Return * self.Shares.fractionVar) p.setObjective(objective, sense=xp.maximize) # Limit the percentage of high-risk values limit_high_risk = \ xp.Sum(self.Shares.loc[self.Shares.HighRisk, 'fractionVar']) \ <= self.MaxHighRisk p.addConstraint(limit_high_risk) # Minimum amount of North-American values limit_north_america = \ xp.Sum(self.Shares.loc[self.Shares.NorthAmerica, 'fractionVar']) \ >= self.MinNorthAmerica p.addConstraint(limit_north_america) # Spend all the capital p.addConstraint(xp.Sum(self.Shares.fractionVar) == 1) # Upper bounds on the investment per share p.addConstraint(share.fractionVar <= self.MaxPerShare for share_id, share in self.Shares.iterrows()) # Solve optimization problem p.solve() # Save results and key indicator values for GUI display self.Shares["fraction"] = pd.Series(p.getSolution(), index=self.ShareIds) self.TotalReturn = p.getObjVal() self.SummaryValues = pd.Series({ "Expected total return": self.TotalReturn, "Total high risk shares": limit_high_risk.ub - p.getSlack(limit_high_risk), "Total North-American": limit_north_america.lb - p.getSlack(limit_north_america), "Largest position": self.Shares.fraction.max() }) self.SummaryIds = self.SummaryValues.index print('\n', self.SummaryValues, '\n', sep='') print('Optimization finished.')
- Finally, at the end of the file, add the main class declaration that specifies which instructions Python should initially run.
if __name__ == "__main__": app = xi.create_app(InsightApp) sys.exit(app.call_exec_modes(["LOAD", "RUN"]))
- Create a new file. In Xpress Workbench, click , or use the keyboard shortcut Ctrl-N. Name the new file
shares.csv
. Save the file to themodel_resources
folder. - Double click
shares.csv
to open it in Xpress Workbench. Copy and paste the following text into the file, then save and close it.ShareIds,Return,HighRisk,NorthAmerica Bank,6.0,False,False Brewery,8.0,False,False Cars,7.0,False,False Electronics,21.0,True,False Hardware,17.0,True,True Highways,9.0,False,False Software,31.0,True,False Telecom,12.0,True,True Theater,26.0,True,True Treasury,5.0,False,True
- Now you can publish the application to Xpress Insight.
© 2001-2025 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.