Budgeting and forecasting (2018)

This is an old but still useful intro to budgeting with hledger. For more about budgeting, see also:

Budgeting and forecasting allows you to keep better track of your expenses and future financial situation. If you write down your expectations of what your income/expenses/investment yields/etc should be, you can use them to:

  • check how far off are your expectations from reality (budgeting)
  • project your future account activity or balances (forecasting)

(This section uses examples/bcexample.hledger from hledger source repository).

Goal-based budgeting

To start budgeting, you need to know what your average yearly or weekly expenditures are. Hledger could help you with that. Usually the interval for which you compute budget figures will be the same as the interval between your paychecks -- monthly or weekly.

Lets create monthly (-M) report for years 2013-2014 (-b 2013) of all top-level expense categories (--depth 2 Expenses), looking for average figures (-A), limiting ourselves to USD transactions only, to save screen space:

$ hledger balance -f bcexample.hledger -MA -b 2013 --depth 2 Expenses cur:USD
Balance changes in 2013/01/01-2014/10/31:

                    ||     2013/01      2013/02      2013/03  ...      2014/07      2014/08      2014/09      2014/10      Average 
====================++========================================...==================================================================
 Expenses:Financial ||    4.00 USD    12.95 USD    39.80 USD  ...    30.85 USD    21.90 USD    12.95 USD     4.00 USD    17.83 USD 
 Expenses:Food      ||  396.46 USD   481.48 USD   603.32 USD  ...   871.20 USD   768.23 USD   466.72 USD    83.00 USD   562.10 USD 
 Expenses:Health    ||  290.70 USD   193.80 USD   193.80 USD  ...   290.70 USD   193.80 USD   193.80 USD    96.90 USD   207.01 USD 
 Expenses:Home      || 2544.98 USD  2545.02 USD  2544.97 USD  ...  2545.12 USD  2545.01 USD  2545.10 USD            0  2429.33 USD 
 Expenses:Taxes     || 5976.60 USD  3984.40 USD  4901.83 USD  ...  5976.60 USD  3984.40 USD  3984.40 USD  1992.20 USD  4322.27 USD 
 Expenses:Transport ||  120.00 USD   120.00 USD   120.00 USD  ...            0   120.00 USD   120.00 USD   120.00 USD   109.09 USD 
--------------------++----------------------------------------...------------------------------------------------------------------
                    || 9332.74 USD  7337.65 USD  8403.72 USD  ...  9714.47 USD  7633.34 USD  7322.97 USD  2296.10 USD  7647.64 USD 

This report is rather wide and portion of it had been cut out for brevity. Most interesting column is the last one, it shows average monthly expenses for each category. Expenses in Food, Health, Home and Transport categories seem to roughly similar month to month, so lets create a budget for them.

Budgets are described with periodic (ie, recurring) transaction rules. Periodic transaction has ~ instead of date and period expression instead of description. In this case we want to create a monthly budget that will come into effect starting from January 2013, which will include income of 10000 USD that is partially spent on Food, Health, Home and Transport and the rest becomes our Assets:

~ monthly from 2013/01
  Expenses:Food    500 USD
  Expenses:Health  200 USD
  Expenses:Home    2545 USD
  Expenses:Transport   120 USD
  Income:US        -10700 USD ;; Taken as monthy average of Income account group
  Assets:US

This transaction could be put into separate file (budget.journal) or could be kept in the main journal. Normally hledger will ignore it and will not include it in any computations or reports.

To put it into action, you need to add --budget switch to your balance invocation. If you do that, you would be able to see how your past expenses aligned with the budget that you just created. This time, lets not limit accounts in any way:

$ hledger balance -f bcexample.hledger -f budget.journal -MB -b 2013 --budget cur:USD
Balance changes in 2013/01/01-2014/10/31:

                          ||                            2013/01                            2013/02                             2013/03 
==========================++===========================================================================================================
 <unbudgeted>:Expenses    ||                        5980.60 USD                        3997.35 USD                         4941.63 USD 
 <unbudgeted>:Liabilities ||                         293.09 USD                        -147.51 USD                          -66.01 USD 
 Assets:US                ||      1893.32 USD [26% of 7335 USD]      2929.77 USD [40% of 7335 USD]     -3898.89 USD [-53% of 7335 USD] 
 Expenses:Food            ||        396.46 USD [79% of 500 USD]        481.48 USD [96% of 500 USD]        603.32 USD [121% of 500 USD] 
 Expenses:Health          ||       290.70 USD [145% of 200 USD]        193.80 USD [97% of 200 USD]         193.80 USD [97% of 200 USD] 
 Expenses:Home            ||     2544.98 USD [100% of 2545 USD]     2545.02 USD [100% of 2545 USD]      2544.97 USD [100% of 2545 USD] 
 Expenses:Transport       ||       120.00 USD [100% of 120 USD]       120.00 USD [100% of 120 USD]        120.00 USD [100% of 120 USD] 
 Income:US                || -15119.10 USD [141% of -10700 USD]  -10331.21 USD [97% of -10700 USD]  -11079.40 USD [104% of -10700 USD] 
--------------------------++-----------------------------------------------------------------------------------------------------------
                          ||                       -3599.95 USD                        -211.30 USD                        -6640.58 USD 

Numbers in square brackets give you your budget estimate and percentage of it used by your real expenses. Numbers below 100% mean that you have some of your budget left, numbers over 100% mean that you went over your budget.

You can notice that actual numbers for Assets:US seem to be well below computed budget of 7335 USD. Why? Answer to this is in the first row of the report: we have quite a lot of unbudgeted Expenses!

Notice that even though we have not limited accounts in any way, report includes just those mentioned in the budget. This is on purpose, assumption is that when you are checking your budgets you probably do not want unbudgeted accounts getting in your way. Another thing to note is that budget numbers have been allocated to top-level expense subcategories (like Expenses:Food). Journal has subaccounts under Food, but to compute budget report they have all been rolled up into a nearest parent with budget number associated with it. Accounts that do not have such parent went into <unbudgeted> row.

Allright, it seems that for Jan 2013 we have ~3000 USD of budgeted expenses and almost twice as much unbudgeted. Lets figure out what they are. We can see more details if we add -E/--empty switch:

$ hledger balance -f bcexample.hledger -f budget.journal -M -b 2013-01 -e 2013-02 --budget cur:USD -E
Balance changes in 2013/01:

                                  ||                            2013/01 
==================================++====================================
 Assets:US                        ||      1893.32 USD [26% of 7335 USD] 
 Expenses:Financial:Fees          ||                           4.00 USD 
 Expenses:Food                    ||        396.46 USD [79% of 500 USD] 
 Expenses:Health                  ||       290.70 USD [145% of 200 USD] 
 Expenses:Home                    ||     2544.98 USD [100% of 2545 USD] 
 Expenses:Taxes:Y2013:US:CityNYC  ||                         524.76 USD 
 Expenses:Taxes:Y2013:US:Federal  ||                        3188.76 USD 
 Expenses:Taxes:Y2013:US:Medicare ||                         319.86 USD 
 Expenses:Taxes:Y2013:US:SDI      ||                           3.36 USD 
 Expenses:Taxes:Y2013:US:SocSec   ||                         844.62 USD 
 Expenses:Taxes:Y2013:US:State    ||                        1095.24 USD 
 Expenses:Transport               ||       120.00 USD [100% of 120 USD] 
 Income:US                        || -15119.10 USD [141% of -10700 USD] 
 Liabilities:US:Chase:Slate       ||                         293.09 USD 
----------------------------------++------------------------------------
                                  ||                       -3599.95 USD 

All the accounts that were rolled up into <unbudgeted> category are now shown with their original name, but budgeted accounts are still rolled up. It is easy to see now that we forgot taxes. Lets add them to our budget:

~ monthly from 2013/01
  Expenses:Food    500 USD
  Expenses:Health  200 USD
  Expenses:Home    2545 USD
  Expenses:Transport   120 USD
  Expenses:Taxes   4300 USD ;; Taken from monthly average report
  Income:US        -10700 USD
  Assets:US

Lets try again for a couple of month with this updated budget:

$ hledger balance -f bcexample.hledger -f budget.journal -M -b 2013-01 -e 2013-04 --budget cur:USD 
Balance changes in 2013q1:

                          ||                            2013/01                            2013/02                             2013/03 
==========================++===========================================================================================================
 <unbudgeted>:Expenses    ||                           4.00 USD                          12.95 USD                           39.80 USD 
 <unbudgeted>:Liabilities ||                         293.09 USD                        -147.51 USD                          -66.01 USD 
 Assets:US                ||      1893.32 USD [62% of 3035 USD]      2929.77 USD [97% of 3035 USD]    -3898.89 USD [-128% of 3035 USD] 
 Expenses:Food            ||        396.46 USD [79% of 500 USD]        481.48 USD [96% of 500 USD]        603.32 USD [121% of 500 USD] 
 Expenses:Health          ||       290.70 USD [145% of 200 USD]        193.80 USD [97% of 200 USD]         193.80 USD [97% of 200 USD] 
 Expenses:Home            ||     2544.98 USD [100% of 2545 USD]     2545.02 USD [100% of 2545 USD]      2544.97 USD [100% of 2545 USD] 
 Expenses:Taxes           ||     5976.60 USD [139% of 4300 USD]      3984.40 USD [93% of 4300 USD]      4901.83 USD [114% of 4300 USD] 
 Expenses:Transport       ||       120.00 USD [100% of 120 USD]       120.00 USD [100% of 120 USD]        120.00 USD [100% of 120 USD] 
 Income:US                || -15119.10 USD [141% of -10700 USD]  -10331.21 USD [97% of -10700 USD]  -11079.40 USD [104% of -10700 USD] 
--------------------------++-----------------------------------------------------------------------------------------------------------
                          ||                       -3599.95 USD                        -211.30 USD                        -6640.58 USD 

Now unbudgeted amounts are much smaller and some of them could be dismissed as noise, and we can see that budget created is actually close enough to the real numbers, meaning that they are usually close to average that we put in our budget.

Budget report that we have used so far assumes that any unused budget amount for a given (monthly) period will not contribute to the budget of the next period. Alternative popular "envelope budget" strategy assumes that you put a certain amount of money into an envelope each month, and any unused amount stays there for future expenses. This is easy to simulate by adding --cumulative switch. Lets redo the last report with it:

$ hledger balance -f bcexample.hledger -f budget.journal -M -b 2013-01 -e 2013-04 --cumulative --budget cur:USD
Ending balances (cumulative) in 2013q1:

                          ||                         2013/01/31                          2013/02/28                          2013/03/31 
==========================++============================================================================================================
 <unbudgeted>:Expenses    ||                           4.00 USD                           16.95 USD                           56.75 USD 
 <unbudgeted>:Liabilities ||                         293.09 USD                          145.58 USD                           79.57 USD 
 Assets:US                ||      1893.32 USD [62% of 3035 USD]       4823.09 USD [79% of 6070 USD]        924.20 USD [10% of 9105 USD] 
 Expenses:Food            ||        396.46 USD [79% of 500 USD]        877.94 USD [88% of 1000 USD]       1481.26 USD [99% of 1500 USD] 
 Expenses:Health          ||       290.70 USD [145% of 200 USD]        484.50 USD [121% of 400 USD]        678.30 USD [113% of 600 USD] 
 Expenses:Home            ||     2544.98 USD [100% of 2545 USD]      5090.00 USD [100% of 5090 USD]      7634.97 USD [100% of 7635 USD] 
 Expenses:Taxes           ||     5976.60 USD [139% of 4300 USD]      9961.00 USD [116% of 8600 USD]    14862.83 USD [115% of 12900 USD] 
 Expenses:Transport       ||       120.00 USD [100% of 120 USD]        240.00 USD [100% of 240 USD]        360.00 USD [100% of 360 USD] 
 Income:US                || -15119.10 USD [141% of -10700 USD]  -25450.31 USD [119% of -21400 USD]  -36529.71 USD [114% of -32100 USD] 
--------------------------++------------------------------------------------------------------------------------------------------------
                          ||                       -3599.95 USD                        -3811.25 USD                       -10451.83 USD 

If you look at Expenses:Food category, you will see that every month budget is increased by 500 USD, and by March total amount budgeted is 1500 USD, of which 1481.26 USD is spent. If you look back at the previous non-cumulative monthly budget report, you will see that in March food expenses were 121% of the budgeted amount, but cumulative report shows that taking into account budget carry-over from Jan and Feb we are well within planned numbers.

Envelope budgeting

Real envelope budgeting involves actually setting aside money for each category and spending only from there. In physical envelope budgeting, there are actual envelopes of cash. When doing envelope budgeting with hledger, the envelopes are represented by subaccounts, into which you transfer money and from which you spend it.

Note with this style of budgeting, you don't use periodic transactions or the --budget report - just regular transfers and regular balance reports. At the end of each period you can decide to remove or reallocate any surpluses, or let them roll over.b

A good place to keep the envelope accounts is under your regular checking or cash account, since it keeps the overall balance correct. Eg assets:checking:rent, assets:checking:food etc. Some people use virtual (imaginary) accounts instead.

The advantage of envelope budgeting is that it models your available funds precisely, which can be important in tight cashflow situations. hledger doesn't prevent overspending from your budget envelopes - you should watch their balances and make sure they never go negative. (The hledger-check-fancyassertions script could help, https://hledger.org/scripts.html.)

The downside is that it requires more bookkeeping work from you. Some people use auto posting rules to try to reduce that, but this can add complexity.

For more about envelope budgeting, see the links at plaintextaccounting.org/budgeting.

Forecasting

Budget transaction that was created could be used to predict what would be our financial situation in the future. If you add --forecast switch, you will see how budgeted income and expense affects you past the last transaction in the journal. Since journal ends in Oct 2014, lets see next two month:

$ hledger balance -f bcexample.hledger -f budget.journal -M -b 2014-10 -e 2015 --forecast cur:USD
Balance changes in 2014q4:

                                    ||      2014/10     2014/11     2014/12 
====================================++======================================
 Assets:US                          ||            0    3035 USD    3035 USD 
 Assets:US:BofA:Checking            || -2453.40 USD           0           0 
 Assets:US:ETrade:Cash              ||  5000.00 USD           0           0 
 Expenses:Financial:Fees            ||     4.00 USD           0           0 
 Expenses:Food                      ||            0     500 USD     500 USD 
 Expenses:Food:Restaurant           ||    83.00 USD           0           0 
 Expenses:Health                    ||            0     200 USD     200 USD 
 Expenses:Health:Dental:Insurance   ||     2.90 USD           0           0 
 Expenses:Health:Life:GroupTermLife ||    24.32 USD           0           0 
 Expenses:Health:Medical:Insurance  ||    27.38 USD           0           0 
 Expenses:Health:Vision:Insurance   ||    42.30 USD           0           0 
 Expenses:Home                      ||            0    2545 USD    2545 USD 
 Expenses:Taxes                     ||            0    4300 USD    4300 USD 
 Expenses:Taxes:Y2014:US:CityNYC    ||   174.92 USD           0           0 
 Expenses:Taxes:Y2014:US:Federal    ||  1062.92 USD           0           0 
 Expenses:Taxes:Y2014:US:Medicare   ||   106.62 USD           0           0 
 Expenses:Taxes:Y2014:US:SDI        ||     1.12 USD           0           0 
 Expenses:Taxes:Y2014:US:SocSec     ||   281.54 USD           0           0 
 Expenses:Taxes:Y2014:US:State      ||   365.08 USD           0           0 
 Expenses:Transport                 ||            0     120 USD     120 USD 
 Expenses:Transport:Tram            ||   120.00 USD           0           0 
 Income:US                          ||            0  -10700 USD  -10700 USD 
 Income:US:Hoogle:GroupTermLife     ||   -24.32 USD           0           0 
 Income:US:Hoogle:Salary            || -4615.38 USD           0           0 
 Liabilities:US:Chase:Slate         ||  -203.00 USD           0           0 
------------------------------------++--------------------------------------
                                    ||            0           0           0 

Note that this time there is no roll-up of accounts. Unlike --budget, which could be used with balance command only, --forecast could be used with any report. Forecast transactions would be added to your real journal and would appear in the report you requested as if you have entered them on the scheduled dates.

Since quite a lot of accounts do not have any budgeted transactions, lets limit the depth of the report to avoid seeing lots of zeroes:

$ hledger balance -f bcexample.hledger -f budget.journal -M -b 2014-10 -e 2015 --forecast cur:USD --depth 2
Balance changes in 2014q4:

                    ||      2014/10     2014/11     2014/12 
====================++======================================
 Assets:US          ||  2546.60 USD    3035 USD    3035 USD 
 Expenses:Financial ||     4.00 USD           0           0 
 Expenses:Food      ||    83.00 USD     500 USD     500 USD 
 Expenses:Health    ||    96.90 USD     200 USD     200 USD 
 Expenses:Home      ||            0    2545 USD    2545 USD 
 Expenses:Taxes     ||  1992.20 USD    4300 USD    4300 USD 
 Expenses:Transport ||   120.00 USD     120 USD     120 USD 
 Income:US          || -4639.70 USD  -10700 USD  -10700 USD 
 Liabilities:US     ||  -203.00 USD           0           0 
--------------------++--------------------------------------
                    ||            0           0           0 

As you can see, we should expect 3035 USD to be added into Assets:US each month. It is quite easy to see how overal amount of Assets will change with time if you use --cumulative switch:

$ hledger balance -f bcexample.hledger -f budget.journal -M -b 2014-10 -e 2015 --forecast cur:USD --depth 2 --cumulative
Ending balances (cumulative) in 2014q4:

                    ||   2014/10/31     2014/11/30     2014/12/31 
====================++============================================
 Assets:US          ||  2546.60 USD    5581.60 USD    8616.60 USD 
 Expenses:Financial ||     4.00 USD       4.00 USD       4.00 USD 
 Expenses:Food      ||    83.00 USD     583.00 USD    1083.00 USD 
 Expenses:Health    ||    96.90 USD     296.90 USD     496.90 USD 
 Expenses:Home      ||            0       2545 USD       5090 USD 
 Expenses:Taxes     ||  1992.20 USD    6292.20 USD   10592.20 USD 
 Expenses:Transport ||   120.00 USD     240.00 USD     360.00 USD 
 Income:US          || -4639.70 USD  -15339.70 USD  -26039.70 USD 
 Liabilities:US     ||  -203.00 USD    -203.00 USD    -203.00 USD 
--------------------++--------------------------------------------
                    ||            0              0              0 

According to forecast, assets are expected to grow to 8600+ USD by the end of 2014. However, our forecast does not include a couple of big one-off year end expenses. First, we plan to buy prize turkey for the Christmas table every year from 2014, spending up to 500 USD on it. And on 17th Nov 2014 we would celebrate birthday of significant other, spending up to 6000 USD in a fancy restaurant:

~ every 20th Dec from 2014
  Expenses:Food   500 USD ; Prize turkey, the biggest of the big
  Assets:US

~ 2014/11/17
  Assets:US
  Expenses:Food   6000 USD ; Birthday, lots of guests 

Note that turkey transaction is not entered as "yearly from 2014/12/20", since yearly/quarterly/monthy/weekly periodic expressions always generate entries at the first day of the calendar year/quarter/month/week. Thus "monthly from 2014/12" will occur on 2014/12/01, 2015/01/01, ..., whereas "every 20th of month from 2014/12" will happen on 2014/12/20, 2015/12/20, etc.

With latest additions forecast now looks like this:

hledger balance -f bcexample.hledger -f budget.journal -M -b 2014-10 -e 2015 --forecast cur:USD --depth 2 --cumulative
Ending balances (cumulative) in 2014q4:

                    ||   2014/10/31     2014/11/30     2014/12/31 
====================++============================================
 Assets:US          ||  2546.60 USD    -418.40 USD    2116.60 USD 
 Expenses:Financial ||     4.00 USD       4.00 USD       4.00 USD 
 Expenses:Food      ||    83.00 USD    6583.00 USD    7583.00 USD 
 Expenses:Health    ||    96.90 USD     296.90 USD     496.90 USD 
 Expenses:Home      ||            0       2545 USD       5090 USD 
 Expenses:Taxes     ||  1992.20 USD    6292.20 USD   10592.20 USD 
 Expenses:Transport ||   120.00 USD     240.00 USD     360.00 USD 
 Income:US          || -4639.70 USD  -15339.70 USD  -26039.70 USD 
 Liabilities:US     ||  -203.00 USD    -203.00 USD    -203.00 USD 
--------------------++--------------------------------------------
                    ||            0              0              0 

It is easy to see that in Nov 2014 we will run out of Assets. Using register we can figure out when or why it would happen:

$ hledger register -f bcexample.hledger -f budget.journal -b 2014-10 -e 2014-12 --forecast cur:USD Assets
2014/10/04 "BANK FEES" | "Monthly bank fee"         Assets:US:BofA:Checking                      -4.00 USD     -4.00 USD
2014/10/09 "Hoogle" | "Payroll"                     Assets:US:BofA:Checking                    2550.60 USD   2546.60 USD
2014/10/10 "Transfering accumulated savings to o..  Assets:US:BofA:Checking                   -5000.00 USD  -2453.40 USD
                                                    Assets:US:ETrade:Cash                      5000.00 USD   2546.60 USD
2014/11/01 Forecast transaction                     Assets:US                                     3035 USD   5581.60 USD
2014/11/17 Forecast transaction                     Assets:US                                    -6000 USD   -418.40 USD

It is 6000 USD planned for birthday! Something will have to be done about the birthday plans.