CoolFace
Apppublic

mihir2007/Cyber-Risk

sourceHugging Faceupdated 16d agoView on Hugging Face
0likes
run_simulation.py170 linesDownload Raw Back to root
1"""2run_simulation.py3------------------4Standalone terminal runner for the CRQ platform. Executes the full pipeline5end-to-end against the SQLite database, without needing the FastAPI server:6 7    1. Initializes the SQLite database (creates tables if missing).8    2. Seeds synthetic enterprise data (idempotent).9    3. Runs a 10,000-iteration Monte Carlo simulation and prints the10       aggregate Enterprise Risk (EAL, VaR 95/99) in ₹.11    4. Runs the PuLP budget optimizer for a ₹50,00,000 budget and prints12       the chosen controls, total spent, and ROSI.13    5. Verifies the run was persisted to `SimulationRun` by querying SQLite14       directly and printing the stored record.15 16Usage:17    python run_simulation.py18"""19 20from __future__ import annotations21 22from database import SessionLocal, init_db23from models import Asset, SecurityControl, SimulationRun24from optimizer import optimize_budget_allocation25from quant_engine import run_enterprise_simulation26from seeder import seed_database27 28DEMO_BUDGET_INR = 5_000_000.0  # ₹50,00,00029 30 31def _format_inr(amount: float) -> str:32    """Formats a rupee amount with Indian-style comma grouping, e.g. ₹1,23,45,678.90."""33    is_negative = amount < 034    amount = abs(amount)35    integer_part, _, decimal_part = f"{amount:.2f}".partition(".")36 37    if len(integer_part) > 3:38        last_three = integer_part[-3:]39        remaining = integer_part[:-3]40        grouped = []41        while len(remaining) > 2:42            grouped.insert(0, remaining[-2:])43            remaining = remaining[:-2]44        if remaining:45            grouped.insert(0, remaining)46        integer_part = ",".join(grouped + [last_three])47 48    sign = "-" if is_negative else ""49    return f"{sign}₹{integer_part}.{decimal_part}"50 51 52def main() -> None:53    print("=" * 78)54    print(" AI-Powered Continuous Cyber Risk Quantification (CRQ) Platform")55    print(" Standalone Simulation Runner")56    print("=" * 78)57 58    # --- Step 1: Initialize database ------------------------------------- #59    print("\n[1/5] Initializing SQLite database (cyber_risk.db)...")60    init_db()61    print("      Tables created/verified.")62 63    db = SessionLocal()64    try:65        # --- Step 2: Seed synthetic data ---------------------------------- #66        print("\n[2/5] Seeding synthetic enterprise telemetry...")67        summary = seed_database(db)68        print(69            f"      Inserted: {summary['assets']} assets, "70            f"{summary['vulnerabilities']} vulnerabilities, "71            f"{summary['controls']} security controls "72            "(0 values mean already seeded)."73        )74 75        assets = db.query(Asset).all()76        all_controls = db.query(SecurityControl).all()77        print(f"      Total assets in DB: {len(assets)} | Total controls in DB: {len(all_controls)}")78 79        # --- Step 3: Monte Carlo enterprise risk simulation ---------------- #80        print("\n[3/5] Running 10,000-iteration Monte Carlo enterprise risk simulation...")81        active_controls = [c for c in all_controls if c.is_active]82        result = run_enterprise_simulation(db, assets, active_controls, persist=True)83 84        print(f"      Expected Annual Loss (EAL):     {_format_inr(result.total_eal_inr)}")85        print(f"      Value at Risk (95% confidence):  {_format_inr(result.var_95_inr)}")86        print(f"      Value at Risk (99% confidence):  {_format_inr(result.var_99_inr)}")87        print(88            f"      Estimated Regulatory Fine Exposure (95th pct): "89            f"{_format_inr(result.total_regulatory_fine_exposure_inr)}"90        )91 92        print("\n      Top 5 riskiest assets by EAL:")93        top_5 = sorted(result.per_asset_results, key=lambda r: r.eal_inr, reverse=True)[:5]94        for rank, r in enumerate(top_5, start=1):95            print(96                f"        {rank}. {r.hostname:<24} ({r.tier:<8}) "97                f"lambda={r.annual_event_frequency:5.2f}/yr  EAL={_format_inr(r.eal_inr)}"98            )99 100        # --- Step 4: Budget-constrained optimization ------------------------ #101        print(f"\n[4/5] Running PuLP 0/1 knapsack budget optimizer for {_format_inr(DEMO_BUDGET_INR)}...")102        opt_result = optimize_budget_allocation(db, assets, all_controls, DEMO_BUDGET_INR)103 104        selected_codes = {c.code for c in opt_result.selected_controls}105        for control in all_controls:106            control.is_active = control.code in selected_codes107        db.commit()108 109        print(f"      Baseline EAL:   {_format_inr(opt_result.baseline_eal_inr)}")110        print(f"      Projected EAL:  {_format_inr(opt_result.projected_eal_inr)}")111        print(f"      Net Risk Reduction (Delta EAL): {_format_inr(opt_result.net_risk_reduction_inr)}")112        print(f"      Total Spent:    {_format_inr(opt_result.total_spent_inr)}")113        print(f"      Remaining Budget: {_format_inr(opt_result.remaining_budget_inr)}")114        print(f"      ROSI: {opt_result.rosi_percent:.2f}%")115        print("\n      Selected controls:")116        for control in opt_result.selected_controls:117            mv = opt_result.control_marginal_values[control.code]118            print(119                f"        - {control.code:<24} {control.name:<48} "120                f"cost={_format_inr(control.cost_inr):>18}  "121                f"marginal_dEAL={_format_inr(mv.adjusted_value_inr)}"122            )123 124        # Persist the optimizer run as well.125        import json as _json126 127        opt_run_record = SimulationRun(128            total_eal_inr=opt_result.projected_eal_inr,129            var_95_inr=result.var_95_inr,130            var_99_inr=result.var_99_inr,131            allocated_budget_inr=DEMO_BUDGET_INR,132            selected_controls_json=_json.dumps(sorted(selected_codes)),133        )134        db.add(opt_run_record)135        db.commit()136        db.refresh(opt_run_record)137 138        # --- Step 5: Verify persistence ------------------------------------- #139        print("\n[5/5] Verifying SimulationRun persistence in SQLite...")140        stored_run = (141            db.query(SimulationRun)142            .order_by(SimulationRun.timestamp.desc())143            .first()144        )145        if stored_run is None:146            print("      ERROR: No SimulationRun record found!")147        else:148            print("      Latest stored SimulationRun record:")149            print(f"        id                     = {stored_run.id}")150            print(f"        timestamp              = {stored_run.timestamp}")151            print(f"        total_eal_inr          = {_format_inr(stored_run.total_eal_inr)}")152            print(f"        var_95_inr             = {_format_inr(stored_run.var_95_inr)}")153            print(f"        var_99_inr             = {_format_inr(stored_run.var_99_inr)}")154            print(f"        allocated_budget_inr   = {_format_inr(stored_run.allocated_budget_inr or 0.0)}")155            print(f"        selected_controls_json = {stored_run.selected_controls_json}")156 157        total_runs = db.query(SimulationRun).count()158        print(f"\n      Total SimulationRun records in database: {total_runs}")159 160    finally:161        db.close()162 163    print("\n" + "=" * 78)164    print(" Simulation complete.")165    print("=" * 78)166 167 168if __name__ == "__main__":169    main()170