Showing the Power of RS-X with a “Scary” Credit-Risk Formula
Source: Dev.to
A “scary” credit‑risk formula
Below is a credit‑risk formula written in TypeScript that pulls together several data sources.
Model definitions
// Model
export interface ICustomer {
age: number;
income: number;
employmentYears: number;
}
// Credit info
export interface ICredit {
score: number;
outstandingDebt: number;
}
// Market parameters
export interface IMarket {
baseInterestRate: number;
}
// Risk parameters
export interface IRisk {
volatilityIndex: number; // e.g., market volatility
recessionProbability: number; // e.g., probability of economic downturn
}
// Risk calculation parameters
export interface IRiskCalcParameters {
readonly market: IMarket;
readonly risk: IRisk;
}
// Asynchronous data sources (simulating API calls)
export interface IRiskModel {
readonly customer: BehaviorSubject;
readonly credit: BehaviorSubject;
readonly riskParameters: BehaviorSubject;
}
The monolithic formula
(
(credit.score = 0.75 ? 'HIGH' : (
(
(credit.score = 0.45 ? 'MEDIUM' : 'LOW'
);
Even if you start with one huge formula, RS‑X lets you transform it into reactive expressions.
Splitting the formula with RS‑X
The data model is simple:
- Customer info
- Credit info
- Market / risk parameters
These values may change independently or arrive asynchronously. RS‑X doesn’t care; you just plug them into expressions and updates flow automatically—no listeners, no manual subscriptions, no explicit recalculateRiskScore() calls.
Sub‑expressions
// Baseline personal risk
const basePersonalRisk = expressionFactory.create(model, `
(credit.score ;
// Age‑based adjustment
const ageBasedRiskAdjustment = expressionFactory.create(_model, `
customer.age ;
// Market risk component
const marketRisk = expressionFactory.create(_model, `
(riskParameters.risk.volatilityIndex * 0.5) +
(riskParameters.risk.recessionProbability * 0.5)
`) as IExpression;
// Interest‑rate impact
const interestRateImpact = expressionFactory.create(_model, `
riskParameters.market.baseInterestRate * 2
`) as IExpression;
Combining the pieces
const riskScore = expressionFactory.create({
basePersonalRisk,
ageBasedRiskAdjustment,
marketRisk,
interestRateImpact
}, `
basePersonalRisk + ageBasedRiskAdjustment + marketRisk + interestRateImpact
`);
const riskClassification = expressionFactory.create({
riskScore: riskScore as IExpression,
thresholds: { highRisk: 0.75, mediumRisk: 0.45 }
}, `
riskScore >= thresholds.highRisk
? 'HIGH'
: riskScore >= thresholds.mediumRisk
? 'MEDIUM'
: 'LOW'
`);
Each sub‑expression recalculates only when its inputs change, giving you both readability and performance.
Other use cases
The same pattern works for:
- Pricing rules
- Validation logic
- Feature flags
- Scoring models
- UI state
…basically anything you can imagine.
Takeaways
- Messy formulas don’t need messy code.
- RS‑X can split monolithic expressions automatically.
- Async and sync data mix effortlessly.
- Updates propagate automatically and efficiently.
RS‑X lets you describe what your logic is, not how to keep it up to date. Even a “scary” formula becomes readable, modular, efficient, and surprisingly calm.
Demo
You can see this in action with a live demo on StackBlitz:
StackBlitz demo
References
- RS‑X GitHub
- NPM packages:
@rs-x/core@rs-x/state-manager@rs-x/expression-parser@rs-x/angular