基于python实现的便利店投资分析财务建模评估

基于python实现的便利店投资分析财务建模评估,不仅计算了基础的盈亏,还引入了**现代投资组合理论(Modern Portfolio Theory)**中的关键指标(如夏普比率、索提诺比率),将传统的实体店铺投资分析提升到了量化金融的维度。

实现了一个基于 Python (PyQt5, Matplotlib, NumPy) 的桌面应用程序,专门针对餐饮、零售等实体行业进行深度财务建模。

详细实现逻辑核心计算逻辑方式的解析:

1. 概览

该项目采用经典的**MVC(模型-视图-控制器)**架构:

  • 视图层 (View)InvestmentApp 类,基于 PyQt5 实现 GUI 界面,包含输入表单、结果标签页和图表展示。
  • 模型层 (Model)
    • IndustryBenchmarks:存储各行业的基准数据(黄金比例)。
    • InvestmentCalculator:核心计算引擎。
    • InvestmentCharts:数据可视化引擎。
  • 逻辑层 (Logic)InvestmentCalculator 中的各类计算方法。

2. 核心计算逻辑详解

这是项目最核心的部分,它将实体投资拆解为四个关键的量化分析维度。

A. 初始投资与现金流生成逻辑

这是所有计算的基础,系统首先计算投资者的"入场费"和日常的"造血能力"。

  • 初始投资 (Initial Investment)
    Total=转让费+(押金+预付月数)×月租金+装修费+设备费+其他Total = 转让费 + (押金 + 预付月数) \times 月租金 + 装修费 + 设备费 + 其他Total=转让费+(押金+预付月数)×月租金+装修费+设备费+其他

    • 逻辑细节:代码中将租金拆分为"首期租金",区分了沉没成本(转让费、装修)和流动资金。
  • 月度现金流 (Monthly Cash Flow)
    月总收入=(日均最低营收+日均最高营收)/2×运营天数月总收入 = (日均最低营收 + 日均最高营收) / 2 \times 运营天数月总收入=(日均最低营收+日均最高营收)/2×运营天数
    月总成本=租金+人力+物料+水电+其他月总成本 = 租金 + 人力 + 物料 + 水电 + 其他月总成本=租金+人力+物料+水电+其他
    月净利润=月总收入−月总成本月净利润 = 月总收入 - 月总成本月净利润=月总收入−月总成本

    • 逻辑细节:成本结构是直接由用户输入的固定金额,而非简单的百分比,这更符合实体经营中"房租、人工"是刚性支出的现实。
B. 回本周期与 ROI (核心生存指标)

这是实体投资者最关心的指标。

  • 回本周期 (Payback Period)
    日均利润=月净利润/30日均利润 = 月净利润 / 30日均利润=月净利润/30
    回本天数=总初始投资/日均利润回本天数 = 总初始投资 / 日均利润回本天数=总初始投资/日均利润

    • 逻辑细节 :代码中 calculate_break_even 方法还引入了 growth_rate(增长率),模拟了收入随时间增长的复利效应,生成每日累计现金流曲线。
  • 年化 ROI (Return on Investment)
    ROI=(月净利润×12/总初始投资)×100%ROI = (月净利润 \times 12 / 总初始投资) \times 100\%ROI=(月净利润×12/总初始投资)×100%

C. 风险调整后收益指标 (专业量化核心)

这是该项目区别于普通计算器的最大亮点。它没有单纯看收益,而是衡量"承担一单位风险能获得多少超额收益"。

1. 夏普比率 (Sharpe Ratio)

衡量总波动风险 下的超额回报。
Sharpe=Rp−RfσpSharpe = \frac{R_p - R_f}{\sigma_p}Sharpe=σpRp−Rf

  • 代码逻辑
    • RpR_pRp (投资组合回报率):年化净利润率。
    • RfR_fRf (无风险利率):默认 2.5% (国债水平)。
    • σp\sigma_pσp (波动率):基于日收入波动率估算年化波动率 (σdaily×252\sigma_{daily} \times \sqrt{252}σdaily×252 )。
    • 评估:夏普比率 > 1 通常被认为是好的,代码中根据行业基准进行了分级。

2. 索提诺比率 (Sortino Ratio)

衡量下行风险 (Downside Risk) 的指标,只惩罚亏损的波动,比夏普比率更精准。
Sortino=Rp−RfσdSortino = \frac{R_p - R_f}{\sigma_d}Sortino=σdRp−Rf

  • 代码逻辑 :代码中简化处理,假设下行波动率是年化波动率的 70% (downside_volatility = annual_volatility * 0.7)。

3. 特雷诺比率 (Treynor Ratio)

衡量系统性风险 (Beta) 下的超额回报。
Treynor=Rp−RfβTreynor = \frac{R_p - R_f}{\beta}Treynor=βRp−Rf

  • 代码逻辑 :代码中通过 market_beta (市场贝塔) 和 industry_beta (行业贝塔) 的平均值来估算项目贝塔系数,评估项目对市场波动的敏感度。
D. 财务健康度与运营效率

这部分将财务数据与行业基准进行对比。

  • 成本结构分析
    • 逻辑:计算租金、人工、物料占营收的比例。
    • 基准对比 :代码中 IndustryBenchmarks 定义了餐饮、便利店、奶茶店等行业的黄金比例。例如,餐饮业的食材成本占比基准是 30%-35%,如果计算结果超过此范围,系统会判定为"风险"。
  • 运营效率
    • 坪效 (Revenue / Area):每平方米产生的月营收。
    • 人效 (Revenue / Staff):每人产生的月营收。
    • 存货周转:评估库存变现速度。

3. 实现逻辑流程图解

用户输入 GUI
数据收集 collect_input_data
核心计算引擎 InvestmentCalculator
初始投资计算
收入与成本建模
回本与 ROI 计算
风险指标计算
财务健康度评估
运营效率分析
生成综合报告 generate_full_report
可视化 Charts
回本周期图
成本结构饼图
多维雷达图
投资仪表盘
GUI 结果展示

4. 代码

复制代码
"""
投资计算评估应用
专业投资者指标分析工具
包含:夏普比率、索提诺比率、特雷诺比率、现金流质量、财务健康度、运营效率等
"""

import sys
import math
from datetime import datetime, timedelta
from typing import Dict, List, Tuple, Optional
import numpy as np
import pandas as pd

from PyQt5.QtWidgets import (
    QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
    QSplitter, QTabWidget, QLabel, QLineEdit, QPushButton, QComboBox,
    QSpinBox, QDoubleSpinBox, QGroupBox, QScrollArea, QTableWidget,
    QTableWidgetItem, QHeaderView, QProgressBar, QFrame, QGridLayout,
    QTextEdit, QFileDialog, QMessageBox, QColorDialog, QCheckBox,
    QListWidget, QCalendarWidget, QProgressDialog, QStatusBar,
    QToolBar, QAction, QMenu, QMenuBar, QLCDNumber, QDial
)
from PyQt5.QtCore import Qt, QTimer, QThread, pyqtSignal, QDate, QSize
from PyQt5.QtGui import QFont, QIcon, QPalette, QColor, QPainter, QPen, QBrush, QPixmap

import matplotlib
matplotlib.use('Qt5Agg')
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5 import NavigationToolbar2QT
import matplotlib.pyplot as plt
from matplotlib.patches import Patch, Circle, Wedge
from matplotlib.figure import Figure
import matplotlib.patches as mpatches
from matplotlib.gridspec import GridSpec

# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'SimHei', 'Arial Unicode MS', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

from scipy import stats


# ============================================================================
# 行业基准数据库
# ============================================================================
class IndustryBenchmarks:
    """行业基准数据"""
    
    BENCHMARKS = {
        '餐饮': {
            'name': '餐饮行业',
            'break_even_optimal': (6, 12),      # 优质回本周期(月)
            'break_even_risky': 18,             # 风险临界点(月)
            'gross_margin': (60, 70),            # 毛利率%
            'net_margin': (5, 15),              # 净利率%
            'labor_cost_ratio': (18, 22),       # 人力成本占比%
            'rent_ratio': (10, 15),             # 租金占比%
            'material_ratio': (30, 35),          # 食材成本占比%
            'efficiency_per_sqm': (1000, 1500),  # 坪效(元/㎡)
            'turnover_rate': 2.0,               # 翻台率
            'repurchase_rate': 40,              # 复购率%
            'inventory_days': (15, 30),         # 存货周转天数
            'debt_ratio': 60,                   # 资产负债率%
            'current_ratio': 1.5,                # 流动比率
            'sharpe_optimal': 1.2,              # 优质夏普比率
            'sortino_optimal': 1.5,            # 优质索提诺比率
            'treynor_optimal': 1.0,            # 优质特雷诺比率
        },
        '零售': {
            'name': '零售行业',
            'break_even_optimal': (8, 18),
            'break_even_risky': 24,
            'gross_margin': (30, 40),
            'net_margin': (3, 8),
            'labor_cost_ratio': (20, 25),
            'rent_ratio': (15, 20),
            'material_ratio': (50, 60),
            'efficiency_per_sqm': (800, 1200),
            'turnover_rate': 4.0,
            'repurchase_rate': 30,
            'inventory_days': (30, 60),
            'debt_ratio': 50,
            'current_ratio': 1.5,
            'sharpe_optimal': 1.0,
            'sortino_optimal': 1.2,
            'treynor_optimal': 0.8,
        },
        '服务': {
            'name': '服务行业',
            'break_even_optimal': (12, 24),
            'break_even_risky': 30,
            'gross_margin': (50, 70),
            'net_margin': (10, 20),
            'labor_cost_ratio': (25, 35),
            'rent_ratio': (10, 18),
            'material_ratio': (10, 20),
            'efficiency_per_sqm': (800, 1500),
            'turnover_rate': 1.0,
            'repurchase_rate': 35,
            'inventory_days': (7, 14),
            'debt_ratio': 55,
            'current_ratio': 1.8,
            'sharpe_optimal': 1.1,
            'sortino_optimal': 1.3,
            'treynor_optimal': 0.9,
        },
        '便利店': {
            'name': '便利店行业',
            'break_even_optimal': (8, 12),
            'break_even_risky': 18,
            'gross_margin': (20, 30),
            'net_margin': (2, 5),
            'labor_cost_ratio': (15, 20),
            'rent_ratio': (15, 25),
            'material_ratio': (60, 70),
            'efficiency_per_sqm': (2000, 3000),
            'turnover_rate': 5.0,
            'repurchase_rate': 50,
            'inventory_days': (7, 14),
            'debt_ratio': 45,
            'current_ratio': 1.2,
            'sharpe_optimal': 0.8,
            'sortino_optimal': 1.0,
            'treynor_optimal': 0.6,
        },
        '水果店': {
            'name': '水果零售',
            'break_even_optimal': (6, 10),
            'break_even_risky': 15,
            'gross_margin': (50, 65),
            'net_margin': (8, 15),
            'labor_cost_ratio': (15, 22),
            'rent_ratio': (12, 18),
            'material_ratio': (40, 50),
            'efficiency_per_sqm': (1500, 2500),
            'turnover_rate': 3.0,
            'repurchase_rate': 45,
            'inventory_days': (3, 7),
            'debt_ratio': 40,
            'current_ratio': 1.5,
            'sharpe_optimal': 1.3,
            'sortino_optimal': 1.6,
            'treynor_optimal': 1.0,
        },
        '奶茶店': {
            'name': '奶茶饮品店',
            'break_even_optimal': (12, 18),
            'break_even_risky': 24,
            'gross_margin': (65, 75),
            'net_margin': (10, 18),
            'labor_cost_ratio': (20, 28),
            'rent_ratio': (15, 22),
            'material_ratio': (25, 35),
            'efficiency_per_sqm': (3000, 5000),
            'turnover_rate': 4.0,
            'repurchase_rate': 55,
            'inventory_days': (2, 5),
            'debt_ratio': 50,
            'current_ratio': 1.4,
            'sharpe_optimal': 1.4,
            'sortino_optimal': 1.7,
            'treynor_optimal': 1.1,
        },
        '酒店': {
            'name': '酒店住宿',
            'break_even_optimal': (18, 36),
            'break_even_risky': 60,
            'gross_margin': (55, 70),
            'net_margin': (8, 20),
            'labor_cost_ratio': (25, 35),
            'rent_ratio': (20, 35),
            'material_ratio': (8, 15),
            'efficiency_per_sqm': (500, 1000),
            'turnover_rate': 0.7,
            'repurchase_rate': 25,
            'inventory_days': (1, 3),
            'debt_ratio': 65,
            'current_ratio': 1.2,
            'sharpe_optimal': 0.9,
            'sortino_optimal': 1.1,
            'treynor_optimal': 0.7,
        },
        '自定义': {
            'name': '自定义行业',
            'break_even_optimal': (12, 24),
            'break_even_risky': 36,
            'gross_margin': (40, 60),
            'net_margin': (5, 15),
            'labor_cost_ratio': (20, 30),
            'rent_ratio': (15, 25),
            'material_ratio': (30, 50),
            'efficiency_per_sqm': (800, 1500),
            'turnover_rate': 2.0,
            'repurchase_rate': 35,
            'inventory_days': (15, 45),
            'debt_ratio': 55,
            'current_ratio': 1.5,
            'sharpe_optimal': 1.0,
            'sortino_optimal': 1.2,
            'treynor_optimal': 0.8,
        }
    }
    
    @classmethod
    def get_benchmark(cls, industry: str) -> Dict:
        """获取行业基准"""
        return cls.BENCHMARKS.get(industry, cls.BENCHMARKS['自定义'])


# ============================================================================
# 投资计算引擎
# ============================================================================
class InvestmentCalculator:
    """投资计算引擎"""
    
    def __init__(self):
        self.data = {}
        self.results = {}
        
    def set_data(self, data: Dict):
        """设置输入数据"""
        self.data = data
        
    def calculate_initial_investment(self) -> Dict:
        """计算初始投资"""
        transfer_fee = self.data.get('transfer_fee', 0)  # 转让费
        deposit_months = self.data.get('deposit_months', 1)  # 押金月数
        advance_months = self.data.get('advance_months', 2)  # 预付月数
        monthly_rent = self.data.get('monthly_rent', 0)  # 月租金
        
        initial_rent = monthly_rent * (deposit_months + advance_months)  # 首期租金
        renovation_cost = self.data.get('renovation_cost', 0)  # 装修费
        equipment_cost = self.data.get('equipment_cost', 0)  # 设备采购
        other_costs = self.data.get('other_costs', 0)  # 其他费用
        
        total_investment = (
            transfer_fee + initial_rent + 
            renovation_cost + equipment_cost + other_costs
        )
        
        return {
            'transfer_fee': transfer_fee,
            'initial_rent': initial_rent,
            'renovation_cost': renovation_cost,
            'equipment_cost': equipment_cost,
            'other_costs': other_costs,
            'total_investment': total_investment,
            'investment_breakdown': {
                '转让费': transfer_fee,
                '首期租金': initial_rent,
                '装修费': renovation_cost,
                '设备费': equipment_cost,
                '其他费用': other_costs
            }
        }
    
    def calculate_revenue(self) -> Dict:
        """计算收入"""
        daily_revenue_min = self.data.get('daily_revenue_min', 0)
        daily_revenue_max = self.data.get('daily_revenue_max', 0)
        operating_days = self.data.get('operating_days', 30)  # 月运营天数
        
        monthly_revenue_min = daily_revenue_min * operating_days
        monthly_revenue_max = daily_revenue_max * operating_days
        monthly_revenue_avg = (daily_revenue_min + daily_revenue_max) / 2 * operating_days
        
        annual_revenue = monthly_revenue_avg * 12
        
        return {
            'daily_revenue_min': daily_revenue_min,
            'daily_revenue_max': daily_revenue_max,
            'daily_revenue_avg': (daily_revenue_min + daily_revenue_max) / 2,
            'monthly_revenue_min': monthly_revenue_min,
            'monthly_revenue_max': monthly_revenue_max,
            'monthly_revenue_avg': monthly_revenue_avg,
            'annual_revenue': annual_revenue
        }
    
    def calculate_costs(self) -> Dict:
        """计算成本 - 直接使用用户输入的实际成本数据"""
        revenue_data = self.calculate_revenue()
        monthly_revenue = revenue_data['monthly_revenue_avg']
        
        # 直接使用用户输入的实际金额
        monthly_rent = self.data.get('cost_rent', 2800)  # 月租金
        monthly_labor = self.data.get('cost_labor', 4000)  # 人力成本
        monthly_material = self.data.get('cost_material', 6000)  # 食材/进货成本
        monthly_utilities = self.data.get('cost_utilities', 600)  # 水电
        monthly_other = self.data.get('cost_other', 1000)  # 其他
        
        # 实际总成本(用户输入是多少就是多少)
        monthly_total_cost = (
            monthly_rent + monthly_labor + monthly_material + 
            monthly_utilities + monthly_other
        )
        
        # 实际净利润 = 营业额 - 所有成本
        monthly_profit = monthly_revenue - monthly_total_cost
        
        # 实际利润率
        profit_rate = monthly_profit / monthly_revenue if monthly_revenue > 0 else 0
        
        # 目标利润率(仅作为参考信息显示)
        target_profit_rate = self.data.get('profit_rate', 0.15)
        target_profit = monthly_revenue * target_profit_rate
        
        # 各项成本占比(相对于总收入)
        rent_ratio = monthly_rent / monthly_revenue if monthly_revenue > 0 else 0
        labor_ratio = monthly_labor / monthly_revenue if monthly_revenue > 0 else 0
        material_ratio = monthly_material / monthly_revenue if monthly_revenue > 0 else 0
        utilities_ratio = monthly_utilities / monthly_revenue if monthly_revenue > 0 else 0
        other_ratio = monthly_other / monthly_revenue if monthly_revenue > 0 else 0
        
        return {
            'profit_rate': profit_rate,
            'rent_ratio': rent_ratio,
            'labor_ratio': labor_ratio,
            'material_ratio': material_ratio,
            'utilities_ratio': utilities_ratio,
            'other_ratio': other_ratio,
            'monthly_profit': monthly_profit,
            'monthly_rent': monthly_rent,
            'monthly_labor': monthly_labor,
            'monthly_material': monthly_material,
            'monthly_utilities': monthly_utilities,
            'monthly_other': monthly_other,
            'monthly_total_cost': monthly_total_cost,
            'target_profit_rate': target_profit_rate,
            'target_profit': target_profit,
            'profit_diff': monthly_profit - target_profit,  # 与目标的差额
            'cost_breakdown': {
                '租金': monthly_rent,
                '人力成本': monthly_labor,
                '食材/进货': monthly_material,
                '水电费': monthly_utilities,
                '其他成本': monthly_other
            }
        }
    
    def calculate_break_even(self) -> Dict:
        """计算回本周期"""
        investment = self.calculate_initial_investment()
        costs = self.calculate_costs()
        
        total_investment = investment['total_investment']
        monthly_profit = costs['monthly_profit']
        daily_profit = monthly_profit / 30
        
        # 精确回本周期计算
        if daily_profit > 0:
            break_even_days = total_investment / daily_profit
            break_even_months = break_even_days / 30
        else:
            break_even_days = float('inf')
            break_even_months = float('inf')
        
        # ROI计算
        annual_profit = monthly_profit * 12
        roi = (annual_profit / total_investment) * 100 if total_investment > 0 else 0
        
        # 生成每日累计现金流数据
        days_list = list(range(int(break_even_days) + 60))  # 回本后延长60天
        daily_cashflow = []
        cumulative = -total_investment
        
        for day in days_list:
            daily_profit_current = daily_profit * (1 + self.data.get('growth_rate', 0) / 365) ** day
            cumulative += daily_profit_current
            daily_cashflow.append({
                'day': day,
                'daily_profit': daily_profit_current,
                'cumulative_cashflow': cumulative
            })
        
        return {
            'total_investment': total_investment,
            'monthly_profit': monthly_profit,
            'daily_profit': daily_profit,
            'break_even_days': break_even_days,
            'break_even_months': break_even_months,
            'roi': roi,
            'annual_profit': annual_profit,
            'payback_quality': self._assess_payback_quality(break_even_months),
            'daily_cashflow': daily_cashflow
        }
    
    def _assess_payback_quality(self, months: float) -> Dict:
        """评估回本周期质量"""
        industry = self.data.get('industry', '自定义')
        benchmark = IndustryBenchmarks.get_benchmark(industry)
        optimal_min, optimal_max = benchmark['break_even_optimal']
        risky = benchmark['break_even_risky']
        
        if months <= optimal_min:
            quality = '优秀'
            color = 'green'
            score = 100
            suggestion = '回本周期非常优秀,属于行业标杆水平'
        elif months <= optimal_max:
            quality = '良好'
            color = 'blue'
            score = 80
            suggestion = '回本周期在优质区间内'
        elif months <= risky:
            quality = '一般'
            color = 'orange'
            score = 60
            suggestion = '回本周期可接受,但需关注成本控制'
        else:
            quality = '风险'
            color = 'red'
            score = 30
            suggestion = '回本周期过长,建议谨慎投资'
        
        return {
            'quality': quality,
            'color': color,
            'score': score,
            'suggestion': suggestion,
            'optimal_range': f'{optimal_min}-{optimal_max}个月',
            'actual': f'{months:.1f}个月'
        }
    
    def calculate_risk_adjusted_metrics(self) -> Dict:
        """计算风险调整后收益指标"""
        break_even = self.calculate_break_even()
        annual_profit = break_even['annual_profit']
        total_investment = break_even['total_investment']
        
        # 年化收益率
        expected_return = annual_profit / total_investment if total_investment > 0 else 0
        
        # 无风险利率(国债收益率,约2.5%)
        risk_free_rate = self.data.get('risk_free_rate', 0.025)
        
        # 波动率估算(基于日收入波动)
        daily_revenue_volatility = self.data.get('daily_revenue_volatility', 0.1)
        
        # 年化波动率
        annual_volatility = daily_revenue_volatility * math.sqrt(252)
        
        # 下行波动率(仅考虑负收益)
        downside_volatility = annual_volatility * 0.7  # 简化估算
        
        # 贝塔系数
        market_beta = self.data.get('market_beta', 1.0)
        industry_beta = self.data.get('industry_beta', 1.2)
        beta = (market_beta + industry_beta) / 2
        
        # 夏普比率 = (预期收益 - 无风险利率) / 波动率
        if annual_volatility > 0:
            sharpe_ratio = (expected_return - risk_free_rate) / annual_volatility
        else:
            sharpe_ratio = 0
        
        # 索提诺比率 = (预期收益 - 无风险利率) / 下行波动率
        if downside_volatility > 0:
            sortino_ratio = (expected_return - risk_free_rate) / downside_volatility
        else:
            sortino_ratio = 0
        
        # 特雷诺比率 = (预期收益 - 无风险利率) / 贝塔
        if beta > 0:
            treynor_ratio = (expected_return - risk_free_rate) / beta
        else:
            treynor_ratio = 0
        
        # 评估指标质量
        industry = self.data.get('industry', '自定义')
        benchmark = IndustryBenchmarks.get_benchmark(industry)
        
        return {
            'expected_return': expected_return,
            'risk_free_rate': risk_free_rate,
            'annual_volatility': annual_volatility,
            'downside_volatility': downside_volatility,
            'beta': beta,
            'sharpe_ratio': sharpe_ratio,
            'sortino_ratio': sortino_ratio,
            'treynor_ratio': treynor_ratio,
            'sharpe_assessment': self._assess_sharpe(sharpe_ratio, benchmark['sharpe_optimal']),
            'sortino_assessment': self._assess_sortino(sortino_ratio, benchmark['sortino_optimal']),
            'treynor_assessment': self._assess_treynor(treynor_ratio, benchmark['treynor_optimal'])
        }
    
    def _assess_sharpe(self, sharpe: float, optimal: float) -> Dict:
        """评估夏普比率"""
        if sharpe >= optimal * 1.5:
            return {'level': '优秀', 'color': 'green', 'score': 100, 
                    'suggestion': '风险收益比极佳,是优质投资标的'}
        elif sharpe >= optimal:
            return {'level': '良好', 'color': 'blue', 'score': 80,
                    'suggestion': '风险收益比良好,符合专业标准'}
        elif sharpe >= optimal * 0.7:
            return {'level': '一般', 'color': 'orange', 'score': 60,
                    'suggestion': '风险收益比处于可接受范围'}
        else:
            return {'level': '风险', 'color': 'red', 'score': 40,
                    'suggestion': '风险收益比不佳,建议谨慎'}
    
    def _assess_sortino(self, sortino: float, optimal: float) -> Dict:
        """评估索提诺比率"""
        if sortino >= optimal * 1.5:
            return {'level': '优秀', 'color': 'green', 'score': 100,
                    'suggestion': '下行风险控制极佳'}
        elif sortino >= optimal:
            return {'level': '良好', 'color': 'blue', 'score': 80,
                    'suggestion': '下行风险控制良好'}
        elif sortino >= optimal * 0.7:
            return {'level': '一般', 'color': 'orange', 'score': 60,
                    'suggestion': '下行风险控制一般'}
        else:
            return {'level': '风险', 'color': 'red', 'score': 40,
                    'suggestion': '下行风险较大,需关注'}
    
    def _assess_treynor(self, treynor: float, optimal: float) -> Dict:
        """评估特雷诺比率"""
        if treynor >= optimal * 1.5:
            return {'level': '优秀', 'color': 'green', 'score': 100,
                    'suggestion': '系统性风险管理优秀'}
        elif treynor >= optimal:
            return {'level': '良好', 'color': 'blue', 'score': 80,
                    'suggestion': '系统性风险管理良好'}
        elif treynor >= optimal * 0.7:
            return {'level': '一般', 'color': 'orange', 'score': 60,
                    'suggestion': '系统性风险管理一般'}
        else:
            return {'level': '风险', 'color': 'red', 'score': 40,
                    'suggestion': '系统性风险较高,需谨慎'}
    
    def calculate_cashflow_quality(self) -> Dict:
        """计算现金流质量指标"""
        costs = self.calculate_costs()
        revenue = self.calculate_revenue()
        
        monthly_revenue = revenue['monthly_revenue_avg']
        monthly_profit = costs['monthly_profit']
        monthly_cost = costs['monthly_total_cost']
        
        # 经营现金流(简化:利润+非现金成本)
        depreciation = self.data.get('monthly_depreciation', 0)
        operating_cashflow = monthly_profit + depreciation
        
        # 自由现金流 = 经营现金流 - 资本支出
        monthly_capex = self.data.get('monthly_capex', 0)
        free_cashflow = operating_cashflow - monthly_capex
        
        # 现金流质量比率 = 经营现金流 / 净利润
        if monthly_profit > 0:
            cf_to_income_ratio = operating_cashflow / monthly_profit
        else:
            cf_to_income_ratio = 0
        
        # 自由现金流比率 = 自由现金流 / 净利润
        if monthly_profit > 0:
            fcf_to_income_ratio = free_cashflow / monthly_profit
        else:
            fcf_to_income_ratio = 0
        
        # 现金转换周期
        cash_conversion_days = 30 * (1 - cf_to_income_ratio) if cf_to_income_ratio < 1 else 0
        
        # 现金流稳定性(基于收入波动估算)
        revenue_volatility = self.data.get('daily_revenue_volatility', 0.1)
        
        return {
            'monthly_revenue': monthly_revenue,
            'monthly_profit': monthly_profit,
            'operating_cashflow': operating_cashflow,
            'free_cashflow': free_cashflow,
            'cf_to_income_ratio': cf_to_income_ratio,
            'fcf_to_income_ratio': fcf_to_income_ratio,
            'cash_conversion_days': cash_conversion_days,
            'revenue_volatility': revenue_volatility,
            'quality_assessment': self._assess_cf_quality(cf_to_income_ratio, fcf_to_income_ratio),
            'stability_assessment': self._assess_cf_stability(revenue_volatility)
        }
    
    def _assess_cf_quality(self, cf_ratio: float, fcf_ratio: float) -> Dict:
        """评估现金流质量"""
        if cf_ratio >= 1.2 and fcf_ratio >= 0.8:
            level = '优秀'
            color = 'green'
            score = 100
            suggestion = '现金流质量极佳,利润转化为现金能力强'
        elif cf_ratio >= 1.0 and fcf_ratio >= 0.5:
            level = '良好'
            color = 'blue'
            score = 80
            suggestion = '现金流质量良好'
        elif cf_ratio >= 0.8:
            level = '一般'
            color = 'orange'
            score = 60
            suggestion = '现金流质量一般,需关注应收款项'
        else:
            level = '风险'
            color = 'red'
            score = 40
            suggestion = '现金流质量差,存在现金流断裂风险'
        
        return {
            'level': level,
            'color': color,
            'score': score,
            'suggestion': suggestion,
            'cf_ratio': cf_ratio,
            'fcf_ratio': fcf_ratio
        }
    
    def _assess_cf_stability(self, volatility: float) -> Dict:
        """评估现金流稳定性"""
        if volatility <= 0.05:
            level = '优秀'
            color = 'green'
            score = 100
        elif volatility <= 0.1:
            level = '良好'
            color = 'blue'
            score = 80
        elif volatility <= 0.2:
            level = '一般'
            color = 'orange'
            score = 60
        else:
            level = '风险'
            color = 'red'
            score = 40
        
        return {
            'level': level,
            'color': color,
            'score': score,
            'volatility': volatility
        }
    
    def calculate_financial_health(self) -> Dict:
        """计算财务健康度指标"""
        costs = self.calculate_costs()
        revenue = self.calculate_revenue()
        
        monthly_revenue = revenue['monthly_revenue_avg']
        monthly_cost = costs['monthly_total_cost']
        monthly_profit = costs['monthly_profit']
        monthly_material = costs['monthly_material']
        
        # 毛利率 = (收入 - 物料成本) / 收入
        gross_margin = (monthly_revenue - monthly_material) / monthly_revenue if monthly_revenue > 0 else 0
        
        # 净利率
        net_margin = monthly_profit / monthly_revenue if monthly_revenue > 0 else 0
        
        # 资产负债率
        investment = self.calculate_initial_investment()
        total_assets = investment['total_investment']
        total_liabilities = self.data.get('total_liabilities', 0)
        debt_ratio = (total_liabilities / total_assets * 100) if total_assets > 0 else 0
        
        # 流动比率
        current_assets = self.data.get('current_assets', monthly_profit * 3)
        current_liabilities = self.data.get('current_liabilities', monthly_cost * 2)
        current_ratio = current_assets / current_liabilities if current_liabilities > 0 else 2.0
        
        # 速动比率
        quick_assets = current_assets - self.data.get('inventory', 0)
        quick_ratio = quick_assets / current_liabilities if current_liabilities > 0 else 1.5
        
        # 成本结构分析 - 使用实际占比
        industry = self.data.get('industry', '自定义')
        benchmark = IndustryBenchmarks.get_benchmark(industry)
        
        # 使用计算后的实际占比
        rent_ratio_pct = costs['rent_ratio'] * 100
        labor_ratio_pct = costs['labor_ratio'] * 100
        material_ratio_pct = costs['material_ratio'] * 100
        
        return {
            'gross_margin': gross_margin * 100,
            'net_margin': net_margin * 100,
            'debt_ratio': debt_ratio,
            'current_ratio': current_ratio,
            'quick_ratio': quick_ratio,
            'cost_structure': {
                'rent_ratio': rent_ratio_pct,
                'labor_ratio': labor_ratio_pct,
                'material_ratio': material_ratio_pct,
                'utilities_ratio': costs['utilities_ratio'] * 100,
                'other_ratio': costs['other_ratio'] * 100
            },
            'gross_margin_assessment': self._assess_gross_margin(gross_margin * 100, benchmark['gross_margin']),
            'net_margin_assessment': self._assess_net_margin(net_margin * 100, benchmark['net_margin']),
            'debt_ratio_assessment': self._assess_debt_ratio(debt_ratio, benchmark['debt_ratio']),
            'current_ratio_assessment': self._assess_current_ratio(current_ratio, benchmark['current_ratio']),
            'cost_structure_assessment': self._assess_cost_structure(rents=rent_ratio_pct, labor=labor_ratio_pct, 
                                                                        material=material_ratio_pct, benchmark=benchmark)
        }
    
    def _assess_gross_margin(self, margin: float, benchmark: Tuple) -> Dict:
        """评估毛利率"""
        if benchmark[0] <= margin <= benchmark[1]:
            return {'level': '良好', 'color': 'green', 'score': 100, 'value': margin}
        elif margin < benchmark[0]:
            diff = benchmark[0] - margin
            if diff <= 5:
                return {'level': '一般', 'color': 'orange', 'score': 70, 'value': margin}
            else:
                return {'level': '风险', 'color': 'red', 'score': 50, 'value': margin}
        else:
            return {'level': '优秀', 'color': 'blue', 'score': 110, 'value': margin}
    
    def _assess_net_margin(self, margin: float, benchmark: Tuple) -> Dict:
        """评估净利率"""
        if benchmark[0] <= margin <= benchmark[1]:
            return {'level': '良好', 'color': 'green', 'score': 100, 'value': margin}
        elif margin < benchmark[0]:
            if margin >= benchmark[0] * 0.7:
                return {'level': '一般', 'color': 'orange', 'score': 70, 'value': margin}
            else:
                return {'level': '风险', 'color': 'red', 'score': 50, 'value': margin}
        else:
            return {'level': '优秀', 'color': 'blue', 'score': 110, 'value': margin}
    
    def _assess_debt_ratio(self, ratio: float, benchmark: float) -> Dict:
        """评估资产负债率"""
        if ratio <= benchmark:
            return {'level': '良好', 'color': 'green', 'score': 100, 'value': ratio}
        elif ratio <= benchmark * 1.2:
            return {'level': '一般', 'color': 'orange', 'score': 70, 'value': ratio}
        else:
            return {'level': '风险', 'color': 'red', 'score': 50, 'value': ratio}
    
    def _assess_current_ratio(self, ratio: float, benchmark: float) -> Dict:
        """评估流动比率"""
        if ratio >= benchmark:
            return {'level': '良好', 'color': 'green', 'score': 100, 'value': ratio}
        elif ratio >= benchmark * 0.8:
            return {'level': '一般', 'color': 'orange', 'score': 70, 'value': ratio}
        else:
            return {'level': '风险', 'color': 'red', 'score': 50, 'value': ratio}
    
    def _assess_cost_structure(self, rents: float = None, labor: float = None, 
                                  material: float = None, benchmark: Dict = None) -> Dict:
        """评估成本结构 - 基于收入占比"""
        if benchmark is None:
            benchmark = IndustryBenchmarks.get_benchmark(self.data.get('industry', '自定义'))
        
        issues = []
        warnings = []
        score = 100
        
        # 租金占比(相对于收入)
        rent_benchmark = benchmark.get('rent_ratio', (10, 20))
        if rents is not None:
            if rents > rent_benchmark[1] * 1.5:
                issues.append(f"租金占比({rents:.1f}%)远超行业上限({rent_benchmark[1]}%)")
                score -= 25
            elif rents > rent_benchmark[1]:
                warnings.append(f"租金占比({rents:.1f}%)略高于行业上限({rent_benchmark[1]}%)")
                score -= 10
        
        # 人力成本占比(相对于收入)
        labor_benchmark = benchmark.get('labor_cost_ratio', (18, 25))
        if labor is not None:
            if labor > labor_benchmark[1] * 1.5:
                issues.append(f"人力成本占比({labor:.1f}%)远超行业上限({labor_benchmark[1]}%)")
                score -= 25
            elif labor > labor_benchmark[1]:
                warnings.append(f"人力成本占比({labor:.1f}%)略高于行业上限({labor_benchmark[1]}%)")
                score -= 10
        
        # 物料占比(相对于收入)
        material_benchmark = benchmark.get('material_ratio', (30, 35))
        if material is not None:
            if material > material_benchmark[1] * 1.5:
                issues.append(f"物料占比({material:.1f}%)远超行业上限({material_benchmark[1]}%)")
                score -= 25
            elif material > material_benchmark[1]:
                warnings.append(f"物料占比({material:.1f}%)略高于行业上限({material_benchmark[1]}%)")
                score -= 10
        
        all_issues = issues + warnings
        if not all_issues:
            level = '良好'
            color = 'green'
            suggestion = '成本结构符合行业黄金比例'
        elif len(all_issues) == 1:
            level = '一般'
            color = 'orange'
            suggestion = all_issues[0]
        else:
            level = '风险'
            color = 'red'
            suggestion = '存在多项成本异常,需重点关注'
        
        return {
            'level': level,
            'color': color,
            'score': max(0, score),
            'issues': all_issues,
            'suggestion': suggestion
        }
    
    def calculate_operational_efficiency(self) -> Dict:
        """计算运营效率指标"""
        revenue = self.calculate_revenue()
        costs = self.calculate_costs()
        
        monthly_revenue = revenue['monthly_revenue_avg']
        area = self.data.get('area', 100)  # 经营面积(平方米)
        staff_count = self.data.get('staff_count', 2)  # 员工数量
        seats = self.data.get('seats', 20)  # 座位数
        daily_customers = self.data.get('daily_customers', 50)  # 日客流量
        
        # 坪效(元/平方米/月)
        efficiency_per_sqm = monthly_revenue / area if area > 0 else 0
        
        # 人效(元/人/月)
        efficiency_per_person = monthly_revenue / staff_count if staff_count > 0 else 0
        
        # 客单价
        operating_days = self.data.get('operating_days', 30)
        avg_customer_value = monthly_revenue / (daily_customers * operating_days) if daily_customers > 0 else 0
        
        # 翻台率(餐饮)
        turnover_rate = (daily_customers * operating_days / 30) / seats if seats > 0 else 0
        
        # 存货周转率
        monthly_material = costs['monthly_material']
        avg_inventory = self.data.get('avg_inventory', monthly_material * 5)
        inventory_turnover = monthly_material / avg_inventory if avg_inventory > 0 else 0
        inventory_days = 30 / inventory_turnover if inventory_turnover > 0 else 30
        
        industry = self.data.get('industry', '自定义')
        benchmark = IndustryBenchmarks.get_benchmark(industry)
        
        return {
            'efficiency_per_sqm': efficiency_per_sqm,
            'efficiency_per_person': efficiency_per_person,
            'avg_customer_value': avg_customer_value,
            'turnover_rate': turnover_rate,
            'inventory_turnover': inventory_turnover,
            'inventory_days': inventory_days,
            'sqm_efficiency_assessment': self._assess_sqm_efficiency(efficiency_per_sqm, benchmark['efficiency_per_sqm']),
            'person_efficiency_assessment': self._assess_person_efficiency(efficiency_per_person, benchmark),
            'turnover_assessment': self._assess_turnover(turnover_rate, benchmark['turnover_rate']),
            'inventory_assessment': self._assess_inventory(inventory_days, benchmark['inventory_days'])
        }
    
    def _assess_sqm_efficiency(self, value: float, benchmark: Tuple) -> Dict:
        """评估坪效"""
        if value >= benchmark[1]:
            return {'level': '优秀', 'color': 'green', 'score': 100, 'value': value, 'benchmark': benchmark}
        elif value >= benchmark[0]:
            return {'level': '良好', 'color': 'blue', 'score': 80, 'value': value, 'benchmark': benchmark}
        elif value >= benchmark[0] * 0.8:
            return {'level': '一般', 'color': 'orange', 'score': 60, 'value': value, 'benchmark': benchmark}
        else:
            return {'level': '风险', 'color': 'red', 'score': 40, 'value': value, 'benchmark': benchmark}
    
    def _assess_person_efficiency(self, value: float, benchmark: Dict) -> Dict:
        """评估人效"""
        # 简化估算人效基准
        baseline = 150000  # 15万/人/年
        
        if value * 12 >= baseline * 1.2:
            return {'level': '优秀', 'color': 'green', 'score': 100, 'value': value}
        elif value * 12 >= baseline:
            return {'level': '良好', 'color': 'blue', 'score': 80, 'value': value}
        elif value * 12 >= baseline * 0.8:
            return {'level': '一般', 'color': 'orange', 'score': 60, 'value': value}
        else:
            return {'level': '风险', 'color': 'red', 'score': 40, 'value': value}
    
    def _assess_turnover(self, rate: float, benchmark: float) -> Dict:
        """评估翻台率"""
        if rate >= benchmark * 1.2:
            return {'level': '优秀', 'color': 'green', 'score': 100, 'value': rate, 'benchmark': benchmark}
        elif rate >= benchmark:
            return {'level': '良好', 'color': 'blue', 'score': 80, 'value': rate, 'benchmark': benchmark}
        elif rate >= benchmark * 0.7:
            return {'level': '一般', 'color': 'orange', 'score': 60, 'value': rate, 'benchmark': benchmark}
        else:
            return {'level': '风险', 'color': 'red', 'score': 40, 'value': rate, 'benchmark': benchmark}
    
    def _assess_inventory(self, days: float, benchmark: Tuple) -> Dict:
        """评估存货周转"""
        if benchmark[0] <= days <= benchmark[1]:
            return {'level': '良好', 'color': 'green', 'score': 100, 'value': days, 'benchmark': benchmark}
        elif days < benchmark[0]:
            return {'level': '优秀', 'color': 'blue', 'score': 110, 'value': days, 'benchmark': benchmark}
        elif days <= benchmark[1] * 1.3:
            return {'level': '一般', 'color': 'orange', 'score': 60, 'value': days, 'benchmark': benchmark}
        else:
            return {'level': '风险', 'color': 'red', 'score': 40, 'value': days, 'benchmark': benchmark}
    
    def calculate_portfolio_metrics(self) -> Dict:
        """计算投资组合管理指标"""
        risk_metrics = self.calculate_risk_adjusted_metrics()
        cashflow = self.calculate_cashflow_quality()
        financial = self.calculate_financial_health()
        operation = self.calculate_operational_efficiency()
        
        # 投资分散化建议
        correlation_suggestion = self._assess_correlation()
        
        # 综合评分
        overall_score = (
            risk_metrics['sharpe_assessment']['score'] * 0.25 +
            cashflow['quality_assessment']['score'] * 0.25 +
            financial['cost_structure_assessment']['score'] * 0.25 +
            operation['sqm_efficiency_assessment']['score'] * 0.25
        )
        
        # 投资评级
        if overall_score >= 90:
            rating = 'A+'
            rating_color = 'green'
            recommendation = '强烈推荐'
        elif overall_score >= 80:
            rating = 'A'
            rating_color = 'green'
            recommendation = '推荐投资'
        elif overall_score >= 70:
            rating = 'B+'
            rating_color = 'blue'
            recommendation = '可以投资'
        elif overall_score >= 60:
            rating = 'B'
            rating_color = 'blue'
            recommendation = '谨慎投资'
        elif overall_score >= 50:
            rating = 'C'
            rating_color = 'orange'
            recommendation = '不建议投资'
        else:
            rating = 'D'
            rating_color = 'red'
            recommendation = '不建议投资'
        
        return {
            'overall_score': overall_score,
            'rating': rating,
            'rating_color': rating_color,
            'recommendation': recommendation,
            'correlation_suggestion': correlation_suggestion,
            'dimension_scores': {
                'risk_adjusted': risk_metrics['sharpe_assessment']['score'],
                'cashflow_quality': cashflow['quality_assessment']['score'],
                'financial_health': financial['cost_structure_assessment']['score'],
                'operational_efficiency': operation['sqm_efficiency_assessment']['score']
            }
        }
    
    def _assess_correlation(self) -> Dict:
        """评估资产相关性"""
        industry = self.data.get('industry', '自定义')
        
        # 不同行业的相关性建议
        suggestions = {
            '餐饮': '建议与零售、服务业组合,降低行业集中度风险',
            '零售': '建议与餐饮、娱乐业组合,分散消费周期性风险',
            '服务': '建议与餐饮、零售业组合,平衡抗周期能力',
            '便利店': '建议与餐饮、社区服务业组合,提高协同效应',
            '水果店': '建议与便利店、零售业组合,共享供应链优势',
            '奶茶店': '建议与餐饮、娱乐业组合,吸引相同客群',
            '酒店': '建议与旅游、娱乐业组合,对冲季节性风险',
            '自定义': '建议进行多元化配置,降低单一项目风险'
        }
        
        return {
            'suggestion': suggestions.get(industry, suggestions['自定义']),
            'ideal_portfolio_size': 5,
            'max_concentration': 30  # 单项目最大占比%
        }
    
    def generate_full_report(self) -> Dict:
        """生成完整评估报告"""
        return {
            'initial_investment': self.calculate_initial_investment(),
            'revenue': self.calculate_revenue(),
            'costs': self.calculate_costs(),
            'break_even': self.calculate_break_even(),
            'risk_adjusted': self.calculate_risk_adjusted_metrics(),
            'cashflow_quality': self.calculate_cashflow_quality(),
            'financial_health': self.calculate_financial_health(),
            'operational_efficiency': self.calculate_operational_efficiency(),
            'portfolio_metrics': self.calculate_portfolio_metrics()
        }


# ============================================================================
# 可视化图表类
# ============================================================================
class InvestmentCharts:
    """投资可视化图表"""
    
    def __init__(self, data: Dict, results: Dict):
        self.data = data
        self.results = results
        
    def create_break_even_chart(self, parent=None) -> Figure:
        """创建回本周期图表"""
        fig, ax = plt.subplots(figsize=(12, 6))
        
        daily_cashflow = self.results['break_even']['daily_cashflow']
        days = [item['day'] for item in daily_cashflow]
        cumulative = [item['cumulative_cashflow'] for item in daily_cashflow]
        
        ax.plot(days, cumulative, 'b-', linewidth=2, label='累计现金流')
        ax.axhline(y=0, color='r', linestyle='--', linewidth=1, label='盈亏平衡线')
        
        # 标记回本点
        break_even_days = self.results['break_even']['break_even_days']
        if break_even_days < len(days):
            ax.axvline(x=break_even_days, color='g', linestyle=':', linewidth=2, 
                      label=f'回本点({break_even_days:.0f}天)')
            ax.scatter([break_even_days], [0], color='g', s=100, zorder=5)
        
        ax.fill_between(days, cumulative, 0, where=[c >= 0 for c in cumulative], 
                       alpha=0.3, color='green', label='盈利区间')
        ax.fill_between(days, cumulative, 0, where=[c < 0 for c in cumulative], 
                       alpha=0.3, color='red', label='亏损区间')
        
        ax.set_xlabel('天数', fontsize=12)
        ax.set_ylabel('现金流(元)', fontsize=12)
        ax.set_title('回本周期分析', fontsize=14, fontweight='bold')
        ax.legend(loc='upper left')
        ax.grid(True, alpha=0.3)
        
        plt.tight_layout()
        return fig
    
    def create_cost_structure_chart(self, parent=None) -> Figure:
        """创建成本结构图表"""
        fig, axes = plt.subplots(1, 2, figsize=(14, 6))
        
        # 饼图 - 成本占比
        costs = self.results['costs']['cost_breakdown']
        labels = list(costs.keys())
        sizes = list(costs.values())
        colors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99', '#ff99cc']
        
        axes[0].pie(sizes, labels=labels, autopct='%1.1f%%', startangle=90, 
                   colors=colors, explode=[0.05]*len(sizes))
        axes[0].set_title('成本结构占比', fontsize=14, fontweight='bold')
        
        # 柱状图 - 月度成本明细
        x = range(len(labels))
        bars = axes[1].bar(x, sizes, color=colors)
        axes[1].set_xticks(x)
        axes[1].set_xticklabels(labels, rotation=45, ha='right')
        axes[1].set_ylabel('金额(元/月)', fontsize=12)
        axes[1].set_title('月度成本明细', fontsize=14, fontweight='bold')
        
        # 添加数值标签
        for bar, val in zip(bars, sizes):
            axes[1].text(bar.get_x() + bar.get_width()/2, bar.get_height() + 50,
                        f'{val:.0f}', ha='center', va='bottom', fontsize=9)
        
        plt.tight_layout()
        return fig
    
    def create_monthly_projection_chart(self, parent=None) -> Figure:
        """创建月度预测图表"""
        fig, axes = plt.subplots(2, 2, figsize=(14, 10))
        
        revenue = self.results['revenue']
        costs = self.results['costs']
        months = range(1, 37)  # 36个月预测
        
        # 月度收入
        monthly_revenue = [revenue['monthly_revenue_avg']] * 36
        axes[0, 0].plot(months, monthly_revenue, 'g-', linewidth=2, marker='o', markersize=3)
        axes[0, 0].fill_between(months, 
                                [revenue['monthly_revenue_min']] * 36,
                                [revenue['monthly_revenue_max']] * 36,
                                alpha=0.3, color='green')
        axes[0, 0].set_title('月度收入预测', fontsize=12, fontweight='bold')
        axes[0, 0].set_xlabel('月份')
        axes[0, 0].set_ylabel('收入(元)')
        axes[0, 0].grid(True, alpha=0.3)
        
        # 月度利润
        growth_rate = self.data.get('growth_rate', 0)
        monthly_profit = [costs['monthly_profit'] * (1 + growth_rate/12)**m for m in months]
        axes[0, 1].plot(months, monthly_profit, 'b-', linewidth=2, marker='s', markersize=3)
        axes[0, 1].fill_between(months, 0, monthly_profit, alpha=0.3, color='blue')
        axes[0, 1].set_title('月度利润预测', fontsize=12, fontweight='bold')
        axes[0, 1].set_xlabel('月份')
        axes[0, 1].set_ylabel('利润(元)')
        axes[0, 1].grid(True, alpha=0.3)
        
        # 累计现金流
        investment = self.results['initial_investment']['total_investment']
        cumulative = [-investment]
        for m in months:
            monthly_net = revenue['monthly_revenue_avg'] * (1 + growth_rate/12)**m - costs['monthly_total_cost']
            cumulative.append(cumulative[-1] + monthly_net)
        axes[1, 0].plot(range(0, 37), cumulative, 'purple', linewidth=2, marker='^', markersize=3)
        axes[1, 0].axhline(y=0, color='r', linestyle='--')
        axes[1, 0].fill_between(range(0, 37), 0, cumulative, where=[c >= 0 for c in cumulative],
                               alpha=0.3, color='green')
        axes[1, 0].fill_between(range(0, 37), 0, cumulative, where=[c < 0 for c in cumulative],
                               alpha=0.3, color='red')
        axes[1, 0].set_title('累计现金流变化', fontsize=12, fontweight='bold')
        axes[1, 0].set_xlabel('月份')
        axes[1, 0].set_ylabel('现金流(元)')
        axes[1, 0].grid(True, alpha=0.3)
        
        # 3年总回报
        total_return = sum(monthly_profit) - investment
        roi_3y = (total_return / investment) * 100 if investment > 0 else 0
        categories = ['初始投资', '3年累计利润', '3年总回报']
        values = [investment, sum(monthly_profit), total_return]
        colors_bar = ['#ff6b6b', '#4ecdc4', '#45b7d1']
        bars = axes[1, 1].bar(categories, values, color=colors_bar)
        axes[1, 1].set_title(f'3年投资回报 (ROI: {roi_3y:.1f}%)', fontsize=12, fontweight='bold')
        axes[1, 1].set_ylabel('金额(元)')
        for bar, val in zip(bars, values):
            axes[1, 1].text(bar.get_x() + bar.get_width()/2, bar.get_height() + 1000,
                           f'{val:,.0f}', ha='center', va='bottom', fontsize=9)
        
        plt.tight_layout()
        return fig
    
    def create_radar_chart(self, parent=None) -> Figure:
        """创建雷达图 - 多维度指标对比"""
        fig = plt.figure(figsize=(10, 10))
        
        # 获取各维度评分
        portfolio = self.results['portfolio_metrics']
        scores = [
            portfolio['dimension_scores']['risk_adjusted'],
            portfolio['dimension_scores']['cashflow_quality'],
            portfolio['dimension_scores']['financial_health'],
            portfolio['dimension_scores']['operational_efficiency'],
            portfolio['overall_score']
        ]
        
        # 雷达图
        categories = ['风险调整收益', '现金流质量', '财务健康度', '运营效率', '综合评分']
        N = len(categories)
        
        angles = [n / float(N) * 2 * 3.14159 for n in range(N)]
        angles += angles[:1]  # 闭合
        scores += scores[:1]   # 闭合
        
        ax = fig.add_subplot(111, polar=True)
        ax.plot(angles, scores, 'o-', linewidth=2, color='#1f77b4')
        ax.fill(angles, scores, alpha=0.25, color='#1f77b4')
        ax.set_xticks(angles[:-1])
        ax.set_xticklabels(categories, fontsize=11)
        ax.set_ylim(0, 120)
        ax.set_title('多维度评估雷达图', fontsize=14, fontweight='bold', pad=20)
        
        # 添加评分标注
        for angle, score in zip(angles[:-1], scores[:-1]):
            ax.annotate(f'{score:.0f}', xy=(angle, score), 
                       xytext=(angle, score + 10),
                       fontsize=10, ha='center')
        
        plt.tight_layout()
        return fig
    
    def create_metrics_dashboard(self, parent=None) -> Figure:
        """创建指标仪表盘"""
        fig = plt.figure(figsize=(16, 12))
        gs = GridSpec(3, 3, figure=fig, hspace=0.3, wspace=0.3)
        
        # 1. 投资评级
        ax1 = fig.add_subplot(gs[0, 0])
        rating = self.results['portfolio_metrics']['rating']
        score = self.results['portfolio_metrics']['overall_score']
        ax1.text(0.5, 0.5, rating, fontsize=60, ha='center', va='center',
                fontweight='bold', color=self._get_color(score))
        ax1.text(0.5, 0.15, f'综合评分: {score:.1f}', fontsize=12, ha='center', va='center')
        ax1.set_xlim(0, 1)
        ax1.set_ylim(0, 1)
        ax1.axis('off')
        ax1.set_title('投资评级', fontsize=14, fontweight='bold')
        
        # 2. 回本周期
        ax2 = fig.add_subplot(gs[0, 1])
        be_days = self.results['break_even']['break_even_days']
        be_quality = self.results['break_even']['payback_quality']
        ax2.text(0.5, 0.6, f'{be_days:.0f}', fontsize=40, ha='center', va='center',
                fontweight='bold', color=self._get_color(be_quality['score']))
        ax2.text(0.5, 0.3, '天', fontsize=16, ha='center', va='center')
        ax2.text(0.5, 0.1, f'({be_quality["quality"]})', fontsize=11, ha='center', va='center',
                color=self._get_color(be_quality['score']))
        ax2.set_xlim(0, 1)
        ax2.set_ylim(0, 1)
        ax2.axis('off')
        ax2.set_title('回本周期', fontsize=14, fontweight='bold')
        
        # 3. 年化ROI
        ax3 = fig.add_subplot(gs[0, 2])
        roi = self.results['break_even']['roi']
        ax3.text(0.5, 0.6, f'{roi:.1f}%', fontsize=40, ha='center', va='center',
                fontweight='bold', color=self._get_color(roi * 3))
        ax3.text(0.5, 0.3, '年化ROI', fontsize=14, ha='center', va='center')
        ax3.set_xlim(0, 1)
        ax3.set_ylim(0, 1)
        ax3.axis('off')
        ax3.set_title('投资回报率', fontsize=14, fontweight='bold')
        
        # 4. 夏普比率
        ax4 = fig.add_subplot(gs[1, 0])
        sharpe = self.results['risk_adjusted']['sharpe_ratio']
        ax4.text(0.5, 0.6, f'{sharpe:.2f}', fontsize=36, ha='center', va='center',
                fontweight='bold', color=self._get_color(sharpe * 40))
        ax4.text(0.5, 0.2, '夏普比率', fontsize=12, ha='center', va='center')
        ax4.set_xlim(0, 1)
        ax4.set_ylim(0, 1)
        ax4.axis('off')
        ax4.set_title('风险调整收益', fontsize=14, fontweight='bold')
        
        # 5. 现金流质量
        ax5 = fig.add_subplot(gs[1, 1])
        cf_ratio = self.results['cashflow_quality']['cf_to_income_ratio']
        ax5.text(0.5, 0.6, f'{cf_ratio:.2f}', fontsize=36, ha='center', va='center',
                fontweight='bold', color=self._get_color(cf_ratio * 50))
        ax5.text(0.5, 0.2, '现金流/利润比', fontsize=11, ha='center', va='center')
        ax5.set_xlim(0, 1)
        ax5.set_ylim(0, 1)
        ax5.axis('off')
        ax5.set_title('现金流质量', fontsize=14, fontweight='bold')
        
        # 6. 坪效
        ax6 = fig.add_subplot(gs[1, 2])
        sqm_eff = self.results['operational_efficiency']['efficiency_per_sqm']
        ax6.text(0.5, 0.6, f'{sqm_eff:.0f}', fontsize=36, ha='center', va='center',
                fontweight='bold', color=self._get_color(sqm_eff / 20))
        ax6.text(0.5, 0.2, '元/㎡/月', fontsize=11, ha='center', va='center')
        ax6.set_xlim(0, 1)
        ax6.set_ylim(0, 1)
        ax6.axis('off')
        ax6.set_title('坪效', fontsize=14, fontweight='bold')
        
        # 7. 关键指标条形图
        ax7 = fig.add_subplot(gs[2, :])
        metrics = {
            '夏普比率': self.results['risk_adjusted']['sharpe_ratio'],
            '索提诺比率': self.results['risk_adjusted']['sortino_ratio'],
            '特雷诺比率': self.results['risk_adjusted']['treynor_ratio'],
            '净利率': self.results['financial_health']['net_margin'],
            '流动比率': self.results['financial_health']['current_ratio']
        }
        names = list(metrics.keys())
        values = list(metrics.values())
        colors = [self._get_color(v * 40 if '比率' in n else v) for n, v in metrics.items()]
        
        bars = ax7.barh(names, values, color=colors)
        ax7.set_xlabel('数值')
        ax7.set_title('关键财务指标', fontsize=14, fontweight='bold')
        ax7.axvline(x=1, color='gray', linestyle='--', alpha=0.5)
        
        for bar, val in zip(bars, values):
            ax7.text(val + 0.05, bar.get_y() + bar.get_height()/2, 
                    f'{val:.2f}', va='center', fontsize=10)
        
        plt.tight_layout()
        return fig
    
    def _get_color(self, score: float) -> str:
        """根据评分获取颜色"""
        if score >= 80:
            return '#2ecc71'  # 绿色
        elif score >= 60:
            return '#3498db'  # 蓝色
        elif score >= 40:
            return '#f39c12'  # 橙色
        else:
            return '#e74c3c'  # 红色


# ============================================================================
# PyQt5 主应用类
# ============================================================================
class InvestmentApp(QMainWindow):
    """投资计算评估应用主窗口"""
    
    def __init__(self):
        super().__init__()
        self.calculator = InvestmentCalculator()
        self.charts = None
        self.init_ui()
        
    def init_ui(self):
        """初始化UI"""
        self.setWindowTitle('投资计算指标分析评估')
        self.setGeometry(100, 100, 1400, 900)
        
        # 创建菜单栏
        self.create_menu_bar()
        
        # 主布局
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        main_layout = QHBoxLayout(central_widget)
        
        # 左侧输入面板
        left_panel = self.create_input_panel()
        main_layout.addWidget(left_panel, 1)
        
        # 右侧结果显示
        right_panel = self.create_result_panel()
        main_layout.addWidget(right_panel, 2)
        
        # 状态栏
        self.statusBar().showMessage('就绪')
        
    def create_menu_bar(self):
        """创建菜单栏"""
        menubar = self.menuBar()
        
        # 文件菜单
        file_menu = menubar.addMenu('文件')
        
        new_action = QAction('新建项目', self)
        new_action.triggered.connect(self.new_project)
        file_menu.addAction(new_action)
        
        save_action = QAction('保存报告', self)
        save_action.triggered.connect(self.save_report)
        file_menu.addAction(save_action)
        
        export_action = QAction('导出图表', self)
        export_action.triggered.connect(self.export_charts)
        file_menu.addAction(export_action)
        
        file_menu.addSeparator()
        
        exit_action = QAction('退出', self)
        exit_action.triggered.connect(self.close)
        file_menu.addAction(exit_action)
        
        # 视图菜单
        view_menu = menubar.addMenu('视图')
        
        self.show_basic_action = QAction('基础数据', self, checkable=True)
        self.show_basic_action.setChecked(True)
        view_menu.addAction(self.show_basic_action)
        
        self.show_advanced_action = QAction('高级参数', self, checkable=True)
        self.show_advanced_action.setChecked(True)
        view_menu.addAction(self.show_advanced_action)
        
        # 帮助菜单
        help_menu = menubar.addMenu('帮助')
        
        about_action = QAction('关于', self)
        about_action.triggered.connect(self.show_about)
        help_menu.addAction(about_action)
        
    def create_input_panel(self) -> QWidget:
        """创建输入面板"""
        scroll = QScrollArea()
        scroll.setWidgetResizable(True)
        scroll.setMinimumWidth(400)
        
        container = QWidget()
        layout = QVBoxLayout(container)
        layout.setSpacing(15)
        
        # === 项目基本信息 ===
        basic_group = QGroupBox('基本信息')
        basic_layout = QGridLayout()
        
        basic_layout.addWidget(QLabel('项目名称:'), 0, 0)
        self.name_input = QLineEdit('店铺投资')
        basic_layout.addWidget(self.name_input, 0, 1)
        
        basic_layout.addWidget(QLabel('行业类型:'), 1, 0)
        self.industry_combo = QComboBox()
        self.industry_combo.addItems(list(IndustryBenchmarks.BENCHMARKS.keys()))
        self.industry_combo.currentTextChanged.connect(self.on_industry_changed)
        basic_layout.addWidget(self.industry_combo, 1, 1)
        
        basic_layout.addWidget(QLabel('备注:'), 2, 0)
        self.notes_input = QLineEdit()
        basic_layout.addWidget(self.notes_input, 2, 1)
        
        basic_group.setLayout(basic_layout)
        layout.addWidget(basic_group)
        
        # === 投资成本 ===
        investment_group = QGroupBox('投资成本')
        investment_layout = QGridLayout()
        
        investment_layout.addWidget(QLabel('转让费(元):'), 0, 0)
        self.transfer_fee = QSpinBox()
        self.transfer_fee.setRange(0, 10000000)
        self.transfer_fee.setValue(120000)
        self.transfer_fee.setSuffix(' 元')
        investment_layout.addWidget(self.transfer_fee, 0, 1)
        
        investment_layout.addWidget(QLabel('月租金(元):'), 1, 0)
        self.monthly_rent = QSpinBox()
        self.monthly_rent.setRange(0, 1000000)
        self.monthly_rent.setValue(2800)
        self.monthly_rent.setSuffix(' 元')
        investment_layout.addWidget(self.monthly_rent, 1, 1)
        
        investment_layout.addWidget(QLabel('押金月数:'), 2, 0)
        self.deposit_months = QSpinBox()
        self.deposit_months.setRange(0, 12)
        self.deposit_months.setValue(1)
        investment_layout.addWidget(self.deposit_months, 2, 1)
        
        investment_layout.addWidget(QLabel('预付月数:'), 3, 0)
        self.advance_months = QSpinBox()
        self.advance_months.setRange(0, 24)
        self.advance_months.setValue(2)
        investment_layout.addWidget(self.advance_months, 3, 1)
        
        investment_layout.addWidget(QLabel('装修费(元):'), 4, 0)
        self.renovation_cost = QSpinBox()
        self.renovation_cost.setRange(0, 5000000)
        self.renovation_cost.setValue(0)
        self.renovation_cost.setSuffix(' 元')
        investment_layout.addWidget(self.renovation_cost, 4, 1)
        
        investment_layout.addWidget(QLabel('设备采购(元):'), 5, 0)
        self.equipment_cost = QSpinBox()
        self.equipment_cost.setRange(0, 5000000)
        self.equipment_cost.setValue(0)
        self.equipment_cost.setSuffix(' 元')
        investment_layout.addWidget(self.equipment_cost, 5, 1)
        
        investment_layout.addWidget(QLabel('其他费用(元):'), 6, 0)
        self.other_costs = QSpinBox()
        self.other_costs.setRange(0, 1000000)
        self.other_costs.setValue(0)
        self.other_costs.setSuffix(' 元')
        investment_layout.addWidget(self.other_costs, 6, 1)
        
        investment_group.setLayout(investment_layout)
        layout.addWidget(investment_group)
        
        # === 收入预测 ===
        revenue_group = QGroupBox('收入预测')
        revenue_layout = QGridLayout()
        
        revenue_layout.addWidget(QLabel('日营业额(最低):'), 0, 0)
        self.daily_revenue_min = QSpinBox()
        self.daily_revenue_min.setRange(0, 100000)
        self.daily_revenue_min.setValue(2500)
        self.daily_revenue_min.setSuffix(' 元/天')
        revenue_layout.addWidget(self.daily_revenue_min, 0, 1)
        
        revenue_layout.addWidget(QLabel('日营业额(最高):'), 1, 0)
        self.daily_revenue_max = QSpinBox()
        self.daily_revenue_max.setRange(0, 100000)
        self.daily_revenue_max.setValue(2800)
        self.daily_revenue_max.setSuffix(' 元/天')
        revenue_layout.addWidget(self.daily_revenue_max, 1, 1)
        
        revenue_layout.addWidget(QLabel('月运营天数:'), 2, 0)
        self.operating_days = QSpinBox()
        self.operating_days.setRange(1, 31)
        self.operating_days.setValue(30)
        revenue_layout.addWidget(self.operating_days, 2, 1)
        
        revenue_layout.addWidget(QLabel('预期利润率(%):'), 3, 0)
        self.profit_rate = QDoubleSpinBox()
        self.profit_rate.setRange(0, 100)
        self.profit_rate.setValue(15)
        self.profit_rate.setSuffix(' %')
        revenue_layout.addWidget(self.profit_rate, 3, 1)
        
        revenue_layout.addWidget(QLabel('月增长率(%):'), 4, 0)
        self.growth_rate = QDoubleSpinBox()
        self.growth_rate.setRange(-50, 100)
        self.growth_rate.setValue(0)
        self.growth_rate.setSuffix(' %')
        revenue_layout.addWidget(self.growth_rate, 4, 1)
        
        revenue_group.setLayout(revenue_layout)
        layout.addWidget(revenue_group)
        
        # === 成本结构(输入具体金额)===
        cost_group = QGroupBox('成本结构(固定成本 - 按月实际金额输入)')
        cost_layout = QGridLayout()
        
        # 提示标签
        hint_label = QLabel('💡 固定成本说明:租金、人力、水电、其他为每月固定支出,物料/进货成本由系统根据目标利润率自动校核')
        hint_label.setStyleSheet('color: #666; font-size: 10px;')
        hint_label.setWordWrap(True)
        cost_layout.addWidget(hint_label, 0, 0, 1, 2)
        
        cost_layout.addWidget(QLabel('月租金(元):'), 1, 0)
        self.cost_rent = QSpinBox()
        self.cost_rent.setRange(0, 1000000)
        self.cost_rent.setValue(2800)
        self.cost_rent.setSuffix(' 元/月')
        cost_layout.addWidget(self.cost_rent, 1, 1)
        
        cost_layout.addWidget(QLabel('月人力成本(元):'), 2, 0)
        self.cost_labor = QSpinBox()
        self.cost_labor.setRange(0, 1000000)
        self.cost_labor.setValue(4000)
        self.cost_labor.setSuffix(' 元/月')
        cost_layout.addWidget(self.cost_labor, 2, 1)
        
        cost_layout.addWidget(QLabel('月食材/物料(元):'), 3, 0)
        self.cost_material = QSpinBox()
        self.cost_material.setRange(0, 1000000)
        self.cost_material.setValue(15000)
        self.cost_material.setSuffix(' 元/月')
        cost_layout.addWidget(self.cost_material, 3, 1)
        
        cost_layout.addWidget(QLabel('月水电费(元):'), 4, 0)
        self.cost_utilities = QSpinBox()
        self.cost_utilities.setRange(0, 100000)
        self.cost_utilities.setValue(700)
        self.cost_utilities.setSuffix(' 元/月')
        cost_layout.addWidget(self.cost_utilities, 4, 1)
        
        cost_layout.addWidget(QLabel('月其他费用(元):'), 5, 0)
        self.cost_other = QSpinBox()
        self.cost_other.setRange(0, 100000)
        self.cost_other.setValue(1000)
        self.cost_other.setSuffix(' 元/月')
        cost_layout.addWidget(self.cost_other, 5, 1)
        
        # 显示计算后的占比
        self.ratio_display = QLabel('成本占比将在计算后显示')
        self.ratio_display.setStyleSheet('color: #333; font-size: 11px; padding: 5px; background: #f5f5f5; border-radius: 3px;')
        self.ratio_display.setWordWrap(True)
        cost_layout.addWidget(self.ratio_display, 6, 0, 1, 2)
        
        # 允许成本提示
        self.allowed_cost_label = QLabel('允许成本将在计算后显示')
        self.allowed_cost_label.setStyleSheet('color: #e74c3c; font-size: 10px; padding: 3px; background: #fff3f3; border-radius: 3px;')
        self.allowed_cost_label.setWordWrap(True)
        cost_layout.addWidget(self.allowed_cost_label, 7, 0, 1, 2)
        
        cost_group.setLayout(cost_layout)
        layout.addWidget(cost_group)
        
        # === 运营参数 ===
        operation_group = QGroupBox('运营参数')
        operation_layout = QGridLayout()
        
        operation_layout.addWidget(QLabel('经营面积(㎡):'), 0, 0)
        self.area = QSpinBox()
        self.area.setRange(1, 10000)
        self.area.setValue(100)
        operation_layout.addWidget(self.area, 0, 1)
        
        operation_layout.addWidget(QLabel('员工数量:'), 1, 0)
        self.staff_count = QSpinBox()
        self.staff_count.setRange(1, 100)
        self.staff_count.setValue(2)
        operation_layout.addWidget(self.staff_count, 1, 1)
        
        operation_layout.addWidget(QLabel('座位数:'), 2, 0)
        self.seats = QSpinBox()
        self.seats.setRange(0, 1000)
        self.seats.setValue(20)
        operation_layout.addWidget(self.seats, 2, 1)
        
        operation_layout.addWidget(QLabel('日客流量:'), 3, 0)
        self.daily_customers = QSpinBox()
        self.daily_customers.setRange(0, 10000)
        self.daily_customers.setValue(50)
        operation_layout.addWidget(self.daily_customers, 3, 1)
        
        operation_group.setLayout(operation_layout)
        layout.addWidget(operation_group)
        
        # === 风险参数 ===
        risk_group = QGroupBox('风险参数(高级)')
        risk_layout = QGridLayout()
        
        risk_layout.addWidget(QLabel('无风险利率(%):'), 0, 0)
        self.risk_free_rate = QDoubleSpinBox()
        self.risk_free_rate.setRange(0, 20)
        self.risk_free_rate.setValue(2.5)
        self.risk_free_rate.setSuffix(' %')
        risk_layout.addWidget(self.risk_free_rate, 0, 1)
        
        risk_layout.addWidget(QLabel('收入波动率(%):'), 1, 0)
        self.revenue_volatility = QDoubleSpinBox()
        self.revenue_volatility.setRange(0, 100)
        self.revenue_volatility.setValue(10)
        self.revenue_volatility.setSuffix(' %')
        risk_layout.addWidget(self.revenue_volatility, 1, 1)
        
        risk_layout.addWidget(QLabel('市场贝塔:'), 2, 0)
        self.market_beta = QDoubleSpinBox()
        self.market_beta.setRange(0.1, 3)
        self.market_beta.setValue(1.0)
        self.market_beta.setSingleStep(0.1)
        risk_layout.addWidget(self.market_beta, 2, 1)
        
        risk_layout.addWidget(QLabel('行业贝塔:'), 3, 0)
        self.industry_beta = QDoubleSpinBox()
        self.industry_beta.setRange(0.1, 3)
        self.industry_beta.setValue(1.2)
        self.industry_beta.setSingleStep(0.1)
        risk_layout.addWidget(self.industry_beta, 3, 1)
        
        risk_group.setLayout(risk_layout)
        layout.addWidget(risk_group)
        
        # === 计算按钮 ===
        calc_button = QPushButton('开始计算评估')
        calc_button.setMinimumHeight(50)
        calc_button.setStyleSheet('''
            QPushButton {
                background-color: #3498db;
                color: white;
                border-radius: 8px;
                font-size: 16px;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #2980b9;
            }
        ''')
        calc_button.clicked.connect(self.calculate)
        layout.addWidget(calc_button)
        
        layout.addStretch()
        
        scroll.setWidget(container)
        return scroll
    
    def create_result_panel(self) -> QWidget:
        """创建结果面板"""
        container = QWidget()
        layout = QVBoxLayout(container)
        
        # 标签页
        self.tabs = QTabWidget()
        
        # 概览标签
        self.overview_tab = self.create_overview_tab()
        self.tabs.addTab(self.overview_tab, '评估概览')
        
        # 回本分析标签
        self.breakeven_tab = self.create_breakeven_tab()
        self.tabs.addTab(self.breakeven_tab, '回本周期分析')
        
        # 指标分析标签
        self.metrics_tab = self.create_metrics_tab()
        self.tabs.addTab(self.metrics_tab, '专业指标')
        
        # 图表标签
        self.chart_tab = self.create_chart_tab()
        self.tabs.addTab(self.chart_tab, '可视化图表')
        
        # 详细报告标签
        self.report_tab = self.create_report_tab()
        self.tabs.addTab(self.report_tab, '详细报告')
        
        layout.addWidget(self.tabs)
        
        return container
    
    def create_overview_tab(self) -> QWidget:
        """创建概览标签页"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        
        # 投资评级卡片
        self.rating_card = self.create_metric_card('投资评级', 'A', '#2ecc71')
        layout.addWidget(self.rating_card)
        
        # 关键指标网格
        grid = QGridLayout()
        
        self.breakeven_card = self.create_metric_card('回本周期', '--- 天', '#3498db')
        grid.addWidget(self.breakeven_card, 0, 0)
        
        self.roi_card = self.create_metric_card('年化ROI', '--- %', '#9b59b6')
        grid.addWidget(self.roi_card, 0, 1)
        
        self.sharpe_card = self.create_metric_card('夏普比率', '---', '#e67e22')
        grid.addWidget(self.sharpe_card, 1, 0)
        
        self.profit_card = self.create_metric_card('月利润', '--- 元', '#1abc9c')
        grid.addWidget(self.profit_card, 1, 1)
        
        layout.addLayout(grid)
        
        # 初步评估结果
        self.overview_text = QTextEdit()
        self.overview_text.setReadOnly(True)
        self.overview_text.setPlaceholderText('点击"开始计算评估"查看结果...')
        layout.addWidget(self.overview_text)
        
        return widget
    
    def create_metric_card(self, title: str, value: str, color: str) -> QWidget:
        """创建指标卡片"""
        card = QFrame()
        card.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
        card.setStyleSheet(f'''
            QFrame {{
                border: 2px solid {color};
                border-radius: 10px;
                background-color: white;
            }}
        ''')
        
        layout = QVBoxLayout(card)
        layout.setContentsMargins(15, 10, 15, 10)
        
        title_label = QLabel(title)
        title_label.setStyleSheet('color: #666; font-size: 12px;')
        title_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(title_label)
        
        value_label = QLabel(value)
        value_label.setObjectName('valueLabel')
        value_label.setStyleSheet(f'color: {color}; font-size: 28px; font-weight: bold;')
        value_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(value_label)
        
        return card
    
    def create_breakeven_tab(self) -> QWidget:
        """创建回本周期标签页"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        
        # 回本周期图表
        self.breakeven_canvas = FigureCanvas(Figure(figsize=(10, 6)))
        layout.addWidget(self.breakeven_canvas)
        
        # 详细数据表
        self.breakeven_table = QTableWidget()
        self.breakeven_table.setColumnCount(4)
        self.breakeven_table.setHorizontalHeaderLabels(['指标', '实际值', '行业基准', '评估'])
        self.breakeven_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        layout.addWidget(self.breakeven_table)
        
        return widget
    
    def create_metrics_tab(self) -> QWidget:
        """创建专业指标标签页"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        
        # 指标表格
        self.metrics_table = QTableWidget()
        self.metrics_table.setColumnCount(4)
        self.metrics_table.setHorizontalHeaderLabels(['指标类别', '指标名称', '数值', '评估'])
        self.metrics_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        layout.addWidget(self.metrics_table)
        
        return widget
    
    def create_chart_tab(self) -> QWidget:
        """创建图表标签页"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        
        # 图表类型选择
        chart_selector = QHBoxLayout()
        chart_selector.addWidget(QLabel('图表类型:'))
        
        self.chart_type_combo = QComboBox()
        self.chart_type_combo.addItems([
            '投资仪表盘',
            '成本结构分析',
            '月度预测',
            '多维度雷达图'
        ])
        chart_selector.addWidget(self.chart_type_combo)
        chart_selector.addStretch()
        
        self.chart_type_combo.currentIndexChanged.connect(self.update_chart)
        
        layout.addLayout(chart_selector)
        
        # 图表画布
        self.chart_canvas = FigureCanvas(Figure(figsize=(12, 8)))
        layout.addWidget(self.chart_canvas)
        
        return widget
    
    def create_report_tab(self) -> QWidget:
        """创建详细报告标签页"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        
        # 报告文本
        self.report_text = QTextEdit()
        self.report_text.setReadOnly(True)
        layout.addWidget(self.report_text)
        
        return widget
    
    def on_industry_changed(self, industry: str):
        """行业变化时更新成本默认值"""
        benchmark = IndustryBenchmarks.get_benchmark(industry)
        
        # 获取当前月收入估算
        daily_avg = (self.daily_revenue_min.value() + self.daily_revenue_max.value()) / 2
        monthly_revenue = daily_avg * self.operating_days.value()
        
        # 使用租金输入框的值
        monthly_rent_actual = self.monthly_rent.value()
        
        # 根据行业基准比例估算成本(保持合理的总成本占比)
        rent_ratio_avg = sum(benchmark.get('rent_ratio', (12, 18))) / 200
        labor_ratio_avg = sum(benchmark.get('labor_cost_ratio', (18, 22))) / 200
        material_ratio_avg = sum(benchmark.get('material_ratio', (30, 35))) / 200
        utilities_ratio_avg = 0.03  # 水电约3%
        other_ratio_avg = 0.05  # 其他约5%
        
        # 总成本占比(1 - 目标利润率)
        target_profit_rate = 0.15  # 15%目标利润率
        total_cost_ratio = 1 - target_profit_rate  # 85%
        
        # 更新成本输入框
        self.cost_rent.setValue(monthly_rent_actual)
        self.cost_labor.setValue(max(2000, int(monthly_revenue * labor_ratio_avg * total_cost_ratio)))
        self.cost_material.setValue(max(3000, int(monthly_revenue * material_ratio_avg * total_cost_ratio)))
        self.cost_utilities.setValue(max(300, int(monthly_revenue * utilities_ratio_avg * total_cost_ratio)))
        self.cost_other.setValue(max(500, int(monthly_revenue * other_ratio_avg * total_cost_ratio)))
    
    def collect_input_data(self) -> Dict:
        """收集输入数据"""
        return {
            'name': self.name_input.text(),
            'industry': self.industry_combo.currentText(),
            'notes': self.notes_input.text(),
            'transfer_fee': self.transfer_fee.value(),
            'monthly_rent': self.monthly_rent.value(),
            'deposit_months': self.deposit_months.value(),
            'advance_months': self.advance_months.value(),
            'renovation_cost': self.renovation_cost.value(),
            'equipment_cost': self.equipment_cost.value(),
            'other_costs': self.other_costs.value(),
            'daily_revenue_min': self.daily_revenue_min.value(),
            'daily_revenue_max': self.daily_revenue_max.value(),
            'operating_days': self.operating_days.value(),
            'profit_rate': self.profit_rate.value() / 100,
            'growth_rate': self.growth_rate.value() / 100,
            # 成本结构 - 实际金额
            'cost_rent': self.cost_rent.value(),
            'cost_labor': self.cost_labor.value(),
            'cost_material': self.cost_material.value(),
            'cost_utilities': self.cost_utilities.value(),
            'cost_other': self.cost_other.value(),
            # 以下保留百分比计算
            'rent_ratio': self.cost_rent.value() / 100,
            'labor_ratio': self.cost_labor.value() / 100,
            'material_ratio': self.cost_material.value() / 100,
            'utilities_ratio': self.cost_utilities.value() / 100,
            'other_ratio': self.cost_other.value() / 100,
            'area': self.area.value(),
            'staff_count': self.staff_count.value(),
            'seats': self.seats.value(),
            'daily_customers': self.daily_customers.value(),
            'risk_free_rate': self.risk_free_rate.value() / 100,
            'daily_revenue_volatility': self.revenue_volatility.value() / 100,
            'market_beta': self.market_beta.value(),
            'industry_beta': self.industry_beta.value(),
        }
    
    def calculate(self):
        """执行计算"""
        self.statusBar().showMessage('正在计算...')
        QApplication.processEvents()  # 刷新界面
        
        try:
            # 收集数据
            data = self.collect_input_data()
            self.calculator.set_data(data)
            
            # 执行计算
            results = self.calculator.generate_full_report()
            self.results = results
            
            # 检查数据合理性
            self.check_data_reasonable(results)
            
            # 创建图表对象
            self.charts = InvestmentCharts(data, results)
            
            # 更新UI
            self.update_overview(results)
            self.update_breakeven(results)
            self.update_metrics(results)
            self.update_chart(0)
            self.update_report(results)
            
            # 更新成本占比显示
            costs = results['costs']
            target_rate = data['profit_rate'] * 100
            actual_profit_rate = costs['profit_rate'] * 100
            profit_diff = costs['profit_diff']
            
            self.ratio_display.setText(
                f"成本占比: 租金{costs['rent_ratio']*100:.1f}% | "
                f"人力{costs['labor_ratio']*100:.1f}% | "
                f"进货{costs['material_ratio']*100:.1f}% | "
                f"水电{costs['utilities_ratio']*100:.1f}% | "
                f"其他{costs['other_ratio']*100:.1f}%"
            )
            
            # 真实反映实际利润率与目标的关系
            if profit_diff >= 0:
                self.allowed_cost_label.setText(
                    f"✓ 实际利润率: {actual_profit_rate:.1f}% (超出目标 {target_rate:.0f}% {profit_diff:,.0f}元)"
                )
                self.allowed_cost_label.setStyleSheet('color: #27ae60; font-size: 10px; padding: 3px; background: #eafaf1; border-radius: 3px;')
            else:
                self.allowed_cost_label.setText(
                    f"实际利润率: {actual_profit_rate:.1f}% (低于目标 {target_rate:.0f}% {profit_diff:,.0f}元)"
                )
                self.allowed_cost_label.setStyleSheet('color: #e74c3c; font-size: 10px; padding: 3px; background: #fff3f3; border-radius: 3px;')
            
            self.statusBar().showMessage('计算完成', 3000)
            
        except Exception as e:
            import traceback
            QMessageBox.critical(self, '错误', f'计算过程出错:\n{str(e)}\n\n{traceback.format_exc()}')
            self.statusBar().showMessage('计算失败', 3000)
    
    def check_data_reasonable(self, results: Dict):
        """数据合理性提醒 - 仅供参考"""
        costs = results['costs']
        revenue = results['revenue']
        break_even = results['break_even']
        
        # 仅作为信息提示,不阻碍计算
        info_messages = []
        
        # 盈亏提示
        if costs['monthly_profit'] < 0:
            info_messages.append(f"📉 当前配置为亏损状态:月亏损 {-costs['monthly_profit']:,.0f} 元")
        else:
            info_messages.append(f"📈 当前配置为盈利状态:月盈利 {costs['monthly_profit']:,.0f} 元")
        
        # 回本周期提醒
        if break_even['break_even_days'] > 365 * 5:
            info_messages.append(f"⚠️ 回本周期超过5年,需长期经营才有回报")
        elif break_even['break_even_days'] == float('inf'):
            info_messages.append(f"⚠️ 项目处于持续亏损状态,无法回本")
        
        # 成本结构提示(与行业对比)
        industry = self.calculator.data.get('industry', '餐饮')
        benchmark = IndustryBenchmarks.get_benchmark(industry)
        
        material_ratio = costs['material_ratio'] * 100
        material_benchmark = benchmark.get('material_ratio', (30, 35))
        if material_ratio > material_benchmark[1]:
            info_messages.append(f"📊 物料/进货成本占比({material_ratio:.1f}%)高于行业参考上限({material_benchmark[1]}%)")
        elif material_ratio < material_benchmark[0] * 0.5 and material_ratio > 0:
            info_messages.append(f"📊 物料/进货成本占比({material_ratio:.1f}%)低于行业参考下限({material_benchmark[0]}%)")
        
        if info_messages:
            msg = "以下是数据参考信息(非错误):\n\n" + "\n".join(info_messages)
            QMessageBox.information(self, '数据参考信息', msg)
    
    def update_overview(self, results: Dict):
        """更新概览"""
        portfolio = results['portfolio_metrics']
        break_even = results['break_even']
        
        # 更新评级卡片
        rating_label = self.rating_card.findChild(QLabel, 'valueLabel')
        rating_label.setText(portfolio['rating'])
        rating_label.setStyleSheet(f'color: {self._get_color(portfolio["overall_score"])}; font-size: 28px; font-weight: bold;')
        
        # 更新指标卡片
        self._update_card(self.breakeven_card, f'{break_even["break_even_days"]:.0f} 天')
        self._update_card(self.roi_card, f'{break_even["roi"]:.1f} %')
        self._update_card(self.sharpe_card, f'{results["risk_adjusted"]["sharpe_ratio"]:.2f}')
        self._update_card(self.profit_card, f'{break_even["monthly_profit"]:,.0f} 元')
        
        # 更新概览文本
        costs = results['costs']
        revenue = results['revenue']
        target_rate = self.calculator.data.get('profit_rate', 0.15) * 100
        actual_rate = costs['profit_rate'] * 100
        profit_status = "盈利" if costs['monthly_profit'] >= 0 else "亏损"
        profit_color = "#27ae60" if costs['monthly_profit'] >= 0 else "#e74c3c"
        
        overview = f"""
<h2>投资评估概览</h2>
<p><b>项目名称:</b> {self.calculator.data.get('name', '店铺投资')}</p>
<p><b>行业类型:</b> {IndustryBenchmarks.get_benchmark(self.calculator.data.get('industry', '自定义'))['name']}</p>

<h3>核心结论</h3>
<p><b>投资评级:</b> <span style="color: {self._get_color(portfolio['overall_score'])}">{portfolio['rating']}</span> - {portfolio['recommendation']}</p>
<p><b>综合评分:</b> {portfolio['overall_score']:.1f}/100</p>

<h3>📊 盈亏计算(如实计算)</h3>
<table style="width:100%; border-collapse: collapse;">
<tr style="background: #e8f5e9;"><td><b>月营业额(平均)</b></td><td>{revenue['monthly_revenue_avg']:,.0f} 元</td><td>({revenue['daily_revenue_avg']:.0f}元/天 × 30天)</td></tr>
<tr style="background: #f8f9fa;"><td>月租金</td><td>{costs['monthly_rent']:,.0f} 元</td><td>{costs['rent_ratio']*100:.1f}%</td></tr>
<tr style="background: #f8f9fa;"><td>月人力成本</td><td>{costs['monthly_labor']:,.0f} 元</td><td>{costs['labor_ratio']*100:.1f}%</td></tr>
<tr style="background: #f8f9fa;"><td>月进货/物料成本</td><td>{costs['monthly_material']:,.0f} 元</td><td>{costs['material_ratio']*100:.1f}%</td></tr>
<tr style="background: #f8f9fa;"><td>月水电费</td><td>{costs['monthly_utilities']:,.0f} 元</td><td>{costs['utilities_ratio']*100:.1f}%</td></tr>
<tr style="background: #f8f9fa;"><td>月其他费用</td><td>{costs['monthly_other']:,.0f} 元</td><td>{costs['other_ratio']*100:.1f}%</td></tr>
<tr style="background: #fce4ec;"><td><b>月总成本</b></td><td><b>{costs['monthly_total_cost']:,.0f} 元</b></td><td>{costs['rent_ratio']*100+costs['labor_ratio']*100+costs['material_ratio']*100+costs['utilities_ratio']*100+costs['other_ratio']*100:.1f}%</td></tr>
<tr style="background: #e3f2fd;"><td><b>月净利润</b></td><td><b style="color: {profit_color}">{break_even['monthly_profit']:,.0f} 元</b></td><td><b style="color: {profit_color}">{actual_rate:.1f}%</b> ({profit_status})</td></tr>
</table>

<h3>💡 与目标利润率对比</h3>
<table style="width:100%; border-collapse: collapse;">
<tr><td><b>目标利润率</b></td><td>{target_rate:.0f}%</td><td>目标月利润: {costs['target_profit']:,.0f} 元</td></tr>
<tr><td><b>实际利润率</b></td><td>{actual_rate:.1f}%</td><td>实际月利润: {break_even['monthly_profit']:,.0f} 元</td></tr>
<tr><td><b>差额</b></td><td colspan="2" style="color: {profit_color}">
    {'+' if costs['profit_diff'] >= 0 else ''}{costs['profit_diff']:,.0f} 元 
    ({'超出目标' if costs['profit_diff'] >= 0 else '低于目标'})
</td></tr>
</table>

<h3>关键指标摘要</h3>
<table style="width:100%">
<tr><td><b>回本周期:</b></td><td>{break_even['break_even_days']:.0f}天 ({break_even['break_even_months']:.1f}个月)</td></tr>
<tr><td><b>年化ROI:</b></td><td>{break_even['roi']:.1f}%</td></tr>
<tr><td><b>总投入:</b></td><td>{break_even['total_investment']:,.0f}元</td></tr>
</table>

<h3>风险评估</h3>
<p><b>夏普比率:</b> {results['risk_adjusted']['sharpe_ratio']:.2f} ({results['risk_adjusted']['sharpe_assessment']['level']})</p>
<p><b>索提诺比率:</b> {results['risk_adjusted']['sortino_ratio']:.2f} ({results['risk_adjusted']['sortino_assessment']['level']})</p>
<p><b>特雷诺比率:</b> {results['risk_adjusted']['treynor_ratio']:.2f} ({results['risk_adjusted']['treynor_assessment']['level']})</p>

<h3>现金流评估</h3>
<p><b>现金流质量:</b> {results['cashflow_quality']['quality_assessment']['level']}</p>
<p><b>现金流/利润比:</b> {results['cashflow_quality']['cf_to_income_ratio']:.2f}</p>

<h3>专业建议</h3>
<p>{break_even['payback_quality']['suggestion']}</p>
<p>{results['cashflow_quality']['quality_assessment']['suggestion']}</p>
<p>{portfolio['correlation_suggestion']['suggestion']}</p>
"""
        self.overview_text.setHtml(overview)
    
    def _update_card(self, card: QFrame, value: str):
        """更新指标卡片"""
        value_label = card.findChild(QLabel, 'valueLabel')
        if value_label:
            value_label.setText(value)
    
    def _get_color(self, score: float) -> str:
        """根据评分获取颜色"""
        if score >= 80:
            return '#2ecc71'
        elif score >= 60:
            return '#3498db'
        elif score >= 40:
            return '#f39c12'
        else:
            return '#e74c3c'
    
    def update_breakeven(self, results: Dict):
        """更新回本周期标签页"""
        # 更新图表
        self.breakeven_canvas.figure.clear()
        fig = self.charts.create_break_even_chart()
        self.breakeven_canvas.figure = fig
        self.breakeven_canvas.draw()
        
        # 更新表格
        break_even = results['break_even']
        investment = results['initial_investment']
        industry = self.calculator.data.get('industry', '自定义')
        benchmark = IndustryBenchmarks.get_benchmark(industry)
        
        self.breakeven_table.setRowCount(6)
        data = [
            ('总初始投入', f'{investment["total_investment"]:,.0f} 元', '-', '需回收'),
            ('月利润', f'{break_even["monthly_profit"]:,.0f} 元', '-', '持续盈利'),
            ('回本周期', f'{break_even["break_even_days"]:.0f} 天', f'{benchmark["break_even_optimal"][0]}-{benchmark["break_even_optimal"][1]}个月', break_even['payback_quality']['quality']),
            ('年化ROI', f'{break_even["roi"]:.1f} %', '25%-50%', '优质' if break_even['roi'] >= 25 else '一般'),
            ('3年总回报', f'{break_even["annual_profit"]*3 - investment["total_investment"]:,.0f} 元', '-', '长期价值'),
            ('投资回收期', f'{break_even["break_even_months"]:.1f} 个月', f'{benchmark["break_even_risky"]}个月风险线', '安全' if break_even['break_even_months'] <= benchmark['break_even_risky'] else '风险'),
        ]
        
        for i, (name, value, benchmark_val, assessment) in enumerate(data):
            self.breakeven_table.setItem(i, 0, QTableWidgetItem(name))
            self.breakeven_table.setItem(i, 1, QTableWidgetItem(value))
            self.breakeven_table.setItem(i, 2, QTableWidgetItem(benchmark_val))
            self.breakeven_table.setItem(i, 3, QTableWidgetItem(assessment))
    
    def update_metrics(self, results: Dict):
        """更新专业指标标签页"""
        risk = results['risk_adjusted']
        cashflow = results['cashflow_quality']
        financial = results['financial_health']
        operation = results['operational_efficiency']
        
        # 设置行数
        self.metrics_table.setRowCount(18)
        
        data = [
            # 风险调整收益指标
            ('风险调整收益', '夏普比率', f'{risk["sharpe_ratio"]:.3f}', risk['sharpe_assessment']['level']),
            ('', '索提诺比率', f'{risk["sortino_ratio"]:.3f}', risk['sortino_assessment']['level']),
            ('', '特雷诺比率', f'{risk["treynor_ratio"]:.3f}', risk['treynor_assessment']['level']),
            ('', '年化波动率', f'{risk["annual_volatility"]*100:.1f}%', '-' if risk['annual_volatility'] < 0.15 else '注意'),
            ('', '贝塔系数', f'{risk["beta"]:.2f}', '-' if risk['beta'] <= 1.2 else '偏高'),
            
            # 现金流质量指标
            ('现金流质量', '经营现金流/利润', f'{cashflow["cf_to_income_ratio"]:.2f}', cashflow['quality_assessment']['level']),
            ('', '自由现金流', f'{cashflow["free_cashflow"]:,.0f}元', '正数' if cashflow['free_cashflow'] > 0 else '负数'),
            ('', '现金流稳定性', f'{cashflow["stability_assessment"]["volatility"]*100:.0f}%', cashflow['stability_assessment']['level']),
            
            # 财务健康度指标
            ('财务健康度', '毛利率', f'{financial["gross_margin"]:.1f}%', financial['gross_margin_assessment']['level']),
            ('', '净利率', f'{financial["net_margin"]:.1f}%', financial['net_margin_assessment']['level']),
            ('', '资产负债率', f'{financial["debt_ratio"]:.1f}%', financial['debt_ratio_assessment']['level']),
            ('', '流动比率', f'{financial["current_ratio"]:.2f}', financial['current_ratio_assessment']['level']),
            
            # 运营效率指标
            ('运营效率', '坪效', f'{operation["efficiency_per_sqm"]:,.0f}元/㎡', operation['sqm_efficiency_assessment']['level']),
            ('', '人效', f'{operation["efficiency_per_person"]:,.0f}元/人', operation['person_efficiency_assessment']['level']),
            ('', '存货周转天数', f'{operation["inventory_days"]:.0f}天', operation['inventory_assessment']['level']),
            ('', '翻台率', f'{operation["turnover_rate"]:.1f}次', operation['turnover_assessment']['level']),
            ('', '客单价', f'{operation["avg_customer_value"]:.0f}元', '-'),
        ]
        
        for i, (category, name, value, assessment) in enumerate(data):
            self.metrics_table.setItem(i, 0, QTableWidgetItem(category))
            self.metrics_table.setItem(i, 1, QTableWidgetItem(name))
            self.metrics_table.setItem(i, 2, QTableWidgetItem(value))
            self.metrics_table.setItem(i, 3, QTableWidgetItem(assessment))
    
    def update_chart(self, index: int):
        """更新图表"""
        if not self.charts:
            return
        
        self.chart_canvas.figure.clear()
        
        chart_types = {
            0: self.charts.create_metrics_dashboard,
            1: self.charts.create_cost_structure_chart,
            2: self.charts.create_monthly_projection_chart,
            3: self.charts.create_radar_chart,
        }
        
        fig = chart_types.get(index, self.charts.create_metrics_dashboard)()
        self.chart_canvas.figure = fig
        self.chart_canvas.draw()
    
    def update_report(self, results: Dict):
        """更新详细报告"""
        portfolio = results['portfolio_metrics']
        break_even = results['break_even']
        risk = results['risk_adjusted']
        cashflow = results['cashflow_quality']
        financial = results['financial_health']
        operation = results['operational_efficiency']
        investment = results['initial_investment']
        
        report = f"""
<h1>投资评估详细报告</h1>

<h2>一、项目基本信息</h2>
<p><b>项目名称:</b> {self.calculator.data.get('name', '店铺投资')}</p>
<p><b>行业类型:</b> {IndustryBenchmarks.get_benchmark(self.calculator.data.get('industry', '自定义'))['name']}</p>
<p><b>评估时间:</b> {datetime.now().strftime('%Y-%m-%d %H:%M')}</p>

<h2>二、投资成本明细</h2>
<table style="width:100%">
<tr><td>转让费</td><td>{investment['investment_breakdown']['转让费']:,.0f} 元</td></tr>
<tr><td>首期租金</td><td>{investment['investment_breakdown']['首期租金']:,.0f} 元</td></tr>
<tr><td>装修费</td><td>{investment['investment_breakdown']['装修费']:,.0f} 元</td></tr>
<tr><td>设备费</td><td>{investment['investment_breakdown']['设备费']:,.0f} 元</td></tr>
<tr><td>其他费用</td><td>{investment['investment_breakdown']['其他费用']:,.0f} 元</td></tr>
<tr><td><b>总投资</b></td><td><b>{investment['total_investment']:,.0f} 元</b></td></tr>
</table>

<h2>三、回本周期分析</h2>
<p><b>回本周期:</b> {break_even['break_even_days']:.0f} 天 ({break_even['break_even_months']:.1f} 个月)</p>
<p><b>评估结果:</b> <span style="color:{self._get_color(break_even['payback_quality']['score'])}">{break_even['payback_quality']['quality']}</span></p>
<p><b>专业建议:</b> {break_even['payback_quality']['suggestion']}</p>
<p><b>年化ROI:</b> {break_even['roi']:.1f}%</p>
<p><b>3年总回报:</b> {break_even['annual_profit']*3 - investment['total_investment']:,.0f} 元</p>

<h2>四、风险调整后收益指标</h2>
<table style="width:100%">
<tr><td><b>夏普比率</b></td><td>{risk['sharpe_ratio']:.3f}</td><td>{risk['sharpe_assessment']['suggestion']}</td></tr>
<tr><td><b>索提诺比率</b></td><td>{risk['sortino_ratio']:.3f}</td><td>{risk['sortino_assessment']['suggestion']}</td></tr>
<tr><td><b>特雷诺比率</b></td><td>{risk['treynor_ratio']:.3f}</td><td>{risk['treynor_assessment']['suggestion']}</td></tr>
<tr><td><b>年化波动率</b></td><td>{risk['annual_volatility']*100:.1f}%</td><td>-</td></tr>
<tr><td><b>贝塔系数</b></td><td>{risk['beta']:.2f}</td><td>-</td></tr>
</table>

<h2>五、现金流质量评估</h2>
<p><b>现金流/利润比:</b> {cashflow['cf_to_income_ratio']:.2f}</p>
<p><b>自由现金流:</b> {cashflow['free_cashflow']:,.0f} 元/月</p>
<p><b>质量评估:</b> <span style="color:{self._get_color(cashflow['quality_assessment']['score'])}">{cashflow['quality_assessment']['level']}</span></p>
<p><b>专业建议:</b> {cashflow['quality_assessment']['suggestion']}</p>

<h2>六、财务健康度</h2>
<table style="width:100%">
<tr><td><b>毛利率</b></td><td>{financial['gross_margin']:.1f}%</td><td>{financial['gross_margin_assessment']['level']}</td></tr>
<tr><td><b>净利率</b></td><td>{financial['net_margin']:.1f}%</td><td>{financial['net_margin_assessment']['level']}</td></tr>
<tr><td><b>资产负债率</b></td><td>{financial['debt_ratio']:.1f}%</td><td>{financial['debt_ratio_assessment']['level']}</td></tr>
<tr><td><b>流动比率</b></td><td>{financial['current_ratio']:.2f}</td><td>{financial['current_ratio_assessment']['level']}</td></tr>
</table>
<p><b>成本结构评估:</b> {financial['cost_structure_assessment']['suggestion']}</p>

<h2>七、运营效率指标</h2>
<table style="width:100%">
<tr><td><b>坪效</b></td><td>{operation['efficiency_per_sqm']:,.0f} 元/㎡/月</td><td>{operation['sqm_efficiency_assessment']['level']}</td></tr>
<tr><td><b>人效</b></td><td>{operation['efficiency_per_person']:,.0f} 元/人/月</td><td>{operation['person_efficiency_assessment']['level']}</td></tr>
<tr><td><b>存货周转天数</b></td><td>{operation['inventory_days']:.0f} 天</td><td>{operation['inventory_assessment']['level']}</td></tr>
</table>

<h2>八、综合投资评级</h2>
<p><b>投资评级:</b> <span style="font-size:24px;color:{self._get_color(portfolio['overall_score'])}">{portfolio['rating']}</span></p>
<p><b>综合评分:</b> {portfolio['overall_score']:.1f}/100</p>
<p><b>投资建议:</b> <span style="color:{self._get_color(portfolio['overall_score'])}">{portfolio['recommendation']}</span></p>

<h2>九、投资组合建议</h2>
<p>{portfolio['correlation_suggestion']['suggestion']}</p>
<p><b>建议组合规模:</b> {portfolio['correlation_suggestion']['ideal_portfolio_size']} 个不同项目</p>
<p><b>单项目最大占比:</b> {portfolio['correlation_suggestion']['max_concentration']}%</p>

<h2>十、专业投资者决策要点</h2>
<ol>
<li><b>回本周期验证:</b> 本项目{break_even['break_even_months']:.1f}个月{'符合' if break_even['break_even_months'] <= 18 else '超过'}行业优质标准(6-18个月)</li>
<li><b>风险收益比:</b> 夏普比率{risk['sharpe_ratio']:.2f},{'优秀' if risk['sharpe_ratio'] >= 1.2 else '良好' if risk['sharpe_ratio'] >= 0.8 else '一般'}</li>
<li><b>现金流质量:</b> 现金流转化率{cashflow['cf_to_income_ratio']:.0%},{'表明盈利可持续' if cashflow['cf_to_income_ratio'] >= 1 else '需关注回款质量'}</li>
<li><b>成本结构:</b> {'成本结构合理' if not financial['cost_structure_assessment']['issues'] else '存在成本异常: ' + '; '.join(financial['cost_structure_assessment']['issues'])}</li>
<li><b>3年总回报率:</b> {(break_even['annual_profit']*3 / investment['total_investment'])*100:.0f}%,{'优秀' if break_even['annual_profit']*3 >= investment['total_investment']*1.5 else '达到' if break_even['annual_profit']*3 >= investment['total_investment'] else '未达标'}专业投资者标准</li>
</ol>

<hr>
<p style="color:#666;text-align:center">本报告由投资计算评估系统自动生成,仅供参考</p>
"""
        self.report_text.setHtml(report)
    
    def new_project(self):
        """新建项目"""
        reply = QMessageBox.question(self, '确认', '确定要新建项目吗?当前未保存的数据将丢失。',
                                    QMessageBox.Yes | QMessageBox.No)
        if reply == QMessageBox.Yes:
            # 重置所有输入
            self.transfer_fee.setValue(120000)
            self.monthly_rent.setValue(2800)
            self.deposit_months.setValue(1)
            self.advance_months.setValue(2)
            self.daily_revenue_min.setValue(2500)
            self.daily_revenue_max.setValue(2800)
            self.profit_rate.setValue(15)
            self.statusBar().showMessage('已新建项目')
    
    def save_report(self):
        """保存报告"""
        if not hasattr(self, 'results'):
            QMessageBox.warning(self, '提示', '请先进行计算')
            return
        
        filename, _ = QFileDialog.getSaveFileName(self, '保存报告', 
                                                  f'投资评估报告_{datetime.now().strftime("%Y%m%d")}.html',
                                                  'HTML文件 (*.html)')
        if filename:
            try:
                with open(filename, 'w', encoding='utf-8') as f:
                    f.write(self.report_text.toHtml())
                QMessageBox.information(self, '成功', f'报告已保存至:\n{filename}')
            except Exception as e:
                QMessageBox.critical(self, '错误', f'保存失败:\n{str(e)}')
    
    def export_charts(self):
        """导出图表"""
        if not self.charts:
            QMessageBox.warning(self, '提示', '请先进行计算')
            return
        
        dirname = QFileDialog.getExistingDirectory(self, '选择保存目录')
        if dirname:
            try:
                charts_to_export = [
                    ('投资仪表盘', self.charts.create_metrics_dashboard),
                    ('成本结构', self.charts.create_cost_structure_chart),
                    ('月度预测', self.charts.create_monthly_projection_chart),
                    ('雷达图', self.charts.create_radar_chart),
                    ('回本周期', self.charts.create_break_even_chart),
                ]
                
                for name, func in charts_to_export:
                    fig = func()
                    fig.savefig(f'{dirname}/{name}_{datetime.now().strftime("%Y%m%d")}.png', 
                               dpi=150, bbox_inches='tight')
                    plt.close(fig)
                
                QMessageBox.information(self, '成功', f'图表已保存至:\n{dirname}')
            except Exception as e:
                QMessageBox.critical(self, '错误', f'导出失败:\n{str(e)}')
    
    def show_about(self):
        """关于"""
        QMessageBox.about(self, '关于', 
                         '<h3>投资计算评估系统 v2.0</h3>'
                         '<p>专业的投资评估工具</p>'
                         '<p>集成夏普比率、索提诺比率、特雷诺比率等专业指标</p>'
                         '<p>帮助投资者进行全面的项目评估</p>')


# ============================================================================
# 主程序入口
# ============================================================================
def main():
    app = QApplication(sys.argv)
    
    # 设置应用样式
    app.setStyle('Fusion')
    
    # 创建并显示主窗口
    window = InvestmentApp()
    window.show()
    
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

5. 总结

实现逻辑,其核心价值在于:

  1. 实体投资的量化金融化:它没有停留在"赚了多少钱",而是引入了标准差(波动率)、贝塔系数(系统风险)来评估实体店铺的稳定性。
  2. 基准化对比:内置了餐饮、零售等多个行业的基准数据库,使得评估结果不是孤立的数字,而是相对于行业水平的相对评分。
  3. 全维度视图:覆盖了从"生存(回本)"到"健康(现金流质量)"再到"效率(坪效/人效)"的完整闭环。
相关推荐
迷藏4942 小时前
**发散创新:Go语言中基于上下文的优雅错误处理机制设计与实战**在现代后端开发中,**错误处理**早已不是简单
java·开发语言·后端·python·golang
杰克尼2 小时前
知识点总结--day10(Spring-Cloud框架)
java·开发语言
okiseethenwhat2 小时前
Java 内部类详解
java·开发语言
枫叶丹42 小时前
【HarmonyOS 6.0】ArkUI 状态管理进阶:深入理解 @Consume 装饰器默认值特性
开发语言·华为·harmonyos
Chase_______2 小时前
【Python 基础】第4章:函数模块与包完全指南(函数/模块/包)
开发语言·python
众创岛2 小时前
测试失败时自动截图并附加到 Allure 报告
开发语言·python
Csvn2 小时前
条件判断与循环结构详解
python
maxmaxma2 小时前
ROS2机器人少年创客营:Python第二课
c++·python·机器人
智算菩萨2 小时前
【Tkinter】10 Tkinter Listbox 列表框控件深度解析:多选模式、滚动条联动与双向选择器实战
python·ai编程