| def format_number_for_table(value): |
| """用于表格的数字格式化:自动 B/M,保留适当小数""" |
| if value is None or value == 0: |
| return "0" |
| if abs(value) >= 1_000_000_000: |
| num = value / 1_000_000_000 |
| if num.is_integer(): |
| return f"{int(num)}B" |
| else: |
| return f"{num:.2f}B".rstrip('0').rstrip('.') |
| elif abs(value) >= 1_000_000: |
| num = value / 1_000_000 |
| if num.is_integer(): |
| return f"{int(num)}M" |
| else: |
| return f"{num:.1f}M".rstrip('0').rstrip('.') |
| else: |
| return f"{value:,.1f}".rstrip('0').rstrip('.') |
|
|
| def safe_float_or_zero(val): |
| if val is None: |
| return 0.0 |
| try: |
| return float(val) |
| except (ValueError, TypeError): |
| return 0.0 |
|
|
| def calculate_yoy_rate(current, previous): |
| if previous == 0: |
| return "+0.0%" if current >= 0 else "-0.0%" |
| rate = (current - previous) / abs(previous) * 100 |
| sign = "+" if rate >= 0 else "-" |
| return f"{sign}{abs(rate):.1f}%" |
|
|
| def build_table_format(three_year_data): |
| |
| sorted_data = sorted(three_year_data, key=lambda x: x["fiscal_year"], reverse=True) |
| |
| |
| year_labels = [] |
| for item in sorted_data: |
| if item['level'] == 'FY': |
| year_labels.append(f"FY {item['fiscal_year']}") |
| else: |
| year_labels.append(f"{item['fiscal_year']} {item['level']}") |
| |
| |
| while len(sorted_data) < 3: |
| sorted_data.append({ |
| "fiscal_year": 0, |
| "level": "N/A", |
| "total_revenue": 0, |
| "net_income": 0, |
| "earnings_per_share": 0.0, |
| "operating_expenses": 0, |
| "operating_cash_flow": 0 |
| }) |
| year_labels.append("N/A") |
|
|
| |
| y0, y1, y2 = sorted_data[0], sorted_data[1], sorted_data[2] |
|
|
| |
| list_data = [ |
| ["Category"] + year_labels[:3], |
| ["Total Revenue", |
| format_number_for_table(safe_float_or_zero(y0["total_revenue"])), |
| format_number_for_table(safe_float_or_zero(y1["total_revenue"])), |
| format_number_for_table(safe_float_or_zero(y2["total_revenue"]))], |
| ["Net Income", |
| format_number_for_table(safe_float_or_zero(y0["net_income"])), |
| format_number_for_table(safe_float_or_zero(y1["net_income"])), |
| format_number_for_table(safe_float_or_zero(y2["net_income"]))], |
| ["Earnings Per Share", |
| f"{safe_float_or_zero(y0['earnings_per_share']):.2f}", |
| f"{safe_float_or_zero(y1['earnings_per_share']):.2f}", |
| f"{safe_float_or_zero(y2['earnings_per_share']):.2f}"], |
| ["Operating Expenses", |
| format_number_for_table(safe_float_or_zero(y0["operating_expenses"])), |
| format_number_for_table(safe_float_or_zero(y1["operating_expenses"])), |
| format_number_for_table(safe_float_or_zero(y2["operating_expenses"]))], |
| ["Operating Cash Flow", |
| format_number_for_table(safe_float_or_zero(y0["operating_cash_flow"])), |
| format_number_for_table(safe_float_or_zero(y1["operating_cash_flow"])), |
| format_number_for_table(safe_float_or_zero(y2["operating_cash_flow"]))] |
| ] |
|
|
| |
| |
| yoy_rates = [ |
| ["Category"] + year_labels[:3], |
| ["Total Revenue", |
| calculate_yoy_rate(safe_float_or_zero(y0["total_revenue"]), safe_float_or_zero(y1["total_revenue"])), |
| calculate_yoy_rate(safe_float_or_zero(y1["total_revenue"]), safe_float_or_zero(y2["total_revenue"])), |
| "--"], |
| ["Net Income", |
| calculate_yoy_rate(safe_float_or_zero(y0["net_income"]), safe_float_or_zero(y1["net_income"])), |
| calculate_yoy_rate(safe_float_or_zero(y1["net_income"]), safe_float_or_zero(y2["net_income"])), |
| "--"], |
| ["Earnings Per Share", |
| calculate_yoy_rate(safe_float_or_zero(y0["earnings_per_share"]), safe_float_or_zero(y1["earnings_per_share"])), |
| calculate_yoy_rate(safe_float_or_zero(y1["earnings_per_share"]), safe_float_or_zero(y2["earnings_per_share"])), |
| "--"], |
| ["Operating Expenses", |
| calculate_yoy_rate(safe_float_or_zero(y0["operating_expenses"]), safe_float_or_zero(y1["operating_expenses"])), |
| calculate_yoy_rate(safe_float_or_zero(y1["operating_expenses"]), safe_float_or_zero(y2["operating_expenses"])), |
| "--"], |
| ["Operating Cash Flow", |
| calculate_yoy_rate(safe_float_or_zero(y0["operating_cash_flow"]), safe_float_or_zero(y1["operating_cash_flow"])), |
| calculate_yoy_rate(safe_float_or_zero(y1["operating_cash_flow"]), safe_float_or_zero(y2["operating_cash_flow"])), |
| "--"] |
| ] |
|
|
| return { |
| "list_data": list_data, |
| "yoy_rates": yoy_rates |
| } |