1

I am trying to learn the DEoptim library in R but I think I am misunderstanding the library documentation from

https://www.rdocumentation.org/packages/DEoptim/versions/2.2-4/topics/DEoptim

I am getting the error argument "returns_covar" is missing, with no default when I try the code below

The function I am trying to optimize (minimize) is:

calculate_portfolio_variance <- function(allocations, returns_covar)
{
  # 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
  # Output: Expected portfolio variance

  portfolio_variance <- allocations%*%returns_covar%*%t(allocations)
  return(portfolio_variance)
}

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("XLE", "XLB", "XLI", "XLY", "XLP", "XLV", "XLK", "XLU", "SHY", "TLT"))
# Set the start and end dates
start_date <- "2013-01-01"
end_date <- "2014-01-01"

# Gather the stock data using quantmod library
getSymbols(Symbols=tickers, from=start_date, to=end_date, 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

# Compute log returns
returns_matrix <- apply(price_matrix, 2, function(x) diff(log(x)))
returns_covar <- cov(returns_matrix)

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

# Calculate the optimum allocation; THIS CAUSES AN ERROR
set.seed(1234)
optim_result <- DEoptim(calculate_portfolio_variance, lower, upper, control = list(NP=100, itermax=300, F=0.8, CR=0.9, allocations, returns_covar))

Again, the error from the last line is that the returns_covar argument is missing, but I try passing it into the DEoptim() function.

I think the above has a parenthesis error, so I've tried the following

optim_result <- DEoptim(calculate_portfolio_variance, lower, upper, control = list(NP=100, itermax=300, F=0.8, CR=0.9), returns_covar)

This results in the following error:

Error in allocations %*% returns_covar %*% t(allocations) : non-conformable arguments

When I check the dimensionality of the matrices, everything seems ok

> dim(allocations)
[1]  1 10
> dim(returns_covar)
[1] 10 10

Adding a dimensionality check within the calculate_portfolio_variance() function

  print(dim(allocations))
  print(dim(returns_covar))

shows that the allocation vector becomes NULL on the second iteration. I'm not sure why or how to address it.

[1]  1 10
[1] 10 10
NULL
[1] 10 10
Error in allocations %*% returns_covar %*% t(allocations) : non-conformable arguments
coolhand
  • 1,876
  • 5
  • 25
  • 46

1 Answers1

2

Not clear if this is what you intend, but if you change calculate_portfolio_variance to

  portfolio_variance <- t(allocations)%*%returns_covar%*%allocations

It works for me. I think it's an issue with your matrix math.

EDIT full working reproducible example:

library(quantmod)
library(DEoptim)


calculate_portfolio_variance <- function(allocations, returns_covar)
{
  # 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
  # Output: Expected portfolio variance

  ### I CHANGED THIS LINE
  #portfolio_variance <- allocations%*%returns_covar%*%t(allocations)
  portfolio_variance <- t(allocations)%*%returns_covar%*%allocations
  return(portfolio_variance)
}

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("XLE", "XLB", "XLI", "XLY", "XLP", "XLV", "XLK", "XLU", "SHY", "TLT"))
# Set the start and end dates
start_date <- "2013-01-01"
end_date <- "2014-01-01"

# Gather the stock data using quantmod library
getSymbols(Symbols=tickers, from=start_date, to=end_date, 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

# Compute log returns
returns_matrix <- apply(price_matrix, 2, function(x) diff(log(x)))
returns_covar <- cov(returns_matrix)

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

# Calculate the optimum allocation
set.seed(1234)
### USING YOUR CORRECTED CALL
optim_result <- DEoptim(calculate_portfolio_variance, lower, upper, control = list(NP=100, itermax=300, F=0.8, CR=0.9), returns_covar)
mikeck
  • 3,534
  • 1
  • 26
  • 39
  • Do you mean to just modify the line within `calculate_portfolio_variance()`? I replaced it with what you suggested but still get the same `non-conformable arguments` error. I agree, there seems to be an issue with the matrix math, but I haven't pinned down where it is yet. When I use `str(lower)` it displays a vector of correct length, using `dim(lower)` displays `NULL`. – coolhand Jan 24 '19 at 20:50
  • For what it's worth, when I execute `portfolio_variance <- allocations%*%returns_covar%*%t(allocations)` in the console, it calculates correctly. But when I execute `portfolio_variance <- t(allocations)%*%returns_covar%*%allocations` in the console, I get a `non-conformable arguments` error – coolhand Jan 24 '19 at 20:55
  • @coolhand I updated my answer to include a working reproducible example. – mikeck Jan 24 '19 at 23:32
  • It's working for me, thanks! Do you know if the issue was an order of operations issue? – coolhand Jan 25 '19 at 01:04
  • 1
    @coolhand sort of, in that because `allocations` is a vector you need to be careful about where you transpose. See [`?matmult`](https://stat.ethz.ch/R-manual/R-devel/library/base/html/matmult.html) for more info. It appears that `%*%` will automatically try to transpose vectors to make the multiplication work, but you explicitly transposed `allocations` on the right. Interestingly, omitting the transpose and just doing `allocations%*%returns_covar%*%allocations` works as well. – mikeck Jan 25 '19 at 15:58