import gradio as gr import pandas as pd import matplotlib.pyplot as plt import numpy as np import plotly.graph_objs as go import plotly.io as pio # Thiết lập theme tối cho matplotlib plt.style.use('dark_background') # Thiết lập theme tối cho plotly pio.templates.default = "plotly_dark" # Đọc dữ liệu từ file Excel try: # Dữ liệu tỷ giá # Chuyển đổi dự báo tỷ giá df_fx = pd.read_excel('df_fx.xlsx', engine='openpyxl', header=0) data_fx = df_fx[['Date','Market price','Forecast price']] data_fx['Forecast price'] = pd.to_numeric(data_fx['Forecast price'], errors='coerce') data_fx['Market price'] = pd.to_numeric(data_fx['Market price'], errors='coerce') data_fx['Date'] = pd.to_datetime(data_fx['Date']) data_fx.set_index('Date', inplace=True) # Chuyển đổi dữ liệu tỷ giá df_fx1 = pd.read_excel('df_fx1.xlsx', engine='openpyxl', header=0) data_fx1 = df_fx1[['Date','Market price','Forecast price','Cap price','STB price']] data_fx1['Forecast price'] = pd.to_numeric(data_fx1['Forecast price'], errors='coerce') data_fx1['Market price'] = pd.to_numeric(data_fx1['Market price'], errors='coerce') data_fx1['Cap price'] = pd.to_numeric(data_fx1['Cap price'], errors='coerce') data_fx1['STB price'] = pd.to_numeric(data_fx1['STB price'], errors='coerce') data_fx1['Date'] = pd.to_datetime(data_fx1['Date']) data_fx1.set_index('Date', inplace=True) # Dữ liệu lãi suất # Chuyển đổi dự báo lãi suất df_rate = pd.read_excel('df_rate.xlsx', engine='openpyxl', header=0) data_rate = df_rate[['Date','Market rate','Forecast rate','STB rate']] data_rate['Market rate'] = data_rate['Market rate']*100 data_rate['Forecast rate'] = data_rate['Forecast rate']*100 data_rate['STB rate'] = data_rate['STB rate']*100 data_rate['Date'] = pd.to_datetime(data_rate['Date']) data_rate.set_index('Date', inplace=True) # Chuyển đổi dữ liệu lãi suất df_rate1 = pd.read_excel('df_rate1.xlsx', engine='openpyxl', header=0) data_rate1 = df_rate1[['Date','Market rate','Forecast rate','STB rate']] data_rate1['Market rate'] = data_rate1['Market rate']*100 data_rate1['Forecast rate'] = data_rate1['Forecast rate']*100 data_rate1['STB rate'] = data_rate1['STB rate']*100 data_rate1['Date'] = pd.to_datetime(data_rate1['Date']) data_rate1.set_index('Date', inplace=True) # Dữ liệu Backtest # Chuyển đổi backtest df_test1 = pd.read_excel('df_test1.xlsx', engine='openpyxl', header=0) data_test1 = df_test1[['Date','Market price','Forecast price']] data_test1['Forecast price'] = pd.to_numeric(data_test1['Forecast price'], errors='coerce') data_test1['Market price'] = pd.to_numeric(data_test1['Market price'], errors='coerce') data_test1['Date'] = pd.to_datetime(data_test1['Date']) data_test1.set_index('Date', inplace=True) df_test2 = pd.read_excel('df_test2.xlsx', engine='openpyxl', header=0) data_test2 = df_test2[['Date','Market price','Forecast price']] data_test2['Forecast price'] = pd.to_numeric(data_test2['Forecast price'], errors='coerce') data_test2['Market price'] = pd.to_numeric(data_test2['Market price'], errors='coerce') data_test2['Date'] = pd.to_datetime(data_test2['Date']) data_test2.set_index('Date', inplace=True) df_test3 = pd.read_excel('df_test3.xlsx', engine='openpyxl', header=0) data_test3 = df_test3[['Date','Market price','Forecast price']] data_test3['Forecast price'] = pd.to_numeric(data_test3['Forecast price'], errors='coerce') data_test3['Market price'] = pd.to_numeric(data_test3['Market price'], errors='coerce') data_test3['Date'] = pd.to_datetime(data_test3['Date']) data_test3.set_index('Date', inplace=True) except FileNotFoundError: print("Một số file Excel không tồn tại. Sử dụng dữ liệu mẫu.") # Tạo dữ liệu mẫu nếu file không tồn tại df_fx = pd.DataFrame({ 'Date': pd.date_range('2024-01-01', periods=30, freq='D'), 'USD_VND': np.random.normal(25000, 100, 30) }) df_rate = pd.DataFrame({ 'Date': pd.date_range('2024-01-01', periods=30, freq='D'), 'Interest_Rate': np.random.normal(4.5, 0.2, 30) }) # Dự báo tỷ giá forex_forecast = { "Tuần": ["07/07-11/07"], "Giá Trị Dự Báo (USD/VND)": ["26,157.6 – 26,198.5"], "Biến Động": ["±0.2%"], "Xu Hướng": ["Có thể tăng do chênh lệch tỷ giá chợ đen và rủi ro Mỹ-Trung"] } # Dự báo lãi suất interest_rate_forecast = { "Tuần": ["07/07-11/07", "14/07-18/07"], "Lãi Suất Dự Báo (%)": ["4.45-4.4", "4.8-4.4"], "Xu Hướng": ["Đi ngang/suy giảm", "Có thể tăng (do đáo hạn các khoản vay OMO) rồi giảm"] } # Backtest tỷ giá # Tính toán MAE, MAPE from sklearn.metrics import mean_squared_error, mean_absolute_error # Tuần 1 mae1 = mean_absolute_error(data_test1['Market price'], data_test1['Forecast price']) mape1 = np.mean(np.abs(data_test1['Market price'] - data_test1['Forecast price'])/np.abs(data_test1['Forecast price']))*100 # Tuần 2 mae2 = mean_absolute_error(data_test2['Market price'], data_test2['Forecast price']) mape2 = np.mean(np.abs(data_test2['Market price'] - data_test2['Forecast price'])/np.abs(data_test2['Forecast price']))*100 # Tuần 3 mae3 = mean_absolute_error(data_test3['Market price'], data_test3['Forecast price']) mape3 = np.mean(np.abs(data_test3['Market price'] - data_test3['Forecast price'])/np.abs(data_test3['Forecast price']))*100 backtest_data = { "Tuần": ["16/06-20/06", "23/06-27/06", "30/06-04/07"], "MAE": [round(mae1,2), round(mae2,2), round(mae3,2)], "MAPE (%)": [round(mape1,3), round(mape2,3), round(mape3,3)] } # Chuyển đổi sang DataFrame df_forex_forecast = pd.DataFrame(forex_forecast) df_rate_forecast = pd.DataFrame(interest_rate_forecast) df_backtest = pd.DataFrame(backtest_data) # Tạo biểu đồ # Tạo biểu đồ Dự Báo Tỷ Giá USD/VND def create_fx_chart(): """Tạo biểu đồ tỷ giá từ DataFrame""" fig = go.Figure() fig.add_trace(go.Scatter( x=data_fx.index, y=data_fx['Market price'], mode='lines', name='Tỷ giá thị trường', line=dict(color='red', width=2), marker=dict(size=4) )) fig.add_trace(go.Scatter( x=data_fx.index, y=data_fx['Forecast price'], mode='lines', name='Tỷ giá dự báo', line=dict(color='blue', width=2), marker=dict(size=4) )) fig.update_layout( title="Dự Báo Tỷ Giá USD/VND", xaxis_title="Ngày", yaxis_title="Tỷ Giá (VND)", template="plotly_dark", height=400 ) return fig # Tạo biểu đồ Dữ liệu tỷ giá USD/VND def create_fx_history(): fig = go.Figure() fig.add_trace(go.Scatter(x = data_fx1.index, y = data_fx1['Market price'], mode ='lines', name = 'Tỷ giá thị trường', line= dict(color='red', width = 2 ))) fig.add_trace(go.Scatter(x = data_fx1.index, y = data_fx1['Forecast price'], mode ='lines', name = 'Tỷ giá dự báo', line= dict(color='blue', width = 2 ))) fig.add_trace(go.Scatter(x = data_fx1.index, y = data_fx1['Cap price'], mode ='lines', name = 'Tỷ giá trần', line= dict(color='yellow', width = 2 ))) fig.add_trace(go.Scatter(x = data_fx1.index, y = data_fx1['STB price'], mode ='lines', name = 'Tỷ giá trung tâm', line= dict(color='green', width = 2 ))) fig.update_layout( title = "Dữ liệu tỷ giá USD/VND", xaxis_title = "Ngày", yaxis_title = "Tỷ Giá (VND)", template = "plotly_dark", height = 400) return fig # Tạo biểu đồ Dự Báo Lãi Suất VN IRD 3M def create_interest_rate_chart(): """Tạo biểu đồ lãi suất từ DataFrame""" fig = go.Figure() fig.add_trace(go.Scatter( x=data_rate.index, y=data_rate['Market rate'], mode='lines', name='Lãi suất thị trường', line=dict(color='blue', width=2) )) fig.add_trace(go.Scatter( x=data_rate.index, y=data_rate['Forecast rate'], mode='lines', name='Lãi suất dự báo', line=dict(color='red', width=2) )) fig.add_trace(go.Scatter( x=data_rate.index, y=data_rate['STB rate'], mode='lines', name='Lãi suất NHNN', line=dict(color='yellow', width=2))) fig.update_layout( title="Dự Báo Lãi Suất VN IRD 3M", xaxis_title="Ngày", yaxis_title="Lãi Suất (%)", template="plotly_dark", height=400 ) return fig # Tạo biểu đồ Dữ liệu Lãi Suất VN IRD 3M def create_rate_history(): fig = go.Figure() fig.add_trace(go.Scatter(x = data_rate1.index, y = data_rate1['Market rate'], mode ='lines', name = 'Lãi Suất thị trường', line= dict(color='blue', width = 2 ))) fig.add_trace(go.Scatter(x = data_rate1.index, y = data_rate1['Forecast rate'], mode ='lines', name = 'Lãi Suất dự báo', line= dict(color='red', width = 2 ))) fig.add_trace(go.Scatter(x = data_rate1.index, y = data_rate1['STB rate'], mode ='lines', name = 'Lãi Suất NHNN', line= dict(color='yellow', width = 2 ))) fig.update_layout( title = "Dữ liệu Lãi Suất VN IRD 3M", xaxis_title = "Ngày", yaxis_title = "Lãi Suất (%)", template = "plotly_dark", height = 400) return fig def create_backtest_line_chart(): """Tạo biểu đồ đường cho kết quả backtest""" fig = go.Figure() fig.add_trace(go.Scatter( x=df_backtest['Tuần'], y=df_backtest['MAE'], mode='lines+markers', name='MAE', line=dict(color='#4ecdc4', width=3), marker=dict(size=8) )) fig.add_trace(go.Scatter( x=df_backtest['Tuần'], y=df_backtest['MAPE (%)'], mode='lines+markers', name='MAPE (%)', line=dict(color='#ffe66d', width=3), marker=dict(size=8), yaxis='y2' )) fig.update_layout( title="Sai Số Mô Hình Theo Tuần (Line Chart)", xaxis_title="Tuần", yaxis_title="MAE", yaxis2=dict( title="MAPE (%)", overlaying='y', side='right' ), template="plotly_dark", height=400 ) return fig # Tạo biểu đồ backtest def create_test1(): fig = go.Figure() fig.add_trace(go.Scatter(x = data_test1.index, y = data_test1['Market price'], mode ='lines', name = 'Giá thị trường', line= dict(color='blue', width = 2 ))) fig.add_trace(go.Scatter(x = data_test1.index, y = data_test1['Forecast price'], mode ='lines', name = 'Giá dự báo', line= dict(color='red', width = 2 ))) fig.update_layout( title = f"Backtest Tuần {min(data_test1.index)} - {max(data_test1.index)} ", xaxis_title = "Ngày", yaxis_title = "Tỷ Giá (VND)", template = "plotly_dark", height = 400) return fig def create_test2(): fig = go.Figure() fig.add_trace(go.Scatter(x = data_test2.index, y = data_test2['Market price'], mode ='lines', name = 'Giá thị trường', line= dict(color='blue', width = 2 ))) fig.add_trace(go.Scatter(x = data_test2.index, y = data_test2['Forecast price'], mode ='lines', name = 'Giá dự báo', line= dict(color='red', width = 2 ))) fig.update_layout( title = f"Backtest Tuần {min(data_test2.index)} - {max(data_test2.index)} ", xaxis_title = "Ngày", yaxis_title = "Tỷ Giá (VND)", template = "plotly_dark", height = 400) return fig def create_test3(): fig = go.Figure() fig.add_trace(go.Scatter(x = data_test3.index, y = data_test3['Market price'], mode ='lines', name = 'Giá thị trường', line= dict(color='blue', width = 2 ))) fig.add_trace(go.Scatter(x = data_test3.index, y = data_test3['Forecast price'], mode ='lines', name = 'Giá dự báo', line= dict(color='red', width = 2 ))) fig.update_layout( title = f"Backtest Tuần {min(data_test3.index)} - {max(data_test3.index)} ", xaxis_title = "Ngày", yaxis_title = "Tỷ Giá (VND)", template = "plotly_dark", height = 400) return fig def create_backtest_bar_chart(): """Tạo biểu đồ cột cho kết quả backtest""" fig = go.Figure() fig.add_trace(go.Bar( x=df_backtest['Tuần'], y=df_backtest['MAE'], name='MAE', marker_color='#4ecdc4', yaxis='y' )) fig.add_trace(go.Bar( x=df_backtest['Tuần'], y=df_backtest['MAPE (%)'], name='MAPE (%)', marker_color='#ffe66d', yaxis='y2' )) fig.update_layout( title="Sai Số Mô Hình Theo Tuần (Bar Chart)", xaxis_title="Tuần", yaxis_title="MAE", yaxis2=dict( title="MAPE (%)", overlaying='y', side='right' ), template="plotly_dark", height=400, barmode='group' ) return fig # CSS để tạo theme tối css = """ .gradio-container { background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%) !important; color: #ffffff !important; } .dark { background: #1a1a1a !important; color: #ffffff !important; } /* Chuyển tất cả text sang màu trắng */ body, .gr-form, .gr-box, .gr-padded, .gr-panel, .gr-block, .gr-row, .gr-column { color: #ffffff !important; } /* Markdown text */ .prose, .markdown, .gr-markdown { color: #ffffff !important; } .prose h1, .prose h2, .prose h3, .prose h4, .prose h5, .prose h6 { color: #ffffff !important; } .prose p, .prose li, .prose span, .prose div { color: #ffffff !important; } /* Dataframe styling */ .gr-dataframe, .gr-dataframe table, .gr-dataframe th, .gr-dataframe td { color: #ffffff !important; background-color: rgba(255, 255, 255, 0.1) !important; } .gr-dataframe th { background-color: rgba(255, 255, 255, 0.2) !important; } /* Tab styling */ .gr-tabs .gr-tab { color: #ffffff !important; } .gr-tabs .gr-tab.selected { color: #ffffff !important; background-color: rgba(255, 255, 255, 0.1) !important; } /* Input fields */ .gr-textbox, .gr-number, .gr-slider { color: #ffffff !important; background-color: rgba(255, 255, 255, 0.1) !important; } /* Labels */ label, .gr-label { color: #ffffff !important; } """ # Tạo giao diện với Gradio with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="cyan"), css=css) as demo: gr.HTML("""
Tuần 07/07 - 11/07/2025