import gradio as gr CUSTOM_CSS = """ body, .gradio-container { background: linear-gradient(180deg, #08101e 0%, #0b1020 100%); color: white !important; font-family: Inter, Arial, sans-serif; } .hero { padding: 24px; border: 1px solid rgba(255,255,255,0.08); border-radius: 20px; background: rgba(255,255,255,0.03); margin-bottom: 16px; } .metric { padding: 16px; border-radius: 16px; background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.08); } """ def analyze_thesis(ticker, direction, horizon, position_size, thesis): thesis_lower = thesis.lower() thesis_score = 60 evidence_score = 55 risk_score = 45 if "valuation" in thesis_lower: thesis_score += 8 evidence_score += 8 if "risk" in thesis_lower: thesis_score += 6 if "earnings" in thesis_lower or "catalyst" in thesis_lower: evidence_score += 8 if "guaranteed" in thesis_lower or "100%" in thesis_lower: risk_score += 20 thesis_score -= 10 if position_size > 20: risk_score += 15 thesis_score = max(0, min(100, thesis_score)) evidence_score = max(0, min(100, evidence_score)) risk_score = max(0, min(100, risk_score)) capital_readiness = max(0, min(100, int(thesis_score * 0.5 + evidence_score * 0.3 + (100 - risk_score) * 0.2))) contradictions = [] if direction == "Bullish" and "overvalued" in thesis_lower: contradictions.append("Bullish view conflicts with 'overvalued' wording.") if direction == "Bearish" and "undervalued" in thesis_lower: contradictions.append("Bearish view conflicts with 'undervalued' wording.") if not contradictions: contradictions.append("No major contradiction detected.") missing = [] if "valuation" not in thesis_lower: missing.append("Valuation context missing.") if "risk" not in thesis_lower: missing.append("Risk definition missing.") if "stop loss" not in thesis_lower and "invalidation" not in thesis_lower: missing.append("Exit or invalidation plan missing.") if "macro" not in thesis_lower: missing.append("Macro sensitivity not discussed.") counter_case = [] if direction == "Bullish": counter_case = [ "Positive expectations may already be priced in.", "Weak guidance can break the thesis quickly.", "Position sizing may be too aggressive for current evidence." ] else: counter_case = [ "Negative sentiment may already be priced in.", "A strong earnings beat can invalidate the bearish view.", "Bear thesis may underestimate business resilience." ] memo = f""" # BetaTwins Memo **Ticker:** {ticker} **Direction:** {direction} **Horizon:** {horizon} **Position Size:** {position_size}% ## Thesis {thesis} ## Scores - Thesis Score: {thesis_score}/100 - Evidence Score: {evidence_score}/100 - Risk Score: {risk_score}/100 - Capital Readiness: {capital_readiness}/100 ## Contradictions - """ + "\n- ".join(contradictions) + """ ## Missing Factors - """ + "\n- ".join(missing) + """ ## Counter-Case - """ + "\n- ".join(counter_case) summary = f""" ### Executive Summary **{ticker}** thesis reviewed with a **{direction.lower()}** stance. - Thesis Score: **{thesis_score}** - Evidence Score: **{evidence_score}** - Risk Score: **{risk_score}** - Capital Readiness: **{capital_readiness}** """ return ( f"
BetaTwins helps traders, investors, and fintech teams detect weak reasoning, hidden assumptions, and missing risks before a decision becomes expensive.