Analytics
The @openinsure/analytics package provides portfolio KPI computation, Workers AI-powered predictive modeling, AI cost anomaly detection, and event tracking via Tinybird. It is consumed by the API worker's analytics routes and by the Finance/Carrier portals.
Modules
Portfolio KPIs (compute.ts)
computeMGAKPIs(policies, claims, submissions)
Computes the full MGA portfolio metrics snapshot:
const kpis = computeMGAKPIs(policies, claims, submissions);
// Returns: MGAPortfolioKPIs
Output:
| Field | Description |
|---|---|
grossWrittenPremium | Sum of grossPremium across active/issued/renewed policies |
earnedPremium | GWP × 0.85 (earned premium factor) |
totalIncurred | Sum of paidAmount + reserveAmount across all claims |
lossRatio | totalIncurred / earnedPremium |
expenseRatio | 12% of earned premium (MGA default) |
combinedRatio | lossRatio + expenseRatio |
gwpByLob | GWP breakdown by line of business |
gwpByState | GWP breakdown by state |
submissionCount | Total submissions in pipeline |
boundRate | Submissions with status = 'bound' / total |
producerRankings | Top producers by GWP contribution |
computeCaptiveKPIs(policies, claims, members)
Captive-specific fund analysis:
| Field | Description |
|---|---|
fundBalance | Net fund position |
memberContributions | Total premium contributions |
claimReserves | Active claim reserve total |
ibnrEstimate | Case reserves × 15% |
stopLossPenetrations | Members approaching specific stop-loss attachment |
premiumToSurplusRatio | Regulatory solvency indicator |
summarizeClaims(claims)
Claims summary for dashboard widgets:
const summary = summarizeClaims(claims);
// { openCount, closedCount, totalPaid, totalReserved, totalIncurred, avgCycleTimeDays, ibnrEstimate }
computeSubmissionPipelineKPIs(submissions)
Submission funnel metrics:
const pipeline = computeSubmissionPipelineKPIs(submissions);
// { inQueue, autoAccepted, autoReferred, autoDeclined, avgAppetiteScore, premiumIndicated }
Predictive Modeling (predict.ts)
Workers AI-powered financial forecasting. Calls the CF Workers AI binding with a structured JSON schema for deterministic output.
predictLossRatio(input: LossRatioPredictionInput)
Forecasts loss ratio for a given LOB using historical performance and macro factors:
const forecast = await predictLossRatio(
{
lineOfBusiness: 'Commercial Auto',
historicalLossRatios: [0.62, 0.58, 0.71, 0.65], // prior 4 years
premiumTrend: 0.08, // 8% premium growth
claimFrequencyTrend: 0.03, // 3% frequency increase
macroFactors: {
inflation: 0.04,
socialInflation: 0.06,
economicCycle: 'expansion',
},
},
aiBinding
);
// Returns: LossRatioPrediction
// { forecastLossRatio, lowerBound90, upperBound90, trend, keyDrivers[] }
scorePricingAdequacy(currentPremium, predictedLossRatio, expenses)
Evaluates whether current pricing is adequate:
const adequacy = scorePricingAdequacy(1_200, 0.68, 0.15);
// { adequate: false, score: 42, deficiencyPercent: 0.17, recommendedAdjustment: 1.24 }
Retention & Portfolio Health (predictive.ts)
scoreRetention(policy, claims, paymentHistory)
Predicts renewal retention risk:
const score = scoreRetention(policy, claims, payments);
// { score: 78, riskLevel: 'medium', factors: ['3 claims this term', 'premium increase > 15%'] }
Risk levels: low (80+) · medium (60–79) · high (40–59) · critical (<40)
findCrossSellopportunities(insured, policies)
Identifies cross-sell opportunities based on current coverages and industry:
const opps = findCrossSellOpportunities(insured, activePolicies);
// [{ recommendedLob: 'Cyber', estimatedPremium: 4800, priority: 'high', reasoning: '...' }]
Premium factors by LOB: GL 1.0× · WC 1.2× · BOP 0.8× · Commercial Auto 1.1× · Cyber 2.2×
computePortfolioHealth(policies)
Portfolio concentration and at-risk premium analysis:
const health = computePortfolioHealth(policies);
// { concentrationIndex, topLobs, topStates, atRiskPremium, herfindahlIndex }
herfindahlIndex > 0.25 signals dangerous concentration in a single LOB or state.
AI Spend Monitoring (ai-spend.ts)
detectSpendAnomaly(dailyCosts, multiplier?)
Detects AI API cost spikes using a rolling 7-day average:
const result = detectSpendAnomaly(last30Days, 3.0);
// { isAnomaly: true, currentCost: 142.50, avgCost: 38.20, ratio: 3.73 }
Default multiplier is 3.0 — anything 3× the rolling average triggers an anomaly alert. Used by the cron job (apps/api/src/cron/portfolio-sweep.ts) to emit a queue event when AI costs spike.
Event Tracking
Tinybird Integration
import { trackEvent } from '@openinsure/analytics';
await trackEvent(
'submission.quoted',
{
submissionId: 'sub_123',
orgId: 'org_456',
premium: 12500,
lineOfBusiness: 'GL',
state: 'NC',
},
env.ANALYTICS_ENGINE
);
Events flow to Tinybird via Cloudflare Analytics Engine. The ANALYTICS_ENGINE binding is configured in wrangler.toml under [analytics_engine_datasets].
Analytics Engine (CF Native)
For high-throughput events (policy bound, claim opened, payment processed), the API writes directly to the CF Analytics Engine binding — zero latency, no HTTP call:
env.ANALYTICS_ENGINE.writeDataPoint({
blobs: [submissionId, orgId, lob, state],
doubles: [premium, claimCount, reserveAmount],
indexes: [orgId],
});
API Routes
The analytics package powers these API endpoints:
| Route | Description |
|---|---|
GET /v1/analytics/mga | MGA portfolio KPIs |
GET /v1/analytics/captive | Captive fund KPIs |
GET /v1/analytics/pipeline | Submission funnel metrics |
GET /v1/analytics/entities | Entity-level analytics |
GET /v1/analytics/compliance | Filing status breakdown |
GET /v1/analytics/claims | Claims frequency and severity |
All routes accept ?period=ytd|qtd|mtd and ?orgId= filters.
Adding Custom KPIs
Extend compute.ts by adding a new function:
export function computeMyKPI(data: MyData): MyKPIResult {
// deterministic calculation — no side effects
return { ... };
}
Add the corresponding API route in apps/api/src/routes/analytics.ts and update the Tinybird datasource schema if new event types are needed.
Finance Portal
AR aging, statutory reports, and TigerBeetle ledger.
AI Agents
Predictive underwriting and claims AI agents.