import streamlit as st import pandas as pd from datetime import datetime from src.utils.visualization import create_revenue_profit_chart, create_return_chart from src.utils.excel_export import to_excel, generate_excel_filename def display_financial_analysis(income, balance, cashflow, ratio, symbol): """ Hiển thị tab phân tích tài chính Args: income: DataFrame chứa báo cáo kết quả kinh doanh balance: DataFrame chứa bảng cân đối kế toán cashflow: DataFrame chứa báo cáo lưu chuyển tiền tệ ratio: DataFrame chứa các chỉ số tài chính symbol: Mã cổ phiếu """ st.markdown('
', unsafe_allow_html=True) # Sidebar cho báo cáo tài chính period = st.selectbox("Chu kỳ báo cáo:", ["year", "quarter"], key="period") if all([income is not None, balance is not None, cashflow is not None, ratio is not None]): # Chỉ số tài chính quan trọng st.subheader("💎 Chỉ số Tài chính Quan trọng") # Xử lý MultiIndex columns try: # Lấy dữ liệu năm gần nhất if isinstance(ratio.columns, pd.MultiIndex): # Với MultiIndex columns year_col = ('Meta', 'Năm') latest_year = ratio[year_col].max() latest_ratio = ratio[ratio[year_col] == latest_year].iloc[0] col1, col2, col3, col4 = st.columns(4) with col1: try: pe = latest_ratio[('Chỉ tiêu định giá', 'P/E')] pb = latest_ratio[('Chỉ tiêu định giá', 'P/B')] except KeyError: pe = pb = 'N/A' st.markdown(f"""

Định giá

P/E: {f'{pe:.2f}' if pe != 'N/A' and pd.notna(pe) else 'N/A'}

P/B: {f'{pb:.2f}' if pb != 'N/A' and pd.notna(pb) else 'N/A'}

""", unsafe_allow_html=True) with col2: try: roe = latest_ratio[('Chỉ tiêu khả năng sinh lợi', 'ROE (%)')] roa = latest_ratio[('Chỉ tiêu khả năng sinh lợi', 'ROA (%)')] except KeyError: roe = roa = 'N/A' st.markdown(f"""

Sinh lời

ROE: {f'{roe:.2f}%' if roe != 'N/A' and pd.notna(roe) else 'N/A'}

ROA: {f'{roa:.2f}%' if roa != 'N/A' and pd.notna(roa) else 'N/A'}

""", unsafe_allow_html=True) with col3: try: current_ratio = latest_ratio[('Chỉ tiêu thanh khoản', 'Chỉ số thanh toán hiện thời')] debt_equity = latest_ratio[('Chỉ tiêu cơ cấu nguồn vốn', 'Nợ/VCSH')] except KeyError: current_ratio = debt_equity = 'N/A' st.markdown(f"""

Tài chính

Thanh khoản: {f'{current_ratio:.2f}' if current_ratio != 'N/A' and pd.notna(current_ratio) else 'N/A'}

Nợ/VCSH: {f'{debt_equity:.2f}' if debt_equity != 'N/A' and pd.notna(debt_equity) else 'N/A'}

""", unsafe_allow_html=True) with col4: try: eps = latest_ratio[('Chỉ tiêu định giá', 'EPS (VND)')] bvps = latest_ratio[('Chỉ tiêu định giá', 'BVPS (VND)')] except KeyError: eps = bvps = 'N/A' st.markdown(f"""

Trên cổ phiếu

EPS: {f'{eps:,.0f}' if eps != 'N/A' and pd.notna(eps) else 'N/A'}

BVPS: {f'{bvps:,.0f}' if bvps != 'N/A' and pd.notna(bvps) else 'N/A'}

""", unsafe_allow_html=True) else: # Với cột thường year_col = None for col in ratio.columns: if 'Năm' in str(col): year_col = col break if year_col: latest_year = ratio[year_col].max() latest_ratio = ratio[ratio[year_col] == latest_year].iloc[0] st.info("Dữ liệu tài chính có sẵn nhưng cấu trúc cột khác mong đợi. Vui lòng kiểm tra lại.") else: st.warning("Không tìm thấy cột năm trong dữ liệu.") except Exception as e: st.error(f"Lỗi khi hiển thị chỉ số tài chính: {str(e)}") st.write("Dữ liệu ratio có sẵn:", ratio.head()) # Biểu đồ xu hướng tài chính st.subheader("📈 Xu hướng Tài chính") col1, col2 = st.columns(2) with col1: # Biểu đồ doanh thu và lợi nhuận try: # Tìm cột năm trong income year_col_income = None if isinstance(income.columns, pd.MultiIndex): year_col_income = ('Meta', 'Năm') if ('Meta', 'Năm') in income.columns else None else: for col in income.columns: if 'Năm' in str(col): year_col_income = col break # Tìm cột doanh thu và lợi nhuận revenue_col = None profit_col = None for col in income.columns: if isinstance(col, tuple): if 'doanh thu' in str(col).lower() and 'tỷ đồng' in str(col).lower(): revenue_col = col elif 'lợi nhuận sau thuế' in str(col).lower() and 'tỷ đồng' in str(col).lower(): profit_col = col else: if 'Doanh thu (Tỷ đồng)' in str(col): revenue_col = col elif 'Lợi nhuận sau thuế của Cổ đông công ty mẹ (Tỷ đồng)' in str(col): profit_col = col if year_col_income and revenue_col and profit_col: fig_revenue = create_revenue_profit_chart(income, year_col_income, revenue_col, profit_col) st.plotly_chart(fig_revenue, use_container_width=True) else: st.warning("Không tìm thấy đủ dữ liệu để hiển thị biểu đồ doanh thu và lợi nhuận.") except Exception as e: st.error(f"Không thể hiển thị biểu đồ doanh thu: {str(e)}") with col2: # Biểu đồ ROE, ROA try: # Tìm cột năm và ROE/ROA trong ratio year_col_ratio = None roe_col = None roa_col = None if isinstance(ratio.columns, pd.MultiIndex): year_col_ratio = ('Meta', 'Năm') if ('Meta', 'Năm') in ratio.columns else None roe_col = ('Chỉ tiêu khả năng sinh lợi', 'ROE (%)') if ('Chỉ tiêu khả năng sinh lợi', 'ROE (%)') in ratio.columns else None roa_col = ('Chỉ tiêu khả năng sinh lợi', 'ROA (%)') if ('Chỉ tiêu khả năng sinh lợi', 'ROA (%)') in ratio.columns else None else: for col in ratio.columns: if 'Năm' in str(col): year_col_ratio = col if 'ROE' in str(col): roe_col = col if 'ROA' in str(col): roa_col = col if year_col_ratio and roe_col and roa_col: fig_return = create_return_chart(ratio, year_col_ratio, roe_col, roa_col) st.plotly_chart(fig_return, use_container_width=True) else: st.warning("Không tìm thấy đủ dữ liệu để hiển thị biểu đồ ROE/ROA.") except Exception as e: st.error(f"Không thể hiển thị biểu đồ ROE/ROA: {str(e)}") # Bảng tài chính chi tiết st.subheader("📋 Báo cáo Tài chính Chi tiết") financial_tab1, financial_tab2, financial_tab3, financial_tab4 = st.tabs( ["Kết quả KD", "Bảng cân đối", "Lưu chuyển tiền", "Chỉ số tài chính"] ) with financial_tab1: st.dataframe(income, use_container_width=True) with financial_tab2: st.dataframe(balance, use_container_width=True) with financial_tab3: st.dataframe(cashflow, use_container_width=True) with financial_tab4: st.dataframe(ratio, use_container_width=True) # Tải xuống Excel st.subheader("📥 Tải xuống Báo cáo") excel_data = to_excel( [income, balance, cashflow, ratio], ['Kết quả KD', 'Bảng cân đối', 'Lưu chuyển tiền', 'Chỉ số tài chính'] ) st.download_button( label="📊 Tải xuống báo cáo Excel", data=excel_data, file_name=generate_excel_filename(symbol), mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ) else: st.error("Không thể lấy dữ liệu tài chính. Vui lòng thử lại sau.") st.markdown('
', unsafe_allow_html=True)