.. Copyright (C) 2023-2024 Enzo Busseti
.. Copyright (C) 2016 Enzo Busseti, Stephen Boyd, Steven Diamond, BlackRock Inc.
.. This file is part of Cvxportfolio.
.. Cvxportfolio is free software: you can redistribute it and/or modify it under
.. the terms of the GNU General Public License as published by the Free Software
.. Foundation, either version 3 of the License, or (at your option) any later
.. version.
.. Cvxportfolio is distributed in the hope that it will be useful, but WITHOUT
.. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
.. FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
.. details.
.. You should have received a copy of the GNU General Public License along with
.. Cvxportfolio. If not, see .
Constraints
===========
.. py:module:: cvxportfolio
:no-index:
.. automodule:: cvxportfolio.constraints
.. autoclass:: DollarNeutral
.. autoclass:: MarketNeutral
.. autoclass:: FactorMaxLimit
.. autoclass:: FactorMinLimit
.. autoclass:: FactorGrossLimit
.. autoclass:: FactorNeutral
.. autoclass:: FixedFactorLoading
.. autoclass:: LeverageLimit
.. autoclass:: LongCash
.. autoclass:: LongOnly
.. autoclass:: MaxWeights
.. autoclass:: MinWeights
.. autoclass:: MaxHoldings
.. autoclass:: MinHoldings
.. autoclass:: MaxTradeWeights
.. autoclass:: MinTradeWeights
.. autoclass:: MaxTrades
.. autoclass:: MinTrades
.. autoclass:: MaxBenchmarkDeviation
.. autoclass:: MinBenchmarkDeviation
.. autoclass:: ParticipationRateLimit
.. autoclass:: TurnoverLimit
.. autoclass:: FixedImbalance
.. autoclass:: NoCash
.. _soft-constraints:
Soft constraints
----------------
(Almost) all the constraints described above can also be be made "soft".
The concept is developed in
:paper:`section 4.6 of the paper `,
and implemented by the objective term :class:`cvxportfolio.SoftConstraint`.
In the case of a linear equality constraint,
which can be expressed as :math:`h(x) = 0`,
the corresponding soft constraint is a cost
of the form :math:`\gamma \|h(x)\|_1`, where
:math:`\gamma` is the *priority* penalizer.
For a linear inequality constraint
:math:`h(x) \leq 0`, instead,
the corresponding soft constraint is the cost
:math:`\gamma \|{(h(x))}_+\|_1`, where
:math:`{(\cdot )}_+` denotes the positive part
of each element of :math:`h(x)`.
In the paper we describe having different penalizers for
different elements of each constraint vector (so that
the penalizer :math:`\gamma` is a vector).
In our implementation this is achieved by constructing
multiple soft constraints, each with a scalar :math:`\gamma`
penalizer.
The syntax of our implementation is very simple. We pass a constraint instance to
:class:`cvxportfolio.SoftConstraint`, multiply the term by the penalizer, and
subtract it from the objective function.
For a high value of the penalizer the constraint will be
enforced almost exactly. For a small value, it will be almost ignored.
For example:
.. code-block:: python
policy = cvx.SinglePeriodOptimization(
objective =
cvx.ReturnsForecast()
- 0.5 * cvx.FullCovariance()
- 10 * cvx.SoftConstraint(cvx.LeverageLimit(3)))
is a policy that almost enforces a leverage limit of 3, allowing for some
violation. This can be controlled by tuning the multiplier in front
of :class:`cvxportfolio.SoftConstraint`.
Some constraint objects, which are in reality compositions of constraints,
can not be used as soft constraints. See their documentation for more details.
Cost inequality as constraint
-----------------------------
Since version ``0.4.6`` you can use any objective function term,
such as :doc:`returns`, :doc:`risks`, and :doc:`costs`, as part
of an inequality constraint.
In fact, you can use any linear combination of objective terms.
For a minimal example see the following risk-constrained policy.
.. code-block:: python
import cvxportfolio as cvx
# limit the covariance
risk_limit = cvx.FullCovariance() <= target_volatility**2
# or, since Cvxportfolio 1.4.0
risk_limit_annualized = cvx.FullCovariance() <= cvx.AnnualizedVolatility(
0.05) # means 5% annualized
cvx.MarketSimulator(universe).backtest(
cvx.SinglePeriodOptimization(
cvx.ReturnsForecast(), [risk_limit])).plot()
Keep in mind that the resulting inequality constraint must be convex.
You can't, for example, require that a risk term is larger or equal than
some value.
Base classes (for extending Cvxportfolio)
-----------------------------------------
.. autoclass:: Constraint
.. autoclass:: EqualityConstraint
.. autoclass:: InequalityConstraint