kussssh/IPO-Analyzer
0
1"""Module 9 — Final IPO Signal Scorecard"""2from langchain_core.prompts import ChatPromptTemplate3 4from backend.schemas import FinalVerdict5from backend.modules.base import get_llm, SYSTEM_PROMPT, _invoke_with_retry6 7 8def run_final_scorecard(m1, m2, m3, m4, m5, m6, m7, m8) -> FinalVerdict:9 """Synthesize all 8 module outputs into a final IPO scorecard."""10 print("\n▶ Running Final Scorecard...")11 12 def sig_to_symbol(sig: str) -> str:13 sig = (sig or "").upper().strip()14 if "POSITIVE" in sig or sig == "+":15 return "+"16 elif "NEGATIVE" in sig or sig == "-":17 return "-"18 return "0"19 20 signals = {21 "Business Quality": sig_to_symbol(m1.signal),22 "Financial Strength": sig_to_symbol(m2.signal),23 "Growth Quality": sig_to_symbol(m3.signal),24 "Valuation": sig_to_symbol(m4.signal),25 "Promoter Alignment": sig_to_symbol(m5.signal),26 "Use of Proceeds": sig_to_symbol(m6.signal),27 "Risk Profile": sig_to_symbol(m7.signal),28 "Institutional": sig_to_symbol(m8.signal),29 }30 31 pos = sum(1 for v in signals.values() if v == "+")32 neg = sum(1 for v in signals.values() if v == "-")33 neu = sum(1 for v in signals.values() if v == "0")34 35 if pos >= 5 and neg <= 1:36 verdict = "Strong"37 elif neg >= 3 or (neg >= 2 and pos <= 2):38 verdict = "Avoid"39 else:40 verdict = "Wait & Watch"41 42 summary_input = f"""43 Company: {m1.company_name}44 45 Module Signals:46 - Business Quality ({signals['Business Quality']}): {m1.signal_reasoning}47 - Financial Strength ({signals['Financial Strength']}): {m2.signal_reasoning}48 - Growth Quality ({signals['Growth Quality']}): {m3.signal_reasoning}49 - Valuation ({signals['Valuation']}): {m4.signal_reasoning}50 - Promoter Alignment ({signals['Promoter Alignment']}): {m5.signal_reasoning}51 - Use of Proceeds ({signals['Use of Proceeds']}): {m6.signal_reasoning}52 - Risk Profile ({signals['Risk Profile']}): {m7.signal_reasoning}53 - Institutional ({signals['Institutional']}): {m8.signal_reasoning}54 55 Score: {pos} Positive, {neu} Neutral, {neg} Negative56 Verdict: {verdict}57 58 Generate:59 1. A 2-3 sentence investment thesis (balanced, analytical, no advice)60 2. Top 3 key positives61 3. Top 3 key concerns62 """63 64 llm = get_llm()65 structured_llm = llm.with_structured_output(FinalVerdict)66 67 prompt = ChatPromptTemplate.from_messages([68 ("system", SYSTEM_PROMPT),69 ("human", "{summary}")70 ])71 72 chain = prompt | structured_llm73 result = _invoke_with_retry(chain, {"summary": summary_input}, "Final Scorecard")74 75 # Override computed fields76 result.business_quality_signal = signals["Business Quality"]77 result.financial_strength_signal = signals["Financial Strength"]78 result.valuation_signal = signals["Valuation"]79 result.promoter_alignment_signal = signals["Promoter Alignment"]80 result.risk_profile_signal = signals["Risk Profile"]81 result.positive_count = pos82 result.neutral_count = neu83 result.negative_count = neg84 result.overall_verdict = verdict85 86 print(f" ✅ Final Verdict: {verdict}")87 return result88 