hledger-forecast 0.2.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -2
  3. data/README.md +169 -71
  4. data/example.journal +40 -0
  5. data/example.yml +38 -36
  6. data/hledger-forecast.gemspec +6 -4
  7. data/lib/hledger_forecast/cli.rb +35 -93
  8. data/lib/hledger_forecast/generator.rb +242 -90
  9. data/lib/hledger_forecast/summarize.rb +4 -5
  10. data/lib/hledger_forecast/tracker.rb +37 -0
  11. data/lib/hledger_forecast/version.rb +1 -1
  12. data/lib/hledger_forecast.rb +2 -1
  13. data/spec/command_spec.rb +14 -4
  14. data/spec/computed_amounts_spec.rb +35 -0
  15. data/spec/custom_spec.rb +35 -42
  16. data/spec/half-yearly_spec.rb +22 -6
  17. data/spec/modifier_spec.rb +87 -0
  18. data/spec/monthly_end_date_spec.rb +47 -0
  19. data/spec/monthly_end_date_transaction_spec.rb +32 -0
  20. data/spec/monthly_spec.rb +35 -27
  21. data/spec/once_spec.rb +22 -7
  22. data/spec/quarterly_spec.rb +21 -7
  23. data/spec/stubs/{monthly/forecast_monthly.yml → forecast.yml} +7 -7
  24. data/spec/stubs/transactions_found.journal +24 -0
  25. data/spec/stubs/transactions_found_inverse.journal +24 -0
  26. data/spec/stubs/transactions_not_found.journal +16 -0
  27. data/spec/track_spec.rb +197 -0
  28. data/spec/yearly_spec.rb +21 -7
  29. metadata +48 -74
  30. data/spec/start_date_spec.rb +0 -12
  31. data/spec/stubs/custom/forecast_custom_days.yml +0 -14
  32. data/spec/stubs/custom/forecast_custom_months.yml +0 -14
  33. data/spec/stubs/custom/forecast_custom_weeks.yml +0 -14
  34. data/spec/stubs/custom/forecast_custom_weeks_twice.yml +0 -24
  35. data/spec/stubs/custom/output_custom_days.journal +0 -24
  36. data/spec/stubs/custom/output_custom_months.journal +0 -20
  37. data/spec/stubs/custom/output_custom_weeks.journal +0 -28
  38. data/spec/stubs/custom/output_custom_weeks_twice.journal +0 -44
  39. data/spec/stubs/half-yearly/forecast_half-yearly.yml +0 -10
  40. data/spec/stubs/half-yearly/output_half-yearly.journal +0 -20
  41. data/spec/stubs/modifiers/forecast_modifiers.yml +0 -13
  42. data/spec/stubs/modifiers/output_modifiers.journal +0 -44
  43. data/spec/stubs/monthly/forecast_monthly_enddate.yml +0 -14
  44. data/spec/stubs/monthly/forecast_monthly_enddate_top.yml +0 -14
  45. data/spec/stubs/monthly/forecast_monthly_modifier.yml +0 -11
  46. data/spec/stubs/monthly/output_monthly.journal +0 -44
  47. data/spec/stubs/monthly/output_monthly_enddate.journal +0 -48
  48. data/spec/stubs/monthly/output_monthly_enddate_top.journal +0 -40
  49. data/spec/stubs/monthly/output_monthly_modifier.journal +0 -20
  50. data/spec/stubs/once/forecast_once.yml +0 -10
  51. data/spec/stubs/once/output_once.journal +0 -12
  52. data/spec/stubs/quarterly/forecast_quarterly.yml +0 -10
  53. data/spec/stubs/quarterly/output_quarterly.journal +0 -20
  54. data/spec/stubs/start_date/forecast_startdate.yml +0 -26
  55. data/spec/stubs/start_date/output_startdate.journal +0 -56
  56. data/spec/stubs/transactions.journal +0 -8
  57. data/spec/stubs/yearly/forecast_yearly.yml +0 -10
  58. data/spec/stubs/yearly/output_yearly.journal +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd24142d4c45b1eb5995c11bbda0fbdbf952f7058a07cbb138bf45ff49105240
4
- data.tar.gz: c229506a5d81565ef2efc995a0bb03676c8e2ca89ebe66a56addbe1c9226991c
3
+ metadata.gz: 85bd96722d50a8d5b2c8e8cbb9f973d88832827f74226d3b78d5f511b96265bf
4
+ data.tar.gz: b69f6698e5c7294cd2b62c8672887044a416d0ed6624803293acd9246a84fa14
5
5
  SHA512:
6
- metadata.gz: 86ff48c7b37ed1ac0045e4b7bef0bd361bfc8245161c25a5dc13d94f5095bdc2d2c8a07f0c015e6a2f7e9ba620950c43902d726c80734dddd72d80c8f5fb9cef
7
- data.tar.gz: aae79d44b7be1db897234360077186fb5a15fefb2260ea778a85e66a45b81530c443a49e14c0967a586f1b7be016e54aa981f9ce2e6af70f353abd6bbe4d27bb
6
+ metadata.gz: 2e3c4e2a1ef57546778525c37fa4b53854a10244f3e509c3bd48d8c3fcb49c2edc892c84f221f7980c56687ec4766f5379939ea82a06a06b238a8aa3f1a1ed8b
7
+ data.tar.gz: 4fd49fc32b5fd5aa17e24ac166f384352a5cb85a72f57cb3aa774b8837c62c94439412252ba7164641b59c4cec7fc60a218eab1419dad913ea008c30058722d5
data/.gitignore CHANGED
@@ -15,7 +15,5 @@ pkg/*
15
15
  /coverage
16
16
 
17
17
  # Misc
18
- forecast.yml
19
- forecast.journal
20
18
  test_output.journal
21
19
  todo.md
data/README.md CHANGED
@@ -2,14 +2,16 @@
2
2
 
3
3
  [![Tests](https://github.com/olimorris/hledger-forecast/actions/workflows/ci.yml/badge.svg)](https://github.com/olimorris/hledger-forecast/actions/workflows/ci.yml)
4
4
 
5
- Uses a YAML file to generate periodic transactions for better forecasting in [Hledger](https://github.com/simonmichael/hledger).
5
+ A wrapper which builds on [hledger's](https://github.com/simonmichael/hledger) [forecasting](https://hledger.org/dev/hledger.html#forecasting) capability. Uses a `yaml` config file to generate forecasts whilst adding functionality for future cost rises (e.g. inflation) and the automatic tracking of planned transactions.
6
6
 
7
7
  See the [rationale](#brain-rationale) section for why this gem may be useful to you.
8
8
 
9
9
  ## :sparkles: Features
10
10
 
11
- - :book: Uses simple YAML files to generate forecasts from periodic transactions
12
- - :date: Generate forecasts between specified start and end dates
11
+ - :book: Uses a simple yaml file to generate forecasts which can be used with hledger
12
+ - :date: Can smartly track forecasted transactions against actuals
13
+ - :moneybag: Can automatically apply modifiers such as inflation/deflation to forecasts
14
+ - :abacus: Supports calculated amounts in forecasts (uses the [Dentaku](https://github.com/rubysolo/dentaku) gem)
13
15
  - :heavy_dollar_sign: Full currency support (uses the [RubyMoney](https://github.com/RubyMoney/money) gem)
14
16
  - :computer: Simple and easy to use CLI
15
17
  - :chart_with_upwards_trend: Summarize your forecasts by period and category and output to the CLI
@@ -24,58 +26,81 @@ Assuming you have Ruby and [Rubygems](http://rubygems.org/pages/download) instal
24
26
 
25
27
  Run:
26
28
 
27
- hledger-forecast generate
29
+ hledger-forecast
28
30
 
29
- > **Note**: This assumes that a `forecast.yml` exists in the current working directory
31
+ The available options are:
30
32
 
31
- Running `hledger-forecast generate -h` shows the available options:
33
+ Usage: hledger-forecast [command] [options]
32
34
 
33
- Usage: Hledger-Forecast generate [options]
35
+ Commands:
36
+ generate Generate the forecast file
37
+ summarize Summarize the forecast file and output to the terminal
34
38
 
35
- -t, --transaction FILE The base TRANSACTIONS file to extend from
36
- -f, --forecast FILE The FORECAST yaml file to generate from
37
- -o, --output-file FILE The OUTPUT file to create
38
- -s, --start-date DATE The date to start generating from (yyyy-mm-dd)
39
- -e, --end-date DATE The date to start generating to (yyyy-mm-dd)
40
- --force Force an overwrite of the output file
39
+ Options:
41
40
  -h, --help Show this help message
41
+ -v, --version Show version
42
42
 
43
- Another example of a common command:
43
+ ### Generate command
44
44
 
45
- hledger-forecast generate -f my_forecast.yml -s 2023-05-01 -e 2024-12-31
45
+ The `hledger-forecast generate` command will generate a forecast _from_ a `yaml` file _to_ a journal file. You can see the output of this command in the [example.journal](https://github.com/olimorris/hledger-forecast/blob/main/example.journal) file.
46
46
 
47
- This will generate an output file (`my_forecast.journal`) from the forecast file between the two date ranges.
47
+ The available options are:
48
+
49
+ Usage: hledger-forecast generate [options]
50
+
51
+ -f, --forecast FILE The path to the FORECAST yaml file to generate from
52
+ -o, --output-file FILE The path to the OUTPUT file to create
53
+ -t, --transaction FILE The path to the TRANSACTION journal file
54
+ --force Force an overwrite of the output file
55
+ --no-track Don't track any transactions
56
+ -h, --help Show this help message
57
+
58
+ > **Note**: For the tracking of transactions you need to include the `-t` flag
59
+
60
+ Running the command with no options will assume a `forecast.yml` file exists.
48
61
 
49
62
  ### Using with Hledger
50
63
 
51
- To use the outputs in Hledger:
64
+ To work with hledger, include the forecast file and use the `--forecast` flag:
52
65
 
53
- hledger -f transactions.journal -f my_forecast.journal
66
+ hledger -f bank_transactions.journal -f forecast.journal --forecast bal assets -e 2024-02
54
67
 
55
- where:
68
+ The command will generate a forecast up to the end of Feb 2024, showing the balance for any asset accounts, overlaying some bank transactions with the forecast journal file. Of course, refer to the [hledger](https://hledger.org/dev/hledger.html) documentation for more information on how to query your finances.
56
69
 
57
- - `transactions.journal` might be your bank transactions (your "_actuals_")
58
- - `my_forecast.journal` is the generated forecast file
70
+ To apply any modifiers, use the `--auto` flag at the end of your command.
71
+
72
+ ### Summarize command
73
+
74
+ As your `yaml` configuration file grows, it can be helpful to sum up the total amounts and output them to the CLI. This can be achieved by:
75
+
76
+ hledger-forecast summarize -f my_forecast.yml
77
+
78
+ The available options are:
79
+
80
+ Usage: hledger-forecast summarize [options]
81
+
82
+ -f, --forecast FILE The path to the FORECAST yaml file to summarize
83
+ -h, --help Show this help message
59
84
 
60
85
  ## :gear: Configuration
61
86
 
62
87
  ### The YAML file
63
88
 
64
- > **Note**: See the [example.yml](https://github.com/olimorris/hledger-forecast/blob/main/example.yml) file for an example of a complex config file
89
+ > **Note**: See the [example.yml](https://github.com/olimorris/hledger-forecast/blob/main/example.yml) file for an example of a complex config file and its [output](https://github.com/olimorris/hledger-forecast/blob/main/example.journal)
65
90
 
66
- Firstly, create a `yml` file which will contain the transactions you'd like to forecast:
91
+ Firstly, create a `yaml` file which will contain the transactions you'd like to forecast:
67
92
 
68
93
  ```yaml
69
94
  # forecast.yml
70
95
  monthly:
71
- - account: "[Assets:Bank]"
72
- start: "2023-03-01"
96
+ - account: "Assets:Bank"
97
+ from: "2023-03-01"
73
98
  transactions:
74
99
  - amount: 2000
75
- category: "[Expenses:Mortgage]"
100
+ category: "Expenses:Mortgage"
76
101
  description: Mortgage
77
102
  - amount: 500
78
- category: "[Expenses:Food]"
103
+ category: "Expenses:Food"
79
104
  description: Food
80
105
 
81
106
  settings:
@@ -84,45 +109,38 @@ settings:
84
109
 
85
110
  Let's examine what's going on in this config file:
86
111
 
87
- - Firstly, we're telling the app to create two monthly transactions and repeat them, forever, starting from March 2023. In this case, forever will be the `end_date` specified when running the app
88
- - If you ran the app with `hledger-forecast -s 2023-04-01` then no transactions would be generated for March as the start date is greater than the periodic start date
89
- - Notice we're also using [virtual postings](https://hledger.org/1.29/hledger.html#virtual-postings) (designated by the brackets). This makes it easy to filter them out with the `-R` or `--real` option in Hledger
90
- - We also have not specified a currency; the default (`USD`) will be used
112
+ - We're telling the app to create two monthly transactions and repeat them, forever, starting from March 2023
113
+ - We're telling the app to link them both to the `Assets:Bank` account
114
+ - We've added descriptions to make it easy to follow in our output file
115
+ - Finally, we're telling the app to use the `GBP` currency; the default (`USD`) will be used if this is not specified
91
116
 
92
117
  ### Periods
93
118
 
94
119
  Besides monthly recurring transactions, the app also supports the following periods:
95
120
 
96
- - `quarterly` - For transactions every _3 months_ from the given start date
97
- - `half-yearly` - For transactions every _6 months_ from the given start date
98
- - `yearly` - Generate transactions _once a year_ from the given start date
121
+ - `quarterly` - For transactions every _3 months_
122
+ - `half-yearly` - For transactions every _6 months_
123
+ - `yearly` - Generate transactions _once a year_
99
124
  - `once` - Generate _one-time_ transactions on a specified date
100
125
  - `custom` - Generate transactions every _n days/weeks/months_
101
126
 
127
+ These will write periodic transactions such as `~ every 3 months` or `~ every year` in the output journal file.
128
+
102
129
  #### Custom period
103
130
 
104
- A custom period allows you to specify a given number of days, weeks or months for a transaction to repeat within. These can be included in the config file as follows:
131
+ When you need a bespoke time bound forecast, a custom period may be useful. Custom periods allow you to specify a periodic rule as per hledger's [periodic rule syntax](https://hledger.org/dev/hledger.html#periodic-transactions):
105
132
 
106
133
  ```yaml
107
134
  custom:
108
- - description: Fortnightly hair and beauty spend
109
- recurrence:
110
- period: weeks
111
- quantity: 2
112
- account: "[Assets:Bank]"
113
- start: "2023-03-01"
135
+ - frequency: "every 2 weeks"
136
+ account: "Assets:Bank"
137
+ from: "2023-03-01"
114
138
  transactions:
115
139
  - amount: 80
116
- category: "[Expenses:Personal Care]"
140
+ category: "Expenses:Personal Care"
117
141
  description: Hair and beauty
118
142
  ```
119
143
 
120
- Where `quantity` is an integer and `period` is one of:
121
-
122
- - days
123
- - weeks
124
- - months
125
-
126
144
  ### Dates
127
145
 
128
146
  The core of any solid forecast is predicting the correct periods that costs will fall into. When running the app from the CLI, you can specify specific dates to generate transactions over (see the [usage](#rocket-usage) section).
@@ -131,34 +149,115 @@ You can further control the dates at a period/top-level as well as at a transact
131
149
 
132
150
  #### Top level
133
151
 
134
- In the example below, all transactions in the `monthly` block will be constrained by the end date:
152
+ In the example below, all transactions in the `monthly` block will be constrained by the `to` date:
135
153
 
136
154
  ```yaml
137
155
  monthly:
138
- - account: "[Assets:Bank]"
139
- start: "2023-03-01"
140
- end: "2025-01-01"
156
+ - account: "Assets:Bank"
157
+ from: "2023-03-01"
158
+ to: "2025-01-01"
141
159
  transactions:
142
160
  # details omitted for brevity
143
161
  ```
144
162
 
145
163
  #### Transaction level
146
164
 
147
- In the example below, only the single transaction will be constrained by the end date and controlled via an additional start date:
165
+ In the example below, only the single transaction will be constrained by the `to` date:
148
166
 
149
167
  ```yaml
150
168
  monthly:
151
- - account: "[Assets:Bank]"
152
- start: "2023-03-01"
169
+ - account: "Assets:Bank"
170
+ from: "2023-03-01"
153
171
  transactions:
154
172
  - amount: 2000
155
- category: "[Expenses:Mortgage]"
173
+ category: "Expenses:Mortgage"
156
174
  description: Mortgage
157
- start: "2023-05-01"
158
- end: "2025-01-01"
175
+ to: "2025-01-01"
176
+ ```
177
+
178
+ ### Calculated amounts
179
+
180
+ > **Note**: Calculations will be determined up to two decimal places
181
+
182
+ It may be helpful to let the app calculate the forecasted amount in your transactions on your behalf. This can be especially useful if you're spreading a payment out over a number of months:
183
+
184
+ ```yaml
185
+ monthly:
186
+ - account: "Liabilities:Amex"
187
+ from: "2023-05-01"
188
+ transactions:
189
+ - amount: "=5000/24"
190
+ category: "Expenses:House"
191
+ description: New Kitchen
159
192
  ```
160
193
 
161
- The addition of the `start` key means that while the block will start on 2023-03-01, the transaction for the mortgage won't start until `2023-05-01`.
194
+ Simply ensure that the amount starts with an `=` sign, is enclosed in quotation marks and uses standard mathematical notations.
195
+
196
+ ### Tracking transactions
197
+
198
+ > **Note**: Marking a transaction for tracking will ensure that it is only written into the forecast if it isn't found within a specified transaction file
199
+
200
+ Sometimes it can be useful to track and monitor forecasted transactions to ensure that they are accounted for in any financial projections. If they are present, then these should be discarded from your forecast as this will create a double count against your actuals. However, if they can't be found then they should be carried forward into a future period to ensure accurate recording.
201
+
202
+ To mark transactions as available for tracking you may use the `track` option in your config file:
203
+
204
+ ```yaml
205
+ once:
206
+ account: "Assets:Bank"
207
+ from: "2023-03-05"
208
+ transactions:
209
+ - amount: 3000
210
+ category: "Expenses:Shopping"
211
+ description: Refund for that damn laptop
212
+ track: true
213
+ ```
214
+
215
+ > **Note**: This feature has been designed to work with one-off transactions only
216
+
217
+ To use this feature, ensure you pass a filepath to the `-t` flag, such as:
218
+
219
+ hledger-forecast generate -t [journal_file_to_search] -f [path_to_yaml_file] -o [path_to_output_journal]
220
+
221
+ The app will use a hledger query to determine if the combination of category and amount is present in the periods between the `from` key and the current date in the journal file you've specified. If not, then the app will include it as a forecast transaction in the output file.
222
+
223
+ ### Applying modifiers
224
+
225
+ > **Note**: For modifiers to be included in your hledger reporting, use the `--auto` flag
226
+
227
+ Within your forecasts, it can be useful to reflect future increases/decreases in certain categories. For example, next year, I expect the cost of groceries to increase by 2%:
228
+
229
+ ```yaml
230
+ monthly:
231
+ account: "Assets:Bank"
232
+ from: "2023-03-05"
233
+ transactions:
234
+ - amount: 450
235
+ category: "Expenses:Groceries"
236
+ description: Food shopping
237
+ modifiers:
238
+ - amount: 0.02
239
+ description: "Inflation"
240
+ from: "2024-01-01"
241
+ to: "2024-12-31"
242
+ ```
243
+
244
+ This will generate an [auto-posting](https://hledger.org/dev/hledger.html#auto-postings) in your forecast which will
245
+ uplift any transaction with an `Expenses:Groceries` category.
246
+
247
+ Of course you may wish to apply 2% for next year and another 3% for the year after:
248
+
249
+ ```yaml
250
+ # details above omitted for brevity
251
+ modifiers:
252
+ - amount: 0.02
253
+ description: "Inflation"
254
+ from: "2024-01-01"
255
+ to: "2024-12-31"
256
+ - amount: 0.05
257
+ description: "Inflation"
258
+ from: "2025-01-01"
259
+ to: "2025-12-31"
260
+ ```
162
261
 
163
262
  ### Additional settings
164
263
 
@@ -168,28 +267,27 @@ Additional settings in the config file to consider:
168
267
  settings:
169
268
  currency: GBP # Specify the currency to use
170
269
  show_symbol: true # Show the currency symbol?
171
- sign_before_symbol: true # Show the negative sign before the symbol?
172
270
  thousands_separator: true # Separate thousands with a comma?
173
271
  ```
174
272
 
175
- ## :rainbow: Helpers
273
+ ## :camera_flash: Screenshots
176
274
 
177
- ### Summarizing the forecast file
275
+ **Yaml config file and output**
178
276
 
179
- As your config file grows, it can be helpful to sum up the total amounts and output them in the CLI. This can be achieved by:
277
+ <img src="https://user-images.githubusercontent.com/9512444/234382872-b81ac84d-2bcc-4488-a041-364f72627087.png" alt="Hledger-Forecast" />
180
278
 
181
- hledger-forecast summarize -f my_forecast.yml
279
+ **Summarize command**
182
280
 
183
- where `my_forecast.yml` is the config file to sum up.
281
+ <img src="https://user-images.githubusercontent.com/9512444/234386807-1301c8d9-af77-4f58-a3c3-a345b5e890a2.png" alt="Summarize command" />
184
282
 
185
- ## :brain: Rationale
283
+ ## :paintbrush: Rationale
186
284
 
187
- Firstly, I've come to realise from reading countless blog and Reddit posts on [plain text accounting](https://plaintextaccounting.org), that everyone does it __completely__ differently!
285
+ Firstly, I've come to realise from reading countless blog and Reddit posts on [plain text accounting](https://plaintextaccounting.org), that everyone does it __completely__ differently! There is _great_ support in hledger for [forecasting](https://hledger.org/1.29/hledger.html#forecasting) using periodic transactions. Infact, it's nearly perfect for my needs. My only wishes were to be able to sum up monthly transactions much faster (so I can see my forecasted monthly I&E), apply future cost pressures more easily (such as inflation) and to be able to track and monitor specific transactions.
188
286
 
189
- My days working in financial modelling have meant that a big macro-enabled spreadsheet was my go-to tool. Growing tired with the manual approach of importing transactions, heavily manipulating them, watching Excel become increasingly slower lead me to PTA. It's been a wonderful discovery.
287
+ Regarding the latter; I may be expecting a material amount of money to leave my account in May (perhaps for a holiday booking). But maybe, that booking ends up leaving in July instead. Whilst I would have accounted for that expense in my forecast, it will be tied to some date in May. So if that transaction doesn't appear in the "actuals" of my May bank statement (which I import into hledger), it won't be included in my forecast at all (as the latest transaction period will be greater than the forecast period). The impact is that my forecasted balance in any future month could be $X better off than reality. Being able to automatically look out for these transactions, and include them if they're not present, is a nice time saver.
190
288
 
191
- One of the aspects of my previous approach to personal finance that I liked was the monthly recap of my performance and the looking ahead to the future. Am I still on track to hit my year-end savings goal given my performance to date and my future commitments? And what about my savings goal in 12 and 24 months time? Or, how much are my financial positions impacted if inflation increases by x%? It was at this point in my shift to PTA that I found it difficult to answer those questions quickly.
289
+ Also, I like to look ahead up to 3 years at a time and understand what my bank balances might look like. For this to be really accurate, factors such as inflation and salary expectations should be included. This is where the idea for modifiers came in. Being able to apply a percentage to a given category between two dates and automatically have the impact included any extended forecasts.
192
290
 
193
- While there is support in Hledger for [forecasting](https://hledger.org/1.29/hledger.html#forecasting) using periodic transactions, these are computed virtually at runtime. If I notice a big difference in my forecasted year-end balance compared to what I'm expecting, I want to investigate and start reconcilling. Computed transactions make this nigh on impossible to unpick. Also, I get a lot of value out of running different forecast scenarios and seeing the impact. For example, _"what's my savings balance looking like in 3 years time if I get the kitchen remodelled?"_.
291
+ Now I'll freely admit these are two minor issues. So minor infact that they can probably be addressed by a dedicated 5 minutes every month as part of your hledger workflow. However I liked the idea of automating as much of my month end process as possible and saw this as an interesting challenge to try and solve.
194
292
 
195
- With this gem, my aim was to make it easy for users to change their config file, regenerate the forecast and open a journal file and see the transactions. Or, use multiple forecast files for different scenarios and pass them in turn to Hledger to observe the impact.
293
+ Whilst I tried to work within the constraints of a `journal` file, moving to a `yaml` format made the implementation of these features much easier and allowed me to stay true to how you'd accomplish forecasting in hledger, manually. Whilst the config file can end up being many lines long, the output journal should be relatively streamlined and easy to follow.
data/example.journal ADDED
@@ -0,0 +1,40 @@
1
+ ~ monthly from 2023-03-01 * Bonus, Salary, Food, New cell phone, Holiday savings
2
+ Income:Bonus £-100.00 ; Bonus
3
+ Income:Salary £-2,000.00; Salary
4
+ Expenses:Food £500.00 ; Food
5
+ Expenses:Phone £75.00 ; New cell phone
6
+ Expenses:Holiday £208.33 ; Holiday savings
7
+ Assets:Bank
8
+
9
+ ~ monthly from 2023-03-01 to 2024-01-01 * Mortgage
10
+ Expenses:Mortgage £1,000.00 ; Mortgage
11
+ Assets:Bank
12
+
13
+ ~ monthly from 2023-03-01 * Pension draw down
14
+ Income:Pension £-500.00 ; Pension draw down
15
+ Assets:Savings
16
+
17
+ ~ every 3 months from 2023-04-01 * Bonus
18
+ Income:Bonus £-1,000.00; Bonus
19
+ Assets:Bank
20
+
21
+ ~ every 6 months from 2023-04-01 * Holiday
22
+ Expenses:Holiday £500.00 ; Holiday
23
+ Assets:Bank
24
+
25
+ ~ yearly from 2023-04-01 * Annual Bonus
26
+ Income:Bonus £-2,000.00; Annual Bonus
27
+ Assets:Bank
28
+
29
+ ~ every 5 days from 2023-03-01 * Car fuel
30
+ Expenses:Car:Fuel £150.00 ; Car fuel
31
+ Assets:Bank
32
+
33
+ ~ 2023-06-01 * [TRACKED] Forecast new car cost
34
+ Expenses:Car £5,000.00 ; Forecast new car cost
35
+ Assets:Bank
36
+
37
+ = Expenses:Food date:2024-01-01..2024-12-31
38
+ Expenses:Food *0.1 ; Food - Inflation
39
+ Assets:Bank *-0.1
40
+
data/example.yml CHANGED
@@ -1,77 +1,79 @@
1
1
  monthly:
2
- - account: "[Assets:Bank]"
3
- start: "2023-03-01"
2
+ - account: "Assets:Bank"
3
+ from: "2023-03-01"
4
4
  transactions:
5
5
  - amount: -100
6
- category: "[Income:Bonus]"
6
+ category: "Income:Bonus"
7
7
  description: Bonus
8
8
  - amount: -2000
9
- category: "[Income:Salary]"
9
+ category: "Income:Salary"
10
10
  description: Salary
11
- - amount: 500.00
12
- category: "[Expenses:Food]"
11
+ - amount: 500
12
+ category: "Expenses:Food"
13
13
  description: Food
14
+ modifiers:
15
+ - amount: 0.1
16
+ description: "Inflation"
17
+ from: "2024-01-01"
18
+ to: "2024-12-31"
14
19
  - amount: 75
15
- category: "[Expenses:Phone]"
20
+ category: "Expenses:Phone"
16
21
  description: New cell phone
17
- start: "2023-08-01"
18
- - amount: 1000.00
19
- category: "[Expenses:Mortgage]"
22
+ - amount: "=2500/12"
23
+ category: "Expenses:Holiday"
24
+ description: Holiday savings
25
+ - amount: 1000
26
+ category: "Expenses:Mortgage"
20
27
  description: Mortgage
21
- end: "2024-01-01"
22
- - account: "[Assets:Savings]"
23
- start: "2023-03-01"
28
+ to: "2024-01-01"
29
+ - account: "Assets:Savings"
30
+ from: "2023-03-01"
24
31
  transactions:
25
32
  - amount: -500
26
- category: "[Income:Pension]"
33
+ category: "Income:Pension"
27
34
  description: Pension draw down
28
35
 
29
36
  quarterly:
30
- - account: "[Assets:Bank]"
31
- start: "2023-04-01"
37
+ - account: "Assets:Bank"
38
+ from: "2023-04-01"
32
39
  transactions:
33
40
  - amount: -1000.00
34
- category: "[Income:Bonus]"
41
+ category: "Income:Bonus"
35
42
  description: Bonus
36
43
 
37
44
  half-yearly:
38
- - account: "[Assets:Bank]"
39
- start: "2023-04-01"
45
+ - account: "Assets:Bank"
46
+ from: "2023-04-01"
40
47
  transactions:
41
48
  - amount: 500
42
- category: "[Expenses:Holiday]"
49
+ category: "Expenses:Holiday"
43
50
  description: Holiday
44
51
 
45
52
  yearly:
46
- - account: "[Assets:Bank]"
47
- start: "2023-04-01"
53
+ - account: "Assets:Bank"
54
+ from: "2023-04-01"
48
55
  transactions:
49
56
  - amount: -2000.00
50
- category: "[Income:Bonus]"
57
+ category: "Income:Bonus"
51
58
  description: Annual Bonus
52
59
 
53
60
  once:
54
- - account: "[Assets:Bank]"
55
- start: "2024-01-01"
61
+ - account: "Assets:Bank"
62
+ from: "2023-03-01"
56
63
  transactions:
57
64
  - amount: 5000.00
58
- category: "[Expenses:Car]"
65
+ category: "Expenses:Car"
59
66
  description: Forecast new car cost
67
+ track: true
60
68
 
61
69
  custom:
62
- - description: Fuel every 5 days
63
- recurrence:
64
- period: days
65
- quantity: 5
66
- account: "[Assets:Bank]"
67
- start: "2023-03-01"
70
+ - frequency: "every 5 days"
71
+ account: "Assets:Bank"
72
+ from: "2023-03-01"
68
73
  transactions:
69
74
  - amount: 150
70
- category: "[Expenses:Car:Fuel]"
75
+ category: "Expenses:Car:Fuel"
71
76
  description: Car fuel
72
77
 
73
78
  settings:
74
79
  currency: GBP
75
- show_symbol: true
76
- sign_before_symbol: true
77
- thousands_separator: true
@@ -1,20 +1,22 @@
1
- lib = File.expand_path('../lib', __FILE__)
1
+ lib = File.expand_path('lib', __dir__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
3
4
  require 'hledger_forecast/version'
4
5
 
5
6
  Gem::Specification.new do |s|
6
7
  s.name = 'hledger-forecast'
7
8
  s.version = HledgerForecast::VERSION
8
9
  s.authors = ['Oli Morris']
9
- s.summary = 'Utility to generate forecasts in Hledger'
10
- s.description = 'Uses a YAML file to generate monthly, quarterly, yearly and one-off transactions for better forecasting in Hledger'
10
+ s.summary = "An extended wrapper around hledger's forecasting functionality"
11
+ s.description = 'Uses a YAML file to generate forecasts which can be used to extend the default functionality in hledger'
11
12
  s.email = 'olimorris@users.noreply.github.com'
12
13
  s.homepage = 'https://github.com/olimorris/hledger-forecast'
13
14
  s.license = 'MIT'
14
15
 
16
+ s.add_dependency "colorize", "~> 0.8.1"
17
+ s.add_dependency "dentaku", "~> 3.5.1"
15
18
  s.add_dependency "highline", "~> 2.1.0"
16
19
  s.add_dependency "money", "~> 6.16.0"
17
- s.add_dependency "colorize", "~> 0.8.1"
18
20
  s.add_dependency "terminal-table", "~> 3.0.2"
19
21
  s.add_development_dependency 'rspec', '~> 3.12'
20
22