piecash.core.factories — Python interface to GnuCash documents 0.14.1 documentation

# Source code for piecash.core.factories

    # coding=utf-8
    from __future__ import unicode_literals

    import yahoo_finance

    from .commodity import GncCommodityError
    from .._common import GnucashException

    def create_stock_accounts(cdty, broker_account, income_account=None, income_account_types="D/CL/I"):
        """Create the multiple accounts used to track a single stock, ie:

        - broker_account/stock.mnemonic

        and the following accounts depending on the income_account_types argument

        - D = Income/Dividend Income/stock.mnemonic
        - CL = Income/Cap Gain (Long)/stock.mnemonic
        - CS = Income/Cap Gain (Short)/stock.mnemonic
        - I = Income/Interest Income/stock.mnemonic

        Args:
            broker_account (:class:`piecash.core.account.Account`): the broker account where the account holding
            the stock is to be created
            income_account (:class:`piecash.core.account.Account`): the income account where the accounts holding
            the income related to the stock are to be created
            income_account_types (str): "/" separated codes to drive the creation of income accounts

        Returns:
            :class:`piecash.core.account.Account`: a tuple with the account under the broker_account where the stock is held
            and the list of income accounts.
        """
        if cdty.namespace == "CURRENCY":
            raise GnucashException("{} is a currency ! You can't create stock_accounts for currencies".format(cdty))

        from .account import Account

        symbol = cdty.mnemonic
        try:
            acc = broker_account.children(name=symbol)
        except KeyError:
            acc = Account(symbol, "STOCK", cdty, broker_account)

        inc_accounts = []
        if income_account:
            cur = cdty.base_currency

            for inc_acc in income_account_types.split("/"):
                sub_account_name = {
                    "D": "Dividend Income",
                    "CL": "Cap Gain (Long)",
                    "CS": "Cap Gain (Short)",
                    "I": "Interest Income",
                }[inc_acc]
                try:
                    sub_acc = income_account.children(name=sub_account_name)
                except KeyError:
                    sub_acc = Account(sub_account_name, "INCOME", cur.base_currency, income_account)
                try:
                    cdty_acc = sub_acc.children(name=symbol)
                except KeyError:
                    cdty_acc = Account(symbol, "INCOME", cur, sub_acc)
                inc_accounts.append(cdty_acc)

        return acc, inc_accounts

    def create_currency_from_ISO(isocode):
        """
        Factory function to create a new currency from its ISO code

        Args:
            isocode (str): the ISO code of the currency (e.g. EUR for the euro)

        Returns:
            :class:`Commodity`: the currency as a commodity object
        """
        from .commodity import Commodity

        # if self.get_session().query(Commodity).filter_by(isocode=isocode).first():
        #     raise GncCommodityError("Currency '{}' already exists".format(isocode))

        from .currency_ISO import ISO_currencies

        cur = ISO_currencies.get(isocode)

        if cur is None:
            raise ValueError("Could not find the ISO code '{}' in the ISO table".format(isocode))

        # create the currency
        cdty = Commodity(mnemonic=cur.mnemonic,
                         fullname=cur.currency,
                         fraction=10 ** int(cur.fraction),
                         cusip=cur.cusip,
                         namespace="CURRENCY",
                         quote_flag=1,
                         )

        # self.gnc_session.add(cdty)
        return cdty

    def create_stock_from_symbol(symbol, book=None):
        """
        Factory function to create a new stock from its symbol. The ISO code of the quoted currency of the stock is
        stored in the slot "quoted_currency".

        Args:
            symbol (str): the symbol for the stock (e.g. YHOO for the Yahoo! stock)

        Returns:
            :class:`Commodity`: the stock as a commodity object

        .. note::
           The information is gathered from the yahoo-finance package
           The default currency in which the quote is traded is stored in a slot 'quoted_currency'

        .. todo::
           use 'select * from yahoo.finance.sectors' and 'select * from yahoo.finance.industry where id ="sector_id"'
           to retrieve name of stocks and allow therefore the creation of a stock by giving its "stock name" (or part of it).
           This could also be used to retrieve all symbols related to the same company
        """
        from .commodity import Commodity

        share = yahoo_finance.Share(symbol).data_set
        currency = share["Currency"]
        if not currency:
            raise GncCommodityError("Can't find information on symbol '{}'".format(symbol))

        stock = Commodity(mnemonic=symbol,
                          fullname=share["Name"],
                          fraction=10000,
                          namespace=share["StockExchange"].upper(),
                          quote_flag=1,
                          )
        stock["quoted_currency"] = share["Currency"]

        if book:
            book.session.add(stock)

        return stock

    def single_transaction(post_date,
                           enter_date,
                           description,
                           value,
                           from_account,
                           to_account):
        from . import Transaction, Split
        # currency is derived from "from_account" (as in GUI)
        currency = from_account.commodity
        # currency of other destination account should be identical (as only one value given)
        assert currency == to_account.commodity, "Commodities of accounts should be the same"
        tx = Transaction(
            currency=currency,
            post_date=post_date,
            enter_date=enter_date,
            description=description,
            splits=[
                Split(account=from_account, value=-value),
                Split(account=to_account, value=value),
            ])
        return tx