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
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
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
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
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
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)
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]
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
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
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
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
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
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
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)
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())
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))