@@ -2988,11 +2988,21 @@ optimize.portfolio <- optimize.portfolio_v2 <- function(
29882988
29892989 # # turnover constraint
29902990 if (! is.null(constraints $ turnover_target )){
2991+ # set weight initial
29912992 if (is.null(constraints $ weight_initial )){
29922993 weight_initial <- rep(1 / N , N )
29932994 } else {
29942995 weight_initial <- constraints $ weight_initial
29952996 }
2997+ # penalty for minvar
2998+ if (tmpname == " StdDev" ){
2999+ if (is.null(constraints $ turnover_penalty )){
3000+ sigma_value_penalty = nearPD(sigma_value )$ mat
3001+ } else {
3002+ sigma_value_penalty = sigma_value + diag(constraints $ turnover_penalty , N )
3003+ }
3004+ obj <- CVXR :: quad_form(wts - weight_initial , sigma_value_penalty ) + 2 * t(wts - weight_initial ) %*% sigma_value %*% weight_initial + t(weight_initial ) %*% sigma_value %*% weight_initial
3005+ }
29963006 constraints_cvxr = append(constraints_cvxr , sum(abs(wts - weight_initial )) < = constraints $ turnover_target )
29973007 }
29983008
@@ -3349,22 +3359,56 @@ optimize.portfolio.rebalancing <- function(R, portfolio=NULL, constraints=NULL,
33493359 training_period <- rolling_window
33503360
33513361 if (is.null(training_period )) {if (nrow(R )< 36 ) training_period = nrow(R ) else training_period = 36 }
3352- if (is.null(rolling_window )){
3353- # define the index endpoints of our periods
3354- ep.i <- endpoints(R ,on = rebalance_on )[which(endpoints(R , on = rebalance_on )> = training_period )]
3355- # now apply optimize.portfolio to the periods, in parallel if available
3356- ep <- ep.i [1 ]
3357- out_list <- foreach :: foreach(ep = iterators :: iter(ep.i ), .errorhandling = ' pass' , .packages = ' PortfolioAnalytics' ) %dopar % {
3358- optimize.portfolio(R [1 : ep ,], portfolio = portfolio , optimize_method = optimize_method , search_size = search_size , trace = trace , rp = rp , parallel = FALSE , ... = ... )
3362+
3363+ # turnover weight_initial is previous time point optimal weight
3364+ turnover_idx <- which(sapply(portfolio $ constraints , function (x ) x $ type == " turnover" ))
3365+ if (length(turnover_idx ) > 0 ){
3366+ turnover_idx <- turnover_idx [1 ]
3367+ # original weight_initial
3368+ if (is.null(portfolio $ constraints [[turnover_idx ]]$ weight_initial )){
3369+ portfolio $ constraints [[turnover_idx ]]$ weight_initial <- rep(1 / length(portfolio $ assets ), length(portfolio $ assets ))
3370+ }
3371+
3372+ # rebalancing
3373+ if (is.null(rolling_window )){
3374+ # define the index endpoints of our periods
3375+ ep.i <- endpoints(R ,on = rebalance_on )[which(endpoints(R , on = rebalance_on )> = training_period )]
3376+ # now apply optimize.portfolio to the periods, in parallel if available
3377+ ep <- ep.i [1 ]
3378+ out_list <- foreach :: foreach(ep = iterators :: iter(ep.i ), .errorhandling = ' pass' , .packages = ' PortfolioAnalytics' ) %dopar % {
3379+ opt <- optimize.portfolio(R [1 : ep ,], portfolio = portfolio , optimize_method = optimize_method , search_size = search_size , trace = trace , rp = rp , parallel = FALSE , ... = ... )
3380+ portfolio $ constraints [[turnover_idx ]]$ weight_initial <- opt $ weights
3381+ opt
3382+ }
3383+ } else {
3384+ # define the index endpoints of our periods
3385+ ep.i <- endpoints(R ,on = rebalance_on )[which(endpoints(R , on = rebalance_on )> = training_period )]
3386+ # now apply optimize.portfolio to the periods, in parallel if available
3387+ out_list <- foreach :: foreach(ep = iterators :: iter(ep.i ), .errorhandling = ' pass' , .packages = ' PortfolioAnalytics' ) %dopar % {
3388+ opt <- optimize.portfolio(R [(ifelse(ep - rolling_window > = 1 ,ep - rolling_window ,1 )): ep ,], portfolio = portfolio , optimize_method = optimize_method , search_size = search_size , trace = trace , rp = rp , parallel = FALSE , ... = ... )
3389+ portfolio $ constraints [[turnover_idx ]]$ weight_initial <- opt $ weights
3390+ opt
3391+ }
33593392 }
33603393 } else {
3361- # define the index endpoints of our periods
3362- ep.i <- endpoints(R ,on = rebalance_on )[which(endpoints(R , on = rebalance_on )> = training_period )]
3363- # now apply optimize.portfolio to the periods, in parallel if available
3364- out_list <- foreach :: foreach(ep = iterators :: iter(ep.i ), .errorhandling = ' pass' , .packages = ' PortfolioAnalytics' ) %dopar % {
3365- optimize.portfolio(R [(ifelse(ep - rolling_window > = 1 ,ep - rolling_window ,1 )): ep ,], portfolio = portfolio , optimize_method = optimize_method , search_size = search_size , trace = trace , rp = rp , parallel = FALSE , ... = ... )
3394+ if (is.null(rolling_window )){
3395+ # define the index endpoints of our periods
3396+ ep.i <- endpoints(R ,on = rebalance_on )[which(endpoints(R , on = rebalance_on )> = training_period )]
3397+ # now apply optimize.portfolio to the periods, in parallel if available
3398+ ep <- ep.i [1 ]
3399+ out_list <- foreach :: foreach(ep = iterators :: iter(ep.i ), .errorhandling = ' pass' , .packages = ' PortfolioAnalytics' ) %dopar % {
3400+ optimize.portfolio(R [1 : ep ,], portfolio = portfolio , optimize_method = optimize_method , search_size = search_size , trace = trace , rp = rp , parallel = FALSE , ... = ... )
3401+ }
3402+ } else {
3403+ # define the index endpoints of our periods
3404+ ep.i <- endpoints(R ,on = rebalance_on )[which(endpoints(R , on = rebalance_on )> = training_period )]
3405+ # now apply optimize.portfolio to the periods, in parallel if available
3406+ out_list <- foreach :: foreach(ep = iterators :: iter(ep.i ), .errorhandling = ' pass' , .packages = ' PortfolioAnalytics' ) %dopar % {
3407+ optimize.portfolio(R [(ifelse(ep - rolling_window > = 1 ,ep - rolling_window ,1 )): ep ,], portfolio = portfolio , optimize_method = optimize_method , search_size = search_size , trace = trace , rp = rp , parallel = FALSE , ... = ... )
3408+ }
33663409 }
33673410 }
3411+
33683412 # out_list is a list where each element is an optimize.portfolio object
33693413 # at each rebalance date
33703414 names(out_list )<- index(R [ep.i ])
0 commit comments