jashii78 commited on
Commit
17edfa9
·
verified ·
1 Parent(s): 20e94d9

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +189 -0
app.py ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+
3
+ CUSTOM_CSS = """
4
+ body, .gradio-container {
5
+ background: linear-gradient(180deg, #08101e 0%, #0b1020 100%);
6
+ color: white !important;
7
+ font-family: Inter, Arial, sans-serif;
8
+ }
9
+ .hero {
10
+ padding: 24px;
11
+ border: 1px solid rgba(255,255,255,0.08);
12
+ border-radius: 20px;
13
+ background: rgba(255,255,255,0.03);
14
+ margin-bottom: 16px;
15
+ }
16
+ .metric {
17
+ padding: 16px;
18
+ border-radius: 16px;
19
+ background: rgba(255,255,255,0.03);
20
+ border: 1px solid rgba(255,255,255,0.08);
21
+ }
22
+ """
23
+
24
+ def analyze_thesis(ticker, direction, horizon, position_size, thesis):
25
+ thesis_lower = thesis.lower()
26
+
27
+ thesis_score = 60
28
+ evidence_score = 55
29
+ risk_score = 45
30
+
31
+ if "valuation" in thesis_lower:
32
+ thesis_score += 8
33
+ evidence_score += 8
34
+ if "risk" in thesis_lower:
35
+ thesis_score += 6
36
+ if "earnings" in thesis_lower or "catalyst" in thesis_lower:
37
+ evidence_score += 8
38
+ if "guaranteed" in thesis_lower or "100%" in thesis_lower:
39
+ risk_score += 20
40
+ thesis_score -= 10
41
+
42
+ if position_size > 20:
43
+ risk_score += 15
44
+
45
+ thesis_score = max(0, min(100, thesis_score))
46
+ evidence_score = max(0, min(100, evidence_score))
47
+ risk_score = max(0, min(100, risk_score))
48
+ capital_readiness = max(0, min(100, int(thesis_score * 0.5 + evidence_score * 0.3 + (100 - risk_score) * 0.2)))
49
+
50
+ contradictions = []
51
+ if direction == "Bullish" and "overvalued" in thesis_lower:
52
+ contradictions.append("Bullish view conflicts with 'overvalued' wording.")
53
+ if direction == "Bearish" and "undervalued" in thesis_lower:
54
+ contradictions.append("Bearish view conflicts with 'undervalued' wording.")
55
+ if not contradictions:
56
+ contradictions.append("No major contradiction detected.")
57
+
58
+ missing = []
59
+ if "valuation" not in thesis_lower:
60
+ missing.append("Valuation context missing.")
61
+ if "risk" not in thesis_lower:
62
+ missing.append("Risk definition missing.")
63
+ if "stop loss" not in thesis_lower and "invalidation" not in thesis_lower:
64
+ missing.append("Exit or invalidation plan missing.")
65
+ if "macro" not in thesis_lower:
66
+ missing.append("Macro sensitivity not discussed.")
67
+
68
+ counter_case = []
69
+ if direction == "Bullish":
70
+ counter_case = [
71
+ "Positive expectations may already be priced in.",
72
+ "Weak guidance can break the thesis quickly.",
73
+ "Position sizing may be too aggressive for current evidence."
74
+ ]
75
+ else:
76
+ counter_case = [
77
+ "Negative sentiment may already be priced in.",
78
+ "A strong earnings beat can invalidate the bearish view.",
79
+ "Bear thesis may underestimate business resilience."
80
+ ]
81
+
82
+ memo = f"""
83
+ # BetaTwins Memo
84
+
85
+ **Ticker:** {ticker}
86
+ **Direction:** {direction}
87
+ **Horizon:** {horizon}
88
+ **Position Size:** {position_size}%
89
+
90
+ ## Thesis
91
+ {thesis}
92
+
93
+ ## Scores
94
+ - Thesis Score: {thesis_score}/100
95
+ - Evidence Score: {evidence_score}/100
96
+ - Risk Score: {risk_score}/100
97
+ - Capital Readiness: {capital_readiness}/100
98
+
99
+ ## Contradictions
100
+ - """ + "\n- ".join(contradictions) + """
101
+
102
+ ## Missing Factors
103
+ - """ + "\n- ".join(missing) + """
104
+
105
+ ## Counter-Case
106
+ - """ + "\n- ".join(counter_case)
107
+
108
+ summary = f"""
109
+ ### Executive Summary
110
+ **{ticker}** thesis reviewed with a **{direction.lower()}** stance.
111
+
112
+ - Thesis Score: **{thesis_score}**
113
+ - Evidence Score: **{evidence_score}**
114
+ - Risk Score: **{risk_score}**
115
+ - Capital Readiness: **{capital_readiness}**
116
+ """
117
+
118
+ return (
119
+ f"<div class='metric'><b>Thesis Score</b><br><span style='font-size:32px'>{thesis_score}</span></div>",
120
+ f"<div class='metric'><b>Evidence Score</b><br><span style='font-size:32px'>{evidence_score}</span></div>",
121
+ f"<div class='metric'><b>Risk Score</b><br><span style='font-size:32px'>{risk_score}</span></div>",
122
+ f"<div class='metric'><b>Capital Readiness</b><br><span style='font-size:32px'>{capital_readiness}</span></div>",
123
+ summary,
124
+ "\n".join([f"- {x}" for x in contradictions]),
125
+ "\n".join([f"- {x}" for x in missing]),
126
+ "\n".join([f"- {x}" for x in counter_case]),
127
+ memo
128
+ )
129
+
130
+ with gr.Blocks(css=CUSTOM_CSS, title="BetaTwins AI") as demo:
131
+ gr.HTML("""
132
+ <div class="hero">
133
+ <h1>Stress-test every investment thesis before capital is deployed.</h1>
134
+ <p>BetaTwins helps traders, investors, and fintech teams detect weak reasoning, hidden assumptions, and missing risks before a decision becomes expensive.</p>
135
+ </div>
136
+ """)
137
+
138
+ with gr.Tabs():
139
+ with gr.Tab("Analyzer"):
140
+ with gr.Row():
141
+ with gr.Column(scale=4):
142
+ ticker = gr.Textbox(label="Ticker", placeholder="e.g. NVDA")
143
+ direction = gr.Dropdown(["Bullish", "Bearish", "Neutral"], value="Bullish", label="Direction")
144
+ horizon = gr.Dropdown(["Short-Term", "Swing", "Long-Term"], value="Swing", label="Time Horizon")
145
+ position_size = gr.Slider(1, 100, value=10, step=1, label="Position Size %")
146
+ thesis = gr.Textbox(label="Investment Thesis", lines=10, placeholder="Write your thesis here...")
147
+ run_btn = gr.Button("Run Analysis")
148
+ with gr.Column(scale=6):
149
+ with gr.Row():
150
+ score1 = gr.HTML()
151
+ score2 = gr.HTML()
152
+ score3 = gr.HTML()
153
+ score4 = gr.HTML()
154
+ with gr.Tabs():
155
+ with gr.Tab("Executive Summary"):
156
+ summary = gr.Markdown()
157
+ with gr.Tab("Contradictions"):
158
+ contradictions = gr.Markdown()
159
+ with gr.Tab("Missing Factors"):
160
+ missing = gr.Markdown()
161
+ with gr.Tab("Counter-Case"):
162
+ counter = gr.Markdown()
163
+ with gr.Tab("Memo"):
164
+ memo = gr.Markdown()
165
+
166
+ run_btn.click(
167
+ fn=analyze_thesis,
168
+ inputs=[ticker, direction, horizon, position_size, thesis],
169
+ outputs=[score1, score2, score3, score4, summary, contradictions, missing, counter, memo]
170
+ )
171
+
172
+ with gr.Tab("About"):
173
+ gr.Markdown("""
174
+ ## BetaTwins AI
175
+ AI-powered thesis stress testing for smarter investment decisions.
176
+
177
+ ### What it does
178
+ - Scores thesis quality
179
+ - Detects contradictions
180
+ - Finds missing factors
181
+ - Generates counter-case
182
+ - Builds memo-style output
183
+
184
+ ### Disclaimer
185
+ This tool is for research and decision-support only. It is not financial advice.
186
+ """)
187
+
188
+ if __name__ == "__main__":
189
+ demo.launch()