Beispiel #1
0
    def filter(self, force=False, **kwargs):
        """Set and apply (if necessary) filters."""
        changed = False
        for filter_name, value in kwargs.items():
            if self._filters[filter_name].set(value):
                changed = True

        if not (changed or force):
            return

        self.entries = self.all_entries

        for filter_class in self._filters.values():
            self.entries = filter_class.apply(self.entries)

        self.root_account = realization.realize(self.entries,
                                                self.account_types)
        self.root_tree = Tree(self.entries)

        self._date_first, self._date_last = getters.get_min_max_dates(
            self.entries, (Transaction))
        if self._date_last:
            self._date_last = self._date_last + datetime.timedelta(1)

        if self._filters["time"]:
            self._date_first = self._filters["time"].begin_date
            self._date_last = self._filters["time"].end_date
Beispiel #2
0
    def _interval_tuples(self, interval, entries):
        """
        Calculates tuples of (begin_date, end_date) of length interval for the
        period in which entries contains Transactions.

        Args:
            interval: Either 'month' or 'year'

        Returns:
            [
                (begin_date, end_date),
                ...
            ]
        """
        date_first, date_last = getters.get_min_max_dates(entries,
                                                          (Transaction))

        if not date_first:
            return []

        interval_tuples = []
        while date_first <= date_last:
            next_date = get_next_interval(date_first, interval)
            interval_tuples.append((date_first, next_date))
            date_first = next_date

        return interval_tuples
Beispiel #3
0
    def filter(
        self,
        force: bool = False,
        account: str | None = None,
        filter: str | None = None,  # pylint: disable=redefined-builtin
        time: str | None = None,
    ) -> None:
        """Set and apply (if necessary) filters."""
        changed = self.filters.set(account=account, filter=filter, time=time)

        if not (changed or force):
            return

        self.entries = self.filters.apply(self.all_entries)

        self.root_account = realization.realize(self.entries,
                                                self.account_types)
        self.root_tree = Tree(self.entries)

        self._date_first, self._date_last = get_min_max_dates(
            self.entries, (Transaction, Price))
        if self._date_last:
            self._date_last = self._date_last + datetime.timedelta(1)

        if self.filters.time:
            self._date_first = self.filters.time.begin_date
            self._date_last = self.filters.time.end_date
Beispiel #4
0
    def filter(self, force=False, **kwargs):
        """Set and apply (if necessary) filters."""
        changed = False
        for filter_name, value in kwargs.items():
            if self._filters[filter_name].set(value):
                changed = True

        if not (changed or force):
            return

        self.entries = self.all_entries

        for filter_class in self._filters.values():
            self.entries = filter_class.apply(self.entries)

        self.root_account = realization.realize(self.entries,
                                                self.account_types)
        self.root_tree = Tree(self.entries)

        self._date_first, self._date_last = \
            getters.get_min_max_dates(self.entries, (Transaction))
        if self._date_last:
            self._date_last = self._date_last + datetime.timedelta(1)

        if self._filters['time']:
            self._date_first = self._filters['time'].begin_date
            self._date_last = self._filters['time'].end_date
Beispiel #5
0
    def _month_tuples(self, entries):
        """
        Calculates tuples of (month_begin, month_end) for the period in
        which entries contains Transactions.

        Returns:
            [
                (begin_date, end_date),
                ...
            ]
        """
        date_first, date_last = getters.get_min_max_dates(entries, (Transaction))

        def get_next_month(date_):
            month = (date_.month % 12) + 1
            year = date_.year + (date_.month + 1 > 12)
            return date(year, month, 1)

        date_first = date(date_first.year, date_first.month, 1)
        date_last = get_next_month(date_last) - timedelta(days=1)

        month_tuples = []
        while date_first <= date_last:
            month_tuples.append((date_first, get_next_month(date_first) - timedelta(days=1)))
            date_first = get_next_month(date_first)

        return month_tuples
Beispiel #6
0
 def interval_ends(self,
                   interval: date.Interval) -> Iterable[datetime.date]:
     """Generator yielding dates corresponding to interval boundaries."""
     first, last = get_min_max_dates(self.entries, (Transaction, Price))
     if last:
         last = last + datetime.timedelta(1)
     if not first or not last:
         return []
     return date.interval_ends(first, last, interval)
Beispiel #7
0
    def interval_totals(self, interval, account_name, accumulate=False):
        """Renders totals for account (or accounts) in the intervals."""
        if isinstance(account_name, str):
            names = [account_name]
        else:
            names = account_name

        interval_tuples = self._interval_tuples(interval, self.entries)
        date_first, _ = getters.get_min_max_dates(self.entries, (Transaction))
        return [{
            'begin_date': begin_date,
            'end_date': end_date,
            'totals': self._total_balance(
                names, begin_date if not accumulate else date_first, end_date),
        } for begin_date, end_date in interval_tuples]
Beispiel #8
0
    def _apply_filters(self):
        self.entries = self.all_entries

        for filter_class in self.filters.values():
            self.entries = filter_class.apply(self.entries, self.options)

        self.root_account = realization.realize(self.entries, self.account_types)

        self.date_first, self.date_last = getters.get_min_max_dates(self.entries, (Transaction))
        if self.date_last:
            self.date_last = self.date_last + datetime.timedelta(1)

        if self.filters["time"]:
            self.date_first = self.filters["time"].begin_date
            self.date_last = self.filters["time"].end_date
Beispiel #9
0
    def _apply_filters(self):
        self.entries = self.all_entries

        for filter in self.filters.values():
            self.entries = filter.apply(self.entries, self.options)

        self.root_account = realization.realize(self.entries,
                                                self.account_types)

        self.date_first, self.date_last = \
            getters.get_min_max_dates(self.entries, (Transaction))

        if self.filters['time']:
            self.date_first = self.filters['time'].begin_date
            self.date_last = self.filters['time'].end_date
Beispiel #10
0
    def _real_accounts(self, account_name, begin_date=None, end_date=None):
        """
        Returns the realization.RealAccount instances for account_name, and their entries
        clamped by the optional begin_date and end_date.

        Returns:
            realization.RealAccount instances
        """
        begin_date_, end_date_ = getters.get_min_max_dates(self.entries, (Transaction))
        if begin_date:
            begin_date_ = begin_date
        if end_date:
            end_date_ = end_date

        entries, index = summarize.clamp_opt(self.entries, begin_date_, end_date_ + timedelta(days=1),
                                                     self.options_map)

        real_accounts = realization.get(realization.realize(entries, self.account_types), account_name)

        return real_accounts
Beispiel #11
0
    def _interval_tuples(self, interval, entries):
        """
        Calculates tuples of (begin_date, end_date) of length interval for the period in
        which entries contains Transactions.

        Args:
            interval: Either 'month' or 'year'

        Returns:
            [
                (begin_date, end_date),
                ...
            ]
        """
        date_first, date_last = getters.get_min_max_dates(
            entries, (Transaction))

        if not date_first:
            return []

        def get_next_interval(date_, interval):
            if interval == 'year':
                return date(date_.year + 1, 1, 1)
            elif interval == 'month':
                month = (date_.month % 12) + 1
                year = date_.year + (date_.month + 1 > 12)
                return date(year, month, 1)
            else:
                raise NotImplementedError

        date_first = date(date_first.year, date_first.month, 1)
        date_last = get_next_interval(date_last, interval) - timedelta(days=1)

        interval_tuples = []
        while date_first <= date_last:
            interval_tuples.append(
                (date_first,
                 get_next_interval(date_first, interval) - timedelta(days=1)))
            date_first = get_next_interval(date_first, interval)

        return interval_tuples
Beispiel #12
0
    def _interval_tuples(self, interval, entries):
        """
        Calculates tuples of (begin_date, end_date) of length interval for the period in
        which entries contains Transactions.

        Args:
            interval: Either 'month' or 'year'

        Returns:
            [
                (begin_date, end_date),
                ...
            ]
        """
        date_first, date_last = getters.get_min_max_dates(entries, (Transaction))

        if not date_first:
            return []

        def get_next_interval(date_, interval):
            if interval == 'year':
                return date(date_.year + 1, 1, 1)
            elif interval == 'month':
                month = (date_.month % 12) + 1
                year = date_.year + (date_.month + 1 > 12)
                return date(year, month, 1)
            else:
                raise NotImplementedError

        date_first = date(date_first.year, date_first.month, 1)
        date_last = get_next_interval(date_last, interval) - timedelta(days=1)

        interval_tuples = []
        while date_first <= date_last:
            interval_tuples.append((date_first, get_next_interval(date_first, interval) - timedelta(days=1)))
            date_first = get_next_interval(date_first, interval)

        return interval_tuples
Beispiel #13
0
    def __init__(
        self,
        ledger: FavaLedger,
        account: str | None = None,
        filter: str | None = None,  # pylint: disable=redefined-builtin
        time: str | None = None,
    ):
        self.ledger = ledger
        self.filters = Filters(ledger.options, ledger.fava_options)
        self.filters.set(account=account, filter=filter, time=time)
        self.entries = self.filters.apply(ledger.all_entries)

        self.root_account = realization.realize(self.entries,
                                                ledger.account_types)
        self.root_tree = Tree(self.entries)

        self._date_first, self._date_last = get_min_max_dates(
            self.entries, (Transaction, Price))
        if self._date_last:
            self._date_last = self._date_last + datetime.timedelta(1)

        if self.filters.time:
            self._date_first = self.filters.time.begin_date
            self._date_last = self.filters.time.end_date
Beispiel #14
0
 def test_get_min_max_dates(self):
     entries = loader.load_string(TEST_INPUT)[0]
     mindate, maxdate = getters.get_min_max_dates(entries)
     self.assertEqual(datetime.date(2012, 2, 1), mindate)
     self.assertEqual(datetime.date(2014, 2, 1), maxdate)
Beispiel #15
0
def toc():
    entries_no_open_close = [
        entry for entry in app.entries
        if not isinstance(entry, (data.Open, data.Close))
    ]
    if entries_no_open_close:
        mindate, maxdate = None, None
    else:
        mindate, maxdate = getters.get_min_max_dates(entries_no_open_close)

    def view_url(name, **kw):
        return app.router.build(name, path=DEFAULT_VIEW_REDIRECT, **kw)

    viewboxes = []
    if app.args.view:
        # Render a single link to a view, the view selected from --view.
        viewboxes.append(('selected', None, [('/', 'Selected View')]))
    else:
        # Render a menu of various views.

        # Global views.
        viewboxes.append(
            ('global', None, [(view_url('all'), 'All Transactions')]))

        # By year views.
        viewboxes.append(
            ('year', 'By Year', [(view_url('year',
                                           year=year), 'Year {}'.format(year))
                                 for year in reversed(app.active_years)]))

        # By tag views.
        viewboxes.append(
            ('tag', 'Tags', [(view_url('tag', tag=tag), '#{}'.format(tag))
                             for tag in getters.get_all_tags(app.entries)]))

        # By component.
        components = getters.get_account_components(app.entries)
        viewboxes.append(
            ('component', 'Component', [(view_url('component',
                                                  component=component),
                                         '{}'.format(component))
                                        for component in components]))

        # Note: With the filtering language, payees will be added and much many more
        # options. Don't worry.

    oss = io.StringIO()
    oss.write('<div id="viewboxes">\n')
    for cssid, title, viewbox in viewboxes:
        view_items = [
            '<li><a href="{}">{}</a></li>'.format(url, title)
            for url, title in viewbox
        ]
        oss.write("""
          <div id="{cssid}" class="viewbox">
            {title}
            <ul>
              {view_items}
            </ul>
          </div>
          <hr/>
        """.format(cssid=cssid,
                   title='<h2>{}</h2>'.format(title) if title else '',
                   view_items='\n'.join(view_items)))
    oss.write('</div> <!-- viewboxes -->\n')

    return render_global(pagetitle="Table of Contents",
                         contents=oss.getvalue())
Beispiel #16
0
def main():
    # Parse and validate options.
    parser = argparse.ArgumentParser(description=__doc__.strip())
    parser.add_argument('--verbose',
                        '-v',
                        action='store_true',
                        help='Verbose mode')
    args = parser.parse_args()
    if args.verbose:
        logging.basicConfig(level=logging.DEBUG,
                            format='%(levelname)-8s: %(message)s')

    # Load the example file.
    examples_dir = path.dirname(path.abspath(__file__))
    filename = path.join(examples_dir, 'example.beancount')
    entries, _, options_map = loader.load_file(filename, log_errors=print)

    # Figure out the number of years in action.
    year_min, year_max = [
        date.year
        for date in getters.get_min_max_dates(entries, data.Transaction)
    ]

    # Figure out dates for the last month and last quarter intervals.
    date_last = entries[-1].date
    date_one_month = date_last - datetime.timedelta(days=30)
    date_three_months = date_last - datetime.timedelta(days=90)

    # Create a list of periods to compute the returns over.
    periods = [(str(year), datetime.date(
        year, 1, 1), min(date_last, datetime.date(year + 1, 1, 1)))
               for year in range(year_min, year_max + 1)] + [
                   ('Last month', date_one_month, date_last),
                   ('Three month', date_three_months, date_last),
               ]

    # Loop over accounts with investments in them. This is defined by the user.
    FORMAT = "  {:<16}  {:10} -> {:10}: {:>12.2%} {:>12.2%}"
    for account_name, assets_regexp, intflows_regexp, internalize_regexp in [
        ('ETrade', 'Assets:US:ETrade', '(Income:US:ETrade|Expenses:Financial)',
         None),
        ('ETrade (no cash)', 'Assets:US:ETrade:[A-Z]+$',
         '(Income:US:ETrade|Expenses:Financial)',
         'Income:US:ETrade:Dividends'),
        ('Vanguard', 'Assets:US:Vanguard',
         '(Income:US:ETrade|Expenses:Financial)', None)
    ]:

        # Print a header.
        print()
        print("Returns for {} account".format(account_name))
        print(
            FORMAT.replace('.2%', '').format('Period', 'Begin', 'End', 'Total',
                                             'Annualized'))

        # Loop over each period.
        for period_name, date_begin, date_end in periods:
            # Compute the returns.
            total_returns, dates, int_entries = returns.compute_returns_with_regexp(
                entries,
                options_map,
                'Assets:Internalized',
                assets_regexp,
                intflows_regexp,
                internalize_regexp,
                date_begin=date_begin,
                date_end=date_end)

            # Annualize the returns for the period.
            annual_returns = returns.annualize_returns(total_returns,
                                                       date_begin, date_end)

            print(
                FORMAT.format(period_name, str(date_begin), str(date_end),
                              total_returns['USD'] - 1,
                              annual_returns['USD'] - 1))