Introduction

The Omega Point optimization API enables customers to apply common portfolio optimization techniques to identify the ideal positioning, given their unique preferences. The API allows you to send a set of positions along with your objectives, constraints, and forecasts to retrieve optimized security weights for the given positions.

The optimization API can help you: 

  • Rebalance production portfolios on a regular basis
  • Construct new factor-aware portfolios with benchmark comparisons
  • Research and validate new strategies

This guide should help familiarize you with the optimization API, beginning with running a simple optimization and reviewing the results. Then you will explore a more advanced optimization, using constraints. By the end of this guide, you should be ready to develop your own customized optimizations.

Before beginning, this guide assumes that you are already familiar with the API and have reviewed the following articles:

Simple Optimization Query

In its simplest form, an optimization on a specified model takes in a position set (a collection of securities with weights) along with an objective function (i.e. your utility function), and returns an optimized position set against that objective.

Query

query(
  $positionSet: PositionSetInput!,
  $objective: [OptimizationObjective]!,
  $modelId: String!,
  $constraints: OptimizationConstraints!) {
  model(id: $modelId) {
    optimization(
      positionSet: $positionSet,
      objective: $objective,
      constraints: $constraints) {
      risk {
        date
        total
        attribution {
          summary {
            factors
            specific
          }
          factors(id: "Volatility") {
            name
            value
          }
        }
      }
      positionsDelta {
        date
        equities {
          id {
            ticker
            mic
          }
        }
      }
    }
  }
}

Variables

Note: update the "modelId" variable below with an appropriate model ID value.

{
  "positionSet": {
    "dates": {
      "date": "2016-06-30",
      "equities": [{
        "id": {
          "ticker": "GOOG",
          "mic": "XNAS"
        },
        "economicExposure": 1000.00
      }, {
        "id": {
          "mic": "XNYS",
          "ticker": "IBM"
        },
        "economicExposure": 2000.00
      }]
    }
  },
  "objective": {
    "minimizeTotalRisk": true
  },
  "modelId": "xxxxx-xx",
  "constraints": {
    "maxTurnover": 0.05
  }
}

The query above, and the variables being passed in, are dissected below.

Required Parameters

Position Set

A set of securities and weight pairings that are used to represent your portfolio, strategy, benchmark, etc. The security is identified by passing in either its SEDOL, ticker/mic pair, or AxiomaID.

Example

...{
  "economicExposure": 2000.00,
  "id": {
    "mic": "XNYS",
    "ticker": "IBM"
  }
}...

Learn more about Using Position Sets

Objective 

The utility function that will be used to achieve a particular goal. To set the objective, you pass in an object with the name of the optimization you'd like to perform:

  • minimizeFactorRisk: Minimize factor risk across the position set.
"objective": { "minimizeFactorRisk": true } 
  • minimizeTotalRisk: Minimize total risk across the position set
"objective": { "minimizeTotalRisk": true } 

Additional optimization objectives are described in the Optimization Common Objectives article.

Model 

The ID of the risk model to use in the optimization. For a list of models supported in your account, run the following query:

query {
  models {
    name
    id
  }
}

Constraints

The Constraints parameter contains requirements the optimizer must meet (e.g. liquidity, turnover, minimum trade size, etc.). You can learn more details in the Common Constraints section below.

Optional Parameters

Base

Base is an optional parameter that is provided when applying the optimization objective relative to another position set.

For example, when attempting to optimize a portfolio that is compared against a benchmark, the provided “base” should be the benchmark, as in the sample below. This input follows a similar structure to a position set:

"base": [
  {
    "type": "BENCHMARK",
    "id": "SP500"
  }
],
"positionSet": {
    "type": "PORTFOLIO",
    "id": "portfolioID"
}

Restrictions with the Base parameter
When using the base parameter, the optimizer API requires certain “positionSet” & “base” configurations for proper operation. Namely, the PositionSetInput object must follow the same structure for both the positionSet and base parameters.

In the sample above, both positionSet and base use the “type/id” structure to access data from the Omega Point platform, with one “on” date, discussed below, that will be used with both those data sets.

"base": [
  {
    "type": "BENCHMARK",
    "id": "SP500"
  }
],
"positionSet": {
    "type": "PORTFOLIO",
    "id": "portfolioID"
},
"on": "2018-01-01"

Otherwise, both positionSet and base must use the “dates” structure together, using the same dates and not using the “on” date, since this “dates” structure already contains the date to be optimized.

"base": { 
    "dates": [{
        "date": "2018-01-01",
        "equities": [...]
    }]
},
"positionSet": {
    "dates": [{
        "date": "2018-01-01",
        "equities": [...]
    }]
}

On

The date of the optimization when a portfolio is used as the position set input.

If you are passing in a position set that references a portfolio by ID (see example below), the "on" date is required in order to specify which date to optimize. Otherwise, do not use the "on" field.

Example:

...
  "positionSet": {
    "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "type": "PORTFOLIO"
  },
  "on": "2017-06-15",
...


Forecast

Forecast can be used to include expected returns, as well as market impact, to account for costs associated with trades. You can see more details in the Forecast section below.

Securities

The securities input can take in a security universe -- a list of securities not currently in your position set -- and find the optimal positioning for those securities for the specified long or short side of the optimization.

It can be configured in one of three ways: 

  • Providing a watchlist
  • Adding equity names on-the-fly
  • A combination of both using a watchlist and on-the-fly names, shown below
(
  securities: {
    short: {
      id: "watchlist_id",
      type: "WATCHLIST",
      equities: [{
        id: {
          ticker: "MSFT",
          mic: "XNAS"
        }
      }]
    }
  }
)

Here we see the structure referencing an existing watchlist. This will pull in all the securities associated with this watchlist as part of the security universe. Learn more about watchlists

In addition, this structure augments the watchlist with on-the-fly equities, passing in an array of IDs to either the long or short side of the book.

Note that these securities lists do not contain a date nor economicExposure as they are external names that may be added to the optimized position set.

Note on Short Market Value, Long Market Value
When adding securities, the optimizer needs to know how much market value to target, longMarketValue or shortMarketValue. The market value is defined as the total economic exposure of that side of the book. This lets the optimizer know how much it can buy into as it adds the external names to the overall book.

Simple Optimization Output

Taking the query from before, the requested risk metrics and resulting trades needed to achieve the optimization are highlighted below:

...
      risk {
        date
        total
        attribution {
          summary {
            factors
            specific
          }
          factors(id: "Volatility") {
            name
            value
          }
        }
      }
      positionsDelta {
        date
        equities {
          id {
            ticker
            mic
          }
        }
      }
...

Risk

By declaring the risk field, the optimization API will return risk characteristics of the optimized position set for a particular date. Specifically, the API is returning the total risk of the optimized position set, including its attribution, broken down into factor and specific risk decompositions. Furthermore, this request asks for the factor risk contribution of Volatility.

Positions Delta

The optimization achieves new security weights by applying trades to the Position Set provided. The positionsDelta parameter asks the optimization API to return the list of securities that were traded into or out-of on a particular date. Each security returned includes its ID, as well as its trade value, under the field economicExposure.

Common Objectives

This section describes common optimization objective levers available to you in the API.

Risk Minimization 

With the optimizer, you can set the objectives to either lower the total risk, or lower factor risk of the provided position set. The optimizer will find the best combination of trades in order to minimize these risks.

The structure of the objective for minimizing total risk is: 

{ "minimizeTotalRisk": true }

The structure of the objective for minimizing factor risk is:

{ "minimizeFactorRisk": true }

Mean-Variance Optimization

You are able to achieve a mean-variance optimization when including additional forecast information. By setting the objective to one of the risk minimization objectives (total risk minimization or factor risk minimization from above) and sending in expected forecasts, you can achieve a more optimal risk-adjusted return.

Learn how to pass in your forecast in the Forecast section below, under Common Constraints.

Tracking Benchmarks

Many long-only managers want to analyze their performance, as compared to a benchmark. The optimizer can account for this tracking by offering an “active” version to any objective. Passing in your positions with the position set for your preferred benchmark will signal the optimizer to return all trades and metrics based on the active objective.

Below is a sample query that would achieve a standard mean-variance optimization, using a forecast and tracking against the S&P500 benchmark. 

query (
  $positionSet: PositionSetInput!
  $objective: [OptimizationObjective]!
  $modelId: String!,
  $forecast: ForecastInput!,
  $benchmark: PositionSetInput!
) {
  model(id: $modelId) {
    optimization(
      positionSet: $positionSet,
      objective: $objective,
      constraints: {},
      forecast: $forecast,
      base: [$benchmark]) {
      positionsDelta {
        date
        equities {
          id {
            ticker
            mic
          }
          economicExposure
        }
      }
    }
  }
}

Variables:
Note: update the "modelId" variable below with an appropriate model ID value.

{
  "positionSet": {
    "dates": {
      "date": "2017-06-30",
      "equities": [{
        "id": {
          "ticker": "GOOG",
          "mic": "XNAS"
        },
        "economicExposure": 1000.00
      }, {
        "id": {
          "ticker": "IBM",
          "mic": "XNYS"
        },
        "economicExposure": 2000.00
      }]
    }
  },
  "objective": {
    "minimizeTotalRisk": true
  },
  "modelId": "xxxxx-xx",
  "forecast": {
    "horizon": 20,
    "equities": [{
      "id": {
        "ticker": "GOOG",
        "mic": "XNAS"
      },
      "expectedPercentReturn": 0.12
    }, {
      "id": {
        "ticker": "IBM",
        "mic": "XNYS"
      },
      "expectedPercentReturn": 0.275
    }]
  },
  "benchmark": {
    "type": "BENCHMARK",
    "id": "SP500"
  }
}

Factor Targeting

In addition to factor risk minimization, the optimizer can isolate specific factors and target your desired factor exposure z-score for each factor specified in a list. For example, if your book has been over-exposed to volatility (with a current exposure of 3.24) and you are targeting an exposure of 1.4, as well as, targeting a size exposure of 1.2, then with objective.targetExposures you can specify the following:

{
  "objective": {
    "targetExposures": [{
      "id": "Volatility",
      "target": 1.4
    },{
      "id": "Size",
      "target": 1.2
    }]
  }
}

Common Constraints

To achieve well-suited optimizations, the optimizer can process customized optimization constraints. Below are some of the most commonly-used constraints; additionally, all of the constraints are documented in the Optimization: GraphQL Parameters article.

Liquidity

Constrains single security concentration to not exceed this multiple of the security's 20-day average daily volume.

Turnover

The percent of the position set that can be traded during the optimization.

Concentration

     Global
     Maximum / minimum proportion of GMV that any single security may hold.

     Per Security
     Minimum and Maximum allowed position sizes for individual securities.

Leverage

     LMV
     Total absolute value of economic exposures across long positions.

     SMV
     Total absolute value of economic exposures across short positions.

Forecast

A forecast is a prediction or estimate of future events that can be used to refine the optimization, with an associated time horizon (in trading days). In the case where either the minimizeTotalRisk or minimizeFactorRisk objective function is selected, the optimizer will attempt to maximize the difference between the expected return and the expected risk objective. Below is a sample of a forecast input:

{
  "horizon": 20,
  "equities": [{
    "id": { "ticker": "MSFT", "mic": "XNAS" },
    "expectedPercentReturn": 0.12
  }, {
    "id": {
       "mic": "XNYS",
       "ticker": "IBM"
    },
    "expectedPercentReturn": 0.275,
    "marketImpact": [{
      "tradeSize": 12,
      "percentImpact": 0.01
    }]
  }]
}

The horizon attribute is an integer that refers to the number of trading days for which this forecast is relevant. 

The equities section contains each security with relevant expectedPercentReturn. In the example above, MSFT is expected to return 0.12%, while IBM is expected to return 0.275% over the next 20 trading days. 

The forecast parameter also supports a market impact attribute, which is further explained in the Optimization with Market Impact article.

Did this answer your question?