|
def render_fund_monitoring(transactions_df): |
|
""" |
|
Render the AI-powered fund monitoring page. |
|
|
|
This feature helps startups monitor spending, detect fraudulent transactions, |
|
and maintain investor trust through AI-powered analysis. |
|
""" |
|
st.markdown("<h1 class='main-header'>Investor Fund Monitoring</h1>", unsafe_allow_html=True) |
|
st.markdown("<p class='sub-header'>AI-powered fraud detection and spending analysis</p>", unsafe_allow_html=True) |
|
|
|
|
|
with st.expander("ℹ️ How AI enhances fund monitoring"): |
|
st.markdown(""" |
|
### How AI Powers Your Fund Monitoring |
|
|
|
The fund monitoring system uses AI to help maintain investor trust and optimize spending: |
|
|
|
- **Anomaly Detection**: Our AI models identify unusual transactions that don't match typical startup spending patterns |
|
- **Risk Scoring**: Each transaction is assigned a risk score based on multiple factors like amount, category, vendor, and description |
|
- **Pattern Recognition**: The system identifies potentially concerning spending trends across categories over time |
|
- **Fraud Prevention**: AI algorithms flag transactions that match known patterns of misuse before they become issues |
|
- **Investor-Ready Reporting**: Generate reports that demonstrate responsible financial stewardship to investors |
|
|
|
This helps founders maintain investor trust, prevent misuse of funds, and create transparency in financial operations. |
|
""") |
|
|
|
st.write("Monitor your startup's spending to maintain investor trust and ensure proper fund usage. Our AI algorithms automatically flag suspicious transactions and identify spending patterns.") |
|
|
|
|
|
insights_key = f"fund_monitoring_{date.today().isoformat()}" |
|
if insights_key not in st.session_state.insights_cache: |
|
insights = generate_ai_response(""" |
|
You are a financial fraud detection expert. Provide 2-3 critical spending patterns that investors typically look for when monitoring startup fund usage. |
|
Format as brief bullet points focused on maintaining investor trust. |
|
""", simulate=True) |
|
st.session_state.insights_cache[insights_key] = insights |
|
|
|
with st.expander("🔍 AI Monitoring Insights", expanded=True): |
|
st.markdown("<span class='ai-badge'>AI-Generated Insights</span>", unsafe_allow_html=True) |
|
st.markdown(st.session_state.insights_cache[insights_key]) |
|
|
|
|
|
processed_df = detect_suspicious_transactions(transactions_df) |
|
|
|
|
|
total_transactions = len(processed_df) |
|
suspicious_transactions = processed_df[processed_df['Suspicious']].copy() |
|
suspicious_count = len(suspicious_transactions) |
|
suspicious_amount = suspicious_transactions['Amount'].sum() |
|
total_amount = processed_df['Amount'].sum() |
|
|
|
col1, col2, col3, col4 = st.columns(4) |
|
|
|
with col1: |
|
st.markdown(f""" |
|
<div class='metric-card'> |
|
<p class='metric-label'>Total Transactions</p> |
|
<p class='metric-value'>{total_transactions}</p> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
with col2: |
|
flagged_percent = suspicious_count/total_transactions*100 if total_transactions > 0 else 0 |
|
status = "danger-metric" if flagged_percent > 10 else ("warning-metric" if flagged_percent > 5 else "good-metric") |
|
st.markdown(f""" |
|
<div class='metric-card'> |
|
<p class='metric-label'>Flagged Transactions</p> |
|
<p class='metric-value {status}'>{suspicious_count} ({flagged_percent:.1f}%)</p> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
with col3: |
|
amount_percent = suspicious_amount/total_amount*100 if total_amount > 0 else 0 |
|
status = "danger-metric" if amount_percent > 15 else ("warning-metric" if amount_percent > 7 else "good-metric") |
|
st.markdown(f""" |
|
<div class='metric-card'> |
|
<p class='metric-label'>Flagged Amount</p> |
|
<p class='metric-value {status}'>${suspicious_amount:,.0f} ({amount_percent:.1f}%)</p> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
with col4: |
|
avg_risk = suspicious_transactions['Risk_Score'].mean() if not suspicious_transactions.empty else 0 |
|
status = "danger-metric" if avg_risk > 50 else ("warning-metric" if avg_risk > 30 else "good-metric") |
|
st.markdown(f""" |
|
<div class='metric-card'> |
|
<p class='metric-label'>Average Risk Score</p> |
|
<p class='metric-value {status}'>{avg_risk:.1f}/100</p> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
|
|
tab1, tab2 = st.tabs(["Flagged Transactions", "All Transactions"]) |
|
|
|
with tab1: |
|
if suspicious_count > 0: |
|
|
|
suspicious_view = suspicious_transactions.copy() |
|
|
|
|
|
def colorize_risk(val): |
|
color = "red" if val > 50 else ("orange" if val > 30 else "blue") |
|
return f'background-color: {color}; color: white; font-weight: bold' |
|
|
|
|
|
styled_suspicious = suspicious_view.style.applymap( |
|
lambda x: colorize_risk(x) if x > 0 else '', |
|
subset=['Risk_Score'] |
|
) |
|
|
|
st.dataframe( |
|
suspicious_view[['Date', 'Category', 'Vendor', 'Amount', 'Description', 'Risk_Score', 'Reason']], |
|
use_container_width=True |
|
) |
|
|
|
|
|
fraud_key = f"fraud_{date.today().isoformat()}" |
|
if fraud_key not in st.session_state.insights_cache: |
|
fraud_analysis = get_fraud_analysis(suspicious_transactions) |
|
st.session_state.insights_cache[fraud_key] = fraud_analysis |
|
|
|
st.markdown("<div class='advisor-card'>", unsafe_allow_html=True) |
|
st.markdown("<span class='ai-badge'>AI Fraud Analysis</span>", unsafe_allow_html=True) |
|
st.markdown(f"<p class='advice-text'>{st.session_state.insights_cache[fraud_key]}</p>", unsafe_allow_html=True) |
|
st.markdown("</div>", unsafe_allow_html=True) |
|
|
|
|
|
st.subheader("Recommended Actions") |
|
|
|
col1, col2, col3 = st.columns(3) |
|
with col1: |
|
if st.button("🔍 Investigate All Flagged"): |
|
st.session_state.investigation_started = True |
|
with col2: |
|
if st.button("📝 Generate Investor Report"): |
|
st.session_state.report_generated = True |
|
with col3: |
|
if st.button("✅ Mark Reviewed"): |
|
st.session_state.marked_reviewed = True |
|
|
|
|
|
if 'investigation_started' in st.session_state and st.session_state.investigation_started: |
|
st.success("Investigation initiated for all flagged transactions. Your financial team will be notified.") |
|
|
|
if 'report_generated' in st.session_state and st.session_state.report_generated: |
|
st.success("Investor report generated and ready for review before sending.") |
|
|
|
if 'marked_reviewed' in st.session_state and st.session_state.marked_reviewed: |
|
st.success("All transactions marked as reviewed. Status will be updated in the system.") |
|
else: |
|
st.success("No suspicious transactions detected by our AI system. Your spending appears to be normal for a startup at your stage.") |
|
|
|
with tab2: |
|
st.dataframe(processed_df[['Date', 'Category', 'Vendor', 'Amount', 'Description', 'Suspicious', 'Risk_Score']], |
|
use_container_width=True) |
|
|
|
|
|
st.subheader("Spending Pattern Analysis") |
|
|
|
|
|
category_spending = processed_df.groupby('Category')['Amount'].sum().reset_index() |
|
|
|
col1, col2 = st.columns(2) |
|
|
|
with col1: |
|
fig = px.bar(category_spending, x='Category', y='Amount', |
|
title="Spending by Category", |
|
labels={'Amount': 'Total Spent ($)'}, |
|
color='Amount', |
|
color_continuous_scale='Blues') |
|
fig.update_layout( |
|
height=400, |
|
plot_bgcolor='rgba(240,247,255,0.8)', |
|
xaxis_title="Category", |
|
yaxis_title="Amount Spent ($)", |
|
font=dict(family="Arial, sans-serif", size=12), |
|
margin=dict(l=20, r=20, t=40, b=20), |
|
) |
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
with col2: |
|
|
|
spending_key = f"spending_pattern_{date.today().isoformat()}" |
|
if spending_key not in st.session_state.insights_cache: |
|
spending_pattern_analysis = generate_ai_response(""" |
|
You are a startup spending analyst. Review the spending patterns and provide 3 key insights about: |
|
1. Categories that appear to have unusually high spending |
|
2. Potential areas where spending could be optimized |
|
3. Changes in spending patterns that investors might find concerning |
|
|
|
Format as concise, actionable bullet points. |
|
""", simulate=True) |
|
st.session_state.insights_cache[spending_key] = spending_pattern_analysis |
|
|
|
st.markdown("<div class='insight-card'>", unsafe_allow_html=True) |
|
st.markdown("<span class='ai-badge'>AI Spending Analysis</span>", unsafe_allow_html=True) |
|
st.markdown(st.session_state.insights_cache[spending_key]) |
|
st.markdown("</div>", unsafe_allow_html=True) |
|
|
|
|
|
processed_df['Date'] = pd.to_datetime(processed_df['Date']) |
|
processed_df['Week'] = processed_df['Date'].dt.isocalendar().week |
|
weekly_spending = processed_df.groupby(['Week', 'Category'])['Amount'].sum().reset_index() |
|
|
|
fig = px.line(weekly_spending, x='Week', y='Amount', color='Category', |
|
title="Weekly Spending Trends", |
|
labels={'Amount': 'Amount Spent ($)'}, |
|
color_discrete_sequence=px.colors.qualitative.Bold) |
|
fig.update_layout( |
|
height=400, |
|
plot_bgcolor='rgba(240,247,255,0.8)', |
|
xaxis_title="Week", |
|
yaxis_title="Amount Spent ($)", |
|
font=dict(family="Arial, sans-serif", size=12), |
|
margin=dict(l=20, r=20, t=40, b=20), |
|
) |
|
st.plotly_chart(fig, use_container_width=True) |
|
|
|
|
|
st.subheader("AI-Recommended Spending Controls") |
|
|
|
|
|
controls_key = f"spending_controls_{date.today().isoformat()}" |
|
if controls_key not in st.session_state.insights_cache: |
|
controls_recommendations = generate_ai_response(""" |
|
You are a financial controls expert for startups. Based on the spending patterns and suspicious transactions, |
|
recommend 3-4 specific spending controls that the startup should implement to prevent misuse of funds. |
|
|
|
For each control, provide: |
|
1. A clear policy statement |
|
2. Implementation steps |
|
3. Expected impact |
|
|
|
Format as concise, actionable recommendations. |
|
""", simulate=True) |
|
st.session_state.insights_cache[controls_key] = controls_recommendations |
|
|
|
st.markdown("<div class='advisor-card'>", unsafe_allow_html=True) |
|
st.markdown("<span class='ai-badge'>AI Control Recommendations</span>", unsafe_allow_html=True) |
|
st.markdown(f"<p class='advice-text'>{st.session_state.insights_cache[controls_key]}</p>", unsafe_allow_html=True) |
|
st.markdown("</div>", unsafe_allow_html=True) |
|
|
|
|
|
st.info("📅 Need help implementing financial controls? [Book a session](#book-a-session) with our AI financial advisor.") |
|
|
|
def detect_suspicious_transactions(transactions_df): |
|
"""AI-enhanced suspicious transaction detection.""" |
|
df = transactions_df.copy() |
|
|
|
|
|
category_thresholds = { |
|
"Travel": 3000, |
|
"Marketing": 10000, |
|
"Office": 7000, |
|
"Software": 6000, |
|
"Consulting": 5000, |
|
"Legal": 6000 |
|
} |
|
|
|
|
|
suspicious_terms = ['luxury', 'cruise', 'premium', 'personal', 'gift'] |
|
|
|
|
|
df['Suspicious'] = False |
|
df['Reason'] = "" |
|
df['Risk_Score'] = 0 |
|
|
|
|
|
for idx, row in df.iterrows(): |
|
reasons = [] |
|
risk_score = 0 |
|
|
|
|
|
if row['Category'] in category_thresholds: |
|
if row['Amount'] > category_thresholds[row['Category']]: |
|
reasons.append(f"Amount exceeds typical spending for {row['Category']}") |
|
risk_score += 30 |
|
|
|
|
|
excess_percentage = (row['Amount'] - category_thresholds[row['Category']]) / category_thresholds[row['Category']] * 100 |
|
if excess_percentage > 100: |
|
risk_score += 20 |
|
|
|
|
|
if any(term in str(row['Vendor']).lower() for term in suspicious_terms): |
|
reasons.append(f"Vendor name contains suspicious term") |
|
risk_score += 25 |
|
|
|
if any(term in str(row['Description']).lower() for term in suspicious_terms): |
|
reasons.append(f"Description contains suspicious term") |
|
risk_score += 20 |
|
|
|
|
|
if row['Amount'] % 1000 == 0 and row['Amount'] > 3000: |
|
reasons.append(f"Suspiciously round amount") |
|
risk_score += 15 |
|
|
|
|
|
if risk_score >= 30: |
|
df.at[idx, 'Suspicious'] = True |
|
df.at[idx, 'Reason'] = "; ".join(reasons) |
|
df.at[idx, 'Risk_Score'] = risk_score |
|
|
|
|
|
df = df.sort_values(by='Risk_Score', ascending=False) |
|
|
|
return df |
|
|
|
def get_fraud_analysis(transactions_df): |
|
"""Get AI analysis of potentially fraudulent transactions.""" |
|
suspicious_df = transactions_df[transactions_df['Suspicious']].copy() |
|
|
|
if len(suspicious_df) == 0: |
|
return "No suspicious transactions detected." |
|
|
|
transactions_text = suspicious_df[['Date', 'Category', 'Vendor', 'Amount', 'Description', 'Risk_Score']].to_string(index=False) |
|
|
|
prompt = f""" |
|
You are a financial forensics expert specializing in startup spending oversight. |
|
Review these flagged transactions: |
|
|
|
{transactions_text} |
|
|
|
Provide a detailed analysis: |
|
1. Identify the most concerning transactions and explain why |
|
2. Calculate the total financial impact of these suspicious transactions |
|
3. Identify spending patterns or potential policy violations |
|
4. Recommend specific actions the startup should take immediately |
|
5. Suggest controls to prevent similar issues in the future |
|
|
|
Be specific about which transactions are most concerning and why investors would have questions. |
|
""" |
|
|
|
return generate_ai_response(prompt) |
|
|