Dylan Doxey


Finance::Budget - A module for helping you predict the effectiveness of your budget.


  use Finance::Budget;

  my $budget = Finance::Budget->new(
      {   days              => 365,
          opening_balance   => 123.01,
          transaction_types => [
              {   category   => 'PAYCHECK',
                  amount     => 1234.56,
                  recurrence => '0:0:2*4:0:0:0', # every second Thursday
              {   category   => 'Visa',
                  amount     => -100.00,
                  recurrence => '0:1*0:0:0:0:0', # first of every month
              {   category   => 'Cox',
                  amount     => -101.01,
                  recurrence => '0:1*0:15:0:0:0', # fifteenth of every month
              {   category   => 'Mortgage',
                  amount     => -1000.10,
                  recurrence => '0:1*0:0:0:0:0',
              {   category   => 'Water',
                  amount     => -150.00,
                  recurrence => '0:3*0:1:0:0:0', # first of every third month
          exceptions => [
              {   category => 'Visa',
                  amount   => 0.00,
                  date     => '12/20/2016',
              {   category => 'Cox',
                  amount   => 0.00,
                  date     => '01/01/2017',
              {   category => 'Mortgage',
                  amount   => 0.00,
                  date     => '01/01/2017',
          recent_history => [
              qq{"12/28/2016","","ACH Trans - Big Plastic","100.00",""},
              qq{"12/27/2016","","ACH Trans - COX CABLE","101.01",""},
              qq{"12/26/2016","","ACH Trans - US BANK MTG","1000.10",""},
              qq{"12/01/2016","","ACH Trans - Waters R Us","150.00",""},
              qq{"12/22/2016","","Deposit - Employer Inc","","1234.56"},
          categorizer => {
              'PAYCHECK' => [
                  qr{ employer \s inc }xmsi
              'Visa' => [
                  qr{ big \s plastic }xmsi
              'Cox' => [
                  qr{ cox \s cable }xmsi,
                  qr{ cox \s communications }xmsi,
              'Mortgage' => [
                  qr{ us \s bank \s mtg }xmsi
              'Water' => [
                  qr{ waters \s r \s us }xmsi

  printf "Opening Balance: % 25s\n",

  while ( my $transaction = $budget->next() )
      print "$transaction\n"
        if $transaction != 0;

  my $chokepoints = $budget->get_chokepoints();

  printf "\nEye of the needle:\n%s\n\n",

  printf "Chokepoints:\n";

  while ( my $point = $chokepoints->next() )
      die "negative chokepoint: $point\n"
          if $point < 0;

      print "$point\n";


This module consumes information about your budget planning and then creates a series of transactions to project what lays ahead.

This can be useful when considering taking on a new car payment or making a big purchase. For example, spending $300 today might have unexpected ramifications 90 days from now. This can also be handy in fine tuning your budget to ensure that it is sustainable.

Check out budget.pl in the demo directory of this project.




The number of days to project into the future. The default is 365.


The format that the transactions will use on stringafication. The default is '%m/%d/%Y'.


Set any string as a currency symbol. The default is '$'.


This is a code reference that gets invoked for each transaction stringafication event. You can use this to format the output any way you like.

The callback receives as the first argument a hash ref like:

  {   date_str    => '...',
      title       => '...',
      amount      => '$...',
      balance_str => '...',
      string      => '...',
      date        => <Date::Manip::Date object>,
      category    => '...',
      cents       => 0,

The callback retuns a formatted string. The default just returns the 'string' value.


The opening blanace, in dollars, of your checking account. The default is 0.


This is a list of transaction type descriptor hashes. Each descriptor has three attributes:

  {   category   => 'Foobar',        # category name
      amount     => -1.00,           # dollar amount -/+
      recurrence => '0:1*0:0:0:0:0', # Date::Manip::Recur string

This field also accepts a data filename which will be read using the Perl do() function.


Use this to define one-off exceptions. For example, your electric utilty bill might generally be $100.00. But you happen to know the next payment will be exactly $87.42.

So, you can define an exception:

  {   category => 'Electric',
      amount   => -87.42,
      date     => '02/01/2017',  # parsable by Date::Manip::Date

This field also accepts a data filename which will be read using the Perl do() function.


This is a list of CSV lines that are scanned for the most recent occurrence date for each transaction type. These dates are important because they are the 'base date' for each recurring transaction. (See Date::Manip::Recur)

Each CSV line is expected to have a 'date' and a 'description' field as given by the first CSV line. This happens to be exactly what my financial institution provides when I download a CSV file from my online banking site.

This field also accepts a CSV filename which will be slurped into memory.


This option accepts a hash of category names mapped to one of two things:

  1. An array ref of regexes. Each regex will be applied to the 'description' in the recent history data. When a match is made that category is applied.

  2. A code ref for a function that returns true if the 'description' applies to this category.

There doesn't need to be a categorizer entry for every single transaction type. For these cases, the category will be guessed when an otherwise uncategorized event matches the exact dollar and non-zero cent value of a transaction type. For example, a particular loan payment could be identified because you've decided to always define that transaction type with an amount of $100.42.



Returns a stringified version of the opening balance (supplied in the constructor).


Get the next transaction.


Returns a chokepoint iterator.


Returns a hash ref mapping of categories and the last time each one occurred as parsed from the recent history.

This might be helpful for debugging your categorizers.


Each transaction represents one event in your budget lifespan.

You'll probably just be satisified to print each "$transaction" in its stringified form, which uses the markup callback you provide.

The transaction object also offers some getter methods.


The transaction objects can be interpolated into strings and they can be used in numeric comparisons.

  print "$transaction\n"
      if $transaction != 0;


The chokepoints are the balance minima between the significant expenses and the significant income events. You might be interested in iterating through these to see where you're going to run into trouble.

The chokepoint objects can be interpolated into strings and they can be used in numeric comparisons.

  die "negative chokepoint: $point\n"
      if $point < 0;


This is the "eye" as in threading the needle -- the smallest of the chokepoints.


Get the next chokepoint.




Dylan Doxey, <dylan@cpan.org>


Copyright (C) 2017 by Dylan Doxey

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.22.1 or, at your option, any later version of Perl 5 you may have available.