Module 1 · Mathematical Language and Quantitative Reasoning Module demo
Payment Fee & Rate Checker
A merchant payment dashboard.
Transcript
19 sentences · select one to jump thereCode lab
Run it yourself
The demo source in one language. Edit it, run TypeScript and Python right here, and compare with the expected output.
/**
* Fintech Math Bootcamp · Module 01 demo · Payment Fee & Rate Checker
* A small merchant's dashboard: one card payment comes in, a fee goes out, the payout lands.
* Around it: the day's approval rate, a cash-advance limit, a rate change reported three ways,
* money kept in integer cents, a half-cent rounded by an explicit rule, and a growth factor.
* Lessons 001–010. Synthetic example; not financial advice.
*/
// 002 · a function with a stated domain: fixed part plus a percentage, amounts of zero or more only
export function feeMills(amountCents: number, fixedCents: number, rateBp: number): number {
if (!Number.isInteger(amountCents) || amountCents < 0) throw new Error("Invalid amount");
// work in mills (tenths of a cent) so the percentage part stays exact: cents × bp / 1000
return fixedCents * 10 + (amountCents * rateBp) / 1000;
}
// 010 · half-up rounding to the cent under a decimal policy (integer mills in, integer cents out)
export function halfUpCents(mills: number): number {
if (!Number.isInteger(mills) || mills < 0) throw new Error("Nonnegative integer mills only");
return Math.floor((mills + 5) / 10);
}
// 009 · units: cents are the storage unit, currency units are for display
export const toDollars = (cents: number) => cents / 100;
// 001 · the payout equation: payout = amount − fee
export const payoutCents = (amountCents: number, feeCents: number) => amountCents - feeCents;
// 003 · a ratio needs a meaningful denominator
export function ratio(part: number, whole: number): number | null {
return whole > 0 ? part / whole : null;
}
// 004 · one rate change, three correct descriptions
export function rateChange(before: number, after: number) {
const delta = after - before;
return {points: delta * 100, basisPoints: delta * 10000, relative: before !== 0 ? delta / before : null};
}
// 008 · an inclusive bound: 0 ≤ request ≤ limit
export const withinLimit = (request: number, limit: number) => Number.isFinite(request) && request >= 0 && request <= limit;
// 006 · a sum starts at zero, a product starts at one
export const sum = (xs: number[]) => xs.reduce((s, x) => s + x, 0);
export const product = (xs: number[]) => xs.reduce((p, x) => p * x, 1);
// 007 · two fee tiers, two totals: solve x + y = count and a·x + b·y = fees
export function solveTiers(count: number, fees: number, low: number, high: number) {
const det = high - low;
if (det === 0) throw new Error("Equations are not independent");
const highCount = (fees - low * count) / det;
const lowCount = count - highCount;
if (low * lowCount + high * highCount !== fees) throw new Error("Solution fails verification");
return {lowCount, highCount};
}
// 005 · growth factor, root and logarithm
export function growth(start: number, factor: number, periods: number) {
const future = start * factor ** periods;
return {future, rootFactor: (future / start) ** (1 / periods), doublingPeriods: Math.log(2) / Math.log(factor)};
}
export function runDemo() {
// the payment
const amountCents = 8420, fixedCents = 30, rateBp = 250;
const mills = feeMills(amountCents, fixedCents, rateBp);
const feeCents = halfUpCents(mills);
const floatFee = 0.30 + 0.025 * 84.20; // what a quick float calculation holds
const payout = payoutCents(amountCents, feeCents);
// the day: approvals, ledger, reconciliation
const approved = 1862, attempted = 1960;
const approvalRate = ratio(approved, attempted);
const ledger = [1250, 840, -310, 420]; // opening balance, sales, refunds, more sales (dollars)
const tiers = solveTiers(10, 26, 2, 3);
// cash advance: the limit and the rate change
const limit = 5000;
const requests = [-50, 0, 3200, 5000, 5400].map(amount => ({amount, allowed: withinLimit(amount, limit)}));
const advanceRate = {before: 0.08, after: 0.09, ...rateChange(0.08, 0.09)};
// growth: monthly card volume growing 5% a month
const g = growth(20000, 1.05, 3);
return {
payment: {
amountCents, amount: toDollars(amountCents), fixedCents, rateBp, ratePct: rateBp / 100,
feeMills: mills, feeCents, fee: toDollars(feeCents),
floatFee, floatFeeToFixed: floatFee.toFixed(2), floatFeeRounded: Math.round(floatFee * 100) / 100,
payoutCents: payout, payout: toDollars(payout), domainOk: [0, 8420].map(a => a >= 0), negativeRejected: true,
},
day: {approved, attempted, approvalRate, approvalPct: approvalRate === null ? null : approvalRate * 100,
ledger, ledgerEnd: sum(ledger), tiers: {count: 10, fees: 26, low: 2, high: 3, ...tiers}},
advance: {limit, requests, rate: advanceRate},
growth: {start: 20000, factor: 1.05, months: 3, ...g, factors: [1.05, 1.05, 1.05], product: product([1.05, 1.05, 1.05])},
};
}
export const checkedResult = {"payment":{"amountCents":8420,"amount":84.2,"fixedCents":30,"rateBp":250,"ratePct":2.5,"feeMills":2405,"feeCents":241,"fee":2.41,"floatFee":2.405,"floatFeeToFixed":"2.40","floatFeeRounded":2.4,"payoutCents":8179,"payout":81.79,"domainOk":[true,true],"negativeRejected":true},"day":{"approved":1862,"attempted":1960,"approvalRate":0.95,"approvalPct":95,"ledger":[1250,840,-310,420],"ledgerEnd":2200,"tiers":{"count":10,"fees":26,"low":2,"high":3,"lowCount":4,"highCount":6}},"advance":{"limit":5000,"requests":[{"amount":-50,"allowed":false},{"amount":0,"allowed":true},{"amount":3200,"allowed":true},{"amount":5000,"allowed":true},{"amount":5400,"allowed":false}],"rate":{"before":0.08,"after":0.09,"points":0.9999999999999996,"basisPoints":99.99999999999994,"relative":0.12499999999999993}},"growth":{"start":20000,"factor":1.05,"months":3,"future":23152.500000000004,"rootFactor":1.05,"doublingPeriods":14.206699082890461,"factors":[1.05,1.05,1.05],"product":1.1576250000000001}};
// Run this file directly: npx tsx lessons/01-mathematical-language-and-quantitative-reasoning/demo-payment-fee-and-rate-checker.ts
if (process.argv[1] && import.meta.url.endsWith(process.argv[1].replace(/\\/g, "/").split("/").pop()!)) {
console.log(JSON.stringify(runDemo(), null, 2));
}
Your output
Press Run to execute the code in your browser.
Expected output
{
"payment": {
"amountCents": 8420,
"amount": 84.2,
"fixedCents": 30,
"rateBp": 250,
"ratePct": 2.5,
"feeMills": 2405,
"feeCents": 241,
"fee": 2.41,
"floatFee": 2.405,
"floatFeeToFixed": "2.40",
"floatFeeRounded": 2.4,
"payoutCents": 8179,
"payout": 81.79,
"domainOk": [
true,
true
],
"negativeRejected": true
},
"day": {
"approved": 1862,
"attempted": 1960,
"approvalRate": 0.95,
"approvalPct": 95,
"ledger": [
1250,
840,
-310,
420
],
"ledgerEnd": 2200,
"tiers": {
"count": 10,
"fees": 26,
"low": 2,
"high": 3,
"lowCount": 4,
"highCount": 6
}
},
"advance": {
"limit": 5000,
"requests": [
{
"amount": -50,
"allowed": false
},
{
"amount": 0,
"allowed": true
},
{
"amount": 3200,
"allowed": true
},
{
"amount": 5000,
"allowed": true
},
{
"amount": 5400,
"allowed": false
}
],
"rate": {
"before": 0.08,
"after": 0.09,
"points": 0.9999999999999996,
"basisPoints": 99.99999999999994,
"relative": 0.12499999999999993
}
},
"growth": {
"start": 20000,
"factor": 1.05,
"months": 3,
"future": 23152.500000000004,
"rootFactor": 1.05,
"doublingPeriods": 14.206699082890461,
"factors": [
1.05,
1.05,
1.05
],
"product": 1.1576250000000001
}
}Prefer your own machine? Every file is in the course repository · open it in Codespaces.
What the demo does
A small merchant dashboard: one card payment becomes a fee and a payout, the day gets an approval rate and a fee reconciliation, a cash advance meets its limit and its rate change is reported three ways, money stays in cents, a half-cent is rounded by rule, and a growth factor says when volume doubles.
Lessons it combines
- Variables, Constants, Expressions, and Equations
- Functions, Domains, Ranges, and Graphs
- Ratios, Proportions, Rates, and Percentages
- Percentage Change, Percentage Points, and Basis Points
- Exponents, Roots, and Logarithms
- Summation, Products, and Index Notation
- Linear Equations and Systems
- Inequalities, Bounds, and Constraints
- Units, Dimensions, Scale, and Normalization
- Rounding, Precision, Tolerance, and Significant Digits