We can determine different constraints with a formatted csv file as follows:
          
Constraints can be established on a top-down level, i.e. factor loading constraints or bottom-up aggregations. Columns (2) and (3) are used to distinguish if a constraint if bottom-up (aggregation) or top-down (projection). Use either column, but same constraint cannot have entries on both columns.
In order to specify an aggregation constraint, the following parameters have to be provided:
- Aggregation type (column 3): Currently only "aggregation_label" and "position" supported. Position specific constraints always take precedence over more generic constraints.
- Type (column 4): "aggregation_label" can be any string associated with the position and is provided during portfolio upload. When "position" is used, the stock ticker is the relevant property.
- Group (column 5): if True, the constraint is considered on the aggregate. If omitted, it is imposed on each security of the aggregation. Please see examples below.
- Sell / Buy (columns 6 and 7): These are relative constraints in terms of percent of existing position. A 100 on "Sell" means that any security belonging to this aggregation can be sold in full. Always provide both Sell/Buy. When columns 6 and 7 are filled, columns 8 to 11 need to be empty
- lower_weight / upper_weight (columns 8 and 9): These are absolute constraints. When used, do not use relative constraints, i.e. columns 6 and 7 need to be empty
- slack-/slack+ (columns 10 and 11): Use these to establish non-binding constraints. Currently can only be used with Grouped constraints or factors, as explained below.
- enabled (column 12): Boolean to turn constraints on and off.
Let's describe the aggregation constraints in the table above:
Constraint 0: (No cash increase)
All the cash positions need to be labelled in the portfolio. Each security representing cash can be sold in its entirety and each cash position cannot be increased:
Constraint 1: (No tradable positions)
Positions that cannot be traded. All the positions subjected to this constraint need to be labelled in the portfolio with the same "Type" used in the constraint specification:
The portfolio to be optimized would required the labels for positions that are not supposed to be traded to be "non_tradable". Any label can be used but users need to enforce consistency with the constraint specification file:
Constraint 2: (Absolute limit on each security from a Type)
Every position labelled as "new_stock" is limited to 2% of the portfolio.
Constraint 3: (Absolute limit on the aggregate of all securities from a Type)
This constraint specifies the combined target allocation for all the securities belonging to an aggregation. In the example below it specifies that "new_stock" should be 7% as a whole. When a different lower and upper weights are provided, the combined allocation is constrained in the range.
Also group constraints can be non-binding. Slacks can be provided. In the example, the target for new stocks in the portfolio should be 7%, but we accept no inclusion (7% negative slack) to 12% (5% positive slack):
Constraint 5: (Absolute limits on a single security)
In the example, VIG is constrained to be between 2% and 10% of the portfolio. If VIG was part of a more generic constraint, this individual constraint will super seed.
Constraints 8-11: (Absolute limits on a factor model)
Constraints on a single multi factor model can be specified. Factor targets are specified in multiple lines. When lower and upper weights differ, the factor loadings are constrained in the ranges. These constraints can be non-binding (similarly to groups - constrain 3)
The targets do not need to add to 100%.