Контекст: я являюсь разработчиком PyPortfolioOpt , библиотеки оптимизации портфеля python, и я пытаюсь позволить пользователям добавлять ограничения к проблеме максимального отношения Шарпа.
В настоящее время пользователи могут передавать свои ограничения в виде лямбда-функции, например, чтобы все веса были больше 1%:
ef = EfficientFrontier(mu, S) # mu and S are expected return and covariance
ef.add_constraint(lambda w: w >= 0.01) # example new constraint
ef.min_volatility() # optimise with constraint
В бэкэнде я передаю переменную cvxpy w = cp.Variable(n)
в функцию лямбда-ограничения, чтобы создать действительное ограничение cvxpy, я передаю его cp.Problem
и решаю его.
Проблема, с которой я столкнулся, заключается в том, что для максимизации коэффициента Шарпа требуется замена переменных. Ограничения вида Ax ~ b
(где ~
обозначает либо равенство, либо неравенство) должны стать Ax ~ k * b
, где k
- неотрицательная переменная оптимизации.
Одна вещь, которую я пытался, состояла в том, чтобы передать w / k
в лямбда-функция. Тогда это приведет к ограничению w / k >= 0.01
, которое, как я надеялся, будет эквивалентно w >= k * 0.01
, но, к сожалению, это дает:
DCPError: Problem does not follow DCP rules. Specifically:
The following constraints are not DCP:
0.01 <= var2817 / Promote(var2818, (20,)) , because the following subexpressions are not:
|-- var2817 / Promote(var2818, (20,))
Затем я подумал, что смогу взять нелинейное ограничение constr = (w / k >= 0.01)
и умножьте его на k
, чтобы получить k * constr = (w >= 0.01 * k)
, но вы не можете умножить ограничения в cvxpy.
TL; DR: как я могу преобразовать объект ограничения cvxpy (уже создан) представление w / k >= 0.01
в объекте ограничения cvxpy, представляющем w >= k * 0.01
?
Или, если это не удалось, есть ли способ, которым я могу изменить это? Я бы хотел оставить API лямбда-функции.