Skip to content

nabla v2.4.0

Choose a tag to compare

@ryanduguid ryanduguid released this 18 Aug 15:33
· 48 commits to main since this release

Two functions that were named as known and not fixed in the v2.3.0 notes.

nb.PeriodStartλ returned a date that is not a period start whenever the anchor is a month end

It walked the calendar to the period's month, rebuilt the date with the anchor's day of the month, and corrected whatever overflowed by exactly one day. Anchored on 31 January, monthly, that asks for 31 February: Excel reads it as 3 March, one day back off it is 2 March, and 2 March is in neither the right month nor on any period boundary. 28 February, which is where that period does start, was unreachable.

A schedule anchored on a month end is what EDATE describes: the anchor's day of the month where the target month has one, the month's own end where it does not, so 31 January monthly runs 31 Jan, 28 Feb, 31 Mar. The procedure now counts the whole periods from the anchor to the date of interest and steps the anchor on by that many, then steps back one period where a truncated quotient overshoots.

Measured against that schedule over 9,900 cases, being eleven anchors by five period lengths by 180 dates at 13-day steps from January 2024, the old procedure was wrong 169 times. Every one had an anchor on the 29th, 30th or 31st, 29 February included. Anchors on the 1st, 15th and 28th were already right and answer exactly as before.

nb.PeriodStartλ("31/1/2026", 1, "5/3/2026")
v2.3.0   2 March 2026
v2.4.0   28 February 2026

nb.TimelineOffsetλ divided by zero on every daily, weekly and fortnightly timeline

It reads the interval off the timeline's first two dates and rounds it to whole months, which is zero for anything shorter than about a fortnight, and the next line divides by it. Every such call returned #DIV/0!.

A sub-monthly period is a fixed number of days, so the offset is now the day difference floored by that count: a date 20 days into a weekly timeline is in period 2, one three days before it starts is in period -1. The month path is untouched and answers exactly what it answered before on monthly, quarterly and yearly timelines, month-end anchored ones included, over 200 dates at 11-day steps.

This does not make nb.Amortiseλ work on a sub-monthly timeline. It calls nb.TimelineOffsetλ on whatever timeline it is handed, so it did inherit this failure, but it rounds the same interval to months itself and then divides twelve by it, so a weekly timeline still fails there on its own arithmetic. nb.Depreciateλ holds a third copy of the rounding and turns nought months into #N/A. Neither is changed here.

Verification

Gate Result
verify_workbook 130 functions, 211 parts
verify_sources src reproduces all 130, every date conversion read
verify_signatures 117 signatures, 122 parameter tables, 119 example blocks
verify_previous_names 130 one-to-one against v1.2.6
verify_cache all 20,221 cached values match their formulas
excel_selftest 195 of 195, 1,129 formulas, 0 error cells

tools/excel_selftest.ps1 gains 43 assertions, 152 to 195. Nineteen compare nb.PeriodStartλ against an EDATE schedule written out in the test rather than borrowed from the function, and four hold nb.TimelineOffsetλ's month path to the same comparison, so a later change cannot quietly redefine what a period start is.

Only xl/workbook.xml and the formula-environment store changed. No worksheet part differs from v2.3.0 and all 20,221 cached values are identical: the sheet that demonstrates nb.TimelineOffsetλ uses a monthly timeline, and no sheet calls nb.PeriodStartλ.

Known and not fixed

  • nb.Amortiseλ and nb.Depreciateλ each hold their own copy of the months-per-period rounding and still fail on sub-monthly timelines, as above.
  • nb.InterestLRVλ is not cap-aware, so in the one period where the cap binds it understates the interest it reports. Balances are unaffected.
  • nb.TimelineOffsetλ's worked example is missing two closing brackets and prints no result, so it cannot be copied.
  • The repository still states no licence for its own tooling.

Asset

nabla.xlsx, 435,780 bytes, sha256 29d641761e01367e623ec588874d712fe17298f314efc5acef5e5c898bb4da35.