Formula Language Guide
Formulas are the key to customizing your FinZot plan. They replace static numbers with dynamic logic, allowing the plan to react to changing conditions over time.
If you’re comfortable in Excel or Google Sheets, this syntax will feel familiar. Each formula is a standalone expression that returns one of two things:
- A Number: Used for any amount, such as a custom income or expense.
- A Boolean (
TRUE/FALSE): Used to trigger milestones or control conditional logic.
For a complete list of all available planner fields (like net_worth or age_primary), see the Planner Context Reference.
Syntax Essentials
Section titled “Syntax Essentials”Data Types & Literals
Section titled “Data Types & Literals”- Numbers: All numbers are 64-bit floats. You can write them in several ways:
123(whole number)1_000_000(underscores as visual separators, ignored by the engine)45.67(decimal)10%(percentage, becomes0.1).75%(leading decimal, becomes0.0075)
- Booleans: Simple
TRUEorFALSEvalues. - Variables: These are fields from the planner, like
invested_assetsortotal_debt. - Comments: Use
//to add a comment. The engine will ignore everything after it on that line.invested_assets * 1.1 // Add a 10% raise
- Case Insensitivity: All variables, function names, and keywords (
IF,AND,TRUE, etc.) are case-insensitive.age_primaryis the same asAge_Primary.
Operators
Section titled “Operators”The language supports standard arithmetic, comparison, and logical operators.
| Category | Operators | Description |
|---|---|---|
| Grouping | ( ... ) | Controls the order of operations. |
| Exponent | ^ | Exponentiation (e.g., 2 ^ 3 is 8). |
| Arithmetic | *, / | Multiplication and Division. |
+, - | Addition and Subtraction. | |
| Comparison | =, !=, <> | Equal, Not Equal. |
>, >=, <, <= | Greater Than, Less Than (or Equal). | |
| Logical | NOT | Inverts a boolean (NOT TRUE is FALSE). |
AND | TRUE if both sides are TRUE. | |
OR | TRUE if at least one side is TRUE. |
The AND and OR operators are “short-circuiting.” This means they stop evaluating as soon as they have an answer.
Order of Operations
Section titled “Order of Operations”Operators follow standard precedence (like PEMDAS/BODMAS). ^ is evaluated first, then * and /, then + and -. AND is evaluated before OR.
When in doubt, use parentheses () to make your logic clear.
((taxable_balance + roth_balance) >= 1_500_000) AND (NOT debt_free)Built-in Functions
Section titled “Built-in Functions”Functions are powerful tools for more complex logic.
Conditional Logic (IF / CASE)
Section titled “Conditional Logic (IF / CASE)”These functions let you choose a value based on one or more tests.
-
IF(condition, then_value, else_value)Returnsthen_valueif theconditionisTRUE, otherwise returnselse_value.// Spend 5k on vacation if is over 65, otherwise 2kIF(age_primary >= 65, 5000, 2000) -
IFS(condition1, value1, [condition2, value2], ...)Evaluates pairs of conditions and values. It returns the value for the first condition that isTRUE. If no conditions are true, it returns0.0.Tip: Use
TRUEas your final condition to create a default “else” value.IFS(net_worth > 5_000_000, 0.02,net_worth > 1_000_000, 0.01,TRUE, 0.0) -
CASE WHEN condition1 THEN value1 ... [ELSE else_value] ENDA readable, SQL-style alternative toIFS. It returns theTHENvalue for the firstWHENcondition that is met. If no conditions match, it returns theELSEvalue or0.0ifELSEis omitted.// Set a spending goal based on the plan yearCASEWHEN calendar_year <= 2040 THEN 75_000WHEN calendar_year <= 2045 THEN 80_000ELSE 85_000END
Logical Functions (AND, OR, NOT)
Section titled “Logical Functions (AND, OR, NOT)”These functions are identical to the AND, OR, and NOT operators but can be more familiar for excel users.
AND(expr1, expr2, ...): ReturnsTRUEif all arguments areTRUE.OR(expr1, expr2, ...): ReturnsTRUEif any argument isTRUE.NOT(expr): Inverts a single boolean expression.
AND( age_primary > 50, net_worth > 1_000_000, debt_free)Math Functions
Section titled “Math Functions”MIN(num1, num2, ...): Returns the smallest number from the list.MAX(num1, num2, ...): Returns the largest number from the list.// Calculate net savings, but ensure it's never less than zeroMAX(0, net_worth - total_debt)// Cap a withdrawal at 50,000MIN(FUTURE_DOLLARS(40000), 50000)ABS(number): Returns the absolute (non-negative) value of a number.// Find the difference between two balances, regardless of which is largerABS(roth_balance - traditional_balance)POWER(base, exponent): Raises a number to a power. (Identical to the^operator).// Calculate 1.03 compounded for (age - 20) periodsPOWER(1.03, age_primary - 20)
Time-Series & Rolling Functions
Section titled “Time-Series & Rolling Functions”These advanced functions look at data from previous years, enabling you to model trends, smooth volatility, or create time-based triggers.
IMPORTANT: The first argument to
LAG,PCT_CHANGE, and allROLLING_functions must be a raw planner field (e.g.,net_worth). You cannot use an expression (e.g.,net_worth - total_debt).
Point-in-Time Lookups
Section titled “Point-in-Time Lookups”-
LAG(variable, periods)Retrieves the value of avariablefrom a specific number ofperiods(years) ago.LAG(net_worth, 0)returns the current year’s value.// Calculate this year's savings by comparing current and prior net worthnet_worth - LAG(net_worth, 1) -
PCT_CHANGE(variable, periods)Calculates the percentage change between the current value and the value fromperiodsago:(current - past) / past.periodsmust be1or greater. It returns0.0if the past value is zero or invalid.// Trigger a milestone if net worth dropped more than 20% in the last yearPCT_CHANGE(net_worth, 1) < -0.20
Rolling Window Aggregations
Section titled “Rolling Window Aggregations”These functions compute a single statistic by looking at a “window” of the last periods years (inclusive of the current year).
ROLLING_SUM(variable, periods): Total sum over the window.ROLLING_AVG(variable, periods): Simple average over the window.ROLLING_MIN(variable, periods): Smallest value in the window.ROLLING_MAX(variable, periods): Largest value in the window.
These are powerful when combined with CASE to create “guardrails” or smooth out volatile values.
// Set a variable withdrawal rate based on the 3-year average of net worthCASE WHEN ROLLING_AVG(invested_assets, 3) < 1_000_000 THEN 0.035 // 3.5% rate WHEN ROLLING_AVG(invested_assets, 3) < 3_000_000 THEN 0.040 // 4.0% rate ELSE 0.045 // 4.5% rateENDTip: Rolling Functions in Early Years
Rolling functions still run in the first few years of a plan, but they operate on a partial window.
ROLLING_AVG(net_worth, 3)in Year 2 will give you the average of Year 1 and Year 2.ROLLING_AND(debt_free, 3)will returnTRUEin Year 1 and Year 2 by default.
Rolling Logic
Section titled “Rolling Logic”These functions look at a window of boolean values.
ROLLING_AND(bool_variable, periods):TRUEif the variable wasTRUEfor all years in the window.ROLLING_OR(bool_variable, periods):TRUEif the variable wasTRUEfor at least one year in the window.
// Trigger a milestone if...OR( // 1. The 3-year minimum net worth ever dropped below 1M ROLLING_MIN(net_worth, 3) < 1_000_000,
// 2. OR not yet debt-free NOT debt_free)// Go on a 5,000 vacation, but only if been debt-free for 3 straight yearsIF(ROLLING_AND(debt_free, 3), 5000, 0)