The Machines · Runtime stack

seedfin

A reckoner seed: fin's time value of money, loans, capital budgeting, depreciation and payroll — machines/seeds/seedfin.shoddy

the seedfin machine's icon

Summary

seedfin is a reckoner seed: a small file that bridges one machine's words into the reckoner calculator. It bridges fin's rates, time value of money, growth, statistics, curve fitting, budgeting, loan amortization and payoff, NPV/IRR/payback, CAGR/ROI, dollar-cost averaging, margin and markup, break-even, payroll and depreciation. Per R4.16 there is no RECORD cell at the keyboard. So every Fin* record fin.shoddy returns is a dict here — a list of name-value pairs, the same LIST-of-PAIR shape seeddict already established, one entry per field.

Why It's Useful

Several words pre-flight a condition fin.shoddy itself Errors on — they test it up front rather than let fin abort:

The model a fit is given is a word

FINFITOF takes the two columns and a model. The model is a word — FINLINEAR, FINLOGMODEL, FINEXPMODEL, FINPOWERMODEL — for the same reason the day-count bases below are. A session reads FINLOGMODEL instead of 2. And a mistyped model is an unknown word, rather than a different curve fitted in silence.

Four of the guards are conditions fin.shoddy already Errors on by name: the three model domains — a logarithm of a non-positive x, an exponential of a non-positive y, a power model needing both — and a model it does not recognise. The fifth is one fin does not state, and it is the one a session meets first. LinFit divides by the variance of the x column — variance measures how much the values spread out. Correl divides by the product of the two standard deviations. So a column that does not vary divides by zero, and the runtime ends the run. The seed's test is exact equality of every element, not a tolerance, because that is precisely when those denominators are exactly zero. A nearly-constant column gives a very large slope. That is fin's answer, and not this seed's to overrule. One such test covers all four models, because the logarithm is injective — it never turns two different inputs into the same output.

The lengths are checked too, though nothing aborts on a mismatch — which is why they need checking. Cov zips the two lists — pairs them up element by element — and the zip stops at the shorter list. So a mismatched pair would otherwise answer a fit of the overlap against the means of the whole. That is a wrong number rather than a refusal, and that is the failure this layer exists for.

The day counts, and the bond pricer standing on them

fin carries a second subsystem — the day-count bases, and a bond pricer built on them — and it is bridged in full. A date is a dict: { ("yr" n) ("mon" n) ("day" n) }, built by seedjulian's JULDATE. The calendar words lived here as FINDATE and friends while fin carried the calendar itself. They moved to seedjulian, renamed, when the calendar moved to julian. The dict shape did not change, so a date built there flows straight into FINDAYS360 and the bond words.

The day-count bases and coupon frequencies are words rather than numbers to remember. fin spells them as zero-argument definitions because Shoddy has no enum — no built-in type for a fixed set of named choices. The same choice here means a session reads "S" RCL "M" RCL 0.05 P FINSEMI FIN360 FINYTM rather than … 2 1 …. A mistyped basis is an unknown word instead of a wrong answer.

Why this subsystem needed more guarding than the rest of the seed

Almost nothing here aborts on bad input, which is exactly the problem. JulSerial is integer arithmetic with no opinion about whether a date exists. It serializes a date — turns it into a plain day number — and it serializes a 30th of February perfectly happily to the 2nd of March. FinYearFrac falls through to actual/365.25 for any basis it does not recognise. FinLastCoupon steps back by 12 / freq whole months whether or not that divides evenly.

Every one of those is a wrong answer rather than a refusal. A wrong answer about money is the failure this whole seed layer exists to prevent. So every word that takes a date checks it on the way in — a dict can also arrive hand-built. And the basis, the frequency and the yield are each refused when they are outside what the arithmetic underneath can mean.

The one genuine abort is FinYtm's, when no yield between 0 and 2 prices the bond. It is guarded the way FINIRR's twin already is: the same test asked first, and refused instead.

User's Guide

A five percent bond, paying twice a year, settling on a coupon date five years before it matures. At a yield equal to its coupon it must be worth exactly par — its face value. That is arithmetic anyone can check:

> 2025 1 15 JULDATE "S" STO  2030 1 15 JULDATE "M" STO
ok: S
ok: M
[ empty ]
> "S" RCL "M" RCL FINSEMI FINCOUPONSBEFORE
x: 10
> "S" RCL "M" RCL 0.05 0.05 FINSEMI FIN360 FINBONDPRICE
x: 100
> "S" RCL "M" RCL 0.05 0.08 FINSEMI FIN360 FINBONDPRICE
x: 87.83365633
> "S" RCL "M" RCL 0.05 100 FINSEMI FIN360 FINYTM
x: 0.05
> "S" RCL "M" RCL 0.05 0.05 FINSEMI FINMDUR
x: 4.376031965
> "S" RCL 2024 7 15 JULDATE 0.05 FINSEMI FIN360 FINACCRUED
x: 2.5

The day counts underneath it, where the whole point is that the bases disagree:

> 2025 1 1 JULDATE 2026 1 1 JULDATE FIN360 FINDATEDIFF
x: 360
> 2025 1 1 JULDATE 2026 1 1 JULDATE FINACTUAL FINDATEDIFF
x: 365

And the refusals, every one of which would otherwise have been a number:

> 2025 1 1 JULDATE 2026 1 1 JULDATE 9 FINYEARFRAC
?: FINYEARFRAC: THAT IS NOT A DAY-COUNT BASIS — USE FINACTUAL, FIN360 OR FIN365
> "M" RCL "S" RCL 0.05 0.05 FINSEMI FIN360 FINBONDPRICE
?: FINBONDPRICE: SETTLEMENT MUST FALL BEFORE MATURITY
> "S" RCL "M" RCL 0.05 5000 FINSEMI FIN360 FINYTM
?: FINYTM: NO YIELD BETWEEN 0 AND 2 PRICES THIS BOND AT 5000

Word Reference

GroupWords
Rates, conversionFINPCT FINASPCT FINEFF FINNOM FINRULE72 FINREAL FINPCTCHG FINTOBPS FINFROMBPS
Time value of moneyFINPV FINFV FINPVANN FINFVANN FINPVANNDUE FINFVANNDUE FINPMT FINPMTDUE FINNPER FINSIMPLE FINCOMPOUND
StatisticsFINSUM FINMEAN FINSTDDEV FINSTDDEVP FINVAR FINVARP FINMEDIAN FINQUANTILE FINMINIMUM FINMAXIMUM FINRANGEOF FINSKEWNESS FINKURTOSIS FINWEIGHTEDMEAN FINGEOMEAN FINCORREL FINCOV FINSPEARMAN FINNORMP FINTDIST FINSTAT1
Curve fittingFINFITOF FINLINEAR FINLOGMODEL FINEXPMODEL FINPOWERMODEL
Budgeting, saving, investingFINGOALPMT FINRETIRE FINNETWORTH FINBUDGETOF FINDCAOF
Loans: amortization, payoffFINBALANCE FINAMORTAT FINSCHEDULE FINEXTRAPAYOFF FINCARDPAYOFF FINCARDMINPAYOFF
Capital budgetingFINNPV FINNPVOF FINIRR FINNFV FINMIRR FINPAYBACK FINPAYBACKDISC
Growth, margin, break-even, payroll, depreciationFINCAGR FINROI FINRSTAT FINYIELD FINDIVGROWTH FINMARGINOF FINMARKUPOF FINSELLFROMMARGIN FINCOSTFROMMARGIN FINBREAKEVENOF FINPAYROLLOF FINSL FINSLBOOK FINSYD FINDB FINFACT FINCOMB FINPERM
Bases and frequenciesFINACTUAL FIN360 FIN365 FINANNUAL FINSEMI FINQUARTERLY
The day countsFINDAYS360 FINDATEDIFF FINYEARFRAC
BondsFINCOUPONSBEFORE FINLASTCOUPON FINACCRUED FINBONDPRICE FINYTM FINMDUR

The day counts and the bonds in full, since neither reads like the rest of the seed. The calendar words that once sat above these — FINDATE through FINDATEADDMONTHS — are seedjulian's now, spelled JUL*:

WordDescription
FINDAYS360 ( a b -- n )Days from a to b on the NASD 30/360 rule.
FINDATEDIFF ( a b basis -- n )Days from a to b, counted on the given basis.
FINYEARFRAC ( a b basis -- n )The fraction of a year from a to b on the given basis.
FINCOUPONSBEFORE ( settle maturity freq -- n )How many coupons — the bond's regular interest payments — are still to come between settlement and maturity.
FINLASTCOUPON ( settle maturity freq -- date )The coupon date on or before settlement — what FINACCRUED accrues from.
FINACCRUED ( settle lastcoupon coupon freq basis -- n )Interest earned since the last coupon and not yet paid, per 100 of face. coupon is a rate: 0.05 for a five percent bond.
FINBONDPRICE ( settle maturity coupon yld freq basis -- price )The clean price per 100 of face — accrued interest excluded, which is what a quoted price means. FINACCRUED is the rest of it.
FINYTM ( settle maturity coupon price freq basis -- yield )The yield to maturity that prices the bond at price. Refuses when no yield between 0 and 2 does.
FINMDUR ( settle maturity coupon yld freq -- years )Modified duration in years: roughly how much the price moves for a one-point move in yield.

Who Uses It

UserHow
halifaxThe calculator's finance words — every group above.
sparkySparky folds it too, so a model calling eval reaches the same words halifax puts at a prompt.

A mill claims this seed by folding RckSeedFin over its reckoner state. That is all halifax does.

The Machines It Uses

MachineWhy
cuttleThe Cell type every bridged word reads its arguments from and answers into.
finThe domain this seed bridges.
reckonerRckReg and the argument readers every registered word is built from.
seqList plumbing under every dict and list converter.
julianThe calendar rules every arriving date dict is checked against, and the JulDate the bond words consume.