Skip to content
All posts
ConfigurationInsurers

The formula language: premium rules you can read

Every calculation on BimaStack is written in one small, spreadsheet-like language. Values, conditions, functions, dates, currency and rounding, with examples from real rate cards.

The BimaStack team · · 7 min read

Every calculation on BimaStack, from a base premium to an age loading to “is this traveller over 80”, is written in one small language. If you can write an Excel formula, you can write one of these. This guide walks through everything it can do, with examples from real rate cards. The reference has the exact rules.

A formula is one expression

A formula is a single expression, read like a spreadsheet cell: no statements, no braces, no programming. It uses the names of the values it is given (the vehicle’s value, the driver’s age, the running total so far) and returns one result.

Three formulas
vehicleValue * 3.5 / 100

if(driverAge < 25, 1.15, 1.0)

max(rawPremium, minimumPremium)

Three kinds of value

Kind Written as Example
NumberDigits, with an optional decimal point0.16, 2500, 1.15
TextIn double quotes"PSV", "EUROPE_SCHENGEN"
Yes/notrue or falsewinterSports, true

A name refers to a value the formula is given. Names are letters, digits and underscores, and may be dotted, like rate.value. A choice from a fixed list (a cover type, a zone) arrives as text, so you compare it with == "PSV".

Arithmetic

Plus, minus, times and divide, with brackets, in the usual order: brackets first, then * and /, then + and -. A minus in front of a value negates it.

A percentage rate, a band width, a discount
sumInsured * rate / 100

(bandTo - bandFrom) * ratePerUnit

-1 * runningTotal * 0.10

Comparisons and conditions

Compare with == (equals), != (not equal), <, <=, > and >=. Combine with the words and, or and not. A comparison gives yes or no.

Conditions
driverAge >= 18 and driverAge <= 65

usage == "PSV" or usage == "COMMERCIAL"

not winterSports

One thing to know: comparisons don’t chain. Write 18 <= age and age <= 65, not 18 <= age <= 65. The editor tells you if you try.

if: choose a value

if(condition, value when yes, value when no) works exactly like Excel’s IF. Both answers must be the same kind (two numbers, or two texts). Only the branch that applies is worked out, so if(count == 0, 0, total / count) never divides by zero.

An age factor from a travel rate card: nested ifs, read top to bottom
if(age < 18, 0.5,
  if(age <= 65, 1.0,
    if(age <= 75, 1.5,
      if(age <= 80, 2.0, 4.0))))
A group discount by headcount, as a percentage
if(groupSize >= 201, 25,
  if(groupSize >= 101, 20,
    if(groupSize >= 51, 15,
      if(groupSize >= 21, 10,
        if(groupSize >= 10, 5, 0)))))

Built-in functions

Function What it does Example
min(a, b), max(a, b)The smaller or larger of two numbers: floors and capsmax(premium, 7500)
round(x, places, mode)Rounds to 0–10 places by a named mode: "HALF_EVEN", "HALF_UP", "HALF_DOWN", "UP", "DOWN", "CEILING", "FLOOR"round(premium, 2, "HALF_EVEN")
ageInYears(birth, onDate)Completed years between two dates (yyyy-MM-dd)ageInYears(dateOfBirth, coverStart)
daysBetween(from, to)Days from one date to another, not counting the firstdaysBetween(coverFrom, coverTo) + 1
convert(amount, from, to)Converts between currencies at the published rateconvert(limit, "USD", "KES")
prorate(amount, from, to, type)Scales an annual amount to the cover period: "FULL_TERM" or "PRORATED" (days ÷ 365)prorate(premium, coverFrom, coverTo, "PRORATED")

Rounding is usually left to the end. Use round when a rule says to round first: each traveller’s premium before adding them up, or up to the next 5 shillings with round(x / 5, 0, "CEILING") * 5. A currency conversion uses one rate for the whole calculation, so two conversions of the same pair always agree.

let: name a step

Start a formula with one or more lets to name a part of it and use it after. Each ends with a semicolon, and the last line is the result.

A loading per child above the four included
let extraChildren = max(childCount - 4, 0);
extraChildren * 1500
Days of cover, counting both ends or not, from the table’s own convention
let days = if(convention == "INCLUSIVE",
              daysBetween(coverFrom, coverTo) + 1,
              daysBetween(coverFrom, coverTo));
days >= bandFrom and days <= bandTo

A let can’t reuse a name already given, so a formula always means one thing when read from the top.

Mistakes are caught before you save

Every formula is checked as you type, and one with an error can’t be saved. The check runs in four stages, and each message points at the exact place:

Stage Catches Example message
SyntaxA missing bracket, a stray symbolUnexpected '!'. Use 'not' for negation.
ReferenceA name or function that doesn’t exist here, with a suggestionUnknown variable 'driverAg'. Suggestion: Did you mean 'driverAge'?
TypeAdding text to a number, a wrong number of argumentsif()'s two branches must have the same type, found NUMBER and STRING.
Risk (a warning)Something that will fail when it runsDivision by a literal zero will always fail at evaluation time.

A risk warning doesn’t stop you saving; the first three do. What no check can catch is a formula that is valid but means the wrong thing (10% of the sum insured when you meant 10% of the running total), which is what trying it is for.

Try it

Give the formula sample values and see the result, worked out by the same engine that prices live quotes. Then try it inside its workflow, against your real rate tables, and read the result of every step.

What it deliberately leaves out

  • No loops or lists. Working over a list of travellers or rate rows is a workflow’s job: it runs your formula once per item. One formula stays one readable line of logic.
  • No lookups. Rates come from rate tables, read by a workflow and handed to the formula as a value.
  • No side effects. A formula computes a value and nothing else, so the same inputs always give the same answer.

Where formulas live

You write a formula inside a workflow step, or once under a name to be reused by many workflows. Either way it is saved as a version that never changes: an edit makes a new version, and a quote always records which version priced it. Built-in calculations such as reading a rate table are written in this same language, so nothing is hidden from you.

Write your first formula

Register your company and open the formula editor.

Register an insurer