Método FIFO sencillo con R
Método FIFO sencillo con R
El método FIFO se puede implementar de una forma sencilla cuando las cantidades son enteras y no alcanzan magnitudes muy elevadas. Por ejemplo, hemos comprado y vendido acciones en distintos momentos y hemos anotado los importes que han conllevado estas operaciones.
suppressMessages(library(data.table)) datos <- fread(text=" time,cantidad,valor 2021-12-31T15:40:00Z,-59,3099.57 2021-12-29T15:10:00Z,-667,9749.57 2021-12-29T14:51:00Z,-93,3560.98 2021-12-20T16:36:00Z,215,-3997.45 2021-12-20T16:33:00Z,100,-2006.34 2021-12-17T15:14:00Z,-252,8291.5 2021-12-16T19:36:00Z,-12,1006.8 2021-12-15T20:59:00Z,49,-1089.47 2021-12-15T19:40:00Z,70,-2978.58 2021-12-14T19:51:00Z,54,-987.53 2021-12-14T19:05:00Z,354,-1991.66 2021-12-14T19:01:00Z,60,-999.73 2021-12-13T16:48:00Z,160,-2986.36 2021-12-13T16:38:00Z,307,-3009.12 2021-12-13T16:36:00Z,629,-3001.6 2021-12-09T20:35:00Z,412,-3042.66 2021-12-06T14:42:00Z,-189,8725.79 2021-12-06T14:38:00Z,-5,465.18 2021-12-03T15:37:00Z,59,-2994.76 2021-12-03T15:34:00Z,375,-3031.54 2021-11-30T16:35:00Z,384,-1000.94 2021-11-26T17:23:00Z,33,-998.62 2021-11-17T20:04:00Z,93,-3032.84 2021-11-15T16:23:00Z,46,-1974.04 2021-11-15T14:48:00Z,123,-2000.93 2021-11-12T14:56:00Z,5,-447.2 ")
Las acciones que quedan en nuestra cartera se calculan muy fácilmente. Basta con sumar las cantidades involucradas.
(accionesencartera <- sum(datos$cantidad))
[1] 2251
Deseamos calcular cuándo hemos vendido unas determinadas acciones siguiendo el método fifo. Procedemos a segmentar la base según si han sido compras o ventas cada registro. Cambiamos el nombre de las columnas. Asimismo, procedemos a calcular el precio de cada unidad.
datos <- datos[order(time)] # Ordenamos según el tiempo datos$precio <- -datos$valor/datos$cantidad # Precio de cada acción ## Compras datoscompras <- datos[cantidad > 0,.(time,cantidad,precio)] names(datoscompras) <- paste0(names(datoscompras),"_compras") ## Ventas datosventas <- datos[cantidad < 0,.(time,cantidad,precio)] names(datosventas) <- paste0(names(datosventas),"_ventas")
Como son cantidades enteras, procedemos a replicar cada registro tantas veces como la cantidad que contenga.
repetir <- rep(seq(1:nrow(datoscompras)), abs(datoscompras$cantidad)) datoscomprasexpandido <- datoscompras[repetir] repetir <- rep(seq(1:nrow(datosventas)), abs(datosventas$cantidad)) datosventasexpandido <- datosventas[repetir]
Asignamos una secuencia consecutiva a cada acción comprada o vendida, ya que están ordenadas temporalmente.
datoscomprasexpandido$registro <- 1:nrow(datoscomprasexpandido) datosventasexpandido$registro <- 1:nrow(datosventasexpandido)
Juntamos ambas bases de datos acorde al registro de cada acción y calculamos el beneficio de su venta. En total se han vendido 1277 acciones.
datoscompraventa <- merge(datosventasexpandido,datoscomprasexpandido,all.x=TRUE) datoscompraventa$beneficio <- datoscompraventa$precio_ventas- datoscompraventa$precio_compras datoscompraventa[,c("registro","time_compras","time_ventas","beneficio")]
registro time_compras time_ventas beneficio 1: 1 2021-11-12 14:56:00 2021-12-06 14:38:00 3.59600 2: 2 2021-11-12 14:56:00 2021-12-06 14:38:00 3.59600 3: 3 2021-11-12 14:56:00 2021-12-06 14:38:00 3.59600 4: 4 2021-11-12 14:56:00 2021-12-06 14:38:00 3.59600 5: 5 2021-11-12 14:56:00 2021-12-06 14:38:00 3.59600 --- 1273: 1273 2021-12-09 20:35:00 2021-12-31 15:40:00 45.14999 1274: 1274 2021-12-09 20:35:00 2021-12-31 15:40:00 45.14999 1275: 1275 2021-12-09 20:35:00 2021-12-31 15:40:00 45.14999 1276: 1276 2021-12-09 20:35:00 2021-12-31 15:40:00 45.14999 1277: 1277 2021-12-09 20:35:00 2021-12-31 15:40:00 45.14999
Si deseamos obtener los resultados por días, creamos unas nuevas variables con esa información. Para cada día de ventas obtenemos el número de acciones y el beneficio de las acciones que ese obtuvieron en la fecha de compra correspondiente.
datoscompraventa$date_compras <- as.Date(datoscompraventa$time_compras) datoscompraventa$date_ventas <- as.Date(datoscompraventa$time_ventas) datoscompraventa[,.(n=.N,beneficio=round(sum(beneficio),2)),by=c("date_ventas","date_compras")]
date_ventas date_compras n beneficio 1: 2021-12-06 2021-11-12 5 17.98 2: 2021-12-06 2021-11-15 169 3827.46 3: 2021-12-06 2021-11-17 20 271.14 4: 2021-12-16 2021-11-17 12 615.47 5: 2021-12-17 2021-11-17 61 17.79 6: 2021-12-17 2021-11-26 33 87.17 7: 2021-12-17 2021-11-30 158 4786.79 8: 2021-12-29 2021-11-30 226 4915.95 9: 2021-12-29 2021-12-03 434 317.50 10: 2021-12-29 2021-12-09 100 723.19 11: 2021-12-31 2021-12-09 59 2663.85
Si juntamos ambas bases de datos en función de las compras, salen las ventas ya realizadas y las compras que aún quedan sin vender.
datoscompraventa2 <- merge(datoscomprasexpandido, datosventasexpandido,all.x=TRUE) datoscompraventa2$beneficio <- datoscompraventa2$precio_ventas- datoscompraventa2$precio_compras datoscompraventa2$date_compras <- as.Date(datoscompraventa2$time_compras) datoscompraventa2$date_ventas <- as.Date(datoscompraventa2$time_ventas) datoscompraventa2[,.(n=.N,beneficio=round(sum(beneficio),2)),by=c("date_ventas","date_compras")]
date_ventas date_compras n beneficio 1: 2021-12-06 2021-11-12 5 17.98 2: 2021-12-06 2021-11-15 169 3827.46 3: 2021-12-06 2021-11-17 20 271.14 4: 2021-12-16 2021-11-17 12 615.47 5: 2021-12-17 2021-11-17 61 17.79 6: 2021-12-17 2021-11-26 33 87.17 7: 2021-12-17 2021-11-30 158 4786.79 8: 2021-12-29 2021-11-30 226 4915.95 9: 2021-12-29 2021-12-03 434 317.50 10: 2021-12-29 2021-12-09 100 723.19 11: 2021-12-31 2021-12-09 59 2663.85 12: < 2021-12-09 253 NA 13: < 2021-12-13 1096 NA 14: < 2021-12-14 468 NA 15: < 2021-12-15 119 NA 16: < 2021-12-20 315 NA