UP | HOME |

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