Source code for finalynx.portfolio.envelope

from datetime import date
from enum import Enum
from typing import Any
from typing import Dict
from typing import List
from typing import Optional

from dateutil.relativedelta import relativedelta  # type: ignore

from .line import Line


[docs]class EnvelopeState(Enum): """Depending on the date, an envelope can be at a certain state (locked, heavily taxed, free, etc).""" UNKNOWN = "Unknown" CLOSED = "Closed" LOCKED = "Locked" TAXED = "Taxed" FREE = "Free"
[docs]class Envelope: """Represents an investment envelope or account (e.g. PEA, Assurance Vie, ...).""" def __init__( self, name: str, code: str, date_created: Optional[date] = None, date_unlock: Optional[date] = None, date_untax: Optional[date] = None, key: Optional[str] = None, ): """ This class represents any investment envelope or account (e.g. PEA, Assurance Vie, CTO, ...) and can be used to :param name: The envelope name (can also act as the `key` if the key is not set), will be displayed in the console and webdashboard :param code: The envelope name in a short version (recommended 3 characters), will be displayed when rendering each line to indicate each line's envelope. :param date_created: Accepts a `date` object to indicate when this envelope was opened. :param date_unlock: Accepts a `date` object to indicate when this envelope will be unlocked. For instance, a PEA will be unlocked 5 years after creation as required by law. :param date_untax: Accepts a `date` object to indicate when this envelope will no longer have higher-than-usual tax rates. For instance, a French Assurance Vie is highly taxed for the first 8 years after creation date, and then changes to a better tax rate. :param key: If you want to set a different name here from Finary's name, set the Finary name in this `key` parameter. The field `name` will be used when displaying the envelope in Finalynx. """ self.name = name self.code = code self.date_created = date_created if date_created else date(1900, 1, 1) self.date_unlock = date_unlock if date_unlock else self.date_created self.date_untax = date_untax if date_untax else self.date_unlock self.key = key if not (self.date_created <= self.date_unlock <= self.date_untax): raise ValueError("Envelope dates must be ordered by created <= unlock <= untax") self.lines: List[Line] = []
[docs] def get_state(self, date: date) -> EnvelopeState: """:return: The state of the envelope at the specified `date` based on the instance's creation, unlock, and untax dates.""" if date < self.date_created: return EnvelopeState.CLOSED elif date < self.date_unlock: return EnvelopeState.LOCKED elif date < self.date_untax: return EnvelopeState.TAXED else: return EnvelopeState.FREE
[docs] def to_dict(self) -> Dict[str, Any]: return { "name": self.name, "code": self.code, "date_created": self.date_created.isoformat(), "date_unlock": self.date_unlock.isoformat(), "date_untax": self.date_untax.isoformat(), }
[docs] @staticmethod def from_dict(dict: Dict[str, Any]) -> "Envelope": return Envelope( dict["name"], dict["code"], date.fromisoformat(dict["date_created"]), date.fromisoformat(dict["date_unlock"]), date.fromisoformat(dict["date_untax"]), )
[docs]class PEA(Envelope): """Handy shortcut to quickly define a PEA (automatically sets 5-years locked).""" def __init__(self, name: str, code: str, date_created: date, key: Optional[str] = None): """Declare a PEA (locked for 5 years) with: :param name: Name of your account. :param code: Short name of your account (3 characters recommended). :param date_created: A `date` instance of the account creation date. :param key: Optional, if you want to use a different name in Finalynx than in Finary. See `Envelope`'s documentation for additional details. """ date_unlock = date_created + relativedelta(years=5) super().__init__(name, code, date_created, date_unlock, date_unlock, key=key)
[docs]class PEE(Envelope): """Handy shortcut to quickly define a PEE (automatically sets 5-years locked).""" def __init__( self, name: str, code: str, date_created: date, date_unlock: Optional[date] = None, key: Optional[str] = None ): """Declare a PEE (locked for 5 years) with: :param name: Name of your account. :param code: Short name of your account (3 characters recommended). :param date_created: A `date` instance of the account creation date. :param date_unlock: A `date` instance of the account unlock date, defaults to 5 years. :param key: Optional, if you want to use a different name in Finalynx than in Finary. See `Envelope`'s documentation for additional details. """ if not date_unlock: date_unlock = date_created + relativedelta(years=5) super().__init__(name, code, date_created, date_unlock, date_unlock, key=key)
[docs]class AV(Envelope): """Handy shortcut to quickly define a PEA (automatically sets 8-years taxed).""" def __init__(self, name: str, code: str, date_created: date, key: Optional[str] = None): """Declare an Assurance Vie (taxed for 8 years) with: :param name: Name of your account. :param code: Short name of your account (3 characters recommended). :param date_created: A `date` instance of the account creation date. :param key: Optional, if you want to use a different name in Finalynx than in Finary. See `Envelope`'s documentation for additional details. """ date_untax = date_created + relativedelta(years=8) super().__init__(name, code, date_created, date_created, date_untax, key=key)
[docs]class PER(Envelope): """Handy shortcut to quickly define a PER (locked until retirement).""" def __init__(self, name: str, code: str, date_created: date, date_retirement: date, key: Optional[str] = None): """Declare a PER (locked until retirement) with: :param name: Name of your account. :param code: Short name of your account (3 characters recommended). :param date_created: A `date` instance of the account creation date. :param date_retirement: A `date` instance of your expected retirement date. :param key: Optional, if you want to use a different name in Finalynx than in Finary. See `Envelope`'s documentation for additional details. """ super().__init__(name, code, date_created, date_retirement, date_retirement, key=key)