Estoy tratando de construir una cartera de arbitraje $\textbf{x}$ tal que $S^T\textbf{x} = 0$ y $A\textbf{x} \geq \textbf{0}$ , donde $A$ es la matriz de pagos en $t=1$ y $S$ es el precio en $t=0$ . No he podido hacerlo manualmente, así que he probado a utilizar las funciones contenidas en el limSolve y lpSolve paquetes en R sin éxito. Tampoco estoy seguro de cómo codificarlo yo mismo. Cualquier ayuda o pista sobre cómo proceder sería muy apreciada. Gracias.
Respuesta
¿Demasiados anuncios?Una prueba de las oportunidades de arbitraje con un LP consiste en minimizar el coste de creación de la cartera, con la restricción de que la cartera no pierda dinero en ningún estado del mundo. (Observe que en su formulación falta el objetivo real; sólo enumera las restricciones). Si encuentra una cartera que tiene un coste negativo (es decir, le pagan por mantenerla), pero nunca pierde dinero, ha encontrado una cartera de arbitraje. O si encuentra una cartera con coste cero, pero sin posibilidad de pérdidas y con al menos un pago positivo, ha encontrado una oportunidad de arbitraje. Si encuentra una cartera de arbitraje, entonces, sin restricciones, normalmente encontrará infinitas. Esto debería ser intuitivo: si se tiene una cartera de coste cero, pero sólo con pagos no negativos, se pueden multiplicar todas las ponderaciones por alguna constante y seguir teniendo una cartera de arbitraje. Además, sin restricciones, una cartera de arbitraje con coste negativo será ilimitada.
Haciendo esto en R:
A <- matrix(c(2, 1, 0, 3, 1,
1, 1, 1, 2, 1,
0, 1, 2, 1, 0), byrow = TRUE, nrow = 3)
S <- c(1, 1, 1, 2, 1/3)
library("Rglpk")
bounds <- list(lower = list(ind = 1:5, val = rep(-Inf, 5)))
lp.sol <- Rglpk_solve_LP(S,
mat = A,
dir = rep(">=", 3),
rhs = c(0, 0, 0),
bounds = bounds,
control = list(canonicalize_status = FALSE,
verbose = TRUE))
## [....]
## LP HAS UNBOUNDED PRIMAL SOLUTION
Eso no es demasiado útil porque sólo te dice que hay una oportunidad de arbitraje. Así que añadimos restricciones: una posición negativa no puede exceder de -1.
bounds <- list(lower = list(ind = 1:5, val = rep(-1, 5)))
lp.sol <- Rglpk_solve_LP(S,
mat = A,
dir = rep(">=", 3),
rhs = c(0, 0, 0),
bounds = bounds)
sum(lp.sol$solution*S)
## [1] -1
A %*% lp.sol$solution
## [,1]
## [1,] 0
## [2,] 3
## [3,] 0
Ahora tiene una cartera de coste negativo (es decir, recibe 1 por crear la cartera). Para hacerla de coste cero, inviertes esos ingresos en un activo:
x <- lp.sol$solution
x[2] <- x[2] + 1/S[2]
sum(x*S)
## [1] 0
A %*% x
## [,1]
## [1,] 1
## [2,] 4
## [3,] 1
Ahora tienes una cartera con coste cero y con unos beneficios estrictamente positivos.
Como alternativa, puede utilizar otro solucionador numérico para resolver directamente el modelo de optimización. He aquí un ejemplo. (Revelación: soy el encargado de mantener los paquetes NMOF
y neighbours
.) Es más conveniente trabajar con devoluciones:
R <- t(t(A)/S) - 1
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 0 -1 0.5 2
## [2,] 0 0 0 0.0 2
## [3,] -1 0 1 -0.5 -1
library("NMOF") ## https://github.com/enricoschumann/NMOF
library("neighbours") ## https://github.com/enricoschumann/neighbours
Ahora maximizamos directamente la ganancia media, digamos. (La implementación que utilizo minimiza, así que multiplico por -1).
max_payoff <- function(x, R, S)
-sum(R %*% x) + ## => maximize average payoff
-10*sum(pmin(R %*% x, 0)) ## => penalty for negative state returns
nb <- neighbourfun(-1, 5, length = 5, stepsize = 5/100)
ta.sol <- LSopt(max_payoff,
list(neighbour = nb,
x0 = rep(0, length(S)),
nI = 5000),
R = R, S = S)
round(ta.sol$xbest, 3) ## the portfolio
## [1] -1.00 -1.00 0.75 -1.00 2.25
round(R %*% ta.sol$xbest, 1) ## the state returns
## [,1]
## [1,] 2.2
## [2,] 4.5
## [3,] 0.0
La cartera en acciones:
x <- round(ta.sol$xbest/S, 3)
sum(x*S)
## [1] 0
A %*% x
## [,1]
## [1,] 2.25
## [2,] 4.50
## [3,] 0.00