Axioma Portfolio™ 2020 R2 -- User's Guide
A guide to using Axioma Portfolio
Java API for portfolio optimization.
Axioma Portfolio™ 2020 R2 -- User's Guide : A guide to using Axioma Portfolio Java API for portfolio optimization.
by Axioma, Inc.
Published July 2020
Axioma Portfolio Overview
Copyright © 2020 Axioma, Inc.
Axioma Portfolio™ is a trademark of Axioma, Inc. All other company, organization, product, or service names referenced herein may be trademarks of
their respective owners.
Axioma Portfolio
Axioma Portfolio™ 2020 R2 -- User's Guide
Contents
1. Preface
1
What is Axioma Portfolio?
1
Prerequisites
1
Notation and Naming Conventions
1
Technical Support
2
Acknowledgements
2
What's New in Axioma Portfolio Java API 2020 R2
2
Refined Analytics and Reportings
2
General Enhancements
2
Infrastructure
3
2. A Quick-start to Using the Axioma Portfolio API
4
A Basic Axioma Portfolio Application
4
Opening a Workspace file
6
Creating a Workspace
7
Building the Model
7
Solving a Problem
14
Inspecting the Solution
15
Installing and Running Axioma Portfolio
16
System Requirements
16
Unzipping the Distribution and Installing Axioma Portfolio Java API on Windows
17
License Files
18
Compiling and setting path for Example Programs
18
Running Axioma Portfolio
18
Unzipping the Distribution and Installing Axioma Portfolio Java API on Linux 18
Troubleshooting Installation Issues
20
3. Portfolio Optimization Basics
22
Basic Modeling Frameworks
22
Axioma Portfolio Features
23
Business Rules
24
Business Goals
26
Business Analysis
26
4. Axioma Portfolio Building Blocks
28
Object Model
28
The Workspace
28
Axioma Portfolio™ 2020 R2 -- User's Guide | Page iii
Axioma Portfolio
Axioma Portfolio™ 2020 R2 -- User's Guide
The Asset Class
Simple Assets
Composite Assets
The Account Class
Account Holdings
The Reference Size
The Budget Size
Risk Models
The FactorRiskModel Class
The DenseRiskModel Class
The Goldman Sachs® Shortfall Model Class
The Strategy Class
The Rebalancing Class
Round Lotting
Asset Groups
Benchmarks
Metagroups
Additional Rebalancing Methods
Setting up API
Creating a workspace connected to database
5. Bounds, Constraints, and Business Rules
The ConstraintProperties and the Constraint.Scope Classes
Constraint Scopes and Units
Collective Constraints
Budget Constraint
After Transaction Cost Budget Constraint
Limit Issuer Holding Constraints
Limit Issuer Exposure Contraints
Tax Constraints
Selection Constraints
Bounds on Holdings
Limiting the Number of Names Held
Limiting Portfolio Risk
Bounds on Transactions
Limiting the Deviation from a Benchmark
29
29
30
30
31
32
32
33
33
35
36
37
37
38
39
40
41
42
42
42
46
46
47
48
48
49
49
50
50
50
52
57
59
61
63
Axioma Portfolio™ 2020 R2 -- User's Guide | Page iv
Axioma Portfolio
Axioma Portfolio™ 2020 R2 -- User's Guide
Limiting Relative Marginal Contribution to Risk
Using the LimitWeightedAvgConstraint Class
Robust Linear Constraint
Goldman Sachs Shortfall Constraint
Limit Short Sell Constraint
Soft Constraints
6. The Objective Function
The Objective
Objective Terms
Expected Return
Robust Term
Transaction Costs
Market Impact
Goldman Sachs Shortfall
Short Sell
Risk
Tax Objective
Multi-Criteria Optimization
LINEAR_TRANSACTION_COST
LINEAR_BUY
LINEAR_SELL
7. Constraint Attribution
Decomposition
Decomposition Base
Decomposition Group
Decomposition Results
8. Solving with Axioma Portfolio
Rebalancing Solution
Optimization Parameters
9. Inspecting the Solution
Portfolio Analysis Functions
Expected Return
Implied Alphas
Implied Betas
Risk Analysis
63
64
67
68
68
68
71
71
71
72
72
73
77
78
79
79
80
80
81
81
81
82
82
82
82
83
84
84
84
86
87
87
87
88
88
Axioma Portfolio™ 2020 R2 -- User's Guide | Page v
Axioma Portfolio
Axioma Portfolio™ 2020 R2 -- User's Guide
Transactions
10. Tax-Aware Optimization
Overview
Problem Specification
Tax Objective
Tax Constraint
Optimizing
Viewing the Solution
11. Multi-Portfolio Optimization
Overview
Multiple Account
Multiple Account Strategy
Multiple Account Rebalancing
Multiple Account Rebalancing Solution
12. Automation Utilities
Creating Frontiers
Batch Jobs
Reports
13. Error Handling
Return Codes
Exceptions
log4j2 Settings
14. Troubleshooting
Tips
A. Example 1: Basic use of API
Glossary
89
90
90
90
93
94
95
95
97
97
97
98
98
99
100
100
101
103
105
105
105
106
107
107
108
114
Axioma Portfolio™ 2020 R2 -- User's Guide | Page vi
Axioma Portfolio
Axioma Portfolio™ 2020 R2 -- User's Guide
List of Tables
2.1. Asset Data
2.2. Exposure Matrix and Specific Risks
2.3. Factor Covariance Matrix
2.4. Troubleshooting Installation Issues
5
5
6
20
Axioma Portfolio™ 2020 R2 -- User's Guide | Page vii
Axioma Portfolio
Axioma Portfolio™ 2020 R2 -- User's Guide
Axioma Portfolio™ 2020 R2 -- User's Guide | Page viii
Axioma Portfolio
Chapter 1. Preface
Chapter 1. Preface
This user's guide is intended to help you get started using Axioma Portfolio quickly so that you can take advantage of
its many features immediately. Axioma Portfolio is a flexible, object-oriented Java set of libraries providing powerful
decision-support for portfolio optimization. More specifically, Axioma Portfolio provides functions to build and solve
portfolio optimization problems based on the Markowitz mean-variance model. The focus of this document is exclusively to illustrate the use of Axioma Portfolio Java API for portfolio construction and portfolio rebalancing.
We begin in Chapter 2 with a small example that presents the main objects and functions in code form. This is followed by Chapter 3 with a description of the overall approach to portfolio optimization, including some mathematical descriptions of the models that Axioma Portfolio supports and an overview of Axioma Portfolio's features. We then
(in Chapter 4 ) give a description of each of the objects that is used to construct portfolio optimization models, including portfolios, risk models, and assets. Business rules and constraints are discussed in Chapter 5 , while the objective function is the topic of Chapter 6 . Solving the problem is described in Chapter 8 . The solution inspection and
analysis functions are presented in Chapter 9 . Chapter 10 is devoted to tax-aware optimization. In Chapter 13, we
discuss some error handling features of Axioma Portfolio. Chapter 14 discusses a number of troubleshooting tips.
Several examples are provided in the examples folder in the distribution. The SimpleAPIExample.java example
is included in Appendix A . This is the complete code for the small example introduced in Chapter 2 .
What is Axioma Portfolio?
Axioma Portfolio is a Java set of libraries of classes and methods that enables you to define and solve portfolio optimization problems easily. The object-model of Axioma Portfolio is designed to be flexible and easy to use. It allows the
user to model and solve a wide variety of portfolio optimization problems without requiring any knowledge of the
structure or approach of the underlying algorithms. Axioma Portfolio makes use of proprietary state-of-the-art mathematical programming solvers. The choice of algorithms and problem solving approaches is made automatically and is
hidden from the user.
The Axioma Portfolio API is intended to be used in an application, by establishing a mapping between the application's object model and Axioma Portfolio's object model. In other words, the Axioma Portfolio classes should not be
inherited by the application's classes. Instead, the Axioma Portfolio classes should be instantiated to objects to which
the application keeps references. Axioma Portfolio handles memory management of the allocated objects.
Prerequisites
This manual assumes that you have a working knowledge of the Java programming language and that you have a basic
understanding of portfolio optimization using mean-variance and factor-based or dense/full covariance risk models.
Notation and Naming Conventions
Throughout this manual we will use the following typographic rules:
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 1
Axioma Portfolio
Chapter 1. Preface
➤ keywords, methods, functions, objects, and classes appear in a special typeface ,
➤ larger program listings are specified in the text in special sections such as:
this is code
and
➤ important ideas are emphasized using italics .
Technical Support
For technical support, send email to <AxiomaPortfolio-support@axiomainc.com>, describing your problem,
including your problem instance (see Chapter 14 on how to do this), your operating system platform, compiler, etc.
Acknowledgements
Axioma Portfolio uses METIS © Regents of the University of Minnesota, a library of algorithms for serial graph partitioning and sparse matrix ordering. METIS can be found on the WWW at http://www-users.cs.umn.edu/~karypis/
metis/index.html .
What's New in Axioma Portfolio Java API 2020 R2
Refined Analytics and Reportings
Comprehensive views of transaction costs
Axioma Portfolio Optimizer now includes asset level views of all transaction cost types in the optimization
strategy library. Non-linear market impact costs, Goldman Sachs Shortfall Model™ costs, piecewise-linearmarket impact costs, fixed ticket charges, linear costs, and short sell costs can all be viewed at the asset and
portfolio level providing in-depth analysis of the costs associated with trading. These views are available for both
single and multi-portfolio rebalancings.
General Enhancements
➤ The Initial vs Final Portfolio risk decomposition now incorporates the initial, final, and change in factor exposure providing a comprehensive dashboard of risk and exposure.
➤ Improved strategy building workflow makes it easier to constrain asset holdings to multiples or fractions of
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 2
Axioma Portfolio
Chapter 1. Preface
the asset's weight in the benchmark.
Infrastructure
➤ The license service mechanism has been upgraded to the latest version, offering improved security as well as
additional options to streamline cloud installations.
➤ The C++ API was upgraded to MSVC 14.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 3
Axioma Portfolio
Chapter 2. A Quick-start to Using the Axioma Portfolio API
Chapter 2. A Quick-start to Using the Axioma Portfolio API
This chapter explains how to get started using the Axioma Portfolio Java API. It describes how to:
➤ open a Axioma Portfolio workspace,
➤ create a Axioma Portfolio workspace,
➤ create a universe of assets,
➤ create a benchmark, an alpha group, and a price group,
➤ create an account containing the initial portfolio holdings,
➤ define a factor risk model, including factors, covariance and exposure matrices, and specific risks,
➤ create a strategy containing constraints (business rules) and objectives,
➤ create an account rebalancing,
➤ solve the portfolio optimization problem, and
➤ inspect the results.
A Basic Axioma Portfolio Application
The basic steps to solve a portfolio optimization problem using Axioma Portfolio are the following:
➤ create a workspace,
➤ build a model,
➤ solve the model, and
➤ inspect the results.
The complete program used in this section can be found in Appendix A. It is also included in the examples directory
in the Axioma Portfolio distribution package, with the name SimpleAPIExample.java. See the section called
“Installing and Running Axioma Portfolio” for guidance on how to compile and run this example.
The example scenario is as follows. There is an account (or a portfolio) with four assets with a total investment of
$100,000, which must be rebalanced in light of new or updated risk or return information. In addition, there exists a
universe that represents the set of assets that can be considered for potential investment. In this example, the universe consists of five assets (just one more than the number of assets in the account). The assets in the account are a
subset of the assets in the universe. We will first discuss the input data elements. Then, we present the code that assembles the input data, sets up the model, and solves the rebalancing problem.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 4
Axioma Portfolio
Chapter 2. A Quick-start to Using the Axioma Portfolio API
The assets in this small example are listed in the first column of Table 2.1 . The other columns include the value of the
initial holdings, benchmark holdings, alphas (or expected returns), and share prices. Holdings are given as the number
of shares of each asset held in the account. Alpha is given as a decimal value (it represents the expected return over
the coming period). For simplicity, we assume that the price of each share for each asset is $1. Therefore, in this
simple example the number of shares is equal to the currency holdings. For instance, the initial holdings in DELL are
$20,000 and the expected return of IBM in the coming period is about 17.76%. Notice that there are no holdings for
SAP in either the account or the benchmark. However, SAP is part of the investment universe.
Table 2.1. Asset Data
Asset
Initial Holding
Benchmark Holding
Alpha
Share Price
DELL
20000
$30000
-0.0564929
$1
MSFT
8000
$12000
0.0399615
$1
IBM
32000
$23000
0.177567
$1
ORCL
40000
$35000
0.0227682
$1
SAP
0
$0
-0.167367
$1
We next characterize the risk model. In this small example, we use a 2-factor risk model. Axioma Portfolio supports
both factor-based risk models and full/dense covariance risk models. The data are shown in Table 2.2 and Table 2.3 .
The risk model is described in more details in the section called “Building the Model”, but for now it is sufficient to
note the three basic components: the exposure matrix, the covariance matrix, and the specific risks. Covariances are
given in squared units (e.g., percent or dollars squared), while specific risks are given in the original units, that is, in
terms of a standard deviation not a variance (for instance in percent or in dollars). For example, in Table 2.2 , the specific risk of DELL is 42%.
Table 2.2. Exposure Matrix and Specific Risks
Asset
Factor 1
Factor 2
Specific Risk
DELL
1
0
0.42
MSFT
0.8
0.2
0.23
IBM
0.1
0.9
0.20
ORCL
0
1
0.13
SAP
0.76
0.98
0.14
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 5
Axioma Portfolio
Chapter 2. A Quick-start to Using the Axioma Portfolio API
Table 2.3. Factor Covariance Matrix
Factor 1
Factor 2
Factor 1
0.0024
-0.00011
Factor 2
-0.00011
0.00099
In addition to a set of assets and a risk model, a basic portfolio optimization problem will include an objective function
as well as any additional restrictions on the solution (for instance, constraints or business rules). For this simple example, we include two constraints: (1) we must be fully invested, i.e., we don't want to hold or borrow any cash, and
(2) the risk relative to the benchmark, also known as the active risk or the tracking error, must be at most 10% of
the size of the portfolio. For an objective, we will maximize expected returns, i.e., we maximize the sum of the scalar
product of the asset holdings and the alphas. In Axioma Portfolio, every constraint or objective is created as part of a
strategy. That is, a constraint or objective belongs to a strategy, just like every asset, account, risk model, or group
belongs to a workspace. Therefore, we will create a strategy in this example and group our constraints and objectives together.
To optimize a portfolio means to find the set of asset holdings that maximize or mininimize an objective or set of objectives subject to a set of constraints. This process is also known as account rebalancing. Axioma Portfolio offers the
Rebalancing class that contains all of the necessary information in order to perform an account rebalancing. For
example, a rebalancing includes an account, a strategy containing the rebalancing constraints and objectives, a set of
round lots etc. Furthermore, a rebalancing includes parameters that can be used to affect the optimization process.
For instance, the optimization search strategy and the modeling for the risk constraints, risk objectives, and quadratic
transaction costs can be controlled by means of the available option parameters. Observe that once a strategy has
been created, it can be shared among various rebalancings. The last step in this example, before the optimization
process takes place, will be to create a Rebalancing object. We will use this Rebalancing object to optimize our
portfolio or account.
The rest of this chapter explains how the Axioma Portfolio API is used to set up these data, express the portfolio optimization problem described above, and find the optimal holdings for this instance. The code presented is broken into pieces to allow a step-by-step discussion of the concepts. Again, the complete code for this example is given in
Appendix A.
Opening a Workspace file
An already existing workspace file can be read by instantiating the
com.axiomainc.portfolioprecision.io.xml.WorkspaceReader class, and loaded using loadWorkspace().
WorkspaceReader wsr = new WorkspaceReader();
Properties params = new Properties();
params.add("AxiomaDataDir", "c:\\Data");
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 6
Axioma Portfolio
Chapter 2. A Quick-start to Using the Axioma Portfolio API
File file = new File("c:\\sample.wsp");
InputStream is = new FileInputStream(file);
ProcessingInfo pi = new ProcessingInfo();
wsr.loadWorkspace(is, pi, params);
In the above code, loadWorkspace() takes the InputStream, ProcessingInfo and paramater Properties as the arguments. The file 'c:\sample.wsp' is passed for parsing, and the parameter properties applies to all the plugins in the
workspace. If the file has any parameter variable $AxiomaDataDir, that will be replaced with the path 'c:\Data'. The
following lists all other possiblities of loadWorkspace() methods.
loadWorkspace(URL url) {...}
loadWorkspace(URL url, ProcessingInfo pi) {...}
loadWorkspace(URL url, ProcessingInfo pi, Properties params) {...}
loadWorkspace(InputStream stream) {...}
loadWorkspace(InputStream stream, ProcessingInfo pi) {...}
loadWorkspace(InputSource is, ProcessingInfo pi, Properties params) {...}
Creating a Workspace
A new instance of the workspace can be created using com.axiomainc.portfolioprecision.Workspace class.
This is typically done early in the main part of the application. All that is required in order to create a workspace object is to include the following statement:
Workspace ws = new Workspace("SimpleAPIExample", "Simple example using PP API", new Date());
The statement above creates a Workspace object named ws and passes three parameters to its constructor. The
first argument of the constructor is a unique name or identifier for the Workspace object, the second argument is an
optional string description of the workspace, and the third argument is a date associated with the workspace
(probably the date the workspace was created).
The variable ws will be used as an argument when constructing objects that belong to this workspace (note that most
objects will belong to a workspace). Creating the workspace will also check if a license to use Axioma Portfolio is
available. If not, an exception is thrown and no Workspace object is created.
Building the Model
As outlined above, we initialize our example portfolio optimization model by defining the input data (assets, initial
holdings, benchmark, expected returns, price group and risk model). We then create a strategy that will contain our
objective and constraints. And finally, we construct a rebalancing that will contain the account, the strategy and the
optimization parameters to perform the account rebalancing.
The Asset Universe
We first define the master set of assets that constitute our workspace asset universe. The universe represents the as-
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 7
Axioma Portfolio
Chapter 2. A Quick-start to Using the Axioma Portfolio API
sets that can be considered for potential investment. In this simple example, we will assume that the universe is made
up of the five assets listed below.
SimpleAsset(ws, "DELL", "Dell");
SimpleAsset(ws, "MSFT", "Microsoft");
SimpleAsset(ws, "IBM", "IBM");
SimpleAsset(ws, "ORCL", "Oracle");
SimpleAsset(ws, "SAP", "SAP");
Above, we added each asset to the workspace universe by creating SimpleAsset objects. The constructor of the
simple asset object takes three arguments. The first argument is the workspace object to which the asset will belong,
in this case the object ws. The second argument is the asset unique name (e.g., the stock ticker symbol). The third
argument is the asset optional description, which can be null. Please keep in mind that once a SimpleAsset is added
to a workspace, it cannot be removed. The reason for this restriction is that assets are referenced by numerous Axioma
Portfolio data structures and allowing them to be removed from the workspace would inevitably lead to the invalidation of the data structures that reference them. Therefore, Axioma Portfolio forbids the removal of assets from the
workspace in order to prevent the user from inadvertently creating invalid data structures.
Observe that we did not store any references to the asset objects created above. If we wanted to, we could write,
for instance:
SimpleAsset dell = new SimpleAsset(ws, "DELL", "Dell");
Now the asset object can be referenced using dell.
In Axioma Portfolio, the asset universe is known as the master set and can be retrieved directly from the workspace
object by means of the getMasterSet() method of the Workspace class.
SimpleGroups: Benchmarks, Expected Returns, and Share Prices
Once the universe has been created, we can proceed with the construction of the remaining objects containing the
input data for our portfolio optimization model. In this subsection, we will create a benchmark, an alpha group, and a
price group. In the next subsection, we will create an account and a risk model.
Axioma Portfolio offers the SimpleGroup class for the construction of (as its name implies) simple groups consisting
of a set of assets with associated values or weights and a unit. The unit represents the unit that the group weights are
expressed in. In Axioma Portfolio, group units are represented by static instances of the Unit class. The available
units are CURRENCY, NUMBER, PERCENT, PRICE and SHARES.
The statements below create a benchmark as a SimpleGroup object and set its composition (or group of assets
with their associated weights) to some appropriate values. A benchmark could also be created as an instance of the
Benchmark class, which extends the SimpleGroup class.
SimpleGroup bm = new SimpleGroup(ws, "SimpleBenchmark", null, ws.getDate(), Unit.CURRENCY);
bm.setComposition(ws.getAsset("DELL"), 30000.0);
bm.setComposition(ws.getAsset("MSFT"), 12000.0);
bm.setComposition(ws.getAsset("IBM"), 23000.0);
bm.setComposition(ws.getAsset("ORCL"), 35000.0);
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 8
Axioma Portfolio
Chapter 2. A Quick-start to Using the Axioma Portfolio API
The constructor of the SimpleGroup class takes five arguments. The first argument is the workspace object to
which the simple group will belong, in this case the Workspace object ws. The second argument is the group unique
name or identifier. The third argument is the optional group description. The fourth argument is the group date. And
the fifth argument is the units in which the group composition weights are expressed. For a benchmark, the permitted units are SHARES, PERCENT or CURRENCY. We use CURRENCY since our benchmark weights are currency holdings.
It is important here to stress a critical issue related to the benchmark holdings. In order for certain types of constraints (in particular active holdings constraints and active risk constraints) to be accurately incorporated in the model, the benchmark weights must be scaled so that their sum is equal to the account's investment size. The benchmark
holdings can be scaled in either of two ways. One approach is to preprocess the benchmark holdings before they are
passed to the setComposition() method so that they sum to the desired investment size. This is done above; notice that the sums of both the initial holdings and the benchmark are $100,000 (which is the investment size). The
other approach is to use an instance of the Benchmark class instead of the SimpleGroup class to represent the
benchmark object. Unlike SimpleGroup objects, the weights of Benchmark objects are automatically and transparently scaled to the reference size by Axioma Portfolio whenever this scaling is necessary (e.g. when performing an
account rebalancing).
The expected returns or alphas group and the prices group are constructed in a similar way, except that the group
units are set to NUMBER for the alphas group and to PRICE for the prices group. Obviously, the group composition is
set to the assets expected returns for the alphas group and to the stock share prices for the prices group. The prices
group containing the share prices for each asset in the asset universe is necessary because in Axioma Portfolio account holdings are always expressed in units of shares. The share prices are used to convert the account holdings
from shares to currency. For the sake of simplicitly, we will set the asset share prices equal to $1 so that the account
holdings in terms of shares are the same as the account holdings in terms of currency.
The alphas simple group is created like this:
SimpleGroup alphas = new SimpleGroup(ws, "AlphaGroup", null, ws.getDate(), Unit.NUMBER);
alphas.setComposition(ws.getAsset("DELL"), -0.0564929);
alphas.setComposition(ws.getAsset("MSFT"), 0.0399615);
alphas.setComposition(ws.getAsset("IBM"), 0.177567);
alphas.setComposition(ws.getAsset("ORCL"), 0.0227682);
alphas.setComposition(ws.getAsset("SAP"), -0.167367);
Similarly, the prices simple group is created in the following manner:
SimpleGroup prices = new SimpleGroup(ws, "PriceGroup", null, ws.getDate(), Unit.PRICE);
prices.setComposition(ws.getAsset("DELL"), 1.0);
prices.setComposition(ws.getAsset("MSFT"), 1.0);
prices.setComposition(ws.getAsset("IBM"), 1.0);
prices.setComposition(ws.getAsset("ORCL"), 1.0);
prices.setComposition(ws.getAsset("SAP"), 1.0);
The Account
In order to create the account, we first need to define the account asset holdings. The asset holdings are constructed
as a set of AssetValue objects. The AssetValue class represents an asset-value pair. In other words, instances of
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 9
Axioma Portfolio
Chapter 2. A Quick-start to Using the Axioma Portfolio API
the AssetValue class allow us to associate a SimpleAsset object with a value. The following code snippet illustrates how the account's asset holdings are defined:
Collection holdings = new HashSet();
holdings.add(new AssetValue(ws.getAsset("DELL"), 20000.0));
holdings.add(new AssetValue(ws.getAsset("MSFT"), 8000.0));
holdings.add(new AssetValue(ws.getAsset("IBM"), 32000.0));
holdings.add(new AssetValue(ws.getAsset("ORCL"), 40000.0));
On the other hand, we could have used instead one of the two specialized classes provided by Axioma Portfolio for
the construction of account holdings: the TaxableHoldings class or the NontaxableHoldings class. These
classes implement the UniqueAssetCollection interface.
Now that the account holdings have been created, we construct the account as an instance of the Account class like
this:
Account account = new Account(ws, "SimpleAccount", null, ws.getDate(), holdings);
The constructor of the Account class takes five arguments. The first argument is the workspace object to which the
account will belong, in this case the ws object. The second argument is the account unique name or identifier. The
third argument is the optional account description. The fourth argument is the account date. And the fifth argument
is the account holdings.
The Risk Model
Next, we define a 2-factor risk model. As stated before, a factor risk model is comprised of a set of asset specific
risks, a factor exposure matrix, and a covariance matrix. We construct each one of these in turn and then use them
to create our factor risk model.
The specific risks are defined as a set of AssetValue objects. An AssetValue object is an object containing an asset and a corresponding value. In this case, the value is the asset specific risk. One AssetValue object is created for
each asset spanned by the risk model.
Set specificRisks = new HashSet();
specificRisks.add(new AssetValue(ws.getAsset("DELL"), 0.42));
specificRisks.add(new AssetValue(ws.getAsset("MSFT"), 0.23));
specificRisks.add(new AssetValue(ws.getAsset("IBM"), 0.2));
specificRisks.add(new AssetValue(ws.getAsset("ORCL"), 0.13));
specificRisks.add(new AssetValue(ws.getAsset("SAP"), 0.14));
Note that the specific risk is entered in units of standard deviation, not variance. For instance, the specific risk for DELL
in the above code sample is 42%. Note that the risk model may contain more assets than are present in the initial
holdings. It may even contain assets that will not be considered as potential investment opportunities in the problem.
Next, we define the factor names and the factor exposure matrix. In this case, we have two factors and five assets.
Thus, the exposure matrix is a 2x5 matrix. For each factor, we create a set of asset-value pairs (or AssetValue objects) representing the exposure of each asset to the corresponding risk factor. This is done as demonstrated by the
following sample code.
String[] factors = { "Factor1", "Factor2" };
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 10
Axioma Portfolio
Chapter 2. A Quick-start to Using the Axioma Portfolio API
Set factor1 = new HashSet();
factor1.add(new AssetValue(ws.getAsset("DELL"), 1.0));
factor1.add(new AssetValue(ws.getAsset("MSFT"), 0.8));
factor1.add(new AssetValue(ws.getAsset("IBM"), 0.1));
factor1.add(new AssetValue(ws.getAsset("ORCL"), 0.0));
factor1.add(new AssetValue(ws.getAsset("SAP"), 0.76));
Set factor2 = new HashSet();
factor2.add(new AssetValue(ws.getAsset("DELL"), 0.0));
factor2.add(new AssetValue(ws.getAsset("MSFT"), 0.2));
factor2.add(new AssetValue(ws.getAsset("IBM"), 0.9));
factor2.add(new AssetValue(ws.getAsset("ORCL"), 1.0));
factor2.add(new AssetValue(ws.getAsset("SAP"), 0.98));
Set[] factorExposures = new Set[]{ factor1, factor2 };
The final component of the risk model is the factor covariance matrix. The covariance matrix is a symmetric matrix
whose matrix elements represent the factor-factor covariances. We create a covariance matrix as a 2-dimensional array of doubles in this way:
double[][] covariances = new double[][]
{
{ 0.0024, -0.00011 },
{ -0.00011, 0.00099 }
};
Once the set of asset specific risks, the covariance matrix, and the exposure matrix have been created, the factor risk
model is constructed as an instance of the FactorRiskModel class as shown below.
new FactorRiskModel(ws, "SmallRiskModel", null, ws.getDate(),
specificRisks, factors, factorExposures, covariances, null);
The statement above creates a FactorRiskModel object and passes nine parameters to its constructor. The first
argument of the constructor is a reference to the workspace object that the risk model will belong to; the second argument is a name for the risk model object; the third argument is an optional risk model description; the fourth argument is the risk model date; the fifth argument is the set of asset specific risks; the sixth argument is the risk factor
names; the seventh argument is the factor exposures; the eighth argument is the covariance matrix; and the ninth argument is the optional set of factor descriptions.
The Strategy: Objectives and Constraints
As described in the introduction of this chapter, the set of constraints and objectives are created as part of a
Strategy object. A strategy is constructed using the following statement:
Strategy strategy = new Strategy(ws, "SimpleStrategy", null, ws.getDate());
The constructor of the Strategy class takes four parameters. The first parameter is the Workspace that the
strategy will belong to. The second parameter is the strategy's name. The third parameter is the optional strategy's
description. And the fourth parameter is the strategy's date.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 11
Axioma Portfolio
Chapter 2. A Quick-start to Using the Axioma Portfolio API
Once the strategy has been created, we can proceed to set its optimization parameters, its local universe and its objectives and constraints. The optimization parameters affect how the optimization process is performed. Examine the
Strategy class in the Axioma Portfolio JavaDocs [index.html] for more details about this feature and to learn which
optimization parameters are available. The local universe refers to the set of assets that are affected by the constraints and objectives contained in the strategy. The following code snippet illustrates how the optimization process
is instructed to allow shorting and how the strategy local universe is set:
strategy.setAllowShorting(true);
LocalUniverse lu = strategy.getLocalUniverse();
lu.includeAsset(ws.getAsset("DELL"));
lu.includeAsset(ws.getAsset("MSFT"));
lu.includeAsset(ws.getAsset("IBM"));
lu.includeAsset(ws.getAsset("ORCL"));
The constraint requiring full investment is created as an instance of the available BudgetConstraint class. The constructor of each constraint class in Axioma Portfolio has three parameters: the first parameter is the strategy that the
constraint belongs to; the second parameter is the name of the constraint; and the third parameter is the optional
constraint description. Furthermore, every constraint contains an instance of the ConstraintProperties class
that must be set by the user. The ConstraintProperties class enables us to set all of the properties that are relevant to a particular constraint. For example, if a constraint has an upper bound or lower bound (maximum or minimum value), we can specify it in its constraint property instance. Other values that can be set in this way include: a
constraint's scope, unit, risk model, benchmark, weight, etc. The static variable ConstraintProperties.Property.USE_BUDGET_VALUE refers to a boolean property that indicates whether a constraint should use a
buget value and can be set to either true or false. Finally, a constraint is inactive or disabled until it is explicitly set
by the user as enabled. All of this is setup as illustrated in the following sample code.
BudgetConstraint bc = new BudgetConstraint(strategy, "BudgetConstraint", null);
ConstraintProperties cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.USE_BUDGET_VALUE, true);
bc.setProperties(cp);
bc.setEnabled(true);
We now define the active risk constraint or tracking error. This constraint restricts the risk of the problem to be at
most 10% of the portfolio size (i.e., $10,000) and it is created as an instance of the LimitTotalRiskConstraint
class. The set of assets this constraint applies to is specified by using the LimitTotalRiskConstraint's addAssetSelection() method. Furthermore, we set the constraint scope to AGGREGATE to indicate that the constraint applies to the set of assets as a whole and not to each asset in the set individually. Notice that the set of assets
includes all of the assets in the master set except for SAP, which is excluded because it is not in the local universe.
Since this is an active risk constraint and Axioma Portfolio supports multiple risk models and benchmarks, we must
specify the benchmark that the risk is measured relative to and the risk model that should be used to compute the
risk. The risk model and the benchmark are specified by means of the ConstraintProperties's BENCHMARK and
RISKMODEL properties, respectively. We indicate that the constraint is to be imposed as a percentage of the portfolio size by means of the ConstraintProperties's UNIT property, which is set to Unit.PERCENT. The constraint
and its constraint properties are setup in the following way:
LimitTotalRiskConstraint arc = new LimitTotalRiskConstraint(strategy, "ActiveRiskConstraint",
null);
cp = new ConstraintProperties();
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 12
Axioma Portfolio
Chapter 2. A Quick-start to Using the Axioma Portfolio API
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.AGGREGATE);
cp.setProperty(ConstraintProperties.Property.MAX, 10.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.PERCENT);
cp.setProperty(ConstraintProperties.Property.BENCHMARK, ws.getGroup("SimpleBenchmark"));
cp.setProperty(ConstraintProperties.Property.RISKMODEL, ws.getRiskModel("SmallRiskModel"));
arc.setProperties(cp);
AssetSet as = new AssetSet(ws, "MyLocalUniverse", null, ws.getDate());
as.includeAssetSet(ws.getMasterSet());
as.excludeAsset(ws.getAsset("SAP"));
arc.addAssetSetSelection(as, ConstraintProperties.EMPTY_PROPERTIES);
arc.setEnabled(true);
Now that the constraints have been setup, we consider the objective function. In Axioma Portfolio, the objective
function, as we will see in Chapter 6, may consist of several components, e.g., expected return, transaction costs,
market impact estimates, risk, and so forth. In this example, we will consider a single objective term --the portfolio
expected return or the sum of the alphas weighted by the asset holdings. The expected return component in the objective function is set up in this way: First we construct an expected return objective term and set its alpha group (or
the set of assets that will be included in the expected return calculation); then we create a simple objective that belongs to the strategy that was created before, we add the expected return objective term and set the objective's target to Objective.Target.MAXIMIZE in order to indicate to the optimizer that this objective should be maximized. These steps are illustrated in the following sample code:
ExpectedReturnTerm ero = new ExpectedReturnTerm(strategy, "ExpectedReturn", null);
ero.setAlphaGroup(ws.getGroup("AlphaGroup"));
Objective simpleObjective = new Objective(strategy, "SimpleObjective", null);
simpleObjective.addObjectiveTerm(ero, 1.0);
simpleObjective.setTarget(Objective.Target.MAXIMIZE);
The Account Rebalancing
The final step is defining an account Rebalancing object, which will keep track of the assets, constraints, and objective we are considering in this particular portfolio optimization problem. A Rebalancing object is created as follows:
Rebalancing rebal = new Rebalancing(ws, account, "SimpleRebalancing", null, ws.getDate());
The constructor of the Rebalancing class takes five arguments. The first argument is the workspace object that the
rebalancing will belong to; the second argument is the account that will be rebalanced; the third argument is the rebalancing name; the fourth argument is the optional rebalancing description; and the fifth argument is the rebalancing
date.
Next, we set the rebalancing strategy, the budget size, and the reference size. You can also set the number of cores
from the hardware's processor to use to solve the problem. The budget size or investment size is used to control the
net asset value of the portfolio. For example, one possibility is that the investment size is set to the sum of the initial
holdings of the assets. This in effect means that the optimization just "rebalances" the existing assets in an optimal
way. The total value of the portfolio will remain the same. Another possibility is that investment size is set to be larger than the sum of the initial holdings. This results in increasing the total investment in the portfolio by the difference
between the investment size and the sum of the initial holdings. For instance, this occurs if there is a new inflow of
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 13
Axioma Portfolio
Chapter 2. A Quick-start to Using the Axioma Portfolio API
cash. Finally, if the investment size is set to be smaller than the sum of current assets then this results in a reduction
in the total investment in the portfolio. This approach can be used to model a withdrawal of funds from the account.
The reference size is the value upon which all relative portfolio calculations are based. For example, when we set a
constraint that is expressed as a percentage (like we did for the risk constraint), the reference size is used to convert
the percentage to an absolute value. If a cash asset is in the local universe and handled directly in the account and the
strategy, then the reference size and the budget size are are usually the same. In this example we set the reference
size and the budget size both to $100,000.00. Please note that if a cash asset is in the local universe and handled directly in the account and strategy, then the reference size and budget size are usually the same.
rebal.setStrategy(strategy);
rebal.setBudgetSize(100000.0);
rebal.setReferenceSize(100000.0);
Multi-core optimization
In the REBALANCING class, use setNumberOfCores to define the max number of cores (positive integer) on the
processor(s) to employ in performing the rebalancing. If the number of cores is not set explicitly, the default number
of cores used is 1. For testing, 4 or 8 cores is recommended as a starting point.
Note
If the number of cores specified exceeds the number of cores available, the parameter value defaults to the
max number of available cores.
What is parallelized (multi-threaded)? setNumberOfCores, where appropriate, controls the maximum number
of processing threads that may be created to execute the portions of the interior point algorithm that can be parallelized. This feature only controls the degree of parallelization of the optimization algorithm; other phases of the optimization are still performed serially. Hence, improvements may be recognized where the branch and bound algorithm
is employed to solve MVO models with combinatorial constraints.
Expectations and use cases. In the most optimistic scenario, average MVO instances may run 40% faster when
the parallel optimizer is employed with 4 to 8 cores. For special MVO cases, processing improvements may be realized as well. For selected instances of scenario-based CVar optimization, problems were solved 4 times as fast with
parallelization using 8 cores. Additionally, for selected multi-portfolio optimization instances, problems were solved
70% faster with parallelization across 8 cores. Processing improvements, however neglible or significant, will vary
depending on the optimization problem considered.
The next sections describe how to optimize a portfolio and examine its solution.
Solving a Problem
To solve the above portfolio optimization problem, we call the solve() method of the Rebalancing object.
RebalancingBase.Status status = rebal.solve();
This method returns a value of type RebalancingBase.Status which is caught in the status variable and which
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 14
Axioma Portfolio
Chapter 2. A Quick-start to Using the Axioma Portfolio API
provides information about the optimization process. This status variable has four possible values:
➤ SolutionFound which signifies that a solution to the problem was found,
➤ NoSolutionFound which signifies that no solution to the problem was found,
➤ NoLicense which signifies that a valid Axioma Portfolio license could not be found, and
➤ InternalError which signifies that an error occurred somewhere in the process (this kind of error may
be caused by bad input data, incorrect usage of the API, etc.).
For more information about these values, see the RebalancingBase.Status class in the Axioma Portfolio JavaDocs
[index.html].
Inspecting the Solution
After optimizing our portfolio, we generally want to look more closely at the new (optimized) holdings. This can be
done as follows:
RebalancingSolution sol = rebal.getSolution();
if (!sol.isSolved()) {
System.out.println("Rebalancing was not solved.");
return;
}
Holdings folio = sol.getFinalHoldings();
// REPORTING
Analytics analyzer = new Analytics(prices);
System.out.println("Objective Value : " + sol.getFinalObjectiveValue());
System.out.println("Expected Return : " +
analyzer.computeExpectedReturn(folio, ws.getGroup("AlphaGroup")));
// Print solution
Holdings ifolio = sol.getInitialHoldings();
SortedSet assets = folio.getAssets();
Iterator it = assets.iterator();
while (it.hasNext()) {
Asset a = (Asset) it.next();
double price = prices.getComposition(a);
double shares = folio.getShares(a);
double ishares = ifolio.getShares(a);
System.out.println(a.getIdentity() + ": " + (shares * price) +
"\t(was: " + (ishares * price) + ")");
}
We do several things in the above code. First we retrieve the rebalancing solution by using the getSolution()
method of the Rebalancing class. We then check that the rebalancing has been solved, and if so, we proceed to retrieve the optimized holdings for each asset in the portfolio (by calling the getFinalHoldings() method of the
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 15
Axioma Portfolio
Chapter 2. A Quick-start to Using the Axioma Portfolio API
RebalancingSolution object). We print the objective function value of the optimized solution by invoking the
getFinalObjectiveValue method of the RebalancingSolution class. Then we compute the expected return
and print it to the screen. In order to compute the expected return, we use an instance of the Analytics class. The
Analytics class is a utility class that provides various methods for computing a set of values that are of interest to
the user in order to analyze or understand the properties of a portfolio or a rebalancing solution. For example, this
class provides methods for computing the expected return for a set of assets, the total risk, the marginal contribution
to active or total risk, the transaction cost associated with the transition from an initial set of holdings to an optimized
portfolio, etc.. The expected return is computed using the computeExpectedReturn() method of the Analytics
class. This methods takes two parameters: The set of asset holdings whose expected return is to be computed and
the corresponding group of alphas. For this example, the objective function will equal the expected return.
Next, we iterate through the assets in the optimized account and for each asset, we print its name or identity along
with its initial and final (or optimized) holdings. The assets in the account are obtained by invoking the getAssets()
method of the Holdings class. The initial holdings are retrieved from the RebalancingSolution object by using
the getInitialHoldings() method. Since the holdings are expressed as shares in the rebalancing solution, we
need to use the price group to convert from shares to currency. Note that the assets in the final holdings, represented here by the variable assets and retrieved from the rebalancing solution final holdings by means of the getAssets() method, only contain those assets with nonzero optimized holdings; therefore, some of the initial holdings
may not be printed.
Installing and Running Axioma Portfolio
Here we describe how to install and run Axioma Portfolio. We give detailed installation instructions for Windows
users. The instructions can also be found in the README file included in the distribution.
System Requirements
This section summarizes the system requirements and installation information for Axioma Portfolio Java API.
Windows [Windows 7/8/10]
➤ 64-bit
➤ Java JDK and JRE versions
➤ 2020 R2 is built on 1.8.0_181. JDK/JRE version 1.8 or higher is required.
Linux: Ubuntu [10.04+] and Red Hat [versions 4, 5, 6,7]
➤ 32-bit or 64-bit
➤ Java JDK and JRE version
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 16
Axioma Portfolio
Chapter 2. A Quick-start to Using the Axioma Portfolio API
➤ 2020 R2 is built on OpenJDK 1.8.0_202. JDK/JRE version 1.8 or higher is required.
Dependencies (packages that will need to be installed to run the Axioma Portfolio API):
➤ lapack - Not generally installed by default. Each Linux distribution we support includes packages containing
this library that can be installed using its respective package manager (For Ubuntu, this package is "liblapackdev").
➤ blas - Not generally installed by default. Each Linux distribution we support includes packages containing this
library that can be installed using its respective package manager (For Ubuntu, this package is "libblas-dev").
➤ lsb - Not generally installed by default. Each Linux distribution we support includes packages containing this
library that can be installed using its respective package manager (For Ubuntu, this package is "lsb").
➤ gfortran or g2c - Once "lapack" and "blas" have been installed using a package manager, these libraries should
automatically have been installed as a dependency.
➤ libstdc++ - This library is usually part of the "gcc" package and is generally installed by default.
Unzipping the Distribution and Installing Axioma Portfolio Java API on Windows
If it is not already installed, install the Java JDK version specified in the System Requirements section matching your
Axioma Portfolio Java API version.
The first step is to unzip the distribution in a directory of your choice. The unzipping will create a subdirectory called
Axioma Portfolio. In there you will find the following directory structure:
bin
This directory needs to be in your PATH in order to be able to run Axioma Portfolio. It contains
runtime libraries used by Axioma Portfolio.
docs
Contains the User's Guide, the XML Guide, and DAO Manual.
examples
Contains example programs that use the Axioma Portfolio API.
lib
This directory contains the library files used when you link with Axioma Portfolio.
Note: We generally recommend that you avoid using the "Program Files" directory or any of its sub-directories as a
target location for the Axioma Portfolio Java API, since the permissions associated with these directories may make it
difficult to compile the example programs provided with the API.
Add the "bin" sub-directory of the Axioma Portfolio Java API distribution to your PATH environment variable.
Make sure the machine on which you have unzipped the Java API distribution has a valid Axioma license file or, if the
Axioma license is installed on a different machine, add the AXIOMA_LICENSE_FILE environment variable and set it
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 17
Axioma Portfolio
Chapter 2. A Quick-start to Using the Axioma Portfolio API
equal to the machine on which the license is installed (for example, if your license is installed on a machine named ESQUINA, then the "AXIOMA_LICENSE_FILE" variable should have the value "@ESQUINA").
License Files
License needs to be set up properly. Contact your Axioma representative if you have any problems with the licenses.
Please provide a log showing the shell/console output when running your application.
Run SimpleAPIExample. You should see output of a small portfolio optimization problem with five assets (see below).
If you get an error, contact your Axioma representative.
Compiling and setting path for Example Programs
To compile the example programs, run compile.bat. To add libraries to classpath, run setup.bat.
Running Axioma Portfolio
After compiling and linking the simple example program (SimpleAPIExample.java) with the Axioma Portfolio libraries, you can run it. You will see the following output:
%> java com.axiomainc.SimpleAPIExample
...
... some reporting on solution progress ...
...
Objective Value : 27344.40
Expected Return : 27344.40
DELL: 32451.06 (was: 20000.0)
IBM: 57649.63 (was: 32000.0)
MSFT: 27727.04 (was: 8000.0)
ORCL: 78098.08 (was: 40000.0)
SAP: -95925.81 (was: 0.0)
%>
The output gives the objective function value ("Objective value") as well as the solution value of the individual components of the objective function (in this case "Expected Return"). Note that these values are in dollars. It then lists all
the assets in the optimized portfolio along with their initial values.
As you see, the optimized rebalancing suggested short selling approximately $95,925 of the SAP stock and using the
proceeds to purchase more of the remaining stocks. For example, $12,451.06 worth of DELL, $25,649.63 worth of
IBM, $19,727.04 worth of MSFT, and $38,098.80 worth of ORCL should be purchased. Observe that because of the
budget constraint that was imposed ealier, the amount of sales and purchases are equal (i.e. no cash is added or removed from the account.) Our expected return (in $) is $27,344. This corresponds to a percentage expected return
of 27344/100000 = 27.34%. More detailed analysis of this solution is facilitated by Axioma Portfolio's many portfolio
analysis functions, to be described in Chapter 9.
Unzipping the Distribution and Installing Axioma Portfolio Java API on Linux
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 18
Axioma Portfolio
Chapter 2. A Quick-start to Using the Axioma Portfolio API
If it is not already installed, install the Java JDK version specified in the System Requirements section matching your
Axioma Portfolio Java API version.
The first step is to unzip the distribution in a directory of your choice. The unzipping will create a subdirectory called
Axioma Portfolio. In there you will find the following directory structure:
bin
This directory needs to be in your PATH in order to be able to run Axioma Portfolio. It contains
runtime libraries used by Axioma Portfolio.
docs
Contains the User's Guide, the XML Guide, and DAO Manual.
examples
Contains example programs that use the Axioma Portfolio API.
lib
This directory contains the library files used when you link with Axioma Portfolio.
Create/add to the following environment variables. The "export" command will establish them for the current terminal session. A sysadmin can persist them.
AXIOMA_JAVA_HOME=(directory where API is installed).
JAVA_HOME=(base directory where Java is installed, if it does not already exist).
The PATH environment variable should containt $JAVA_HOME.
The LD_LIBRARY_PATH environment variable should contain $AXIOMA_JAVA_HOME/bin.
Make sure the machine on which you have unzipped the Java API distribution has a valid Axioma license file or, if the
Axioma license is installed on a different machine, add the AXIOMA_LICENSE_FILE environment variable and set it
equal to the machine on which the license is installed (for example, if your license is installed on a machine named ESQUINA, then the "AXIOMA_LICENSE_FILE" variable should have the value "@ESQUINA").
Run setup.sh (located in the examples\java sub-directory) to add the Axioma Portfolio Java API classes to the
CLASSPATH environment variable. On Linux, this is run as:
%> . setup.sh (period, then space, then setup.sh)
Run compile.sh (located in the examples\jave sub-directory) to compile and link the .java programs in the examples\jave sub-directory.
%> . compile.sh (period, then space, then compile.sh)
After compiling and linking, the simple example program (SimpleAPIExample.java) with the Axioma Portfolio libraries, you can run it. You will see the following output:
%> java com.axiomainc.SimpleAPIExample
...
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 19
Axioma Portfolio
Chapter 2. A Quick-start to Using the Axioma Portfolio API
... some reporting on solution progress ...
...
Objective Value : 27344.40
Expected Return : 27344.40
DELL: 32451.06 (was: 20000.0)
IBM: 57649.63 (was: 32000.0)
MSFT: 27727.04 (was: 8000.0)
ORCL: 78098.08 (was: 40000.0)
SAP: -95925.81 (was: 0.0)
%>
The output gives the objective function value ("Objective value") as well as the solution value of the individual components of the objective function (in this case "Expected Return"). Note that these values are in dollars. It then lists all
the assets in the optimized portfolio along with their initial values.
As you see, the optimized rebalancing suggested short selling approximately $95,925 of the SAP stock and using the
proceeds to purchase more of the remaining stocks. For example, $12,451.06 worth of DELL, $25,649.63 worth of
IBM, $19,727.04 worth of MSFT, and $38,098.80 worth of ORCL should be purchased. Observe that because of the
budget constraint that was imposed ealier, the amount of sales and purchases are equal (i.e. no cash is added or removed from the account.) Our expected return (in $) is $27,344. This corresponds to a percentage expected return
of 27344/100000 = 27.34%. More detailed analysis of this solution is facilitated by Axioma Portfolio's many portfolio
analysis functions, to be described in Chapter 9.
Troubleshooting Installation Issues
Table 2.4. Troubleshooting Installation Issues
Error
Resolution
java.lang.UnsatisfiedLinkError: no jPortfolioPrecisionLoader-2.26.0 in java.library.path
If you are running the Axioma Portfolio Java API on Linux,
make sure the "lapack", "blas", and "lsb" packages are installed, and make sure the bin directory of the Axioma
Portfolio Java API is listed in the LD_LIBRARY_PATH environment variable.
Exception in thread "main"
java.lang.NoClassDefFoundError: com/axiomainc/portfolioprecision/...
The Axioma Portfolio Java API is not in the CLASSPATH.
Run the setup.sh (or setup.bat on Windows) again.
com.axiomainc.portfolioprecision2.PortfolioException:
No valid Axioma_API license available. Cannot connect
to license server system.
Make sure the license file is installed correctly or the license server is up and running. Verify that the AXIOMA_LICENSE_FILE environment variable is pointing
to the correct location.
This concludes our quick overview of Axioma Portfolio. We have described the basic features for setting up and solving a simple model. Chapter 4 through Chapter 13 will present these ideas in more detail, specifically describing a
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 20
Axioma Portfolio
Chapter 2. A Quick-start to Using the Axioma Portfolio API
number of additional features. First, however, we provide an overview of the basics of modern portfolio optimization.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 21
Axioma Portfolio
Chapter 3. Portfolio Optimization Basics
Chapter 3. Portfolio Optimization Basics
Mean-variance analysis, originally developed by Harry Markowitz in the 1950s, provides an important framework for
understanding the risk/return tradeoff and the value of diversification. Solution of the underlying optimization problem determines the optimal investment (defined as the one with the minimum risk for a given level of expected return, or the largest expected return for a given level of allowed risk).
For many years, solutions for realistic, large-scale portfolio optimization problems were out of reach. This was partly
due to computing and algorithmic limitations, but was also the result of some shortcomings of the original optimization framework.
In the real world, portfolio managers must make investment decisions that satisfy additional business rules and balance multiple business goals. Business rules might include tracking an index or benchmark (on which performance is
generally judged), limiting the number of names held, or limiting the holdings in a particular sector of the market. In
addition to maximizing expected return, goals could include minimizing transaction costs, or minimizing tax liability. A
portfolio optimization model that is able to accommodate these additional considerations provides solutions that are
effective and useful. Only recently, with advances in computing speed and algorithms, have such realistic optimization
problems been solvable.
Basic Modeling Frameworks
The basic mean-variance model assumes the portfolio manager currently holds a portfolio of securities from an asset
or security universe. This is termed the "initial holdings." A portfolio is always specified through the weight or amount
invested in each security of the asset universe. The bulk of the mean-variance model consists of estimated data: estimates of expected security return over the coming period, estimates of security risk, correlations, etc. In addition,
there are user-specified constraints, business rules, business goals, and an objective function that defines the risk/
return tradeoff.
Assume the portfolio manager now wishes to rebalance the initial portfolio based on up-to-date data. Expected return is represented by the alphas. The portfolio risk can be measured either using absolute risk (e.g., the standard deviation of the portfolio returns) or the relative risk (e.g., the standard deviation of the difference between portfolio
return and the return of a "benchmark".) Often the risk is measured relative to a benchmark, where the goal is to
track the benchmark within a certain target percentage (the active risk or tracking error).
The covariance matrix of security returns is generally decomposed using a multi-factor risk model. The risk model is
a linear decomposition of the market-related risk into factors. These factors represent macro-economic or fundamental entities or the different industries of the economy. The security's risk is expressed as the total exposure to
the risk factors plus its specific risk. The specific risk is the risk that is not correlated with the factors or the market.
A factor risk model is then composed of these three parts - an exposure matrix, a factor covariance matrix, and the
specific risks. With the factor model, the absolute risk and the relative risk can be determined through the following
equations:
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 22
Axioma Portfolio
Chapter 3. Portfolio Optimization Basics
where w is the vector of portfolio holdings, b is the vector of benchmark holdings, B is the exposure matrix, Ω is the
factor covariance matrix, and ∆ is a diagonal matrix of the specific risks. Note that w and b may have negative entries
denoting short positions.
The portfolio manager may decide to formulate the portfolio optimization problem in one of the following three
ways:
1.
maximize expected return subject to keeping the risk below a target level, or
2.
maximize expected return minus a multiple of the risk, or
3.
minimize risk subject to keeping the expected return above a certain target expected return.
Note that risk here can be absolute risk or active risk.
Axioma Portfolio can solve any of these models. Below we specify each of these models mathematically. Let S be the
portfolio size.
For (1), the basic model is:
For (2), the basic model is:
For (3), the basic model is:
These three frameworks provide examples of the core structure of the optimization models.
Axioma Portfolio Features
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 23
Axioma Portfolio
Chapter 3. Portfolio Optimization Basics
The Axioma Portfolio product is intended to facilitate the modeling and solution of complex portfolio optimization
problems. Axioma Portfolio provides the user unprecedented flexibility. Axioma Portfolio supports both factor risk
models and dense risk models in the problem specification. In fact, the user may utilize more than one risk model for
a single portfolio. Nearly all business rules can be specified in absolute dollar terms or as a percentage of the portfolio
size. Performance measures can be computed in either absolute terms or relative to a user-specified benchmark. Axioma Portfolio also supports the use of more than one benchmark in a single optimization problem so that different
benchmarks can be used to construct and evaluate different portions of the portfolio.
It is often important that tax issues be taken into account in portfolio rebalancing. Axioma Portfolio has this capability.
The user may specify tax lots with information about the cost basis and date of purchase of the each lot and taxrelated parameters such as tax rates, gains or losses from other accounts, and wash sale information. Given this information, Axioma Portfolio supports modeling of tax considerations using both tax-related rules and tax-related
goals.
In the sections that follow we list the many types of business rules, business goals, and business analysis functions that
are available in Axioma Portfolio. Axioma Portfolio also incorporates several generic methods that allow the user to
add customized rules, goals, and analytical tools. These rules and goals can be used in nearly every conceivable combination to provide ultimate flexibility.
Business Rules
There are a number of additional constraints (or business rules) and objectives (or business goals) that can be added
to the basic models presented in this chapter to increase the utility of the solutions they provide. Next, we provide a
short description of each.
1.
Limits on holdings. A portfolio manager may want to limit the investment in any one asset or set of assets.
This limit can be expressed as either a percentage of the portfolio size or a dollar amount. For example, a
limit on the holdings for an individual security of 2% would mean that the security represents no more
than 2% of the portfolio size. An absolute limit on holdings for assets in a sector or industry may say, for
instance, that no more than $100,000 is invested in the computer industry. Axioma Portfolio also supports
limits on long and short holdings for any asset or set of assets (including the entire portfolio).
2.
Limits on active holdings. A portfolio manager may want to keep the holdings in a given security or industry
close to those held by the benchmark. To limit the possible deviation of the portfolio holdings in a given industry from the benchmark holdings (either above or below), an active holdings constraint can be added.
For example, if the benchmark has 5% of its value in the CHEMICALS industry and the active holdings in
the CHEMICALS industry are limited to 2%, then the holdings in the CHEMICALS industry are limited to
at least 3% and at most 7% of the portfolio value. An active holdings constraint can be imposed on any
single asset or set of assets in the asset universe.
3.
Limits on the number of names held. Generally, it is desirable to keep the portfolio simple. This can be
achieved by limiting the number of distinct names held. Axioma Portfolio supports limits on the total number of names held in the portfolio as well as the total number of names held in an industry. It is also possible to place limits on the number of long and short holdings in the entire portfolio or in an industry.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 24
Axioma Portfolio
Chapter 3. Portfolio Optimization Basics
4.
Minimum holdings and minimum threshold holdings. A portfolio manager may want to require a minimum investment in a specific security or group of securities. The minimum holdings constraint requires that the
optimized portfolio includes at least the minimum value from securities in the group. This minimum value
may be specified as a percentage of the portfolio size or a dollar value. In addition, Axioma Portfolio supports a second type of minimum on the holdings in an individual security. The minimum threshold holdings
constraint limits the holdings of an individual security to be either 0 (no holdings) or at least a certain minimum threshold value, say 0.1% (either long or short).
5.
Limits on Transactions . Axioma Portfolio supports limits on the total amount of turnover in the portfolio as
well as the turnover in any security or group of securities. These limits can be specified as a percentage of
the portfolio size or a dollar amount. In addition, the user may specify independent limits on the total
amount of buy and/or sell transactions for the entire portfolio or any set of securities.
6.
Minimum transaction and minimum threshold transaction. A portfolio manager may want to require a minimum transaction amount for a specific security or group of securities. The minimum transaction constraint
specifies a minimum amount for the total transactions for an individual security or group of securities. This
minimum value may be specified as a percentage of the portfolio size or a dollar value. In addition, Axioma
Portfolio supports a second type of minimum on the transactions for an individual security. The minimum
threshold transaction constraint limits the transactions of an individual security to be either 0 or at least a
certain minimum threshold value (either buy or sell).
7.
Limits on risk. Axioma Portfolio supports several types of limits on the risk of the resulting portfolio. The
user may impose a limit on the total absolute risk, the active risk relative to a benchmark, the risk resulting
from holdings in a specific industry, or the risk resulting from a user-defined set of assets. Recall that Axioma Portfolio supports multiple risk models for a single portfolio. The user simply specifies the risk model
or models to be used for the assets in each individual constraint.
8.
Limits on beta. Portfolio managers may want to impose a constraint that the beta of the optimized portfolio
be close to the beta of the benchmark. For instance, a bound can be imposed so that the beta of the new
portfolio is within 3% of the benchmark beta. Similar constraints can be imposed on other portfolio attributes such as P/E, P/B, etc..
9.
Limits on expected return. Portfolio managers may want to impose a lower bound on the expected return of
the optimized portfolio. This limit can be an overall return, the return on assets from a specific industry, or
a return relative to the return of a benchmark.
10. Limits on deviation from a benchmark. Portfolio managers may want to explicitly limit the deviation of the
optimized portfolio from a benchmark. These limits can be placed on the holdings in the entire portfolio or
the holdings in a subset of the assets. In addition, Axioma Portfolio supports multiple benchmarks so that
the user may constrain the holdings in the overall portfolio or different industries relative to different
benchmarks.
11. Round lotting. Typically, trades are required to be in round lots of, for instance, 100 shares. It is possible to
specify, at an asset-level, the asset's round lot unit (in shares). Each trade recommended in the rebalancing
of the portfolio will be a multiple of the round lot unit.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 25
Axioma Portfolio
Chapter 3. Portfolio Optimization Basics
12. Tax-related rules . Axioma Portfolio supports a number of constraints related to the tax consequences of the
portfolio rebalancing. The user may place limits on the total tax-liability resulting from the portfolio transactions. Moreover, Axioma Portfolio supports explicit limits on the realized long-term and short-term gains
or losses from the transactions.
In addition, many of the constraints specified above can be treated as soft constraints. A soft constraint may be violated by incurring a penalty. Axioma Portfolio supports linear, quadratic and scaled quadratic penalties on the violation.
Axioma Portfolio also provides several general constraint classes that allow the user to specify customized restrictions that can be expressed as linear inequalities.
Business Goals
The overall goals of the optimization process are expressed as terms in the optimization objective. Axioma Portfolio
allows the user to specify the individual goals to be included in the objective as well as their relative importance. Below, we give a list of typical components that may be included in the overall goal.
1.
Expected Return. Generally, the primary goal of portfolio optimization is to maximize the expected return
of the portfolio. Axioma Portfolio automates the process of adding the expected return calculation to the
overall goal and allows the user to specify the importance of the return relative to the costs and risks associated with the portfolio.
2.
Risk. Axioma Portfolio allows risk measures to be added to the optimization objective to minimize the risk
of the resulting portfolio. Risk may be measured in absolute terms or relative to a benchmark. Absolute
risk may be measured as either a standard deviation or a variance.
3.
Transaction costs . Linear and piecewise linear transaction costs, which can be used to account for fees,
commissions and/or taxes, can be added to the objective function.
4.
Market impact (illiquidity) estimates. In order to discourage large transactions and mitigate illiquidity effects,
a quadratic transaction cost term can be added to the objective function. Thus, large transactions are penalized by a term that grows quadratically in the transaction size. Axioma Portfolio supports both symmetric
and asymmetric market impact models.
5.
Tax-aware optimization . The portfolio optimization will determine the optimal trades taking into account
the user's tax sensitivity and chosen objective. For instance, the user may choose to minimize total tax liability.
6.
User-Defined Linear Objectives. Other custom linear objectives can be added to the objective function as
well. Axioma Portfolio allows the user to have any number of objective terms grouped in a single objective.
Business Analysis
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 26
Axioma Portfolio
Chapter 3. Portfolio Optimization Basics
Axioma Portfolio provides functionality that automates the calculation of many attributes of the resulting portfolio to
allow quick and thorough analysis of the holdings. Examples of the calculations supported include:
1.
Expected return. The portfolio manager can quickly provide statistics of the expected return of the entire
portfolio or any subset of the holdings in the portfolio.
2.
Transaction costs . The user can easily report the total transaction costs resulting from the rebalancing as
well as the transaction costs for any security or industry. The cost structure may be either linear or piecewise linear.
3.
Market impact. Axioma Portfolio supports automatic calculation of both symmetric and asymmetric market
impact measurements for any set of transactions.
4.
Risk. Axioma Portfolio provides functionality to compute measures of absolute risk and risk relative to a
benchmark for the entire portfolio or a subset of the holdings. In addition, more than one benchmark and
more than one risk model may be used for risk evaluation.
5.
Turnover . Functionality to calculate the total turnover and the turnover in any industry in the portfolio is
provided.
6.
Beta. Axioma Portfolio will automatically compute the beta coefficient of a portfolio.
7.
Holdings. Axioma Portfolio provides functionality to compute useful statistics about the holdings in a portfolio. Methods are available to compute the total portfolio value, the value of both the long and short holdings, as well as the numbers of names held (total, long, and short).
8.
Marginal Contribution To Risk . The marginal contribution to total or to active risk can be easily computed
for an asset or group of assets using Axioma Portfolio analytic functions.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 27
Axioma Portfolio
Chapter 4. Axioma Portfolio Building Blocks
Chapter 4. Axioma Portfolio Building Blocks
This chapter gives an overview of the objects used in Axioma Portfolio.
Object Model
The Axioma Portfolio API provides a set of classes representing entities used in portfolio optimization. A portfolio
optimization problem is defined by creating instantiations of these classes and using their methods. The figure below
gives an overview of the main objects in Axioma Portfolio.
AxiomaPortfolio Object Model
The Workspace object is at the center, with assets, risk models, benchmarks, strategies, etc., connected to it. The
risk model was discussed from a mathematical and optimization perspective in Chapter 3. In this chapter (the section
called “Risk Models”) we will show how a risk model is built using the API. Strategies, business rules and constraints
are discussed in Chapter 5. The objective function is the topic of Chapter 6. Solving the problem is described in
Chapter 8, and solution analysis is covered in Chapter 9.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 28
Axioma Portfolio
Chapter 4. Axioma Portfolio Building Blocks
The Workspace
The Workspace object is the base container for all the elements necessary to run a rebalancing. It contains the assets, risk models, strategies, rebalancings, accounts, benchmarks, groups, and metagroups.
A Workspace object is responsible for managing, discarding and invalidating all of its member objects when these are
no longer needed. This is done by invoking the destroy() method of the Workspace class. All workspace objects
are derived from the IdentifiableObject base class. IdentifiableObject objects have a unique identifier that
can be retrieved by means of the getIdentity() method of the IdentifiableObject class. Please note that the
identity prefix market. is reserved. Giving an identity that starts with market., i.e. market.Prices, will cause issues.
A Workspace object is created in the following way:
Workspace ws = new Workspace("ExWS", "Simple Example Workspace", new Date(), "USD");
As can be seen in the above code, this Workspace class constructor takes parameters corresponding to a unique
name or identifier, an optional workspace description, and a workspace date, and numeraire (the workspace base
currency/ISO currency code), respectively.
"USD" is the default base currency code, if one is not specified via the numeraire parameter. All multi-currency related plugins (Axioma DB plugins, Axioma Flat File plugins, Price attribute plugin etc.,) use the currency code in
workspace to apply currency exchange rate information. When it comes to workspace, all data supplied should be in
terms of the base currency.
The Asset Class
Assets form a core portion of the portfolio optimization model, and accordingly, Axioma Portfolio defines a class with
that name. An Asset object represents an asset in the workspace. In Axioma Portfolio the Asset class is an abstract
class that is the base class for two concrete classes: the SimpleAsset class and the CompositeAsset class.
Simple Assets
A SimpleAsset class represents an object of monetary value that is owned by a firm or an investor. For example,
SimpleAsset objects can represent cash, bonds, stocks, etc.. In Axioma Portfolio, each asset must belong to a
workspace and must have a unique identifier and an optional description. Using ticker names as the IDs, we can add
Assets to the Workspace, ws, for Microsoft, Dell, and Oracle as follows:
Asset msft = new SimpleAsset(ws, "MSFT", "Microsoft");
Asset dell = new SimpleAsset(ws, "DELL", "Dell Computers");
Asset orcl = new SimpleAsset(ws, "ORCL", "Oracle Corporation");
Simple Asset as Cash Asset
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 29
Axioma Portfolio
Chapter 4. Axioma Portfolio Building Blocks
Any simple asset can be declared as cash asset using setAsCash(). There is not a limitation to the number of cash
assets that can be present in a workspace. The price for each cash asset will be set to 1, unless the asset holds a price
already. Similarly, the cash asset gets added to the asset map, if it does not exist already.
SimpleAsset cashAsset = new SimpleAsset(ws_, "CSH_USD", "Cash Asset");
// Set asset as cash
cashAsset.setAsCash();
Composite Assets
A CompositeAsset object is an Asset that is a group of SimpleAsset objects. CompositeAssets can be used to
model such assets as mutual funds, SPDRs, and index futures. A CompositeAsset is defined by a required unique
ID, an optional description, and its composition. The composition is a list of SimpleAssets with associated weights.
The weight of a SimpleAsset defines how many units of this Asset are represented in one unit of the composite.
In order to create a CompositeAsset, a Group containing the composite asset's composition is created and passed
as a parameter to the constructor of the new CompositeAsset object. Valid units for the Group are PERCENT,
SHARES, and CURRENCY. For example, suppose we want to create a CompositeAsset such that for each unit, it
contains 30 percent of MSFT, 50 percent of DELL, and 20 percent of ORCL. This composite asset can be modeled in
Axioma Portfolio as follows:
Group g = new SimpleGroup(ws, "Group", null, Unit.PERCENT);
g.setComposition(msft, 0.3);
g.setComposition(dell, 0.5);
g.setComposition(orcl, 0.2);
Asset ca = new CompositeAsset(ws, "COMPOSITE", "A Composite Asset", g);
Note that CompositeAssets are treated as distinct Assets throughout Axioma Portfolio with the exception of
(active) risk computations (e.g. in constraints, the objective, or analytics). For risk computations, holdings in a CompositeAsset are added to the holdings of its simple components. For that reason, composite assets cannot be added to risk models.
The Account Class
The Account class encapsulates the properties of a portfolio including its asset holdings, budget and reference size,
price and alpha groups, tax rates and settings, transaction cost model, transaction and holding lots, etc.. An Account
can be taxable or non-taxable depending on the type of holdings it contains. That is, if the holdings in an account are
taxable, then the account is itself a taxable account; otherwise, it is non-taxable.
In the next section, we will show how to create taxable and non-taxable holdings. For the moment, assume that a set
of holdings have been created and it is represented by an object called holdings. With the available holdings, we
can create an account using the following statment:
Account account = new Account(ws, "SimpleAccount", "Example of an Account",
ws.getDate(), holdings);
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 30
Axioma Portfolio
Chapter 4. Axioma Portfolio Building Blocks
The Account class constructor takes five parameters: The Workspace object that the account will belong to, the
unique account name or identifier, the optional account description, the account date, and the account holdings.
Once an account has been created, we can set its properties (such as its reference and budget size, its tax code information, its round lots, its alphas group etc.). Alternatively, these properties can be set in a Rebalancing object as
we show in the section called “The Rebalancing Class”.
Account Holdings
As stated before, the account holdings in Axioma Portfolio can be taxable or non-taxable. Taxable holdings are those
holdings to which, as their name implies, tax rules apply. Non-taxable holdings are holdings to which tax rules do not
apply. Taxable holdings in Axioma Portfolio are created using the TaxableHoldings class. Non-taxable holdings in
Axioma Portfolio can be created using either the Java Collection class or Axioma Portfolio NontaxableHoldings class. Taxable holdings contain a collection of HoldingLot and TransactionLot objects, while non-taxable
holdings use a collection of AssetValue objects. The AssetValue class represents an asset-value pair, which in the
case of asset holdings represent an asset and its corresponding holdings in shares.
Please note that all holdings in Axioma Portfolio are expressed in units of shares.
A set of non-taxable holdings is created like this:
Collection holdings = new HashSet();
holdings.add(new AssetValue(ws.getAsset("DELL"), 20000.0));
holdings.add(new AssetValue(ws.getAsset("MSFT"), 8000.0));
holdings.add(new AssetValue(ws.getAsset("IBM"), 32000.0));
...
NontaxableHoldings nonTaxHolds = new NontaxableHoldings(holdings);
In order to construct a set of taxable holdings, we must first create its set of holding lots and transaction lots. A holding lot represents a number of shares of a specific asset that is owned by an investor. It is characterized, in addition to
the asset and number of shares, by the purchase date and the per share purchase price. A transaction lot represents
a transaction that involves the sale of a certain number of shares of a specific asset that was owned by an investor. It
is characterized, in addition to the asset and number of shares, by the purchase date, the per share purchase price,
the sell date, and the per share sell price.
The collection of holding lots and transaction lots are grouped together using an instance of the Java Collection
class. A set of short holding lots and transaction lots are specified as follows:
Collection hlots = new HashSet();
Calendar buyDate = new GregorianCalendar();
buyDate.set(2000,0,2);
hlots.add(new HoldingLot(ws.getAsset("DELL"), buyDate.getTime(), -400.0, 20.0));
buyDate.set(2001,4,13);
hlots.add(new HoldingLot(ws.getAsset("DELL"), buyDate.getTime(), -400.0, 28.0));
buyDate.set(2001,0,2);
hlots.add(new HoldingLot(ws.getAsset("MSFT"), buyDate.getTime(), 75.0, 90.0));
...
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 31
Axioma Portfolio
Chapter 4. Axioma Portfolio Building Blocks
Collection tlots = new HashSet();
Calendar sellDate = new GregorianCalendar();
buyDate.set(2001,0,2);
sellDate.set(2001,6,15);
tlots.add(new TransactionLot(ws.getAsset("MSFT"), -25.0, buyDate.getTime(), 90.0,
sellDate.getTime(), 60.0));
TaxableHoldings taxableHolds = new TaxableHoldings(hlots, tlots);
The Reference Size
Axioma Portfolio allows users to specify constraints in absolute terms as well as in relative terms. The value of reference size is implicitly used in constraints and business rules that are expressed as percentage using the
Unit.PERCENT static class. Reference size is the value upon which all percentages are based. For example, if the reference size is $100,000, and a maximum turnover constraint of 2% is imposed on the portfolio (using
Unit.PERCENT and 2.0), the turnover will be limited to be at most $2,000. Note that in many cases the reference
size will be chosen equal to the investment size. However, this is not required.
The Account and the Rebalancing classes provide the setReferenceSize() and getReferenceSize() methods in order to allow the user to set and retrieve the reference size, respectively. Please note that the reference size
must be strictly positive.
The Budget Size
The budget size is used to control the size of the investment in the portfolio. For example, one possibility is that the
budget (or investment) size is set equal to the sum of the initial holdings of the assets. This in effect means that the
optimization just "rebalances" the existing assets in an optimal way. The total value of the portfolio will remain the
same. Another possibility is that the budget size is set to be larger than the sum of the initial holdings. This results in
increasing the total investment in the portfolio by the difference between the budget size and the sum of the initial
holdings. For instance, this occurs if there is a new inflow of cash. Finally, if the budget size is set to be smaller than
the sum of current assets then this results in a reduction in the total investment in the portfolio. This approach can be
used to model a withdrawal of funds from the account.
Some examples will make this clearer. Say your current initial holdings are $100. You set the budget size to be $120.
Then, after rebalancing (i.e., after optimization), the total value of assets in the portfolio will be $120. One way to
think about this is that an additional $20 in cash is implicitly added to the pre-optimized portfolio and then the optimization is run. The optimization model will then determine the best use for the cash. If no asset representing cash has
been defined, then these new funds will be invested in non-cash assets. If a cash asset has been defined, then the optimization will determine whether these new funds should be invested or kept as cash.
Consider the other case. Say the current holdings are $100 and the budget size is set to $80. This means that the
new (optimized) portfolio will have only $80 in value, and will result in $20 in cash being extracted from the portfolio.
(This cash is technically "outside" or not included in the optimized portfolio since it is not counted in the investment
size).
Note that the Account and the Rebalancing classes provide a method called getBudgetSize() to retrieve the
budget size. In addition, the boolean method hasBudgetSize() returns true if a budget size has been specified.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 32
Axioma Portfolio
Chapter 4. Axioma Portfolio Building Blocks
The budget size for an account or a rebalancing can be set using the setBudgetSize() method of the Rebalancing and Account classes.
Risk Models
Axioma Portfolio supports both factor risk models and dense/full covariance risk models. A single portfolio optimization problem may use several risk models of different types representing different industries, countries or economic
markets.
In the following, we explain how to create these risk models. In the next chapter (Chapter 5) we will describe how
these risk models can be incorporated in constraints and business goals.
The FactorRiskModel Class
Axioma Portfolio supports risk estimation using a factor-based risk model. This functionality is provided by the class
FactorRiskModel. An instance of this class is comprised of factors, and exposure and covariance matrices. In addition, a risk model contains the specific risk for each of the assets that it spans.
As was indicated in Chapter 2, before a FactorRiskModel can be constructed, we must first define its input parameters (i.e. the set of asset specific risks, the factor-factor covariance matrix, the asset-factor exposure matrix, and
the factor names as an array of Strings), which are required by the FactorRiskModel class constructor.
The specific risks are defined as a set of AssetValue objects. An AssetValue object is an object containing an asset
and a corresponding value. In this case, the value is the asset risk. One AssetValue object is created for each asset
spanned by the risk model. Assuming that the assets have already been created and that they can thus be retrieved
from the workspace, the set of asset specific risks is created in this way:
Set specificRisks = new HashSet();
specificRisks.add(new AssetValue(ws.getAsset("DELL"), 0.42));
specificRisks.add(new AssetValue(ws.getAsset("MSFT"), 0.23));
...
where ws represents the parent workspace. Note that the specific risk is entered in units of standard deviation (in percent or currency), not as a variance.
In a factor-based risk model, the covariance matrix represents the correlation between the risk factors, or in other
words, it expresses how the risk factors relate to each other. The covariance matrix must be positive semidefinite,
otherwise an IllegalArgumentException will be thrown. Also note that the units of the covariance are squared
units. In Axioma Portfolio, the covariance matrix is defined as an nxn array of doubles (where n is the number of risk
factors in the risk model). For example, a two dimensional covariance matrix would be defined like this:
double[][] covariances = new double[][]
{
{ 0.0024, -0.00011 },
{ -0.00011, 0.00099 }
};
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 33
Axioma Portfolio
Chapter 4. Axioma Portfolio Building Blocks
The exposures of the assets to the factors are defined as a set of asset-value pairs (or AssetValue objects) representing the exposure of each asset to the corresponding risk factor. For example, assuming that the risk model contains only two risk factors, the exposures for two assets, say IBM and SAP, could be defined in the following way:
Set factor1 = new HashSet();
Set factor2 = new HashSet();
factor1.add(new AssetValue(ws.getAsset("IBM"), 0.1));
factor1.add(new AssetValue(ws.getAsset("SAP"), 0.76));
factor2.add(new AssetValue(ws.getAsset("IBM"), 0.9));
factor2.add(new AssetValue(ws.getAsset("SAP"), 0.98));
If an entry is not explicitly provided, the value of 0.0 will be assumed. For example, if MSFT is spanned by this risk
model, then its exposures to the two risk factors is 0.0 since we have not explicitly specified any values.
Next, we assign names to the risk factors and group the factor exposures in a Set so that we can use them in the
constructor of the factor risk model, as we will see shortly. The following statements assign the names Factor1 and
Factor2 to the two risk factors and create a set of factor exposures represented by the variable factorExposures:
String[] factors = { "Factor1", "Factor2" };
Set[] factorExposures = new Set[]{ factor1, factor2 };
Assuming that all of the required inputs have been defined, the FactorRiskModel object can be constructed with
the following statement:
FactorRiskModel frm = new FactorRiskModel(ws, "FRM", "SmallFactorRiskModel", new Date(),
specificRisks, factorNames, factorExposures, covariances, null);
This creates a FactorRiskModel object named frm. The first argument of the constructor is a reference to the
parent workspace, the second argument is the risk model's name, the third argument is the optional risk model's description, the fourth argument is the risk model date, the fifth argument is the set of asset specific risks, the sixth argument is the risk factor names (as an array of String objects), the seventh argument is the asset factor exposures,
the eighth argument is the covariance matrix, and the ninth argument is the optional set of factor descriptions.
The FactorRiskModel is now complete. There are many additional methods that are part of this class. Some of the
obvious ones are used to retrieve information from the risk model, e.g., getIdentity(), getDescription(),
getAssets(), getFactorNames(), getFactorCount(), getSpecificRisk(), getCovarianceElements()
and containsCompositeAssets(). These are described (along with argument syntax) in detail in the Axioma Portfolio JavaDocs [index.html]. We now describe a few of the less obvious methods of the FactorRiskModel class.
For each risk factor in a factor risk model, it is possible to retrieve the exposures for all of the assets spanned by the
risk model as a RiskfactorGroup object. This is done using the getRiskfactorGroup() method, as in:
RiskfactorGroup rfg = frm.getRiskfactorGroup("VOLTILTY");
This returns factor exposures for all the assets in the risk model for the specified risk factor. In this case, the exposures for the risk factor VOLTILTY is returned; that is assuming that VOLTILTY is one of the risk factors of the risk
model and that the factor exposures are not all zero. Note that if a factor name is used that does not exist, the function will throw an IllegalArgumentException (described in Chapter 13).
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 34
Axioma Portfolio
Chapter 4. Axioma Portfolio Building Blocks
The risk model serves a central role in the Axioma Portfolio API, and therefore, we point out its important features.
First of all, a problem can be set up with more than one risk model. Second, assets in the asset universe (the set of
potential investments) may or may not be members of a risk model. Third, a risk model may contain additional assets
that are not in the local asset universe.
This last point is important. A risk model may include a much larger set of investment opportunities than you wish to
consider for a particular portfolio. It is not necessary to pare down the risk model to fit your needs (in terms of the
asset universe you want) for each individual portfolio optimization problem. Axioma Portfolio facilitates the reuse of
risk models. Instead of constructing a customized risk model for each individual investment problem, you may use
the entire risk model in all cases. Only those assets that you are currently considering as potential investments (the
asset universe) need to be specified using the Asset constructor.
Axioma regional and global models by default have most of the risk concentrated on the market factor. The risk from
market factor can be moved to other factors, using shiftFactorRisk method. Assume f1 is the name of the market factor and f2, f3 are names of industry factors, the risk from market factor can be moved to industry factors using:
List targetFactors = new ArrayList<RiskfactorGroup>();
targetFactors.add(frm.getRiskfactorGroup("f2"));
targetFactors.add(frm.getRiskfactorGroup("f3"));
FactorRiskModel shiftedFrm = frm_.shiftFactorRisk(frm_.getRiskfactorGroup("f1"), targetFactors_);
This call is cached, meaning if you call the method with the same set of parameters multiple times, it will return the
same FactorRiskModel each time. Also, the total risk of shiftedFrm and frm_ will be the same. Only the risk is shifted from market factor to target factors.
The DenseRiskModel Class
In Axioma Portfolio, it is possible to define a dense, or full covariance, risk model. In a dense risk model, risk is estimated using a covariance matrix spanning all asset combinations and no factors. This dense risk model is specified using
the class DenseRiskModel. An instance of this class is comprised of a set of assets as well as a covariance matrix
spanning these assets.
The DenseRiskModel class has two constructors with different input parameters. The simplest constructor accepts
a parent workspace, an array of Asset's, and an array of double values representing the asset-asset covariance matrix. The other constructor accepts, in addition to the aforementioned parameters, a required name or identity for
the risk model, an optional risk model description, and a date. For the purpose of this document, we'll consider the
simplest constructor only.
An instance of the DenseRiskModel class is constructed with the statement:
DenseRiskModel drm = new DenseRiskModel(ws, assets, covariances);
This creates a DenseRiskModel object named drm. The first argument of the constructor is a reference to the parent workspace object, the second argument is an array of Asset's (i.e. the assets spanned by this dense risk model),
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 35
Axioma Portfolio
Chapter 4. Axioma Portfolio Building Blocks
and the third argument is the asset-asset covariance matrix as an nxn array of doubles, where n is the number of assets. It is assumed that these arguments have been previously defined. Since a name or identifier was not given, one is
generated automatically by the API.
The covariance matrix must be positive semidefinite otherwise an IllegalArgumentException will be thrown.
Note finally that the units of the covariance are squared units.
The Goldman Sachs® Shortfall Model Class
The GoldmanSachsShortfallModel class is used to store encrypted Goldman Sachs Shortfall models. These
models can be used to supply the required data for a GoldmanSachsShortfallTerm. The model consists of a set
of assets and their associated data, which is encrypted data and the checksums for that encrypted data.
In the following, we explain how to create this model. In (Chapter 6) we will describe how these models can be incorporated into a GoldmanSachsShortfallTerm objective.
An instance of the GoldmanSachsShortfallModel class is constructed with the statement:
GoldmanSachsShortfallModel gssm_ = new GoldmanSachsShortfallModel(ws_, "gssm", null, null);
gssm_.setShortfallInfo(a1_, "^_dq#/=7CLYi$9QSgx2Nj&F", 895347441L);
gssm_.setShortfallInfo(a2_, "^_hv\")93=FWhz6I]`u,Ic&@b", 4192448245L);
gssm_.setShortfallInfo(a3_, "_`lq{+93?H[l{56L\\o/Ea$", 2264452990L);
gssm_.setShortfallInfo(a4_, "bckw)7E?JSh{5GY[o%BXq3N", 3695110181L);
This creates a GoldmanSachsShortfallModel object named gssm_ that belongs to the specified Worspace object and
whose identity, description and date are set to the specified values. The first argument of the constructor is a reference to the parent workspace object, the second argument is a required string unique identifier, the third is a optional string description that can be null and the fourth argument is a Date object that represents the Goldman Sachs
Shortfall Model date.
The next 4 lines of code after the constructor set shortfall information (encrypted shortfall information, checksum for
encrypted data) for the specified asset. The first parameter of the setShortfallInfo method is the asset whose
shortfall information is to be set, the second argument is the encrypted shortfall information and last is the checksum
for the encrypted shortfall information. NOTE: If asset already exists in the model, then it overwrites the old value.
This product as enhanced with the Goldman Sachs Shortfall Model ("Shortfall Model") generates Shortfall estimates,
and such Shortfall estimates may not be identical to Shortfall estimates generated with the Shortfall Model in a different operating environment. Such differences may arise due to processing requirements (e.g., portfolio optimization
requirements) of the operating environment. Please contact your Axioma representative for further information.
The Shortfall Model produces information that is additional to, and compiled in a format differing from, that required
under applicable regulations to which regulated financial institutions and broker-dealers are subject. Goldman, Sachs
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 36
Axioma Portfolio
Chapter 4. Axioma Portfolio Building Blocks
& Co. and/or its affiliates ("GS") have taken reasonable steps to ensure such information and/or formatting
("Materials"), as provided to Axioma, Inc. for use in this product is accurate and complete, but apprise the user that
this information and/or formatting is being furnished "AS IS" as a courtesy. GS DISCLAIMS ALL REPRESENTATIONS AND
WARRANTIES, EXPRESS OR IMPLIED, RELATING TO THE MATERIALS, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, SECURITY AND NON-INFRINGEMENT. The
Materials are not an official report and, as such, GS is not responsible for any errors or omissions. GS does not represent that the Materials are accurate, complete and/or current and does not accept liability for losses or damages
arising from use of this information and/or formatting. GS SHALL UNDER NO CIRCUMSTANCES BE HELD LIABLE
WHETHER IN CONTRACT, IN TORT, UNDER ANY WARRANTY OR ANY OTHER THEORY OF LIABILITY, FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR PUNITIVE DAMAGES, INCLUDING BUT NOT LIMITED TO, LOSS
OF REVENUE, LOSS OF PROFITS, LOSS OF OPPORTUNITY, BUSINESS DISRUPTION OR OTHER PECUNIARY LOSS
ARISING OUT OF THE USE OF OR INABILITY TO USE THE MATERIALS, EVEN IF GS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. In the event of any discrepancy between the Materials and the terms set forth in any
official confirmation or statement with respect to a particular transaction or transactions, the terms of the official
confirmation or statement shall govern.
The Strategy Class
A strategy captures all the information about the optimization options, objectives and constraints used to rebalance a
portfolio. In Axioma Portfolio, every constraint and objective is constructed as part of a Strategy object. That is, a
constraint or an objective must belong to a Strategy object. This requirement is enforced by means of the constraint and objective constructors which require a parent strategy.
In addition to constraints and objectives, a Strategy object also contains a set of optimization options that dictate
how a portfolio rebalancing that uses that strategy is performed. For example, whether crossover, grandfathering,
shorting, etc. are permitted for the optimization process can be controlled by means of the strategy optimization options.
A strategy is constructed using the following statement:
Strategy strategy = new Strategy(ws, "SimpleStrategy", null, ws.getDate());
The constructor of the Strategy class takes four parameters. The first parameter is the Workspace that the
strategy belongs to. The second parameter is the strategy's name. The third parameter is the optional strategy's description. And the fourth parameter is the strategy's date.
Finally, a strategy can also contain ObjectiveTerm, ConstraintTerm and Decomposition objects. These are
covered in Chapter 5, Chapter 6 and Chapter 7.
The Rebalancing Class
The Rebalancing class represents a rebalancing instance. It contains the problem definition based on the account,
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 37
Axioma Portfolio
Chapter 4. Axioma Portfolio Building Blocks
the trasaction cost model, the market impact, the round lots, and the strategy. In addition, it includes parameters that
can be used to affect the optimization process. For example, the optimization search strategy and the modeling of
the risk constraints, risk objectives, and quadratic transaction costs can be controlled by means of the available option
parameters. The following risk approximations are available:
➤ RiskApproximation.NONE,
➤ RiskApproximation.SIMPLE, and
➤ RiskApproximation.BCN.
A rebalancing object consists of settings that dictate how the rebalancing should be performed, a starting account, a
strategy for rebalancing the account and, if the portfolio has been rebalanced, a solution representing the rebalancing
results.
A Rebalancing object is created as follows:
Rebalancing rebal = new Rebalancing(ws, account, "SimpleRebalancing", null, ws.getDate());
The constructor of the Rebalancing class takes five arguments. The first argument is the workspace object that the
rebalancing will belong to, the second argument is the account that will be rebalanced, the third argument is the rebalancing name, the fourth argument is the optinal rebalancing description, and the fifth argument is the rebalancing
date.
Round Lotting
Axioma Portfolio supports round lotting. That is, given a round lot size of, for instance, 100 shares, Axioma Portfolio
ensures that all transactions will be in multiples of 100 shares. These round lot units can be specified at the assetlevel, and thus can differ by asset. Round lotting is done automatically if an asset's round lot unit is defined and it is
positive and non-zero. The assets' round lots are specified by invoking the setRoundLotGroup() method of the
Rebalancing class. This method accepts a single parameter: a SimpleGroup object consisting of the asset and lot
size (always in shares). This is done as follows:
SimpleGroup rlg = new SimpleGroup(ws, "RoundLotGroup", null, ws.getDate(), Unit.SHARES);
rlg.setComposition(ws.getAsset("DELL"), 100.0);
rlg.setComposition(ws.getAsset("MSFT"), 500.0);
rlg.setComposition(ws.getAsset("IBM"), 100.0);
...
rebal.setRoundLotGroup(ws.getGroup("RoundLotGroup"));
Provided that the assets round lots have been specified for a particular rebalancing, round lotting will be done automatically by Axioma Portfolio, i.e., there is no special function to call or other parameters to set. In the example
above, to obtain the optimized holdings (from the initial holdings) will require trading DELL and IBM in units of 100
shares (if at all), and trading MSFT in units of 500 shares (if at all).
An example of round lotting (called RoundLotExample.java) is provided in the examples folder in the product
distribution.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 38
Axioma Portfolio
Chapter 4. Axioma Portfolio Building Blocks
A number of additional methods are available on the Rebalancing class. Some of these are described in the section
called “Additional Rebalancing Methods” .
Asset Groups
Collections of assets are critical building blocks for writing constraints, specifying objective function terms, or performing analyses of results. For this purpose, Axioma Portfolio defines three classes: the SimpleGroup, the
RiskfactorGroup, and the AssetSet classes. The first two classes represent group of assets (weighted collection
of assets) while the third class represents a set of assets (a collection of assets that does not include asset weights).
A SimpleGroup is a set of assets with associated weights. The weights in a SimpleGroup generally represent the
assets' exposure to an industry or factor, but can serve other purposes as well. For instance, a group can be used to
represent the expected returns for a set of assets or the round lots that apply to each asset. A TextGroup is a set of
assets with associated text. The text value can be any string. A text group can be created by selecting Unit as TEXT.
Note, a TextGroup cannot be used for analytics or optimization purposes.
Let's consider the AssetSet first. An AssetSet object is created as follows:
AssetSet mySet = new AssetSet(ws, "AssetSet", "An Asset Set", ws.getDate());
mySet.includeAsset(ws.getAsset("DELL"));
mySet.includeAsset(ws.getAsset("MSFT"));
mySet.includeAsset(ws.getAsset("IBM"));
This defines a set of assets called mySet containing DELL, MSFT, and IBM. The constructor of the AssetSet class
takes the following parameters: the workspace that the asset set will belong to, the unique asset set's name, the optional asset set's description, and the asset set's date. The assets to be included in the asset set are added using the
includeAsset() method of the AssetSet class. Assets from another asset set, a group or a metagroup can be added to an asset set using the includeAssetSet(), includeGroup(), or includeMetagroup() methods of the
AssetSet class. Assets, sets, groups, and metagroups can be excluded using the appropriate excludeAsset(),
excludeAssetSet(), excludeGroup(), or excludeMetagroup(), methods of the AssetSet class.
Constraints, such as limiting the number of names held within a set of assets, can then be defined using this AssetSet. This will be described in detail in Chapter 5.
A set of assets and weights (a Group) can also be easily constructed, as in:
Group myIndustry = new SimpleGroup(ws, "myInd", "An Industry Group", Unit.NUMBER);
myIndustry.setComposition(ws.getAsset("TSG"), 1);
myIndustry.setComposition(ws.getAsset("DELL"), 1);
myIndustry.setComposition(ws.getAsset("ARBA"), 0.5);
A set of assets and text (a Group) can also be constructed, as in:
Group myIndustry = new TextGroup(ws,"myInd", "An Industry Text Group", Unit.TEXT);
myIndustry.setComposition(ws.getAsset("TSG"), "BUY");
myIndustry.setComposition(ws.getAsset("DELL"), "HOLD");
myIndustry.setComposition(ws.getAsset("ARBA"), "SELL");
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 39
Axioma Portfolio
Chapter 4. Axioma Portfolio Building Blocks
There are several methods that can be used when dealing with groups. For example, the getCompositionSum()
method of the Group class returns the group net weight (the sum of the individual asset weights in the group). In the
above defined myIndustry group, the code:
double groupWeight = myIndustry.getCompositionSum();
assigns the value 2.5 to groupWeight.
A collection of non text groups in a workspace can be obtained from getNonTextGroups().
Collection sg = ws.getNonTextGroups()
Other group methods include: containsAsset(), containsCompositeAssets(), getAssetCount(), getUnit(), setUnit(), etc., with obvious results and functionalities.
There is also a number of Groups that are defined implicitly and automatically when a portfolio model is created.
These involve the assets with a non-zero exposure to certain factors (or industries) in the risk model. These special
groups are instances of the RiskfactorGroup class and can be easily extracted, as in:
Industry ind = frm.getRiskFactorGroup("CMPTRHW");
Here ind will contain all assets in the factor risk model frm which have a strictly positive exposure to the "CMPTRHW" factor. The weight for each asset in ind will be the exposure. This is convenient for expressing constraints
on industries or factors defined in a risk model (see the section called “Industry Constraints”), among other things.
It is also possible to retrieve all of the RiskfactorGroups of a factor risk model at once as illustrated in the following sample code:
java.util.Set rfg = frm.getRiskFactors();
The getRiskFactors() method of the FactorRiskModel class returns the set of RiskfactorGroup objects
that represent the asset exposures to each factor spanning the risk model.
Benchmarks
The Benchmark class extends the SimpleGroup class and it is used to specify benchmarks in a portfolio optimization problem. There are two important characteristics of a Benchmark object. First, a Benchmark object is automatically scaled to the referenced size of the rebalancing where it is being used to specify an active constraint or objective. Second, the units of a Benchmark object are restricted to SHARES, CURRENCY, or PERCENT.
It is important here to stress a critical issue related to the benchmark holdings. In order for certain constraints (in
particular, active holdings constraints and active risk constraints) to be accurately incorporated into a model, the
benchmark weights must be scaled so that their sum is equal to the portfolio's investment size. If a Group object is an instance of the Benchmark class, its holdings or asset compositions will be scaled automatically by Axioma Portfolio to
prevent unexpected results.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 40
Axioma Portfolio
Chapter 4. Axioma Portfolio Building Blocks
A Benchmark object is created in the following way:
Benchmark bm = new Benchmark(ws, "simpleBM", "Simple Benchmark", ws.getDate(), Unit.CURRENCY);
bm.setComposition(ws.getAsset("DELL"), 30000.0);
bm.setComposition(ws.getAsset("MSFT"), 12000.0);
bm.setComposition(ws.getAsset("IBM"), 23000.0);
bm.setComposition(ws.getAsset("ORCL"), 35000.0);
In the above code, the user has created a benchmark bm by using the Benchmark constructor, which takes the following parameters: the workspace object that the Benchmark object will belong to, the benchmark's required name
or identity, the benchmark's optional description, the benchmark's date, and the benchmark's unit. Once the benchmark has been created, it should be populated. The setComposition() method of the Benchmark class is used to
add the assets and their weights that we wish to include in the Benchmark object.
Metagroups
A metagroup is a collection of groups and/or other metagroups with associated weights. A metagroup could be used
to represent, for example, a sector. Metagroups are created as instances of the Metagroup class in Axioma Portfolio
as illustrated in the following code sample:
Group wireless = new SimpleGroup(ws, "WT", "Wireless Telecommunications Group", Unit.NUMBER);
wireless.setComposition(verizon, 0.34);
wireless.setComposition(nextel, 0.95);
wireless.setComposition(quest, 0.08);
Group telephone = new SimpleGroup(ws, "TT", "Telephone Telecomunications Group", Unit.NUMBER);
telephone.setComposition(verizon, 0.66);
telephone.setComposition(nextel, 0.05);
telephone.setComposition(quest, 0.92);
Metagroup telecom = new Metagroup(ws, "Tel", "Telecommunications Metagroup", ws.getDate());
telecom.addGroup(wireless, 1.0);
telecom.addGroup(telephone, 1.0);
Above, we first created two groups representing the wireless and the telephone industries. Then we created the metagroup called telecom representing a sector. We added the wireless and telephone groups to the telecom
sector using the addGroup() method of the Metagroup class. The constructor of the Metagroup class takes four
parameters: the workspace that the metagroup will belong to, the unique metagroup name or identifier, the optional
metagroup description, and the metagroup date, in this order.
A metagroup is considered to be a partition if the sum of the weight distribution among the groups of each asset
equals 1.
Note that a metagroup cannot contain itself.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 41
Axioma Portfolio
Chapter 4. Axioma Portfolio Building Blocks
Additional Rebalancing Methods
Now that we have introduced a number of classes that can be used to create objects representing various portfolio
related entities, we turn to the Rebalancing class and describe briefly some of the additional methods that it
provides.
The most significant method that the Rebalancing class offers is the the solve() method. This method is used to
perform an account rebalancing or, in other words, to optimize an initial portfolio (see Chapter 8). Once a rebalancing has been solved, its optimized solution can be retrieved by means of the Rebalancing's class getSolution()
method. This method returns an instance of the RebalancingSolution class containing the initial and final
(optimized) holdings, the initial and final objective values, the number of shares traded in transitioning from the initial
holdings to the final holdings, and the set of assets traded. The properties of the RebalancingSolution class is
covered in Chapter 9). Other methods of the Rebalancing can be classified as getters and setters for optimization
parameters that, as was mentioned before, affect the optimization process, and getters and setters of data structures
or attributes that are needed in order to perform an account rebalancing. Among the getter and setter methods for
the optimization parameters we find: setRiskApproximation(), getRiskApproximation(),
setRunTimeMax(), getRunTimeMax(), setRunTimeMin(), getRunTimeMin(), setBranchBoundMethod(),
and getBranchBoundMethod(). Among the getter and setter methods that can be used to set or retrieve the objects containing information necessary to perform an account rebalancing or to set or retrieve some of the rebalancing attributes we find: setAccount(), getAccount(), setStrategy(), getStrategy(), setBudgetSize(),
getBudgetSize(), setReferenceSize(), getReferenceSize(), setRoundLotGroup(), getRoundLotGroup(), setTransactionCostModel(), getTransactionCostModel(), etc.. The getAccount() method
returns the account contained in the rebalancing object. The returned Account object can be used in turn to retrieve the set of assets in the asset universe by means of its getAssets() method.
Setting up API
There are two static methods in AxiomaPortfolioAPI - setUp() and tearDown(). setUp() should be called before creating any workspace(s) and before any threads are started. tearDown() should be called when all workspace(s) are destroyed and after all threads are done.
Creating a workspace connected to database
A workspace can be built by connecting to an Axioma Portfolio Analytics database. The class DatabaseMasterProviderDAO can be used to connect to the database and bring in various elements to the workspace. These elements
can include assets, riskmodels, attributes and accounts. The DatabaseMasterProviderDAO class takes some required and optional properties. The values host, port, database vendor, database name, username, and password are
used connect to the database. They are passed as required properties to the DatabaseMasterProviderDAO class.
The riskmodels, accounts, and groups can be brought into the workspace by providing them as optional properties.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 42
Axioma Portfolio
Chapter 4. Axioma Portfolio Building Blocks
The assets in the groups and accounts get added to the workspace automatically. The fundamental attributes, asset
maps, factor covariances, factor specific risk and factor specific covariances get updated for the assets added to the
workspace.
If unknown, the properties required to connect to the Axioma Portfolio Analytics database can be obtained from the
preferences of the Axioma Portfolio Optimizer GUI. The preference window in the GUI also includes a tool that is
useful for converting a plain text password into the encoded password required to pass to the database.
AxiomaPortfolioOptimizer Connection Preferences
There are two ways that can be used in order to create a workspace using the Axioma DBConnector:
1. Database Connection
From v6.14, a few changes have been made in the properties to connect to a database. Four new properties have
been added for host, port, vendor and the database name. Before v6.14, the property PROP_REQ_DATABASE_URL
used to be used for this information. That property is still supported for backward compatibility and will be deprecated in future releases.
Calendar cal = Calendar.getInstance();
cal.set(2009, Calendar.MAY, 29);
// Change the database host
private final static String DB_HOST = "localhost";
// Change the database port
private final static String DB_PORT = "1433";
// Set the database vendor. Constants.VENDOR_SQLSERVER and
// Constants.VENDOR_POSTGRES are valid options
private final static String DB_VENDOR = Constants.VENDOR_SQLSERVER;
// Change the database name
private final static String DB_NAME = "axiomadb";
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 43
Axioma Portfolio
Chapter 4. Axioma Portfolio Building Blocks
// Create the Properties object used with DatabaseMasterProviderDAO
Properties dbmstrprops = new Properties();
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_REQ_DATA_CONNECTION_TYPE,
DataConnectionMode.DATABASE_CONNECTION.toString());
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_REQ_DATABASE_HOST, DB_HOST);
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_REQ_DATABASE_PORT, DB_PORT);
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_REQ_DATABASE_VENDOR, DB_VENDOR);
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_REQ_DATABASE_NAME, DB_NAME);
// Use the above 4 properties or the PROP_OPT_DATABASE_URL property,
// which will be depricated in future releases.
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_OPT_DATABASE_URL, dburl_);
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_REQ_DATABASE_PWD, "nMSgpwmb");
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_REQ_DATABASE_APP_USERID, "axioma");
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_REQ_DATABASE_APP_PWD, "nMSgpwmb");
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_OPT_RISKMODEL_ID, "WW21AxiomaMH");
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_OPT_BENCHMARK_IDS, "market.FTSE All-World");
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_OPT_USER_ATTS, "MyAlpha");
// Construct workspace
ws_ = new Workspace("TestWorkspace", null, cal.getTime());
ws_.setAutoNotifyDataProviders(false);
try{
DatabaseMasterProviderDAO dbmstrDAO = new DatabaseMasterProviderDAO();
dbmstrDAO.setProperties(dbmstrprops);
ws_.setAssetProvider(dbmstrDAO);
ws_.addDataProvider(dbmstrDAO);
ws_.setAutoNotifyDataProviders(true);
}
catch (Exception ex){
ex.printStackTrace();
}
2. Webservices Connection - In order to use webservices, just replace the dbmstrprops from the above to:
// Create the Properties object used with DatabaseMasterProviderDAO
Properties dbmstrprops = new Properties();
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_REQ_DATA_CONNECTION_TYPE,
DataConnectionMode.WEB_SERVICES_CONNECTION.toString());
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_REQ_WEBSERVICE_PROTOCOL, "http");
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_REQ_WEBSERVICE_HOST, "localhost");
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_REQ_WEBSERVICE_PORT, "8080");
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_REQ_WEBSERVICE_CONTEXT, "websrv-context");
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_REQ_WEBSERVICE_USERID, "axioma");
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_REQ_WEBSERVICE_PWD, "nMSgpwmb");
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_OPT_RISKMODEL_ID, "WW21AxiomaMH");
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_OPT_BENCHMARK_IDS, "market.FTSE All-World");
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_OPT_USER_ATTS, "MyAlpha");
// Construct workspace
ws_ = new Workspace("TestWorkspace", null, cal.getTime());
ws_.setAutoNotifyDataProviders(false);
try{
DatabaseMasterProviderDAO dbmstrDAO = new DatabaseMasterProviderDAO();
dbmstrDAO.setProperties(dbmstrprops);
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 44
Axioma Portfolio
Chapter 4. Axioma Portfolio Building Blocks
ws_.setAssetProvider(dbmstrDAO);
ws_.addDataProvider(dbmstrDAO);
ws_.setAutoNotifyDataProviders(true);
}
catch (Exception ex){
ex.printStackTrace();
}
From v6.14, Lookback functionality enables the application to lookback a specified number of days in the database
for the most recent corresponding data, if data for current date is unavailable. Lookback functionality is supported in
v7.7 or greater. To enable the lookback functionality, add the following properties.
// By default, this property is set to false. To support lookback, set the property to true.
dbmstrprops.setProperty(DatabaseProviderDAO.PROP_OPT_DO_LOOKBACK, "true");
//Set the number of lookback days.
dbmstrprops.setProperty(DatabaseMasterProviderDAO.PROP_OPT_LOOKBACK_DAYS, "7");
Note: In the above examples, the database properties didn't have the property DatabaseMasterProviderDAO.PROP_OPT_DATE. In that case, the DatabaseMasterProviderDAO defaults to the workspace date. If we want
to connect to the database for a date different than the workspace date, use dbmstrprops.setProperty(DatabaseMasterProviderDAO.PROP_OPT_DATE, "20090701")
The date string for the above property should always be yyyyMMdd format. Other date formats aren't supported.
Note
If data is stored on a Red Hat server and you are experiencing problems with your data connection, please
contact <support@axioma.com>.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 45
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
Chapter 5. Bounds, Constraints, and Business Rules
In this section, we show how to specify many of the constraints and business rules available through the Axioma
Portfolio API. For a complete listing of all the constraint classes see the Axioma Portfolio JavaDocs [index.html]. Many
of the code snippets found in this chapter can also be found in the examples provided in the distribution (see the examples folder). In particular, many of the constraints listed below can be found in the ConstraintsExample.java
example.
Axioma Portfolio provides many specialized classes for specifying business rules in portfolio management language.
These rules deal with holdings, transactions, and risk. In addition, Axioma Portfolio provides several generic constraint classes that can be used to specify customized restrictions.
In Axioma Portfolio, constraints are classified as either Collective constraints or as Selection constraints. Collective constraints are constraints that implicitly apply to all of the assets in a rebalancing account as whole, while Selection constraints are constraints that apply to a selected group of assets. Examples of Collective constraints are BudgetConstraint and LimitTaxLiabilityConstraint. Examples of Selection constraints are LimitHoldingConstraint and LimitTurnoverConstraint. We will examine each of these contraint types in the following sections
and provide examples.
As described in the section called “The Strategy Class”, every constraint and objective in Axioma Portfolio must belong to a strategy. Furthermore, the constraints and objectives in a strategy are included in a rebalancing object and
applied to the portfolio optimization problem when the solve() method of the Rebalancing class is invoked (see
Chapter 8 for more information on this issue). We, therefore assume that a Strategy object called strategy and a
Rebalancing object named rebal have been created and that we can use them in this section for illustration purposes.
The ConstraintProperties and the Constraint.Scope Classes
Before we begin our discussion about constraints, it is important to introduce two classes that play a central role in
the construction of constraints in Axioma Portfolio: the ConstraintProperties class and the Constraint.Scope class.
The properties or characteristics of a constraint are specified in Axioma Portfolio by means of an instance of the
ConstraintProperties class. For example, the bounds on a constraint (minimum and maximum), the constraint
scope, the benchmark that the constraint is measured relative to (for active constraints), the risk model (for risk constraints), the constraint units, etc., are specified using the ConstraintProperties class. Additionally, minimum and
maximum values group are constraint selection properties which are applicable to asset set selection and when scope
is asset. For example:
LimitHoldingConstraint lhcon2 = new LimitHoldingConstraint(strat_, "lhcon2", "LHC");
ConstraintProperties cp2 = new ConstraintProperties();
cp2.setProperty(ConstraintProperties.Property.UNIT, Unit.CURRENCY);
cp2.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.ASSET);
lhcon2.setProperties(cp2);
ConstraintProperties selcp7 = new ConstraintProperties();
selcp7.setProperty(ConstraintProperties.Property.MIN_VALUES_GROUP, minGroup_.getIdentity());
selcp7.setProperty(ConstraintProperties.Property.MAX_VALUES_GROUP, maxGroup_.getIdentity());
lhcon2.addAssetSetSelection(minMaxSet_, selcp7);
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 46
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
Here in the above example, we get the min value of the assets from minGroup and similarly max values for the assets
from maxGroup. These selection properties are applied to the minMaxSet_ using addAssetSelection()
Also, we can get minimum and maximum values from metagroup using minimum and maximum values metagroup as
constraint selection properties, which are applicable to metagroup selection and when scope is member. For example:
LimitHoldingConstraint lhcon2 = new LimitHoldingConstraint(strat_, "lhcon2", "LHC");
ConstraintProperties cp2 = new ConstraintProperties();
cp2.setProperty(ConstraintProperties.Property.UNIT, Unit.CURRENCY);
cp2.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.MEMBER);
lhcon2.setProperties(cp2);
ConstraintProperties selcp7 = new ConstraintProperties();
selcp7.setProperty(ConstraintProperties.Property.MIN_VALUES_METAGROUP, minMG_.getIdentity());
selcp7.setProperty(ConstraintProperties.Property.MAX_VALUES_METAGROUP, maxMG_.getIdentity());
lhcon2.addMetagroupSelection(unWeightedMG, selcp7);
Here in the above example, we get the min value of the elements in unWeightedMG from minMG and similarly max
values for the elements in unWeighedMG from maxMG. These selection properties are applied to unWeightedMG
using addMetagroupSelection()
The Constraint.Scope class provides a representation of constraint scopes. Scopes indicate the extent to which a
constraint is applied in Axioma Portfolio. For example, when a constraint is constructed with a group of assets, the
constraint could be applied to the group as a whole or to each individual asset in the group. The constraint scope
helps resolve this apparent ambiguity.
There are four types of constraint scopes available in Axioma Portfolio:
➤ ASSET: a separate constraint is constructed for each asset in the specified group of assets.
➤ AGGREGATE: a single constraint is constructed for all of the assets in the selected group or groups of assets.
➤ SELECTION: a separate constraint is constructed for each of the selection.
➤ MEMBER: a separate constraint is constructed for each of the first level children of the selection.
Constraint Scopes and Units
The scopes and units related to a constraint can be obtained using the constraint name. For example to get the scope
units map related LimitHoldingConstraint
LinkedHashMap su = LimitHoldingConstraint.getScopesAndUnits();
Similarly, all the available scopes and units can also be obtained as follows.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 47
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
Collection scopes = getAvailableScopes(su);
ArrayList units = getAvailableUnits(su);
Collective Constraints
A collective constraint represents a type of constraint that imposes a limit on a property of the portfolio under consideration, and therefore, does not require that the set of assets that it will apply to be specified explicitly. In other
words, the constraint applies to all of the assets in the rebalancing account as a whole. For example, a budget constraint limits the total net value of the optimized portfolio holdings. It does not limit any of the individual asset holdings specifically but rather the net sum of all the asset holdings. A budget constraint is an example of a collective constraint. Other examples of collective constraints available in Axioma Portfolio include limit on the net tax losses, limit
on the net tax gains, and limit on the overall tax liability.
Budget Constraint
The budget constraint limits the total value of the optimized portfolio. Here we describe how a budget constraint can
be created and activated by the user.
The total value of the portfolio usually consists of the initial holdings and potentially cash flows in or out of the portfolio. The budget constraint allows the user to specify exactly the total value of the optimized portfolio. For instance, if
a portfolio has value $100,000 and an additional $10,000 of cash is added to it then the total value, or the budget, is
$110,000. Conversely, if $20,000 in cash is to be extracted from the portfolio, then the total value or budget is
$80,000. See the discussion in the section called “The Budget Size” for more on this issue.
A budget constraint is imposed using the BudgetConstraint class, as follows:
// Require full investment
BudgetConstraint bc = new BudgetConstraint(strategy, "BudgetConstraint", null);
ConstraintProperties cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.USE_BUDGET_VALUE, true);
bc.setProperties(cp);
bc.setEnabled(true);
The first argument of the constructor of the BudgetConstraint class is the strategy that the budget constraint will
belong to. The second argument is the required unique name or identifier for the constraint object. And the third argument is the optional constraint description.
In the above budget constraint example, we have created a ConstraintProperties object and set its
USE_BUDGET_VALUE property to true. This property indicates that we are requiring full investment. In order to
complete the budget constraint setup, we must specify the budget value for the account rebalancing. The rebalancing
budget value is setup using the setBudgetSize(double d) method of the Rebalancing class as illustrated below:
rebal.setBudgetSize(100000.00);
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 48
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
Observe that once the budget constraint object was created, we enabled it by invoking the setEnabled(boolean
option) method of the Constraint class with a boolean argument equal to true. This step was unnecessary
since constraints are enabled by default in Axioma Portfolio. However, if for whatever reason a constraint should be
excluded when performing a portfolio optimization process, it can be disabled by invoking its setEnabled(boolean option) method with a boolean argument equal to false.
After Transaction Cost Budget Constraint
The after transaction cost budget constraint limits the total value of the optimized portfolio, taking the buy and the
sell transaction costs as computed using a transaction cost model into account. Here we describe how a after transaction cost budget constraint can be created and activated by the user.
The first argument of the constructor of the AfterTransacationCostBudgetConstraint class is the strategy
that the constraint will belong to. The second argument is the required unique name or identifier for the constraint
object. And the third argument is the optional constraint description.
AfterTransactionCostBudgetConstraint aftertcostbc = new AfterTransactionCostBudgetConstraint(strategy, "Af
ConstraintProperties cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.USE_BUDGET_VALUE, true);
cp.setProperty(ConstraintProperties.Property.BUY_ATTRIBUTE, ws.getGroup("buyGroup"));
cp.setProperty(ConstraintProperties.Property.SELL_ATTRIBUTE, ws.getGroup("sellGroup"));
aftertcostbc.setProperties(cp);
aftertcostbc.setEnabled(true);
Limit Issuer Holding Constraints
A concrete implementation of the LimitIssuerConstraint that limits the holdings to issuers. This constraint behaves like the LimitHoldingConstraint, where composite assets only contribute if explicitly included in an issuer
group or the single issue set.
An instance of the LimitIssuerHoldingConstraint class is constructed with the statement:
LimitIssuerHoldingConstraint lihConst = new LimitIssuerHoldingConstraint(stg_, "lihConst", null);
or
LimitIssuerHoldingConstraint lihConst = new LimitIssuerHoldingConstraint(ca_, "lihConst", null);
The first constructs a new LimitIssuerExposureConstraint object using the specified strategy containing a
SubElementSet to which this constraint will be applied, the required String identity and optional String description.
The second constructor creates a new LimitIssuerHoldingConstraint object with the compliance account
containing a SubElementSet to which this constraint will be applied, the required String identity and optional
String description.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 49
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
Limit Issuer Exposure Contraints
A concrete implementation of the LimitIssuerConstraint that limits the exposure to issuers. This constraint behaves like the LimitExposureConstraint in that holdings in a particular asset and holdings in a composite that
holds that asset will both contribute to an issuer if that asset is specified in the issuer group or in the single issue set.
An instance of the LimitIssuerExposureConstraint class is constructed with the statement:
LimitIssuerExposureConstraint lieConst = new LimitIssuerExposureConstraint(stg_, "lieConst", null);
or
LimitIssuerExposureConstraint lieConst = new LimitIssuerExposureConstraint(ca_, "lieConst", null);
The first constructor creates a new LimitIssuerHoldingConstraint object belonging to the specified
Strategy stg_, and whose identity and description are set to the specified values.
The second constructor creates a new LimitIssuerHoldingConstraint object with the compliance account
containing a SubElementSet to which this constraint will be applied. The next two String arguments are the required identity and optional description.
Tax Constraints
Axioma Portfolio provides specialized classes to support constraints on tax-related attributes of the portfolio. These
will be described in more detail in Chapter 10.
Selection Constraints
A selection constraint represents a type of constraint that is applicable to a selected asset or group of assets. For example, we might want to individually limit the holdings for each asset in a portfolio within specific bounds, or we
might want to prevent large buy or sell transactions for a group of assets.
Selection constraints are created as instances of the SelectionConstraint class in Axioma Portfolio. The SelectionConstraint class provides the addAssetSelection(Asset a, ConstraintProperties cp), addAssetSetSelection(AssetSet as, ConstraintProperties cp), addGroupSelection(Group g,
ConstraintProperties cp), and addMetagroupSelection(Metagroup mp, ConstraintProperties
cp) methods in order to specify the individual asset, set of assets, group of assets, or metagroup that the selection
constraint applies to. These methods takes two parameters: the first parameter is an Asset, AssetSet, Group, or
Metagroup object representing the assets in the constraint; the second parameter is a ConstraintProperties
object that specifies the constraint characteristics that apply to the current asset selection. The ConstraintProperties parameter is included because the addAssetSelection(Asset a, ConstraintProperties cp)
method can be invoked multiple times with different asset selections and different constraint properties applicable to
each asset selection individually. If an instance of the static class ConstraintProperties.EMPTY_PROPERTIES is
used as the second parameter, then the SelectionConstraint's ConstraintProperties is used instead of the
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 50
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
expected constraint properties object. In principle, we can create just one specific type of selection constraint and
vary the asset selection and constraint properties objects in order to accomodate all of the necessary asset selection
contraints of that type that we might need. For example, we can create one LimitHoldingConstraint constraint
with its own constraint properties object and then invoke the addAssetSelection(Asset a, ConstraintProperties cp) method for each asset selection that we wish to constrain. This is illustrated in the next subsection.
The SelectionConstraint.SelectionType class represents the type of selections that allowed for selection
constraints.
The following selection types are available:
➤ ASSET,
➤ GROUP,
➤ METAGROUP, and
➤ SET
Examples of selection constraints include limits on holdings, limits on trades, limits on turnover, robust constraints,
etc.
Limit Almost Long Term Gains
LimitAlmostLongTermGainsConstraint can be used to prohibit trading lots with positive holdings which satisfy
the following conditions: their price has increased since their purchase (i.e. they have unrealized gains), they are still
short-term lots, and they will become long-term lots within a specified number of days. For example,
LimitAlmostLongTermGainsConstraint laltg = new LimitAlmostLongTermGainsConstraint(
stgy, "LALTGC", null);
ConstraintProperties cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.NUM_OF_DAYS, 50);
cp.setProperty(ConstraintProperties.Property.SCOPE, aggregate);
laltg.setProperties(cp);
laltg.addAssetSetSelection(ws.getMasterSet(),
ConstraintProperties.EMPTY_PROPERTIES);
laltg.setEnabled(true);
Limit Minimum Holding Period
A LimitMinimumHoldingPeriodConstraint can be used to prohibit trading tax lots which were recently purchased. The NUM_OF_DAYS property is used to specify the minimum number of days a tax lot must be kept before it
is traded. For example,
LimitMinimumHoldingPeriodConstraint lmhpc = new LimitMinimumHoldingPeriodConstraint(
stgy, "LMHPC", null);
ConstraintProperties cp1 = new ConstraintProperties();
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 51
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
cp1.setProperty(ConstraintProperties.Property.NUM_OF_DAYS, 50);
cp1.setProperty(ConstraintProperties.Property.SCOPE, aggregate);
lmhpc.setProperties(cp1);
lmhpc.addAssetSetSelection(ws.getMasterSet(),
ConstraintProperties.EMPTY_PROPERTIES);
lmhpc.setEnabled(true);
Bounds on Holdings
General lower and upper bounds on holdings in an individual asset or a set of assets can be handled using the LimitHoldingConstraint class. For example,
LimitHoldingConstraint lhc = new LimitHoldingConstraint(strategy, "LHC", "LimitHolding");
ConstraintProperties cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE,Constraint.Scope.ASSET);
cp.setProperty(ConstraintProperties.Property.MAX, 40000);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.CURRENCY);
lhc.setProperties(cp);
lhc.addAssetSelection(ws.getAsset("IBM"), ConstraintProperties.EMPTY_PROPERTIES);
will ensure that the optimized holdings in IBM are at most $40,000, while
ConstraintProperties cp2 = new ConstraintProperties();
cp2.setProperty(ConstraintProperties.Property.SCOPE,Constraint.Scope.ASSET);
cp2.setProperty(ConstraintProperties.Property.MIN, 2.0);
cp2.setProperty(ConstraintProperties.Property.UNIT, Unit.PERCENT);
lhc.addAssetSelection(ws.getAsset("AZPN"), cp2);
will force the investment in AZPN to be at most 2% of the reference size. Negative values can be used to constrain
the short side. Observe that we did not have to create a new instance of the LimitHoldingConstraint class. Instead, we added a new asset selection to the previously created LimitHoldingConstraint object with a ConstraintProperties built according to how we wanted to constrain the holdings of AZPN.
Constraints on the total holdings in an industry or the entire portfolio can be imposed using the appropriate AssetSet, Group or Metagroup as the first argument of the addAssetSetSelection(AssetSet as, ConstraintProperties cp), addGroupSelection(Group g, ConstraintProperties cp), or addMetagroupSelection(Metagroup mg, ConstraintProperties cp) methods of the SelectionConstraint class. For example, the following LimitHoldingConstraint limits the short holdings relative to the long holdings for the group
of assets in the user-defined group myIndustry:
Group myIndustry = new SimpleGroup(ws, "IndustryGroup2", null, ws.getDate(), Unit.NUMBER);
myIndustry.setComposition(ws.getAsset("TSG"), 1.0);
myIndustry.setComposition(ws.getAsset("DELL"), 1.0);
myIndustry.setComposition(ws.getAsset("ARBA"), 0.5);
SelectionConstraint indC = new LimitHoldingConstraint(strategy, "IC", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE,Constraint.Scope.SELECTION);
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 52
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
cp.setProperty(ConstraintProperties.Property.MIN, 0.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.CURRENCY);
indC.setProperties(cp);
indC.addGroupSelection(myIndustry, ConstraintProperties.EMPTY_PROPERTIES);
This will ensure that the total sum of weighted holdings in these assets will be positive, which still allows for individual
short positions. The weights in this case are 1.0 for TSG and DELL, but 0.5 for ARBA. That is, if TSG and DELL are
each short $10,000 then ARBA must be long at least $40,000 to offset the shorting of the other two. You can think of
these weights as exposures to an industry and this constraint as a no-shorting constraint applied to the industry as a
whole, but not on the individual assets in that industry.
Other examples incorporating groups of assets are presented in the section called “Limits on Short Holdings” and the
section called “Industry Constraints”.
To simultaneously limit the holdings on both the long and the short side, the LimitAbsoluteHoldingConstraint
is provided. The statement
LimitAbsoluteHoldingConstraint lahc =
new LimitAbsoluteHoldingConstraint(strategy, "LAHC", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE,Constraint.Scope.ASSET);
cp.setProperty(ConstraintProperties.Property.MAX, 5000);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.CURRENCY);
lahc.setProperties(cp);
lahc.addAssetSelection(ws.getAsset("DELL"), ConstraintProperties.EMPTY_PROPERTIES);
will force the holdings in DELL to be at most $5000 on either the long or the short side. If the first argument is a
Group rather than a single asset, the LimitAbsoluteHoldingConstraint will limit the total weighted long and
short holdings in the group. The weighted sum is calculated using the absolute value of the holdings is each asset. That
is, short holdings are treated as positive, rather than negative, values.
Minimum Threshold Holdings Constraints
Often a portfolio optimization problem includes the restriction that if an asset is held, the position must be at least
some threshold (minimum) amount (either long or short). This kind of constraint (called a "minimum threshold holdings" constraint) can be specified by creating a ThresholdHoldingConstraint object. This allows you to put an
absolute lower bound L on individual positions, with the caveat that a zero value for holdings is allowed. This works
transparently on either the long or the short side (if shorting is allowed). The constraint ensures that the optimized
holdings are either 0 (no holdings), at least L (i.e., for long holding) or at most -L (i.e., for short holdings). For example,
// Make sure we short or long MSFT with at least 2% (if we hold MSFT at all)
ThresholdHoldingConstraint thc = new ThresholdHoldingConstraint(strategy, "Threshold", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.ASSET);
cp.setProperty(ConstraintProperties.Property.MIN, 2.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.PERCENT);
thc.setProperties(cp);
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 53
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
thc.addAssetSelection(ws.getAsset("MSFT"), ConstraintProperties.EMPTY_PROPERTIES);
will ensure that holdings in MSFT are either 0, or at least 2% of the reference size (either long or short). Translating
this to absolute numbers, for a reference size of $100,000, this means that holdings must be either $0, at least $2,000
or at most -$2,000 (i.e., at least $2,000 short).
The ThresholdHoldingConstraint constraint does support minimum thresholds on the holdings in a group of
assets.
Limits on Short Holdings
A common restriction imposed on a portfolio is a limit on the amount of short holdings. As noted above, these restrictions can be modeled using the LimitHoldingConstraint where the minimum is a negative value. However,
to make these restrictions more intuitive, Axioma Portfolio also incorporates a LimitShortHoldingConstraint
object.
To limit the total amount of short holdings in the portfolio, the LimitShortHoldingConstraint object is used as
follows:
LimitShortHoldingConstraint lshc = new LimitShortHoldingConstraint(strategy, "Shorts", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.SELECTION);
cp.setProperty(ConstraintProperties.Property.MAX, 10.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.PERCENT);
lshc.setProperties(cp);
lshc.addAssetSetSelection(ws.getLocalUniverseSet(),ConstraintProperties.EMPTY_PROPERTIES);
This statement limits the total short holdings to no more than 10% of the portfolio reference size.
To impose no shorting on a single asset, we can include a LimitShortHoldingConstraint for the individual security. For example:
LimitShortHoldingConstraint ashc = new LimitShortHoldingConstraint(strategy, "ASH", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE,Constraint.Scope.ASSET);
cp.setProperty(ConstraintProperties.Property.MAX, 0.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.CURRENCY);
ashc.setProperties(cp);
ashc.addAssetSelection(ws.getAsset("TSG"), ConstraintProperties.EMPTY_PROPERTIES);
will forbid shorting of TSG. An equivalent statement is:
LimitHoldingConstraint ahc = new LimitAbsoluteHoldingConstraint(strategy, "AHC", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE,Constraint.Scope.ASSET);
cp.setProperty(ConstraintProperties.Property.MIN, 0.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.CURRENCY);
ahc.setProperties(cp);
ahc.addAssetSelection(ws.getAsset("TSG"), ConstraintProperties.EMPTY_PROPERTIES);
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 54
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
It is also possible to write a limit on shorting over a group of assets or an industry. For instance, once a LimitShortHoldingConstraint is created, we can invoke its addGroupSelection(Group g, ConstraintProperties cp) method with a Group, or its addMetagroupSelection(Metagroup mg, ConstraintProperties cp) method with Metagroup, as the first argument in order to limit the holdings on a user-defined group or
metagroup, as in:
Group myIndustry2 = new SimpleGroup(ws, "IndustryGroup2", null, ws.getDate(), Unit.NUMBER);
myIndustry.setComposition(ws.getAsset("MSFT"), 1.0);
myIndustry.setComposition(ws.getAsset("IBM"), 1.0);
myIndustry.setComposition(ws.getAsset("ORCL"), 1.0);
SelectionConstraint indSC = new LimitShortHoldingConstraint(strategy, "ISC", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE,Constraint.Scope.SELECTION);
cp.setProperty(ConstraintProperties.Property.MIN, -30,000);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.CURRENCY);
indSC.setProperties(cp);
indSC.addGroupSelection(myIndustry2, ConstraintProperties.EMPTY_PROPERTIES);
The LimitShortHoldingConstraint above will ensure that the net short holdings in the user-defined group myIndustry2 will be at least -$30,000.
Axioma Portfolio also incorporates a LimitLongHoldingConstraint class that can be used to restrict the long
holdings in the same manner that the LimitShortHoldingConstraint is applied to short holdings.
Bounds on Active Holdings
The active holdings or bet for an asset or industry is the difference in investment in the asset or industry between the
portfolio and a benchmark. Active holding constraints allow the user to directly limit the investment in an industry (or
other asset group) in order to be close to the benchmark investment in this industry. This section describes how to
put bounds on bets.
Lower and upper bounds on bets can be set by creating LimitHoldingConstraint objects and setting the ConstraintProperties.Property.MIN, the ConstraintProperties.Property.MAX, and the ConstraintProperties.Property.BENCHMARK properties to appropriate values. Simply specifying a reference to a valid
benchmark converts a constraint to its active constraint equivalent. For example,
LimitHoldingConstraint ahc = new LimitHoldingConstraint(strategy, "AHC", "Active");
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE,Constraint.Scope.ASSET);
cp.setProperty(ConstraintProperties.Property.MAX, 12000);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.CURRENCY);
cp.setProperty(ConstraintProperties.Property.BENCHMARK, ws.getGroup("SimpleBenchmark"));
ahc.setProperties(cp);
ahc.addAssetSelection(ws.getAsset("DELL"), ConstraintProperties.EMPTY_PROPERTIES);
will ensure that the investment in DELL is no more than $12,000 more than the value for DELL in the benchmark
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 55
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
SimpleBenchmark. Similarly,
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE,Constraint.Scope.ASSET);
cp.setProperty(ConstraintProperties.Property.MIN, -10000);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.CURRENCY);
cp.setProperty(ConstraintProperties.Property.BENCHMARK, ws.getGroup("SimpleBenchmark"));
ahc.setProperties(cp);
ahc.addAssetSelection(ws.getAsset("SAP"), cp);
will constrain the holdings in SAP to be no more than $10,000 below the value for SAP in the benchmark SimpleBenchmark. In other words, the holding in SAP must be at least the benchmark weight for SAP minus $10,000.
Note that this constraint does not enforce anything on the positive side, i.e. a position in SAP larger than specified in
the benchmark is unrestricted.
Minimum threshold active holdings are currently not supported in Axioma Portfolio, i.e. there is no way of stating
that the holdings in, say, SAP should either be identical to the benchmark or differ from the benchmark by at least
$20,000 (either holding less or holding more). In contrast, these two-sided bounds are available for holdings
(ThresholdHoldingConstraint) and transactions (ThresholdTradeConstraint).
Limiting the Long/Short Ratio
It is sometimes necessary, either by law or institutional guidelines, to limit the amount of money held long relative to
the amount held short. In Axioma Portfolio, this can be accomplished by using a LimitLongShortRatioConstraint. For example, suppose that a hedge fund wants to limit its risks by requiring the long/short ratio to be
greater than one. This can be enforced with the following:
LimitLongShortRatioConstraint lsr = new LimitLongShortRatioConstraint(strategy, "LSR", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE,Constraint.Scope.SELECTION);
cp.setProperty(ConstraintProperties.Property.MIN, 1.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.NUMBER);
lsr.setProperties(cp);
lsr.addAssetSetSelection(ws.getLocalUniverseSet(),ConstraintProperties.EMPTY_PROPERTIES);
Industry Constraints
Axioma Portfolio supports limits on holdings in industries, factors, or specially defined groups of assets. Previous sections illustrated how, for example, bounds could be set on the short holdings in a user-defined industry. This section
will give a few more examples.
First, industries or factors (we make no distinction between them here) can be easily extracted from the risk model.
A factor risk model in Axioma Portfolio contains a method called getRiskfactorGroup(java.lang.String
factor) that accepts a string representing the name of a risk factor and that returns a RiskfactorGroup (itself a
Group) object whose weights represent the asset exposures to the risk factor. If in addition of being a factor risk
model, the risk factor is a Barra model, then there exists an alternate mechanism for retrieving the risk factor
groups or industries. When processing a Barra risk model, Axioma Portfolio automatically generates its risk factor
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 56
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
groups and adds them to the workspace. The risk factor groups can be retrieved from the workspace using the getGroup(java.lang.String id) method of the Workspace class. The name of the group is constructed by concatenating the name of the factor risk model and the name of the risk factor separated by a period. For example, assuming that a factor risk model with the identifier "SmallRiskModel" exists and that it contains a risk factor called
"CMPTRHW" representing the computer hardware industry, the resulting group in the workspace would have the
name "SmallRiskModel.CMPTRHW". Furthemore, three metagroups are created that represent the factor risk model
common factors, the factor risk model industries, and the factor risk model risk factors. Each of these metagroups
can be retrieved from the workspace by invoking its getMetagroup(java.lang.String id) method with a
string that is constructed by concatenating the factor risk model name to the word FACTORTYPES, INDUSTRIES, or
RISKFACTORS, respectively. To extract the industry called "CMPTRHW" from the risk model and limit its holdings,
we write the following:
LimitHoldingConstraint cmptrhw = new LimitHoldingConstraint(strategy, "LimitCMPTRHW", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.SELECTION);
cp.setProperty(ConstraintProperties.Property.MAX, 40.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.PERCENT);
cmptrhw.setProperties(cp);
cmptrhw.addGroupSelection(ws.getGroup("SmallRiskModel.CMPTRHW"),
ConstraintProperties.EMPTY_PROPERTIES);
This limits holdings in the computer hardware industry to be at most 40% of the reference size.
You can restrict any factor/industry from the risk model (or any user-defined Group) in terms of holdings, transactions, active holdings, number of names held, turnover, etc. Almost all Axioma Portfolio constraint classes presented
in this chapter can be applied to a set of assets in the manner presented above.
The following constraints together limit the total investment in the wireless industry to be within 1% of the benchmark holdings in that industry (this is called an industry bet):
LimitHoldingConstraint wireless =
new LimitHoldingConstraint(strategy, "LimitWIRELESS", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.SELECTION);
cp.setProperty(ConstraintProperties.Property.MAX, 1.0);
cp.setProperty(ConstraintProperties.Property.MIN, -1.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.PERCENT);
cp.setProperty(ConstraintProperties.Property.BENCHMARK, ws.getGroup("SimpleBenchmark"));
wireless.setProperties(cp);
wireless.addGroupSelection(ws.getGroup("SmallRiskModel.WIRELESS"),
ConstraintProperties.EMPTY_PROPERTIES);
The above example is an industry bet relative to the SimpleBenchmark benchmark. This will ensure that the investment in the WIRELESS industry is within 1% of the investment in the same industry in the benchmark SimpleBenchmark (a Benchmark or Group object).
Limiting the Number of Names Held
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 57
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
In many cases, restricting the number of holdings, or number of names held in a portfolio, is important. In Axioma
Portfolio, this is done through the LimitNamesConstraint, an object which allows bounding the number of nonzero holdings. For example, to limit the number of names held (either long or short) to 10, we write:
LimitNamesConstraint namesC = new LimitNamesConstraint(strategy, "LimitNames", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.SELECTION);
cp.setProperty(ConstraintProperties.Property.MAX, 10.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.NUMBER);
namesC.setProperties(cp);
namesC.addAssetSetSelection(ws.getMasterSet(), ConstraintProperties.EMPTY_PROPERTIES);
Note that the constraint's asset selection specifies the set of assets over which the constraint should be written, in
this case all the assets in the portfolio. We can also specify limits on the number of names held short and long as follows:
LimitShortNamesConstraint shortNC = new LimitShortNamesConstraint(strategy, "LSNC", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.SELECTION);
cp.setProperty(ConstraintProperties.Property.MAX, 10.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.NUMBER);
shortNC.setProperties(cp);
shortNC.addAssetSetSelection(ws.getMasterSet(), ConstraintProperties.EMPTY_PROPERTIES);
The constraint above limits the number of names held short to at most 10 securities. Below, we create a LimitLongNamesConstraint object in order limit the number of names held long to be at most 8 securities.
LimitLongNamesConstraint longNC = new LimitLongNamesConstraint(strategy, "LLNC", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.SELECTION);
cp.setProperty(ConstraintProperties.Property.MAX, 8.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.NUMBER);
longNC.setProperties(cp);
longNC.addAssetSetSelection(ws.getMasterSet(), ConstraintProperties.EMPTY_PROPERTIES);
To bound the number of holdings over a subset of the asset universe, we build an AssetSet containing the assets to
constrain. For example:
AssetSet mySet = new AssetSet(ws, "MYSET", null, ws.getDate());
mySet.includeAsset(ws.getAsset("DELL"));
mySet.includeAsset(ws.getAsset("MSFT"));
mySet.includeAsset(ws.getAsset("IBM"));
LimitNamesConstraint nholdC = new LimitNamesConstraint(strategy, "NamesConst", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.SELECTION);
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 58
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
cp.setProperty(ConstraintProperties.Property.MAX, 2.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.NUMBER);
nholdC.setProperties(cp);
nholdC.addAssetSetSelection(mySet, ConstraintProperties.EMPTY_PROPERTIES);
imposes the restriction that at most two names out of DELL, MSFT and IBM be held (either long or short).
Now consider the following:
LimitNamesConstraint cmptrhwNC = new LimitNamesConstraint(strategy, "cmptrhwNC", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.SELECTION);
cp.setProperty(ConstraintProperties.Property.MAX, 6.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.NUMBER);
cmptrhwNC.setProperties(cp);
cmptrhwNC.addGroupSelection(ws.getGroup("SmallRiskModel.CMPTRHW"),
ConstraintProperties.EMPTY_PROPERTIES);
These code statements add a constraint on the number of names held in the computer hardware industry (as defined
in the risk model SmallRiskModel). Specifically, it requires that no more than six names be held.
In order to required that at least two names from the computer hardware industry group be held, we use the addGroupSelection(Group g, ConstraintProperties cp) method of the previously created LimitNamesConstraint with the SmallRiskModel.CMPTRHW group as its first argument and the following constraint
properties as its second argument:
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.SELECTION);
cp.setProperty(ConstraintProperties.Property.MIN, 2.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.NUMBER);
cmptrhwNC.addGroupSelection(ws.getGroup("SmallRiskModel.CMPTRHW"), cp);
Bounding the Number of Holdings by Zero
The LimitShortNamesConstraint, LimitLongNamesConstraint, and LimitNamesConstraint objects are
used to place nonzero limits on the number of positions among sets of securities. For example, using myIndustry as
defined above we can add the statement:
LimitNamesConstraint indNC = new LimitShortNamesConstraint(strategy, "indNC", null);
indNC.addGroupSelection(myIndustry, cp);
to limit the number of short positions among TSG, DELL, and ARBA to at most two. It is also permissible to place an
upper limit of zero on the number of (short, long, or total) positions. However, it is better practice to use LimitShortHoldingConstraint or LimitLongHoldingConstraint to forbid short or long positions in each individual asset. This approach will generally provide better computational performance.
Limiting Portfolio Risk
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 59
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
A common restriction in many portfolio optimization problems is limiting the portfolio risk to be less than a target
value. There are two kinds of risks that can be controlled in this manner: absolute risk and active risk.
In the following section, we will describe how to limit absolute and active risk for problems with a single benchmark
and a single risk model.
Limiting Absolute Risk
The absolute portfolio risk is defined as the standard deviation of the portfolio returns over the coming period. The
absolute portfolio risk can be constrained by creating a LimitTotalRiskConstraint object. For instance:
LimitTotalRiskConstraint trc = new LimitTotalRiskConstraint(strategy, "TRC", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.AGGREGATE);
cp.setProperty(ConstraintProperties.Property.MAX, 15.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.PERCENT);
cp.setProperty(ConstraintProperties.Property.RISKMODEL, ws.getRiskModel("SimpleRiskModel"));
trc.setProperties(cp);
trc.addAssetSetSelection(ws.getMasterSet(), ConstraintProperties.EMPTY_PROPERTIES);
This constraint limits the portfolio's absolute risk to be no more than 15% of the reference size. Note that we used
the getMasterSet() method of the workspace object to specify that this absolute risk be calculated over all the assets in the portfolio. The risk model to use in the risk calculations is specified by setting the constraint property
RISKMODEL to a reference pointing to the desired risk model. In this case, we retrieve a reference to the risk model
called "SimpleRiskModel" from the workspace.
If the riskmodel is an instance of factor risk model, instead of using all the factors, selected factors can be used. The
list can have both factor names and reference to metagroups.
List<String> selectedfactors = new ArrayList<String>();
selectedfactors.add("SimpleRiskModel.Factor1");
selectedfactors.add("SimpleRiskModel.Factor2");
trc.setSelectedFactors(selectedFactors);
Limiting Risk Relative A Benchmark
The portfolio's risk relative to a benchmark (sometimes called the tracking error or active risk) is defined as the standard deviation of the difference between the portfolio returns and the benchmark returns over the coming period.
The portfolio's risk relative to the benchmark can be constrained by creating a LimitTotalRiskConstraint object and specifying a benchmark in its constraint properties object. For instance:
LimitTotalRiskConstraint arc = new LimitTotalRiskConstraint(strategy, "ARC", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.AGGREGATE);
cp.setProperty(ConstraintProperties.Property.MAX, 30000.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.CURRENCY);
cp.setProperty(ConstraintProperties.Property.BENCHMARK, myBenchmark);
cp.setProperty(ConstraintProperties.Property.RISKMODEL, ws.getRiskModel("SmallRiskModel"));
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 60
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
arc.setProperties(cp);
arc.addAssetSetSelection(ws.getMasterSet(), ConstraintProperties.EMPTY_PROPERTIES);
This constraint limits the portfolio's risk relative to the benchmark myBenchmark to be no more than $30,000. Note
again that we have used the getMasterSet() method of the workspace object to specify that the risk be calculated
over all the assets in the portfolio. The risk model could be either a FactorRiskModel or a DenseRiskModel.
Bounds on Transactions
Limits on transactions are also available. For example, to make sure that no more than $5,000 worth of ORCL is
sold, we use LimitSellConstraint to write:
LimitSellConstraint lsc = new LimitSellConstraint(strategy, "LimitSell", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.ASSET);
cp.setProperty(ConstraintProperties.Property.MAX, 5000.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.CURRENCY);
lsc.setProperties(cp);
lsc.addAssetSelection(ws.getAsset("ORCL"), ConstraintProperties.EMPTY_PROPERTIES);
Note that this constraint places no limit on the amount of ORCL that may be purchased.
To ensure that at most $7,000 worth of DELL is purchased, we use LimitBuyConstraint and write:
LimitBuyConstraint lbc = new LimitBuyConstraint(strategy, "LimitBuy", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.ASSET);
cp.setProperty(ConstraintProperties.Property.MAX, 7000.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.CURRENCY);
lbc.setProperties(cp);
lbc.addAssetSelection(ws.getASSET("DELL"), ConstraintProperties.EMPTY_PROPERTIES);
Again, note that this constraint places no limit on the amount of DELL that may be sold.
Upper bounds on transaction sizes of individual positions are accomplished by creating a LimitTurnoverConstraint object. For example,
LimitTurnoverConstraint toc = new LimitTurnoverConstraint(strategy, "LimitTO", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.ASSET);
cp.setProperty(ConstraintProperties.Property.MAX, 5000.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.CURRENCY);
toc.setProperties(cp);
toc.addAssetSelection(ws.getAsset("ARBA"), ConstraintProperties.EMPTY_PROPERTIES);
will ensure that a transaction on ARBA is at most $5,000 (either buy or sell). See the section called “Limits on
Turnover” for examples on how to use the LimitTurnoverConstraint on groups, industries or whole portfolios.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 61
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
Minimum Threshold Transaction Constraints
It is also possible to specify a minimum transaction size for assets by creating a ThresholdTradeConstraint object. This will ensure that if there is a transaction on the asset, then the transaction is for at least a minimum
threshold amount (either a buy or a sell). For example,
ThresholdTradeConstraint thtc = new ThresholdTradeConstraint(strategy, "THT", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.ASSET);
cp.setProperty(ConstraintProperties.Property.MIN, 10000.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.CURRENCY);
thtc.setProperties(cp);
thtc.addAssetSelection(ws.getAsset("DELL"), ConstraintProperties.EMPTY_PROPERTIES);
will ensure that if DELL is traded, then the transaction is for at least $10,000 (either a buy or sell of this amount or
more). Note that a zero transaction is permissible. In addition, it is always permissible to trade an amount that will reduce the holdings to zero even if that trade amount does not reach the minimum threshold level specified by the minimum transaction constraint. See the Axioma Portfolio JavaDocs [index.html] for more details.
Limits on Turnover
When rebalancing a portfolio, it is often desirable to limit the total amount bought and sold (i.e., the turnover). For
example, one can limit the turnover to, say, 10% of the reference size.
In Axioma Portfolio, control of turnover is made available through the LimitTurnoverConstraint class, which allows the user to put a maximum upper limit on the turnover of a portfolio, an industry, an asset group, or an individual asset. Turnover constraints differ from trades constraints in that in a turnover constraint, all trade values (buys
and sells) are treated as positive values.
For example, the following function limits the total turnover of the portfolio to 10% of the reference size:
LimitTurnoverConstraint ltoc = new LimitTurnoverConstraint(strategy, "TOC", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.SELECTION);
cp.setProperty(ConstraintProperties.Property.MAX, 10.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.PERCENT);
ltoc.setProperties(cp);
ltoc.addAssetSetSelection(ws.getLocalUniverse(), ConstraintProperties.EMPTY_PROPERTIES);
Note the scope and the asset set selection specifies that the constraint be defined over all assets of the portfolio.
Limiting the Number of Transactions
Sometimes it may be more convenient to control transaction costs by explicitly limiting the number of transactions.
Suppose that in order to reduce the cost and time to rebalance a portfolio, a portfolio manager wants to limit the
number of names traded to 10. This can be accomplished with the following:
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 62
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
LimitNumTradesConstraint ntc = new LimitNumTradesConstraint(strategy, "NTC", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.SELECTION);
cp.setProperty(ConstraintProperties.Property.MAX, 10.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.NUMBER);
ntc.setProperties(cp);
ntc.addAssetSetSelection(ws.getLocalUniverse(), ConstraintProperties.EMPTY_PROPERTIES);
Limiting the Deviation from a Benchmark
The LimitModelDeviationConstraint puts an upper bound on the distance between the optimized holdings of
a weighted group of assets and their benchmark weights. The assets and their (nonnegative) weights are specified as
a SimpleGroup. The distance computed is the 2-norm of the vector of differences. A LimitModelDeviationConstraint may be specified to limit the deviation from a given benchmark. To limit the deviation of the optimized
portfolio from the benchmark SimpleBenchmark (assumed to have been previously created) to 5% of the reference size, we include:
LimitModelDeviationConstraint devConst =
new LimitModelDeviationConstraint(strategy, "ModelDeviation", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.SELECTION);
cp.setProperty(ConstraintProperties.Property.MAX, 5.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.PERCENT);
cp.setProperty(ConstraintProperties.Property.BENCHMARK, ws.getGroup("SimpleBenchmark"));
devConst.setProperties(cp);
devConst.addAssetSetSelection(ws.getMasterSet(), ConstraintProperties.EMPTY_PROPERTIES);
Limiting Relative Marginal Contribution to Risk
Axioma Portfolio allows the user to explicitly limit the relative marginal contribution to (active) risk using the
LimitRelativeMarginalContributionToRiskConstraint class. The marginal contribution to risk of an asset
is calculated relative to the total risk of the assets in an AssetSet. That is, given an AssetSet mySet, we can limit
the portion of the total risk over the set that can be attributed to a specific asset in the set. To specify a relative marginal contribution to risk constraint, the user must supply an asset, an AssetSet containing the set of assets over
which risk is to be computed, and an upper bound on the contribution to risk. In addition, the risk model to be used
in the risk calculation must also be specified. For more details on the exact computation of relative marginal risk contributions, examine the LimitRelativeMarginalContributionToRiskConstraint class in the Axioma Portfolio
JavaDocs [index.html]. To limit the relative marginal contribution to risk of DELL to be at most 5% of the total risk of
the AssetSet mySet using the FactorRiskModel myFRM, we write:
LimitRelativeMarginalContributionToRiskConstraint mctrc =
new LimitRelativeMarginalContributionToRiskConstraint(strategy, "MCTRC", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.ASSET);
cp.setProperty(ConstraintProperties.Property.MAX, 5.0);
cp.setProperty(ConstraintProperties.Property.BASE_SET, mySet);
cp.setProperty(ConstraintProperties.Property.RISKMODEL, myFRM);
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 63
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
mctrc.setProperties(cp);
mctrc.addAssetSelection(ws.getAsset("DELL"), ConstraintProperties.EMPTY_PROPERTIES);
In the following, we restrict the relative marginal contribution to active risk (relative to the Benchmark "myBenchmark") of DELL to be at most 3% of the total active risk of mySet.
LimitRelativeMarginalContributionToRiskConstraint mcarc =
new LimitRelativeMarginalContributionToRiskConstraint(strategy, "MCARC", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.ASSET);
cp.setProperty(ConstraintProperties.Property.MAX, 3.0);
cp.setProperty(ConstraintProperties.Property.BASE_SET, mySet);
cp.setProperty(ConstraintProperties.Property.RISKMODEL, myFRM);
cp.setProperty(ConstraintProperties.Property.BENCHMARK, ws.getGroup("myBenchmark"));
mcarc.setProperties(cp);
mcarc.addAssetSelection(ws.getAsset("DELL"), ConstraintProperties.EMPTY_PROPERTIES);
Note that the factor component of the relative marginal contribution to active risk of an asset can be constrained by
supplying a factor risk model with no specific risks. Similarly, the specific risk component of the relative marginal contribution to active risk of an asset can be constrained by supplying a factor risk model with no factors and only specific risks. Similarly, instead of using all the factors in the factor riskmodels, selected factors can be used. The list can
have factor names and reference to metagroups.
List<String> selectedfactors = new ArrayList<String>();
selectedfactors.add("myFRM.Factor1");
selectedfactors.add("myFRM.Factor2");
mcarc.setSelectedFactors(selectedFactors);
Using the LimitWeightedAvgConstraint Class
Axioma Portfolio supports a weighted-average constraint that imposes a bound on the ratio between the weighted
sum of holdings and the sum of holdings of a set of assets. In other words, given a user-defined group, which could
represent a portfolio property such as the assets expected returns, this constraint limits the weighted linear sum of
the group composition where the weighting coefficients are the assets optimized holding fractions. As we will see
shortly, this constraint is ideal for imposing a limit on various portfolio properties that can be represented as a
weighted-average.
To demonstrate how to use this constraint class, consider an example where you want to limit the average P/E ratio
of the holdings in a set of technology stocks to be less than 40. Assume that we have already constructed a SimpleGroup called techPE containing the P/E ratios of all technology stocks. If you knew exactly how much you
wanted to hold in technology stocks, then you could use a LimitHoldingConstraint with the techPE group.
However, if you do not constrain the exact total holdings in technology stocks, then it may be easier to use a LimitWeightedAvgConstraint as in:
LimitWeightedAvgConstraint wtAvgConst =
new LimitWeightedAvgConstraint(strategy, "LWTAVG", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.SELECTION);
cp.setProperty(ConstraintProperties.Property.MAX, 40.0);
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 64
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.NUMBER);
cp.setProperty(ConstraintProperties.Property.BASE_SET, ws.getMasterSet());
wtAvgConst.setProperties(cp);
wtAvgConst.addGroupSelection(techPE, ConstraintProperties.EMPTY_PROPERTIES);
In addition to specifying the group of assets for which the weighted-average will be computed, a LimitWeightedAvgConstraint requires that a set of assets that function as a base set. The base-set of assets is specified using the
constraint's BASE_SET property. The base-set may refer to the group of assets used in the group selection. If the
base-set refers to a larger set of assets, the assets not in the selection group will be assigned a weight of zero. If the
base-set refers to a subset of the group, the wighted average computation will exclude all assets not in the base-set.
Bounds on Expected Return
Axioma Portfolio also supports constraints on the portfolio expected return. For instance, suppose we want to enforce that the expected return of the portfolio is at least 2%. This can be done as follows:
LimitWeightedAvgConstraint ac = new LimitWeightedAvgConstraint(strategy, "AC", null);
ConstraintProperties cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE,Constraint.Scope.SELECTION);
cp.setProperty(ConstraintProperties.Property.MIN, 2);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.PERCENT);
cp.setProperty(ConstraintProperties.Property.BENCHMARK, ws.getGroup("SimpleBenchmark"));
cp.setProperty(ConstraintProperties.Property.BASE_SET, ws.getMasterSet());
ac.setProperties(cp);
ac.addGroupSelection(ws.getGroup("AlphaGroup"), ConstraintProperties.EMPTY_PROPERTIES);
The constraint is written using a LimitWeightedAvgConstraint object that uses the workspace's alpha group.
The expected return of the portfolio is the weighted average of the asset returns where the weighting factors correspond to the assets holding fraction. By imposing a LimitWeightedAvgConstraint where the group selection
chosen is the set of asset alphas, we are in effect imposing a constraint on the portfolio expected return.
Limits on Beta
Axioma Portfolio also supports constraints on the portfolio beta. This requires that a beta group has been defined for
each asset in the local universe. The constraint on the portfolio beta is written using a LimitWeightedAvgConstraint object similar to the way that we constrained the portfolio alpha in the previous section. The only difference is that betas are not expressed as percentages and we must take this into account. Supposed that we want to
limit the optimized portfolio weighted average beta to be at most equal to 1.40. In order to achieve this, we setup a
LimitWeightedAvgConstraint using the workspace beta group (which we assume has been previously defined)
as follows:
LimitWeightedAvgConstraint bc = new LimitWeightedAvgConstraint(strategy, "BC", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE,Constraint.Scope.SELECTION);
cp.setProperty(ConstraintProperties.Property.MAX, 140);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.PERCENT);
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 65
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
cp.setProperty(ConstraintProperties.Property.BENCHMARK, ws.getGroup("SimpleBenchmark"));
cp.setProperty(ConstraintProperties.Property.BASE_SET, ws.getMasterSet());
bc.setProperties(cp);
bc.addGroupSelection(ws.getGroup("BetaGroup"), ConstraintProperties.EMPTY_PROPERTIES);
Observed that we used 140 (instead of 1.40) when specifying the upper bound on the portfolio weighted average
beta because we specified the constraint unit as PERCENT.
Now suppose that we wish to limit the optimized portfolio weighted average beta to be within 3% of the benchmark beta. Again, we can do this by means of a LimitWeightedAvgConstraint in the following way:
LimitWeightedAvgConstraint abc = new LimitWeightedAvgConstraint(strategy, "ABC", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE,Constraint.Scope.SELECTION);
cp.setProperty(ConstraintProperties.Property.MAX, 3.0);
cp.setProperty(ConstraintProperties.Property.MIN, -3.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.PERCENT);
cp.setProperty(ConstraintProperties.Property.BENCHMARK, ws.getGroup("SimpleBenchmark"));
cp.setProperty(ConstraintProperties.Property.BASE_SET, ws.getMasterSet());
abc.setProperties(cp);
abc.addGroupSelection(ws.getGroup("BetaGroup"), ConstraintProperties.EMPTY_PROPERTIES);
Note that in this case we have specified both an upper and lower bound (the constrain's maximum and minimum).
Limits on Factor Exposures
A constraint on the exposure of a set of holdings to a risk factor can be created just as we did with a limit on the
portfolio beta and expected return using an instance of the LimitWeightedAvgConstraint class. In this particular
case, the group or metagroup specified for the constraint's group or metagroup selection represent the assets exposures to a risk factor or the set of asset exposures to the risk factors. The factor exposure group(s) can be retrieved
directly from the factor risk model, or in the case of Barra factor risk model, from the workspace as we did in the
section called “Industry Constraints”.
To demonstrate how to utilize a LimitWeightedAvgConstraint that references a metagroup of RiskfactorGroups, consider an example where we want to limit the active exposure to each risk factor to be no more than 5%
above the benchmark exposure. Then we could use the following code assuming that a Barra FactorRiskModel
with the identifier FRM has been previously created:
LimitWeightedAvgConstraint fxc = new LimitWeightedAvgConstraint(strategy, "FXC", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE,Constraint.Scope.SELECTION);
cp.setProperty(ConstraintProperties.Property.MAX, 5.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.PERCENT);
cp.setProperty(ConstraintProperties.Property.BENCHMARK, ws.getGroup("SimpleBenchmark"));
cp.setProperty(ConstraintProperties.Property.BASE_SET, ws.getMasterSet());
fxc.setProperties(cp);
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 66
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
fxc.addMetagroupSelection(ws.getMetagroup("FRM.RISKFACTORS"),
ConstraintProperties.EMPTY_PROPERTIES);
Observe that we were able to retrieve the metagroup representing the risk model's set of assets exposures to the
risk factors by invoking the Workspace's class getMetagroup(java.lang.String id) method with the string
resulting by concatenating the factor risk model name and the word RISKFACTORS separated by a period. This is
possible because the factor risk model is a Barra risk factor, and as was pointed out in the section called “Industry
Constraints”, such a metagroup is automatically generated by Axioma Portfolio when the factor risk model is created.
Robust Linear Constraint
A RobustConstraint imposes a linear inequality for a weighted combination of asset holdings, where the weights
are not known with certainty. We assume that we have estimates for the means of these weights and that the joint
distribution of these estimates has an elliptical shape. For a given uncertainty parameter, #, a RobustConstraint
ensures that the given inequality holds for all weights in an elliptical uncertainty region whose size is determined by
#.
To demonstrate how to utilize this constraint class, let us reconsider the example in the section called “Bounds on
Expected Return”. Since expected returns are not known with certainty, but rather are estimates, they are certain to
contain error. Suppose that we wish to constrain the expected return of the portfolio to be greater than 5% for all
values of alpha in its 99%-uncertainty parameter. Assuming that the estimation error in the expected returns of the
assets is normally distributed with mean b and variance defined by the factor risk model aem, the desired constraint
can be created as follows:
SimpleGroup alphaGroup = ws.getGroup("AlphaGroup");
// Add estimation errors as specific risks for all assets
Set specificRisks = new HashSet();
specificRisks.add(new AssetValue(ws.getAsset("DELL"), 0.004);
specificRisks.add(new AssetValue(ws.getAsset("MSFT", 0.005);
...
FactorRiskModel aem = new FactorRiskModel(ws, "AlphaErrorModel", null, ws.getDate(),
specificRisks);
RobustConstraint rc = new RobustConstraint(strategy, "RobustConst", "Robust Constraint");
// Set the alpha group, the base set of assets, the risk model and the confidence level (ETA)
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.SELECTION);
cp.setProperty(ConstraintProperties.Property.MIN, 5.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.PERCENT);
cp.setProperty(ConstraintProperties.Property.ALPHA_UNCERTAINTY_MODEL, aem);
cp.setProperty(ConstraintProperties.Property.KAPPA, 0.99);
cp.setProperty(ConstraintProperties.Property.BASE_SET, ws.getMasterSet());
cp.setProperty(ConstraintProperties.Property.BENCHMARK, bm);
rc.setProperties(cp);
rc.addGroupSelection(alphaGroup, ConstraintProperties.EMPTY_PROPERTIES);
Note that the value of alpha given in aem for each asset is not used in the RobustConstraint. Adding benchmark
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 67
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
to the constraint properties results in the active version of the constraint. The RobustConstraint is used to satisfy
linear inequality for a weighted combination of asset holdings.
Goldman Sachs Shortfall Constraint
A LimitGSShortfallConstraint can be used to pose a limit on the shortfall cost.
While trading large number of assets at a time, asset's value get reduced or increased, selling or buying the shares respectively. This trade off results in a shortfall cost. The Goldman Sachs Shortfall Constraint helps to place a limit on
the shortfall cost, so that the trading cost doesnt exceed a certain limit.
To demonstrate how to utilize this constraint class, let us consider the example, where a shortfall cost of 245000 in
currency is posed on the constraint.
LimitGSShortfallConstraint gssCon = new LimitGSShortfallConstraint(stg_, "gsscon", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.CURRENCY);
cp.setProperty(ConstraintProperties.Property.MAX, 245000.0);
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.AGGREGATE);
cp.setProperty(ConstraintProperties.Property.GS_SHORTFALL_MODEL, gssm_.getIdentity());
gssCon.setProperties(cp);
ConstraintProperties selcp = new ConstraintProperties();
gssCon.addAssetSetSelection(gssm_.getShortfallAssetSet(), selcp);
Limit Short Sell Constraint
A LimitShortSellConstraint can be used to pose a limit on the shortsell trading.
To demonstrate how to utilize this constraint class, let us consider the example, where a shortsell cost of 50000 in
currency is posed on the constraint.
LimitShortSellConstraint lssCon = new LimitShortSellConstraint(stg_, "lss constr", "Limit Short Sell const
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.CURRENCY);
cp.setProperty(ConstraintProperties.Property.MAX, 50000.0);
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.AGGREGATE);
cp.setProperty(ConstraintProperties.Property.GS_SHORTFALL_MODEL, gssm_.getIdentity());
lssCon.setProperties(cp);
lssCon.addGroupSelection(ws.getMasterSet(), ConstraintProperties.EMPTY_PROPERTIES);
Soft Constraints
Axioma Portfolio supports soft constraints. Traditionally, the term constraint has meant a "hard" restriction which
cannot be violated. That is, any solution that does not satisfy all of the constraints is not valid. This is an adequate
framework in many cases, but it is not always flexible enough to provide a realistic representation of the complex
tradeoffs present in portfolio optimization. Often, we would like to impose a constraint where a slight violation is
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 68
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
permissible if the violation allows a significant improvement in the overall objective function value. This can be accomplished through "soft" constraints. A soft constraint is a restriction that may be violated in exchange for a userspecified penalty in the objective function. In Axioma Portfolio, soft constraints can be imposed by specifying a number of parameters including the penalty to assess for a violation of the constraint, and also the penalty type. The latter
defines whether the penalty is a linear function of the amount of violation (in which case the penalty is the slope), a
quadratic or a scaled quadratic function of the amount of violation (in which case the penalty is the coefficient). In addition, Axioma Portfolio supports the imposition of a true "hard" constraint to limit the overall violation. The optional
"hard" bound is called the soft constraint's maximum violation.
A hard constraint is converted to a soft constraint by providing suitable values for the Constraint.PenaltyType,
Constraint.PenaltyValue, and the optional ConstraintProperties.Property.MAX_VIOLATION constraint
properties.
The following three constraint penalty types are available in Axioma Portfolio:
➤ Constraint.PenaltyType.LINEAR: The penalty is computed based on the violation of the soft bound.
➤ Constraint.PenaltyType.QUADRATIC: The penalty is computed based on the square of the violation of
the soft bound.
➤ Constraint.PenaltyType.SCALED_QUADRATIC: The penalty is computed based on the square of the
violation of the soft bound divided by the reference value of the portfolio.
For example, to specify a soft constraint on an active risk constraint, the following statements are required:
LimitTotalRiskConstraint actRC = new LimitTotalRiskConstraint(strategy, "actRC", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.AGGREGATE);
cp.setProperty(ConstraintProperties.Property.MAX, 15000.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.CURRENCY);
cp.setProperty(ConstraintProperties.Property.BENCHMARK, myBenchmark);
cp.setProperty(ConstraintProperties.Property.RISKMODEL, ws.getRiskModel("SmallRiskModel"));
cp.setProperty(ConstraintProperties.Property.MAX_VIOLATION, 1000.00);
cp.setProperty(ConstraintProperties.Property.PenaltyValue, 0.01);
cp.setProperty(ConstraintProperties.PenaltyType, Constraint.PenaltyType.LINEAR);
actRC.setProperties(cp);
actRC.addAssetSetSelection(ws.getMasterSet(), ConstraintProperties.EMPTY_PROPERTIES);
The first six lines impose the active risk constraint as usual: limiting the active risk (computed using the specified risk
model SmallRiskModel and relative to the specified benchmark myBenchmark) to $15,000. The next three lines
of code set the constraint properties necessary to convert this "hard" constraint to its soft constraint counterpart (i.e.
the PenaltyType, the PenaltyValue, and the optional MAX_VIOLATION). Finally, the remaining two lines of code
set the LimitTotalRiskConstraint object's constraint properties and specify the set of assets that the constraint
applies to. The soft constraint's maximum violation was specified as $1,000. That is, in this example, under no circumstances will the tracking error exceed $16,000. The constraint above is imposed as a soft constraint where each unit
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 69
Axioma Portfolio
Chapter 5. Bounds, Constraints, and Business Rules
of violation (per dollar in this case) from $15,000 to $16,000 is penalized linearly by 0.01 in the objective.
All of the constraint classes in Axioma Portfolio support the the soft constraint properties except for the following:
➤ BudgetConstraint,
➤ LimitLongShortRatioConstraint,
➤ LimitRelativeMarginalContributionToRiskConstraint,
➤ LimitWeightedAvgConstraint,
➤ ThresholdHoldingConstraint, and
➤ ThresholdTradeConstraint.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 70
Axioma Portfolio
Chapter 6. The Objective Function
Chapter 6. The Objective Function
In Axioma Portfolio, the objective function is expressed as a linear combination of objective terms or goals. For example, the rebalancing objective might be to maximize net return (expected return minus transaction costs). In this
case, we would need a term representing the expected return and another term representing the transaction costs.
In the following sections, we first introduce the objective function and then we describe each of the specialized
classes that are available in Axioma Portfolio to represent objective terms.
An example that shows how to create an objective function and that uses several of the objective term types is included in the examples folder in the product distribution. It is called ObjectivesExample.cpp.
The Objective
The objective function in Axioma Portfolio is created as an instance of the Objective class. The Objective is a
container that groups together and manages all of the user's objective terms and that constitute the rebalancing's net
objective.
An Objective object is created as part of a Strategy object. In other words, every objective in Axioma Portfolio
belongs to a strategy. The Objective class has two constructors. One constructor takes as input parameters the
strategy that the objective will belongs to, the objective's required name or identity, and the objective's optional description. The other constructor takes, in addition to the parameters just mentioned, a list of objective terms. The
use of these two constructors is illustrated below:
Objective simpleObjective = new Objective(strategy, "SimpleObjective", null);
Objective complexObjective = new Objective(strategy, "ComplexObjective", null, objTerms);
The first statement constructs an Objective using the simplest of the two constructors. The second statement constructs an Objective object using the constructor that requires the list of objective terms; in this case, objTerms
represents the set of objective terms, which we assume have been previously defined. Both of these objectives will
belong to the strategy object.
The objective sense for the objective function is set by using the setTarget(Objective.Target target) method of the Objective class and is specified as an instance of the static class Objective.Target. Two options are
available:
➤ Objective.Target.MAXIMIZE
➤ Objective.Target.MINIMIZE
In the following statement we specify that the simpleObjective variable represents a maximization problem:
simpleObjective.setTarget(Objective.Target.MAXIMIZE);
Objective Terms
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 71
Axioma Portfolio
Chapter 6. The Objective Function
In addition to the expected return and the transaction costs terms mentioned in the introduction of this chapter, an
objective function may include a number of other objective terms. For example, an objective function may incorporate one or more of the following terms: a market-impact term, a variance term, a robust term, a tax gains term, a
tax-liability term, and a linear term. The linear term represents a generic objective term that allows the user to include in the objective any function that can be calculated as a weighted sum of the holdings in a set of assets. The
variance term can be used to include objective terms that minimize the absolute risk or the active risk of a portfolio.
Axioma Portfolio provides specialized classes to allow specification of these objective goals in portfolio management
terms. We will discuss each one of these in the following subsections.
Once the objective terms have been created, they can be added to the objective function in one of two ways. On the
one hand, the objective terms can be grouped together in a java.util.Collection object and passed directly to
the Objective class constructor (as was shown in the previous section). In this case, each objective term is assigned
by default a weighting coefficient of +1.0. The user can manually change the coefficient by means of the setObjectiveTermWeight(ObjectiveTerm term, double weight) method of the Objective class. On the other
hand, the objective terms can be added individually using the addObjectiveTerm(ObjectiveTerm term,
double weight) method of the Objective class. For example, the following statement adds the objective term
objTerm object to the simpleObjective variable using a weighting coefficient of -1.0. The objTerm object is assumed to have been previously created.
simpleObjective.addObjectiveTerm(objTerm, -1.0);
Expected Return
An objective term representing the expected return (alpha) of a group of assets may be included in the objective
function by creating an ExpectedReturnTerm object:
ExpectedReturnTerm ero = new ExpectedReturnTerm(strategy, "ExpectedReturn", null);
ero.setAlphaGroup(ws.getGroup("AlphaGroup"));
The first argument of the ExpectedReturnTerm class constructor represents the strategy that the objective term
object will belong to. The second and third arguments represent the objective term's unique name and optional description, respectively. Once an ExpectedReturnTerm object has been created, we must specify the group of assets with associated weights (alphas) that will be used to compute the portfolio expected return. This can be done by
using the setAlphaGroup(Group alphaGroup) method of the ExpectedReturnTerm class. The net return is
computed as the sum of the scalar product of the optimized holdings and the alphas of each asset.
When adding the expected return term to the objective function, we will choose a positive weighting coefficient (or
multiplier) if the sense of the objective function will be set so as to maximize it. If we were going to minimize the objective function, then we would add the expected return objective term to the objective function with a negative
multiplier.
Robust Term
A RobustTerm represents a weighted combination of asset holdings where the weights are not known with certainty but are assumed to have a multivariate normal distribution. For a given set of asset holdings, the value of a RobustTerm is computed as the worst value for all weights in a uncertainty region around the mean. That is, if you are
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 72
Axioma Portfolio
Chapter 6. The Objective Function
maximizing a RobustTerm, then the value is the lowest possible among all values inside the uncertainty region.
To demonstrate how to utilize this objective term type, suppose that we want to maximize the expected return of a
portfolio subject to a set of constraints. Since expected returns are not known with certainty, but rather are estimates, they are certain to contain error. Suppose that we want to maximize the worst-case expected return of a portfolio where the worst-case value is computed as the least expected return possible using a given uncertainty region
of expected returns for individual assets. We assume that the estimation error of the expected returns for the individual assets is normally distributed with mean b and variance defined by the factor risk model aem. This objective
term can be created as follows:
AssetGroup b = ws.getGroup("AlphaGroup");
AssetSet s = ws.getMasterSet();
// Add estimation errors as specific risks for all assets
Set specificRisks = new HashSet();
specificRisks.add(new AssetValue(ws.getAsset("DELL"), 0.004);
specificRisks.add(new AssetValue(ws.getAsset("MSFT", 0.005);
...
FactorRiskModel aem = new FactorRiskModel(ws, "AlphaErrorModel", null, ws.getDate(),
specificRisks);
RobustTerm rt = new RobustTerm(strategy, "RobustTerm", "Simple Robust Term");
// Set the alpha group, the base set of assets, the risk model, the uncertainty parameter (Kappa)
// and the benchmark.
rt.setAlphaGroup(b);
rt.setBaseAssetSet(s);
rt.setAlphaUncertaintyModel(aem);
rt.setKappa(0.99);
rt.setBenchmark(bm);
Note that the value of the average alpha is computed as the mean of the returns specified in the AssetGroup object
b and that the uncertainty region is defined through the uncertainty level (Kappa).
Transaction Costs
Axioma Portfolio supports linear and piecewise-linear (convex) symmetric and asymmetric transaction costs in the
objective function. Before we can create a transaction cost term to be included in the objective function of a rebalancing, we must first construct a transaction cost model that specifies how the costs associated with the transactions
(purchases and sales) for each asset are calculated. A transaction cost model itself is a collection of cost structures
that resembles a linear function for computing the transaction costs.
In Axioma Portfolio, a transaction cost objective term is created as an instance of the TransactionCostTerm class
and then incorporated into the objective function by means of the addObjectiveTerm(ObjectiveTerm term,
double weight) method of the Objective class.
In the following sections, we show how to create a TransactionCostModel object along with its set of CostStructure objects, and how to create a TransactionCostTerm object using the TransactionCostModel object.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 73
Axioma Portfolio
Chapter 6. The Objective Function
Transaction Cost Models
A transaction cost model is a collection of cost structures that resemble a model for calculating piecewise linear purchase and sale costs. A transaction cost model is created as an instance of the TransactionCostModel class. Its
constructor takes four arguments: The parent workspace, the required unique name or identifier, the optional description, and the transaction cost model date. A transaction cost model is created in this way:
TransactionCostModel tcm = new TransactionCostModel(ws, "TCostModel", null, ws.getDate());
There are four types of transaction cost structures that are supported in Axioma Portfolio:
➤ Symmetric Linear
➤ Asymmetric Linear
➤ Symmetric Piecewise-Linear
➤ Asymmetric Piecewise-Linear
The type of a transaction cost model is defined by the type of cost structures that it contains. For example, a transaction cost model is said to be symmetric linear if each one of the cost structures that it contains is symmetric linear. Similarly, a transaction cost model is said to be asymmetric linear if any of the cost structures that it contains is asymmetric
linear. In the next section, we'll provide a definition for cost structures and describe each of the four cost structure
types that are available in Axioma Portfolio
Cost Structures
A cost structure defines a series of domains or regions, delimited by a set of breakpoints, where the transaction cost
for a given transaction value (either a sale or a purchase) is computed as a linear sum of terms that represent the
product of a transaction cost coefficient and a transaction amount for each of the regions spanned by the given transaction value. An example will make this point clearer. Assume that a cost structure for ARBA and AZPN is defined in
such a way that sell transactions larger than $0.0 but smaller than $5000 are computed as 2% of the transaction
amount, while those that are larger than $5000 are computed as 4% of the transaction amount. The $0.0 and $5000
values are referred to as the breakpoints of the cost structure. The 2% value is referred to as the transaction cost
coefficient for the first transaction cost region (from $0 to $5000) of the cost structure. On the other hand, 4% is the
transaction cost coefficient for the remaining transaction cost region (from $5000 to infinity). The transaction cost
coefficients are usually referred to as the slopes of the cost structure domains. Now suppose that we wish to compute the transaction cost for a sell transaction for an amount of $2000 for either AZPN or ARBA. Since this value falls
within the first transaction cost region, the transaction cost is 2% of $2000, or $40. The transaction cost for a transaction larger than $5000 is computed differently. Assume that we wish to compute the transaction cost for a sale
transaction for an amount of $6000. In this case, we need to compute the transaction cost corresponding to the two
regions that are covered by the $6000 value (i.e., the regions before and after the $5000 breakpoint). The first transaction cost is 2% of the initial $5000 (or $100) and the second transaction cost is 4% of the remaining $1000 (or
$40). Therefore the net transaction cost for a $6000 sell transaction is $140 ($100 + $40).
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 74
Axioma Portfolio
Chapter 6. The Objective Function
Buy transaction costs are computed in a similar way, except that the buy slopes and breakpoints are used instead. If
the buy slopes and breakpoints in a cost structure are the same as the sell slopes and breakpoints, the cost structure
is said to be symmetrical. Otherwise, it is said to be asymmetrical. A transaction cost function must be convex, i.e.,
the slopes must be non-decreasing with the index.
To summarize, the characteristics of a cost structure are its composition (or set of assets that it applies to) and its
buy and sell slopes along with their corresponding buy and sell breakpoints.
Cost structures are created as instances of the CostStructure class in Axioma Portfolio. Every cost structure must
be created as a member of a TransactionCostModel object. The constructor of the CostStructure class takes
three arguments: A parent transaction cost model, a unique name or identifier, and an optional description. The following statement creates a cost structure called CS1:
CostStructure cs1 = new CostStructure(tcm, "CS1", "Symmetric Linear");
After creating a cost structure, we add the assets that it will apply to. This is achieved by using the includeAsset(Asset a) method of the CostStructure class. This method takes a single parameter: the Asset object to
be included in the cost structure. The CostStructure's breakpoints and slopes are specified using the addBuySlope(double start, double value) and addSellSlope(double start, double value) methods. The addBuySlope(double start, double value) method is used to specify breakpoints and slopes applicable to buy transactions; the addSellSlope(double start, double value) method is used to specify
breakpoints and slopes applicable to sell transactions. In the following statements, we specify that CostStructure
cs1 is applicable to DELL, MSFT, and IBM. Furthemore, we indicate that there exists a single breakpoint equal to 0.0
with a slope of 0.02. That is, the transaction costs for buy and sell transactions that occur in the region from $0.0 to
infinity are computed as 2% of the transaction amount:
cs1.includeAsset(ws.getAsset("DELL"));
cs1.includeAsset(ws.getAsset("MSFT"));
cs1.includeAsset(ws.getAsset("IBM"));
cs1.addBuySlope(0.0, 0.02);
cs1.addSellSlope(0.0, 0.02);
Observe that the same breakpoint and slope is being used for both buy and sell transaction costs. Cost structures
with a single breakpoint and slope are called linear cost structures. If the breakpoints and slopes for the buy and sell
transaction costs are equal, then the cost structure is said to be symmetric. cs1 is an example of a symmetric linear
cost structure. If there exists a single breakpoint and slope for both the buy and sell transactions, but the breakpoint
and slope for the buy transactions is different from the breakpoint and slope of the sell transaction costs, then the
cost structure is linear and asymmetric. Here is an example of an asymmetric linear cost structure:
CostStructure cs2 = new CostStructure(tcm, "CS2", "Asymmetric Linear");
CDATA[cs2.includeAsset(ws.getAsset("ORCL"));
cs2.addBuySlope(0.0, 0.04);
cs2.addSellSlope(0.0, 0.06);
This second cost structure indicates that buy and sell transaction cost for ORCL are computed differently. Buy transaction costs are computed as 4% of the transaction amount, while sell transaction costs are computed as 6% of the
transaction amount.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 75
Axioma Portfolio
Chapter 6. The Objective Function
If a cost structure contains more than one breakpoint and slope, then it is called piecewise-linear. If in addition, the
breakpoints and slopes are the same for the buy and sell transactions, then the cost structure is also symmetric. The
following example creates the cost structure that was described in the introduction of this section. This cost structure is piecewise-linear symmetric:
CostStructure cs3 = new CostStructure(tcm, "CS3", "Piecewise-Linear Symmetric");
cs3.includeAsset(ws.getAsset("ARBA"));
cs3.includeAsset(ws.getAsset("AZPN"));
cs3.addBuySlope(0.0, 0.02);
cs3.addBuySlope(5000.0, 0.04);
cs3.addSellSlope(0.0, 0.02);
cs3.addSellSlope(5000.0, 0.04);
Finally, if a cost structure contains more than one breakpoint and slope, but the breakpoints and slopes for the buy
and sell transactions are not equal, then the cost structure is said to be piecewise-linear asymmetric. This is an example of a piecewise-linear asymmetric cost structure:
CostStructure cs4 = new CostStructure(tcm, "CS4", "Piecewise-Linear Asymmetric");
cs3.includeAsset(ws.getAsset("SAP"));
cs3.includeAsset(ws.getAsset("TSG"));
cs3.addBuySlope(0.0, 0.04);
cs3.addBuySlope(5000.0, 0.06);
cs3.addSellSlope(0.0, 0.02);
cs3.addSellSlope(10000.0, 0.03);
Once a cost structure has been defined, the transaction cost for the transaction amount is computed by invoking the
getCost(double value) method of the CostStructure class. This method takes a single parameter representing the transaction amount. The sign of the specified transaction value determines whether a buy transaction cost or
a sell transaction cost is computed. A positive value indicates a buy transaction while a negative value indicates a sell
transaction. The value returned applies to each of the assets that were included in the cost structure. For example,
the transaction cost computed using the cost structure cs1 applies to DELL, MSFT, and IBM.
Now that the transaction costs structures and the transaction cost model has been created, we can define the transaction cost objective term. A transaction cost objective term is created using the TransactionCostTerm class. The
constructor of the TransactionCostTerm class takes three parameters: the strategy that the transaction cost objective term will belong to, the required strategy name, and the optional strategy description. A TransactionCostTerm object is created like this:
TransactionCostTerm tct = new TransactionCostTerm(strategy, "TCT", "Transaction Cost Objetive Term");
The newly created transaction cost objective term tct is incorporated into the objective function using the addObjectiveTerm() method of the Objective class as demonstrated by the following statement:
simpleObjective.addObjectiveTerm(tct, -1.0);
The second argument, -1.0, is the multiplier on the transaction costs in the objective. This multiplier is sometimes
called the aversion coefficient. Consistent with our use of a 1.0 multiplier for the expected return, it makes sense to
have a negative multiplier for transaction costs since these (positive) costs should be subtracted from the objective
which will be maximized.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 76
Axioma Portfolio
Chapter 6. The Objective Function
Market Impact
In Axioma Portfolio, it is possible to penalize large trades. The idea is that a large trade is difficult to process or implement on the trading side and costs more because the trade itself affects the price and, therefore, it should be penalized in the portfolio optimization to discourage it from appearing in the solution. This is sometimes called market impact or illiquidity. It is modeled using a penalty cost that is a quadratic function of the transaction size (either a purchase or a sale). This serves to penalize the transaction more heavily as the transaction size increases. This market
impact component can be added to the objective with a negative multiplier (aversion coefficient) to signify that it
should be penalized in the objective function (that we will maximize). Of course, if you are minimizing the overall objective, then the market impact should be given a positive multiplier.
By default, Axioma Portfolio models market impact using a penalty cost that is as a quadratic function of the transaction. However, it is also possible to model the market impact using a penalty cost that elevates the transaction to the
three-halves-power instead of squaring it. If you wish to use the three-halves-power of the transaction as a market
impact penalty, then after creating your market impact objective term, specify its type as MarketImpactType.THREE_HALVES_POWER using the setType(MarketImpactType miType) method of the MarketImpactTerm class.
For symmetric market impact models, i.e., models where the market impact is identical whether it is a buy or a sell,
the market impact component is constructed by defining a Group object. The weight associated with an asset represents the coefficient in front of the quadratic term (the asset's transaction size squared). The following example
defines market impact penalties on a set of eight assets, each with coefficients 0.000001, and then adds the market
impact objective term to the objective function:
Group mig = new SimpleGroup(ws, "MIG", "MarketImpactGroup", ws.getDate(), Unit.NUMBER);
mig.setComposition(ws.getAsset("DELL"), 0.000001);
mig.setComposition(ws.getAsset("MSFT"), 0.000001);
mig.setComposition(ws.getAsset("IBM"), 0.000001);
mig.setComposition(ws.getAsset("ORCL"), 0.000001);
mig.setComposition(ws.getAsset("ARBA"), 0.000001);
mig.setComposition(ws.getAsset("AZPN"), 0.000001);
mig.setComposition(ws.getAsset("SAP"), 0.000001);
mig.setComposition(ws.getAsset("TSG"), 0.000001);
MarketImpactTerm mit = new MarketImpactTerm(strategy, "MIT", "MarketImpactTerm");
mit.setBuyImpactGroup(mig);
mit.setSellImpactGroup(mig);
simpleObjective.addObjectiveTerm(mit, -1.0);
The multiplier of the market impact on the objective is -1.0 signifying that these should negatively impact the objective. Note that care must be taken in defining the coefficients. See the MarketImpactTerm class in the Axioma Portfolio JavaDocs [index.html] for more details.
Asymmetric market impact models, where the magnitudes of buy and sell market impact are different, is constructed
by defining a separate Group for the buy and sell transactions. The weights specified in the Group objects represent
the coefficients in front of the quadratic term (the asset's transaction size squared): one for the buy-side, the other
for the sell-side. The following example defines market impact penalties on a set of eight assets, each with buy-side
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 77
Axioma Portfolio
Chapter 6. The Objective Function
coefficients of 0.000001 and sell-side coefficients of 0.000002, and then adds the market impact objective term to the
objective function:
Group mig2 = new SimpleGroup(ws, "MIG2", "MarketImpactGroup", ws.getDate(), Unit.NUMBER);
mig2.setComposition(ws.getAsset("DELL"), 0.000002);
mig2.setComposition(ws.getAsset("MSFT"), 0.000002);
mig2.setComposition(ws.getAsset("IBM"), 0.000002);
mig2.setComposition(ws.getAsset("ORCL"), 0.000002);
mig2.setComposition(ws.getAsset("ARBA"), 0.000002);
mig2.setComposition(ws.getAsset("AZPN"), 0.000002);
mig2.setComposition(ws.getAsset("SAP"), 0.000002);
mig2.setComposition(ws.getAsset("TSG"), 0.000002);
MarketImpactTerm mit2 = new MarketImpactTerm(strategy, "MIT2", "MarketImpactTerm");
mit2.setBuyImpactGroup(mig2);
mit2.setSellImpactGroup(mig2);
simpleObjective.addObjectiveTerm(mit2, -1.0);
Observe that we have reused the Group object mig that was created in the previous example in order to specify the
buy-side coefficients of the new market impact objective term mit2.
Goldman Sachs Shortfall
A concrete implementation of the ObjectiveTerm class that represents the Goldman Sachs Shorfall for a set of assets. Once a GoldmanSachsShortfallTerm object has been created, it can be included in the objective function of
a rebalancing by means of the
Objective.addObjectiveTerm(ObjectiveTerm);
method. A GoldmanSachsShortfallTerm incorporates Goldman Sachs shortfall into the objective.
An instance of the GoldmanSachsShortfallTerm class is constructed with the statement:
GoldmanSachsShortfallTerm gssTerm = new GoldmanSachsShortfallTerm(stg_, "gssterm", null);
This creates a new GoldmanSachsShortfallTerm object belonging to the specified Strategy stg_, and whose
identity and description are set to the specified values.
Below is an example of using the GoldmanSachsShortfallModel from Chapter 4 with the GoldmanSachsShortfallTerm:
GoldmanSachsShortfallModel gssm_ = new GoldmanSachsShortfallModel(ws_, "gssm", null, null);
gssm_.setShortfallInfo(a1_, "^_dq#/=7CLYi$9QSgx2Nj&F", 895347441L);
gssm_.setShortfallInfo(a2_, "^_hv\")93=FWhz6I]`u,Ic&@b", 4192448245L);
gssm_.setShortfallInfo(a3_, "_`lq{+93?H[l{56L\\o/Ea$", 2264452990L);
gssm_.setShortfallInfo(a4_, "bckw)7E?JSh{5GY[o%BXq3N", 3695110181L);
GoldmanSachsShortfallTerm gssTerm = new GoldmanSachsShortfallTerm(stg_, "gssterm", null);
gssTerm.setBaseAssetSet(ws_.getMasterSet());
gssTerm.setGoldmanSachsShortfallModel(gssm_);
gssTerm.setDefaultWeight(-0.01);
obj_.addObjectiveTerm(gssTerm);
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 78
Axioma Portfolio
Chapter 6. The Objective Function
For details on the Goldman Sachs Shortfall Model see the the section called “The Goldman Sachs® Shortfall Model
Class”.
Short Sell
A concrete implementation of the ObjectiveTerm class that represents a generic objective term that allows the
user to include in the objective any function that can be represented as a weighted combination of the short portion
of an asset sell variable. Once a LinearShortSellTerm object has been created, it can be included in the objective
function of a rebalancing by means of the
Objective.addObjectiveTerm(ObjectiveTerm);
method.
An instance of the LinearShortSellTerm class is constructed with the statement:
LinearShortSellTerm lssTerm = new LinearShortSellTerm(stg_, "lssterm", null);
This creates a new LinearShortSellTerm object belonging to the specified Strategy stg_, and whose identity
and description are set to the specified values.
Risk
Often it is desirable to penalize risk in the objective function. This can be either absolute risk, active risk, or a variance. Note that absolute risk and active risk are measured as standard deviations (the same units as expected return
or transaction costs, i.e., either dollars or a percentage of the reference size) and not as a variance. Axioma Portfolio
offers two classes that can be used to represent risk terms and variance terms that can be incorporated in the objective of a rebalancing. Objective terms representing the risk of a group of assets can be constructed using the
RiskTerm class, while objective terms representing the variance of a group of assets can be constructed using the
VarianceTerm class. These two classes are covered in more details in the following sections.
The RiskTerm Class
The RiskTerm class represents the risk of a weighted combination of assets. This class represents active or relative
risk terms depending on whether a benchmark has been specified or not. A benchmark is specified by means of the
setBenchmark(Group benchmark) method of the RiskTerm class. In order to represent variance terms, use the
VarianceTerm class (see the section called “The VarianceTerm Class” ).
A RiskTerm object is created as part of a Strategy. Its constructor contains three parameters: a reference to the
strategy that the RiskTerm object will belong to; a name or identity for the RiskTerm object; and an optional description. The following statement creates a risk term (rt) that belongs to the strategy strategy, and whose name
and description are set to riskterm and SimpleRiskTerm, repectively:
RiskTerm rt = new RiskTerm(strategy, "riskterm", "SimpleRiskTerm");
Once a RiskTerm object has been created, we can use its setGroup(Group assets) method to specify the
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 79
Axioma Portfolio
Chapter 6. The Objective Function
group of assets for which the risk will be computed, and the setRiskModel(RiskModel riskmodel) method to
specify the risk model that will be used to compute the risk for the group of assets. The following statements convert
the risk term rt to an active risk term, by providing a suitable benchmark, and set its risk model and group of assets
to appropriate variables, which we assume have been previously created:
rt.setBenchmark(ws.getGroup("simpleBM"));
rt.setRiskModel(ws.getRiskmodel("FRM"));
rt.setGroup(ws.getGroup("myInd"));
When the selected risk model is a factor risk model, instead of using all the factors, selected factors can be used. The
selected factors can have factor names and reference to metagroups.
List<String> selectedfactors = new ArrayList<String>();
selectedfactors.add("FRM.Factor1");
selectedfactors.add("FRM.Factor2");
mcarc.setSelectedFactors(selectedFactors);
The variable rt can now be included in the objective of a rebalancing by means of the addObjectectiveTerm(ObjectiveTerm term, double weight) method of the Objective class. The next code sample illustrates how the newly created active risk term can be included in the simpleObjective object that was created in
the beginning of this chapter:
simpleObjective.addObjectiveTerm(rt, -1.0);
The VarianceTerm Class
The VarianceTerm class represents the variance of a weighted combination of assets. This class represents active
or relative variance terms depending on whether a benchmark has been specified or not. A benchmark is specified by
means of the setBenchmark(Group benchmark) method of the VarianceTerm class.
A VarianceTerm object is created as part of a Strategy. Its constructor contains three parameters: a reference to
the strategy that the VarianceTerm object will belong to; a name or identity for the VarianceTerm object; and an
optional description.
Like in the case of a RiskTerm object, the group of assets that a VarianceTerm applies to and the risk model to use
in order to compute the group of assets variance are specified with the setGroup(Group group) method and the
setRiskModel(RiskModel riskmodel) method, repectively. When the selected risk model is a factor risk model, instead of using all the factors, selected factors can be used using setSelectedFactors(List selectedFactors) . The selected factors can have factor names and reference to metagroups. Furthermore, a VarianceTerm object can be included in the objective function of a rebalancing by means of the addObjectiveTerm(ObjectiveTerm term, double weight) method of the Objective class.
Tax Objective
Axioma Portfolio also supports incorporation of tax-liability in the objective function. This functionality will be described in detail in Chapter 10.
Multi-Criteria Optimization
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 80
Axioma Portfolio
Chapter 6. The Objective Function
Objective terms are included in an Objective object by means of the addObjectiveTerm(ObjectiveTerm
term, double weight) method of the Objective class. This method takes two parameters: the objective term
to be incorporated in the objective and a multiplier. The multiplier defines both the sense and the weight of each objective term. In the previous example, the objective will be maximized. Since a higher expected return is desired, the
expected return objective term received a positive multiplier (a weight of 1.0), while the transaction costs, market
impact and risk objective terms got negative multipliers. The multipliers determine the relative impact of each objective term and implicitly define the multi-criteria trade-offs used to search for the optimal solution.
Adjusting these multipliers, by means of the setObjectiveTermWeight(ObjectiveTerm term, double
weight) method of the Objective class, specifies the relative importance of the different objective function components (e.g., to do multi-criteria optimization). This provides full flexibility to the user. See the section called “Tax
Objective” for an optimization example that uses multiple objective terms in the objective function.
LINEAR_TRANSACTION_COST
The Linear Transaction Cost term represents a weighted combination of asset holdings. Both or a buygroup-ref/buy-set-ref or sell-group-ref/sell-set-ref attribute must be included. If a buy/sell-group-ref is used the asset
weights from the group are used in the linear term. If a buy/sell-set-ref is used, a weight of 1.0 is assigned to each
member of the set.
LINEAR_BUY
The Linear Buy term represents a weighted combination of asset holdings. Either a group-ref or a set-ref attribute
must be included. If a group-ref is used the asset weights from the group are used in the linear term. If a set-ref is
used, a weight of 1.0 is assigned to each member of the set.
LINEAR_SELL
The Linear Sell term represents a weighted combination of asset holdings. Either a group-ref or a set-ref attribute
must be included. If a group-ref is used the asset weights from the group are used in the linear term. If a set-ref is
used, a weight of 1.0 is assigned to each member of the set.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 81
Axioma Portfolio
Chapter 7. Constraint Attribution
Chapter 7. Constraint Attribution
Constraint Attribution methodology helps the user understand how constraints impact the optimal portfolio resulting
from solving a rebalancing. The constraint impact can be viewed in two ways:
➤ The holdings decomposition attributes a portfolio of holdings to each constraint. Under most circumstances,
optimization theory guarantees that the portfolios of all the constraints sum to the optimal (active) holdings.
➤ The implied alpha decomposition shows how each constraint and objective contribute to the implied alpha
of the portfolio.
Decomposition
The Decomposition class is used to do perform the decomposition. The methods setAlphaDecomposition(boolean) and setHoldingDecomposition(boolean) can be used to set the type of decomposition and
doDecomposition() is used to perform the decomposition. The setDecompositionBaseSet() and getDecompositionBaseSet() can be used to set/get the decomposition base set (assetset). There can be one decomposition base and one or more decomposition groups.
Decomposition decomp = strategy.getDecomposition();
decomp.setAlphaDecompEnabled(true);
decomp.setHoldingsDecompEnabled(true);
decomp.setDecompositionBaseSet(ws.getMasterSet());
Decomposition Base
The setDecompositionBase() and getDecompositionBase() is used to set/ get the decomposition base.
Either a Objective Term or a Constraint which is an instance of HoldingsDecompositionBase can be set as the
decomposition base.
LimitTotalRiskConstraint arc = new LimitTotalRiskConstraint(strategy, "ActiveRiskConstraint", null);
// Set decomposition base
decomp.setHoldingsDecompBase(arc);
Decomposition Group
The decomposition group can be any of Objective Term, Constraint or ImplicitConstraint. The following are the
available implicit constraints: GRANDFATHER_BOUNDS, LOCAL_UNIVERSE, OPTIONS.NO_SHORTING, OPTIONS.NO_CROSSOVER. One or more decomposition group's can be used to perform the decomposition.
// Create decomposition groups
DecompositionGroup budgetExpRtn = new DecompositionGroup(decomp, "BudgetExpRtn",
"Group for Budget constraint and expected return term");
budgetExpRtn.addConstraint(bc);
budgetExpRtn.addObjectiveTerm(ero);
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 82
Axioma Portfolio
Chapter 7. Constraint Attribution
DecompositionGroup totalRisk = new DecompositionGroup(decomp, "TotalRisk",
"Group for total risk constraint");
totalRisk.addConstraint(arc);
// Decomposition Group with implicit constraints
DecompositionGroup implicitConstraints = new DecompositionGroup(decomp, "ImplicitConstraints",
"Group for implicit grandfather bounds constraint");
implicitConstraints.addImplicitConstraint(Decomposition.IMPLICIT_GRANDFATHER_BOUNDS_CON);
implicitConstraints.addImplicitConstraint(Decomposition.IMPLICIT_LOCAL_UNIVERSE_CON);
User can also add compliance constraints to decomposition group using:
DecompositionGroup complianceConsGp = new DecompositionGroup(decomp, "ComplianceConsGp",
"Group for compliance constraints");
// Determines the account at run-time based on which rebalancing the strategy is used
complianceConsGp.addConstraint("ACCOUNT.maxRisk");
// If myAccountName is not the rebalancing account, then this is ignored
complianceConsGp.addConstraint("myAccountName.maxRisk");
Decomposition Results
The decomposition is performed on the results obtained from the rebalancing. The getAlphaDecomposition()
and getHoldingsDecomposition() can be used to view the results of the alpha and holdings decomposition. The
getAlphaResidual() and getHoldingsResidual() can be used to view the results of the residuals.
Map<DecompositionGroup, Collection<AssetValue>> decompMap = null;
RebalancingSolution sol = rebalancing.getSolution();
try {
sol.doDecomposition();
}
catch (DecompositionException ex) {
ex.printStackTrace();
}
// Get alpha decomposition results
decompMap = sol.getAlphaDecomposition();
// Get holding decomposition results
decompMap = sol.getHoldingsDecomposition();
// Get alpha residual results
decompMap = sol.getAlphaResidual();
// Get holding residual results
decompMap = sol.getHoldingsResidual();
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 83
Axioma Portfolio
Chapter 8. Solving with Axioma Portfolio
Chapter 8. Solving with Axioma Portfolio
The above chapters focused on defining portfolio optimization problems. In this chapter we show how to solve them
using Axioma Portfolio.
Rebalancing Solution
Axioma Portfolio was designed to automatically employ the best solution strategy given a particular problem instance, so most often it is sufficient to invoke the solve() method of a Rebalancing object in order to obtain a
solution. This is illustrated in the following code statement:
RebalancingBase.Status status = rebal.solve();
The solve() method of the Rebalancing class returns a value of type RebalancingBase.Status, which in the
above example is caught in the status variable and which provides information about the optimization process. This
status variable has four possible values:
➤ SolutionFound, which signifies that a solution to the problem was found,
➤ NoSolutionFound, which signifies that no solution to the problem was found,
➤ NoLicense, which signifies that a valid Axioma Portfolio license could not be found, and
➤ InternalError, which signifies that an error occurred somewhere in the process (this kind of error may
be caused by bad input data, incorrect usage of the API, etc.).
For more information about these values, see the RebalancingBase.Status class in the Axioma Portfolio JavaDocs
[index.html].
The next step is to inspect the solution: this is discussed in the next chapter. First, we describe some of the optimization parameters that can be accessed to impact the solution process.
Optimization Parameters
Axioma Portfolio provides some adjustable parameters that affect the optimization process. These parameters are
set in the Rebalancing object using the appropriate setXXX method, where XXX stands for the name of the parameter that we wish to set.
For instance, it is possible to specify how much time is spent searching for a solution. This is done as follows:
rebal.setRunTimeMax(300d);
The setRunTimeMax(double d) method of the Rebalancing class sets the maximum time (in seconds) that the
optimization search algorithm is allowed to run for. In the above example, we set this to 300 seconds (5 minutes).
The optimization process will stop after 300 seconds (and return the best solution found so far) or when an optimal
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 84
Axioma Portfolio
Chapter 8. Solving with Axioma Portfolio
solution is found, whichever comes first.
Several other parameter settings are available. For instance:
rebal.setNameCountCriterion(1.0, Unit.CURRENCY);
Sets the unit and value for the rebalancing name-count-criterion property. The name-count-criterion is a minimum
value on the holdings in an asset for it to be counted in limit-names, limit-long-names, and limit-short-names constraints. The purpose of the name-count-criterion is to prevent the optimizer from taking an extremely small position
in a security in order to satisfy a lower bound on the number of names held. The above code instructs Axioma Portfolio not to count any asset whose optimized holdings are less than $1.0 in any limit names constraint.
Other optimization parameters that can be set are the rebalancing right-hand-side tolerance, scale factor and the cardinality branch rule. The right-hand-side tolerance is a value that defines a maximum range around which the optimization solution is guaranteed to be optimal. The rebalancing right-hand-side tolerance can be set using the setRightHandSideTolerance(double d) method of the Rebalancing class. The scale factor is a multiplier that
scales the rebalancing solution. The rebalancing scale factor can be set using the setScaleFactor(double d)
method of the Rebalancing class. The cardinality branch rule provides an option to select branching rule for LimitNames and LimitNumTrades constraint. The rebalancing cardinality branch rule can be set using the setCardinalityBranch(String cardinalityBranch) method of the Rebalancing class. The next statements set the optimization right-hand-side tolerance to 1e-6, the scale factor to 1e-3 and the cardinality branch rule to
MAX_POSITION respectively:
rebal.setRightHandSideTolerance(1e-6);
rebal.setScaleFactor(1e-3);
rebal.setCardinalityBranch("MAX_POSITION");
Optimization problems with combinatorial constraints such as limits on the number of names or thresholds can be
very challenging to solve, sometimes requiring a significant amount of time to find feasible solutions. One key component to solving these problems is to find tractable optimization problems that closely approximate these combinatorial constraints. These optimizations are often referred to as relaxations, as they relax the more difficult constraints.
There are a variety of ways to accomplish this and some relaxations approximate the combinatorial constraints more
tightly than others. While the tighter relaxations are usually more difficult to solve, they generally lead to finding higher quality solutions that satisfy the combinatorial constraints in a shorter period of time. However, the efficacy of using tighter approximations can vary with specific instances. By default, the optimization engine uses a tight approximation. In some rare instances, users may find that this default setting results in degradation in performance compared
to looser relaxations. In this case, users can switch the RelaxParam setting to NORMAL, in which the engine will use
relaxation that is looser and easier to solve. For instance:
rebal.setRelaxParam(RebalancingBase.RelaxParam.NORMAL);
These and other parameters are described in more detail in the Axioma Portfolio JavaDocs [index.html].
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 85
Axioma Portfolio
Chapter 9. Inspecting the Solution
Chapter 9. Inspecting the Solution
Axioma Portfolio provides the Analytics class in order to analyze the properties of a portfolio or the results of a
rebalancing. An instance of this class can be used to compute the expected return for a set of assets, the turnover involved in transitioning from an initial to a final set of holdings, the marginal contribution to total or active risk for a
group of assets, etc. Some of the functions available in the Analytics are examined in more details in the section
called “Portfolio Analysis Functions”.
In addition to the Analytics class, Axioma Portfolio offers the RebalancingSolution class to facilitate the encapsulation of all of the information that pertains to the solution of a portfolio rebalancing. For example, this class
contains a number of useful methods such as: getTradedAssets(), getIntialObjectiveValue(), getFinalObjectiveValue(), getInitialHoldings(), getFinalHoldings(), getSharesTraded(), etc..
Below, we extract the RebalancingSolution instance contained in the Rebalancing object rebal and use it in
conjunction with an instance of the Analytics class in order to compare the initial and final portfolio holdings and to
compute the final portfolio expected return. Since the holdings in the rebalancing solution are expressed as shares,
we use the price Group to convert from shares to currency.
RebalancingSolution sol = rebal.getSolution();
if (!sol.isSolved()) {
System.out.println("Rebalancing was not solved.");
return;
}
Holdings finalHold = sol.getFinalHoldings();
// REPORTING
Analytics analyzer = new Analytics(prices);
System.out.println("Objective Value : " + sol.getFinalObjectiveValue());
System.out.println("Expected Return : " +
analyzer.computeExpectedReturn(finalHold, ws.getGroup("AlphaGroup")));
// Print solution
Holdings initHold = sol.getInitialHoldings();
SortedSet assets = finalHold.getAssets();
Iterator it = assets.iterator();
while (it.hasNext()) {
Asset a = (Asset) it.next();
double price = prices.getComposition(a);
double shares = finalHold.getShares(a);
double ishares = initHold.getShares(a);
System.out.println(a.getIdentity() + ": " + (shares * price) +
"\t(was: " + (ishares * price) + ")");
}
We do several things in the above code. First we retrieve the rebalancing solution by using the getSolution()
method of the Rebalancing class. We then check that the rebalancing has been solved, and if so, we proceed to retrieve the optimized holdings for each asset in the portfolio (by calling the getFinalHoldings() method of the
RebalancingSolution object). We print the objective function value of the optimized solution by invoking the
getFinalObjectiveValue() method of the RebalancingSolution class. Then we compute the expected return and print it to the screen. In order to compute the expected return, we use an instance of the Analytics class.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 86
Axioma Portfolio
Chapter 9. Inspecting the Solution
The expected return is computed using the computeExpectedReturn(Holdings holdings, Group alphas)
method of the Analytics class. This methods takes two parameters: the set of asset holdings whose expected return is to be computed and the corresponding group of alphas. For this example, the objective function will equal the
expected return.
Next, we iterate through the assets in the portfolio account and for each asset, we print its name or identity along
with its initial and final (or optimized) holdings. The assets in the account are obtained by invoking the getAssets()
method of the Holdings class. The initial holdings are retrieved from the RebalancingSolution object by using
the getInitialHoldings() method. Since the holdings are expressed as shares in the rebalancing solution, we
need to use the price group to convert from shares to currency.
Portfolio Analysis Functions
Axioma Portfolio provides a set of functions as part of the Analytics class that simplifies analysis of a solution. The
Analytics class is a utility class that provides various methods for computing a set of values that are of interest to
the user in order to analyze or understand the properties of a portfolio or a rebalancing solution. For example, this
class provides methods for computing the expected return for a set of assets, the total risk for a group of assets, the
marginal contribution to active or total risk, the transaction cost associated with the transition from an initial set of
holdings to an optimized portfolio, etc.
In this section we describe some of these functions in the context of the problem we have just solved. We use an instance of the Analytics class named analyzer. Examine the Analytics class in the Axioma Portfolio JavaDocs
[index.html] for more information about additional functions that are not described in this manual.
Expected Return
To compute the expected return of the optimized holdings, we use the computeExpectedReturn() function of
the Analytics class as in:
double er = analyzer.computeExpectedReturn(finalHold, ws.getGroup("AlphaGroup"));
The first argument of the method is the asset holdings (in this case the optimized holdings) specifying the weight of
each asset and the second argument is the alphas of all the individual assets in the asset universe (which we retrieve
from the workspace).
Implied Alphas
To compute the alphas that are "implied" by the risk model and market portfolio, m, we use the computeImpliedAlpha function. The implied alphas are those alphas that when used to maximize the unconstrained quadratic
utility function with a specified risk aversion parameter, produces the market portfolio, m. To compute the implied alphas for the assets in the portfolio, finalHold, we write:
Set impliedAlphas = analyzer.computeImpliedAlpha(rm, m, finalHold.getAssets());
The first argument of the method is the risk model, the second is a set of Holdings specifying the weights of the as-
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 87
Axioma Portfolio
Chapter 9. Inspecting the Solution
sets in the market portfolio and the third is an AssetSet specifying the assets for which to compute the implied alphas. computeImpliedAlpha returns a java.util.Set specifying the alpha weights. In this example the default
risk aversion parameter value 1.5 is used. Alternately, the risk aversion parameter (a double) can be specified as the
fourth argument of the method.
Implied Betas
To compute the implied betas for the assets in the portfolio we write:
Set impliedBetas = analyzer.computeImpliedBeta(rm, m, finalHold.getAssets());
The method takes as arguments a risk model, a Holdings object representing the market portfolio weights, and an
AssetSet specifying the assets for which the implied betas are to be calculated. It returns a java.util.Set containing the implied betas.
Risk Analysis
Axioma Portfolio incorporates many methods to compute risk characteristics of the portfolio. We present only a few
of them here. A complete listing can be found in the Axioma Portfolio JavaDocs [index.html].
We can compute the total risk of the portfolio as a standard deviations using the computeTotalRisk(RiskModel
riskmodel, Holdings holdings) method. For example,
double tr = analyzer.computeTotalRisk(rm, finalHold);
computes the total risk of the optimized holdings using risk model rm. The risk model may be either a factor risk
model or a dense risk model.
We can compute the active risk or tracking error of the optimized holdings using the computeActiveTotalRisk(RiskModel riskmodel, Holdings holdings, Group benchmark, double referenceValue)
function, as in:
double te = computeActiveTotalRisk(rm, finalHold, mybenchmark, 100000.0);
Note that rm may be either a factor risk model or a dense risk model. The benchmark could be either a Benchmark
or Group object.
The specific risk of a set of holdings or of a group or benchmark relative to a factor risk-model can be computed using the computeSpecificRisk(FactorRiskModel factorRiskModel, Holdings holdings) method of
the Analytics class. This method takes two parameters if the specific risk to be computed is for a set of holdings:
the factor risk-model and the asset holdings. For example, the specific risk for the final holdings finalHold is computed like this:
double spRisk = analyzer.computeSpecificRisk(rm, finalHolds);
The computeSpecificRisk() function takes three parameters if the specific risk to be computed is for a benchmark: the factor risk-model, the benchmark, and a reference size since the benchmark might not be normalized. For
example, the specific risk for the benchmark mybenchmark with reference size refSize is computed like this:
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 88
Axioma Portfolio
Chapter 9. Inspecting the Solution
double spRisk = analyzer.computeSpecificRisk(rm, mybenchmark, refSize);
Transactions
Several methods are available to calculate quantities related to transactions. For example the market impact and total
transaction costs for rebalanced portfolio specified by finalHold are calculated by:
double mi = analyzer.computeMarketImpact(mkImpact, initHold, finalHold);
double tc = analyzer.computeTransactionCost(tcost, initHold, finalHold);
where mkImpact and tcost are instances of the MarketImpact and TransactionCostModel classes, repectively, and represent the market impact and transaction cost models. initHold represent the initial portfolio (or unoptimized) holdings.
The turnover for the rebalancing can be computed as
double to = analyzer.computeTurnover(initHold, finalHold);
where initHold represents the initial holdings and finalHold represents the final (optimized) holdings.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 89
Axioma Portfolio
Chapter 10. Tax-Aware Optimization
Chapter 10. Tax-Aware Optimization
Overview
Axioma Portfolio supports tax-aware portfolio optimization. The U.S. tax code specifies that short term and long
term capital gains are taxed at different rates. This difference in rates can have a significant impact on the after-tax return of a portfolio. Axioma Portfolio can explicitly account for a user-specified tax objective during the rebalancing
optimization. After rebalancing, Axioma Portfolio can perform an optimal assignment of trades to tax lots according
to the tax objective. If the rebalancing strategy contains a tax objective or constraint, then the tax-lot assignment is
considered in the initial optimization process. A second step to assigning tax lots is only required if round-lotting is
performed. This section describes how the appropriate tax information is specified in Axioma Portfolio, how the
portfolio rebalancing problem is solved, and how the optimized holdings and trades are inspected.
Setting up a tax-aware optimization problem requires defining tax holding lots and tax transaction lots as well as a
number of tax parameters. We give a brief overview of these topics here. A more detailed description follows.
A tax holding lot records the purchase of a number of shares together with the date of purchase and the purchase
price per share. The number of shares can be negative indicating shares that were sold to create short holdings in the
asset. Tax holding lots are created as instances of the HoldingLot class. After a portfolio has been optimized, the
resulting trades can then be assigned to the existing tax lots (and new tax lots created as necessary).
A tax transaction lot records a past transaction in a previously held tax holding lot. Information about tax transaction
lots is maintained so that the wash sale rule can be applied if necessary. The only tax transaction lots that need to be
included in a tax optimization are lots whose transaction date is within the wash period. Tax transaction lots are created as instances of the TransactionLot class. The information stored in a tax transaction lot includes the number
of shares involved in the final transaction (negative for a sale and positive for a purchase) the date and price of the
original purchase (or sale) as well as an additional date and price for the final sale (or purchase).
Problem Specification
To specify a tax-aware portfolio optimization problem several steps are required. First, current price-per-share information is specified for all assets (this is needed to determine whether a lot represents a gain or a loss). This is accomplished by creating a price group as a SimpleGroup object and assigning it to the Workspace object. The following code snippet illustrates this:
prices = new SimpleGroup(ws, "PriceGroup", "Asset Share prices", ws.getDate(), Unit.PRICE);
prices.setComposition(ws.getAsset("DELL"), 25.0);
prices.setComposition(ws.getAsset("MSFT"), 64.0);
prices.setComposition(ws.getAsset("IBM"), 100.0);
prices.setComposition(ws.getAsset("ORCL"), 20.0);
...
ws.setDefaultPriceGroup(prices);
In the code above, we create a simple group representing the share prices as a member of the Workspace object
ws.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 90
Axioma Portfolio
Chapter 10. Tax-Aware Optimization
Second, the tax lots must be specified. In Axioma Portfolio, tax lots are called holding lots. A holding lot is defined by
(1) a date of purchase or sale and (2) a price per share (bought or sold). These must be specified for all assets currently held (long or short). Each share held (long or short) must appear in some holding lot. The holding lots are
grouped together in a java.util.Set object so that we can use it later in the constructor of our Account object.
The holding lots are created in the following way:
Collection hlots = new HashSet();
Calendar buyDate = new GregorianCalendar();
buyDate.set(2000, 0, 2);
hlots.add(new HoldingLot(ws.getAsset("DELL"), buyDate.getTime(), -400.0, 20.0));
buyDate.set(2001, 4, 13);
hlots.add(new HoldingLot(ws.getAsset("DELL"), buyDate.getTime(), -400.0, 28.0));
buyDate.set(2001, 0, 2);
hlots.add(new HoldingLot(ws.getAsset("MSFT"), buyDate.getTime(), 75.0, 90.0));
buyDate.set(2001, 6, 1);
hlots.add(new HoldingLot(ws.getAsset("MSFT"), buyDate.getTime(), 25.0, 65.0));
buyDate.set(2000, 0, 1);
hlots.add(new HoldingLot(ws.getAsset("IBM"), buyDate.getTime(), 100.0, 110.0));
...
The constructor for the HoldingLot class takes four arguments: The first argument is the asset for which the holding lot is being created; the second argument is the date of purchase or sale; the third argument is the number of
shares bought or sold in that holding lot (sales appear as negative numbers); and the fourth argument is the is the cost
basis, or the price per share at which the asset was originally bought or sold. To specify a date, we use a
java.util.Date class which calls for three arguments: the year, the month and the day of the month. The
java.util.Calendar and java.util.GregorianCalendar classes are also employed when dealing with dates.
Third, we must specify information about previous trades since these may have implications on the tax lot assignment
because of the wash sales rule. Trades that need to be included here are recent trades (within the last 30 days generally), specifically recent sales of shares owned as well as recent purchases of shares for which a short position was
held. Axioma Portfolio does not allow wash sales. In Axioma Portfolio, share trades are termed transaction lots. Two
transaction lots are specified here:
Collection tlots = new HashSet();
Calendar sellDate = new GregorianCalendar();
buyDate.set(2001, 0, 2);
sellDate.set(2001, 6, 15);
tlots.add(new TransactionLot(ws.getAsset("MSFT"), -25.0, buyDate.getTime(), 90.0,
sellDate.getTime(), 60.0));
buyDate.set(2001, 1, 6);
sellDate.set(2001, 6, 3);
tlots.add(new TransactionLot(ws.getAsset("DELL"), 45.0, buyDate.getTime(), 52.0,
sellDate.getTime(), 47.0);
The constructor for the TransactionLot class takes six arguments: The second argument specifies the number of
shares traded. Note in the above, 25 shares of MSFT are sold and 45 shares of DELL are bought. The next two argu-
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 91
Axioma Portfolio
Chapter 10. Tax-Aware Optimization
ments specify information about when these shares were originally acquired or sold short. This includes the date they
were acquired or sold short and the cost basis or price per share at that time. The last two arguments concern the
date the transaction occurred. Thus in the above transaction lot for MSFT, we are specifying that 25 shares of MSFT
were sold on 15/7/2001 (July 15, 2001) at a price of $60 per share. These shares were originally acquired on
2/1/2001 (January 2, 2001) at a price of $90 per share. In the above transaction lot for DELL, we are specifying that
45 shares of DELL were bought on 3/7/2001 (July 3, 2001) at a price of $47 per share. These shares were originally
shorted on 6/2/2001 (February 6, 2001) at a price of $52 per share. As in the case of the holding lots, the transaction
lots were grouped together in a java.util.Set object that will be used later in the constructor of the Account
object.
Now that the holding lots and transaction lots have been created, we can proceed with our taxable account creation.
The account is created as an instance of the Account class in this way:
Account account = new Account(ws, "txAccount", "TaxableAccount", ws.getDate(), hlots, tlots);
The next step is to enter the information about the tax rules. This is done in two steps: First the user must create a
TaxCode.TaxGainLossInfo object in order to specify the taxable account's long and short term gains and losses.
The TaxCode.TaxGainLossInfo object is created and added to the taxable account like this:
TaxCode.TaxGainLossInfo gainsLosses = new TaxCode.TaxGainLossInfo(50000.0, 0.0,
-25000.0, 0.0);
account.setInitialRealizedGainsLosses(gainsLosses);
The constructor of the TaxCode.TaxGainLossInfo class takes four arguments: The initial long term gains, the initial long term losses, the initial short term gains, and the initial short term losses, in that order. Any initial long and
short term gains or losses (losses are represented by negative numbers) are specified. This information is needed if
gains or losses are carried over from other accounts or transactions. In the above code, we set the long term gains to
$50,000 and the short term gains to -$25,000. The long term losses and the short term losses are both set to 0.0.
Second, the user then creates a TaxCode object and adds it to the taxable account. The TaxCode object contains
the tax rates that are applicable to the taxable account. It is created and added to the account in the following way:
TaxCode taxCode = new TaxCode(0.15, 0.50, 365, 30);
account.setTaxCode(taxCode);
In the above code we create a TaxCode object and add it to our taxable account account. The constructor of the
TaxCode takes four parameters: the long and short term capital gains tax rates; the maximum number of days an asset can be held for a short term gain; and the number of days in the wash period for the wash sale rules, in this order.
Above we use the default values for illustration purposes. If default values are sufficient, the the TaxCode object can
be constructed using the default constructor instead. Note that the tax rates are entered as decimal values, not percentages. In the U.S. the number of days that defines a "short term" is a year (or 365 days). Similarly, the number of
days that defines a "wash sale" is 30 days.
In the above, we specify a number of parameters necessary to correctly compute the tax burden on portfolio transactions. The current date for the portfolio optimization is set using the setDate() method of the Account class
(again, using the java.util.Date class).
Next we specify how tax lots will be assigned. This is done by specifying the tax lot selection method using the
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 92
Axioma Portfolio
Chapter 10. Tax-Aware Optimization
setLotSelection() method of the Account class. Axioma Portfolio offers the Account.LotSelection with
four options for lot selection:
➤ Account.LotSelection.FIFO,
➤ Account.LotSelection.HIFO,
➤ Account.LotSelection.LIFO, and
➤ Account.LotSelection.OPTIMAL.
The syntax for lot selection assignment is:
account.setLotSelection(Account.LotSelection.OPTIMAL);
If the lot selection method is specified as FIFO, then trades are assigned to tax lots in chronological order, newest
lots last. If the lot selection method is specified as HIFO, then trades are assigned to tax lots in order of highest cost
basis (price) first. For short holdings, it uses lowest price first. If the lot selection method is specified as LIFO, then
trades are assigned to tax lots in reverse chronological order, newest lots first. Finally, if the lot selection is specified
as OPTIMAL, then trades are assigned to tax lots in an optimal fashion: minimizing the resulting tax liability.
Tax Objective
To incorporate tax considerations into the objective function for the rebalancing, we must add either a TaxLiabilityTerm or a TaxGainsTerm object to the objective function. A TaxLiabilityTerm object is an objective term
that represents the total tax liability (gains minus losses) resulting from portfolio transactions, while a TaxGainsTerm
object is an objective term that represents the total tax liability due to long and short term gains resulting from portfolio transactions.
Typically, we would like to maximize the after-tax return (expected return minus total tax liabilities). In this case, we
create a strategy containing an expected return term and a tax liability term. Then we create an objective using the
strategy and the objective terms (the expected return and tax liability terms). Since we want the expected return
minus the tax liabilities, we set the coefficient for the expected return to +1.0 and the coefficient for the tax liability
term to -1.0. This is illustrated in sample code below:
Strategy strategy = new Strategy(ws, "taxStrategy", "Simple Tax Strategy", ws.getDate());
Set terms = new HashSet();
//Add an expected return component to the strategy
ExpectedReturnTerm ert = new ExpectedReturnTerm(strategy, "ExpectedReturn", null);
ert.setAlphaGroup(ws.getGroup("AlphaGroup"));
terms.add(ert);
//Add a tax liability component to the strategy
TaxLiabilityTerm tlt = new TaxLiabilityTerm(strategy, "taxLiability", null);
terms.add(tlt);
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 93
Axioma Portfolio
Chapter 10. Tax-Aware Optimization
//Create an objective using the expected return and tax liability terms
Objective taxObjective = new Objective(strategy, "SimpleObjective", null, terms);
taxObjective.setObjectiveTermWeight(ert, 1.0);
taxObjective.setObjectiveTermWeight(tlt, -1.0);
taxObjective.setTarget(Objective.Target.MAXIMIZE);
In other circumstances, we would like to minimize the portfolio risk while maximizing the total tax gains. In this case,
we create a risk term and a tax gains term instead and set their coefficients to -1.0 and +1.0, respectively. The exact
tax-liability terms will be constructed based on the tax rules, holding lots, and transaction lots already specified.
Tax Constraint
Tax-related quantities may also be limited directly through the use of the LimitTaxLiabilityConstraint, the
LimitNetTaxGainsConstraint, the LimitNetTaxLossesConstraint, the LimitGrossTaxGainsConstraint or the LimitGrossTaxLossesConstraint.
The Net Tax Gains constraint takes into account the sum of difference between long term gain and long term loss,
and difference between short term gain and short term loss. Similarly, Net Tax Loss takes into account the sum of
the difference between long term loss and long term gain, and difference between short term loss and short term
gain. The Gross Tax Gains constraint takes into account the sum of the long term and short term gains. Similarly,
Gross Tax Losses constraint takes into account the sum of the long term and short term losses.
This calculation is under the assumption that both short-term and long-term are included. The properties includelong-term and include-short-term are true by default. If either of the value is set to false, calculation of the tax constraints changes accordingly. For example, if include-short-term is false, then the Net Tax Gains constraint is equal to
difference between long term gain and long term loss.
Consider the example to limit the total long-term and short-term gains to at most 10% of the reference value
LimitNetTaxGainsConstraint txConst = LimitNetTaxGainsConstraint(strategy, "taxConstraint",
"Limit Net-Tax Gains");
ConstraintProperties cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.AGGREGATE);
cp.setProperty(ConstraintProperties.Property.MAX, 10.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.PERCENT);
cp.setProperty(ConstraintProperties.Property.INCLUDE_SHORT_TERM, false);
cp.setProperty(ConstraintProperties.Property.INCLUDE_LONG_TERM, true);
txConst.setProperties(cp);
txConst.setEnabled(true);
In general, LimitTaxLiabilityConstraint adds a linear inequality on a weighted combination of the tax liability,
long-term gains, long-term losses, short-term gains, and short-term losses. The first argument of the constructor is
the strategy that the constraint belongs to; the second argument is the constraint name or identity; and the third argument is the constraint optional description.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 94
Axioma Portfolio
Chapter 10. Tax-Aware Optimization
Optimizing
Once the tax information is specified, the next step is to optimize the portfolio and then assign the tax lots. This is
done as follows:
Rebalancing.Status status = rebal.solve();
Viewing the Solution
To view the solution, including the optimized trades by tax lot, the following should be used:
if (status == RebalancingBase.Status.SolutionFound) {
RebalancingSolution sol = rebal.getSolution();
Holdings finalHold = sol.getFinalHoldings();
Holdings initHold = sol.getInitialHoldings();
// REPORTING
Analytics analyzer = new Analytics(prices);
System.out.println("Objective Value : " + sol.getFinalObjectiveValue());
System.out.println("Expected Return : " +
analyzer.computeExpectedReturn(folio, ws.getGroup("AlphaGroup")));
// Realized gains and losses
gainsLosses = taxCode.getRealizedGainsLosses(initHold, finalHold, prices, account.getDate());
System.out.print("\nRealized long term gain: " + gainLosses.getTaxLongTermGains());
System.out.print("Realized long term loss: " + gainLosses.getTaxLongTermLosses());
System.out.print("Realized short term gain: " + gainLosses.getTaxShortTermGains());
System.out.print("Realized short term loss: " + gainLosses.getTaxShortTermLosses());
// Unrealized gains and losses
gainsLosses = taxCode.getUnrealizedGainsLosses(account, prices, account.getDate());
System.out.print("\nUnealized long term gain: " + gainLosses.getTaxLongTermGains());
System.out.print("Unrealized long term loss: " + gainLosses.getTaxLongTermLosses());
System.out.print("Unrealized short term gain: " + gainLosses.getTaxShortTermGains());
System.out.print("Unrealized short term loss: " + gainLosses.getTaxShortTermLosses());
// Print solution
SortedSet assets = finalHold.getAssets();
Iterator it = assets.iterator();
while (it.hasNext()) {
Asset asset = (Asset) it.next();
String id = asset.getIdentity();
double shares = finalHold.getShares(asset);
double ishares = initHold.getShares(asset);
System.out.println(id + ": " + shares + "\t(was: " + ishares + ")\n");
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 95
Axioma Portfolio
Chapter 10. Tax-Aware Optimization
// Holding Lots
java.util.Collection hlots = getHoldingLots(asset);
Iterator hlIter = hlots.iterator();
while (hlIter.hasNext()) {
HoldingLot holdLot = hlIter.next();
Date date = holdLot.getBuyDate();
System.out.println(" Date: " + date.getDay() + "-" +
date.getMonth() + "-" +
date.getYear());
System.out.println(" Price: " + holdLot.getPrice());
System.out.println(" Shares: " + holdLot.getShares());
System.out.println(" (was: " + ishares);
}
// Transaction Lots
java.util.Collection tlots = getTransactionLots(asset);
Iterator tlIter = tlots.iterator();
while (tlIter.hasNext()) {
TransactionLot transLot = tlIter.next();
Date date = transLot.getBuyDate();
Date nDate = transLot.getSellDate();
System.out.println(" Date: " + date.getDay() + "-" +
date.getMonth() + "-" +
date.getYear());
System.out.println(" Price: " + transLot.getBuyPrice());
System.out.println(" New date: " + nDate.getDay() + "-" +
ndate.getMonth() + "-" +
ndate.getYear());
System.out.println(" New Price: " + transLot.getSellPrice());
System.out.println(" Transaction Shares: " + transLot.getShares());
}
}
}
}
In the above code, we do several things. First we print some basic problem information (optimized net gains, short
and long term). We then loop through the assets and print the optimized and initial shares. Next we loop through the
tax holding lots and print out the optimized and initial shares. Finally, we do the same with the tax transaction lots.
The TaxExample.java example in the examples folder in the product distribution gives an example of the use of
taxes.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 96
Axioma Portfolio
Chapter 11. Multi-Portfolio Optimization
Chapter 11. Multi-Portfolio Optimization
Overview
The Axioma Portfolio multiple account optimization allows for the simultaneous rebalancing of multiple accounts in a
single rebalancing. This functionality takes the rebalancing of the multiple accounts and aggregates them into one rebalancing while additionally considering any objectives or constraints across multiple accounts. Multiple-account optimization should be used whenever there is any interaction in objectives or constraints across multiple accounts. For
example, when rebalancing several large accounts simultaneously, the market-impact on the aggregate trades of all
accounts should be considered in order to avoid significant underestimation of the actual market-impact effect. If
multiple accounts are to share the allocation of a holding or trade that is restricted by average daily volume, for example, then the problem should be modeled as multi-account problem in order to correctly reflect the constraint as
opposed to allocating the trades pro rata. The multiple-account optimization engine can also be used to manage multiple accounts belonging to a single taxpayer as is the case in overlay portfolio management. This is a common practice in private wealth management. Here, the netting of gains and losses, prevention of wash sales, etc. across multiple accounts can be correctly considered from a tax perspective. This chapter highlights how you can model the
multi-portfolio optimization using our API.
Multiple Account
As in the single account optimization, the multiple account optimization contains the same data elements. But user
could aggregate multiple accounts using the AccountGroup object. Just like ComplianceAccount, the user could
also create ComplianceAccountGroup object so that compliances could be specified at the AccountGroup level.
The following code snippet illustrates how to create AccountGroup and add accounts to it.
Collection holdings = new HashSet();
holdings.add(new AssetValue(ws.getAsset("DELL"), 20000.0));
holdings.add(new AssetValue(ws.getAsset("MSFT"), 8000.0));
holdings.add(new AssetValue(ws.getAsset("IBM"), 32000.0));
holdings.add(new AssetValue(ws.getAsset("ORCL"), 40000.0));
account1 = new Account(ws, "Account1", null, workspaceDate, holdings);
holdings.clear();
holdings.add(new AssetValue(ws.getAsset("IBM"), 3000.0));
holdings.add(new AssetValue(ws.getAsset("ORCL"), 13000.0));
account2 = new Account(ws, "Account2", null, workspaceDate, holdings);
holdings.clear();
holdings.add(new AssetValue(ws.getAsset("MSFT"), 3000.0));
holdings.add(new AssetValue(ws.getAsset("ORCL"), 7000.0));
account3 = new Account(ws, "Account3", null, workspaceDate, holdings);
accountGroup1 = new AccountGroup(ws, "AccountGroup1", null, workspaceDate);
accountGroup1.addAccount(account1);
accountGroup1.addAccount(account2);
accountGroup1.addAccount(account3);
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 97
Axioma Portfolio
Chapter 11. Multi-Portfolio Optimization
Multiple Account Strategy
Creating a multiple account strategy is similar to a single account strategy except for the use of the qualification property in the objectives and constraints. Additionally, all objective terms or constraints applied to specific accounts must
be explicitly stated. The following is an example of the use of a multi-portfolio constraint and objective. Here the
qualification represents the name of the Account or AccountGroup object on whose assets the constraints or objective terms are placed.
ExpectedReturnTerm ero = new ExpectedReturnTerm(strategy, "ExpectedReturn", null);
ero.setAlphaGroup(ws.getGroup("AlphaGroup"));
ero.setQualification(ws.getAccount("Account1"));
Objective simpleObjective = new Objective(strategy, "SimpleObjective", null);
simpleObjective.addObjectiveTerm(ero, 1.0);
simpleObjective.setTarget(Objective.Target.MAXIMIZE);
LimitTotalRiskConstraint arc =
new LimitTotalRiskConstraint(strategy, "ActiveRiskConstraint", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.SELECTION);
cp.setProperty(ConstraintProperties.Property.MAX, 10.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.PERCENT);
cp.setProperty(ConstraintProperties.Property.BENCHMARK, ws.getGroup("SimpleBenchmark"));
cp.setProperty(ConstraintProperties.Property.RISKMODEL, ws.getRiskModel("SmallRiskModel"));
arc.setProperties(cp);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.QUALIFICATION, account1.getIdentity());
arc.addAssetSetSelection(ws.getLocalUniverseSet(), cp);
arc.setEnabled(true);
Multiple Account Rebalancing
The user can create a MultiRebalancing object and can add Account or AccountGroup object to it. Each account or account group to be used as a qualification must be listed as well. So, even if all accounts are listed, an AccountGroup containing a subset of the accounts must be listed as well if its compliance is to be considered or if the
AccountGroup is to be used as a qualification in the strategy. Below is a code snippet of how a MultiRebalancing
is created.
MultiRebalancing rebal = new MultiRebalancing(ws, "MultiRebalancing", null, workspaceDate);
rebal.addAccount(account1);
rebal.addAccount(account2);
rebal.addAccount(account3);
rebal.addAccountGroup(accountGroup1);
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 98
Axioma Portfolio
Chapter 11. Multi-Portfolio Optimization
rebal.setStrategy(strategy);
rebal.setBudgetSize(100000.0);
rebal.setReferenceSize(100000.0);
In a constraint that uses PERCENT as the unit, if the scope is AGGREGATE, the reference size of the rebalancing is
used to determine the min and/or max value of the constraint even if an account qualification is specified. But for other scopes, if qualification is present, the reference size of the qualification is used to determine the min and/or max
value of the constraint.
Multiple Account Rebalancing Solution
When MultiRebalancing is ran, it generates MultiRebalancingSolution. The user can use this class to get
the total final holdings and final holdings of individual qualifications. Below is a code snippet which prints final objective value, expected return, total holdings and individual holdings of the Account and AccountGroup.
MultiRebalancingSolution sol = rebal.getSolution();
if (!sol.isSolved()) {
System.out.println("Rebalancing was not solved.");
return;
}
Holdings folio = sol.getFinalHoldings();
// REPORTING
Analytics analyzer = new Analytics(prices);
System.out.println("Objective Value : " + sol.getFinalObjectiveValue());
System.out.println("Expected Return : "
+ analyzer.computeExpectedReturn(folio, ws.getGroup("AlphaGroup")));
// Print solution
System.out.println("---- Multi Rebalancing Solution ----");
System.out.println("---- All Holdings ----");
printHoldings(sol.getInitialHoldings(), sol.getFinalHoldings());
Iterator accit = rebal.getAccounts().iterator();
while(accit.hasNext()) {
Account acc = (Account) accit.next();
System.out.println("---- Holdings of "+acc.getIdentity()+" ----");
printHoldings(acc, sol.getFinalHoldings(acc));
}
Iterator accgit = rebal.getAccountGroups().iterator();
while(accgit.hasNext()) {
AccountGroup accGrp = (AccountGroup) accgit.next();
System.out.println("---- Holdings of "+accGrp.getIdentity()+" ----");
printHoldings(accGrp, sol.getFinalHoldings(accGrp));
}
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 99
Axioma Portfolio
Chapter 12. Automation Utilities
Chapter 12. Automation Utilities
Axioma Portfolio contains several utilities that allow more advanced, but commonly requested, functionality to be
used easily. In this chapter, we will discuss one such utility: efficient frontiers. The Frontier class optimizes a sequence of problems over a specified range of problem parameters. In the section called “Creating Frontiers”, we will
demonstrate how this can be used to analyze the tradeoffs of any optimization parameters. This analysis is not limited
to tradeoffs between risk and return.
Creating Frontiers
The Frontier class allows the users of Axioma Portfolio to quickly and easily calculate efficient frontiers. An efficient
frontier is computed by solving a sequence of portfolio optimization problems where one or more elements of the
problem are varied in a systematic manner. A classic example of an efficient frontier results from varying the risk
aversion parameter to observe the tradeoff between risk and return in a portfolio.
The example given in FrontierExample.java shows exactly how to create such a frontier. We will now describe
the major steps of this example. Assume that we have already setup a Workspace, ws, and that it contains a
FactorRiskModel, an Account, a price and alpha Groups. Furthermore, assume that a Strategy, strategy, has
been constructed and that it contains a BudgetConstraint to require full investment, and a Objective that consists of an ExpectedReturnTerm and a RiskTerm. The RiskTerm is included in the rebalancing objective because
we want to maximize the portfolio expected return while minimizing the total risk and to determine how the net objective varies as the risk-aversion coefficient of the risk objective term changes. The ExpectedReturnTerm, the
RiskTerm and the Objective are created and added to the strategy in the following way:
// Construct the Expected Return term
ExpectedReturnTerm ero = new ExpectedReturnTerm(strategy, "ExpectedReturn", null);
ero.setAlphaGroup(ws.getGroup("AlphaGroup"));
// Construct the Risk term
RiskTerm riskTerm = new RiskTerm(strategy, "RiskTerm", null);
riskTerm.setRiskModel(ws.getRiskModel("SmallRiskModel"));
riskTerm.setGroup(ws.getLocalUniverseSet());
// Build the objective function
Objective simpleObjective = new Objective(strategy, "SimpleObjective", null);
simpleObjective.addObjectiveTerm(ero, 1.0);
simpleObjective.addObjectiveTerm(riskTerm, -0.1);
simpleObjective.setTarget(Objective.Target.MAXIMIZE);
The next step is to instantiate a Frontier class with the object to vary and the ranges over which the object is to be
varied. In our case, we will change the risk-aversion parameter of the risk term object from -2.0 to 0 in 20 steps. The
object for which a parameter will vary in a Frontier is specified using either the setFrontierConstraint(Constraint con) method or the setFrontierObjectiveTerm(ObjectiveTerm ot) method of
the Frontier class depending on whether we are changing a parameter of a constraint or of an objective term. By
default, weight is used as the objective term property. The frontier supported objective term properties depends on
the selected ObjectiveTerm. The start and end values for the parameter that will be varied and the number of data
points to consider are specified using the setStartValue(double startValue), setEndValue(double endValue) and setNumberOfPoints(int numPoints) methods of the Frontier class, respectively. The following
lines of codes demonstrate how this is done:
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 100
Axioma Portfolio
Chapter 12. Automation Utilities
Frontier frontier = new Frontier(ws, account, "RiskFrontier", null, ws.getDate());
ws.setDefaultPriceGroup(prices);
frontier.setStrategy(strategy);
frontier.setFrontierObjectiveTerm(riskTerm);
frontier.setFrontierObjectiveTermProperty(ObjectiveTerm.FACTOR_WEIGHT);
frontier.setStartValue(-2.0);
frontier.setEndValue(0.0);
frontier.setNumberOfPoints(20);
Observe that, just as in the case of a Rebalancing, a Frontier requires a strategy (set of constraints and objectives) to be specified.
The efficient portfolios are created and retrieved by calling the solve() and getSolutions() methods of the
Frontier class. The getSolutions() method returns a list of FrontierSolution objects. Each frontier solution
object can be queried to determine if a solution was found and to retrieve the parameter value and its corresponding
objective or constraint value. The following codes illustrate how the list of efficient frontier results are retrieved and
how to iterate through the list in order to print out the risk-aversion parameter and the rebalancing objective value:
// Generate Frontier
frontier.solve();
DecimalFormat df1 = new DecimalFormat("0.0000000000");
DecimalFormat df2 = new DecimalFormat("#########.000");
List solutions = frontier.getSolutions();
System.out.println("Risk Aversion\tObjective Value");
System.out.println("-------------\t---------------");
Iterator it = solutions.iterator();
while (it.hasNext()) {
FrontierSolution fs = (FrontierSolution) it.next();
if (fs.isSolved()) {
String value2 = "
" + df2.format(fs.getFinalObjectiveValue());
System.out.println(df1.format(fs.getValue()) + "\t" +
value2.substring(value2.length()-15));
} else {
System.out.println(df1.format(fs.getValue()) + "\t" + "Solution not found.");
}
};
Note that we used the isSolved() method of the returned FrontierSolution objects to determine if a solution
was obtained for a particular value of the risk-aversion coefficient. If no solution was obtained, we print the riskaversion coefficient and a message indicating that no solution was found.
Batch Jobs
The RebalancingBatchJob class is used to create a batch job object that can solve multiple Rebalancings or a
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 101
Axioma Portfolio
Chapter 12. Automation Utilities
Frontier in batch form. There is also support to create a predefined set of reports for a rebalancing that is being
executed in the batch job.
The first step to create a Batch Job is to construct a new RebalancingBatchJob object and add job items using the
addJobItem(JobItem) method. Currently there are two job items supported by a rebalancing batch job: Rebalancing and Frontier. Below is an example:
BatchJob exampleBatchJob = new RebalancingBatchJob(ws, "Batch1", "Batch Job", new Date());
exampleBatchJob.addJobItem(RebalancingObject);
The next step is to add reports and their properties if desired
ReportContext rc = new ReportContext();
exampleBatchJob.addBatchJobContext(rc);
exampleBatchJob.setReportDir("C:\\Reports");
exampleBatchJob.setPrependTimeStampInReportFileName(true);
The last step is to execute the batch job.
exampleBatchJob.execute();
Alternatively, a Set of Rebalancings can also be passed to the constructor.
RebalancingBatchJob job1 = new RebalancingBatchJob(SetofRebals, ws, "Batch1", "Batch Job", new Date());
job1.execute();
The AccountBatchJob class is used to create a batch job object that can report on multiple Accounts in batch
form. The account batch job only creates reports.
The first step to create a Batch Job is to construct a new AccountBatchJob object and add job items using the addJobItem(Account) method. Below is an example:
BatchJob exampleBatchJob = new AccountBatchJob(ws, "Batch1", "Batch Job", new Date());
exampleBatchJob.addJobItem(AccountObject);
The next step is to add reports and their properties if desired
AccountReportContext rc = new AccountReportContext();
exampleBatchJob.addBatchJobContext(rc);
exampleBatchJob.setReportDir("C:\\Reports");
exampleBatchJob.setPrependTimeStampInReportFileName(true);
The last step is to execute the batch job.
exampleBatchJob.execute();
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 102
Axioma Portfolio
Chapter 12. Automation Utilities
Alternatively, a Set of Rebalancings can also be passed to the constructor.
RebalancingBatchJob job1 = new RebalancingBatchJob(SetofRebals, ws, "Batch1", "Batch Job", new Date());
job1.execute();
The BatchJobContext class is a useful interface that can allow hooks into the pre-process, post-process, executionDone and executionCancelled phases of a batch job. A good example of a BatchJobContext are ReportContext and AccountReportContext. In order to create a context, you must implement the BatchJobContext. Below
is an example:
...
public class MyContext implements BatchJobContext {
...
public void preProcess(final BatchJob batchjob, final JobItem jobItem){
// Pre processing task
}
public void postProcess(final BatchJob batchjob, final JobItem jobItem, final BatchResult batchResult) {
// Post Process task
}
public void executionDone(final BatchJob batchjob) {
// Execution Done task
}
public void executionCancelled() {
// Execution Cancelled task
}
}
...
The last step is to add an instance of the context to the batchjob
exampleBatchJob.addBatchJobContext(myContext);
Reports
The ReportManager class is a useful utility used by batching to produce pre-defined reports on a Account or Rebalancing. The following reports can be created for a Rebalancing provided the relevant data for that report is
available (example: Composites for a composite report), otherwise that report is not created: Initial vs. Final Summary, Initial Risk Decomposition, Initial Portfolio Asset Details Long/Short, Initial Portfolio Asset Details Account, Initial Portfolio Asset Details Account + Benchmark, Initial Portfolio Asset Details Account + Benchmark + Composite, Final Risk Decomposition, Final Portfolio Asset Details Long/Short, Final Portfolio Asset Details Account, Final
Portfolio Asset Details Account + Composite, Final Portfolio Asset Details Account + Benchmark, Final Portfolio
Asset Details Account + Benchmark + Composite, and a Trades Report. The following reports can be created for a
Account provided the relevant data for that report is available (example: Benchmark for a benchmark report), otherwise that report is not created: Account Summary, Account Risk Decomposition, Account Asset Details, Account
Asset Details Long/Short, Account Asset Details Account + Composite, Account Asset Details Account + Bench-
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 103
Axioma Portfolio
Chapter 12. Automation Utilities
mark, Account Asset Details Account + Benchmark + Composite. An aggregate trades list report can also be created on a set of solved Rebalancings to concatenate the individual trade reports into one report. Currently, there
is no support to choose which reports get created by the report manager. Below is an example on using the ReportManager:
...
//Retrieve Account
Account myAccount ...;
//Retrieve Solved Rebalancings
Rebalancing myRebalancing ...;
Rebalancing myOtherRebalancing ...;
...
ReportManager rm = new ReportManager();
// Create Rebalancing Reports
// Optional fields to override defaults
// beta, initialReferenceSzie, initialBenchmarkSize
// riskAversion, alphaFactor, probabilityLevel
rm.createRebalancingReports("MyRebalancingReportTest", myRebalancing,
"C:\\Reports", null, null, null, null, null, null);
// Create Account Reports
// Optional fields to override defaults
// beta, initialReferenceSzie, initialBenchmarkSize
// riskAversion, alphaFactor, probabilityLevel
rm.createAccountReports("MyAccountReportTest", accn1,
"C:\\Reports", null, null, null, null, null, null);
An aggregate trades list can also be created on a set of solved Rebalancings.
...
// Add Rebalancings to a Set
LinkedHashSet<Rebalancing> rebals = new LinkedHashSet<Rebalancing>(2);
rebals.add(myRebalancing);
rebals.add(myOtherRebalancing);
rm.createAggregatedTradesReport("AggregateTest", rebals, "C:\\Reports");
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 104
Axioma Portfolio
Chapter 13. Error Handling
Chapter 13. Error Handling
Axioma Portfolio uses a combination of error codes and exceptions to report unexpected events or errors occurring
during interaction with the API.
Return Codes
Some functions, such as Rebalancing.solve(), will return a status code indicating the result of the invocation:
//--- Optimize ---//
RebalancingBase.Status status = rebal.solve();
The variable status will hold the status of the solution process, which should be checked to ensure that the optimization terminated as expected:
if (status == RebalancingBase.Status.NoSolutionFound) {
System.out.println("No solution found.");
}
if (status == RebalancingBase.Status.InternalError) {
System.out.println("Internal error.");
}
if (status == RebalancingBase.Status.SolutionFound) {
... do something with the solution ...
}
See RebalancingBase.Status in the Axioma Portfolio JavaDocs [index.html] for details.
It is highly recommended that you retrieve and check the return codes in your application to make sure that you detect any unexpected behavior. See the examples in the examples folder in the distribution. If you fail to catch errors
and detect the current state of Axioma Portfolio, you may get incorrect results or unexpected information. For example, the RebalancingSolution class will return invalid Holdings when its getFinalHoldings() method is
invoked if a rebalancing could not be successfully optimized.
Exceptions
In some cases, exceptions are used in Axioma Portfolio to signal that something out of the ordinary occurred. For example, when Axioma Portfolio detects an error in the way the API is used, an exception will be thrown. The following example will make this clear:
Rebalancing rebal = new Rebalancing(ws, account, "Rebalancing", null, ws.getDate());
rebal.setStrategy(strategy);
rebal.setBudgetSize(100000.0);
rebal.setReferenceSize(100000.0);
try {
rebal.sanityCheck();
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 105
Axioma Portfolio
Chapter 13. Error Handling
} catch (SanityCheckException except) {
System.out.println("An exception occurred.");
System.out.println("Description: " + except.getMessage());
}
This code will result in an exception being thrown. The reason is that a Rebalancing object must have, in addition
to a valid account and a valid strategy, a valid price group. The program will exit with the following message being
printed:
An exception occurred.
Description: missing prices
We recommend that you consistently catch and handle exceptions from Axioma Portfolio in your application code.
log4j2 Settings
You can customize the logging settings using the configurable log4j2.properties file. This change will allow for API
users to change the log4j level. The levels are ALL, DEBUG, INFO, WARN, ERROR, FATAL, and OFF. The default
setting is WARN. The file is located under the "bin" sub-directory of the Axioma Portfolio Java API distribution.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 106
Axioma Portfolio
Chapter 14. Troubleshooting
Chapter 14. Troubleshooting
Axioma Portfolio is a sophisticated decision support tool which has been extensively tested. However, there are always things that can go wrong if it is used improperly. Send any reports of unusual behavior to your Axioma representative. If it is necessary to send your problem data, Axioma Portfolio provides a simple way to do this.
The following statements, placed just before the optimization call (solve()) but after the model is built, will facilitate this:
try {
OutputStream ofile = new FileOutputStream("problem.xml");
WorkspaceWriter wsWriter = new WorkspaceWriter();
wsWriter.write(ws, ofile);
} catch (IOException ex) {
System.out.println("Unable to open file for XML output: " + ex.getMessage());
}
The piece of code does the following: First a file is created; in this example we call it "problem.xml," but any name
can be used there. We then create an instance of the WorkspaceWriter class in order to output the Workspace ws
to the output file in Axioma's proprietary Axioma Portfolio XML format. Finally, we catch any exception that might
have been thrown if the file could not have been created.
The WorkspaceWriter class can be used to print to an OutputStream object an XML representation of various Axioma Portfolio objects. For example, its overloaded write() method can be used to print out to an OutputStream
an XML representation of the following Axioma Portfolio objects: an AssetSet, a Group, a Metagroup, a Riskmodel, a TransactionCost, or a Workspace. An account XML representation can be printed out using the writeAccount() method, while a strategy can be printed out using the writeStrategy() method.
Tips
1.
Remember that the benchmark should be scaled to have total size equal to the portfolio's reference size.
See the section called “Benchmarks” for details on how to do this.
2.
In order to be able to use the Relative keyword in constraints, it is necessary to define a strictly positive
reference size for the portfolio.
3.
Note that Axioma Portfolio does not automatically create an asset representing cash. If a cash asset is
needed in the model, then the user must create the cash asset.
4.
Windows users with old versions of Axioma Portfolio on their machine need to rename old versions of the
file lsapiw32.dll (this file should be in an old bin directory) to, for example, lsapiw32.old. This will
prevent the old license file from interfering with the new one.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 107
Axioma Portfolio
Appendix A. Example 1: Basic use of API
Appendix A. Example 1: Basic use of API
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import org.apache.log4j.Level;
import com.axiomainc.portfolioprecision.Account;
import com.axiomainc.portfolioprecision.Analytics;
import com.axiomainc.portfolioprecision.Asset;
import com.axiomainc.portfolioprecision.AssetSet;
import com.axiomainc.portfolioprecision.AssetValue;
import com.axiomainc.portfolioprecision.AxiomaPortfolioAPI;
import com.axiomainc.portfolioprecision.FactorRiskModel;
import com.axiomainc.portfolioprecision.Holdings;
import com.axiomainc.portfolioprecision.RiskfactorGroup;
import com.axiomainc.portfolioprecision.SimpleAsset;
import com.axiomainc.portfolioprecision.SimpleGroup;
import com.axiomainc.portfolioprecision.Unit;
import com.axiomainc.portfolioprecision.Workspace;
import com.axiomainc.portfolioprecision.optimization.Constraint;
import com.axiomainc.portfolioprecision.optimization.LocalUniverse;
import com.axiomainc.portfolioprecision.optimization.Objective;
import com.axiomainc.portfolioprecision.optimization.Rebalancing;
import com.axiomainc.portfolioprecision.optimization.RebalancingSolution;
import com.axiomainc.portfolioprecision.optimization.Strategy;
import com.axiomainc.portfolioprecision.optimization.constraints.BudgetConstraint;
import com.axiomainc.portfolioprecision.optimization.constraints.ConstraintProperties;
import com.axiomainc.portfolioprecision.optimization.constraints.LimitTotalRiskConstraint;
import com.axiomainc.portfolioprecision.optimization.objectives.ExpectedReturnTerm;
public class SimpleAPIExample {
private Workspace ws;
private SimpleGroup prices;
private Account account;
private Strategy strategy;
private Rebalancing rebal;
private final Date workspaceDate = new Date();
private FactorRiskModel frm_;
private FactorRiskModel shiftedFrm_;
public static void main(String[] args) {
org.apache.log4j.BasicConfigurator.configure();
org.apache.log4j.Logger.getRootLogger().setLevel(Level.OFF);
AxiomaPortfolioAPI.setUp();
SimpleAPIExample ex = new SimpleAPIExample();
ex.ws = new Workspace("SimpleAPIExample", "Simple example
using PortfolioPrecision API", ex.workspaceDate);
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 108
Axioma Portfolio
Appendix A. Example 1: Basic use of API
ex.createMaster();
ex.createFactorRiskModels();
ex.createAlphas();
ex.createPrices();
ex.createAccount();
ex.createShiftedFactorRiskModel();
ex.createBenchmark();
ex.createStrategy();
ex.createRebalancing();
// Optimize
Rebalancing.Status status = ex.rebal.solve();
System.out.println(status);
ex.printSolution();
ex.ws.destroy();
AxiomaPortfolioAPI.tearDown();
}
private void createMaster() {
new SimpleAsset(ws, "DELL", "Dell");
new SimpleAsset(ws, "MSFT", "Microsoft");
new SimpleAsset(ws, "IBM", "IBM");
new SimpleAsset(ws, "ORCL", "Oracle");
new SimpleAsset(ws, "SAP", "SAP");
}
private void createFactorRiskModels() {
// Set specific risks
Set<AssetValue> specificRisks = new HashSet<>();
specificRisks.add(new AssetValue(ws.getAsset("DELL"), 0.42));
specificRisks.add(new AssetValue(ws.getAsset("MSFT"), 0.23));
specificRisks.add(new AssetValue(ws.getAsset("IBM"), 0.2));
specificRisks.add(new AssetValue(ws.getAsset("ORCL"), 0.13));
specificRisks.add(new AssetValue(ws.getAsset("SAP"), 0.14));
// Set factors and factor exposures
String[] factors = { "Market", "Airlines", "Pharmaceuticals" };
String[] factorTypes = { "Market", "Industry", "Industry" };
Set<AssetValue> factor1 = new HashSet<>();
factor1.add(new AssetValue(ws.getAsset("DELL"), 1.0));
factor1.add(new AssetValue(ws.getAsset("MSFT"), 0.8));
factor1.add(new AssetValue(ws.getAsset("IBM"), 0.1));
factor1.add(new AssetValue(ws.getAsset("ORCL"), 0.0));
factor1.add(new AssetValue(ws.getAsset("SAP"), 0.76));
Set<AssetValue> factor2 = new HashSet<>();
factor2.add(new AssetValue(ws.getAsset("DELL"), 0.0));
factor2.add(new AssetValue(ws.getAsset("MSFT"), 0.2));
factor2.add(new AssetValue(ws.getAsset("IBM"), 0.9));
factor2.add(new AssetValue(ws.getAsset("ORCL"), 1.0));
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 109
Axioma Portfolio
Appendix A. Example 1: Basic use of API
factor2.add(new AssetValue(ws.getAsset("SAP"), 0.98));
Set<AssetValue> factor3 = new HashSet<>();
factor3.add(new AssetValue(ws.getAsset("DELL"), 0.0));
factor3.add(new AssetValue(ws.getAsset("MSFT"), 0.1));
factor3.add(new AssetValue(ws.getAsset("IBM"), 0.1));
factor3.add(new AssetValue(ws.getAsset("ORCL"), 0.0));
factor3.add(new AssetValue(ws.getAsset("SAP"), 0.06));
@SuppressWarnings("unchecked")
Set<AssetValue>[] factorExposures = new Set[] { factor1, factor2, factor3 };
// Set factor covariances
double[][] covariances = new double[][]
{
{ 0.0024, -0.00011, 0.001 },
{ -0.00011, 0.00099, 0.02 },
{ 0.001, 0.02, 1 }
};
frm_ = new FactorRiskModel(ws, "SmallRiskModel", null,
workspaceDate, specificRisks, factors, factorExposures,
covariances, null, factorTypes);
frm_.setSpecificCovariance(ws.getAsset("DELL"),
ws.getAsset("IBM"), 0.42 * 0.2 * 0.5);
frm_.setSpecificCovariance(ws.getAsset("MSFT"),
ws.getAsset("ORCL"), 0.23 * 0.13 * -0.5);
}
private void createAccount() {
Collection<AssetValue> holdings = new HashSet<>();
holdings.add(new AssetValue(ws.getAsset("DELL"), 20000.0));
holdings.add(new AssetValue(ws.getAsset("MSFT"), 8000.0));
holdings.add(new AssetValue(ws.getAsset("IBM"), 32000.0));
holdings.add(new AssetValue(ws.getAsset("ORCL"), 40000.0));
account = new Account(ws, "SimpleAccount", null, workspaceDate, holdings);
}
private void createAlphas() {
SimpleGroup alphas = new SimpleGroup(ws, "AlphaGroup", null,
workspaceDate, Unit.NUMBER);
alphas.setComposition(ws.getAsset("DELL"), -0.0564929);
alphas.setComposition(ws.getAsset("MSFT"), 0.0399615);
alphas.setComposition(ws.getAsset("IBM"), 0.177567);
alphas.setComposition(ws.getAsset("ORCL"), 0.0227682);
alphas.setComposition(ws.getAsset("SAP"), -0.167367);
}
private void createPrices() {
prices = new SimpleGroup(ws, "PriceGroup", null, workspaceDate,
Unit.PRICE);
prices.setComposition(ws.getAsset("DELL"), 1.0);
prices.setComposition(ws.getAsset("MSFT"), 1.0);
prices.setComposition(ws.getAsset("IBM"), 1.0);
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 110
Axioma Portfolio
Appendix A. Example 1: Basic use of API
prices.setComposition(ws.getAsset("ORCL"), 1.0);
prices.setComposition(ws.getAsset("SAP"), 1.0);
ws.setDefaultPriceGroup(prices);
}
private void createShiftedFactorRiskModel() {
List<RiskfactorGroup> targetFactors = new ArrayList<>();
targetFactors.add(frm_.getRiskfactorGroup("Airlines"));
targetFactors.add(frm_.getRiskfactorGroup("Pharmaceuticals"));
// This method shifts the risk from market factor to target industry factors
shiftedFrm_ = frm_.shiftFactorRisk(frm_.getRiskfactorGroup("Market"), targetFactors);
Analytics analytics = new Analytics(prices);
// Total risk of the shifted risk model and original risk model are same.
//Only the risk is shifted from market factor to industry factors.
System.out.println("Total risk of factor risk model: " +
analytics.computeTotalRisk(frm_, account));
System.out.println("Total risk of shifted factor risk model: " +
analytics.computeTotalRisk(shiftedFrm_, account));
System.out.println();
}
private void createBenchmark() {
SimpleGroup bm = new SimpleGroup(ws, "SimpleBenchmark", null,
workspaceDate, Unit.CURRENCY);
bm.setComposition(ws.getAsset("DELL"), 30000.0);
bm.setComposition(ws.getAsset("MSFT"), 12000.0);
bm.setComposition(ws.getAsset("IBM"), 23000.0);
bm.setComposition(ws.getAsset("ORCL"), 35000.0);
}
private void createStrategy() {
strategy = new Strategy(ws, "SimpleStrategy", null, workspaceDate);
strategy.setAllowShorting(true);
LocalUniverse lu = strategy.getLocalUniverse();
lu.includeAsset(ws.getAsset("DELL"));
lu.includeAsset(ws.getAsset("MSFT"));
lu.includeAsset(ws.getAsset("IBM"));
lu.includeAsset(ws.getAsset("ORCL"));
// Require full investment
BudgetConstraint bc = new BudgetConstraint(strategy, "BudgetConstraint", null);
ConstraintProperties cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.USE_BUDGET_VALUE, true);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.CURRENCY);
bc.setProperties(cp);
bc.setEnabled(true);
//Define active risk, restricting the risk of the problem
//to be at most 10% of the portfolio size (i.e., $10,000)
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 111
Axioma Portfolio
Appendix A. Example 1: Basic use of API
LimitTotalRiskConstraint arc = new LimitTotalRiskConstraint(strategy,
"ActiveRiskConstraint", null);
cp = new ConstraintProperties();
cp.setProperty(ConstraintProperties.Property.SCOPE, Constraint.Scope.AGGREGATE);
cp.setProperty(ConstraintProperties.Property.MAX, 10.0);
cp.setProperty(ConstraintProperties.Property.UNIT, Unit.PERCENT);
cp.setProperty(ConstraintProperties.Property.BENCHMARK, ws.getGroup("SimpleBenchmark"));
cp.setProperty(ConstraintProperties.Property.RISKMODEL, ws.getRiskModel("SmallRiskModel"));
arc.setProperties(cp);
//arc.addLocalUniverseSelection(ConstraintProperties.EMPTY_PROPERTIES);
AssetSet as = new AssetSet(ws, "MyLocalUniverse", null, workspaceDate);
as.includeAssetSet(ws.getMasterSet());
as.excludeAsset(ws.getAsset("SAP"));
arc.addAssetSetSelection(as, ConstraintProperties.EMPTY_PROPERTIES);
arc.setEnabled(true);
// Put an expected return component into the objective function
ExpectedReturnTerm ero = new ExpectedReturnTerm(strategy, "ExpectedReturn", null);
ero.setAlphaGroup(ws.getGroup("AlphaGroup"));
Objective simpleObjective = new Objective(strategy, "SimpleObjective", null);
simpleObjective.addObjectiveTerm(ero, 1.0);
simpleObjective.setTarget(Objective.Target.MAXIMIZE);
}
private void createRebalancing() {
rebal = new Rebalancing(ws, account, "SimpleRebalancing", null, workspaceDate);
rebal.setStrategy(strategy);
rebal.setBudgetSize(100000.0);
rebal.setReferenceSize(100000.0);
}
private void printSolution() {
RebalancingSolution sol = rebal.getSolution();
if (!sol.isSolved()) {
System.out.println("Rebalancing was not solved.");
return;
}
Holdings folio = sol.getFinalHoldings();
// REPORTING
Analytics analyzer = new Analytics(prices);
System.out.println("Objective Value: " + sol.getFinalObjectiveValue());
System.out.println("Expected Return: " +
analyzer.computeExpectedReturn(folio, ws.getGroup("AlphaGroup")));
// Print solution
Holdings ifolio = sol.getInitialHoldings();
SortedSet<Asset> assets = folio.getAssets();
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 112
Axioma Portfolio
Appendix A. Example 1: Basic use of API
Iterator<Asset> it = assets.iterator();
while (it.hasNext()) {
Asset a = it.next();
double price = prices.getComposition(a);
double shares = folio.getShares(a);
double ishares = ifolio.getShares(a);
System.out.println(a.getIdentity() + ": "
+ (shares * price) + "\t(was: " + (ishares * price) + ")");
}
}
}
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 113
Axioma Portfolio
Glossary
Glossary
Absolute Risk
The standard deviation of the portfolio returns over the coming period.
See Also Portfolio, Benchmark.
Active Holdings
The difference between the holdings in a portfolio and the benchmark, either for
an individual security or set of securities (e.g., an industry). This is also referred to
as the "bet" or "active weight". The active holdings are negative if the portfolio
holds less than the benchmark and positive if the portfolio holds more.
See Also Holdings, Portfolio.
Active Risk
A measure of the risk of a portfolio with respect to a benchmark. The standard
deviation of the difference between portfolio returns and benchmark returns
over the coming period. Also referred to as the "tracking error".
See Also Benchmark, Portfolio.
Active Weight
See Active Holdings.
Alpha
Expected return or expected excess return of a security or portfolio over a given
period of time, expressed as a percentage relative to the value of the security at
the start of the period.
See Also Asset, Security, Return.
Asset
See Security.
Asset Universe
The complete set of assets (securities) available for investment. This must include
the initial portfolio holdings and usually include the assets in the benchmark or
others. Typical asset universes include the stocks of the S&P500, the Nasdaq or
the Wilshire 5000.
Benchmark
A portfolio of securities from the asset universe on which portfolio performance
will be judged. For index-tracking, the benchmark is the portfolio that is to be
tracked. Common benchmarks includes market portfolios such as the S&P 500,
Nasdaq 100, or other proprietary indexes.
See Also Index, Portfolio, Risk Model.
Benchmark Size
The size of the portfolio represented by the benchmark.
See Also Portfolio Size.
Benchmark Weight
The holdings in a benchmark security, represented as a percentage of the benchmark size.
See Also Weight.
Bet
See Active Holdings.
Beta
Beta is a measure of a security's or portfolio's sensitivity to market movements. It
measures the relationship between the security's or portfolio's return (or excess
return) and the return (or excess return) of the market.
Bet Variable
Refers to the variable representing the bet on a particular security in the math-
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 114
Axioma Portfolio
Glossary
ematical model, usually denoted dj for security j.
See Also Individual Bet, Holdings, Transaction , Security.
Budget Constraint
Requires that the total value of the optimized portfolio (the sum of all asset values) should equal the investment size.
See Also Investment Size.
Common Factor Risk
See Risk Model.
Covariance Matrix
See Risk Model.
Derivative
Short for "derivative security". A contract whose value is based on the performance of an underlying financial asset, index or other investment. Examples include
options and futures.
See Also Option, Future, Security.
Diversification
Spreading of risk by taking positions in securities with differing risk profiles in an
effort to lower overall risk.
See Also Portfolio, Risk Model.
Excess Return
The return in excess of the risk-free rate provided by a security over a given period of time.
See Also Security, Return.
Expected Return
See Alpha.
Exposure Matrix
See Risk Model.
Factor Model
See Risk Model.
Future
Short for "futures contract". Agreement to buy or sell a specific amount of a commodity or financial instrument at a particular price on a stipulated future date.
Part of the class of securities called derivatives.
See Also Derivative, Option.
Holdings
As in initial holdings or benchmark holdings. The value of an asset, i.e., the investment (either positive or negative) made in a security for a portfolio. Positive holdings in a security means that the portfolio is long on the security (owns shares).
Negative holdings in a security means that the portfolio is short on the security
(owes shares).
See Also Transaction , Bet, Asset, Portfolio, Benchmark.
Holding Lot
See Tax Holding Lot .
Illiquidity Effect
See Market Impact.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 115
Axioma Portfolio
Glossary
Individual Bet
The difference between the holdings in an individual security in the portfolio and
the corresponding holdings in a benchmark. The bet measures, for a particular
security, how much the portfolio holdings differ from the benchmark holdings. A
positive (negative) bet is called an over (under).
See Also Industry Bet.
Index
See Benchmark.
Industry
A group of securities representing corporations with the same or similar primary
business activity. This usually is determined by the largest portion of revenue.
These may be implicitly defined in the factor (risk) model.
See Also Bet.
Industry Bet
The difference, between the portfolio and the benchmark, in net holdings in an
industry.
See Also Bet.
Investment Size
The total value of all holdings in a portfolio.
See Also Holdings, Portfolio.
Long
As in "long holdings", i.e., owning shares of a security. The opposite of "short."
See Also Short, Asset, Holdings.
Market Impact
The impact a large sell or buy order will have on the price of a security in the
market. Generally, one tries to avoid market impact by limiting the size of trading
relative to the trading volume of the security. Also called the "illiquidity effect."
Option
Gives the buyer the right, but not the obligation, to buy or sell an asset for a fixed
price at a certain date or before. Belong to a class of securities called derivatives.
An option to buy is denoted a call option, and an option to sell is called a put option.
See Also Security, Derivative.
Portfolio
A set of weights or dollar amounts representing the investment (long or short) in
each asset of the asset universe.
See Also Asset.
Portfolio Beta
See Beta.
Portfolio Size
The total dollar value of securities owned by a portfolio, less the total dollar value
of securities owed.
Portfolio Weight
The holdings in a security, represented as a percentage of the portfolio size.
Rebalancing
The process of adjusting holdings in a portfolio to better track an index or reduce
risk. Commonly done on a regular basis for institutional and individual portfolios.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 116
Axioma Portfolio
Glossary
See Also Benchmark, Portfolio, Risk Model.
Reference Size
The value upon which all relative portfolio calculations are based. For example, if
the reference size is $100,000, and a turnover constraint of 2% is imposed on
the portfolio (using Relative and 0.02), the turnover will effectively be limited
to be at most $2,000. The reference size is usually equal to the investment size,
although this is not required.
See Also Investment Size.
Return
The change in value of a portfolio or asset over an evaluation period, expressed
as a percentage of the value at the start of the period. Generally includes dividend
distributions made during that period.
See Also Asset, Expected Return.
Risk Model
Typical risk models provide a decomposition of risk into factors. A security's risk
is represented by the part exposed to the factors (systematic risk) plus a term
specific to the security (specific risk). is compatible with such factor models. Each
asset is related to each factor through an exposure matrix. The factors are also related through the covariance matrix. In combination, the factors, exposure, and
covariance matrices implicitly relate all securities and their inherent risk.
See Also Asset, Index, Benchmark, Exposure Matrix, Covariance Matrix.
Round Lotting
A requirement that the number of shares in all transactions for a security be multiples of the round-lot value specified for that security.
Security
Instrument that signifies an ownership position in a corporation (a stock), or a
creditor relationship with a corporation or government body (a bond), or rights
to ownership such as those represented by an option, subscription right, and subscription warrant. Synonymous, for our purposes, with asset.
See Also Asset.
Short
As in "selling short." Sale of a security or commodity futures contract not owned
by the seller; a technique used (1) to take advantage of an anticipated decline in
the price or (2) to protect a profit in a long position. The opposite of long. Shorting a position in a portfolio optimization framework signifies giving it a negative
value. Same as "short sale" or "shorting an asset."
See Also Long, Asset, Holdings.
Specific Risk
See Risk Model.
Systematic Risk
See Risk Model.
Tax Holding Lot
A tax holding lot denotes a number of shares bought of an asset together with
the date when they were bought and the price per share when they were
bought. This also pertains to a short sale, i.e., a tax holding lot can denote a date
when a short position was taken and the price per share when the shares were
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 117
Axioma Portfolio
Glossary
shorted.
See Also Tax Transaction Lot .
Tax Lot Selection Method
The method used to assign tax holding lots to tax transaction lots. The three
available options are OptimalLot, LIFOLot, and HIFOLot.
See Also Tax Holding Lot , Tax Transaction Lot .
Tax Transaction Lot
A tax transaction lot is a transaction (date, number of shares and price per share)
in a previously held tax holding lot. It is used so that the wash sales rule can be
correctly applied.
See Also Tax Holding Lot , Wash Sales Rule.
Transaction
The purchase or sell of a security. A transaction occurs when the holdings in a security change between the initial holdings and the portfolio holdings after rebalancing (the "new" holdings). If the new holdings in the security are greater than
the initial holdings, then a transaction occurs (a buy). If the new holdings in the
security are less than the initial holdings, then a transaction occurs (a sell).
See Also Rebalancing, Asset, Holdings, Portfolio, Benchmark.
Transaction Cost
Cost of buying or selling a security, which consists mainly of the brokerage commission, the dealer markdown or markup, or fee (as would be charged by a bank
or broker-dealer to transact Treasuries, for example) but also includes direct
taxes, such as the SEC fee, any state-imposed transfer taxes, or other direct
taxes. These costs are typically modeled as proportional (linear) to the quantity
bought or sold, as a percentage of the value of the transaction (the tj variable for
asset j in the optimization model), and may be asset dependent.
See Also Rebalancing.
Soft Constraints
A constraint that may be violated by a user-specified amount. A user-specified
penalty is imposed for each unit of the violation. The penalty may be either linear
or quadratic in the amount of the violation.
Tracking Error
See Active Risk.
Transaction Lot
See Tax Transaction Lot .
Turnover
Dollar volume of shares traded as a percentage of the portfolio size. Long turnover
represents the dollar volume of shares bought as a percentage of the portfolio
size, while short turnover represents the dollar volume of shares sold as a percentage of the portfolio size.
Universe
See Asset Universe.
Wash Sales Rule
A tax rule that disallows the capital loss on the sale of a security if the same security is purchased within a short period of time called the wash period.
See Also Tax Transaction Lot .
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 118
Axioma Portfolio
Glossary
Weight
The position in a security, represented as a percentage of the portfolio size.
See Also Benchmark Weight, Portfolio Weight.
Axioma Portfolio™ 2020 R2 -- User's Guide | Page 119
0
You can add this document to your study collection(s)
Sign in Available only to authorized usersYou can add this document to your saved list
Sign in Available only to authorized users(For complaints, use another form )