feat: 初始提交 - 科创企业特有风险的识别与管理 (数智风控系统)
This commit is contained in:
@@ -0,0 +1,304 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
🛡️ 科创企业智能风控与核保系统 - 首页 / 风控大屏入口
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
import streamlit as st
|
||||
import pandas as pd
|
||||
import plotly.express as px
|
||||
import plotly.graph_objects as go
|
||||
|
||||
# 确保项目根目录在 Python 路径中
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from config import PAGE_TITLE, PAGE_ICON, LAYOUT
|
||||
from collectors.financial_collector import get_all_companies
|
||||
from risk_engine.risk_scorer import calculate_six_dimension_scores, get_risk_level
|
||||
|
||||
# ============================================================
|
||||
# 页面配置
|
||||
# ============================================================
|
||||
st.set_page_config(
|
||||
page_title=PAGE_TITLE,
|
||||
page_icon=PAGE_ICON,
|
||||
layout=LAYOUT,
|
||||
initial_sidebar_state="expanded",
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# 自定义样式
|
||||
# ============================================================
|
||||
st.markdown("""
|
||||
<style>
|
||||
/* 主标题渐变 */
|
||||
.main-title {
|
||||
background: linear-gradient(120deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
|
||||
padding: 30px;
|
||||
border-radius: 15px;
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
box-shadow: 0 4px 15px rgba(0,0,0,0.3);
|
||||
}
|
||||
.main-title h1 {
|
||||
color: #e94560;
|
||||
font-size: 2.2em;
|
||||
margin: 0;
|
||||
}
|
||||
.main-title p {
|
||||
color: #a8a8b3;
|
||||
font-size: 1.1em;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* 统计卡片 */
|
||||
.stat-card {
|
||||
background: linear-gradient(135deg, #1a1a2e, #16213e);
|
||||
padding: 20px;
|
||||
border-radius: 12px;
|
||||
text-align: center;
|
||||
border: 1px solid #2a2a4a;
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
.stat-card:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
.stat-card .number {
|
||||
font-size: 2.5em;
|
||||
font-weight: bold;
|
||||
color: #e94560;
|
||||
}
|
||||
.stat-card .label {
|
||||
color: #a8a8b3;
|
||||
font-size: 0.95em;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
/* 企业卡片 */
|
||||
.company-card {
|
||||
background: #16213e;
|
||||
padding: 15px;
|
||||
border-radius: 10px;
|
||||
margin: 8px 0;
|
||||
border-left: 4px solid;
|
||||
}
|
||||
|
||||
/* 侧边栏 */
|
||||
[data-testid="stSidebar"] {
|
||||
background: linear-gradient(180deg, #1a1a2e 0%, #0f0f23 100%);
|
||||
}
|
||||
</style>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
from utils.session_helper import render_sidebar_global_company_selector
|
||||
|
||||
# ============================================================
|
||||
# 侧边栏
|
||||
# ============================================================
|
||||
with st.sidebar:
|
||||
render_sidebar_global_company_selector()
|
||||
st.markdown("---")
|
||||
st.markdown("### 🛡️ 系统导航")
|
||||
st.markdown("---")
|
||||
st.markdown("""
|
||||
**功能模块**
|
||||
- 🏠 系统首页
|
||||
- 📊 企业风险概览
|
||||
- 🕸️ 供应链知识图谱
|
||||
- ⚖️ 多智能体辩论诊断
|
||||
- 💰 动态定价与核保
|
||||
""")
|
||||
st.markdown("---")
|
||||
st.markdown("""
|
||||
**技术栈**
|
||||
- 🤖 DeepSeek API (LLM)
|
||||
- 🕸️ NetworkX (知识图谱)
|
||||
- 📊 Plotly (可视化)
|
||||
- 🔧 Streamlit (Web框架)
|
||||
""")
|
||||
st.markdown("---")
|
||||
st.caption("中国平安 × 挑战杯 · 科创风控原型")
|
||||
|
||||
# ============================================================
|
||||
# 主页内容
|
||||
# ============================================================
|
||||
|
||||
# 标题
|
||||
st.markdown("""
|
||||
<div class="main-title">
|
||||
<h1>🛡️ 科创企业智能风控与核保系统</h1>
|
||||
<p>基于多智能体辩论 × 知识图谱 × 动态定价的全链条风控平台</p>
|
||||
<p style="font-size: 0.85em; color: #666;">中国青基会平安励志计划 · XH-202626 · 科创企业特有风险的识别与管理</p>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
# 加载企业数据
|
||||
companies = get_all_companies()
|
||||
|
||||
# ============================================================
|
||||
# 统计概览卡片
|
||||
# ============================================================
|
||||
st.markdown("### 📊 系统概览")
|
||||
|
||||
# 计算所有企业的风险评分
|
||||
risk_data = []
|
||||
for comp in companies:
|
||||
scores = calculate_six_dimension_scores(comp)
|
||||
risk_data.append({
|
||||
"company": comp["short_name"],
|
||||
"stock_code": comp["stock_code"],
|
||||
"industry": comp["industry"],
|
||||
"sector": comp["sector"],
|
||||
"comprehensive_score": scores["comprehensive_score"],
|
||||
"risk_level": scores["risk_level"]["level"],
|
||||
**scores["scores"],
|
||||
})
|
||||
|
||||
df = pd.DataFrame(risk_data)
|
||||
|
||||
# 统计卡片
|
||||
col1, col2, col3, col4, col5 = st.columns(5)
|
||||
|
||||
with col1:
|
||||
st.markdown(f"""
|
||||
<div class="stat-card">
|
||||
<div class="number">{len(companies)}</div>
|
||||
<div class="label">监控企业总数</div>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
with col2:
|
||||
high_risk = len(df[df["comprehensive_score"] >= 70])
|
||||
st.markdown(f"""
|
||||
<div class="stat-card">
|
||||
<div class="number" style="color: #F44336;">{high_risk}</div>
|
||||
<div class="label">⚠️ 高风险企业</div>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
with col3:
|
||||
med_risk = len(df[(df["comprehensive_score"] >= 40) & (df["comprehensive_score"] < 70)])
|
||||
st.markdown(f"""
|
||||
<div class="stat-card">
|
||||
<div class="number" style="color: #FF9800;">{med_risk}</div>
|
||||
<div class="label">🟡 中风险企业</div>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
with col4:
|
||||
low_risk = len(df[df["comprehensive_score"] < 40])
|
||||
st.markdown(f"""
|
||||
<div class="stat-card">
|
||||
<div class="number" style="color: #4CAF50;">{low_risk}</div>
|
||||
<div class="label">🟢 低风险企业</div>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
with col5:
|
||||
sanctioned = len([c for c in companies if "被列入" in c.get("compliance", {}).get("entity_list_status", "")])
|
||||
st.markdown(f"""
|
||||
<div class="stat-card">
|
||||
<div class="number" style="color: #B71C1C;">{sanctioned}</div>
|
||||
<div class="label">⛔ 受制裁企业</div>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
st.markdown("<br>", unsafe_allow_html=True)
|
||||
|
||||
# ============================================================
|
||||
# 风险分布图
|
||||
# ============================================================
|
||||
col_left, col_right = st.columns([3, 2])
|
||||
|
||||
with col_left:
|
||||
st.markdown("#### 🎯 企业综合风险评分分布")
|
||||
|
||||
# 水平柱状图,按风险排序
|
||||
df_sorted = df.sort_values("comprehensive_score", ascending=True)
|
||||
|
||||
colors = []
|
||||
for score in df_sorted["comprehensive_score"]:
|
||||
if score >= 70:
|
||||
colors.append("#F44336")
|
||||
elif score >= 50:
|
||||
colors.append("#FF9800")
|
||||
elif score >= 30:
|
||||
colors.append("#FFC107")
|
||||
else:
|
||||
colors.append("#4CAF50")
|
||||
|
||||
fig = go.Figure(go.Bar(
|
||||
x=df_sorted["comprehensive_score"],
|
||||
y=df_sorted["company"],
|
||||
orientation="h",
|
||||
marker_color=colors,
|
||||
text=df_sorted["comprehensive_score"],
|
||||
textposition="outside",
|
||||
))
|
||||
fig.update_layout(
|
||||
height=400,
|
||||
margin=dict(l=0, r=30, t=10, b=10),
|
||||
plot_bgcolor="rgba(0,0,0,0)",
|
||||
paper_bgcolor="rgba(0,0,0,0)",
|
||||
font=dict(color="white"),
|
||||
xaxis=dict(
|
||||
title="综合风险评分",
|
||||
range=[0, 105],
|
||||
gridcolor="rgba(255,255,255,0.1)",
|
||||
),
|
||||
yaxis=dict(gridcolor="rgba(255,255,255,0.1)"),
|
||||
)
|
||||
# 添加阈值线
|
||||
fig.add_vline(x=70, line_dash="dash", line_color="#F44336",
|
||||
annotation_text="高风险线(70)", annotation_position="top right")
|
||||
fig.add_vline(x=40, line_dash="dash", line_color="#FF9800",
|
||||
annotation_text="中风险线(40)", annotation_position="top right")
|
||||
st.plotly_chart(fig, use_container_width=True)
|
||||
|
||||
with col_right:
|
||||
st.markdown("#### 🏷️ 行业风险热力")
|
||||
|
||||
# 按行业汇总
|
||||
sector_risk = df.groupby("sector")["comprehensive_score"].mean().reset_index()
|
||||
sector_risk.columns = ["行业", "平均风险"]
|
||||
sector_risk = sector_risk.sort_values("平均风险", ascending=False)
|
||||
|
||||
fig2 = px.bar(
|
||||
sector_risk, x="行业", y="平均风险",
|
||||
color="平均风险",
|
||||
color_continuous_scale=["#4CAF50", "#FFC107", "#F44336"],
|
||||
range_color=[0, 100],
|
||||
)
|
||||
fig2.update_layout(
|
||||
height=400,
|
||||
margin=dict(l=0, r=0, t=10, b=10),
|
||||
plot_bgcolor="rgba(0,0,0,0)",
|
||||
paper_bgcolor="rgba(0,0,0,0)",
|
||||
font=dict(color="white"),
|
||||
showlegend=False,
|
||||
coloraxis_showscale=False,
|
||||
)
|
||||
st.plotly_chart(fig2, use_container_width=True)
|
||||
|
||||
# ============================================================
|
||||
# 企业列表
|
||||
# ============================================================
|
||||
st.markdown("### 📋 企业风险速览")
|
||||
|
||||
# 格式化数据表格
|
||||
display_df = df[["company", "stock_code", "industry", "comprehensive_score", "risk_level"]].copy()
|
||||
display_df.columns = ["企业名称", "股票代码", "行业", "综合风险评分", "风险等级"]
|
||||
|
||||
st.dataframe(display_df, use_container_width=True, height=400)
|
||||
|
||||
# ============================================================
|
||||
# 底部信息
|
||||
# ============================================================
|
||||
st.markdown("---")
|
||||
st.markdown("""
|
||||
<div style="text-align: center; color: #666; font-size: 0.85em;">
|
||||
<p>🛡️ 科创企业智能风控与核保系统 v1.0</p>
|
||||
<p>技术架构: Multi-Agent 交叉验证 × 供应链知识图谱 × 动态保险定价</p>
|
||||
<p>数据来源: 科创板公开年报 · BIS 实体清单 · 网信办算法备案公示</p>
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
Reference in New Issue
Block a user