Skip to main content

Overview

The Country Instability Index (CII) is a real-time stability scoring system (0-100) that blends structural baseline risk with detected events across multiple intelligence streams. Every country with incoming data receives a live score automatically.
23 curated tier-1 nations have individually tuned baseline risk profiles. All other countries use universal default scoring (DEFAULT_BASELINE_RISK = 15, DEFAULT_EVENT_MULTIPLIER = 1.0).

Score Calculation Formula

The CII is calculated using a blended approach that combines baseline risk (40%) with dynamic event scoring (60%):
Source: src/services/country-instability.ts:883-907

Component Breakdown

Unrest Score (25% weight)

Measures civil unrest events from ACLED protests:
number
Number of protest events detected in country (24h window).
number
default:"1.0"
Country-specific scaling factor. High-volume democracies (US, France, India) use logarithmic scaling to prevent routine protests from inflating scores.Examples:
  • US: 0.3 (protests are routine, not destabilizing)
  • Russia: 2.0 (protests are rare and significant)
  • Iran: 2.0 (authoritarian state, every protest matters)
number
Math.min(30, fatalities * 5 * multiplier) — deadly protests escalate score significantly.
number
Math.min(20, highSeverityCount * 10 * multiplier) — protest severity classification from ACLED.
number
Internet outages during protests indicate censorship:
  • Total outage: +30 per event
  • Major outage: +15 per event
  • Partial outage: +5 per event
  • Cap: 50 points
Formula:
Source: src/services/country-instability.ts:683-716

Conflict Score (30% weight)

Measures armed conflict intensity from ACLED + GDELT + Iran attack events:
number
Direct combat engagements (×3 multiplier).
number
Remote violence and explosions (×4 multiplier).
number
Violence against civilians (×5 multiplier + 10pt bonus cap).
number
Math.min(40, Math.sqrt(totalFatalities) * 5 * multiplier) — square root scaling prevents outlier events from dominating.
number
Recent strikes (7-day window):
  • Base: +3 per strike
  • High/critical severity: additional +5 per strike
  • Cap: 50 points
number
Israel-specific: OREF rocket alert integration
  • Active alerts: +25 base
  • Additional +5 per alert (up to +25 more)
  • 24-hour history: +10 if ≥10 alerts, +5 if 3-9 alerts
Formula:
Source: src/services/country-instability.ts:747-791

Security Score (20% weight)

Measures military activity and aviation disruption:
number
ADS-B tracked military aircraft (3pts each, cap 50).Foreign military presence: Flights from non-resident operators are double-weighted to account for threat projection.
number
AIS + USNI tracked naval vessels (5pts each, cap 30).
number
Airport delays/closures:
  • Closure: +20
  • Severe delay: +15
  • Major delay: +10
  • Moderate delay: +5
  • Cap: 40 points
number
GPS/GNSS interference from ADS-B transponder analysis:
  • High interference (>10%): +5 per H3 hex cell
  • Medium interference (2-10%): +2 per hex
  • Cap: 35 points
Region tagging: Interference zones mapped to 12 conflict regions (Iran-Iraq, Ukraine-Russia, Levant, Baltic, etc.)
Formula:
Source: src/services/country-instability.ts:803-821

Information Score (25% weight)

Measures news velocity and reporting intensity:
number
Clustered news events mentioning country (6h window).
number
Average sources-per-hour across news clusters.Threshold: High-volume countries (US, China, Russia) require velocity >5 to trigger boost. Others require >2.
number
+20 * multiplier if any news cluster has isAlert flag (breaking news).
Formula:
Source: src/services/country-instability.ts:823-846

Additional Boosters

Hotspot Proximity Boost

Events near intelligence hotspots (Tehran, Kyiv, Gaza, etc.) increase country scores:
Source: src/services/country-instability.ts:304-348

Focal Point Urgency Boost

Correlation between news coverage and map signals:
number
default:"+8"
Country appears as critical focal point (3+ signal types + high news coverage).
number
default:"+4"
Country appears as elevated focal point (2+ signal types + moderate news coverage).

Displacement Boost

number
default:"+8"
≥1M refugees + asylum seekers (UNHCR data).
number
default:"+4"
100K–1M refugees + asylum seekers.

Climate Stress Boost

number
default:"+15"
Temperature/precipitation >2 standard deviations from 30-day ERA5 baseline.
number
default:"+8"
1.5-2 standard deviations from baseline.
Monitored zones: Ukraine, Middle East (Iran, Israel, Saudi Arabia, Syria, Yemen), South Asia (Pakistan, India), Myanmar

Government Travel Advisory Boost

number
  • Base: +15
  • Multi-source consensus bonus:
    • 3+ governments: +5
    • 2 governments: +3
  • Floor: Score cannot drop below 60 with Do-Not-Travel advisory
number
  • Base: +10
  • Multi-source bonus (same as above)
  • Floor: Score cannot drop below 50
number
+5 (no floor)
Sources: US State Dept, Australia DFAT, UK FCDO, New Zealand MFAT

Supplemental Signal Boost

number
Vessel tracking anomalies:
  • High severity: +2.5 per event
  • Elevated: +1.5 per event
  • Low: +0.5 per event
  • Cap: 10 points
number
NASA FIRMS thermal hotspots:
  • High intensity (≥360K or ≥50MW): +1.5 per fire
  • Normal fires: +0.25 each (20 fire cap)
  • Cap: 8 points
number
Geolocated IOCs (C2 servers, phishing, malware):
  • Critical: +3 per threat
  • High: +1.8 per threat
  • Medium: +0.9 per threat
  • Cap: 12 points
number
Welford’s algorithm detects deviations from 90-day baseline:
  • Critical (z-score ≥3.0): +2 per anomaly
  • Normal (z-score 1.5-3.0): +0.75 per anomaly
  • Cap: 6 points

Floor Scores

UCDP Conflict Classification

UN-classified active wars override optimistic scores:
number
default:"70"
≥1,000 battle deaths in the current calendar year.Example: Ukraine automatically receives ≥70 CII due to UCDP “war” classification.
number
default:"50"
25-999 battle deaths.
number
default:"0"
No UCDP conflict classification.
Source: UCDP Georeferenced Event Dataset (GED) with automatic version discovery

Threat Level Ranges

range
default:"81-100"
Imminent or active crisis. Examples: Ukraine (85), Yemen (82), Syria (88).
range
default:"66-80"
Significant instability. Examples: Iran (72), Myanmar (68).
range
default:"51-65"
Moderate risk. Examples: Venezuela (58), Pakistan (54).
range
default:"31-50"
Baseline geopolitical activity. Examples: Russia (42), Saudi Arabia (38), Mexico (35).
range
default:"0-30"
Stable. Examples: US (18), Germany (12), Japan (15).

Trend Detection

Scores are compared against previous values (stored in Map<string, number>) to calculate 24-hour trends:
Threshold: ±5 points required to trigger trend indicator.

Learning Mode

On cold start (no cached scores), CII enters a 15-minute learning phase:
number
default:"900000"
15 minutes in milliseconds. Dashboard displays learning progress bar.
boolean
If cached scores from previous session exist (via /api/risk-scores), learning mode is skipped entirely.
Source: src/services/country-instability.ts:85-96

Example Scores

Key Files

  • src/services/country-instability.ts — Core CII calculation engine
  • src/services/focal-point-detector.ts — News-signal correlation for urgency boost
  • src/services/geo-convergence.ts — Geographic event clustering
  • src/config/countries.ts — Curated country configurations
  • api/risk-scores.ts — Cached CII scores endpoint