R 中的递归 optim() 函数导致错误

问题描述

我正在尝试使用 R 中的 optim() 函数来最小化矩阵运算的值。在这种情况下,我试图将一组股票的波动性降至最低,这些股票的单个回报彼此共变。被最小化的目标函数是 calculate_portfolio_variance

library(quantmod)

filter_and_sort_symbols <- function(symbols)
{
  # Name: filter_and_sort_symbols
  # Purpose: Convert to uppercase if not
  # and remove any non valid symbols
  # Input: symbols = vector of stock tickers
  # Output: filtered_symbols = filtered symbols
  
  # convert symbols to uppercase
  symbols <- toupper(symbols)
  
  # Validate the symbol names
  valid <- regexpr("^[A-Z]{2,4}$",symbols)
  
  # Return only the valid ones
  return(sort(symbols[valid == 1]))
}

# Create the list of stock tickers and check that they are valid symbols
tickers <- filter_and_sort_symbols(c("AAPL","NVDA","MLM","AA"))
benchmark <- "SPY"
# Set the start and end dates
start_date <- "2007-01-01"
end_date <- "2019-01-01"

# Gather the stock data using quantmod library
getSymbols(Symbols=tickers,from=start_date,to=end_date,auto.assign = TRUE)
getSymbols(benchmark,auto.assign = TRUE)

# Create a matrix of only the adj. prices
price_matrix <- NULL
for(ticker in tickers){price_matrix <- cbind(price_matrix,get(ticker)[,6])}
# Set the column names for the price matrix
colnames(price_matrix) <- tickers
benchmark_price_matrix <- NULL
benchmark_price_matrix <- cbind(benchmark_price_matrix,get(benchmark)[,6])

# Compute log returns
returns_matrix <- NULL
for(ticker in tickers){returns_matrix <- cbind(returns_matrix,annualReturn(get(ticker)))}
returns_covar <- cov(returns_matrix)
colnames(returns_covar) <- tickers
rownames(returns_covar) <- tickers
# get average returns for tickers and benchmark
ticker_avg <- NULL
for(ticker in tickers){ticker_avg <- cbind(ticker_avg,colMeans(annualReturn(get(ticker))))}
colnames(ticker_avg) <- tickers
benchmark_avg <- colMeans(annualReturn(get(benchmark)))

# create the objective function
calculate_portfolio_variance <- function(allocations,returns_covar,ticker_avg,benchmark_avg)
{
  # Name: calculate_portfolio_variance
  # Purpose: Computes expected portfolio variance,to be used as the minimization objective function
  # Input: allocations = vector of allocations to be adjusted for optimality; returns_covar = covariance matrix of stock returns
  #        ticker_avg = vector of average returns for all tickers,benchmark_avg = benchmark avg. return
  # Output: Expected portfolio variance
  
  # get benchmark volatility 
  benchmark_variance <- (sd(annualReturn(get(benchmark))))^2
  # scale allocations for 100% investment
  allocations <- as.matrix(allocations/sum(allocations))
  # get the naive allocations
  naive_allocations <- rep(c(1/ncol(ticker_avg)),times=ncol(ticker_avg))
  portfolio_return <-  sum(t(allocations)*ticker_avg)
  portfolio_variance <- t(allocations)%*%returns_covar%*%allocations
  
  # constraints = portfolio expected return must be greater than benchmark avg. return and
  #               portfolio variance must be less than benchmark variance (i.e. a better reward at less risk)
  if(portfolio_return < benchmark_avg | portfolio_variance > benchmark_variance)
  {
    allocations <- naive_allocations
  }
  
  portfolio_variance <- t(allocations)%*%returns_covar%*%allocations
  return(portfolio_variance)
}


# Specify lower and upper bounds for the allocation percentages
lower <- rep(0,ncol(returns_matrix))
upper <- rep(1,ncol(returns_matrix))

# Initialize the allocations by evenly distributing among all tickers
set.seed(1234)
allocations <- rep(1/length(tickers),times=length(tickers))

当我手动调用目标函数时,它会按预期返回一个值:

> calculate_portfolio_variance(allocations,benchmark_avg)
          [,1]
[1,] 0.1713439

但是,当我使用 optim() 函数时,它返回错误:

> optim_result <- optim(par=allocations,fn=calculate_portfolio_variance(allocations,benchmark_avg),lower=lower,upper=upper,method="L-BFGS-B")
Error in t(allocations) %*% returns_covar : non-conformable arguments

我不确定原因,但可能与 optim() 递归使用 allocations 变量的方式有关。我该怎么做才能解决这个问题?

编辑:FWIW,其他优化策略有效(差分进化、模拟退火)但我更喜欢使用梯度下降,因为它要快得多

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)