""" prima.py — Cuánto se aleja del mercado lo que pagaste (o cobraste) por tu bitcoin. En una compra entre particulares (P2P) se paga algo más que el precio de mercado: esa diferencia es la prima. Aquí se compara el precio de cada compra o venta de bitcoin apuntada con el cierre de ese día (spot_btc.py): prima = importe / (cantidad × cierre del día) − 1 Sirve para dos cosas: ver de un vistazo lo que te costó cada compra frente al mercado, y cazar erratas (un importe con un cero de más, una cantidad mal copiada, una fecha equivocada). No cambia ninguna cifra de la cartera: el coste de una compra es lo que pagaste de verdad, con su prima. Se avisa de una operación cuando queda «lejos»: te salió más de un 15 % peor que el mercado, o más de un 5 % MEJOR (comprar por debajo del mercado, o vender por encima, es raro). Si la cifra es buena, se marca como revisada («prima_ok» en la operación) y deja de avisar. Una compra «estimada» tiene por importe el propio cierre del día, así que su prima es cero: de esas avisa «Para revisar», no esto. """ from __future__ import annotations from . import spot_btc EN_CONTRA = 0.15 # más de un 15 % peor que el mercado A_FAVOR = 0.05 # más de un 5 % mejor que el mercado TIPOS = ("Compra", "Venta") def es_bitcoin(activo: dict) -> bool: return activo.get("tipo") == "Cripto" and (activo.get("codigo") or "").lower() == "bitcoin" def de_movimientos(activos: list[dict], movimientos: list[dict], precios: list[dict]) -> dict[str, dict]: """{id de operación: {ref, dia, prima, lejos}} de las compras y ventas de bitcoin que tienen cantidad e importe y un cierre cercano con que comparar.""" bitcoins = {a["id"] for a in activos if es_bitcoin(a)} guardados: dict[str, list[dict]] = {} for p in precios: if p.get("activo") in bitcoins: guardados.setdefault(p["activo"], []).append(p) salida = {} for m in movimientos: if m["activo"] not in bitcoins or m["tipo"] not in TIPOS: continue cantidad, importe = float(m.get("cantidad") or 0), float(m.get("importe") or 0) if cantidad <= 0 or importe <= 0: continue ref, dia = spot_btc.precio(m["fecha"], guardados.get(m["activo"])) if not ref: continue prima = importe / (cantidad * ref) - 1 contra = prima if m["tipo"] == "Compra" else -prima # > 0: te salió peor que el mercado salida[m["id"]] = {"ref": ref, "dia": dia, "prima": round(prima, 4), "lejos": contra > EN_CONTRA or contra < -A_FAVOR} return salida