import warnings warnings.simplefilter(action='ignore', category=FutureWarning) import streamlit as st import pandas as pd import numpy as np import plotly.graph_objs as go from vnstock import Vnstock, Listing st.set_page_config(page_title="Vietnam Stock Market Insight", layout="wide") st.title("📈 Vietnam Stock Market Insight") symbol = st.text_input("Nhập mã cổ phiếu (ví dụ: VNM, FPT, VCB):", value="GMD") col1, col2 = st.columns(2) with col1: start_date = st.date_input("Ngày bắt đầu", pd.to_datetime("2025-01-01")) with col2: end_date = st.date_input("Ngày kết thúc", pd.to_datetime("2025-12-31")) tab1, tab2, tab3 = st.tabs([ "📉 Phân tích kỹ thuật", "📊 Phân tích cơ bản", "🏢 Thông tin doanh nghiệp" ]) # TAB 1 - Phân tích kỹ thuật with tab1: if st.button("Phân tích kỹ thuật"): with st.spinner("Đang tải dữ liệu..."): try: stock = Vnstock().stock(symbol=symbol, source='VCI') df = stock.quote.history( start=start_date.strftime("%Y-%m-%d"), end=end_date.strftime("%Y-%m-%d"), interval='1D' ) df['date'] = pd.to_datetime(df['time']) df.set_index('date', inplace=True) df.sort_index(inplace=True) df['EMA12'] = df['close'].ewm(span=12, adjust=False).mean() df['EMA26'] = df['close'].ewm(span=26, adjust=False).mean() df['MACD'] = df['EMA12'] - df['EMA26'] df['MACD_Signal'] = df['MACD'].ewm(span=9, adjust=False).mean() df['BB_Middle'] = df['close'].rolling(window=20).mean() df['BB_Std'] = df['close'].rolling(window=20).std() df['BB_Upper'] = df['BB_Middle'] + (2 * df['BB_Std']) df['BB_Lower'] = df['BB_Middle'] - (2 * df['BB_Std']) delta = df['close'].diff() gain = delta.where(delta > 0, 0) loss = -delta.where(delta < 0, 0) avg_gain = gain.rolling(window=14).mean() avg_loss = loss.rolling(window=14).mean() rs = avg_gain / avg_loss df['RSI'] = 100 - (100 / (1 + rs)) st.subheader("📊 Dữ liệu giá cổ phiếu") st.dataframe(df[['open', 'high', 'low', 'close', 'volume']].dropna().tail(10)) st.subheader("📈 Bollinger Bands") fig_bb = go.Figure() fig_bb.add_trace(go.Scatter(x=df.index, y=df['close'], name='Close')) fig_bb.add_trace(go.Scatter(x=df.index, y=df['BB_Upper'], name='Upper Band')) fig_bb.add_trace(go.Scatter(x=df.index, y=df['BB_Lower'], name='Lower Band')) st.plotly_chart(fig_bb, use_container_width=True) st.subheader("📉 RSI") fig_rsi = go.Figure() fig_rsi.add_trace(go.Scatter(x=df.index, y=df['RSI'], name='RSI')) fig_rsi.update_layout(yaxis=dict(range=[0, 100])) st.plotly_chart(fig_rsi, use_container_width=True) st.subheader("📉 MACD") fig_macd = go.Figure() fig_macd.add_trace(go.Scatter(x=df.index, y=df['MACD'], name='MACD')) fig_macd.add_trace(go.Scatter(x=df.index, y=df['MACD_Signal'], name='Signal')) st.plotly_chart(fig_macd, use_container_width=True) except Exception as e: st.error(f"❌ Lỗi kỹ thuật: {e}") # TAB 2 - Phân tích cơ bản with tab2: if st.button("Phân tích cơ bản"): with st.spinner("Đang tải báo cáo tài chính..."): try: stock = Vnstock().stock(symbol=symbol, source='VCI') df_financial = stock.finance.income_statement(period='quarter', lang='vi', dropna=True) st.subheader("📊 Báo cáo tài chính quý") st.dataframe(df_financial) except Exception as e: st.error(f"❌ Lỗi dữ liệu tài chính: {e}") # TAB 3 - Thông tin doanh nghiệp đầy đủ with tab3: try: stock = Vnstock().stock(symbol=symbol, source='VCI') st.subheader(f"🏢 Tổng quan công ty: {symbol}") st.dataframe(stock.company.overview()) st.subheader("💰 Bảng cân đối kế toán") st.dataframe(stock.finance.balance_sheet()) st.subheader("💸 Báo cáo lưu chuyển tiền tệ") st.dataframe(stock.finance.cash_flow()) st.subheader("👥 Cổ đông lớn") st.dataframe(stock.company.shareholders()) st.subheader("🧑‍💼 Ban lãnh đạo (đang làm việc)") st.dataframe(stock.company.officers(filter_by="working")) st.subheader("📎 Tài liệu công bố") st.dataframe(stock.company.documents()) st.subheader("📋 Danh sách công ty niêm yết") listing = Listing() df_listing = listing.all_symbols() st.dataframe(df_listing) except Exception as e: st.error(f"❌ Lỗi khi lấy thông tin doanh nghiệp: {e}")