Example #1
0
    def test_find_balance_currencies(self):
        currencies = find_prices.find_balance_currencies(self.entries, None)
        self.assertEqual(
            {('QQQ', 'USD'), ('GBP', 'USD'), ('GBP', 'CAD'), ('USD', 'CAD')},
            currencies)

        currencies = find_prices.find_balance_currencies(
            self.entries, datetime.date(2015, 12, 1))
        self.assertEqual(
            {('XSP', 'CAD'), ('QQQ', 'USD'), ('GBP', 'USD'), ('GBP', 'CAD'),
             ('USD', 'CAD')}, currencies)

        currencies = find_prices.find_balance_currencies(
            self.entries, datetime.date(2015, 11, 1))
        self.assertEqual(
            {('QQQ', 'USD'), ('GBP', 'USD'), ('GBP', 'CAD'), ('USD', 'CAD')},
            currencies)

        currencies = find_prices.find_balance_currencies(
            self.entries, datetime.date(2015, 2, 1))
        self.assertEqual(set(), currencies)
Example #2
0
def get_price_jobs_at_date(entries: data.Entries,
                           date: Optional[datetime.date] = None,
                           inactive: bool = False,
                           undeclared_source: Optional[str] = None):
    """Get a list of prices to fetch from a stream of entries.

    The active holdings held on the given date are included.

    Args:
      entries: A list of beancount entries, the name of a file to process.
      date: A datetime.date instance.
      inactive: Include currencies with no balance at the given date. The default
        is to only include those currencies which have a non-zero balance.
      undeclared_source: A string, the name of the default source module to use to
        pull prices for commodities without a price source metadata on their
        Commodity directive declaration.
    Returns:
      A list of DatedPrice instances.

    """
    # Find the list of declared currencies, and from it build a mapping for
    # tickers for each (base, quote) pair. This is the only place tickers
    # appear.
    declared_triples = find_currencies_declared(entries, date)
    currency_map = {(base, quote): psources
                    for base, quote, psources in declared_triples}

    # Compute the initial list of currencies to consider.
    if undeclared_source:
        # Use the full set of possible currencies.
        cur_at_cost = find_prices.find_currencies_at_cost(entries)
        cur_converted = find_prices.find_currencies_converted(entries, date)
        cur_priced = find_prices.find_currencies_priced(entries, date)
        currencies = cur_at_cost | cur_converted | cur_priced
        log_currency_list("Currency held at cost", cur_at_cost)
        log_currency_list("Currency converted", cur_converted)
        log_currency_list("Currency priced", cur_priced)
        default_source = import_source(undeclared_source)
    else:
        # Use the currencies from the Commodity directives.
        currencies = set(currency_map.keys())
        default_source = None

    log_currency_list("Currencies in primary list", currencies)

    # By default, restrict to only the currencies with non-zero balances at the
    # given date.
    if not inactive:
        balance_currencies = find_prices.find_balance_currencies(entries, date)
        log_currency_list("Currencies held in assets", balance_currencies)
        currencies = currencies & balance_currencies

    log_currency_list("Currencies to fetch", currencies)

    # Build up the list of jobs to fetch prices for.
    jobs = []
    for base_quote in currencies:
        psources = currency_map.get(base_quote, None)
        base, quote = base_quote

        # If there are no sources, create a default one.
        if not psources:
            psources = [PriceSource(default_source, base, False)]

        jobs.append(DatedPrice(base, quote, date, psources))
    return sorted(jobs)