Risk Tape v1 — Data Quality Scoring
Source: src/modules/riskTape/dataQuality.ts
Scoring formula
overall_score = Completeness (max 70) + ND Usage (max 20) + Consistency (max 10)
1. Completeness (70 points)
Measures how many of the 19 Tier A fields are present:
completeness = 70 × (fields_present / 19)
Cap: If track_record_months < 6, completeness is capped at 40 regardless
of field presence.
The 19 Tier A fields are:
| # | Path |
|---|---|
| 1 | schema_version |
| 2 | as_of_date |
| 3 | obligor.obligor_id |
| 4 | obligor.jurisdiction |
| 5 | cashflow_summary.currency |
| 6 | cashflow_summary.track_record_months |
| 7 | cashflow_summary.income_30d |
| 8 | cashflow_summary.income_90d |
| 9 | risk_profile.avg_monthly_revenue |
| 10 | risk_profile.volatility_cv_12m |
| 11 | risk_profile.max_drawdown_pct_36m |
| 12 | risk_profile.platform_concentration_index |
| 13 | risk_profile.top_platform_share |
| 14 | risk_profile.track_record_months |
| 15 | eligibility.rbf.eligible |
| 16 | eligibility.rbf.risk_tier |
| 17 | eligibility.rbf.max_advance_amount |
| 18 | eligibility.rbf.max_revenue_share_pct |
| 19 | eligibility.rbf.payback_cap_multiple |
2. ND Usage (20 points)
Deducts 1 point for each ND2, ND3, or ND4 code found in
cashflow_summary.revenue_monthly items:
nd_component = max(0, 20 - penalty_count)
ND1 (not applicable) does not penalise.
3. Consistency (10 points)
Deducts 2 points for each failed sanity check:
| Check | Flag if failed |
|---|---|
income_30d < 0 | negative_income_30d |
income_90d < 0 | negative_income_90d |
avg_monthly_revenue < 0 | negative_avg_monthly_revenue |
volatility_cv_12m < 0 | invalid_volatility_cv |
platform_concentration_index outside 0–1 | platform_concentration_out_of_range |
top_platform_share outside 0–1 | top_platform_share_out_of_range |
max_drawdown_pct_36m outside 0–1 | max_drawdown_out_of_range |
consistency_component = max(0, 10 - 2 × failed_checks)
Score interpretation
| Score | Meaning |
|---|---|
| 90–100 | Excellent — all Tier A fields present, clean data |
| 70–89 | Good — minor gaps or a few ND codes |
| 50–69 | Fair — some Tier A fields missing or short track record |
| 0–49 | Poor — significant data gaps, likely ineligible |
JSON schema validation
After scoring, the tape is validated against risk-tape-v1.json using AJV.
If validation fails:
data_quality.blocking_validation_failed = truedata_quality.quality_flagsincludesjson_schema_validation_failedstatusis set to"failed"
Source: src/modules/riskTape/validator.ts