Source code for woob.capabilities.bank.wealth

# Copyright(C) 2010-2016 Romain Bignon
#
# This file is part of woob.
#
# woob is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# woob is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with woob. If not, see <http://www.gnu.org/licenses/>.

# flake8: compatible

from woob.capabilities.base import BaseObject, DecimalField, Enum, EnumField, Field, IntField, StringField
from woob.capabilities.date import DateField

from .base import Account, CapBank


__all__ = [
    "PerVersion",
    "PerProviderType",
    "Per",
    "Investment",
    "Pocket",
    "MarketOrderType",
    "MarketOrderDirection",
    "MarketOrderPayment",
    "MarketOrder",
    "CapBankWealth",
]


[docs]class PerVersion(Enum): PERIN = "perin" # "PER individuel", subscribed by the account holder PERCOL = "percol" # "PER collectif", subscribed by the employer for all employees PERCAT = "percat" # "PER catégoriel", subscribed by the employer for a category of employees (for example managers)
[docs]class PerProviderType(Enum): BANK = "bank" INSURER = "insurer"
[docs]class Per(Account): """ Account type dedicated to PER retirement savings plans. """ version = EnumField("Version of PER", PerVersion) provider_type = EnumField("Type of account provider", PerProviderType)
[docs]class Investment(BaseObject): """ Investment in a financial market. """ CODE_TYPE_ISIN = "ISIN" CODE_TYPE_AMF = "AMF" label = StringField("Label of stocks") code = StringField("Identifier of the stock") code_type = StringField("Type of stock code (ISIN or AMF)") stock_symbol = StringField("Alternative identifier of the stock (different from ISIN)") stock_market = StringField("Stock market related to the stock") description = StringField("Short description of the stock") quantity = DecimalField("Quantity of stocks") unitprice = DecimalField("Buy price of one stock") unitvalue = DecimalField("Current value of one stock") valuation = DecimalField("Total current valuation of the Investment") vdate = DateField("Value date of the valuation amount") diff = DecimalField("Difference between the buy cost and the current valuation") diff_ratio = DecimalField("Difference in ratio (1 meaning 100%) between the buy cost and the current valuation") portfolio_share = DecimalField("Ratio (1 meaning 100%) of the current amount relative to the total") performance_history = Field("History of the performances of the stock (key=years, value=diff_ratio)", dict) srri = IntField("Synthetic Risk and Reward Indicator of the stock (from 1 to 7)") asset_category = StringField("Category of the stock") recommended_period = StringField("Recommended investment period of the stock") # International original_currency = StringField("Currency of the original amount") original_valuation = DecimalField("Original valuation (in another currency)") original_unitvalue = DecimalField("Original unitvalue (in another currency)") original_unitprice = DecimalField("Original unitprice (in another currency)") original_diff = DecimalField("Original diff (in another currency)") def __repr__(self): return f"<Investment label={self.label!r} code={self.code!r} valuation={self.valuation!r}>" # compatibility alias @property def diff_percent(self): return self.diff_ratio @diff_percent.setter def diff_percent(self, value): self.diff_ratio = value
class PocketCondition(Enum): UNKNOWN = 0 DATE = 1 # If 'availability_date' has passed AVAILABLE = 2 RETIREMENT = 3 # the following conditions are used if : # 'acquisition_date' and 'transferability_date' are displayed on the website. # If 'acquisition_date' has not passed. DATE_WHEN_ACQUIRED = 4 # If 'acquisition_date' has passed and 'transferability_date' has not. DATE_WHEN_TRANSFERABLE = 5 # the following conditions are irrelevant, don't use them WEDDING = 6 DEATH = 7 INDEBTEDNESS = 8 DIVORCE = 9 DISABILITY = 10 BUSINESS_CREATION = 11 BREACH_EMPLOYMENT_CONTRACT = 12 UNLOCKING_EXCEPTIONAL = 13 THIRD_CHILD = 14 EXPIRATION_UNEMPLOYMENT = 15 PURCHASE_APARTMENT = 16
[docs]class Pocket(BaseObject): """ Pocket """ CONDITION_UNKNOWN = PocketCondition.UNKNOWN CONDITION_DATE = PocketCondition.DATE CONDITION_DATE_WHEN_ACQUIRED = PocketCondition.DATE_WHEN_ACQUIRED CONDITION_DATE_WHEN_TRANSFERABLE = PocketCondition.DATE_WHEN_TRANSFERABLE CONDITION_AVAILABLE = PocketCondition.AVAILABLE CONDITION_RETIREMENT = PocketCondition.RETIREMENT # the following conditions are irrelevant, don't use them CONDITION_WEDDING = PocketCondition.WEDDING CONDITION_DEATH = PocketCondition.DEATH CONDITION_INDEBTEDNESS = PocketCondition.INDEBTEDNESS CONDITION_DIVORCE = PocketCondition.DIVORCE CONDITION_DISABILITY = PocketCondition.DISABILITY CONDITION_BUSINESS_CREATION = PocketCondition.BUSINESS_CREATION CONDITION_BREACH_EMPLOYMENT_CONTRACT = PocketCondition.BREACH_EMPLOYMENT_CONTRACT CONDITION_UNLOCKING_EXCEPTIONAL = PocketCondition.UNLOCKING_EXCEPTIONAL CONDITION_THIRD_CHILD = PocketCondition.THIRD_CHILD CONDITION_EXPIRATION_UNEMPLOYMENT = PocketCondition.EXPIRATION_UNEMPLOYMENT CONDITION_PURCHASE_APARTMENT = PocketCondition.PURCHASE_APARTMENT label = StringField("Label of pocket") amount = DecimalField("Amount of the pocket") quantity = DecimalField("Quantity of stocks") availability_date = DateField("Availability date of the pocket") condition = EnumField("Withdrawal condition of the pocket", PocketCondition, default=CONDITION_UNKNOWN) investment = Field("Reference to the investment of the pocket", Investment)
[docs]class MarketOrderType(Enum): UNKNOWN = 0 MARKET = 1 """Order executed at the current market price""" LIMIT = 2 """Order executed with a maximum or minimum price limit""" TRIGGER = 3 """Order executed when the price reaches a specific value"""
[docs]class MarketOrderDirection(Enum): UNKNOWN = 0 BUY = 1 SALE = 2
[docs]class MarketOrderPayment(Enum): UNKNOWN = 0 CASH = 1 DEFERRED = 2
[docs]class MarketOrder(BaseObject): """ Market order """ # Important: a Market Order always corresponds to one (and only one) investment label = StringField("Label of the market order") # MarketOrder values unitprice = DecimalField("Value of the stock at the moment of the market order") unitvalue = DecimalField("Current value of the stock associated with the market order") ordervalue = DecimalField("Limit value or trigger value, only relevant if the order type is LIMIT or TRIGGER") currency = StringField("Currency of the market order - not always the same as account currency") quantity = DecimalField("Quantity of stocks in the market order") amount = DecimalField("Total amount that has been bought or sold") # MarketOrder additional information order_type = EnumField("Type of market order", MarketOrderType, default=MarketOrderType.UNKNOWN) direction = EnumField( "Direction of the market order (buy or sale)", MarketOrderDirection, default=MarketOrderDirection.UNKNOWN ) payment_method = EnumField( "Payment method of the market order", MarketOrderPayment, default=MarketOrderPayment.UNKNOWN ) date = DateField("Creation date of the market order") validity_date = DateField("Validity date of the market order") execution_date = DateField("Execution date of the market order (only for market orders that are completed)") state = StringField("Current state of the market order (e.g. executed)") code = StringField("Identifier of the stock related to the order") stock_symbol = StringField("Alternative identifier of the stock related to the order (different from ISIN)") stock_market = StringField("Stock market on which the order was executed")
[docs]class CapBankWealth(CapBank): """ Capability of bank websites to see investments and pockets. """
[docs] def iter_investment(self, account): """ Iter investment of a market account :param account: account to get investments :type account: :class:`Account` :rtype: iter[:class:`Investment`] :raises: :class:`AccountNotFound` """ raise NotImplementedError()
[docs] def iter_pocket(self, account): """ Iter pocket :param account: account to get pockets :type account: :class:`Account` :rtype: iter[:class:`Pocket`] :raises: :class:`AccountNotFound` """ raise NotImplementedError()
[docs] def iter_market_orders(self, account): """ Iter market orders :param account: account to get market orders :type account: :class:`Account` :rtype: iter[:class:`MarketOrder`] :raises: :class:`AccountNotFound` """ raise NotImplementedError()