beancount.plugins

Example plugins for filtering transactions.

These are various examples of how to filter entries in various creative ways.

IMPORTANT: These are not meant to tbe complete features, rather just experiments in problem-solving using Beancount, work-in-progress that can be selectively installed via a –plugin option, or one-offs to answer questions on the mailing-list.

beancount.plugins.auto

A plugin of plugins which triggers are all the automatic and lax plugins.

In a sense, this is the inverse of “pedantic.” This is useful when doing some types of quick and dirty tests. You can just import the “auto” plugin. Put that in a macro.

Also see: the ‘pedantic’ plugin.

beancount.plugins.auto_accounts

This module automatically inserts Open directives for accounts not opened (at the date of the first entry) and automatically removes open directives for unused accounts. This can be used as a convenience for doing demos, or when setting up your initial transactions, as an intermediate step.

beancount.plugins.auto_accounts.auto_insert_open(entries, unused_options_map)

Insert implicitly defined prices from Transactions.

Explicit price entries are simply maintained in the output list. Prices from postings with costs or with prices from Transaction entries are synthesized as new Price entries in the list of entries output.

Parameters
  • entries – A list of directives. We’re interested only in the Transaction instances.

  • unused_options_map – A parser options dict.

Returns

A list of entries, possibly with more Price entries than before, and a list of errors.

beancount.plugins.book_conversions

A plugin that automatically converts postings at price to postings held at cost, applying an automatic booking algorithm in assigning the cost bases and matching lots.

This plugin restricts itself to applying these transformations within a particular account, which you provide. For each of those accounts, it also requires a corresponding Income account to book the profit/loss of reducing lots (i.e., sales):

plugin “beancount.plugins.book_conversions” “Assets:Bitcoin,Income:Bitcoin”

Then, simply input the transactions with price conversion. We use “Bitcoins” in this example, converting Bitcoin purchases that were carried out as currency into maintaining these with cost basis, for tax reporting purposes:

2015-09-04 * “Buy some bitcoins”

Assets:Bank -1000.00 USD Assets:Bitcoin 4.333507 BTC @ 230.76 USD

2015-09-05 * “Buy some more bitcoins at a different price”

Assets:Bank -1000.00 USD Assets:Bitcoin 4.345747 BTC @ 230.11 USD

2015-09-20 * “Use (sell) some bitcoins”

Assets:Bitcoin -6.000000 BTC @ 230.50 USD Expenses:Something

The result is that cost bases are inserted on augmenting lots:

2015-09-04 * “Buy some bitcoins”

Assets:Bitcoin 4.333507 BTC {230.76 USD} @ 230.76 USD Assets:Bank -1000.00 USD

2015-09-05 * “Buy some more bitcoins at a different price”

Assets:Bitcoin 4.345747 BTC {230.11 USD} @ 230.11 USD Assets:Bank -1000.00 USD

While on reducing lots, matching FIFO lots are automatically found and the corresponding cost basis added:

2015-09-20 * “Use (sell) some bitcoins”

Assets:Bitcoin -4.333507 BTC {230.76 USD} @ 230.50 USD Assets:Bitcoin -1.666493 BTC {230.11 USD} @ 230.50 USD Income:Bitcoin 0.47677955 USD Expenses:Something 1383.00000000 USD

Note that multiple lots were required to fulfill the sale quantity here. As in this example, this may result in multiple lots being created for a single one.

Finally, Beancount will eventually support booking methods built-in, but this is a quick method that shows how to hack your own booking method via transformations of the postings that run in in a plugin.

Implementation notes:

  • This code uses the FIFO method only for now. However, it would be very easy to customize it to provide other booking methods, e.g. LIFO, or otherwise. This will be added eventually, and I’m hoping to reuse the same inventory abstractions that will be used to implement the fallback booking methods from the booking proposal review (http://furius.ca/beancount/doc/proposal-booking).

  • Instead of keeping a list of (Position, Transaction) pairs for the pending FIFO lots, we really ought to use a beancount.core.inventory.Inventory instance. However, the class does not contain sufficient data to carry out FIFO booking at the moment. A newer implementation, living in the “booking” branch, does, and will be used in the future.

  • This code assumes that a positive number of units is an augmenting lot and a reducing one has a negative number of units, though we never call them that way on purpose (to eventually allow this code to handle short positions). This is not strictly true; however, we would need an Inventory in order to figrue this out. This will be done in the future and is not difficult to do.

Important

This plugin was developed before the booking methods (FIFO, LIFO, and others) were fully implemented in Beancount. It was built to answer a question on the mailing-list about FIFO booking. You probably don’t need to use them anymore. Always prefer to use the native syntax instead of this.

class beancount.plugins.book_conversions.BookConversionError(source, message, entry)
class beancount.plugins.book_conversions.ConfigError(source, message, entry)
beancount.plugins.book_conversions.augment_inventory(pending_lots, posting, entry, eindex)

Add the lots from the given posting to the running inventory.

Parameters
  • pending_lots – A list of pending ([number], Posting, Transaction) to be matched. The number is modified in-place, destructively.

  • posting – The posting whose position is to be added.

  • entry – The parent transaction.

  • eindex – The index of the parent transaction housing this posting.

Returns

A new posting with cost basis inserted to be added to a transformed transaction.

beancount.plugins.book_conversions.book_price_conversions(entries, assets_account, income_account)

Rewrite transactions to insert cost basis according to a booking method.

See module docstring for full details.

Parameters
  • entries – A list of entry instances.

  • assets_account – An account string, the name of the account to process.

  • income_account – An account string, the name of the account to use for booking realized profit/loss.

Returns

A tuple of

entries: A list of new, modified entries. errors: A list of errors generated by this plugin. matches: A list of (number, augmenting-posting, reducing-postings) for all

matched lots.

beancount.plugins.book_conversions.book_price_conversions_plugin(entries, options_map, config)

Plugin that rewrites transactions to insert cost basis according to a booking method.

See book_price_conversions() for details.

Parameters
  • entries – A list of entry instances.

  • options_map – A dict of options parsed from the file.

  • config – A string, in “<ACCOUNT1>,<ACCOUNT2>” format.

Returns

A tuple of

entries: A list of new, modified entries. errors: A list of errors generated by this plugin.

beancount.plugins.book_conversions.extract_trades(entries)

Find all the matching trades from the metadata attached to postings.

This inspects all the postings and pairs them up using the special metadata field that was added by this plugin when booking matching lots, and returns pairs of those postings.

Parameters

entries – The list of directives to extract from.

Returns

A list of (number, augmenting-posting, reducing-posting).

beancount.plugins.book_conversions.is_matching(posting, account)

“Identify if the given posting is one to be booked.

Parameters
  • posting – An instance of a Posting.

  • account – The account name configured.

Returns

A boolean, true if this posting is one that we should be adding a cost to.

Modify the entries in-place to add matching links to postings.

Parameters
  • entries – The list of entries to modify.

  • all_matches – A list of pairs of (augmenting-posting, reducing-posting).

Returns

A list of pairs of (index, Posting) for the new (augmenting, reducing) annotated postings.

beancount.plugins.book_conversions.main()

Extract trades from metadata-annotated postings and report on them.

beancount.plugins.book_conversions.reduce_inventory(pending_lots, posting, eindex)

Match a reducing posting against a list of lots (using FIFO order).

Parameters
  • pending_lots – A list of pending ([number], Posting, Transaction) to be matched. The number is modified in-place, destructively.

  • posting – The posting whose position is to be added.

  • eindex – The index of the parent transaction housing this posting.

Returns

A tuple of
postings: A list of new Posting instances corresponding to the given

posting, that were booked to the current list of lots.

matches: A list of pairs of (augmenting-posting, reducing-posting). pnl: A Decimal, the P/L incurred in reducing these lots. errors: A list of new errors generated in reducing these lots.

beancount.plugins.check_average_cost

A plugin that ensures cost basis is preserved in unbooked transactions.

This is intended to be used in accounts using the “NONE” booking method, to manually ensure that the sum total of the cost basis of reducing legs matches the average of what’s in the account inventory. This is a partial first step toward implementing the “AVERAGE” booking method. In other words, this plugins provides assertions that will constrain you to approximate what the “AVERAGE” booking method will do, manually, and not to leak too much cost basis through unmatching bookings without checks. (Note the contrived context here: Ideally the “NONE” booking method would simply not exist.)

class beancount.plugins.check_average_cost.MatchBasisError(source, message, entry)
beancount.plugins.check_average_cost.validate_average_cost(entries, options_map, config_str=None)

Check that reducing legs on unbooked postings are near the average cost basis.

Parameters
  • entries – A list of directives.

  • unused_options_map – An options map.

  • config_str – The configuration as a string version of a float.

Returns

A list of new errors, if any were found.

beancount.plugins.check_closing

A plugin that automatically inserts a balance check on a tagged closing posting.

Some postings are known to the user to be “closing trades”, which means that the resulting position of the instrument just after the trade should be zero. For instance, this is the case for most ordinary options trading, only one lot of a particular instrument is held, and eventually expires or gets sold off in its entirely. One would like to confirm that, and the way to do this in Beancount is to insert a balance check.

This plugin allows you to do that more simply, by inserting metadata. For example, this transaction:

2018-02-16 * “SOLD -14 QQQ 100 16 FEB 18 160 CALL @5.31”
Assets:US:Brokerage:Main:Options -1400 QQQ180216C160 {2.70 USD} @ 5.31 USD

closing: TRUE

Expenses:Financial:Commissions 17.45 USD Expenses:Financial:Fees 0.42 USD Assets:US:Brokerage:Main:Cash 7416.13 USD Income:US:Brokerage:Main:PnL

Would expand into the following two directives:

2018-02-16 * “SOLD -14 QQQ 100 16 FEB 18 160 CALL @5.31”

Assets:US:Brokerage:Main:Options -1400 QQQ180216C160 {2.70 USD} @ 5.31 USD Expenses:Financial:Commissions 17.45 USD Expenses:Financial:Fees 0.42 USD Assets:US:Brokerage:Main:Cash 7416.13 USD Income:US:Brokerage:Main:PnL

2018-02-17 balance Assets:US:Brokerage:Main:Options 0 QQQ180216C160

Insert the closing line when you know you’re closing the position.

beancount.plugins.check_closing.check_closing(entries, options_map)

Expand ‘closing’ metadata to a zero balance check.

Parameters
  • entries – A list of directives.

  • unused_options_map – An options map.

Returns

A list of new errors, if any were found.

beancount.plugins.check_commodity

A plugin that verifies that all seen commodities have a Commodity directive.

This is useful if you’re a bit pedantic and like to make sure that you’re declared attributes for each of the commodities you use. It’s useful if you use the portfolio export, for example.

class beancount.plugins.check_commodity.CheckCommodityError(source, message, entry)
beancount.plugins.check_commodity.validate_commodity_directives(entries, options_map)

Find all commodities used and ensure they have a corresponding Commodity directive.

Parameters
  • entries – A list of directives.

  • unused_options_map – An options map.

Returns

A list of new errors, if any were found.

beancount.plugins.coherent_cost

This plugin validates that currencies held at cost aren’t ever converted at price and vice-versa. This is usually the case, and using it will prevent users from making the mistake of selling a lot without specifying it via its cost basis.

class beancount.plugins.coherent_cost.CoherentCostError(source, message, entry)
beancount.plugins.coherent_cost.validate_coherent_cost(entries, unused_options_map)

Check that all currencies are either used at cost or not at all, but never both.

Parameters
  • entries – A list of directives.

  • unused_options_map – An options map.

Returns

A list of new errors, if any were found.

beancount.plugins.commodity_attr

A plugin that asserts that all Commodity directives have a particular attribute and that it is part of a set of enum values.

The configuration must be a mapping of attribute name to list of valid values, like this:

plugin “beancount.plugins.commodity_attr” “{

‘sector’: [‘Technology’, ‘Financials’, ‘Energy’], ‘name’: None,

}”

The plugin issues an error if a Commodity directive is missing the attribute, or if the attribute value is not in the valid set. If you’d like to just ensure the attribute is set, set the list of valid values to None, as in the ‘name’ attribute in the example above.

class beancount.plugins.commodity_attr.CommodityError(source, message, entry)
class beancount.plugins.commodity_attr.ConfigError(source, message, entry)
beancount.plugins.commodity_attr.validate_commodity_attr(entries, unused_options_map, config_str)

Check that all Commodity directives have a valid attribute.

Parameters
  • entries – A list of directives.

  • unused_options_map – An options map.

  • config_str – A configuration string.

Returns

A list of new errors, if any were found.

beancount.plugins.divert_expenses

For tagged transactions, convert expenses to a single account.

This plugin allows you to select a tag and it automatically converts all the Expenses postings to use a single account. For example, with this input:

plugin “divert_expenses” “[‘kid’, ‘Expenses:Child’]”

2018-01-28 * “CVS” “Formula” #kid

Liabilities:CreditCard -10.27 USD Expenses:Food:Grocery 10.27 USD

It will output:

2018-01-28 * “CVS” “Formula” #kid

Liabilities:CreditCard -10.27 USD Expenses:Child 10.27 USD

You can limit the diversion to one posting only, like this:

2018-05-05 * “CVS/PHARMACY” “” #kai

Liabilities:CreditCard -66.38 USD Expenses:Pharmacy 21.00 USD ;; Vitamins for Kai Expenses:Pharmacy 45.38 USD

divert: FALSE

See unit test for details.

See this thread for context: https://docs.google.com/drawings/d/18fTrrGlmz0jFbfcGGHTffbdRwbmST8r9_3O26Dd1Xww/edit?usp=sharing

beancount.plugins.divert_expenses.divert_expenses(entries, options_map, config_str)

Divert expenses.

Explicit price entries are simply maintained in the output list. Prices from postings with costs or with prices from Transaction entries are synthesized as new Price entries in the list of entries output.

Parameters
  • entries – A list of directives. We’re interested only in the Transaction instances.

  • options_map – A parser options dict.

  • config_str – A configuration string, which is intended to be a list of two strings, a tag, and an account to replace expenses with.

Returns

A modified list of entries.

beancount.plugins.divert_expenses.replace_expenses_accounts(entry, replacement_account, acctypes)

Replace the Expenses accounts from the entry.

Parameters
  • entry – A Transaction directive.

  • replacement_account – A string, the account to use for replacement.

  • acctypes – An AccountTypes instance.

Returns

A possibly entry directive.

beancount.plugins.exclude_tag

Exclude #virtual tags.

This is used to demonstrate excluding a set of transactions from a particular tag. In this example module, the tag name is fixed, but if we integrated this we could provide a way to choose which tags to exclude. This is simply just another mechanism for selecting a subset of transactions.

See discussion here for details: https://groups.google.com/d/msg/ledger-cli/N8Slh2t45K0/aAz0i3Be4LYJ

beancount.plugins.exclude_tag.exclude_tag(entries, options_map)

Select all transactions that do not have a #virtual tag.

Parameters
  • entries – A list of entry instances.

  • options_map – A dict of options parsed from the file.

Returns

A tuple of entries and errors.

beancount.plugins.fill_account

Insert an posting with a default account when there is only a single posting.

This is convenient to use in files which have mostly expenses, such as during a trip. Set the name of the default account to fill in as an option.

class beancount.plugins.fill_account.FillAccountError(source, message, entry)
beancount.plugins.fill_account.fill_account(entries, unused_options_map, insert_account)

Insert an posting with a default account when there is only a single posting.

Parameters
  • entries – A list of directives.

  • unused_options_map – A parser options dict.

  • insert_account – A string, the name of the account.

Returns

A list of entries, possibly with more Price entries than before, and a list of errors.

beancount.plugins.fix_payees

Rename payees based on a set of rules.

This can be used to clean up dirty imported payee names.

This plugin accepts a list of rules in this format:

plugin “beancount.plugins.fix_payees” “[

(PAYEE, MATCH1, MATCH2, …),

]”

Each of the “MATCH” clauses is a string, in the format:

“A:<regexp>” : Match the account name. “D:<regexp>” : Match the payee or the narration.

The plugin matches the Transactions in the file and if there is a case-insensitive match against the regular expression (we use re.search()), replaces the payee name by “PAYEE”. If multiple rules match, only the first rule is used.

For example:

plugin “beancount.plugins.fix_payees” “[

(“T-Mobile USA”,

“A:Expenses:Communications:Phone”, “D:t-mobile”),

(“Con Edison”,

“A:Expenses:Home:Electricity”, “D:con ?ed”),

(“Birreria @ Eataly”,

“D:EATALY BIRRERIA”),

]”

class beancount.plugins.fix_payees.FixPayeesError(source, message, entry)
beancount.plugins.fix_payees.fix_payees(entries, options_map, config)

Rename payees based on a set of rules. See module docstring for details.

Parameters
  • entries – a list of entry instances

  • options_map – a dict of options parsed from the file

  • config – A configuration string, which is intended to be a list of (PAYEE, MATCH, …) rules. See module docstring for details.

Returns

A tuple of entries and errors.

beancount.plugins.forecast

An example of adding a forecasting feature to Beancount via a plugin.

This entry filter plugin uses existing syntax to define and automatically inserted transactions in the future based on a convention. It serves mostly as an example of how you can experiment by creating and installing a local filter, and not so much as a serious forecasting feature (though the experiment is a good way to get something more general kickstarted eventually, I think the concept would generalize nicely and should eventually be added as a comon feature of Beancount).

A user can create a create a transaction like this:

2014-03-08 # “Electricity bill [MONTHLY]”“

Expenses:Electricity 50.10 USD Assets:Checking -50.10 USD

and new transactions will be created monthly for the following year. Note the use of the ‘#’ flag and the word ‘MONTHLY’ which defines the periodicity.

The number of recurrences can optionally be specified either by providing an end date or by specifying the number of times that the transaction will be repeated. For example:

2014-03-08 # “Electricity bill [MONTHLY UNTIL 2019-12-31]”“

Expenses:Electricity 50.10 USD Assets:Checking -50.10 USD

2014-03-08 # “Electricity bill [MONTHLY REPEAT 10 TIMES]”“

Expenses:Electricity 50.10 USD Assets:Checking -50.10 USD

Transactions can be also be repeated at yearly intervals, e.g.:

2014-03-08 # “Electricity bill [YEARLY REPEAT 10 TIMES]”“

Expenses:Electricity 50.10 USD Assets:Checking -50.10 USD

beancount.plugins.forecast.forecast_plugin(entries, options_map)

An example filter that piggybacks on top of the Beancount input syntax to insert forecast entries automatically. This functions accepts the return value of beancount.loader.load_file() and must return the same type of output.

Parameters
  • entries – a list of entry instances

  • options_map – a dict of options parsed from the file

Returns

A tuple of entries and errors.

beancount.plugins.implicit_prices

This plugin synthesizes Price directives for all Postings with a price or directive or if it is an augmenting posting, has a cost directive.

class beancount.plugins.implicit_prices.ImplicitPriceError(source, message, entry)
beancount.plugins.implicit_prices.add_implicit_prices(entries, unused_options_map)

Insert implicitly defined prices from Transactions.

Explicit price entries are simply maintained in the output list. Prices from postings with costs or with prices from Transaction entries are synthesized as new Price entries in the list of entries output.

Parameters
  • entries – A list of directives. We’re interested only in the Transaction instances.

  • unused_options_map – A parser options dict.

Returns

A list of entries, possibly with more Price entries than before, and a list of errors.

beancount.plugins.ira_contribs

Automatically adding IRA contributions postings.

This plugin looks for increasing postings on specified accounts (‘+’ sign for Assets and Expenses accounts, ‘-‘ sign for the others), or postings with a particular flag on them and when it finds some, inserts a pair of postings on that transaction of the corresponding amounts in a different currency. The currency is intended to be an imaginary currency used to track the number of dollars contributed to a retirement account over time.

For example, a possible configuration could be:

plugin “beancount.plugins.ira_contribs” “{

‘currency’: ‘IRAUSD’, ‘flag’: ‘M’, ‘accounts’: {

‘Income:US:Acme:Match401k’: (

‘Assets:US:Federal:Match401k’, ‘Expenses:Taxes:TY{year}:US:Federal:Match401k’),

(‘C’, ‘Assets:US:Fidelity:PreTax401k:Cash’): (

‘Assets:US:Federal:PreTax401k’, ‘Expenses:Taxes:TY{year}:US:Federal:PreTax401k’),

}

}”

Note: In this example, the configuration that triggers on the “Income:US:Acme:Match401k” account does not require a flag for those accounts; the configuration for the “Assets:US:Fidelity:PreTax401k:Cash” account requires postings to have a “C” flag to trigger an insertion.

Given a transaction like the following, which would be typical for a salary entry where the employer is automatically diverting some of the pre-tax money to a retirement account (in this example, at Fidelity):

2013-02-15 * “ACME INC PAYROLL”

Income:US:Acme:Salary … … Assets:US:BofA:Checking … Assets:US:Fidelity:PreTax401k:Cash 620.50 USD …

A posting with account ‘Assets:US:Fidelity:PreTax401k:Cash’, which is configured to match, would be found. The configuration above instructs the plugin to automatically insert new postings like this:

2013-02-15 * “ACME INC PAYROLL”

… Assets:US:Fidelity:PreTax401k:Cash 620.50 USD M Assets:US:Federal:PreTax401k -620.50 IRAUSD M Expenses:Taxes:TY2013:US:Federal:PreTax401k 620.50 IRAUSD …

Notice that the “{year}” string in the configuration’s account names is automatically replaced by the current year in the account name. This is useful if you maintain separate tax accounts per yera.

Furthermore, as in the configuration example above, you may have multiple matching entries to trigger multiple insertions. For example, the employer may also match the employee’s retirement contribution by depositing some money in the retirement account:

2013-02-15 * “BUYMF - MATCH” “Employer match, invested in SaveEasy 2030 fund”

Assets:US:Fidelity:Match401k:SE2030 34.793 SE2030 {17.834 USD} Income:US:Acme:Match401k -620.50 USD

In this example the funds get reported as invested immediately (an intermediate deposit into a cash account does not take place). The plugin configuration would match against the ‘Income:US:Acme:Match401k’ account and since it increases its value (the normal balance of an Income account is negative), postings would be inserted like this:

2013-02-15 * “BUYMF - MATCH” “Employer match, invested in SaveEasy 2030 fund”

Assets:US:Fidelity:Match401k:SE2030 34.793 SE2030 {17.834 USD} Income:US:Acme:Match401k -620.50 USD M Assets:US:Federal:Match401k -620.50 IRAUSD M Expenses:Taxes:TY2013:US:Federal:Match401k 620.50 IRAUSD

Note that the special dict keys ‘currency’ and ‘flag’ are used to specify which currency to use for the inserted postings, and if set, which flag to mark these postings with.

beancount.plugins.ira_contribs.add_ira_contribs(entries, options_map, config_str)

Add legs for 401k employer match contributions.

See module docstring for an example configuration.

Parameters
  • entries – a list of entry instances

  • options_map – a dict of options parsed from the file

  • config_str – A configuration string, which is intended to be a Python dict mapping match-accounts to a pair of (negative-account, position-account) account names.

Returns

A tuple of entries and errors.

beancount.plugins.ira_contribs.add_postings(entry, amount_, neg_account, pos_account, flag)

Insert positive and negative postings of a position in an entry.

Parameters
  • entry – A Transaction instance.

  • amount – An Amount instance to create the position, with positive number.

  • neg_account – An account for the posting with the negative amount.

  • pos_account – An account for the posting with the positive amount.

  • flag – A string, that is to be set as flag for the new postings.

Returns

A new, modified entry.

beancount.plugins.leafonly

A plugin that issues errors when amounts are posted to non-leaf accounts, that is, accounts with child accounts.

This is an extra constraint that you may want to apply optionally. If you install this plugin, it will issue errors for all accounts that have postings to non-leaf accounts. Some users may want to disallow this and enforce that only leaf accounts may have postings on them.

class beancount.plugins.leafonly.LeafOnlyError(source, message, entry)
beancount.plugins.leafonly.validate_leaf_only(entries, unused_options_map)

Check for non-leaf accounts that have postings on them.

Parameters
  • entries – A list of directives.

  • unused_options_map – An options map.

Returns

A list of new errors, if any were found.

beancount.plugins.mark_unverified

Add metadata to Postings which occur after their last Balance directives.

Some people use Balance directives as a way to indicate that all postings before them are verified. They want to compute balances in each account as of the date of that last Balance directives. One way to do that is to use this plugin to mark the postings which occur after and to then filter them out using a WHERE clause on that metadata:

SELECT account, sum(position) WHERE NOT meta(“unverified”)

Note that doing such a filtering may result in a list of balances which may not add to zero.

Also, postings for accounts without a single Balance directive on them will not be marked as unverified as all (otherwise all the postings would be marked, this would make no sense).

beancount.plugins.mark_unverified.mark_unverified(entries, options_map)

Add metadata to postings after the last Balance entry. See module doc.

Parameters
  • entries – A list of data directives.

  • options_map – A dict of options, that confirms to beancount.parser.options.

Returns

A list of entries, which includes the new unrealized capital gains entries at the end, and a list of errors. The new list of entries is still sorted.

beancount.plugins.merge_meta

Merge the metadata from a second file into the current set of entries.

This is useful if you like to keep more sensitive private data, such as account numbers or passwords, in a second, possibly encrypted file. This can be used to generate a will, for instance, for your loved ones to be able to figure where all your assets are in case you pass away. You can store all the super secret stuff in a more closely guarded, hidden away separate file.

The metadata from

  • Open directives: Account name must match.

  • Close directives: Account name must match.

  • Commodity directives: Currency must match.

are copied over. Metadata from the external file conflicting with that present in the main file overwrites it (external data wins).

WARNING! If you include an encrypted file and the main file is not encrypted, the contents extraction from the encrypted file may appear in the cache.

beancount.plugins.merge_meta.merge_meta(entries, options_map, config)

Load a secondary file and merge its metadata in our given set of entries.

Parameters
  • entries – A list of directives. We’re interested only in the Transaction instances.

  • unused_options_map – A parser options dict.

  • config – The plugin configuration string.

Returns

A list of entries, with more metadata attached to them.

beancount.plugins.noduplicates

This plugin validates that there are no duplicate transactions.

beancount.plugins.noduplicates.validate_no_duplicates(entries, unused_options_map)

Check that the entries are unique, by computing hashes.

Parameters
  • entries – A list of directives.

  • unused_options_map – An options map.

Returns

A list of new errors, if any were found.

beancount.plugins.nounused

This plugin validates that there are no unused accounts.

class beancount.plugins.nounused.UnusedAccountError(source, message, entry)
beancount.plugins.nounused.validate_unused_accounts(entries, unused_options_map)

Check that all accounts declared open are actually used.

We check that all of the accounts that are open are at least referred to by another directive. These are probably unused, so issue a warning (we like to be pedantic). Note that an account that is open and then closed is considered used–this is a valid use case that may occur in reality. If you have a use case for an account to be open but never used, you can quiet that warning by initializing the account with a balance asserts or a pad directive, or even use a note will be sufficient.

(This is probably a good candidate for optional inclusion as a “pedantic” plugin.)

Parameters
  • entries – A list of directives.

  • unused_options_map – An options map.

Returns

A list of new errors, if any were found.

beancount.plugins.onecommodity

A plugin that issues errors when more than one commodity is used in an account.

class beancount.plugins.onecommodity.OneCommodityError(source, message, entry)
beancount.plugins.onecommodity.validate_one_commodity(entries, unused_options_map)

Check that each account has units in only a single commodity.

This is an extra constraint that you may want to apply optionally, despite Beancount’s ability to support inventories and aggregations with more than one commodity. I believe this also matches GnuCash’s model, where each account has a single commodity attached to it.

Parameters
  • entries – A list of directives.

  • unused_options_map – An options map.

Returns

A list of new errors, if any were found.

beancount.plugins.pedantic

A plugin of plugins which triggers are all the pedantic plugins.

In a sense, this is the inverse of “pedantic.” This is useful when doing some types of quick and dirty tests.

beancount.plugins.sellgains

A plugin that cross-checks declared gains against prices on lot sales.

When you sell stock, the gains can be automatically implied by the corresponding cash amounts. For example, in the following transaction the 2nd and 3rd postings should match the value of the stock sold:

1999-07-31 * “Sell”

Assets:US:BRS:Company:ESPP -81 ADSK {26.3125 USD} Assets:US:BRS:Company:Cash 2141.36 USD Expenses:Financial:Fees 0.08 USD Income:US:Company:ESPP:PnL -10.125 USD

The cost basis is checked against: 2141.36 + 008 + -10.125. That is, the balance checks computes

-81 x 26.3125 = -2131.3125 +
2141.36 +

0.08 +

-10.125

and checks that the residual is below a small tolernace.

But… usually the income leg isn’t given to you in statements. Beancount can automatically infer it using the balance, which is convenient, like this:

1999-07-31 * “Sell”

Assets:US:BRS:Company:ESPP -81 ADSK {26.3125 USD} Assets:US:BRS:Company:Cash 2141.36 USD Expenses:Financial:Fees 0.08 USD Income:US:Company:ESPP:PnL

Additionally, most often you have the sales prices given to you on your transaction confirmation statement, so you can enter this:

1999-07-31 * “Sell”

Assets:US:BRS:Company:ESPP -81 ADSK {26.3125 USD} @ 26.4375 USD Assets:US:BRS:Company:Cash 2141.36 USD Expenses:Financial:Fees 0.08 USD Income:US:Company:ESPP:PnL

So in theory, if the price is given (26.4375 USD), we could verify that the proceeds from the sale at the given price match non-Income postings. That is, verify that

-81 x 26.4375 = -2141.4375 +
2141.36 +

0.08 +

is below a small tolerance value. So this plugin does this.

In general terms, it does the following: For transactions with postings that have a cost and a price, it verifies that the sum of the positions on all postings to non-income accounts is below tolerance.

This provides yet another level of verification and allows you to elide the income amounts, knowing that the price is there to provide an extra level of error-checking in case you enter a typo.

class beancount.plugins.sellgains.SellGainsError(source, message, entry)
beancount.plugins.sellgains.validate_sell_gains(entries, options_map)

Check the sum of asset account totals for lots sold with a price on them.

Parameters
  • entries – A list of directives.

  • unused_options_map – An options map.

Returns

A list of new errors, if any were found.

beancount.plugins.split_expenses

Split expenses of a Beancount ledger between multiple people.

This plugin is given a list of names. It assumes that any Expenses account whose components do not include any of the given names are to be split between the members. It goes through all the transactions and converts all such postings into multiple postings, one for each member.

For example, given the names ‘Martin’ and ‘Caroline’, the following transaction:

2015-02-01 * “Aqua Viva Tulum - two nights”

Income:Caroline:CreditCard -269.00 USD Expenses:Accommodation

Will be converted to this:

2015-02-01 * “Aqua Viva Tulum - two nights”

Income:Caroline:CreditCard -269.00 USD Expenses:Accommodation:Martin 134.50 USD Expenses:Accommodation:Caroline 134.50 USD

After these transformations, all account names should include the name of a member. You can generate reports for a particular person by filtering postings to accounts with a component by their name.

beancount.plugins.split_expenses.get_participants(filename, options_map)

Get the list of participants from the plugin configuration in the input file.

Parameters

options_map – The options map, as produced by the parser.

Returns

A list of strings, the names of participants as they should appear in the account names.

Raises
  • KeyError – If the configuration does not contain configuration for the list

  • of participants.

beancount.plugins.split_expenses.main()

Generate final reports for a shared expenses on a trip or project.

For each of many participants, generate a detailed list of expenses, contributions, a categorized summary of expenses, and a final balance. Also produce a global list of final balances so that participants can reconcile between each other.

beancount.plugins.split_expenses.save_query(title, participant, entries, options_map, sql_query, *format_args, boxed=True, spaced=False, args=None)

Save the multiple files for this query.

Parameters
  • title – A string, the title of this particular report to render.

  • participant – A string, the name of the participant under consideration.

  • entries – A list of directives (as per the loader).

  • options_map – A dict of options (as per the loader).

  • sql_query – A string with the SQL query, possibly with some placeholders left for *format_args to replace.

  • *format_args – A tuple of arguments to be formatted into the SQL query string. This is provided as a convenience.

  • boxed – A boolean, true if we should render the results in a fancy-looking ASCII box.

  • spaced – If true, leave an empty line between each of the rows. This is useful if the results have a lot of rows that render over multiple lines.

  • args

    A dummy object with the following attributes: output_text: An optional directory name, to produce a text rendering of

    the report.

    output_csv: An optional directory name, to produce a CSV rendering of

    the report.

    output_stdout: A boolean, if true, also render the output to stdout. currency: An optional currency (a string). If you use this, you should

    wrap query targets to be converted with the pseudo-function “CONV[…]” and it will get replaced to CONVERT(…, CURRENCY) automatically.

beancount.plugins.split_expenses.split_expenses(entries, options_map, config)

Split postings according to expenses (see module docstring for details).

Parameters
  • entries – A list of directives. We’re interested only in the Transaction instances.

  • unused_options_map – A parser options dict.

  • config – The plugin configuration string.

Returns

A list of entries, with potentially more accounts and potentially more postings with smaller amounts.

beancount.plugins.tag_pending

An example of tracking unpaid payables or receivables.

A user with lots of invoices to track may want to produce a report of pending or incomplete payables or receivables. Beancount does not by default offer such a dedicated feature, but it is easy to build one by using existing link attributes on transactions. This is an example on how to implement that with a plugin.

For example, assuming the user enters linked transactions like this:

2013-03-28 * “Bill for datacenter electricity” ^invoice-27a30ab61191

Expenses:Electricity 450.82 USD Liabilities:AccountsPayable

2013-04-15 * “Paying electricity company” ^invoice-27a30ab61191

Assets:Checking -450.82 USD Liabilities:AccountsPayable

Transactions are grouped by link (“invoice-27a30ab61191”) and then the intersection of their common accounts is automatically calculated (“Liabilities:AccountsPayable”). We then add up the balance of all the postings for this account in this link group and check if the sum is zero. If there is a residual amount in this balance, we mark the associated entries as incomplete by inserting a #PENDING tag on them. The user can then use that tag to navigate to the corresponding view in the web interface, or just find the entries and produce a listing of them.

beancount.plugins.tag_pending.tag_pending_plugin(entries, options_map)

A plugin that finds and tags pending transactions.

Parameters
  • entries – A list of entry instances.

  • options_map – A dict of options parsed from the file.

Returns

A tuple of entries and errors.

beancount.plugins.tag_pending.tag_pending_transactions(entries, tag_name='PENDING')

Filter out incomplete linked transactions to a transfer account.

Given a list of entries, group the entries by their link and compute the balance of the intersection of their common accounts. If the balance does not sum to zero, insert a ‘tag_name’ tag in the entries.

Parameters
  • entries – A list of directives/transactions to process.

  • tag_name – A string, the name of the tag to be inserted if a linked group of entries is found not to match

Returns

A modified set of entries, possibly tagged as pending.

beancount.plugins.unique_prices

This module adds validation that there is a single price defined per date and base/quote currencies. If multiple conflicting price values are declared, an error is generated. Note that multiple price entries with the same number do not generate an error.

This is meant to be turned on if you want to use a very strict mode for entering prices, and may not be realistic usage. For example, if you have (1) a transaction with an implicitly generated price during the day (from its cost) and (2) a separate explicit price directive that declares a different price for the day’s closing price, this would generate an error. I’m not certain this will be useful in the long run, so placing it in a plugin.

class beancount.plugins.unique_prices.UniquePricesError(source, message, entry)
beancount.plugins.unique_prices.validate_unique_prices(entries, unused_options_map)

Check that there is only a single price per day for a particular base/quote.

Parameters
  • entries – A list of directives. We’re interested only in the Transaction instances.

  • unused_options_map – A parser options dict.

Returns

The list of input entries, and a list of new UniquePricesError instances generated.

beancount.plugins.unrealized

Compute unrealized gains.

The configuration for this plugin is a single string, the name of the subaccount to add to post the unrealized gains to, like this:

plugin “beancount.plugins.unrealized” “Unrealized”

If you don’t specify a name for the subaccount (the configuration value is optional), by default it inserts the unrealized gains in the same account that is being adjusted.

class beancount.plugins.unrealized.UnrealizedError(source, message, entry)
beancount.plugins.unrealized.add_unrealized_gains(entries, options_map, subaccount=None)

Insert entries for unrealized capital gains.

This function inserts entries that represent unrealized gains, at the end of the available history. It returns a new list of entries, with the new gains inserted. It replaces the account type with an entry in an income account. Optionally, it can book the gain in a subaccount of the original and income accounts.

Parameters
  • entries – A list of data directives.

  • options_map – A dict of options, that confirms to beancount.parser.options.

  • subaccount – A string, and optional the name of a subaccount to create under an account to book the unrealized gain. If this is left to its default value, the gain is booked directly in the same account.

Returns

A list of entries, which includes the new unrealized capital gains entries at the end, and a list of errors. The new list of entries is still sorted.

beancount.plugins.unrealized.get_unrealized_entries(entries)

Return entries automatically created for unrealized gains.

Parameters

entries – A list of directives.

Returns

A list of directives, all of which are in the original list.