models.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. from decimal import Decimal
  2. from django.db import models
  3. class Valor(models.Model):
  4. """Un valor bursátil (acción, ETF...) de la cartera."""
  5. ticker = models.CharField(
  6. max_length=20, unique=True,
  7. help_text='Ticker según Yahoo Finance; en Bolsa española con sufijo .MC',
  8. )
  9. nombre = models.CharField(max_length=100)
  10. mercado = models.CharField(max_length=30, blank=True, help_text='p. ej. SIBE, NASDAQ')
  11. isin = models.CharField(max_length=12, blank=True)
  12. precio_actual = models.DecimalField(
  13. max_digits=12, decimal_places=4, null=True, blank=True,
  14. editable=False,
  15. )
  16. actualizado_en = models.DateTimeField(null=True, blank=True, editable=False)
  17. class Meta:
  18. verbose_name = 'valor'
  19. verbose_name_plural = 'valores'
  20. ordering = ['ticker']
  21. def __str__(self):
  22. return f'{self.ticker} - {self.nombre}'
  23. class Operacion(models.Model):
  24. COMPRA = 'C'
  25. VENTA = 'V'
  26. TIPOS = [
  27. (COMPRA, 'Compra'),
  28. (VENTA, 'Venta'),
  29. ]
  30. valor = models.ForeignKey(Valor, on_delete=models.CASCADE, related_name='operaciones')
  31. tipo = models.CharField('tipo de operación', max_length=1, choices=TIPOS)
  32. fecha = models.DateField()
  33. cantidad = models.DecimalField(max_digits=14, decimal_places=4)
  34. precio = models.DecimalField(
  35. max_digits=12, decimal_places=4,
  36. help_text='Precio unitario por acción',
  37. )
  38. comisiones = models.DecimalField(max_digits=10, decimal_places=2, default=Decimal('0'))
  39. class Meta:
  40. ordering = ['-fecha', '-pk']
  41. verbose_name = 'operación'
  42. def __str__(self):
  43. return f'{self.get_tipo_display()} {self.cantidad} {self.valor.ticker} ({self.fecha})'
  44. @property
  45. def importe(self):
  46. """Importe total de la operación, comisiones incluidas."""
  47. return (self.cantidad * self.precio).quantize(Decimal('0.01')) + self.comisiones
  48. class Dividendo(models.Model):
  49. valor = models.ForeignKey(Valor, on_delete=models.CASCADE, related_name='dividendos')
  50. fecha = models.DateField()
  51. bruto = models.DecimalField(max_digits=10, decimal_places=2)
  52. retencion = models.DecimalField(max_digits=10, decimal_places=2, default=Decimal('0'))
  53. class Meta:
  54. ordering = ['-fecha', '-pk']
  55. def __str__(self):
  56. return f'Dividendo {self.bruto} € {self.valor.ticker} ({self.fecha})'
  57. @property
  58. def neto(self):
  59. return self.bruto - self.retencion