Ferdinand Wehle
Ferdinand Wehle

Reputation: 11

Quadratic function optimization using solve.QP in R

I am currently in the process of coding a portfolio weight optimizer using solve.QP for my finance uni class. Even though I think I have understood the matrix dimensions etc. for the solve.QP, the weights I am receiving, do not lead to a portfolio which is the tangent point of the capital market line and the efficient frontier.

Some info for the model: it should evaluate the best combination of 2 assets. The constraints of the model are, that the weights of the assets must add to 1 and that they are >= 0. The Sharpe ratio should be minimized. There are no covariances between the assets.

Below is the code, any help would be greatly appreciated!!!

library(quadprog)
library(ggplot2)

# Defining required variables
returns = c(0.04, 0.10)
volatility = c(0.06, 0.10)
risk_free_rate = 0.02  
excess_returns = returns - risk_free_rate  

# Simulation of 100 randomly weighted portfolios using the two assets to approximate the efficient frontier
all_portfolios <- data.frame(Volatility = numeric(100), Return = numeric(100))
for (i in 1:100) {
  weights = runif(2)
  weights = weights / sum(weights)
  
  portfolio_volatility = sqrt(sum((weights * volatility)^2))
  portfolio_return = sum(weights * returns)
  
  all_portfolios[i, ] = c(portfolio_volatility, portfolio_return)
}

# Defining the variables for the solve.QP and finding the optimal_weights
Dmat = diag(volatility**2)
dvec = excess_returns
Amat = t(rbind(1, diag(2)))
bvec = c(1, 0, 0)
qp = solve.QP(Dmat, dvec, Amat, bvec, meq = 1)
optimal_weights = qp$solution
sprintf(optimal_weights, fmt = '%#.3f')

# Calculating the optimal_portfolio volatility and return
optimal_portfolio = data.frame(Vol = sqrt(sum((optimal_weights*volatility)^2)), 
                               Ret = sum(optimal_weights * returns))

# Plotting the randomly weighted portfolios, the optimal portfolio, the two stocks and the line which SHOULD tangent the efficient frontier
plot <- ggplot() + 
  xlim(min(optimal_portfolio$Vol - 0.05, min(volatility) - 0.05), max(volatility) + 0.05) + ylim(min(returns) - 0.005, max(returns) + 0.005) +
  xlab("Volatility") + ylab("Return") +
  geom_point(data = all_portfolios, aes(x = Volatility, y = Return)) +
  geom_point(data = optimal_portfolio, aes(x = Vol, y = Ret), col = "red") +
  geom_point(data = data.frame(x = volatility, y = returns), aes(x = x, y = y), col = "blue") +
  geom_abline(slope = (optimal_portfolio$Ret - risk_free_rate) / optimal_portfolio$Vol - 0, intercept = risk_free_rate)

plot

Upvotes: 0

Views: 34

Answers (0)

Related Questions