Я работал над некоторыми примерами кода, пытаясь изучить CVX и вращая свои колеса, пытаясь выяснить расширение к примеру Келли в CVXR:
"Расширения: как отмечено в некоторых вышеупомянутых траекторияхбогатство, как правило, снижается на значительную величину, прежде чем увеличиваться в конечном итоге. Один из способов уменьшить этот риск просадки - добавить выпуклое ограничение, как описано в Busseti, Ryu и Boyd (2016, 5.3). С помощью CVXR это можно сделать за один раз.строка с использованием атома log_sum_exp. Другие расширения, такие как цели богатства, ограничения ставок и границы VaR / CVaR, также легко включены. "
Версия R примера CVXR (без расширения) находится здесь: https://cvxr.rbind.io/cvxr_examples/cvxr_kelly-strategy/
## Solve for Kelly optimal bets
b <- Variable(n)
obj <- Maximize(t(ps) %*% log(rets %*% b))
constraints <- list(sum(b) == 1, b >= 0)
prob <- Problem(obj, constraints)
result <- solve(prob)
bets <- result$getValue(b)
Это прекрасно работает.
Версия Python (из справочного документа) с расширением находится здесь: https://github.com/cvxgrp/kelly_code
"Конечный результатЗадача RCK (11) может быть сформулирована и решена в CVXPY как "
b = Variable(n)
lambda_risk = Parameter(sign = ’positive’)
growth = ps.T*log(rets.T*b)
risk_constraint = (log_sum_exp (log(ps) - lambda_risk * log(rets.T*b)) <= 0)
constraints = [ sum_entries(b) == 1, b >= 0, risk_constraint ]
risk_constr_kelly = Problem(Maximize(growth),constraints)
risk_constr_kelly.solve()
In R с приведенной выше формулировкой, lambda_risk иrisk_constraints должны выглядеть следующим образом:
lambda_risk = Parameter(sign = "POSITIVE")
risk_constraint = (log_sum_exp(log(ps) - lambda_risk * log(rets %*% b) ) )
Однако это приводит к ошибке в CVXR :: psolve (a, b, ...): проблема не соответствует правилам DCP.
is_atom_convex(log_sum_exp(log(ps) - lambda_risk * log(rets %*% b) ))
TRUE
is_convex(log_sum_exp(log(ps) - lambda_risk * log(rets %*% b) ))
FALSE
is_dcp(log_sum_exp(log(ps) - lambda_risk * log(rets %*% b) ))
FALSE
curvature((sum(exp( log(ps) - lambda_risk * log(rets %*% b) ))))
curvature(log(sum(exp( log(ps) - lambda_risk * log(rets %*% b) ))))
CONVEX & UNKNOWN
sign((sum(exp( log(ps) - lambda_risk * log(rets %*% b) ))))
sign(log(sum(exp( log(ps) - lambda_risk * log(rets %*% b) ))))
ПОЗИТИВНО И НЕИЗВЕСТНО
Похоже, что окончательный журнал - это то, что его дисквалифицирует.
Если я подставлю переменную b фактическими «ставками» из исходной итерации, она скажет, что это is_dcp TRUE
is_dcp(log_sum_exp(log(ps) - lambda_risk * log(rets %*% bets) ))
ИСТИНА
Может ли быть так, как этот неотвеченный пост (тот же основной вопрос) Log_sum_exp выпуклой функции не соответствует dcp? предположил, что CVXR :: log_sum_exp «не может вывестивыпуклость log_sum_exp », возможно, потому что он не распознает знак переменных?
Я был бы удивлен, если бы в моем коде была ошибка R, а не чего-то не хватало.
Кроме того, при значении lambda_risk @ value равном нулю, он должен просто вернуть прямую ставку Kelly Optimal,Я получаю этот результат, только если перезаписываю переменную lambda_risk числом 0.
is_dcp( log_sum_exp( log(ps) - 0 * log(rets %*% b) ) )
is_dcp(log_sum_exp( log(ps) - 0))
TRUE & TRUE
lambda_risk@value= 0
is_dcp( log_sum_exp( log(ps) - lambda_risk * log(rets %*% b) ) )
FALSE
Я в тупике.
Везде есть решения на python, и я также получил формулировку, которую я пробовал выше, для работы в DEOPTIM (значительно дольше), поэтому я не ожидал, что реализация CVXR будет такой сложной.Будем благодарны за любые пути преследования или даже за подтверждение того, что кто-то заставил его работать (не ошибка).