Delete decision-simulator.py
Browse files- decision-simulator.py +0 -321
decision-simulator.py
DELETED
@@ -1,321 +0,0 @@
|
|
1 |
-
def render_decision_simulator(startup_data):
|
2 |
-
"""
|
3 |
-
Render the AI-powered decision simulator page.
|
4 |
-
|
5 |
-
This feature helps startup founders test the financial impact of business
|
6 |
-
decisions before implementing them, using AI to analyze risks and benefits.
|
7 |
-
"""
|
8 |
-
st.markdown("<h1 class='main-header'>Decision Simulator</h1>", unsafe_allow_html=True)
|
9 |
-
st.markdown("<p class='sub-header'>AI-powered analysis of business decisions</p>", unsafe_allow_html=True)
|
10 |
-
|
11 |
-
# How AI helps with decision-making
|
12 |
-
with st.expander("ℹ️ How AI enhances your decision-making"):
|
13 |
-
st.markdown("""
|
14 |
-
### How AI Powers Your Decision Simulator
|
15 |
-
|
16 |
-
The decision simulator uses AI to help you make better strategic decisions:
|
17 |
-
|
18 |
-
- **Scenario Analysis**: Our AI model simulates multiple financial scenarios based on your input variables
|
19 |
-
- **Risk Assessment**: The system automatically evaluates risk levels based on your cash runway and growth metrics
|
20 |
-
- **Return Prediction**: AI algorithms predict potential returns on investments like hiring or marketing
|
21 |
-
- **Opportunity Cost Analysis**: The model compares different allocations of capital to maximize growth
|
22 |
-
- **Personalized Recommendations**: Based on your specific situation, the AI provides tailored alternatives
|
23 |
-
|
24 |
-
This helps founders make data-driven decisions with less guesswork, avoid costly mistakes, and optimize resource allocation.
|
25 |
-
""")
|
26 |
-
|
27 |
-
st.write("Test the financial impact of key business decisions before implementing them. Our AI advisor will analyze the risks and benefits.")
|
28 |
-
|
29 |
-
# Quick decision templates
|
30 |
-
st.subheader("Common Scenarios")
|
31 |
-
|
32 |
-
decision_templates = {
|
33 |
-
"Hiring Engineering Team": {
|
34 |
-
"description": "Evaluate the impact of growing your engineering team",
|
35 |
-
"new_hires": 3,
|
36 |
-
"new_marketing": 0,
|
37 |
-
"other_expenses": 2000,
|
38 |
-
"growth_impact": 0.02,
|
39 |
-
"question": "We're considering hiring 3 more engineers to accelerate product development. How will this affect our runway and what growth impact should we expect to justify this investment?"
|
40 |
-
},
|
41 |
-
"Marketing Expansion": {
|
42 |
-
"description": "Test increasing your marketing budget",
|
43 |
-
"new_hires": 0,
|
44 |
-
"new_marketing": 15000,
|
45 |
-
"other_expenses": 0,
|
46 |
-
"growth_impact": 0.04,
|
47 |
-
"question": "We want to increase our marketing spend by $15K/month to drive growth. What growth rate would we need to achieve to make this financially viable?"
|
48 |
-
},
|
49 |
-
"Office Expansion": {
|
50 |
-
"description": "Analyze the cost of moving to a larger office",
|
51 |
-
"new_hires": 0,
|
52 |
-
"new_marketing": 0,
|
53 |
-
"other_expenses": 8000,
|
54 |
-
"growth_impact": 0.01,
|
55 |
-
"question": "We're considering moving to a larger office space that would add $8K/month to our expenses. Is this justified at our current stage?"
|
56 |
-
},
|
57 |
-
"Custom Scenario": {
|
58 |
-
"description": "Create your own custom scenario",
|
59 |
-
"new_hires": 0,
|
60 |
-
"new_marketing": 0,
|
61 |
-
"other_expenses": 0,
|
62 |
-
"growth_impact": 0.0,
|
63 |
-
"question": ""
|
64 |
-
}
|
65 |
-
}
|
66 |
-
|
67 |
-
# Template selection
|
68 |
-
template_cols = st.columns(4)
|
69 |
-
selected_template = None
|
70 |
-
|
71 |
-
for i, (template_name, template) in enumerate(decision_templates.items()):
|
72 |
-
with template_cols[i]:
|
73 |
-
if st.button(f"{template_name}\n{template['description']}", key=f"template_{i}"):
|
74 |
-
selected_template = template_name
|
75 |
-
|
76 |
-
# Initialize form values based on selected template
|
77 |
-
if selected_template and selected_template != "Custom Scenario":
|
78 |
-
new_hires = decision_templates[selected_template]["new_hires"]
|
79 |
-
new_marketing = decision_templates[selected_template]["new_marketing"]
|
80 |
-
other_expenses = decision_templates[selected_template]["other_expenses"]
|
81 |
-
growth_impact = decision_templates[selected_template]["growth_impact"]
|
82 |
-
question = decision_templates[selected_template]["question"]
|
83 |
-
else:
|
84 |
-
new_hires = 0
|
85 |
-
new_marketing = 0
|
86 |
-
other_expenses = 0
|
87 |
-
growth_impact = 0.0
|
88 |
-
question = ""
|
89 |
-
|
90 |
-
# Decision input form
|
91 |
-
with st.form("decision_form"):
|
92 |
-
st.subheader("Scenario Parameters")
|
93 |
-
|
94 |
-
col1, col2 = st.columns(2)
|
95 |
-
|
96 |
-
with col1:
|
97 |
-
new_hires = st.number_input("New Engineering Hires", min_value=0, max_value=10, value=new_hires,
|
98 |
-
help=f"Each engineer costs ${ENGINEER_SALARY:,} per month")
|
99 |
-
st.caption(f"Monthly Cost: ${new_hires * ENGINEER_SALARY:,}")
|
100 |
-
|
101 |
-
new_marketing = st.number_input("Additional Monthly Marketing Budget",
|
102 |
-
min_value=0, max_value=50000, value=new_marketing, step=1000,
|
103 |
-
help="Additional marketing spend per month")
|
104 |
-
|
105 |
-
with col2:
|
106 |
-
other_expenses = st.number_input("Other Additional Monthly Expenses",
|
107 |
-
min_value=0, max_value=50000, value=other_expenses, step=1000,
|
108 |
-
help="Any other additional monthly expenses")
|
109 |
-
|
110 |
-
growth_impact = st.slider("Estimated Impact on Monthly Growth Rate",
|
111 |
-
min_value=0.0, max_value=0.10, value=growth_impact, step=0.01,
|
112 |
-
format="%.2f",
|
113 |
-
help="Estimated increase in monthly growth rate due to these investments")
|
114 |
-
st.caption(f"New Growth Rate: {(startup_data['growth_rate'] + growth_impact) * 100:.1f}% (current: {startup_data['growth_rate'] * 100:.1f}%)")
|
115 |
-
|
116 |
-
question = st.text_area("Describe your decision scenario",
|
117 |
-
value=question,
|
118 |
-
height=100,
|
119 |
-
placeholder="E.g., We're considering hiring two more engineers and increasing our marketing budget...")
|
120 |
-
|
121 |
-
decision_summary = f"""
|
122 |
-
- {new_hires} new engineers: ${new_hires * ENGINEER_SALARY:,}/month
|
123 |
-
- Marketing increase: ${new_marketing:,}/month
|
124 |
-
- Other expenses: ${other_expenses:,}/month
|
125 |
-
- Total additional burn: ${new_hires * ENGINEER_SALARY + new_marketing + other_expenses:,}/month
|
126 |
-
- Growth impact: +{growth_impact * 100:.1f}% monthly growth
|
127 |
-
"""
|
128 |
-
|
129 |
-
st.markdown(f"**Decision Summary:**\n{decision_summary}")
|
130 |
-
|
131 |
-
submitted = st.form_submit_button("Simulate Decision")
|
132 |
-
|
133 |
-
if submitted:
|
134 |
-
# Calculate current and new runway
|
135 |
-
current_runway, new_runway, current_df, new_df = simulate_decision(
|
136 |
-
startup_data['cash'],
|
137 |
-
startup_data['burn_rate'],
|
138 |
-
startup_data['revenue'],
|
139 |
-
startup_data['growth_rate'],
|
140 |
-
other_expenses,
|
141 |
-
new_hires,
|
142 |
-
new_marketing,
|
143 |
-
growth_impact
|
144 |
-
)
|
145 |
-
|
146 |
-
# Display results
|
147 |
-
st.markdown("<h3>Decision Impact Analysis</h3>", unsafe_allow_html=True)
|
148 |
-
|
149 |
-
# Summary metrics
|
150 |
-
col1, col2, col3 = st.columns(3)
|
151 |
-
|
152 |
-
with col1:
|
153 |
-
st.metric("Current Runway", f"{current_runway} months")
|
154 |
-
with col2:
|
155 |
-
runway_change = new_runway - current_runway
|
156 |
-
st.metric("New Runway", f"{new_runway} months",
|
157 |
-
delta=f"{runway_change} months",
|
158 |
-
delta_color="off" if runway_change == 0 else ("normal" if runway_change > 0 else "inverse"))
|
159 |
-
with col3:
|
160 |
-
new_burn = startup_data['burn_rate'] + other_expenses + (new_hires * ENGINEER_SALARY) + new_marketing
|
161 |
-
burn_change = new_burn - startup_data['burn_rate']
|
162 |
-
burn_percentage = burn_change / startup_data['burn_rate'] * 100
|
163 |
-
st.metric("New Monthly Burn", f"${new_burn:,}",
|
164 |
-
delta=f"${burn_change:,} ({burn_percentage:.1f}%)",
|
165 |
-
delta_color="inverse")
|
166 |
-
|
167 |
-
# Cash projection comparison
|
168 |
-
st.subheader("Cash Projection Comparison")
|
169 |
-
|
170 |
-
# Combine dataframes for comparison
|
171 |
-
current_df['Scenario'] = 'Current'
|
172 |
-
new_df['Scenario'] = 'After Decision'
|
173 |
-
|
174 |
-
combined_df = pd.concat([current_df, new_df])
|
175 |
-
combined_df = combined_df.reset_index()
|
176 |
-
combined_df = combined_df.rename(columns={'index': 'Date'})
|
177 |
-
|
178 |
-
# Plot comparison
|
179 |
-
fig = px.line(combined_df, x='Date', y='Cumulative_Cash', color='Scenario',
|
180 |
-
title="Cash Runway Comparison",
|
181 |
-
labels={'Cumulative_Cash': 'Remaining Cash'},
|
182 |
-
color_discrete_sequence=['#4c78a8', '#f58518'])
|
183 |
-
|
184 |
-
fig.add_hline(y=0, line_dash="dash", line_color="red", annotation_text="Out of Cash")
|
185 |
-
|
186 |
-
fig.update_layout(
|
187 |
-
height=400,
|
188 |
-
plot_bgcolor='rgba(240,247,255,0.8)',
|
189 |
-
xaxis_title="Date",
|
190 |
-
yaxis_title="Cash Balance ($)",
|
191 |
-
font=dict(family="Arial, sans-serif", size=12),
|
192 |
-
margin=dict(l=20, r=20, t=40, b=20),
|
193 |
-
)
|
194 |
-
|
195 |
-
st.plotly_chart(fig, use_container_width=True)
|
196 |
-
|
197 |
-
# Get AI analysis
|
198 |
-
if question:
|
199 |
-
decision_params = {
|
200 |
-
"new_hires": new_hires,
|
201 |
-
"new_marketing": new_marketing,
|
202 |
-
"other_expenses": other_expenses,
|
203 |
-
"growth_impact": growth_impact
|
204 |
-
}
|
205 |
-
|
206 |
-
analysis = get_decision_analysis(question, startup_data, decision_params)
|
207 |
-
|
208 |
-
st.markdown("<div class='advisor-card'>", unsafe_allow_html=True)
|
209 |
-
st.markdown("<span class='ai-badge'>AI Decision Analysis</span>", unsafe_allow_html=True)
|
210 |
-
st.markdown(f"<p class='advice-text'>{analysis}</p>", unsafe_allow_html=True)
|
211 |
-
st.markdown("</div>", unsafe_allow_html=True)
|
212 |
-
|
213 |
-
# Break down impacts of each component
|
214 |
-
st.subheader("Component Impact Analysis")
|
215 |
-
|
216 |
-
# Calculate the impact of each component in isolation
|
217 |
-
_, hiring_runway, _, _ = simulate_decision(
|
218 |
-
startup_data['cash'],
|
219 |
-
startup_data['burn_rate'],
|
220 |
-
startup_data['revenue'],
|
221 |
-
startup_data['growth_rate'],
|
222 |
-
0,
|
223 |
-
new_hires,
|
224 |
-
0,
|
225 |
-
0
|
226 |
-
)
|
227 |
-
|
228 |
-
_, marketing_runway, _, _ = simulate_decision(
|
229 |
-
startup_data['cash'],
|
230 |
-
startup_data['burn_rate'],
|
231 |
-
startup_data['revenue'],
|
232 |
-
startup_data['growth_rate'],
|
233 |
-
0,
|
234 |
-
0,
|
235 |
-
new_marketing,
|
236 |
-
growth_impact
|
237 |
-
)
|
238 |
-
|
239 |
-
_, expenses_runway, _, _ = simulate_decision(
|
240 |
-
startup_data['cash'],
|
241 |
-
startup_data['burn_rate'],
|
242 |
-
startup_data['revenue'],
|
243 |
-
startup_data['growth_rate'],
|
244 |
-
other_expenses,
|
245 |
-
0,
|
246 |
-
0,
|
247 |
-
0
|
248 |
-
)
|
249 |
-
|
250 |
-
component_data = {
|
251 |
-
"Component": ["Engineering Hires", "Marketing Increase", "Other Expenses", "Combined Impact"],
|
252 |
-
"Runway Impact (months)": [
|
253 |
-
hiring_runway - current_runway,
|
254 |
-
marketing_runway - current_runway,
|
255 |
-
expenses_runway - current_runway,
|
256 |
-
new_runway - current_runway
|
257 |
-
]
|
258 |
-
}
|
259 |
-
|
260 |
-
component_df = pd.DataFrame(component_data)
|
261 |
-
|
262 |
-
fig = px.bar(component_df, x='Component', y='Runway Impact (months)',
|
263 |
-
title="Impact of Each Component on Runway",
|
264 |
-
color='Runway Impact (months)',
|
265 |
-
color_continuous_scale=['#dc3545', '#ffc107', '#28a745'],
|
266 |
-
text='Runway Impact (months)')
|
267 |
-
|
268 |
-
fig.update_layout(
|
269 |
-
height=400,
|
270 |
-
plot_bgcolor='rgba(240,247,255,0.8)',
|
271 |
-
font=dict(family="Arial, sans-serif", size=12),
|
272 |
-
margin=dict(l=20, r=20, t=40, b=20),
|
273 |
-
)
|
274 |
-
|
275 |
-
fig.update_traces(texttemplate='%{text:.1f}', textposition='outside')
|
276 |
-
st.plotly_chart(fig, use_container_width=True)
|
277 |
-
|
278 |
-
# Risk assessment
|
279 |
-
risk_level = "High" if new_runway < 3 else ("Medium" if new_runway < 6 else "Low")
|
280 |
-
risk_color = "danger-metric" if risk_level == "High" else ("warning-metric" if risk_level == "Medium" else "good-metric")
|
281 |
-
|
282 |
-
st.markdown(f"""
|
283 |
-
<div class='metric-card'>
|
284 |
-
<p class='metric-label'>Risk Assessment</p>
|
285 |
-
<p class='metric-value {risk_color}'>{risk_level} Risk Decision</p>
|
286 |
-
<p>This decision would give you {new_runway} months of runway.</p>
|
287 |
-
</div>
|
288 |
-
""", unsafe_allow_html=True)
|
289 |
-
|
290 |
-
# Recommendations
|
291 |
-
st.info("💡 **Want personalized guidance on this decision?** [Book a session](#book-a-session) with our AI financial advisor for detailed analysis.")
|
292 |
-
|
293 |
-
def get_decision_analysis(question, financial_data, decision_params):
|
294 |
-
"""Get AI analysis for a specific business decision."""
|
295 |
-
prompt = f"""
|
296 |
-
You are a financial advisor for startups. A founder asks:
|
297 |
-
"{question}"
|
298 |
-
|
299 |
-
Here's their current financial situation:
|
300 |
-
- Current cash: ${financial_data['cash']}
|
301 |
-
- Monthly burn rate: ${financial_data['burn_rate']}
|
302 |
-
- Monthly revenue: ${financial_data['revenue']}
|
303 |
-
- Monthly growth rate: {financial_data['growth_rate'] * 100}%
|
304 |
-
|
305 |
-
They're considering these changes:
|
306 |
-
- Adding {decision_params['new_hires']} new engineers (${ENGINEER_SALARY}/month each)
|
307 |
-
- Increasing marketing budget by ${decision_params['new_marketing']}/month
|
308 |
-
- Adding ${decision_params['other_expenses']}/month in other expenses
|
309 |
-
- Expecting {decision_params['growth_impact'] * 100}% additional monthly growth
|
310 |
-
|
311 |
-
Analyze this decision thoroughly:
|
312 |
-
1. Quantify the impact on runway (exact calculation)
|
313 |
-
2. Assess the risk level (low, medium, high)
|
314 |
-
3. Compare the ROI potential
|
315 |
-
4. Provide 3 specific recommendations or alternatives
|
316 |
-
5. Suggest timeline and milestones for implementation if approved
|
317 |
-
|
318 |
-
Be direct and specific with numbers and timeframes.
|
319 |
-
"""
|
320 |
-
|
321 |
-
return generate_ai_response(prompt)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|