CoolFace
Apppublic

btmnngoc/dataexplorers2025dabaverse

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes
test.py346 linesDownload Raw Back to pages
1import streamlit as st2import pandas as pd3import numpy as np4import matplotlib.pyplot as plt5import plotly.graph_objects as go6from sklearn.preprocessing import MinMaxScaler7from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score8from tensorflow.keras.models import load_model9import xgboost as xgb10import joblib11import os12from datetime import datetime, timedelta13 14# Thiết lập trang Streamlit15st.set_page_config(16    page_title="Dự Báo Giá Cổ Phiếu FPT & CMG",17    page_icon="📈",18    layout="wide"19)20 21# Tiêu đề ứng dụng22st.title("📈 Hệ Thống Dự Báo Giá Cổ Phiếu FPT & CMG")23st.markdown("""24**Kết hợp phân tích kỹ thuật và cơ bản để dự báo giá cổ phiếu với đánh giá độ tin cậy**25""")26 27# Sidebar cho lựa chọn cổ phiếu và thông số28with st.sidebar:29    st.header("Cấu hình Dự Báo")30    stock_choice = st.selectbox("Chọn cổ phiếu", ["FPT", "CMG"])31    forecast_days = st.slider("Số ngày dự báo", 1, 30, 7)32    confidence_threshold = st.slider("Ngưỡng tin cậy tối thiểu (%)", 50, 95, 70)33    st.markdown("---")34    st.info("""35    Hệ thống sử dụng mô hình hybrid kết hợp:36    - LSTM cho phân tích chuỗi thời gian37    - XGBoost cho phân tích đặc trưng38    - Meta-model để kết hợp kết quả39    """)40 41# Hàm tải dữ liệu (giả lập - thay bằng dữ liệu thực tế của bạn)42@st.cache_data43def load_stock_data(stock_id):44    # Đây là phần giả lập - thay bằng code tải dữ liệu thực tế của bạn45    # Từ code gốc của bạn, bạn cần thay thế phần này với các file CSV thực tế46    47    # Tạo dữ liệu giả lập cho demo48    date_range = pd.date_range(end=datetime.today(), periods=365)49    prices = np.cumsum(np.random.normal(0.1, 2, 365)) + 10050    51    df = pd.DataFrame({52        'Date': date_range,53        'Closing Price': prices,54        'Total Volume': np.random.randint(100000, 500000, 365),55 56        'Volume_ratio': np.random.uniform(0.8, 1.2, 365),57        'Volatility': np.random.uniform(1, 5, 365),58        'Price_Momentum': np.random.normal(0, 2, 365),59        'Dividend_Event': np.random.choice([0, 1], 365, p=[0.95, 0.05]),60        'Meeting_Event': np.random.choice([0, 1], 365, p=[0.9, 0.1]),61        'ROE': np.random.uniform(10, 20, 365),62        'P/E': np.random.uniform(15, 25, 365),63        'EPS': np.random.uniform(5000, 8000, 365)64    })65    66    df['Return%'] = df['Closing Price'].pct_change() * 10067    df = df.fillna(0)68    69    return df70 71# Hàm tải mô hình72@st.cache_resource73def load_models(stock_id):74    # Trong thực tế, bạn cần thay bằng đường dẫn đến các model đã train75    # Đây chỉ là phần giả lập76    77    class DummyModel:78        def predict(self, X):79            return np.random.normal(0, 1, len(X))80    81    return {82        'lstm': DummyModel(),83        'xgb': DummyModel(),84        'meta': DummyModel()85    }86 87# Tải dữ liệu và mô hình88df = load_stock_data(stock_choice)89models = load_models(stock_choice)90 91# Tab chính92tab1, tab2, tab3 = st.tabs(["📊 Dữ Liệu & Phân Tích", "🔮 Dự Báo Giá", "📌 Đề Xuất Giao Dịch"])93 94with tab1:95    st.header(f"Phân Tích Cổ Phiếu {stock_choice}")96    97    col1, col2 = st.columns(2)98    99    with col1:100        st.subheader("Biểu Đồ Giá")101        fig = go.Figure()102        fig.add_trace(go.Scatter(x=df['Date'], y=df['Closing Price'], name='Giá đóng cửa', line=dict(color='blue')))103 104        fig.update_layout(height=400, xaxis_title='Ngày', yaxis_title='Giá')105        st.plotly_chart(fig, use_container_width=True)106    107    with col2:108        st.subheader("Chỉ Số Kỹ Thuật")109        110        # Tính RSI111        delta = df['Closing Price'].diff()112        gain = (delta.where(delta > 0, 0)).rolling(window=14).mean()113        loss = (-delta.where(delta < 0, 0)).rolling(window=14).mean()114        rs = gain / loss115        rsi = 100 - (100 / (1 + rs))116        117        # Tính MACD118        ema12 = df['Closing Price'].ewm(span=12, adjust=False).mean()119        ema26 = df['Closing Price'].ewm(span=26, adjust=False).mean()120        macd = ema12 - ema26121        signal = macd.ewm(span=9, adjust=False).mean()122        123        # Hiển thị các chỉ số124        st.metric("RSI (14 ngày)", f"{rsi.iloc[-1]:.2f}", 125                  "Mua quá" if rsi.iloc[-1] > 70 else "Bán quá" if rsi.iloc[-1] < 30 else "Bình thường")126        st.metric("MACD", f"{macd.iloc[-1]:.2f}", 127                  "Tăng" if macd.iloc[-1] > signal.iloc[-1] else "Giảm")128        st.metric("Khối lượng giao dịch", f"{df['Total Volume'].iloc[-1]:,.0f}")129        130        # Phân tích xu hướng131        trend = "Tăng" if df['Closing Price'].iloc[-1] > df['Closing Price'].iloc[-5] else "Giảm"132        st.metric("Xu hướng ngắn hạn", trend)133 134with tab2:135    st.header(f"Dự Báo Giá {stock_choice}")136    137    # Chuẩn bị dữ liệu cho dự báo (giả lập)138    lookback = 7139    last_data = df.iloc[-lookback:][['Closing Price']].values140    scaler = MinMaxScaler()141    scaled_data = scaler.fit_transform(last_data)142    143    # Tạo dự báo (giả lập)144    forecast_dates = [df['Date'].iloc[-1] + timedelta(days=i) for i in range(1, forecast_days+1)]145    forecast_prices = []146    confidence_scores = []147    148    for i in range(forecast_days):149        # Trong thực tế, bạn sẽ sử dụng model.predict()150        pred = df['Closing Price'].iloc[-1] * (1 + np.random.normal(0.001, 0.02))151        forecast_prices.append(pred)152        153        # Tính độ tin cậy giả lập (dựa trên độ biến động gần đây)154        recent_volatility = df['Volatility'].iloc[-10:].mean()155        confidence = max(50, 100 - recent_volatility * 5 + np.random.normal(10, 5))156        confidence_scores.append(confidence)157    158    # Hiển thị kết quả dự báo159    col1, col2 = st.columns(2)160    161    with col1:162        st.subheader("Biểu Đồ Dự Báo")163        164        fig = go.Figure()165        fig.add_trace(go.Scatter(166            x=df['Date'].iloc[-30:], 167            y=df['Closing Price'].iloc[-30:], 168            name='Giá lịch sử',169            line=dict(color='blue')170        ))171        fig.add_trace(go.Scatter(172            x=forecast_dates,173            y=forecast_prices,174            name='Dự báo',175            line=dict(color='red', dash='dot')176        ))177        178        # Thêm vùng độ tin cậy179        for i, (date, price, conf) in enumerate(zip(forecast_dates, forecast_prices, confidence_scores)):180            color = 'green' if conf >= confidence_threshold else 'orange' if conf >= 60 else 'red'181            fig.add_shape(type="line",182                x0=date, y0=price*0.98, x1=date, y1=price*1.02,183                line=dict(color=color, width=2)184            )185            if i % 3 == 0:  # Hiển thị nhãn cho một số ngày để tránh rối186                fig.add_annotation(x=date, y=price*1.03,187                    text=f"{conf:.0f}%",188                    showarrow=False,189                    font=dict(size=10, color=color)190                )191        192        fig.update_layout(193            height=500,194            title=f"Dự báo giá {stock_choice} trong {forecast_days} ngày tới",195            xaxis_title="Ngày",196            yaxis_title="Giá",197            showlegend=True198        )199        st.plotly_chart(fig, use_container_width=True)200    201    with col2:202        st.subheader("Chi Tiết Dự Báo")203        204        # Tạo bảng dự báo205        forecast_df = pd.DataFrame({206            'Ngày': forecast_dates,207            'Giá dự báo': forecast_prices,208            'Độ tin cậy (%)': confidence_scores,209            'Biến động (%)': [(p/df['Closing Price'].iloc[-1]-1)*100 for p in forecast_prices]210        })211        212        # Định dạng bảng213        forecast_df['Giá dự báo'] = forecast_df['Giá dự báo'].apply(lambda x: f"{x:,.0f}")214        forecast_df['Biến động (%)'] = forecast_df['Biến động (%)'].apply(lambda x: f"{x:+.2f}%")215        forecast_df['Độ tin cậy (%)'] = forecast_df['Độ tin cậy (%)'].apply(lambda x: f"{x:.0f}%")216        217        # Hiển thị bảng với màu sắc theo độ tin cậy218        def color_confidence(val):219            val = float(val.strip('%'))220            color = 'green' if val >= confidence_threshold else 'orange' if val >= 60 else 'red'221            return f'background-color: {color}; color: white'222        223        st.dataframe(224            forecast_df.style.applymap(color_confidence, subset=['Độ tin cậy (%)']),225            hide_index=True,226            use_container_width=True227        )228        229        # Thống kê dự báo230        avg_confidence = np.mean(confidence_scores)231        max_change = max([abs(float(x.strip('%'))) for x in forecast_df['Biến động (%)']])232        233        st.metric("Độ tin cậy trung bình", f"{avg_confidence:.1f}%")234        st.metric("Biến động tối đa dự kiến", f"{max_change:.2f}%")235        236        # Đánh giá tổng quan237        if avg_confidence >= confidence_threshold:238            st.success("✅ Dự báo có độ tin cậy cao, có thể cân nhắc sử dụng")239        elif avg_confidence >= 60:240            st.warning("⚠️ Dự báo có độ tin cậy trung bình, cần thận trọng")241        else:242            st.error("❌ Dự báo có độ tin cậy thấp, không nên sử dụng")243 244with tab3:245    st.header(f"Đề Xuất Giao Dịch {stock_choice}")246    247    # Phân tích kỹ thuật để đưa ra đề xuất248    current_price = df['Closing Price'].iloc[-1]249 250    rsi_value = rsi.iloc[-1] if 'rsi' in locals() else 50  # Sử dụng RSI đã tính ở tab1251    252    # Tạo đề xuất253    recommendation = "Giữ"254    confidence = 70255    reasoning = []256    257 258    259    if rsi_value < 30:260        recommendation = "Mua mạnh" if recommendation == "Mua" else "Mua"261        confidence = min(95, confidence + 15)262        reasoning.append("RSI dưới 30 - cổ phiếu bị bán quá mức")263    elif rsi_value > 70:264        recommendation = "Bán mạnh" if recommendation == "Bán" else "Bán"265        confidence = min(95, confidence + 15)266        reasoning.append("RSI trên 70 - cổ phiếu mua quá mức")267    268    # Xem xét các sự kiện công ty269    if df['Dividend_Event'].iloc[-5:].sum() > 0:270        reasoning.append("Có sự kiện cổ tức gần đây - thường tạo biến động giá")271    272    if df['Meeting_Event'].iloc[-5:].sum() > 0:273        reasoning.append("Có sự kiện họp cổ đông gần đây - cần theo dõi thông tin")274    275    # Hiển thị đề xuất276    col1, col2 = st.columns([1, 3])277    278    with col1:279        st.subheader("Khuyến Nghị")280        281        if recommendation.startswith("Mua"):282            st.success(f"### {recommendation}")283        elif recommendation.startswith("Bán"):284            st.error(f"### {recommendation}")285        else:286            st.info(f"### {recommendation}")287        288        st.metric("Độ tin cậy", f"{confidence}%")289        st.metric("Giá hiện tại", f"{current_price:,.0f}")290        291        # Điểm vào lệnh và cắt lỗ đề xuất292        if recommendation.startswith("Mua"):293            entry = current_price * 0.99294            stop_loss = current_price * 0.95295            take_profit = current_price * 1.08296        elif recommendation.startswith("Bán"):297            entry = current_price * 1.01298            stop_loss = current_price * 1.05299            take_profit = current_price * 0.92300        else:301            entry = current_price302            stop_loss = current_price * 0.97303            take_profit = current_price * 1.03304        305        st.metric("Điểm vào lệnh", f"{entry:,.0f}")306        st.metric("Cắt lỗ", f"{stop_loss:,.0f}", delta=f"{(stop_loss/current_price-1)*100:+.1f}%")307        st.metric("Chốt lời", f"{take_profit:,.0f}", delta=f"{(take_profit/current_price-1)*100:+.1f}%")308    309    with col2:310        st.subheader("Phân Tích Chi Tiết")311        312        # Hiển thị lý do313        st.write("**Cơ sở đề xuất:**")314        for reason in reasoning:315            st.write(f"- {reason}")316        317        # Hiển thị các chỉ số quan trọng318        st.write("**Chỉ số quan trọng:**")319        cols = st.columns(4)320        with cols[0]:321            st.metric("P/E", f"{df['P/E'].iloc[-1]:.1f}")322        with cols[1]:323            st.metric("ROE", f"{df['ROE'].iloc[-1]:.1f}%")324        with cols[2]:325            st.metric("EPS", f"{df['EPS'].iloc[-1]:,.0f}")326        with cols[3]:327            st.metric("Volume Ratio", f"{df['Volume_ratio'].iloc[-1]:.2f}")328        329        # Cảnh báo rủi ro330        st.warning("**Cảnh báo rủi ro:**")331        st.write("""332        - Dự báo không đảm bảo chính xác 100%333        - Thị trường có thể biến động do yếu tố vĩ mô334        - Luôn sử dụng lệnh cắt lỗ để quản lý rủi ro335        - Cân nhắc đa dạng hóa danh mục đầu tư336        """)337 338# Footer339st.markdown("---")340st.markdown("""341**Hướng dẫn sử dụng:**3421. Chọn cổ phiếu và số ngày dự báo ở sidebar3432. Xem phân tích kỹ thuật và cơ bản ở tab đầu tiên3443. Kiểm tra dự báo giá và độ tin cậy ở tab thứ hai3454. Tham khảo đề xuất giao dịch ở tab cuối cùng346""")