使用 ROI (R) 构建具有各种约束的投资组合

问题描述 投票:0回答:1

我正在尝试使用投资回报率构建一个投资组合,在给定期限内最大化投资组合收益率。为了走捷径,我尝试了 Chat GPT 路径,但没有任何收获。

代码是:

opt_data <- data <- data.frame(
  Type = c("Public", "Public", "Public", "Public", "Public", "Public", "Private", "Private", "Private"),
  Sector = c("Cash", "Senior Bank", "Senior Bank", "Senior Bank", "ABS", "Senior Bank", "ABS", "ABS", "ABS"),
  IGNG = c("IG", "IG", "IG", "IG", "IG", "IG", "NG", "NG", "NG"),
  Rating = c("AAA", "AA", "AA", "A", "AA", "A", "AA", "A", "AA"),
  Duration = c(1, 1, 2, 1, 3, 2, 4, 3, 5),
  Yield = c(0.035, 0.05, 0.051, 0.052, 0.052, 0.053, 0.053, 0.054, 0.054)
)

objective_function <- function(weights) {
  weighted_yield <- sum(weights * opt_data$Yield)
  return(-weighted_yield)  # We're maximizing yield, so we use negative yield
}


opt_model <- ROI::OP(
  objective = "max",
  objective_fun = objective_function,
  constraints = list(
    sum = c(1, "="),  # Total weight equals 1
    private_assets = c(sum(opt_data$Type == "Private"), "<=", 0.5),  # Private assets cannot exceed 50%
    duration = c(sum(opt_data$Duration), "<=", 3),  # Portfolio duration cannot exceed 3
    cash_and_bank = c(sum(opt_data$Sector %in% c("Cash", "Senior Bank")), ">=", 0.1),  # Sum of cash and senior bank debt cannot be less than 10%
    investment_grade = c(sum(opt_data$IGNG == "IG"), "<=", 0.6)  # Sum of investment grade assets cannot be more than 60%
  ),
  types = "C"  # Continuous decision variables
)

# Solve optimization problem
opt_solution <- ROI::ROI_solve(opt_model, solver = "glpk")

# Extract the optimized weights
optimized_weights <- opt_solution$weights

# Print solution
print(opt_solution)

作为解释,代码试图最大化投资组合收益率(这将是每种资产的加权收益率之和),同时确保:

  • 私人资产比例不超过50%
  • 投资组合久期为 3(这又是每项资产的加权久期之和)
  • 现金和银行必须至少占 10%,并且
  • 投资级(IG)资产不能超过60%

目前我收到此错误

Error in ROI::OP(objective = "max", objective_fun = objective_function,  : 
  unused argument (objective_fun = objective_function)

但是,我很确定还有其他问题。例如,3 的持续时间必须是加权持续时间。此外,数据框中没有权重向量。

如果有任何可以帮助我,我将不胜感激。

r portfolio roi glpk
1个回答
0
投票

我改变了路线并使用了 PortfolioAnalytic 软件包。问题是这适用于时间序列数据。我想做的是使用持续时间而不是不同的日期。知道我还需要添加一个持续时间约束,我可以将其添加到组列表中,但该包似乎没有考虑此类问题。有什么想法吗?

library(ROI)
library(ROI.plugin.glpk)
library(ROI.plugin.quadprog)
library(PortfolioAnalytics)
library(tidyr)

# Load data
opt_data <- data.frame(
  Type = c("Public", "Public", "Public", "Public", "Public", "Public", "Private", "Private", "Private", "Public"),
  Sector = c("Cash", "Senior Bank", "Senior Bank", "Senior Bank", "RMBS", "RMBS", "RMBS", "RMBS", "CMBS", "CMBS"),
  IGNG = c("IG", "IG", "IG", "IG", "IG", "IG", "NG", "NG", "NG","IG"),
  Rating = c("AAA", "AAA", "AA", "A", "AA", "A", "B", "BB", "BB","AA"),
  Duration = c(1, 1, 2, 1, 3, 2, 4, 3, 5, 3),
  Yield = c(0.035, 0.05, 0.051, 0.052, 0.052, 0.053, 0.053, 0.054, 0.054, 0.06)
)

# Join to create unique combinations
opt_data$concatenate <- paste(opt_data$Type, opt_data$Sector, opt_data$IGNG, opt_data$Rating, sep = "-")

# Pivot data 
opt_data_pivot <- opt_data[c("concatenate", "Duration", "Yield")]
a <- pivot_wider(opt_data_pivot, names_from = concatenate, values_from = Yield)

# Add duration as a constraint
port_spec <- portfolio.spec(opt_data$concatenate)

##  This does not work
port_spec <- add.constraint(portfolio = port_spec, type = "duration", lower = 1, upper = 1)

# Add other constraints
port_spec <- add.constraint(portfolio = port_spec, type = "full_investment")
port_spec <- add.constraint(portfolio = port_spec, type = "long_only")

group_list <- list(groupIG = c(1,2,3,4,5,6,10),
                   groupNIG = c(7,8,9),
                   cash = c(1),
                   noncash = c(2:10),
                   liquid = c(1,2,3),
                   nonliquid = c(4:10),
                   private = c(7:9),
                   public = c(1:6,10)
)

port_spec <- add.constraint(portfolio=port_spec, 
                            type="group", 
                            groups=group_list,
                            group_min=c(0.0, 0.0, 0.05,0.05 ,0.1, 0.0,0.0,0.0),
                            group_max=c(1.0, 0.3, 0.95,0.95 ,1.0, 0.9,0.3,0.8 ))


# Set objective to maximize return
port_spec <- add.objective(portfolio = port_spec, type = "return", name = "mean")

row_dates <- as.Date(c("2023-01-01", "2023-01-02", "2023-01-03", "2023-01-04", "2023-01-05"))
row.names(a) <- row_dates

# Solve the optimization problem
opt <- optimize.portfolio(a, portfolio = port_spec, optimize_method = "ROI")

# Extract weights
extractWeights(opt)

# Plot weights
chart.Weights(opt)
© www.soinside.com 2019 - 2024. All rights reserved.