New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New Report: Balance Forecast #467
Conversation
Hi @ZDBioHazard First, welcome and thank you for your contribution. Second, if this is your first foray into scheme then the code quality is very clean, and uses the API very well! If you don't mind I will try pick it apart some parts of the report, aiming for better fit into the current set of reports. I don't particularly use SX myself so I've created some to try understand the chart.
I do not have an opinion whether this chart is useful for inclusion -- I'll leave this to the core devs. I attach a screenshot of a working chart. Early x/y points are regular balances, later ones indicate SX monthly outgoing payment. |
(As an alternative to adding a new report, the existing reports could be augmented to add future SX amounts in the future dates, and even possibly work on liability/income/expense accounts as well...) |
I have created a prototype branch https://github.com/christopherlam/gnucash/tree/maint-sx-adjustments to augment existing charts to take into account future SX transactions. There would be a new option to enable these adjustments. The advantages to augmenting reports are that there will be a lesser maintenance burden and fewer tests will need to be created. I would be very keen to assign authorship to @ZDBioHazard, mostly thanks to the very clean code presented here. |
Here's an updated branch with some of the improvements you mentioned.
My income and expenses are very predictable, so I have tons of scheduled transactions which I use for forecasting like this. Here's an example of this report in action as I use it: The "reserve" is set to a balance I don't want to drop below. Let's say I'm trying to save $X to purchase something, and I want to know when I can expect to have that much. I set "target" to $X, and I can see on the graph that if all goes according to plan, I should be able to afford $X by mid-April, but it would be best to wait until July. The "minimum" line just helps visualize future dips so you don't accidentally miss a reserve-crossing if you're playing it close. I'd love for the other reports to support scheduled transactions. (Especially the expense and cash flow reports, which I also use often.) However, the only SX-related function I could find ( I would imagine the easiest way to add support would be to simply add an (optional) flag to all information retrieval functions to realize SX transactions before returning their data. Then only very minimal changes would have to be made to the reports. That seems like it would be quite a change however. I don't know if I'm up to rewriting the other reports at the moment though. I had a heck of a time trying to figure out how the Gnucash API worked by looking at other reports, and the reports that do splits processing were very frustrating to try to glean insight from. Also, this report was written during breaks and lunches over 3 months, because that's all the free time I have lately. ;) |
Thank you - definitely better - I'd use srfi-1 as much as possible myself, and I usually try eradicate
This may be a worthwhile idea; it will change the nature of reporting from 'booked amounts' to 'forecast amounts' though. Documentation belongs to the gnucash-docs repository. I can guarantee there will be requests for enhancements - support liability/expense/income accounts. I'm still not 100% sure it's better to create a new set of forecast-type reports, or augment existing ones. The maintenance, localization and documentation burdens are a major issue for devs. |
Wow, awesome. That's much better. I was trying to figure out how to slice a list.
I know the
I imagine that this would manifest as an "include scheduled transactions" checkbox on the report options page. Then all the Updating all the reports to include and use this option sounds like a pain, but probably less of a pain than creating and maintaining a whole separate set of reports, or adding a second execution path to every API-related part of every existing report. Maybe just add the option to the global preferences, update the functions internally, and skip changing any of the actual reports. As a bonus, everyone's private reports get forecast capability too. ;)
I'm not sure what you mean. This particular report supports liability/expense/income accounts.The "minimum" line doesn't make any sense outside of balance forecasting though. |
Ok prepare to be blown... the above still not optimized because it cycles through balances to count (let loop ((result '())
(balances balances))
(if (null? balances)
(reverse result)
(loop (cons (apply min balances) result)
(cdr balances))))
Agree but this is a minor issue and
The above function is IMHO not desirable to run repeatedly for each date point; it calls With regards to updating existing reports, my vote would definitely be to augment the desired reports to instantiate sx transactions as part of the balance accumulator... the branch https://github.com/christopherlam/gnucash/tree/maint-sx-adjustments shows how it can be coded (and also uses the optimized balancelist function above). There would be new options in a new tab in the appriate reports.
|
P.S. I think it is worth highlighting that the SX algorithms will adjust the date-specific balances by calling Alternatively you could select the sx-start-date to be More testing required, and digging into SX code. I think there should be a new function |
Hi @ZDBioHazard I've experimented augmenting the existing charts, but find that the charts become too cluttered, and UI is quite difficult. So, I'd change my view and think that your report is uniquely useful. I'd add a couple of changes though:
Moreover the See the additional commit as follows. |
Ok last commit added to adjust sx accumulator by sx instanstiations between 'earliest-split' and 'report start-date'. This means the report can choose any start/end dates and all sx transactions will now be captured, assuming that all sx transactions must take place after an account's earliest split! Note the guile (let* ((earliest-date
(apply min
(map xaccTransGetDate
(map xaccSplitGetParent
(map car
(filter pair? (map xaccAccountGetSplitList accounts)))))))
... is rewritten (let* ((earliest-date
(apply min (map (compose xaccTransGetDate xaccSplitGetParent car)
(filter pair? (map xaccAccountGetSplitList accounts)))))
... |
@ZDBioHazard I have now been able to remove call to I have also enabled localisation for the series labels. I hope you do not mind. I am now happy that the chart is feature-complete, and can be merged in. I would ask that when it is merged, the chart should not be changed except for bugfixes and possibly future enhancements. I will aim to create implementation tests which will ensure the functionality is stabilised, and ask that the documentation is completed. Would you mind doing the needful? |
@ZDBioHazard I'd like to merge this chart into official release from 3.5 due in 3 weeks' time. Apologies for taking over; would you be happy to write a paragraph for the documentation? Alternatively I can copy from the comments above? |
Wow, perfect timing, I was just looking at this now. Your edits look great. It looks like you fixed some of the things that were bothering me (like the boolean options), added in some of the things I forgot about (like no accounts and zero balances), and optimized the algorithms that had better solutions I just didn't know enough about Scheme to implement. I'm not 100% sure what's going on in this report code anymore, but I understand what the changes are for and why, so we're good. I haven't had a chance to pull and test myself though. I'll try to do that tomorrow if I get a chance. I'm attending SCaLE 17x right now. No worries on taking over this PR, that's what opensource and collaboration is all about. :) I'll see about writing some documentation, but I have a busy couple weeks coming up, so if I don't make it, please feel free to chop up the above comments. Whatever I write will basically be a modified version of the above comments anyway. Thanks for fixing up this report for me. It will be nice to have it mainlined. I know I've seen at least one mailing list post asking for something like this long ago. |
Cool I've managed to push to your repo. This is for any other core devs who wish to offer comment. |
@ZDBioHazard the main scheme magic is extensive use of srfi-1 loops. this takes some getting used to, but extremely expressive.
last commit has added some helptext and reuse existing localized strings to reduce translator burden. to other devs - I don't think I can create suitable tests for this work because the sx creation routines are not very accessible to scheme. |
This report forecasts the combined balances of the selected accounts based on the scheduled transactions and plots them on a line graph. You can set a "reserve" amount, which will draw a red line on the graph, so you can easily see if your forecast dips below a given value. There is also a "future minimum" line which shows what the lowest future balance will be at a given point. I find this useful in conjunction with the "target" line for planning.
* Fix dates display to ISO format * Use make-list properly to create a list with identical elements
* Draw the "balance" line over the "minimum" line. * X axis labels should be for the end of the period, as that's when all the balance samples are taken.
1. convert simple boolean to complex boolean to toggle amounts 2. convert list processing functions to scheme conventions
this commit will initialize the sx accumulator by adding all instantiated sx amounts, from the earliest split posted-date among the selected accounts, until the report start-date.
previous will call gnc:account-get-comm-balance-at-date which calls xaccAccountGetBalanceAsOfDate for every account at every date point. The xaccAccountGetBalanceAsOfDate is an expensive function because it scans the account's whole splitlist from the start every time. use gnc:account-get-balances-at-dates instead which scans an account only once to generate a balancelist. this should be a much faster chart.
this commit will modify to reuse some strings which are already translated, and also add help strings for the various options.
The gnc:case-exchange-fn seems to be designed for single-date reports, whereas gnc:case-exchange-time-fn for multi-date reports. It may be faster to have a single exchange-fn definition. The main reason for this change is to harmonize - all multidate charts are using case-exchange-time-fn.
merged, thanks. We'll update documentation in due course. |
Last word, I think this chart should be moved from top-level to Asset&Liabilities submenu? |
A&L sounds good to me, I didn't consider menu placement during development. |
This report forecasts the combined balances of the selected accounts based on the scheduled transactions and plots them on a line graph.
You can set a "reserve" amount, which will draw a red line on the graph, so you can easily see if your forecast dips below a given value.
There is also a "future minimum" line which shows what the lowest future balance will be at a given point. I find this useful in conjunction with the "target" line for planning.
Let me know what you all think. Before this report, the only way I could find to predict future balances on a graph was to create scheduled transactions far in advance and use the "Average Balance" report.
I wanted to find a way to use each interval's minimum balance as a worst-case scenario for paycheck-to-paycheck budgeting, but that looked like it was going to take a lot of split processing, and I was having a hard time figuring out how to retrieve and manipulate data from accounts.
I was also thinking about adding an optional table that lists all the times the balance goes below the reserve threshold.
This is my first experiment with Scheme, so let me know if there are any issues.