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)