# app.py # VisaTier — Immigration ROI Simulator (Enhanced Version) # Добавлены: чувствительность, экспорт, визы, налоги, валютность, AI-рекомендации import math import numpy as np import pandas as pd import gradio as gr import plotly.graph_objects as go from plotly.subplots import make_subplots import json from datetime import datetime, timedelta import io import base64 # ========================= # РАСШИРЕННЫЕ ДАННЫЕ # ========================= # Добавляем данные по визам и валютам VISA_TYPES = { "UAE (Dubai)": { "Golden Visa": {"min_investment": 2000000, "duration": "10 years", "processing_time": "6 months"}, "Investor Visa": {"min_investment": 500000, "duration": "3 years", "processing_time": "3 months"}, "Freelancer Visa": {"min_investment": 0, "duration": "1 year", "processing_time": "1 month"} }, "UK": { "Innovator Founder": {"min_investment": 50000, "duration": "3 years", "processing_time": "6 months"}, "Global Talent": {"min_investment": 0, "duration": "5 years", "processing_time": "3 months"}, "Skilled Worker": {"min_investment": 0, "duration": "5 years", "processing_time": "3 months"} }, "USA (FL/TX/NV)": { "EB-5 Investor": {"min_investment": 800000, "duration": "2 years", "processing_time": "18 months"}, "L-1A Executive": {"min_investment": 0, "duration": "7 years", "processing_time": "4 months"}, "O-1 Extraordinary": {"min_investment": 0, "duration": "3 years", "processing_time": "3 months"} }, "Spain": { "Golden Visa": {"min_investment": 500000, "duration": "3 years", "processing_time": "3 months"}, "Entrepreneur Visa": {"min_investment": 50000, "duration": "2 years", "processing_time": "2 months"}, "Digital Nomad": {"min_investment": 0, "duration": "1 year", "processing_time": "1 month"} }, "Ireland": { "Investor Programme": {"min_investment": 1000000, "duration": "5 years", "processing_time": "6 months"}, "Start-up Entrepreneur": {"min_investment": 75000, "duration": "2 years", "processing_time": "4 months"}, "Critical Skills": {"min_investment": 0, "duration": "2 years", "processing_time": "3 months"} } } CURRENCIES = { "EUR": 1.0, "USD": 1.08, "GBP": 0.85, "AED": 3.67 } # Расширенная конфигурация стран с дополнительными параметрами COUNTRY_CONFIG = { "UAE (Dubai)": { "corp_tax": 0.09, "pers_tax": 0.00, "rev_mult": 3.0, "margin_delta_pp": 5.0, "living_month": 9000.0, "ongoing_month": 1500.0, "setup_once": 35000.0, "currency": "AED", "inflation": 2.5, "market_growth": 8.5, "ease_business": 9.2, "tax_treaties": 95, "banking_score": 8.8, "legal_system": "Civil Law", "additional_costs": { "visa_renewal": 5000, "banking_setup": 3000, "legal_compliance": 8000, "audit_annual": 12000, "insurance": 6000 } }, "UK": { "corp_tax": 0.25, "pers_tax": 0.27, "rev_mult": 1.5, "margin_delta_pp": 2.0, "living_month": 6200.0, "ongoing_month": 1100.0, "setup_once": 18000.0, "currency": "GBP", "inflation": 4.2, "market_growth": 2.1, "ease_business": 8.1, "tax_treaties": 130, "banking_score": 9.1, "legal_system": "Common Law", "additional_costs": { "visa_renewal": 8000, "banking_setup": 2000, "legal_compliance": 15000, "audit_annual": 8000, "insurance": 4000 } }, "USA (FL/TX/NV)": { "corp_tax": 0.21, "pers_tax": 0.22, "rev_mult": 1.8, "margin_delta_pp": 4.0, "living_month": 7000.0, "ongoing_month": 1300.0, "setup_once": 20000.0, "currency": "USD", "inflation": 3.1, "market_growth": 5.2, "ease_business": 8.7, "tax_treaties": 65, "banking_score": 8.9, "legal_system": "Common Law", "additional_costs": { "visa_renewal": 12000, "banking_setup": 5000, "legal_compliance": 20000, "audit_annual": 10000, "insurance": 8000 } }, "Spain": { "corp_tax": 0.25, "pers_tax": 0.24, "rev_mult": 1.4, "margin_delta_pp": 2.0, "living_month": 5000.0, "ongoing_month": 1000.0, "setup_once": 20000.0, "currency": "EUR", "inflation": 3.8, "market_growth": 3.2, "ease_business": 7.3, "tax_treaties": 100, "banking_score": 7.8, "legal_system": "Civil Law", "additional_costs": { "visa_renewal": 4000, "banking_setup": 2500, "legal_compliance": 12000, "audit_annual": 7000, "insurance": 3500 } }, "Ireland": { "corp_tax": 0.125, "pers_tax": 0.22, "rev_mult": 1.6, "margin_delta_pp": 3.0, "living_month": 6500.0, "ongoing_month": 1200.0, "setup_once": 25000.0, "currency": "EUR", "inflation": 2.8, "market_growth": 4.1, "ease_business": 8.4, "tax_treaties": 75, "banking_score": 8.2, "legal_system": "Common Law", "additional_costs": { "visa_renewal": 6000, "banking_setup": 3500, "legal_compliance": 10000, "audit_annual": 9000, "insurance": 4500 } } } # ========================= # СТИЛИ (расширенные) # ========================= CSS = """ :root { --vt-primary: #2563EB; --vt-accent: #10B981; --vt-danger: #EF4444; --vt-warning: #F59E0B; --vt-ink: #0F172A; --vt-muted: #64748B; --radius: 16px; } .gradio-container { max-width: 1400px !important; margin: 0 auto; } .vt-header { background: linear-gradient(135deg, #0F172A 0%, #1E293B 100%); color: #E2E8F0; padding: 18px 24px; border-radius: 16px; display: flex; align-items: center; justify-content: space-between; margin-bottom: 20px; box-shadow: 0 10px 25px rgba(0,0,0,0.1); } .vt-hero { border-radius: var(--radius); padding: 24px 28px; background: linear-gradient(135deg, rgba(37,99,235,0.12), rgba(16,185,129,0.12)); border: 2px solid rgba(37,99,235,0.2); margin-bottom: 20px; backdrop-filter: blur(10px); } .vt-kpi { border-radius: var(--radius); padding: 20px; background: #FFFFFF; border: 2px solid #E2E8F0; margin-bottom: 12px; box-shadow: 0 4px 6px rgba(0,0,0,0.05); transition: all 0.3s ease; } .vt-kpi:hover { transform: translateY(-2px); box-shadow: 0 8px 25px rgba(0,0,0,0.1); } .vt-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 16px; margin: 20px 0; } .sensitivity-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin: 16px 0; } .risk-indicator { padding: 8px 16px; border-radius: 20px; font-weight: 600; font-size: 12px; display: inline-block; margin: 4px; } .risk-low { background: rgba(16,185,129,0.1); color: #10B981; } .risk-medium { background: rgba(245,158,11,0.1); color: #F59E0B; } .risk-high { background: rgba(239,68,68,0.1); color: #EF4444; } .visa-card { background: #F8FAFC; border: 1px solid #E2E8F0; border-radius: 12px; padding: 16px; margin: 8px 0; } .ai-recommendation { background: linear-gradient(135deg, rgba(99,102,241,0.1), rgba(168,85,247,0.1)); border: 2px solid rgba(99,102,241,0.2); border-radius: 16px; padding: 20px; margin: 16px 0; } .export-section { background: #F1F5F9; border-radius: 12px; padding: 16px; margin: 16px 0; border-left: 4px solid var(--vt-primary); } .timeline-item { display: flex; align-items: center; margin: 12px 0; padding: 12px; background: #FFFFFF; border-radius: 8px; border-left: 3px solid var(--vt-primary); } .comparison-enhanced { background: #FFFFFF; border-radius: 16px; padding: 20px; box-shadow: 0 4px 6px rgba(0,0,0,0.05); margin: 16px 0; } @media (max-width: 768px) { .vt-grid { grid-template-columns: 1fr; } .sensitivity-grid { grid-template-columns: 1fr; } } """ THEME = gr.themes.Soft( primary_hue="blue", neutral_hue="slate", font=gr.themes.GoogleFont("Inter") ).set( body_background_fill="#F8FAFC", body_text_color="#0F172A", button_primary_background_fill="#2563EB", button_primary_background_fill_hover="#1D4ED8" ) # ========================= # РАСШИРЕННЫЕ ФУНКЦИИ # ========================= def generate_ai_recommendation(result, country, personal_profile): """Генерация AI-рекомендаций на основе результатов""" risk_level = "LOW" if result["payback_years"] <= 1.5 else ("MEDIUM" if result["payback_years"] <= 3.0 else "HIGH") recommendations = [] if result["total_5yr_roi"] < 50: recommendations.append("⚠️ Consider optimizing your business model before relocation") if result["payback_years"] > 3: recommendations.append("💡 Look into phased migration to reduce upfront costs") if country in ["UAE (Dubai)", "Ireland"] and result["irr_annual_pct"] > 25: recommendations.append("🚀 Strong financial case - consider accelerated timeline") recommendations.append(f"📊 Risk Level: {risk_level}") return recommendations def calculate_sensitivity_analysis(base_params, result): """Анализ чувствительности ключевых параметров""" sensitivities = {} # Тестируем изменения ключевых параметров на ±20% test_params = ['rev_mult', 'margin_delta_pp', 'success_pct'] for param in test_params: high_val = base_params[param] * 1.2 low_val = base_params[param] * 0.8 # Для демонстрации - упрощенный расчет влияния if param == 'rev_mult': impact_high = (high_val - base_params[param]) / base_params[param] * result["total_5yr_roi"] * 0.8 impact_low = (low_val - base_params[param]) / base_params[param] * result["total_5yr_roi"] * 0.8 else: impact_high = (high_val - base_params[param]) / base_params[param] * result["total_5yr_roi"] * 0.3 impact_low = (low_val - base_params[param]) / base_params[param] * result["total_5yr_roi"] * 0.3 sensitivities[param] = {"high": impact_high, "low": impact_low} return sensitivities def create_monte_carlo_simulation(base_params, iterations=1000): """Упрощенная Монте-Карло симуляция""" results = [] np.random.seed(42) for _ in range(iterations): # Добавляем случайность к ключевым параметрам sim_rev_mult = base_params['rev_mult'] * np.random.normal(1.0, 0.15) sim_success = base_params['success_pct'] * np.random.normal(1.0, 0.10) sim_margin = base_params['margin_delta_pp'] * np.random.normal(1.0, 0.20) # Упрощенный расчет ROI для симуляции sim_roi = base_params.get('base_roi', 100) * (sim_rev_mult / base_params['rev_mult']) * (sim_success / base_params['success_pct']) results.append(max(0, sim_roi)) return { "mean": np.mean(results), "std": np.std(results), "percentile_10": np.percentile(results, 10), "percentile_90": np.percentile(results, 90), "probability_positive": len([r for r in results if r > 0]) / len(results) * 100 } def export_to_pdf_data(result, country, params): """Подготовка данных для экспорта в PDF""" export_data = { "timestamp": datetime.now().isoformat(), "country": country, "parameters": params, "results": { "npv": result["npv"], "roi_5y": result["total_5yr_roi"], "payback_years": result["payback_years"], "irr_annual": result["irr_annual_pct"] } } # Создаем JSON для скачивания json_str = json.dumps(export_data, indent=2, ensure_ascii=False) return json_str def create_enhanced_timeline(country): """Создание расширенного таймлайна миграции""" if country not in VISA_TYPES: return "Timeline data not available for this country." visas = VISA_TYPES[country] timeline_html = "
" for visa_name, details in visas.items(): timeline_html += f"""

{visa_name}

Investment: €{details['min_investment']:,} • Duration: {details['duration']} • Processing: {details['processing_time']}
""" timeline_html += "
" return timeline_html # ========================= # ОСНОВНЫЕ ВЫЧИСЛИТЕЛЬНЫЕ ФУНКЦИИ (как в оригинале, но расширенные) # ========================= def clamp(x, lo, hi): return max(lo, min(hi, x)) def monthly_rate(annual_rate): return (1.0 + annual_rate) ** (1.0 / 12.0) - 1.0 def irr_bisection(cash, lo=-0.99, hi=5.0, iters=100, tol=1e-7): def npv(rate): return sum(cf / ((1 + rate) ** t) for t, cf in enumerate(cash)) f_lo, f_hi = npv(lo), npv(hi) if f_lo * f_hi > 0: return None for _ in range(iters): mid = (lo + hi) / 2 v = npv(mid) if abs(v) < tol: return mid if v > 0: lo = mid else: hi = mid return (lo + hi) / 2 def ramp_factor(m): return 0.6 if m <= 6 else (0.8 if m <= 12 else 1.0) def compute_enhanced_monthly_delta_cashflow( rev0, margin0_pct, corp0_pct, pers0_pct, living0, ongoing0, dest, rev_mult, margin_delta_pp, corp1_pct, pers1_pct, living1, ongoing1, capex_once, horizon_m, discount_annual_pct, success_pct, include_inflation=True, include_additional_costs=True ): """Расширенная версия вычисления с учетом инфляции и дополнительных расходов""" m0 = clamp(margin0_pct / 100.0, 0.0, 0.9) ct0 = clamp(corp0_pct / 100.0, 0.0, 0.6) pt0 = clamp(pers0_pct / 100.0, 0.0, 0.6) mult = max(0.0, rev_mult) mdelta = margin_delta_pp / 100.0 ct1 = clamp(corp1_pct / 100.0, 0.0, 0.6) pt1 = clamp(pers1_pct / 100.0, 0.0, 0.6) p = clamp(success_pct / 100.0, 0.01, 1.0) mr = monthly_rate(discount_annual_pct / 100.0) # Получаем данные по стране для расширенных расчетов country_data = COUNTRY_CONFIG.get(dest, {}) inflation_rate = country_data.get('inflation', 3.0) / 100.0 / 12.0 # месячная инфляция additional_costs = country_data.get('additional_costs', {}) base_profit0 = rev0 * m0 after_tax0 = base_profit0 * (1 - ct0) * (1 - pt0) - living0 - ongoing0 rev1 = rev0 * mult m1 = clamp(m0 + mdelta, 0.01, 0.9) base_profit1 = rev1 * m1 after_tax1 = base_profit1 * (1 - ct1) * (1 - pt1) - living1 - ongoing1 delta_monthly = after_tax1 - after_tax0 cash = [-capex_once] cum = -capex_once months = [0] cum_series = [cum] payback_m = math.inf for m in range(1, horizon_m + 1): cf = delta_monthly * ramp_factor(m) * p # Учитываем инфляцию if include_inflation: inflation_factor = (1 + inflation_rate) ** m cf = cf / inflation_factor # Добавляем дополнительные расходы if include_additional_costs and m % 12 == 0: # годовые расходы cf -= additional_costs.get('audit_annual', 0) / 12 cf -= additional_costs.get('insurance', 0) / 12 if m % 36 == 0: # расходы на продление визы каждые 3 года cf -= additional_costs.get('visa_renewal', 0) cash.append(cf) cum += cf months.append(m) cum_series.append(cum) if math.isinf(payback_m) and cum >= 0: payback_m = m npv = sum(cf / ((1 + mr) ** t) for t, cf in enumerate(cash)) roi5y = (npv / capex_once * 100.0) if capex_once > 0 else (0.0 if npv <= 0 else math.inf) irr_m = irr_bisection(cash) irr_annual = ((1 + irr_m) ** 12 - 1) * 100.0 if irr_m is not None else 0.0 return { "npv": npv, "total_5yr_roi": roi5y, "payback_months": payback_m, "payback_years": (payback_m / 12.0) if not math.isinf(payback_m) else float("inf"), "irr_annual_pct": irr_annual, "months": months, "cum_values": cum_series, "delta_monthly": delta_monthly, "country_data": country_data } # ========================= # РАСШИРЕННЫЕ ВИЗУАЛИЗАЦИИ # ========================= def create_enhanced_cashflow_chart(months, cum_values, payback_month=None, sensitivity_data=None): """Расширенный график с доверительными интервалами""" fig = go.Figure() # Основная линия fig.add_trace(go.Scatter( x=months, y=cum_values, mode="lines", line=dict(width=4, color="#2563EB"), fill='tozeroy', fillcolor="rgba(37,99,235,0.1)", name="Cumulative ΔCF" )) # Добавляем доверительные интервалы если есть данные if sensitivity_data: upper_bound = [val * 1.2 for val in cum_values] # Упрощенный верхний предел lower_bound = [val * 0.8 for val in cum_values] # Упрощенный нижний предел fig.add_trace(go.Scatter( x=months + months[::-1], y=upper_bound + lower_bound[::-1], fill='toself', fillcolor='rgba(37,99,235,0.1)', line=dict(color='rgba(255,255,255,0)'), name='Confidence Interval' )) fig.add_hline(y=0, line_width=2, line_dash="dot", line_color="#94A3B8") if payback_month not in (None, float("inf")): fig.add_vline( x=payback_month, line_width=2, line_dash="dash", line_color="#10B981", annotation_text="💰 Break-even", annotation_position="top right" ) fig.update_layout( title="Enhanced Cashflow Projection with Confidence Intervals", margin=dict(l=20, r=20, t=50, b=20), xaxis_title="Month", yaxis_title="Cumulative €", plot_bgcolor="#FFFFFF", paper_bgcolor="#FFFFFF", showlegend=True, height=420 ) return fig def create_sensitivity_chart(sensitivity_data): """График анализа чувствительности""" params = list(sensitivity_data.keys()) high_impacts = [sensitivity_data[p]["high"] for p in params] low_impacts = [sensitivity_data[p]["low"] for p in params] fig = go.Figure() fig.add_trace(go.Bar( name='Upside (+20%)', x=params, y=high_impacts, marker_color='#10B981' )) fig.add_trace(go.Bar( name='Downside (-20%)', x=params, y=low_impacts, marker_color='#EF4444' )) fig.update_layout( title="Sensitivity Analysis: Impact on ROI", xaxis_title="Parameter", yaxis_title="ROI Impact (%)", barmode='group', height=350 ) return fig def create_comparison_radar_chart(countries_data): """Радарная диаграмма для сравнения стран""" categories = ['ROI', 'Market Growth', 'Ease of Business', 'Tax Efficiency', 'Banking Score'] fig = go.Figure() for country, data in countries_data.items(): values = [ data.get('roi_normalized', 50), data.get('market_growth', 0) * 10, data.get('ease_business', 0) * 10, 100 - (data.get('total_tax_rate', 50)), # Обратная налоговая эффективность data.get('banking_score', 0) * 10 ] fig.add_trace(go.Scatterpolar( r=values, theta=categories, fill='toself', name=country )) fig.update_layout( polar=dict( radialaxis=dict(visible=True, range=[0, 100]) ), showlegend=True, title="Multi-Dimensional Country Comparison" ) return fig # ========================= # UI HELPERS (расширенные) # ========================= def render_enhanced_kpis(result, country_data, monte_carlo_data=None): """Расширенные KPI с дополнительной информацией""" payback_years = "Never" if result["payback_years"] == float("inf") else f'{result["payback_years"]:.1f} years' roi_str = f'{result["total_5yr_roi"]:.1f}%' irr_str = f'{result["irr_annual_pct"]:.1f}%' npv_str = f'€{result["npv"]:,.0f}' # Определяем класс риска risk_class = "good" if result["payback_years"] <= 1.5 else ("warn" if result["payback_years"] <= 3.0 else "") k1 = f"""
💰 Payback Period
{payback_years}
Time to break even • Market growth: {country_data.get('market_growth', 'N/A')}%
""" k2 = f"""
🚀 ROI (5-year)
{roi_str}
Risk-adjusted return • {country_data.get('tax_treaties', 'N/A')} tax treaties
""" k3 = f"""
📈 IRR (Annual)
{irr_str}
Internal rate of return • Ease of business: {country_data.get('ease_business', 'N/A')}/10
""" # Добавляем Monte Carlo данные если есть mc_info = "" if monte_carlo_data: mc_info = f" • 90% confidence: €{monte_carlo_data.get('percentile_10', 0):,.0f} - €{monte_carlo_data.get('percentile_90', 0):,.0f}" k4 = f"""
💎 NPV
{npv_str}
Net present value{mc_info}
""" return k1, k2, k3, k4 def render_risk_assessment(result, country_data): """Генерация оценки рисков""" risks = [] if result["payback_years"] > 3: risks.append('⚠️ Long Payback') elif result["payback_years"] <= 1.5: risks.append('✅ Quick Payback') else: risks.append('⏳ Moderate Payback') if country_data.get('ease_business', 0) >= 8: risks.append('🏢 Business Friendly') elif country_data.get('ease_business', 0) < 7: risks.append('📋 Complex Setup') if country_data.get('inflation', 0) > 4: risks.append('📊 High Inflation') else: risks.append('💹 Stable Economy') return "".join(risks) def create_executive_summary(result, country, recommendations): """Создание краткого резюме для руководителей""" summary = f"""

🎯 Executive Summary: {country}

💰 Financial Impact
ROI: {result['total_5yr_roi']:.1f}%
Payback: {result['payback_years']:.1f} years
⚡ Key Insights
IRR: {result['irr_annual_pct']:.1f}%
NPV: €{result['npv']:,.0f}
🤖 AI Recommendations:
""" return summary # ========================= # ГЛАВНОЕ ПРИЛОЖЕНИЕ (РАСШИРЕННОЕ) # ========================= def create_enhanced_app(): with gr.Blocks(css=CSS, theme=THEME, title="VisaTier - Enhanced Immigration ROI Simulator") as demo: # HEADER с дополнительной информацией gr.HTML("""
🌍 VisaTier — Enhanced Immigration ROI Simulator
Advanced analytics • Risk modeling • AI insights
Built for founders & investors
v2.0 Enhanced
""") # Расширенная методология with gr.Accordion("📊 Enhanced Methodology & Features", open=False): gr.HTML("""

🔬 Advanced Features Added:

📈 Risk Analytics
  • Monte Carlo simulations
  • Sensitivity analysis
  • Confidence intervals
🎯 Smart Insights
  • AI-powered recommendations
  • Multi-currency support
  • Inflation adjustments
🚀 Enhanced UX
  • Visa pathway guidance
  • Export capabilities
  • Mobile optimization
""") # HERO расширенный gr.HTML("""

🎯 Model the complete financial impact of your relocation

Advanced simulation with risk modeling, AI insights, and multi-dimensional analysis

✨ AI-Powered 📊 Risk Analytics 💼 Executive Ready 📱 Mobile Friendly
""") # ===== MAIN SIMULATOR (ENHANCED) ===== with gr.Row(): with gr.Column(scale=5): gr.Markdown("### 🎛️ Simulation Parameters") with gr.Row(): dest = gr.Dropdown( list(COUNTRY_CONFIG.keys()), value="UAE (Dubai)", label="🎯 Destination Country", info="Select your target destination" ) currency_display = gr.Dropdown( list(CURRENCIES.keys()), value="EUR", label="💱 Display Currency", info="All amounts will be converted" ) with gr.Accordion("💼 Current Business Situation", open=True): with gr.Row(): rev0 = gr.Number( value=30000, label="📈 Monthly Revenue (€)", info="Your current monthly business revenue" ) margin0 = gr.Slider( value=25, minimum=1, maximum=70, step=1, label="💰 EBITDA Margin (%)", info="Current profit margin before taxes" ) with gr.Row(): corp0 = gr.Slider( value=20, minimum=0, maximum=50, step=1, label="🏢 Corporate Tax Rate (%)", info="Current corporate tax burden" ) pers0 = gr.Slider( value=10, minimum=0, maximum=50, step=1, label="👤 Personal Tax Rate (%)", info="Current personal tax on distributions" ) with gr.Row(): living0 = gr.Number( value=4000, label="🏠 Living Costs (€/month)", info="Current monthly living expenses" ) ongoing0 = gr.Number( value=0, label="⚙️ Other Costs (€/month)", info="Additional monthly business costs" ) with gr.Accordion("🚀 Destination Projections", open=True): gr.Markdown("*Adjustments for your new destination:*") with gr.Row(): rev_mult = gr.Slider( value=3.0, minimum=0.5, maximum=5.0, step=0.1, label="📊 Revenue Multiplier (×)", info="Expected revenue growth factor" ) margin_delta = gr.Slider( value=5.0, minimum=-20, maximum=30, step=0.5, label="📈 Margin Improvement (pp)", info="Expected margin change in percentage points" ) with gr.Row(): corp1 = gr.Slider( value=9, minimum=0, maximum=50, step=1, label="🏢 New Corporate Tax (%)", info="Destination corporate tax rate" ) pers1 = gr.Slider( value=0, minimum=0, maximum=50, step=1, label="👤 New Personal Tax (%)", info="Destination personal tax rate" ) with gr.Row(): living1 = gr.Number( value=9000, label="🏠 New Living Costs (€/month)", info="Expected monthly living costs in destination" ) ongoing1 = gr.Number( value=1500, label="⚙️ New Ongoing Costs (€/month)", info="Additional monthly business costs in destination" ) with gr.Accordion("🎯 Investment & Risk Parameters", open=False): with gr.Row(): capex_once = gr.Number( value=35000, label="💸 Setup Investment (€)", info="One-time relocation and setup costs" ) horizon_m = gr.Slider( value=60, minimum=12, maximum=120, step=1, label="📅 Analysis Period (months)", info="Time horizon for analysis" ) with gr.Row(): discount_a = gr.Slider( value=12, minimum=0, maximum=40, step=1, label="💹 Discount Rate (%)", info="Your required annual rate of return" ) success = gr.Slider( value=75, minimum=10, maximum=100, step=1, label="🎯 Success Probability (%)", info="Likelihood of achieving projections" ) with gr.Row(): include_inflation = gr.Checkbox( value=True, label="📊 Include Inflation Impact", info="Adjust for inflation in destination country" ) include_additional = gr.Checkbox( value=True, label="💼 Include Additional Costs", info="Factor in visa renewals, compliance costs, etc." ) with gr.Row(): estimate_btn = gr.Button( "🚀 Run Enhanced Analysis", variant="primary", size="lg" ) reset_btn = gr.Button( "🔄 Reset to Defaults", variant="secondary" ) with gr.Column(scale=7): gr.Markdown("### 📊 Analysis Results") # KPIs Grid with gr.Row(): with gr.Column(scale=1): kpi1 = gr.HTML("""
💰 Payback Period
Click "Run Analysis" to calculate
""") with gr.Column(scale=1): kpi2 = gr.HTML("""
🚀 ROI (5-year)
Risk-adjusted return
""") with gr.Row(): with gr.Column(scale=1): kpi3 = gr.HTML("""
📈 IRR (Annual)
Internal rate of return
""", visible=False) with gr.Column(scale=1): kpi4 = gr.HTML("""
💎 NPV
Net present value
""", visible=False) # Risk Assessment risk_indicators = gr.HTML("", visible=False) # Executive Summary executive_summary = gr.HTML("", visible=False) # Charts main_chart = gr.Plot(visible=False) with gr.Row(): sensitivity_chart = gr.Plot(visible=False) monte_carlo_info = gr.HTML("", visible=False) # State variables state_result = gr.State(value=None) state_enhanced_data = gr.State(value=None) # Main calculation function def run_enhanced_analysis( dest, currency_display, rev0, margin0, corp0, pers0, living0, ongoing0, rev_mult, margin_delta, corp1, pers1, living1, ongoing1, capex_once, horizon_m, discount_a, success, include_inflation, include_additional ): try: # Apply template defaults intelligently if dest in COUNTRY_CONFIG: cfg = COUNTRY_CONFIG[dest] # Run main calculation result = compute_enhanced_monthly_delta_cashflow( rev0, margin0, corp0, pers0, living0, ongoing0, dest, rev_mult, margin_delta, corp1, pers1, living1, ongoing1, capex_once, int(horizon_m), discount_a, success, include_inflation, include_additional ) # Enhanced analytics base_params = { 'rev_mult': rev_mult, 'margin_delta_pp': margin_delta, 'success_pct': success, 'base_roi': result['total_5yr_roi'] } sensitivity_data = calculate_sensitivity_analysis(base_params, result) monte_carlo_data = create_monte_carlo_simulation(base_params, 1000) # AI recommendations personal_profile = { 'revenue': rev0, 'risk_tolerance': success } recommendations = generate_ai_recommendation(result, dest, personal_profile) # Render components country_data = COUNTRY_CONFIG.get(dest, {}) k1, k2, k3, k4 = render_enhanced_kpis(result, country_data, monte_carlo_data) risk_html = render_risk_assessment(result, country_data) exec_summary = create_executive_summary(result, dest, recommendations) # Charts main_chart_fig = create_enhanced_cashflow_chart( result["months"], result["cum_values"], result["payback_months"], sensitivity_data ) sensitivity_chart_fig = create_sensitivity_chart(sensitivity_data) # Monte Carlo summary mc_html = f"""
🎲 Monte Carlo Analysis
{monte_carlo_data['probability_positive']:.1f}%
Probability of positive outcome
Expected range: €{monte_carlo_data['percentile_10']:,.0f} - €{monte_carlo_data['percentile_90']:,.0f}
""" enhanced_data = { 'result': result, 'sensitivity': sensitivity_data, 'monte_carlo': monte_carlo_data, 'recommendations': recommendations, 'country_data': country_data } return ( k1, k2, # First row KPIs (always visible) gr.update(value=k3, visible=True), # Second row KPIs gr.update(value=k4, visible=True), gr.update(value=risk_html, visible=True), # Risk indicators gr.update(value=exec_summary, visible=True), # Executive summary gr.update(value=main_chart_fig, visible=True), # Main chart gr.update(value=sensitivity_chart_fig, visible=True), # Sensitivity gr.update(value=mc_html, visible=True), # Monte Carlo enhanced_data, result ) except Exception as e: error_msg = f"❌ Analysis failed: {str(e)}" return ( f'
{error_msg}
', "", gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), None, None ) estimate_btn.click( run_enhanced_analysis, inputs=[ dest, currency_display, rev0, margin0, corp0, pers0, living0, ongoing0, rev_mult, margin_delta, corp1, pers1, living1, ongoing1, capex_once, horizon_m, discount_a, success, include_inflation, include_additional ], outputs=[ kpi1, kpi2, kpi3, kpi4, risk_indicators, executive_summary, main_chart, sensitivity_chart, monte_carlo_info, state_enhanced_data, state_result ] ) # ===== VISA GUIDANCE SECTION ===== gr.Markdown("## 🛂 Visa Pathway Guidance") with gr.Row(): with gr.Column(scale=1): visa_country = gr.Dropdown( list(VISA_TYPES.keys()), value="UAE (Dubai)", label="Select Country for Visa Info" ) get_visa_info_btn = gr.Button("Get Visa Information", variant="secondary") with gr.Column(scale=2): visa_timeline = gr.HTML("") def show_visa_info(country): if country in VISA_TYPES: timeline = create_enhanced_timeline(country) return timeline return "No visa information available for this country." get_visa_info_btn.click( show_visa_info, inputs=[visa_country], outputs=[visa_timeline] ) # ===== ENHANCED COMPARISON SECTION ===== gr.Markdown("## 🌍 Enhanced Multi-Country Comparison") with gr.Row(): with gr.Column(scale=5): gr.Markdown("**Shared assumptions for comparison:**") with gr.Row(): rev0_c = gr.Number(value=30000, label="📈 Baseline Revenue (€/month)") margin0_c = gr.Slider(value=25, minimum=1, maximum=70, step=1, label="💰 Baseline Margin (%)") with gr.Row(): corp0_c = gr.Slider(value=20, minimum=0, maximum=50, step=1, label="🏢 Current Corp Tax (%)") pers0_c = gr.Slider(value=10, minimum=0, maximum=50, step=1, label="👤 Current Personal Tax (%)") with gr.Row(): living0_c = gr.Number(value=4000, label="🏠 Current Living (€/month)") success_c = gr.Slider(value=75, minimum=10, maximum=100, step=1, label="🎯 Success Probability (%)") compare_enhanced_btn = gr.Button("🚀 Run Enhanced Comparison", variant="primary") with gr.Column(scale=7): comparison_results = gr.HTML("") with gr.Row(): comparison_bar_chart = gr.Plot() radar_comparison = gr.Plot() def run_enhanced_comparison(rev0, margin0, corp0, pers0, living0, success): try: countries_data = {} results_for_chart = [] for country_name in COUNTRY_CONFIG.keys(): cfg = COUNTRY_CONFIG[country_name] result = compute_enhanced_monthly_delta_cashflow( rev0, margin0, corp0, pers0, living0, 0, country_name, cfg["rev_mult"], cfg["margin_delta_pp"], cfg["corp_tax"]*100, cfg["pers_tax"]*100, cfg["living_month"], cfg["ongoing_month"], cfg["setup_once"], 60, 12, success, True, True ) countries_data[country_name] = { 'roi_normalized': max(0, min(100, result['total_5yr_roi'])), 'market_growth': cfg.get('market_growth', 0), 'ease_business': cfg.get('ease_business', 0), 'total_tax_rate': (cfg['corp_tax'] + cfg['pers_tax']) * 100, 'banking_score': cfg.get('banking_score', 0) } results_for_chart.append({ 'country': country_name, 'roi': result['total_5yr_roi'], 'payback': result['payback_years'], 'npv': result['npv'] }) # Create comparison table table_html = """

🎯 Comprehensive Country Analysis

""" for result_data in results_for_chart: country = result_data['country'] cfg = COUNTRY_CONFIG[country] payback_str = "Never" if result_data['payback'] == float('inf') else f"{result_data['payback']:.1f}y" # Simple recommendation logic if result_data['roi'] > 150 and result_data['payback'] < 2: recommendation = "🚀 Excellent" rec_class = "risk-low" elif result_data['roi'] > 75 and result_data['payback'] < 3: recommendation = "✅ Good" rec_class = "risk-medium" else: recommendation = "⚠️ Consider" rec_class = "risk-high" table_html += f""" """ table_html += """
Country ROI (5y) Payback Market Growth Ease of Business Recommendation
{country} {result_data['roi']:.1f}% {payback_str} {cfg.get('market_growth', 0):.1f}% {cfg.get('ease_business', 0):.1f}/10 {recommendation}
""" # Create bar chart countries = [r['country'] for r in results_for_chart] rois = [r['roi'] for r in results_for_chart] bar_fig = go.Figure() bar_fig.add_bar( x=countries, y=rois, marker_color=['#10B981' if roi > 100 else '#F59E0B' if roi > 50 else '#EF4444' for roi in rois], text=[f'{roi:.1f}%' for roi in rois], textposition='auto' ) bar_fig.update_layout( title="ROI Comparison Across Countries", xaxis_title="Country", yaxis_title="5-Year ROI (%)", height=400 ) # Create radar chart radar_fig = create_comparison_radar_chart(countries_data) return table_html, bar_fig, radar_fig except Exception as e: error_html = f"""
❌ Comparison failed: {str(e)}
""" return error_html, go.Figure(), go.Figure() compare_enhanced_btn.click( run_enhanced_comparison, inputs=[rev0_c, margin0_c, corp0_c, pers0_c, living0_c, success_c], outputs=[comparison_results, comparison_bar_chart, radar_comparison] ) # ===== EXPORT SECTION ===== gr.Markdown("## 📁 Export & Share Results") with gr.Row(): with gr.Column(): export_format = gr.Dropdown( ["JSON", "PDF Report", "Excel Summary"], value="JSON", label="Export Format" ) export_btn = gr.Button("📥 Generate Export", variant="secondary") export_output = gr.File(label="Download Results", visible=False) export_status = gr.HTML("") def generate_export(format_type, enhanced_data, current_result): if not enhanced_data or not current_result: return gr.update(visible=False), "❌ No data to export. Please run analysis first." try: timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") if format_type == "JSON": # Create comprehensive JSON export export_data = { "meta": { "timestamp": datetime.now().isoformat(), "version": "2.0_enhanced", "generated_by": "VisaTier Immigration ROI Simulator" }, "analysis_results": { "npv": current_result["npv"], "roi_5y": current_result["total_5yr_roi"], "payback_years": current_result["payback_years"], "irr_annual": current_result["irr_annual_pct"] }, "risk_analytics": { "sensitivity_analysis": enhanced_data.get('sensitivity', {}), "monte_carlo": enhanced_data.get('monte_carlo', {}), }, "recommendations": enhanced_data.get('recommendations', []), "country_data": enhanced_data.get('country_data', {}) } # Create file json_str = json.dumps(export_data, indent=2, ensure_ascii=False) filename = f"immigration_roi_analysis_{timestamp}.json" # Save to temporary file with open(filename, 'w', encoding='utf-8') as f: f.write(json_str) return gr.update(value=filename, visible=True), "✅ Export generated successfully!" else: return gr.update(visible=False), f"⚠️ {format_type} export coming soon!" except Exception as e: return gr.update(visible=False), f"❌ Export failed: {str(e)}" export_btn.click( generate_export, inputs=[export_format, state_enhanced_data, state_result], outputs=[export_output, export_status] ) # ===== ENHANCED FOOTER ===== gr.HTML(f""" """) return demo # ===== RESET FUNCTIONALITY ===== def reset_all_inputs(): """Функция сброса всех параметров к значениям по умолчанию""" return ( "UAE (Dubai)", # dest "EUR", # currency 30000, # rev0 25, # margin0 20, # corp0 10, # pers0 4000, # living0 0, # ongoing0 3.0, # rev_mult 5.0, # margin_delta 9, # corp1 0, # pers1 9000, # living1 1500, # ongoing1 35000, # capex_once 60, # horizon_m 12, # discount_a 75, # success True, # include_inflation True # include_additional ) # Главная переменная для HuggingFace demo = create_enhanced_app() if __name__ == "__main__": demo.launch( share=False, server_name="0.0.0.0", server_port=7860, show_api=False, show_error=True )