Datavision / backend /mcp /simulation_engine.py
DataVision CI/CD Bot
release: clean production build for HuggingFace Space
09801ca
Raw
History Blame Contribute Delete
13.8 kB
# Simulation Engine MCP Service
"""
Enterprise What-If Scenario Simulation Engine
Features:
- Price elasticity modeling
- Marketing impact simulation
- Customer churn prediction
- Revenue scenario comparison
- Sensitivity analysis
Usage:
from mcp.simulation_engine import SimulationEngine
engine = SimulationEngine()
result = engine.simulate(base_data, modifiers)
"""
import numpy as np
from typing import Dict, List, Any, Optional
from dataclasses import dataclass, field
import json
@dataclass
class Scenario:
"""A single simulation scenario"""
name: str
revenue: float
profit: float
customers: int
churn_rate: float
change_pct: float
risk_level: str
description: str
@dataclass
class SimulationResult:
"""Result from simulation engine"""
scenarios: List[Scenario]
recommended_strategy: str
best_scenario: str
risk_assessment: str
insights: List[str]
confidence: float
class SimulationEngine:
"""
Enterprise What-If Simulation Engine.
Supports:
- Price change impact
- Marketing spend impact
- Customer acquisition/churn
- Multi-variable scenarios
"""
# Default elasticity coefficients
PRICE_ELASTICITY = -1.2 # 1% price increase โ†’ 1.2% demand decrease
MARKETING_ELASTICITY = 0.3 # 1% marketing increase โ†’ 0.3% revenue increase
CHURN_SENSITIVITY = 0.5 # Sensitivity to price/service changes
def __init__(self):
self.scenarios_run = 0
def simulate(
self,
base_revenue: float,
base_customers: int = 100,
base_profit_margin: float = 0.2,
base_churn_rate: float = 0.05,
modifiers: Optional[Dict[str, float]] = None
) -> SimulationResult:
"""
Run what-if simulations with given modifiers.
Args:
base_revenue: Current revenue
base_customers: Current customer count
base_profit_margin: Current profit margin (0-1)
base_churn_rate: Current churn rate (0-1)
modifiers: Dict of modifiers to simulate, e.g.:
{
"price_change": [5, 10, 15], # % changes
"marketing_change": [10, 20],
"churn_reduction": [10, 20]
}
Returns:
SimulationResult with all scenarios compared
"""
if modifiers is None:
# Default simulation scenarios
modifiers = {
"price_change": [-10, -5, 5, 10, 15],
"marketing_change": [10, 20, 50],
}
scenarios = []
# Base scenario
base_scenario = Scenario(
name="Current State",
revenue=base_revenue,
profit=base_revenue * base_profit_margin,
customers=base_customers,
churn_rate=base_churn_rate,
change_pct=0,
risk_level="low",
description="Current business state"
)
scenarios.append(base_scenario)
# Price change scenarios
if "price_change" in modifiers:
for pct in modifiers["price_change"]:
scenario = self._simulate_price_change(
base_revenue, base_customers,
base_profit_margin, base_churn_rate, pct
)
scenarios.append(scenario)
# Marketing change scenarios
if "marketing_change" in modifiers:
for pct in modifiers["marketing_change"]:
scenario = self._simulate_marketing_change(
base_revenue, base_customers,
base_profit_margin, base_churn_rate, pct
)
scenarios.append(scenario)
# Find best scenario
best = max(scenarios, key=lambda s: s.profit)
# Generate recommendation
recommendation = self._generate_recommendation(scenarios, best)
# Risk assessment
risk = self._assess_overall_risk(scenarios)
# Generate insights
insights = self._generate_insights(scenarios, base_scenario, best)
return SimulationResult(
scenarios=scenarios,
recommended_strategy=recommendation,
best_scenario=best.name,
risk_assessment=risk,
insights=insights,
confidence=85.0
)
def _simulate_price_change(
self,
base_revenue: float,
base_customers: int,
profit_margin: float,
churn_rate: float,
price_change_pct: float
) -> Scenario:
"""Simulate impact of price change."""
# Price elasticity effect on demand
demand_change = price_change_pct * self.PRICE_ELASTICITY
# Calculate new metrics
new_revenue = base_revenue * (1 + price_change_pct/100) * (1 + demand_change/100)
# Churn increases with price increases
churn_impact = max(0, price_change_pct * self.CHURN_SENSITIVITY / 100)
new_churn = min(0.5, churn_rate + churn_impact)
# Customers affected by churn
customer_loss = int(base_customers * churn_impact)
new_customers = max(0, base_customers - customer_loss)
# Profit margin slightly improves with price increase
margin_boost = price_change_pct * 0.005
new_margin = min(0.5, profit_margin + margin_boost)
new_profit = new_revenue * new_margin
# Risk level
if price_change_pct > 10:
risk = "high"
elif price_change_pct > 5:
risk = "medium"
elif price_change_pct < -5:
risk = "medium"
else:
risk = "low"
change_pct = ((new_revenue - base_revenue) / base_revenue * 100) if base_revenue else 0
return Scenario(
name=f"Price {'+' if price_change_pct >= 0 else ''}{price_change_pct}%",
revenue=round(new_revenue, 2),
profit=round(new_profit, 2),
customers=new_customers,
churn_rate=round(new_churn, 3),
change_pct=round(change_pct, 1),
risk_level=risk,
description=f"{'Increase' if price_change_pct >= 0 else 'Decrease'} prices by {abs(price_change_pct)}%"
)
def _simulate_marketing_change(
self,
base_revenue: float,
base_customers: int,
profit_margin: float,
churn_rate: float,
marketing_change_pct: float
) -> Scenario:
"""Simulate impact of marketing spend change."""
# Marketing elasticity effect
revenue_boost = marketing_change_pct * self.MARKETING_ELASTICITY
new_revenue = base_revenue * (1 + revenue_boost/100)
# Marketing cost reduces profit margin
marketing_cost = base_revenue * (marketing_change_pct / 100) * 0.1
new_profit = (new_revenue * profit_margin) - marketing_cost
# New customer acquisition
customer_gain = int(base_customers * (marketing_change_pct / 100) * 0.2)
new_customers = base_customers + customer_gain
# Marketing reduces churn
churn_reduction = marketing_change_pct * 0.001
new_churn = max(0.01, churn_rate - churn_reduction)
# Risk level
if marketing_change_pct > 50:
risk = "medium"
else:
risk = "low"
change_pct = ((new_revenue - base_revenue) / base_revenue * 100) if base_revenue else 0
return Scenario(
name=f"Marketing +{marketing_change_pct}%",
revenue=round(new_revenue, 2),
profit=round(new_profit, 2),
customers=new_customers,
churn_rate=round(new_churn, 3),
change_pct=round(change_pct, 1),
risk_level=risk,
description=f"Increase marketing spend by {marketing_change_pct}%"
)
def _generate_recommendation(
self,
scenarios: List[Scenario],
best: Scenario
) -> str:
"""Generate strategic recommendation."""
if best.name == "Current State":
return "Maintain current strategy - changes show limited upside"
if "Price" in best.name:
if best.change_pct > 0:
return f"Consider {best.name} - shows {best.change_pct:.1f}% revenue increase with {best.risk_level} risk"
else:
return f"Consider {best.name} to capture market share"
if "Marketing" in best.name:
return f"Invest in {best.name} - projected {best.change_pct:.1f}% revenue growth"
return f"Implement {best.name} for optimal results"
def _assess_overall_risk(self, scenarios: List[Scenario]) -> str:
"""Assess overall risk of recommended changes."""
high_risk = sum(1 for s in scenarios if s.risk_level == "high")
medium_risk = sum(1 for s in scenarios if s.risk_level == "medium")
if high_risk > 2:
return "high"
elif medium_risk > 3 or high_risk > 0:
return "medium"
else:
return "low"
def _generate_insights(
self,
scenarios: List[Scenario],
base: Scenario,
best: Scenario
) -> List[str]:
"""Generate actionable insights."""
insights = []
# Best scenario insight
if best.name != "Current State":
profit_gain = best.profit - base.profit
insights.append(
f"๐Ÿ’ก {best.name} could increase profit by ${profit_gain:,.0f}"
)
# Risk insight
high_risk_scenarios = [s for s in scenarios if s.risk_level == "high"]
if high_risk_scenarios:
names = ", ".join(s.name for s in high_risk_scenarios[:2])
insights.append(f"โš ๏ธ High-risk scenarios: {names}")
# Price sensitivity insight
price_scenarios = [s for s in scenarios if "Price" in s.name]
if price_scenarios:
optimal = max(price_scenarios, key=lambda s: s.profit)
insights.append(
f"๐Ÿ“Š Optimal pricing point: {optimal.name} (profit: ${optimal.profit:,.0f})"
)
# Marketing ROI insight
marketing_scenarios = [s for s in scenarios if "Marketing" in s.name]
if marketing_scenarios:
best_marketing = max(marketing_scenarios, key=lambda s: s.change_pct)
insights.append(
f"๐Ÿ“ˆ Best marketing ROI: {best_marketing.name} ({best_marketing.change_pct:.1f}% revenue boost)"
)
return insights
def run_monte_carlo(
self,
base_revenue: float,
uncertainty: float = 0.1,
simulations: int = 1000
) -> Dict[str, Any]:
"""
Run Monte Carlo simulation for revenue prediction.
Args:
base_revenue: Base revenue value
uncertainty: Uncertainty range (0-1)
simulations: Number of simulations
Returns:
Dict with percentile outcomes
"""
results = []
for _ in range(simulations):
# Random variation
variation = np.random.normal(0, uncertainty)
simulated = base_revenue * (1 + variation)
results.append(max(0, simulated))
results = np.array(results)
return {
"mean": float(np.mean(results)),
"median": float(np.median(results)),
"p10": float(np.percentile(results, 10)),
"p25": float(np.percentile(results, 25)),
"p75": float(np.percentile(results, 75)),
"p90": float(np.percentile(results, 90)),
"std": float(np.std(results)),
"best_case": float(np.max(results)),
"worst_case": float(np.min(results))
}
def simulate_scenarios(
revenue: float,
customers: int = 100,
margin: float = 0.2,
churn: float = 0.05
) -> Dict[str, Any]:
"""
Convenience function for scenario simulation.
Returns:
Dict with simulation results
"""
engine = SimulationEngine()
result = engine.simulate(revenue, customers, margin, churn)
return {
"success": True,
"scenarios": [
{
"name": s.name,
"revenue": s.revenue,
"profit": s.profit,
"customers": s.customers,
"churn_rate": s.churn_rate,
"change_pct": s.change_pct,
"risk": s.risk_level,
"description": s.description
}
for s in result.scenarios
],
"recommendation": result.recommended_strategy,
"best_scenario": result.best_scenario,
"risk_level": result.risk_assessment,
"insights": result.insights,
"confidence": f"{result.confidence}%"
}
# Quick test
if __name__ == "__main__":
result = simulate_scenarios(
revenue=100000,
customers=500,
margin=0.25,
churn=0.08
)
print("Simulation Results:")
print(f"Best Scenario: {result['best_scenario']}")
print(f"Recommendation: {result['recommendation']}")
print(f"\nInsights:")
for insight in result['insights']:
print(f" {insight}")
print(f"\nScenarios:")
for s in result['scenarios'][:5]:
print(f" {s['name']}: Revenue ${s['revenue']:,.0f}, Profit ${s['profit']:,.0f}")