Draft, not signed off
This page was assembled from the code rather than written from memory, and it is waiting on Christoph's sign-off as licensee. Read the parity paragraph under "The checks behind the numbers" most closely. It compares two separate calculation engines, and it describes the state today, part way through a rebuild.
The calculator on this site is a browser copy of the engine this practice has used in its own work for some time. The calculator reads no market data of its own: the site hands the calculator the data files, the calculator computes, and the page draws the result. This page lists what the calculator holds, what it charges, how it taxes, how it picks its windows, and how many checks stand behind the calculator.
| Class | In the code | Income assumption for the tax split | Fund fee the site applies |
|---|---|---|---|
| Australian sharesgrowth | AusEq | 4.0% a year of the balance, 77% of it franked at a 30% company rate from FY1988 | 0.053%mean of VAS 0.07, A200 0.04, IOZ 0.05 |
| International sharesgrowth | IntEq | 2.5% a year, unfranked | 0.117%mean of VGS 0.18, BGBL 0.08, IWLD 0.09 |
| US sharesgrowth, optional | USEq | 1.5% a year, unfranked | 0.035%mean of VTS 0.03, IVV 0.04 |
| Australian listed propertygrowth, optional | AusProp | 5.0% a year, split five ways for tax. See "The A-REIT distribution" below | 0.230%VAP 0.23 |
| Australian bondsdefensive | AusFI | the financial year's average 10 year government bond yield, from its own series, plus the credit premium. See "The credit premium on the bond sleeve" below | 0.130%mean of VAF 0.10, IAF 0.10, OZBD 0.19 |
| Cashdefensive | Cash | the whole return is income, unfranked | 0.125%mean of AAA 0.18, BILL 0.07 |
| Term depositsdefensive | TermDep | the whole return is income, unfranked | none. A term deposit is money with a bank, not a fund, so there is no management cost to subtract and the flat fee override doesn't reach it |
Fund names appear here as the basis of a fee assumption, not as recommendations.
23 data series are in use today. The engine reads 21 of them, and the other two supply figures quoted elsewhere in this section without reaching a calculation. The full register is on the data and licences page. Each entry there gives the publisher's own terms and the source line the series has to carry.
| Series | Publisher | What the engine does with it |
|---|---|---|
| Asset class total returns, as published | Vanguard Investments Australia | the financial year returns for shares and property, in data/fy_returns_full.csv, 56 financial years from FY1971 to FY2026 |
| Asset class total returns, the underlying compilation | Andex Charts Pty Ltd | the same numbers, one step upstream. Recorded separately because the compilation and the publication carry different terms |
| S&P/ASX accumulation indices and the S&P 500 | S&P Dow Jones Indices LLC | the indices underneath the Australian and US share returns |
| MSCI World ex-Australia | MSCI Inc. | the index underneath the international share returns |
| Bloomberg AusBond Composite and Bank Bill indices | Bloomberg Index Services Limited | the indices underneath the incumbent bond and cash returns. This practice has built free substitutes for both from Reserve Bank data, so this dependency can be dropped |
| 124 year Australian share return table | Fintech Equity Pty Ltd | the Australian share years before FY1971, in data/fy_returns_extended.csv, FY1951 onward. The same file carries the bond and cash years of that era, and the rebuilt Reserve Bank series are built to take those over |
| Australian government bond yields, table F2 | Reserve Bank of Australia | the 10 year yield that sets the bond income assumption, in data/bond_yield_fy.csv. It is also the input to the rebuilt bond return series |
| Historical interest rates and bond yields | Reserve Bank of Australia, Occasional Paper 8 | the bond yields before FY1970, in data/bond_yield_fy_extended.csv |
| Term deposit and retail deposit rates, table F4 | Reserve Bank of Australia | the published one year term deposit rate, which is what the term deposit series is built from |
| Term deposit rates, rolling one year | In Your Interest Financial Planning, computed from Reserve Bank data | the term deposit return for each financial year, in data/term_deposit_rates_fy.csv, FY1983 to FY2026 |
| Consumer price index | Australian Bureau of Statistics, through Reserve Bank table G1 | the actual inflation rate for each financial year, in data/cpi_fy.csv, FY1923 onward. This is the one series that reaches every figure on the site |
| Lifestage glide paths | Australian Prudential Regulation Authority, Quarterly MySuper Statistics, Table 1b | the growth share by age of the published MySuper lifecycle products, reduced to five anonymous percentile curves in data/lifestage_glide_paths.json, read only when a visitor ticks the lifestage strategy on tab 8 |
| Dwelling prices | OECD analytical house price indicators, Australia, from ABS sources | the nominal house price index averaged over each financial year, FY1971 to FY2025, in data/dwelling_price_fy.csv, the home's value path in rent or buy |
| Rents | Australian Bureau of Statistics, Consumer Price Index, Rents expenditure class, weighted average of eight capital cities | the rent index averaged over each financial year, FY1973 to FY2025, in data/rent_index_fy.csv, the rent path in rent or buy |
| Earnings by qualification | Australian Bureau of Statistics, Employee Earnings, August 2025 | the level of the career-paths tab's wage profiles (a bachelor degree about 1.70 times, a certificate about 1.40 times no post-school qualification), in data/earnings_paths.json |
| Income by age | Australian Bureau of Statistics, Personal Income in Australia, 2022-23 | the shape by age of the same wage profiles; the cross of the two is a construction the assumptions page names |
| Housing loan rate | Reserve Bank of Australia, Statistical Table F5, series FILRHLBVS | the banks' standard variable owner-occupier rate averaged over each financial year, in data/housing_rate_fy.csv, the loan rate of tab 8's SMSF property scenario plus its margin |
| Housing rates actually paid | Reserve Bank of Australia, Statistical Table F6, from APRA's Economic and Financial Statistics | the owner-occupier variable rate on outstanding loans from July 2019, the source of the discount schedule's recent years in data/mortgage_discount_fy.csv, which the mortgage decision reads |
| Wage growth by financial year | Australian Bureau of Statistics (Average Weekly Earnings, 6302.0), with the years before FY1983 from the ABS data the Reserve Bank compiled in Occasional Paper 8 | each financial year's growth in average weekly ordinary time earnings, in data/awote_fy.csv, FY1971 onward, read only when a visitor chooses "Wage growth (AWOTE)" as the contribution growth; the method and the splice are in data/AWOTE_SERIES.md |
| Tax rules, rates and thresholds | Australian Taxation Office | the rates, caps, and thresholds in the tax section that follows |
| Legislation | Office of Parliamentary Counsel, Federal Register of Legislation | the primary text behind the same rules, and the pension minimum drawdown factors |
Neither of these two series reaches a number the engine produces. They are on the register because they are in use. They are on this page so the user can see where the figures on the other pages came from.
| Series | Publisher | Where it appears |
|---|---|---|
| SPIVA Australia Scorecard figures | S&P Dow Jones Indices LLC | the share of active funds that trailed their index, on the active and passive page. That page is reached from the professionals section and is deliberately not linked from here: the scorecard is published for institutions only |
| Australia Persistence Scorecard figures | S&P Dow Jones Indices LLC | how rarely a top quarter fund stayed there, on the same page |
The calculator engine includes four types of costs and tax treatments differ depending on the type of account (investment, super, pension). It charges every layer on the average of the opening balance and the pre-fee closing balance. A year that grows is therefore charged on something between the two.
| Layer | Default | How the tax treats it |
|---|---|---|
| Fund fee, per class | the per-class figures in the preceding class table | no credit and no deduction inside super, either kind of super. Deductible at the marginal rate outside super. Subtracted from the gross index return, because the return series is before fees |
| Advice cost | 1.0% a year before goods and services tax (GST), so 1.1% with it; selectable at 0.9, 1.0, 1.1, or 1.2, or turned off | advice costs receive a tax credit of 15% as they count as an expense to the superannuation fund. No credit in a pension. Outside super this tool deducts none of it, because only the part of the advice costs that relates to tax advice is deductible and the tool doesn't guess at a split |
| Platform fee | 0.25% a year before GST, so 0.275% with it | the same 15% credit in super accumulation, no credit in a pension, deductible at the marginal rate outside super |
| Fixed amount in dollars | none by default | held in start-year dollars and indexed along the same inflation path as everything else in the window. Super accounts only: it gets the 15% credit in accumulation, none in a pension, and outside super nothing is charged at all |
The engine applies 10% GST to the advice cost and the platform fee, and to nothing else. The code holds that as a factor of 1.10.
Each class has an assumed cash income yield, in the preceding class table. That assumption splits a total return into the part that is taxed each year and the part that is not. Of the Australian share income, 77% is treated as franked at a company rate of 30%, from FY1988 onward, which is the first full year of imputation. Before that year the credit is zero.
Australian listed property is the one class whose income is not a single kind of income. An A-REIT is a trust, and a trust pays no company tax, so most of what it distributes has never been through a company tax return. The engine splits the distribution five ways rather than taxing all of it at the marginal rate.
| Component | Share | How the engine taxes it |
|---|---|---|
| Ordinary incomenet rent, interest, unfranked dividends | 44.3% | assessable in full |
| Capital gains distributed | 46.7% | assessable at half outside super and two thirds inside it, which is the CGT discount each account type receives |
| Franked dividends | 4.3% | assessable in full, and it carries the credits below |
| Foreign income | 4.3% | assessable in full. The foreign income tax offset the notices report is not modelled |
| Not assessable | 0.4% | not taxed, and not deducted from the cost base either. See the note on tax-deferred amounts below |
| Franking creditsattributed on top of the cash | 2.25% | of the cash distribution, from FY1988 like every other credit here. Given as a share of the cash rather than as 30/70 of the franked line, because the credits the notices report do not sit at 30/70 of it |
The five shares are shares of the cash distribution and add to all of it. They are cash-weighted over the nine financial years FY2018 to FY2026, from Vanguard's own quarterly distribution tax estimate notices for its Australian Property Securities Index ETF, all 36 of them read directly. The year-to-year range is wide: the capital gains share alone ran from 6.5% to 73.2% over those nine years, so the split describes a long run and not any single year.
Three things follow that are worth stating rather than leaving to be inferred.
The default growth block holds no A-REIT weight, so this split reaches a figure only where the user builds a growth mix that includes listed property.
The bond series is government bonds. The index it stands in for, the standard Australian bond index, is 90.6% government and government-related and about 9% corporate, and that corporate slice is worth extra yield. The engine adds it as one number the user can set, rather than building it into the series.
The engine doesn't model capital gains tax year by year for shares, because an index fund distributes almost no realised gains. Australian listed property is the exception, and it is handled as income in the section above rather than here, because those gains are distributed rather than realised on a sale. What this section covers is the tax at disposal, for accounts outside super only, and the engine computes it twice: once under the current law and once under the 2027 rules. Both runs use the same cost-base layers, one per financial year, and each layer is that year's contribution plus the net income reinvested in it.
| Current law | 2027 rules | |
|---|---|---|
| The gain | sale value less the cost base as it stands | sale value less a cost base with every layer indexed by inflation from its own financial year to the sale |
| The discount | 50% on every layer held more than twelve months. The final year's addition is under twelve months old and is taxed undiscounted | none |
| The rate | the rate at sale selected | the rate at sale, or 30%, whichever is higher. The minimum applies at every marginal rate |
| A loss | no tax, and no refund implied | no tax. Indexation cannot create a loss or make one bigger |
The engine applies the same two regimes to a panic sale part way through a window, on the view that shows what selling out cost, so the comparison between selling and holding carries its tax with it.
Inflation enters the engine in exactly one place. A running deflator starts at 1.0, and at the end of each financial year the engine multiplies it by one plus that year's inflation. If an inflation rate is chosen, the engine uses it; otherwise it uses the published rate for that financial year.
The tool replays history rather than simulating it. It holds the mix the user sets through every stretch of history the data can cover, and it reports one result per starting year.
Term deposits work differently from everything else the engine holds, because the year's locked rate is the year's return.
Draft, and the parity claim is Christoph's to own
The same calculation exists in two places: this browser engine, and the desktop tooling this practice uses in its own work. A fixed file of results sits beside the code, and the browser engine runs against it. That is 361,621 checks in all, across 30 scenarios, a per-year grid of 180 windows, and 2,770 sell-out cases. Today 0 of those checks disagree.
That was not so during the rebuild. Between 21 August and 4 September 2026 this engine moved away from the desktop engine five times, each time on purpose and each time recorded here with the count of checks it moved: the 2026 inflation rate finalised from 4.0942% to 3.9419% (2,022 checks); term deposits, which the desktop engine does not hold (none, since the fixed file cannot see them); the A-REIT distribution split of 27 August (2,468, all in the one scenario holding listed property); the credit premium on the bond sleeve of the same day, which reached every scenario holding a bond (100,982); and the contribution caps of 4 September, indexed to wages and rounded down to a step as the law has them (18,592). Those four counts add to the 124,064 disagreements this page reported on 4 September. On 5 September the desktop engine took on all of them except term deposits, which stay outside the fixed file and are checked against their own rules instead (233 checks, all passing); the fixed file was re-derived from the reconciled desktop engine; and the shared default-path fixture, which neither engine owns, was re-locked only after both engines matched the proposed file to the cent. Every one of the five had been attributed the same way before it was reconciled: put the old value back and the checks it moved agreed again exactly.
The reconciliation was the condition for this site going live, and it has passed. A future change to either engine is expected to move the fixed file again; the rule from here is that the two agree before a change ships, or this paragraph says what disagrees and why.
| Suite | Checks | Disagreeing | What it holds |
|---|---|---|---|
| tests/run_default_path.mjs | 2,426 | 0 | the shared fixture, which neither language owns. Three account types, the site's own first-load inputs, every valid 25 year window |
| tests/run_golden.mjs | 359,195 | 0 | the expanded grid: ending balances, contributions, tax paid, both capital gains regimes, money-weighted returns, the before-inflation pair, and every sell-out case |
| tests/check_term_deposits.mjs | 233 | 0 | term deposits: that the default is unchanged, that the sleeve computes, and that a window the series cannot cover is refused |
| tests/check_areit_and_credit.mjs | 123 | 0 | the A-REIT distribution split and the credit premium on the bond sleeve: that the split is a split, that the default mix cannot see it, and that each parameter moves a figure in the direction and by the amount the research behind it measured |
| tests/check_moves.mjs | 280 | 0 | the three moves of tab 7: that every new engine option is inert by default to the last bit, that never restoring the mix matches a hand stepper, that the chase rule looks at no future year and its extra cost is charged as a fund cost, that a cash sit which never ends is the stress test's own sold run, and that the figures at a zero credit premium reproduce the research brief the exhibit was planned on |
| tests/check_events.mjs | 91 | 0 | the life-events path of tab 8: that an empty path changes nothing to the last bit, that a lump leaving the account at a given age does what it says and taxes the gain outside super, that a contribution scale removes exactly the years it names, that a constant glide path is the plain run and a falling one is not, and that events combine and bad ones are refused |
| tests/check_careers.mjs | 22 | 0 | the career paths' income rules: the university and apprentice incomes by age, the year the apprentice's income reaches its multiple, the retraining stages (a stage dated before the study ends waits for it; no study years is a straight step), and the guarantee's excess over the concessional cap |
| tests/check_rentbuy.mjs | 25 | 0 | rent or buy: a constant-rate loan amortises to nothing over its term and its repayments match the annuity, the two households share the same money, a higher yield means more rent and less invested, and uncovered stretches and bad inputs are refused |
| tests/check_mortgage.mjs | 61 | 0 | the mortgage decision's three arms: a constant-rate paydown matches its closed form, a visitor's own discount sets the rate, a small loan clears and the surplus goes outside, the super and outside arms are ordinary runWindow scenarios, and uncovered years and bad inputs are refused |
| tests/check_property.mjs | 49 | 0 | the SMSF property leg of tab 8: the deposit leaves and the price and loan follow the LVR, running costs are charged empty or not, empty months lower the end, a long vacancy at a high LVR makes the member top up and, with the forced sale on, sells the property at the haircut, and the leg is refused outside super accumulation, without the loan-rate series, and with a drifting mix |
| tests/check_loanrate.mjs | 24 | 0 | investing against a loan rate, and the sell-out decision's own count: the loan side compounds at the rate exactly, a yearly amount matches its closed form, the invested side is an ordinary personal run after capital gains tax, a higher rate is beaten less often, the exhibit is refused inside super, and a package with nothing added to it finishes below one that is added to |
| tests/check_deploy.mjs | 37 | 0 | a lump sum at once or spread over several years: every arm puts in the same lump plus the interest the waiting money earned, that interest is the year's cash return after tax and nothing else, a spread arm rebuilt by hand matches to the last bit, a lump on day one equals an opening balance, the two kinds of lump are told apart, both ways won somewhere in the history, and a pension account is refused |
| tests/check_clock.mjs | 27 | 0 | the savings clock: one entry per length of stretch, every valid stretch run and only those, each entry the ordinary run of that stretch, a shorter length has at least as many stretches, saving for longer came to more at the median, the configuration says no house-price series feeds it, and a pension account is refused |
| tests/check_cgt2027.mjs | 40 | 0 | the 2027 capital gains change, pinned to the reading of the Act: with no inflation the 2027 rules tax the whole gain at the higher of the marginal rate and 30%, the floor bites at 19% and not at 45%, indexation lowers the tax below the flat figure, a loss pays nothing under either rule set, the funds carry no individual capital gains tax, the register carries the Act under its own name with the assent date, and the tab is gated until the reading is signed |
| tests/check_catchup.mjs | 29 | 0 | unused cap space used before a release age, the money then paid onto the loan: the take-home given up is the before-tax amount less the marginal rate, no space leaves the three arms the same run, more space widens the advantage over investing outside super, a balance above the limit cannot use the space at all, and the two ways of counting the loan differ by the starting loan and nothing else |
| tests/check_splitting.mjs | 31 | 0 | splitting contributions to an older partner: with nothing else changed the two arms are equal to the dollar, the concessional cap binds before the split so a couple cannot use two caps, a second account pays its own fixed cost, and starting a pension moves money out of super where its earnings are taxed at the marginal rate |
| tests/check_recycling.mjs | 61 | 0 | pension payments put back into super: a household that spends every payment leaves the two arms the same run, recycling leaves more inside super and less outside, the second account is merged at the end of the year it reaches the balance set, nothing goes back in after the age limit or above the cap and the rest is saved outside, and the tax-free proportion and the death benefits tax follow from the components |
| tests/check_scenario_panel.mjs | 28 | 0 | the Your Scenario panel's rules: each structure reads back as itself and the site defaults as the adviser structure, the SMSF keeps the platform cost, any hand change reads as custom, and a wage becomes a contribution at the guarantee rate |
| tests/check_site.mjs | 1,134 | 0 | not the engine: the pages against the data files, so a figure in the copy cannot drift from the figure in the code. This page is on that list |
Money is checked to the cent and rates to eleven decimal places. A check is one number in one window in one scenario, so the count runs to hundreds of thousands rather than dozens.
These are the limitations of the calculator:
Built by In Your Interest Financial Planning. In Your Interest Financial Planning Pty Ltd, ABN 28 094 300 464 is Authorised Rep. No 308161 of Fiduciary Duty Advisers Pty Ltd AFSL No 527434. Nothing on this page is advice to you or to your clients. Corrections are welcome and very much appreciated – contact us.