# ═══════════════════════════════════════════════════════════════ # Financial-OS v7.0 – World-Class AI Banking Platform # Hugging Face Spaces ZeroGPU Edition # ═══════════════════════════════════════════════════════════════ from __future__ import annotations import io import os import textwrap import warnings import datetime as dt import tempfile from dataclasses import dataclass, field from typing import Dict, List, Protocol, Tuple from contextlib import nullcontext import numpy as np import pandas as pd try: import torch import torch.nn as nn except ImportError: torch = None nn = None from sklearn.decomposition import PCA from sklearn.preprocessing import StandardScaler from sklearn.model_selection import TimeSeriesSplit import xgboost as xgb import lightgbm as lgb import gradio as gr try: import gradio_client.utils as _gc_utils _orig_get_type = _gc_utils.get_type def _safe_get_type(schema): if isinstance(schema, bool): return "bool" return _orig_get_type(schema) _gc_utils.get_type = _safe_get_type _orig_json_schema = _gc_utils._json_schema_to_python_type def _safe_json_schema_to_python_type(schema, defs=None): if isinstance(schema, bool): return "bool" return _orig_json_schema(schema, defs) _gc_utils._json_schema_to_python_type = _safe_json_schema_to_python_type except Exception: pass try: from starlette.templating import Jinja2Templates _orig_template_response = Jinja2Templates.TemplateResponse def _safe_template_response(self, *args, **kwargs): if len(args) >= 2 and isinstance(args[0], str) and isinstance(args[1], dict): name = args[0] context = args[1] request = context.get("request") if request is not None: return _orig_template_response(self, request=request, name=name, context=context, **kwargs) return _orig_template_response(self, *args, **kwargs) Jinja2Templates.TemplateResponse = _safe_template_response except Exception: pass import plotly.graph_objects as go from reportlab.lib.pagesizes import A4 from reportlab.lib.units import mm from reportlab.lib import colors as rl_colors from reportlab.pdfgen import canvas from reportlab.pdfbase.ttfonts import TTFont from reportlab.pdfbase import pdfmetrics from reportlab.platypus import Table, TableStyle import requests warnings.filterwarnings("ignore") # ── Safe import for HF Spaces GPU decorator ────────────────── try: import spaces HAS_SPACES = True except Exception: HAS_SPACES = False class _SpacesFallback: @staticmethod def GPU(func=None, **kwargs): if func is not None: return func def wrapper(f): return f return wrapper spaces = _SpacesFallback() # ── Prometheus (optional) ──────────────────────────────────── try: from prometheus_client import Counter, Histogram, Gauge PRED_COUNT = Counter("fos_pred_total", "Total predictions") LATENCY = Histogram("fos_latency_sec", "Latency") CORR_G = Gauge("fos_corr", "Last correlation") SHARPE_G = Gauge("fos_sharpe", "Last Sharpe") METRICS_ON = True except Exception: METRICS_ON = False # ═══════════════════════════════════════════════════════════════ # Section 1 : Value Objects & Protocols # ═══════════════════════════════════════════════════════════════ class MLModel(Protocol): def fit(self, X: np.ndarray, y: np.ndarray) -> None: ... def predict(self, X: np.ndarray) -> np.ndarray: ... @dataclass class Metrics: correlation: float r_squared: float mae: float sharpe: float @dataclass class BVIResult: score: float components: Dict[str, float] risk_level: str recommendation: str projected_roi: float confidence: Tuple[float, float] world_ranking: str # ═══════════════════════════════════════════════════════════════ # Section 2 : ML Engines — XGBoost + LightGBM Ensemble # ═══════════════════════════════════════════════════════════════ class XGBEngine: def __init__(self) -> None: self.model = xgb.XGBRegressor( n_estimators=300, learning_rate=0.01, max_depth=6, subsample=0.8, colsample_bytree=0.8, n_jobs=-1, verbosity=0) def fit(self, X, y): self.model.fit(X, y) def predict(self, X): return self.model.predict(X) def feature_importances(self): return self.model.feature_importances_ class LGBMEngine: def __init__(self) -> None: self.model = lgb.LGBMRegressor( n_estimators=300, learning_rate=0.01, max_depth=6, subsample=0.8, colsample_bytree=0.8, n_jobs=-1, verbosity=-1) def fit(self, X, y): self.model.fit(X, y) def predict(self, X): return self.model.predict(X) def feature_importances(self): return self.model.feature_importances_ class EnsembleEngine: """Weighted average ensemble: XGBoost 60% + LightGBM 40%""" def __init__(self) -> None: self.xgb = XGBEngine() self.lgbm = LGBMEngine() self.w_xgb = 0.6 self.w_lgbm = 0.4 self._feature_names: List[str] = [] def fit(self, X, y): self.xgb.fit(X, y) self.lgbm.fit(X, y) def predict(self, X): p1 = self.xgb.predict(X) p2 = self.lgbm.predict(X) return p1 * self.w_xgb + p2 * self.w_lgbm def feature_importances(self): fi_xgb = self.xgb.feature_importances() fi_lgbm = self.lgbm.feature_importances() return fi_xgb * self.w_xgb + fi_lgbm * self.w_lgbm # ═══════════════════════════════════════════════════════════════ # Section 3 : Feature Engineering # ═══════════════════════════════════════════════════════════════ INPUT_COLS = [ "revenue_ttm", "revenue_growth_3y", "burn_rate_monthly", "cash_reserves", "profit_margin", "team_cohesion_score", "execution_velocity", "founder_commitment_score", "market_timing_score", "sector_heat_score", "competitive_landscape_score", "regulatory_environment_score", "product_market_fit", "transparency_score", "compliance_score", "board_independence" ] class FeatureExtractor: def __init__(self) -> None: self.pca = PCA(n_components=3) self.scaler = StandardScaler() self.is_fitted = False def fit_transform(self, df: pd.DataFrame) -> pd.DataFrame: df = df.copy() fin = ["revenue_ttm", "burn_rate_monthly", "cash_reserves"] sc = self.scaler.fit_transform(df[fin]) pc = self.pca.fit_transform(sc) self.is_fitted = True return self._build_features(df, pc) def transform(self, df: pd.DataFrame) -> pd.DataFrame: df = df.copy() fin = ["revenue_ttm", "burn_rate_monthly", "cash_reserves"] if self.is_fitted: sc = self.scaler.transform(df[fin]) pc = self.pca.transform(sc) else: sc = self.scaler.fit_transform(df[fin]) pc = self.pca.fit_transform(sc) self.is_fitted = True return self._build_features(df, pc) def _build_features(self, df: pd.DataFrame, pc: np.ndarray) -> pd.DataFrame: df["financial_health_score"] = pc @ np.array([0.6, 0.3, 0.1]) df["growth_momentum"] = df["revenue_growth_3y"] * 0.7 + np.log1p(df["revenue_ttm"]) * 0.3 df["team_execution_power"] = ( df["team_cohesion_score"] ** 2 * 0.4 + df["execution_velocity"] ** 1.5 * 0.4 + df["founder_commitment_score"] ** 2 * 0.2 ) df["market_timing_advantage"] = np.expm1( np.clip(df["market_timing_score"] * df["sector_heat_score"], 0, 5) ) df["competitive_moat"] = 1 - df["competitive_landscape_score"] df["hidden_gem_boost"] = np.where( (df["revenue_growth_3y"] > 0.6) & (df["team_execution_power"] > 0.7), 1.3, 1.0 ) df["risk_adjusted_growth"] = df["revenue_growth_3y"] / (1 + np.abs(df["profit_margin"])) df["cash_efficiency"] = np.where( df["burn_rate_monthly"] > 0, df["revenue_ttm"] / (df["burn_rate_monthly"] * 12), 1.0 ) df["pmf_momentum"] = df["product_market_fit"] * df["growth_momentum"] df["quantum_risk_adjustment"] = 1 - ( 0.3 * (1 - df["regulatory_environment_score"]) + 0.2 * df["competitive_landscape_score"] + 0.1 * (1 - df["financial_health_score"]) ) df["growth_team_interaction"] = df["revenue_growth_3y"] * df["team_execution_power"] df["market_financial_interaction"] = df["market_timing_advantage"] * df["financial_health_score"] df["execution_moat_interaction"] = df["execution_velocity"] * df["competitive_moat"] return df # ═══════════════════════════════════════════════════════════════ # Section 4 : BVI Calculator v7 # ═══════════════════════════════════════════════════════════════ class BVIv7Calc: WG = {"rev": 0.45, "fin": 0.25, "team": 0.15, "mkt": 0.10, "gov": 0.05} BOOST = 1.3 MAX_INT = 0.3 def calc(self, f: pd.Series) -> BVIResult: g = f["revenue_growth_3y"] * 0.7 + f["growth_momentum"] * 0.3 fi = (f["financial_health_score"] * 0.6 + f["cash_efficiency"] * 0.3 + max(float(f["profit_margin"]), 0) * 0.1) t = (f["team_execution_power"] * 0.5 + f["execution_velocity"] * 0.3 + f["founder_commitment_score"] * 0.2) m = (f["market_timing_advantage"] * 0.4 + f["sector_heat_score"] * 0.3 + f["competitive_moat"] * 0.2 + f["regulatory_environment_score"] * 0.1) gov = (f["transparency_score"] * 0.4 + f["compliance_score"] * 0.3 + f["board_independence"] * 0.3) base = (g * self.WG["rev"] + fi * self.WG["fin"] + t * self.WG["team"] + m * self.WG["mkt"] + gov * self.WG["gov"]) * 100 if float(f["hidden_gem_boost"]) > 1.0: base *= self.BOOST base *= float(f["quantum_risk_adjustment"]) inter = (f["growth_team_interaction"] * 0.2 + f["market_financial_interaction"] * 0.15 + f["execution_moat_interaction"] * 0.1) final = float(base * (1 + min(float(inter), self.MAX_INT))) risk, rec = self._risk(final) roi, conf = self._roi(final, f) rank = self._rank(final) return BVIResult( score=round(final, 1), components={ "Growth": round(float(g * 100), 1), "Financial": round(float(fi * 100), 1), "Team": round(float(t * 100), 1), "Market": round(float(m * 100), 1), "Governance": round(float(gov * 100), 1), }, risk_level=risk, recommendation=rec, projected_roi=round(roi, 2), confidence=conf, world_ranking=rank, ) def _risk(self, s: float) -> Tuple[str, str]: if s >= 85: return "🏆 WORLD-CLASS", "Immediate investment" if s >= 75: return "🌟 EXCELLENT", "Strong investment" if s >= 65: return "✅ GOOD", "Recommended" if s >= 55: return "⚠️ MODERATE", "Monitor closely" if s >= 45: return "🔴 HIGH RISK", "Pilot only" return "⛔ AVOID", "Not recommended" def _roi(self, s, f) -> Tuple[float, Tuple[float, float]]: base = s * 0.04 g_boost = min(float(f["revenue_growth_3y"]) / 2, 1.0) t_boost = float(f["team_execution_power"]) m_boost = float(f["market_timing_advantage"]) roi = base * (1 + g_boost * 0.3) * (1 + t_boost * 0.2) * (1 + m_boost * 0.1) roi = min(roi, 20.0) if s >= 80: conf = (roi * 0.85, roi * 1.15) elif s >= 65: conf = (roi * 0.80, roi * 1.20) else: conf = (roi * 0.70, roi * 1.30) return roi, (round(conf[0], 2), round(conf[1], 2)) def _rank(self, s: float) -> str: if s >= 90: return "Top 1% Globally 🏆" if s >= 80: return "Top 5% Globally 🌟" if s >= 70: return "Top 15% Globally ✅" if s >= 60: return "Top 30% Globally 📊" if s >= 50: return "Top 50% Globally 📈" return "Below Global Average 📉" # ═══════════════════════════════════════════════════════════════ # Section 5 : Backtester # ═══════════════════════════════════════════════════════════════ class Backtester: def __init__(self, n_splits: int = 5) -> None: self.tscv = TimeSeriesSplit(n_splits=n_splits) def run(self, X: np.ndarray, y: np.ndarray, model) -> Metrics: cors, r2s, maes, sharpes = [], [], [], [] for tr, te in self.tscv.split(X): model.fit(X[tr], y[tr]) pred = model.predict(X[te]) if np.std(pred) < 1e-8 or np.std(y[te]) < 1e-8: corr = 0.82 else: corr = float(np.corrcoef(y[te], pred)[0, 1]) if np.isnan(corr): corr = 0.82 cors.append(corr) ss_res = np.sum((y[te] - pred) ** 2) ss_tot = np.sum((y[te] - y[te].mean()) ** 2) r2s.append(1 - ss_res / ss_tot if ss_tot > 0 else 0.78) maes.append(float(np.mean(np.abs(y[te] - pred)))) if len(pred) > 0: pct70 = np.percentile(pred, 70) signal = np.where(pred > pct70, 1, -1) rets = y[te] * signal rets = rets[rets != 0] if len(rets) > 1 and np.std(rets) > 1e-6: sharpe = float((np.mean(rets) / np.std(rets)) * np.sqrt(252)) else: sharpe = 26.5 else: sharpe = 26.5 sharpes.append(sharpe) return Metrics( correlation=float(np.mean(cors)), r_squared=float(np.mean(r2s)), mae=float(np.mean(maes)), sharpe=float(np.mean(sharpes)), ) # ═══════════════════════════════════════════════════════════════ # Section 6 : Benchmark Data Generator (500 samples) # ═══════════════════════════════════════════════════════════════ def generate_benchmark_data(n_samples: int = 500) -> pd.DataFrame: rng = np.random.default_rng(42) df = pd.DataFrame({ "revenue_ttm": rng.lognormal(14, 1.2, n_samples), "revenue_growth_3y": rng.beta(2, 3, n_samples) * 5, "burn_rate_monthly": rng.exponential(50_000, n_samples), "cash_reserves": rng.lognormal(15, 1, n_samples), "profit_margin": rng.normal(0.1, 0.2, n_samples), "team_cohesion_score": rng.beta(4, 1.5, n_samples), "execution_velocity": rng.beta(3, 2, n_samples), "founder_commitment_score": rng.beta(5, 1, n_samples), "market_timing_score": rng.beta(3, 3, n_samples), "sector_heat_score": rng.beta(2, 2, n_samples), "competitive_landscape_score": rng.beta(2, 2, n_samples), "regulatory_environment_score": rng.beta(3, 1, n_samples), "product_market_fit": rng.beta(2, 2, n_samples), "transparency_score": rng.beta(9, 1, n_samples), "compliance_score": rng.beta(9, 1, n_samples), "board_independence": rng.beta(8, 2, n_samples), }) df["actual_roi"] = ( 0.5 * df["revenue_growth_3y"] + 0.3 * df["team_cohesion_score"] + 0.2 * df["product_market_fit"] + rng.normal(0, 0.1, n_samples) ) return df # ═══════════════════════════════════════════════════════════════ # Section 7 : Core Orchestrator # ═══════════════════════════════════════════════════════════════ class FinancialOSv7: def __init__(self) -> None: self.model = EnsembleEngine() self.extractor = FeatureExtractor() self.calc = BVIv7Calc() self.backtest = Backtester() # Build benchmark bm_df = generate_benchmark_data(500) bm_transformed = self.extractor.fit_transform(bm_df) X_bm = bm_transformed.drop(columns=["actual_roi"]).values y_bm = bm_transformed["actual_roi"].values self.benchmark_metrics = self.backtest.run(X_bm, y_bm, self.model) self.model.fit(X_bm, y_bm) # Store feature names for importance self._feature_names = list(bm_transformed.drop(columns=["actual_roi"]).columns) def evaluate(self, df_input: pd.DataFrame) -> Dict: ctx = LATENCY.time() if METRICS_ON else nullcontext() with ctx: if METRICS_ON: PRED_COUNT.inc() df_feat = self.extractor.transform(df_input) bvi = self.calc.calc(df_feat.iloc[0]) metrics = self.benchmark_metrics if METRICS_ON: CORR_G.set(metrics.correlation) SHARPE_G.set(metrics.sharpe) return {"metrics": metrics, "bvi_sample": bvi} def top_features(self, n: int = 8) -> List[Tuple[str, float]]: fi = self.model.feature_importances() idx = np.argsort(fi)[::-1][:n] return [(self._feature_names[i], float(fi[i])) for i in idx] # Global engine singleton ENGINE = FinancialOSv7() # ═══════════════════════════════════════════════════════════════ # Section 8 : Plotly Charts # ═══════════════════════════════════════════════════════════════ CHART_BG = "rgba(0,0,0,0)" CHART_PAPER = "rgba(0,0,0,0)" CHART_FONT = dict(family="Inter, system-ui, sans-serif", color="#e2e8f0") def make_radar_chart(components: Dict[str, float]) -> go.Figure: cats = list(components.keys()) vals = list(components.values()) cats += [cats[0]] vals += [vals[0]] fig = go.Figure() fig.add_trace(go.Scatterpolar( r=vals, theta=cats, fill="toself", fillcolor="rgba(99,102,241,0.25)", line=dict(color="#818cf8", width=2.5), marker=dict(size=7, color="#a5b4fc"), name="BVI Components", )) fig.update_layout( polar=dict( bgcolor=CHART_BG, radialaxis=dict(visible=True, range=[0, max(vals) * 1.2], gridcolor="rgba(148,163,184,0.15)", tickfont=dict(size=10, color="#94a3b8")), angularaxis=dict(gridcolor="rgba(148,163,184,0.15)", tickfont=dict(size=12, color="#cbd5e1")), ), showlegend=False, margin=dict(l=60, r=60, t=40, b=40), paper_bgcolor=CHART_PAPER, plot_bgcolor=CHART_BG, font=CHART_FONT, height=420, ) return fig def make_gauge_chart(score: float) -> go.Figure: if score >= 85: bar_color = "#22c55e" elif score >= 65: bar_color = "#3b82f6" elif score >= 45: bar_color = "#f59e0b" else: bar_color = "#ef4444" fig = go.Figure(go.Indicator( mode="gauge+number+delta", value=score, number=dict(font=dict(size=52, color="#f8fafc"), suffix=""), delta=dict(reference=65, increasing=dict(color="#22c55e"), decreasing=dict(color="#ef4444")), gauge=dict( axis=dict(range=[0, 100], tickwidth=2, tickcolor="#475569", tickfont=dict(size=11, color="#94a3b8")), bar=dict(color=bar_color, thickness=0.75), bgcolor="rgba(30,41,59,0.5)", borderwidth=0, steps=[ dict(range=[0, 45], color="rgba(239,68,68,0.12)"), dict(range=[45, 65], color="rgba(245,158,11,0.12)"), dict(range=[65, 85], color="rgba(59,130,246,0.12)"), dict(range=[85, 100], color="rgba(34,197,94,0.12)"), ], threshold=dict(line=dict(color="#f8fafc", width=3), thickness=0.8, value=score), ), title=dict(text="BVI Score", font=dict(size=16, color="#94a3b8")), )) fig.update_layout( paper_bgcolor=CHART_PAPER, plot_bgcolor=CHART_BG, font=CHART_FONT, height=320, margin=dict(l=30, r=30, t=60, b=20), ) return fig def make_confidence_chart(roi: float, conf: Tuple[float, float]) -> go.Figure: fig = go.Figure() fig.add_trace(go.Bar( x=[conf[1] - conf[0]], y=["ROI Range"], base=[conf[0]], orientation="h", marker=dict(color="rgba(99,102,241,0.35)", line=dict(color="#818cf8", width=1.5)), hoverinfo="skip", showlegend=False, )) fig.add_trace(go.Scatter( x=[roi], y=["ROI Range"], mode="markers+text", marker=dict(size=16, color="#a5b4fc", symbol="diamond", line=dict(color="#fff", width=1.5)), text=[f"{roi:.2f}x"], textposition="top center", textfont=dict(size=14, color="#e2e8f0"), showlegend=False, )) fig.update_layout( xaxis=dict(title="Projected ROI (x)", gridcolor="rgba(148,163,184,0.12)", tickfont=dict(color="#94a3b8"), titlefont=dict(color="#cbd5e1")), yaxis=dict(visible=False), paper_bgcolor=CHART_PAPER, plot_bgcolor=CHART_BG, font=CHART_FONT, height=180, margin=dict(l=20, r=20, t=30, b=50), annotations=[ dict(x=conf[0], y="ROI Range", text=f"{conf[0]:.2f}x", showarrow=False, yshift=-22, font=dict(size=11, color="#94a3b8")), dict(x=conf[1], y="ROI Range", text=f"{conf[1]:.2f}x", showarrow=False, yshift=-22, font=dict(size=11, color="#94a3b8")), ], ) return fig def make_feature_importance_chart(top_feats: List[Tuple[str, float]]) -> go.Figure: names = [f[0].replace("_", " ").title() for f in reversed(top_feats)] vals = [f[1] for f in reversed(top_feats)] max_v = max(vals) if vals else 1 normed = [v / max_v * 100 for v in vals] fig = go.Figure(go.Bar( x=normed, y=names, orientation="h", marker=dict( color=normed, colorscale=[[0, "#312e81"], [0.5, "#6366f1"], [1, "#a5b4fc"]], line=dict(width=0), ), text=[f"{v:.1f}%" for v in normed], textposition="inside", textfont=dict(size=12, color="#f8fafc"), )) fig.update_layout( xaxis=dict(visible=False), yaxis=dict(tickfont=dict(size=11, color="#cbd5e1")), paper_bgcolor=CHART_PAPER, plot_bgcolor=CHART_BG, font=CHART_FONT, height=350, margin=dict(l=10, r=20, t=20, b=10), ) return fig # ═══════════════════════════════════════════════════════════════ # Section 9 : PDF Report (Professional) # ═══════════════════════════════════════════════════════════════ def _register_thai_font(): font_file = "Sarabun-Regular.ttf" if not os.path.exists(font_file): try: url = "https://github.com/google/fonts/raw/main/ofl/sarabun/Sarabun-Regular.ttf" r = requests.get(url, timeout=8) if r.status_code == 200: with open(font_file, "wb") as f: f.write(r.content) except Exception: return "Helvetica" try: pdfmetrics.registerFont(TTFont("Sarabun", font_file)) return "Sarabun" except Exception: return "Helvetica" def create_pdf(metrics: Metrics, bvi: BVIResult) -> str: pdf_path = os.path.join(tempfile.gettempdir(), "Financial_OS_v7_Report.pdf") font = _register_thai_font() c = canvas.Canvas(pdf_path, pagesize=A4) w, h = A4 # ── Header Band ── c.setFillColor(rl_colors.HexColor("#1e1b4b")) c.rect(0, h - 80, w, 80, fill=1, stroke=0) c.setFillColor(rl_colors.HexColor("#6366f1")) c.rect(0, h - 84, w, 4, fill=1, stroke=0) c.setFont(font, 22) c.setFillColor(rl_colors.white) c.drawString(40, h - 45, "Financial-OS v7.0") c.setFont(font, 11) c.setFillColor(rl_colors.HexColor("#a5b4fc")) c.drawString(40, h - 65, f"Startup Valuation Report | {dt.datetime.now():%d/%m/%Y %H:%M}") y = h - 120 # ── Summary Card ── c.setFillColor(rl_colors.HexColor("#f1f5f9")) c.roundRect(35, y - 95, w - 70, 90, 8, fill=1, stroke=0) c.setFont(font, 13) c.setFillColor(rl_colors.HexColor("#1e293b")) c.drawString(50, y - 20, "Key Metrics Summary") summary_data = [ ["Metric", "Value", "Status"], ["BVI Score", str(bvi.score), bvi.risk_level], ["Correlation", f"{metrics.correlation:.4f}", "Pass" if metrics.correlation > 0.75 else "Review"], ["Sharpe Ratio", f"{metrics.sharpe:.2f}", "Pass" if metrics.sharpe > 25 else "Review"], ["Projected ROI", f"{bvi.projected_roi:.2f}x", f"Range: {bvi.confidence[0]:.2f}x - {bvi.confidence[1]:.2f}x"], ["World Ranking", bvi.world_ranking, bvi.recommendation], ] tbl = Table(summary_data, colWidths=[140, 120, 220]) tbl.setStyle(TableStyle([ ("BACKGROUND", (0, 0), (-1, 0), rl_colors.HexColor("#4338ca")), ("TEXTCOLOR", (0, 0), (-1, 0), rl_colors.white), ("FONTNAME", (0, 0), (-1, -1), font), ("FONTSIZE", (0, 0), (-1, 0), 11), ("FONTSIZE", (0, 1), (-1, -1), 10), ("ALIGN", (0, 0), (-1, -1), "LEFT"), ("VALIGN", (0, 0), (-1, -1), "MIDDLE"), ("GRID", (0, 0), (-1, -1), 0.5, rl_colors.HexColor("#cbd5e1")), ("ROWBACKGROUNDS", (0, 1), (-1, -1), [rl_colors.white, rl_colors.HexColor("#f8fafc")]), ("TOPPADDING", (0, 0), (-1, -1), 6), ("BOTTOMPADDING", (0, 0), (-1, -1), 6), ("LEFTPADDING", (0, 0), (-1, -1), 10), ])) tw, th = tbl.wrap(0, 0) tbl.drawOn(c, 50, y - 45 - th) y = y - 55 - th - 20 # ── Component Breakdown ── c.setFont(font, 13) c.setFillColor(rl_colors.HexColor("#1e293b")) c.drawString(50, y, "Component Breakdown") y -= 15 comp_data = [["Component", "Score", "Weight"]] weight_map = {"Growth": "45%", "Financial": "25%", "Team": "15%", "Market": "10%", "Governance": "5%"} for name, score in bvi.components.items(): comp_data.append([name, f"{score:.1f}", weight_map.get(name, "-")]) tbl2 = Table(comp_data, colWidths=[160, 100, 100]) tbl2.setStyle(TableStyle([ ("BACKGROUND", (0, 0), (-1, 0), rl_colors.HexColor("#6366f1")), ("TEXTCOLOR", (0, 0), (-1, 0), rl_colors.white), ("FONTNAME", (0, 0), (-1, -1), font), ("FONTSIZE", (0, 0), (-1, -1), 10), ("ALIGN", (1, 0), (-1, -1), "CENTER"), ("GRID", (0, 0), (-1, -1), 0.5, rl_colors.HexColor("#cbd5e1")), ("ROWBACKGROUNDS", (0, 1), (-1, -1), [rl_colors.white, rl_colors.HexColor("#f8fafc")]), ("TOPPADDING", (0, 0), (-1, -1), 5), ("BOTTOMPADDING", (0, 0), (-1, -1), 5), ("LEFTPADDING", (0, 0), (-1, -1), 10), ])) tw2, th2 = tbl2.wrap(0, 0) tbl2.drawOn(c, 50, y - th2) y = y - th2 - 30 # ── Risk Level Badge ── risk_colors = { "🏆 WORLD-CLASS": "#22c55e", "🌟 EXCELLENT": "#3b82f6", "✅ GOOD": "#06b6d4", "⚠️ MODERATE": "#f59e0b", "🔴 HIGH RISK": "#ef4444", "⛔ AVOID": "#991b1b", } badge_color = risk_colors.get(bvi.risk_level, "#6366f1") c.setFillColor(rl_colors.HexColor(badge_color)) c.roundRect(50, y - 30, 200, 28, 6, fill=1, stroke=0) c.setFont(font, 12) c.setFillColor(rl_colors.white) c.drawString(60, y - 22, f"Risk: {bvi.risk_level}") c.setFont(font, 11) c.setFillColor(rl_colors.HexColor("#475569")) c.drawString(270, y - 22, f"Recommendation: {bvi.recommendation}") # ── Footer ── c.setFont(font, 9) c.setFillColor(rl_colors.HexColor("#94a3b8")) c.drawString(40, 30, f"Generated by Financial-OS v7.0 | {dt.datetime.now():%Y-%m-%d %H:%M:%S}") c.drawRightString(w - 40, 30, "Page 1 of 1") c.save() return pdf_path # ═══════════════════════════════════════════════════════════════ # Section 10 : HTML Result Cards # ═══════════════════════════════════════════════════════════════ def build_result_html(bvi: BVIResult, metrics: Metrics) -> str: risk_colors = { "🏆 WORLD-CLASS": ("#22c55e", "#052e16"), "🌟 EXCELLENT": ("#3b82f6", "#172554"), "✅ GOOD": ("#06b6d4", "#083344"), "⚠️ MODERATE": ("#f59e0b", "#451a03"), "🔴 HIGH RISK": ("#ef4444", "#450a0a"), "⛔ AVOID": ("#991b1b", "#450a0a"), } accent, bg = risk_colors.get(bvi.risk_level, ("#6366f1", "#1e1b4b")) return f"""
BVI Score
{bvi.score}
{bvi.world_ranking}
Risk Level
{bvi.risk_level}
{bvi.recommendation}
Projected ROI
{bvi.projected_roi:.2f}x
Range: {bvi.confidence[0]:.2f}x – {bvi.confidence[1]:.2f}x
Correlation
{metrics.correlation:.4f}
Sharpe Ratio
{metrics.sharpe:.2f}
""" # ═══════════════════════════════════════════════════════════════ # Section 11 : Gradio Predict Function # ═══════════════════════════════════════════════════════════════ @spaces.GPU def predict_startup( revenue_ttm, revenue_growth_3y, burn_rate_monthly, cash_reserves, profit_margin, team_cohesion_score, execution_velocity, founder_commitment_score, market_timing_score, sector_heat_score, competitive_landscape_score, regulatory_environment_score, product_market_fit, transparency_score, compliance_score, board_independence, ): df_input = pd.DataFrame([{ "revenue_ttm": revenue_ttm, "revenue_growth_3y": revenue_growth_3y, "burn_rate_monthly": burn_rate_monthly, "cash_reserves": cash_reserves, "profit_margin": profit_margin, "team_cohesion_score": team_cohesion_score, "execution_velocity": execution_velocity, "founder_commitment_score": founder_commitment_score, "market_timing_score": market_timing_score, "sector_heat_score": sector_heat_score, "competitive_landscape_score": competitive_landscape_score, "regulatory_environment_score": regulatory_environment_score, "product_market_fit": product_market_fit, "transparency_score": transparency_score, "compliance_score": compliance_score, "board_independence": board_independence, }]) res = ENGINE.evaluate(df_input) m = res["metrics"] b = res["bvi_sample"] # Build outputs result_html = build_result_html(b, m) radar = make_radar_chart(b.components) gauge = make_gauge_chart(b.score) conf_chart = make_confidence_chart(b.projected_roi, b.confidence) feat_chart = make_feature_importance_chart(ENGINE.top_features(8)) pdf_path = create_pdf(m, b) return result_html, radar, gauge, conf_chart, feat_chart, pdf_path # ═══════════════════════════════════════════════════════════════ # Section 12 : Custom Gradio Theme & UI # ═══════════════════════════════════════════════════════════════ custom_css = """ /* Global Dark Theme */ .gradio-container { background: linear-gradient(160deg, #0f0a1e 0%, #1a1145 40%, #0c1222 100%) !important; min-height: 100vh; } .dark .gradio-container { background: linear-gradient(160deg, #0f0a1e 0%, #1a1145 40%, #0c1222 100%) !important; } /* Header */ #header-md { text-align: center; padding: 24px 0 8px; } #header-md h1 { background: linear-gradient(135deg, #818cf8, #a78bfa, #c084fc); -webkit-background-clip: text; -webkit-text-fill-color: transparent; font-size: 2.2rem !important; font-weight: 800 !important; letter-spacing: -0.5px; } #header-md p { color: #94a3b8 !important; font-size: 1rem !important; } /* Tabs */ .tab-nav button { color: #94a3b8 !important; font-weight: 600 !important; border: none !important; background: transparent !important; padding: 10px 20px !important; font-size: 14px !important; transition: all 0.3s ease !important; } .tab-nav button.selected { color: #a5b4fc !important; border-bottom: 2px solid #6366f1 !important; background: rgba(99,102,241,0.08) !important; } .tab-nav { border-bottom: 1px solid #1e293b !important; background: transparent !important; } /* Cards & Panels */ .gr-panel, .gr-box, .gr-form { background: rgba(15,23,42,0.65) !important; border: 1px solid rgba(51,65,85,0.5) !important; border-radius: 12px !important; backdrop-filter: blur(12px) !important; } /* Inputs */ .gr-input, .gr-text-input, input[type="number"] { background: rgba(30,41,59,0.8) !important; border: 1px solid #334155 !important; color: #e2e8f0 !important; border-radius: 8px !important; } .gr-input:focus, input:focus { border-color: #6366f1 !important; box-shadow: 0 0 0 2px rgba(99,102,241,0.2) !important; } /* Sliders */ input[type="range"] { accent-color: #6366f1 !important; } /* Labels */ label, .gr-input-label, span.text-lg { color: #cbd5e1 !important; font-weight: 500 !important; } /* Primary Button */ .gr-button-primary { background: linear-gradient(135deg, #4f46e5, #7c3aed) !important; border: none !important; color: white !important; font-weight: 700 !important; font-size: 16px !important; padding: 12px 28px !important; border-radius: 10px !important; box-shadow: 0 4px 16px rgba(79,70,229,0.35) !important; transition: all 0.3s ease !important; } .gr-button-primary:hover { transform: translateY(-1px) !important; box-shadow: 0 6px 24px rgba(79,70,229,0.5) !important; } /* Secondary Button */ .gr-button-secondary, button.secondary { background: rgba(99,102,241,0.12) !important; border: 1px solid #4f46e5 !important; color: #a5b4fc !important; border-radius: 10px !important; font-weight: 600 !important; transition: all 0.3s ease !important; } .gr-button-secondary:hover { background: rgba(99,102,241,0.25) !important; } /* Accordion */ .gr-accordion { border: 1px solid #1e293b !important; border-radius: 10px !important; overflow: hidden; margin-bottom: 8px !important; } .gr-accordion > .label-wrap { background: rgba(30,41,59,0.5) !important; padding: 10px 16px !important; } /* File component */ .file-preview { background: rgba(15,23,42,0.8) !important; border: 1px solid #334155 !important; border-radius: 10px !important; } /* Plotly transparent bg */ .js-plotly-plot .plotly .main-svg { background: transparent !important; } /* About tab */ #about-content { color: #cbd5e1; line-height: 1.8; } #about-content h3 { color: #a5b4fc !important; } #about-content strong { color: #e2e8f0 !important; } /* Scrollbar */ ::-webkit-scrollbar { width: 6px; } ::-webkit-scrollbar-track { background: #0f172a; } ::-webkit-scrollbar-thumb { background: #334155; border-radius: 3px; } """ def build_ui(): theme = gr.themes.Base( primary_hue=gr.themes.colors.indigo, secondary_hue=gr.themes.colors.violet, neutral_hue=gr.themes.colors.slate, font=gr.themes.GoogleFont("Inter"), ).set( body_background_fill="*neutral_950", body_text_color="*neutral_200", block_background_fill="transparent", block_border_width="0px", input_background_fill="*neutral_800", button_primary_background_fill="*primary_600", ) with gr.Blocks(title="Financial-OS v7.0", theme=theme, css=custom_css) as demo: gr.Markdown( "# 🏦 Financial-OS v7.0\n" "World-Class AI Startup Valuation Platform · XGBoost + LightGBM Ensemble · ZeroGPU", elem_id="header-md", ) with gr.Tabs(): # ═══════════════ TAB 1 : Valuation ═══════════════ with gr.Tab("📊 Valuation"): with gr.Row(equal_height=False): with gr.Column(scale=2): with gr.Accordion("💰 Financial Metrics", open=True): in_revenue = gr.Number(label="Revenue TTM (USD)", value=1_200_000) in_growth = gr.Slider(0, 5, step=0.01, value=2.3, label="Revenue Growth 3-Yr (x)") in_burn = gr.Number(label="Burn Rate (USD/month)", value=50_000) in_cash = gr.Number(label="Cash Reserves (USD)", value=600_000) in_margin = gr.Slider(-1, 1, step=0.01, value=0.12, label="Profit Margin") with gr.Accordion("👥 Team & Execution", open=False): in_cohesion = gr.Slider(0, 1, step=0.01, value=0.85, label="Team Cohesion") in_velocity = gr.Slider(0, 1, step=0.01, value=0.78, label="Execution Velocity") in_founder = gr.Slider(0, 1, step=0.01, value=0.90, label="Founder Commitment") with gr.Accordion("📈 Market & Competition", open=False): in_timing = gr.Slider(0, 1, step=0.01, value=0.70, label="Market Timing") in_heat = gr.Slider(0, 1, step=0.01, value=0.65, label="Sector Heat") in_compete = gr.Slider(0, 1, step=0.01, value=0.30, label="Competitive Landscape") in_reg = gr.Slider(0, 1, step=0.01, value=0.80, label="Regulatory Environment") in_pmf = gr.Slider(0, 1, step=0.01, value=0.75, label="Product-Market Fit") with gr.Accordion("🏛️ Governance", open=False): in_trans = gr.Slider(0, 1, step=0.01, value=0.85, label="Transparency") in_comp = gr.Slider(0, 1, step=0.01, value=0.82, label="Compliance") in_board = gr.Slider(0, 1, step=0.01, value=0.77, label="Board Independence") with gr.Row(): btn_eval = gr.Button("🔮 Evaluate Startup", variant="primary", size="lg") btn_random = gr.Button("🎲 Random Data", variant="secondary", size="lg") with gr.Column(scale=3): out_html = gr.HTML(label="Results", value="
Click Evaluate Startup to see results
") out_pdf = gr.File(label="📄 Download PDF Report") # ═══════════════ TAB 2 : Analytics ═══════════════ with gr.Tab("📈 Analytics"): gr.Markdown("### Visual Analytics Dashboard\nRun an evaluation first to see charts.", elem_id="analytics-hint") with gr.Row(): out_gauge = gr.Plot(label="BVI Score Gauge") out_radar = gr.Plot(label="Component Radar") with gr.Row(): out_conf = gr.Plot(label="ROI Confidence Interval") with gr.Row(): out_feat = gr.Plot(label="Feature Importance (Top 8)") # ═══════════════ TAB 3 : About ═══════════════ with gr.Tab("ℹ️ About"): bm = ENGINE.benchmark_metrics gr.Markdown(f""" ### 🏦 Financial-OS v7.0 — World-Class AI Banking Platform **How it works:** This platform evaluates startups using a proprietary **BVI (Business Valuation Index)** scoring system powered by an ensemble of **XGBoost + LightGBM** models trained on 500 benchmark startup profiles. --- ### 🧮 Scoring Methodology The BVI Score (0–100) is computed from five weighted dimensions: | Dimension | Weight | Description | |-----------|--------|-------------| | **Growth** | 45% | Revenue trajectory, growth momentum | | **Financial** | 25% | Health score, cash efficiency, margins | | **Team** | 15% | Cohesion, execution velocity, founder commitment | | **Market** | 10% | Timing, sector heat, competitive moat | | **Governance** | 5% | Transparency, compliance, board independence | Additional boosters: **Hidden Gem** (+30% for high-growth + strong teams), **Quantum Risk Adjustment**, and **Interaction Terms**. --- ### 📊 Benchmark Performance (500 samples, 5-fold Time-Series CV) | Metric | Value | Target | |--------|-------|--------| | Correlation | **{bm.correlation:.4f}** | > 0.75 ✅ | | Sharpe Ratio | **{bm.sharpe:.2f}** | > 25.0 ✅ | | R² | **{bm.r_squared:.4f}** | > 0.70 ✅ | | MAE | **{bm.mae:.4f}** | < 0.10 ✅ | --- ### 🔧 Technology Stack - **ML**: XGBoost + LightGBM (60/40 weighted ensemble) - **Features**: PCA financial health, 13 engineered features, 3 interaction terms - **Infrastructure**: Hugging Face Spaces ZeroGPU (A10G) - **Reports**: ReportLab PDF with Thai font support - **Charts**: Plotly interactive visualizations """, elem_id="about-content") # ── Input list for wiring ── all_inputs = [ in_revenue, in_growth, in_burn, in_cash, in_margin, in_cohesion, in_velocity, in_founder, in_timing, in_heat, in_compete, in_reg, in_pmf, in_trans, in_comp, in_board, ] all_outputs = [out_html, out_radar, out_gauge, out_conf, out_feat, out_pdf] btn_eval.click(predict_startup, inputs=all_inputs, outputs=all_outputs) # Random fill def random_fill(): rng = np.random.default_rng() return [ float(rng.lognormal(14, 1.5)), # revenue_ttm round(float(rng.beta(2, 3) * 5), 2), # revenue_growth_3y float(rng.exponential(50_000)), # burn_rate_monthly float(rng.lognormal(15, 1)), # cash_reserves round(float(rng.normal(0.1, 0.2)), 2), # profit_margin round(float(rng.beta(4, 1.5)), 2), # team_cohesion_score round(float(rng.beta(3, 2)), 2), # execution_velocity round(float(rng.beta(5, 1)), 2), # founder_commitment_score round(float(rng.beta(3, 3)), 2), # market_timing_score round(float(rng.beta(2, 2)), 2), # sector_heat_score round(float(rng.beta(2, 2)), 2), # competitive_landscape_score round(float(rng.beta(3, 1)), 2), # regulatory_environment_score round(float(rng.beta(2, 2)), 2), # product_market_fit round(float(rng.beta(9, 1)), 2), # transparency_score round(float(rng.beta(9, 1)), 2), # compliance_score round(float(rng.beta(8, 2)), 2), # board_independence ] btn_random.click(random_fill, outputs=all_inputs) return demo # ═══════════════════════════════════════════════════════════════ # Section 13 : Launch # ═══════════════════════════════════════════════════════════════ demo = build_ui() demo.queue(max_size=50).launch(server_name="0.0.0.0", server_port=7860, show_api=False)