www

My personal website(s)
Log | Files | Refs

elbank-ynab.html (13988B)


      1 <!DOCTYPE html>
      2 <html lang="en">
      3 
      4   <head>
      5     <meta charset="utf-8">
      6     <meta http-equiv="X-UA-Compatible" content="IE=edge">
      7     <meta name="viewport" content="width=device-width, initial-scale=1">
      8 
      9     <title>Using Ledger for YNAB-like envelope budgeting</title>
     10     <meta name="description" content="Bye bye Elbank">
     11 
     12     <link rel="shortcut icon" type="image/png" href="/favicon.png"/>
     13     <link href="https://fonts.googleapis.com/css?family=Fira+Mono|Gentium+Book+Basic|Lato" rel="stylesheet">
     14     <link rel="stylesheet" href="/assets/main.css">
     15     <link rel="stylesheet" href="/css/cafe.css">
     16     <link rel="canonical" href="https://emacs.cafe/ledger/emacs/ynab/budgeting/2018/06/12/elbank-ynab.html">
     17     <link rel="alternate" type="application/rss+xml" title="Emacs café" href="/feed.xml">
     18     
     19     
     20 </head>
     21 
     22 
     23   <body>
     24 
     25     <header class="site-header" role="banner">
     26 
     27     <div class="wrapper">
     28         
     29         
     30         <a class="site-title" href="/"><img src="/img/emacscafe.png"/>Emacs café</a>
     31         
     32         
     33         <nav class="site-nav">
     34             <input type="checkbox" id="nav-trigger" class="nav-trigger" />
     35             <label for="nav-trigger">
     36                 <span class="menu-icon">
     37                     <svg viewBox="0 0 18 15" width="18px" height="15px">
     38                         <path fill="#424242" d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.031C17.335,0,18,0.665,18,1.484L18,1.484z"/>
     39                         <path fill="#424242" d="M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0c0-0.82,0.665-1.484,1.484-1.484 h15.031C17.335,6.031,18,6.696,18,7.516L18,7.516z"/>
     40                         <path fill="#424242" d="M18,13.516C18,14.335,17.335,15,16.516,15H1.484C0.665,15,0,14.335,0,13.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.031C17.335,12.031,18,12.696,18,13.516L18,13.516z"/>
     41                     </svg>
     42                 </span>
     43             </label>
     44 
     45             <div class="trigger">
     46                 
     47                 
     48                 
     49                 <a class="page-link" href="/about/">About Emacs café</a>
     50                 
     51                 
     52                 
     53                 
     54                 
     55                 
     56                 
     57                 
     58                 
     59                 
     60                 
     61             </div>
     62         </nav>
     63         
     64     </div>
     65 </header>
     66 
     67 
     68     <main class="page-content" aria-label="Content">
     69       <div class="wrapper">
     70         <article class="post" itemscope itemtype="http://schema.org/BlogPosting">
     71 
     72   <header class="post-header">
     73     <h1 class="post-title" itemprop="name headline">Using Ledger for YNAB-like envelope budgeting</h1>
     74     <p class="post-meta">
     75       <time datetime="2018-06-12T21:20:00+02:00" itemprop="datePublished">
     76         
     77         Jun 12, 2018
     78       </time>
     79       
     80         • <span itemprop="author" itemscope itemtype="http://schema.org/Person"><span itemprop="name">Nicolas Petton</span></span>
     81       </p>
     82   </header>
     83 
     84   <div class="post-content" itemprop="articleBody">
     85     <h1 id="bye-bye-elbank">Bye bye Elbank</h1>
     86 
     87 <p>I have to start this post with this: I will not be actively maintaining
     88 <a href="https://github.com/NicolasPetton/elbank">Elbank</a> anymore, simply because I
     89 switched back to <a href="https://www.ledger-cli.org/">Ledger</a>.  If someone wants to
     90 take over, please contact me!</p>
     91 
     92 <p>The main reason for switching is budgeting.  While Elbank was a cool experiment,
     93 it is not an accounting software, and inherently lacks support for powerful
     94 budgeting.</p>
     95 
     96 <p>When I started working on Elbank as a replacement for Ledger, I was looking for
     97 a reporting tool within Emacs that would fetch bank transactions automatically,
     98 so I wouldn’t have to enter transactions by hand (this is a seriously tedious
     99 task, and I grew tired of doing it after roughly two years, and finally gave up).</p>
    100 
    101 <p>Since then, I learned about ledger-autosync and boobank, which I use to sync my
    102 bank statements with Ledger (more about that in another post).</p>
    103 
    104 <h1 id="ynabs-way-of-budgeting">YNAB’s way of budgeting</h1>
    105 
    106 <p>I only came across <a href="https://ynab.com">YNAB</a> recently.  While I won’t use their
    107 software (being a non-free web application, and, you know… there’s no <code class="highlighter-rouge">M-x
    108 ynab</code>), I think that the principles behind it are really appealing for personal
    109 budgeting. I encourage you to <a href="https://www.youneedabudget.com/method/">read more about
    110 it</a> (or grab a <a href="https://www.youneedabudget.com/book-order-now/">copy of the
    111 book</a>, it’s great), but here’s
    112 the idea.</p>
    113 
    114 <ol>
    115   <li>
    116     <p><strong>Budget every euro</strong>: Quite simple once you get it. Every single Euro you have
    117 should be in a budget envelope. You should assign a job to every Euro you
    118 earn (that’s called
    119 <a href="https://en.wikipedia.org/wiki/Zero-based_budgeting">zero-based</a>, <a href="https://en.wikipedia.org/wiki/Envelope_system">envelope
    120 system</a>).</p>
    121   </li>
    122   <li>
    123     <p><strong>Embrace your true expenses</strong>: Plan for larger and less frequent expenses, so
    124 when a yearly bill arrives, or your car breaks down, you’ll be covered.</p>
    125   </li>
    126   <li>
    127     <p><strong>Roll with the punches</strong>: Address overspending as it happens by taking money
    128 overspent from another envelope.  As long as you keep budgeting, you’re
    129 succeeding.</p>
    130   </li>
    131   <li>
    132     <p><strong>Age your money</strong>: Spend less than you earn, so your money stays in the bank
    133 account longer.  As you do that, the age of your money will grow, and once
    134 you reach the goal of spending money that is at least one month old, you
    135 won’t worry about that next bill.</p>
    136   </li>
    137 </ol>
    138 
    139 <h1 id="implementation-in-ledger">Implementation in Ledger</h1>
    140 
    141 <p>I assume that you are familiar with Ledger, but if not I recommend reading its
    142 great
    143 <a href="https://www.ledger-cli.org/3.0/doc/ledger3.html#Introduction-to-Ledger">introduction</a>
    144 and <a href="https://www.ledger-cli.org/3.0/doc/ledger3.html#Ledger-Tutorial">tutorial</a>.</p>
    145 
    146 <p>The implementation in Ledger uses plain double-entry accounting.  I took most of
    147 it from
    148 <a href="http://sachachua.com/blog/2014/11/keeping-financial-score-ledger/">Sacha</a>, with
    149 some minor differences.</p>
    150 
    151 <h2 id="budgeting-new-money">Budgeting new money</h2>
    152 
    153 <p>After each income transaction, I budget the new money:</p>
    154 
    155 <div class="highlighter-rouge"><pre class="highlight"><code>2018-06-12 Employer
    156     Assets:Bank:Checking                        1600.00 EUR
    157     Income:Salary                              -1600.00 EUR
    158 
    159 2018-06-12 Budget
    160     [Assets:Budget:Food]                         400.00 EUR
    161     [Assets:Budget:Rent]                         600.00 EUR
    162     [Assets:Budget:Utilities]                    600.00 EUR
    163     [Equity:Budget]                            -1600.00 EUR
    164 </code></pre>
    165 </div>
    166 
    167 <p>Did you notice the square brackets around the accounts of the budget
    168 transaction? It’s a feature Ledger calls <a href="https://www.ledger-cli.org/3.0/doc/ledger3.html#Virtual-postings">virtual
    169 postings</a>. These
    170 postings are not considered real, and won’t be present in any report that uses
    171 the <code class="highlighter-rouge">--real</code> flag.  This is exactly what we want, since it’s a budget allocation
    172 and not a “real” transaction.  Therefore we’ll use the <code class="highlighter-rouge">--real</code> flag for all
    173 reports except for our budget report.</p>
    174 
    175 <h2 id="automatically-crediting-budget-accounts-when-spending-money">Automatically crediting budget accounts when spending money</h2>
    176 
    177 <p>Next, we need to credit the budget accounts each time we spend money.  Ledger
    178 has another neat feature called <a href="https://www.ledger-cli.org/3.0/doc/ledger3.html#Automated-Transactions">automated
    179 transactions</a>
    180 for this:</p>
    181 
    182 <div class="highlighter-rouge"><pre class="highlight"><code>= /Expenses/
    183     [Assets:Budget:Unbudgeted]                    -1.0
    184     [Equity:Budget]                                1.0
    185 
    186 = /Expenses:Food/
    187     [Assets:Budget:Food]                          -1.0
    188     [Assets:Budget:Unbudgeted]                     1.0
    189 	
    190 = /Expenses:Rent/
    191     [Assets:Budget:Rent]                          -1.0
    192     [Assets:Budget:Unbudgeted]                     1.0
    193 	
    194 = /Expenses:Utilities/
    195     [Assets:Budget:Utilities]                     -1.0
    196     [Assets:Budget:Unbudgeted]                     1.0
    197 </code></pre>
    198 </div>
    199 
    200 <p>Every expense is taken out of the <code class="highlighter-rouge">Assets:Budget:Unbudgeted</code> account by default.</p>
    201 
    202 <p>This forces me to budget properly, as <code class="highlighter-rouge">Assets:Budget:Unbudgeted</code> should always
    203 be 0 (if it is not the case I immediately know that there is something wrong
    204 going on).</p>
    205 
    206 <p>All other automatic transactions take money out of the
    207 <code class="highlighter-rouge">Assets:Budget:Unbudgeted</code> account instead of <code class="highlighter-rouge">Equity:Budget</code> account.</p>
    208 
    209 <h2 id="a-budget-report">A Budget report</h2>
    210 
    211 <p>This is the final piece of the puzzle.  Here’s the budget report command:</p>
    212 
    213 <div class="highlighter-rouge"><pre class="highlight"><code>ledger --empty -S -T -f ledger.dat bal ^assets:budget
    214 </code></pre>
    215 </div>
    216 
    217 <p>If we have the following transactions:</p>
    218 
    219 <div class="highlighter-rouge"><pre class="highlight"><code>2018/06/12 Groceries store
    220     Expenses:Food                                123.00 EUR
    221     Assets:Bank:Checking
    222 
    223 2018/06/12 Landlord
    224     Expenses:Rent                                600.00 EUR
    225     Assets:Bank:Checking
    226 
    227 2018/06/12 Internet provider
    228     Expenses:Utilities:Internet                   40.00 EUR
    229     Assets:Bank:Checking
    230 </code></pre>
    231 </div>
    232 
    233 <p>Here’s what the report looks like:</p>
    234 
    235 <div class="highlighter-rouge"><pre class="highlight"><code>          837.00 EUR  Assets:Budget
    236           560.00 EUR    Utilities
    237           277.00 EUR    Food
    238                    0    Rent
    239                    0    Unbudgeted
    240 --------------------
    241           837.00 EUR
    242 </code></pre>
    243 </div>
    244 
    245 <h1 id="conclusion">Conclusion</h1>
    246 
    247 <p>Ledger is amazingly powerful, and provides a great framework for YNAB-like
    248 budgeting.  In a future post I’ll explain how I automatically import my bank
    249 transactions using a mix of <code class="highlighter-rouge">ledger-autosync</code> and <code class="highlighter-rouge">weboob</code>.</p>
    250 
    251   </div>
    252 
    253   
    254     
    255 
    256 <div id="disqus_thread"></div>
    257 <script>
    258  /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    259  var disqus_shortname = 'emacs-cafe';
    260 
    261  /* * * DON'T EDIT BELOW THIS LINE * * */
    262  (function() {
    263      var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
    264      dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
    265      (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    266  })();
    267 </script>
    268 <noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript" rel="nofollow">comments powered by Disqus.</a></noscript>
    269 
    270 
    271   
    272 </article>
    273 
    274       </div>
    275     </main>
    276 
    277     <footer class="site-footer">
    278 
    279   <div class="wrapper">
    280 
    281     <h2 class="footer-heading">Emacs café</h2>
    282 
    283     <div class="footer-col-wrapper">
    284       <div class="footer-col footer-col-1">
    285         <ul class="contact-list">
    286           <li>
    287             
    288               Emacs café
    289             
    290             </li>
    291             
    292             <li><a href="mailto:nicolas@petton.fr">nicolas@petton.fr</a></li>
    293             
    294         </ul>
    295       </div>
    296 
    297       <div class="footer-col footer-col-2">
    298         <ul class="social-media-list">
    299           
    300           <li>
    301             <a href="https://github.com/NicolasPetton"><span class="icon icon--github"><svg viewBox="0 0 16 16" width="16px" height="16px"><path fill="#828282" d="M7.999,0.431c-4.285,0-7.76,3.474-7.76,7.761 c0,3.428,2.223,6.337,5.307,7.363c0.388,0.071,0.53-0.168,0.53-0.374c0-0.184-0.007-0.672-0.01-1.32 c-2.159,0.469-2.614-1.04-2.614-1.04c-0.353-0.896-0.862-1.135-0.862-1.135c-0.705-0.481,0.053-0.472,0.053-0.472 c0.779,0.055,1.189,0.8,1.189,0.8c0.692,1.186,1.816,0.843,2.258,0.645c0.071-0.502,0.271-0.843,0.493-1.037 C4.86,11.425,3.049,10.76,3.049,7.786c0-0.847,0.302-1.54,0.799-2.082C3.768,5.507,3.501,4.718,3.924,3.65 c0,0,0.652-0.209,2.134,0.796C6.677,4.273,7.34,4.187,8,4.184c0.659,0.003,1.323,0.089,1.943,0.261 c1.482-1.004,2.132-0.796,2.132-0.796c0.423,1.068,0.157,1.857,0.077,2.054c0.497,0.542,0.798,1.235,0.798,2.082 c0,2.981-1.814,3.637-3.543,3.829c0.279,0.24,0.527,0.713,0.527,1.437c0,1.037-0.01,1.874-0.01,2.129 c0,0.208,0.14,0.449,0.534,0.373c3.081-1.028,5.302-3.935,5.302-7.362C15.76,3.906,12.285,0.431,7.999,0.431z"/></svg>
    302 </span><span class="username">NicolasPetton</span></a>
    303 
    304           </li>
    305           
    306 
    307           
    308           <li>
    309             <a href="https://twitter.com/NicolasPetton"><span class="icon icon--twitter"><svg viewBox="0 0 16 16" width="16px" height="16px"><path fill="#828282" d="M15.969,3.058c-0.586,0.26-1.217,0.436-1.878,0.515c0.675-0.405,1.194-1.045,1.438-1.809c-0.632,0.375-1.332,0.647-2.076,0.793c-0.596-0.636-1.446-1.033-2.387-1.033c-1.806,0-3.27,1.464-3.27,3.27 c0,0.256,0.029,0.506,0.085,0.745C5.163,5.404,2.753,4.102,1.14,2.124C0.859,2.607,0.698,3.168,0.698,3.767 c0,1.134,0.577,2.135,1.455,2.722C1.616,6.472,1.112,6.325,0.671,6.08c0,0.014,0,0.027,0,0.041c0,1.584,1.127,2.906,2.623,3.206 C3.02,9.402,2.731,9.442,2.433,9.442c-0.211,0-0.416-0.021-0.615-0.059c0.416,1.299,1.624,2.245,3.055,2.271 c-1.119,0.877-2.529,1.4-4.061,1.4c-0.264,0-0.524-0.015-0.78-0.046c1.447,0.928,3.166,1.469,5.013,1.469 c6.015,0,9.304-4.983,9.304-9.304c0-0.142-0.003-0.283-0.009-0.423C14.976,4.29,15.531,3.714,15.969,3.058z"/></svg>
    310 </span><span class="username">NicolasPetton</span></a>
    311 
    312           </li>
    313           
    314         </ul>
    315       </div>
    316 
    317       <div class="footer-col footer-col-3">
    318         <p>A blog about Emacs, mostly focused on JavaScript development, by Nicolas Petton.
    319 </p>
    320       </div>
    321     </div>
    322 
    323   </div>
    324 
    325 </footer>
    326 
    327 
    328   </body>
    329 
    330 </html>