Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,446 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import pandas as pd
|
3 |
+
import matplotlib.pyplot as plt
|
4 |
+
import numpy as np
|
5 |
+
import plotly.graph_objs as go
|
6 |
+
import plotly.io as pio
|
7 |
+
|
8 |
+
# Thiết lập theme tối cho matplotlib
|
9 |
+
plt.style.use('dark_background')
|
10 |
+
|
11 |
+
# Thiết lập theme tối cho plotly
|
12 |
+
pio.templates.default = "plotly_dark"
|
13 |
+
|
14 |
+
# Đọc dữ liệu từ file Excel
|
15 |
+
try:
|
16 |
+
# Dữ liệu tỷ giá
|
17 |
+
# Chuyển đổi dự báo tỷ giá
|
18 |
+
df_fx = pd.read_excel('df_fx.xlsx', engine='openpyxl', header=0)
|
19 |
+
data_fx = df_fx[['Date','Market price','Forecast price']]
|
20 |
+
data_fx['Forecast price'] = pd.to_numeric(data_fx['Forecast price'], errors='coerce')
|
21 |
+
data_fx['Market price'] = pd.to_numeric(data_fx['Market price'], errors='coerce')
|
22 |
+
data_fx['Date'] = pd.to_datetime(data_fx['Date'])
|
23 |
+
data_fx.set_index('Date', inplace=True)
|
24 |
+
# Chuyển đổi dữ liệu tỷ giá
|
25 |
+
df_fx1 = pd.read_excel('df_fx1.xlsx', engine='openpyxl', header=0)
|
26 |
+
data_fx1 = df_fx1[['Date','Market price','Forecast price','Cap price','STB price']]
|
27 |
+
data_fx1['Forecast price'] = pd.to_numeric(data_fx1['Forecast price'], errors='coerce')
|
28 |
+
data_fx1['Market price'] = pd.to_numeric(data_fx1['Market price'], errors='coerce')
|
29 |
+
data_fx1['Cap price'] = pd.to_numeric(data_fx1['Cap price'], errors='coerce')
|
30 |
+
data_fx1['STB price'] = pd.to_numeric(data_fx1['STB price'], errors='coerce')
|
31 |
+
data_fx1['Date'] = pd.to_datetime(data_fx1['Date'])
|
32 |
+
data_fx1.set_index('Date', inplace=True)
|
33 |
+
|
34 |
+
# Dữ liệu lãi suất
|
35 |
+
# Chuyển đổi dự báo lãi suất
|
36 |
+
df_rate = pd.read_excel('df_rate.xlsx', engine='openpyxl', header=0)
|
37 |
+
data_rate = df_rate[['Date','Market rate','Forecast rate','STB rate']]
|
38 |
+
data_rate['Market rate'] = data_rate['Market rate']*100
|
39 |
+
data_rate['Forecast rate'] = data_rate['Forecast rate']*100
|
40 |
+
data_rate['STB rate'] = data_rate['STB rate']*100
|
41 |
+
data_rate['Date'] = pd.to_datetime(data_rate['Date'])
|
42 |
+
data_rate.set_index('Date', inplace=True)
|
43 |
+
# Chuyển đổi dữ liệu lãi suất
|
44 |
+
df_rate1 = pd.read_excel('df_rate1.xlsx', engine='openpyxl', header=0)
|
45 |
+
data_rate1 = df_rate1[['Date','Market rate','Forecast rate','STB rate']]
|
46 |
+
data_rate1['Market rate'] = data_rate1['Market rate']*100
|
47 |
+
data_rate1['Forecast rate'] = data_rate1['Forecast rate']*100
|
48 |
+
data_rate1['STB rate'] = data_rate1['STB rate']*100
|
49 |
+
data_rate1['Date'] = pd.to_datetime(data_rate1['Date'])
|
50 |
+
data_rate1.set_index('Date', inplace=True)
|
51 |
+
|
52 |
+
# Dữ liệu Backtest
|
53 |
+
# Chuyển đổi backtest
|
54 |
+
df_test1 = pd.read_excel('df_test1.xlsx', engine='openpyxl', header=0)
|
55 |
+
data_test1 = df_test1[['Date','Market price','Forecast price']]
|
56 |
+
data_test1['Forecast price'] = pd.to_numeric(data_test1['Forecast price'], errors='coerce')
|
57 |
+
data_test1['Market price'] = pd.to_numeric(data_test1['Market price'], errors='coerce')
|
58 |
+
data_test1['Date'] = pd.to_datetime(data_test1['Date'])
|
59 |
+
data_test1.set_index('Date', inplace=True)
|
60 |
+
|
61 |
+
|
62 |
+
df_test2 = pd.read_excel('df_test2.xlsx', engine='openpyxl', header=0)
|
63 |
+
data_test2 = df_test2[['Date','Market price','Forecast price']]
|
64 |
+
data_test2['Forecast price'] = pd.to_numeric(data_test2['Forecast price'], errors='coerce')
|
65 |
+
data_test2['Market price'] = pd.to_numeric(data_test2['Market price'], errors='coerce')
|
66 |
+
data_test2['Date'] = pd.to_datetime(data_test2['Date'])
|
67 |
+
data_test2.set_index('Date', inplace=True)
|
68 |
+
|
69 |
+
df_test3 = pd.read_excel('df_test3.xlsx', engine='openpyxl', header=0)
|
70 |
+
data_test3 = df_test3[['Date','Market price','Forecast price']]
|
71 |
+
data_test3['Forecast price'] = pd.to_numeric(data_test3['Forecast price'], errors='coerce')
|
72 |
+
data_test3['Market price'] = pd.to_numeric(data_test3['Market price'], errors='coerce')
|
73 |
+
data_test3['Date'] = pd.to_datetime(data_test3['Date'])
|
74 |
+
data_test3.set_index('Date', inplace=True)
|
75 |
+
except FileNotFoundError:
|
76 |
+
print("Một số file Excel không tồn tại. Sử dụng dữ liệu mẫu.")
|
77 |
+
# Tạo dữ liệu mẫu nếu file không tồn tại
|
78 |
+
df_fx = pd.DataFrame({
|
79 |
+
'Date': pd.date_range('2024-01-01', periods=30, freq='D'),
|
80 |
+
'USD_VND': np.random.normal(25000, 100, 30)
|
81 |
+
})
|
82 |
+
df_rate = pd.DataFrame({
|
83 |
+
'Date': pd.date_range('2024-01-01', periods=30, freq='D'),
|
84 |
+
'Interest_Rate': np.random.normal(4.5, 0.2, 30)
|
85 |
+
})
|
86 |
+
# Dự báo tỷ giá
|
87 |
+
forex_forecast = {
|
88 |
+
"Tuần": ["07/07-11/07"],
|
89 |
+
"Giá Trị Dự Báo (USD/VND)": ["26,157.6 – 26,198.5"],
|
90 |
+
"Biến Động": ["±0.2%"],
|
91 |
+
"Xu Hướng": ["Có thể tăng do chênh lệch tỷ giá chợ đen và rủi ro Mỹ-Trung"]
|
92 |
+
}
|
93 |
+
|
94 |
+
# Dự báo lãi suất
|
95 |
+
interest_rate_forecast = {
|
96 |
+
"Tuần": ["07/07-11/07", "14/07-18/07"],
|
97 |
+
"Lãi Suất Dự Báo (%)": ["4.45-4.4", "4.8-4.4"],
|
98 |
+
"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"]
|
99 |
+
}
|
100 |
+
|
101 |
+
# Backtest tỷ giá
|
102 |
+
# Tính toán MAE, MAPE
|
103 |
+
from sklearn.metrics import mean_squared_error, mean_absolute_error
|
104 |
+
# Tuần 1
|
105 |
+
mae1 = mean_absolute_error(data_test1['Market price'], data_test1['Forecast price'])
|
106 |
+
mape1 = np.mean(np.abs(data_test1['Market price'] - data_test1['Forecast price'])/np.abs(data_test1['Forecast price']))*100
|
107 |
+
# Tuần 2
|
108 |
+
mae2 = mean_absolute_error(data_test2['Market price'], data_test2['Forecast price'])
|
109 |
+
mape2 = np.mean(np.abs(data_test2['Market price'] - data_test2['Forecast price'])/np.abs(data_test2['Forecast price']))*100
|
110 |
+
# Tuần 3
|
111 |
+
mae3 = mean_absolute_error(data_test3['Market price'], data_test3['Forecast price'])
|
112 |
+
mape3 = np.mean(np.abs(data_test3['Market price'] - data_test3['Forecast price'])/np.abs(data_test3['Forecast price']))*100
|
113 |
+
|
114 |
+
|
115 |
+
backtest_data = {
|
116 |
+
"Tuần": ["16/06-20/06", "23/06-27/06", "30/06-04/07"],
|
117 |
+
"MAE": [round(mae1,2), round(mae2,2), round(mae3,2)],
|
118 |
+
"MAPE (%)": [round(mape1,3), round(mape2,3), round(mape3,3)]
|
119 |
+
}
|
120 |
+
|
121 |
+
# Chuyển đổi sang DataFrame
|
122 |
+
df_forex_forecast = pd.DataFrame(forex_forecast)
|
123 |
+
df_rate_forecast = pd.DataFrame(interest_rate_forecast)
|
124 |
+
df_backtest = pd.DataFrame(backtest_data)
|
125 |
+
|
126 |
+
# Tạo biểu đồ
|
127 |
+
# Tạo biểu đồ Dự Báo Tỷ Giá USD/VND
|
128 |
+
def create_fx_chart():
|
129 |
+
"""Tạo biểu đồ tỷ giá từ DataFrame"""
|
130 |
+
fig = go.Figure()
|
131 |
+
fig.add_trace(go.Scatter(
|
132 |
+
x=data_fx.index,
|
133 |
+
y=data_fx['Market price'],
|
134 |
+
mode='lines',
|
135 |
+
name='Market price',
|
136 |
+
line=dict(color='red', width=2),
|
137 |
+
marker=dict(size=4)
|
138 |
+
))
|
139 |
+
fig.add_trace(go.Scatter(
|
140 |
+
x=data_fx.index,
|
141 |
+
y=data_fx['Forecast price'],
|
142 |
+
mode='lines',
|
143 |
+
name='Forecast price',
|
144 |
+
line=dict(color='blue', width=2),
|
145 |
+
marker=dict(size=4)
|
146 |
+
))
|
147 |
+
|
148 |
+
fig.update_layout(
|
149 |
+
title="Dự Báo Tỷ Giá USD/VND",
|
150 |
+
xaxis_title="Ngày",
|
151 |
+
yaxis_title="Tỷ Giá (VND)",
|
152 |
+
template="plotly_dark",
|
153 |
+
height=400
|
154 |
+
)
|
155 |
+
|
156 |
+
return fig
|
157 |
+
|
158 |
+
# Tạo biểu đồ Dữ liệu tỷ giá USD/VND
|
159 |
+
def create_fx_history():
|
160 |
+
fig = go.Figure()
|
161 |
+
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='blue', width = 2 )))
|
162 |
+
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='red', width = 2 )))
|
163 |
+
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 )))
|
164 |
+
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 )))
|
165 |
+
|
166 |
+
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)
|
167 |
+
return fig
|
168 |
+
|
169 |
+
|
170 |
+
# Tạo biểu đồ Dự Báo Lãi Suất VN IRD 3M
|
171 |
+
def create_interest_rate_chart():
|
172 |
+
"""Tạo biểu đồ lãi suất từ DataFrame"""
|
173 |
+
fig = go.Figure()
|
174 |
+
fig.add_trace(go.Scatter(
|
175 |
+
x=data_rate.index,
|
176 |
+
y=data_rate['Market rate'],
|
177 |
+
mode='lines',
|
178 |
+
name='Lãi suất thị trường',
|
179 |
+
line=dict(color='blue', width=2)
|
180 |
+
))
|
181 |
+
fig.add_trace(go.Scatter(
|
182 |
+
x=data_rate.index,
|
183 |
+
y=data_rate['Forecast rate'],
|
184 |
+
mode='lines',
|
185 |
+
name='Lãi suất dự báo',
|
186 |
+
line=dict(color='red', width=2)
|
187 |
+
))
|
188 |
+
fig.add_trace(go.Scatter(
|
189 |
+
x=data_rate.index,
|
190 |
+
y=data_rate['STB rate'],
|
191 |
+
mode='lines',
|
192 |
+
name='Lãi suất NHNN',
|
193 |
+
line=dict(color='yellow', width=2)))
|
194 |
+
|
195 |
+
fig.update_layout(
|
196 |
+
title="Dự Báo Lãi Suất VN IRD 3M",
|
197 |
+
xaxis_title="Ngày",
|
198 |
+
yaxis_title="Lãi Suất (%)",
|
199 |
+
template="plotly_dark",
|
200 |
+
height=400
|
201 |
+
)
|
202 |
+
|
203 |
+
return fig
|
204 |
+
|
205 |
+
|
206 |
+
# Tạo biểu đồ Dữ liệu Lãi Suất VN IRD 3M
|
207 |
+
def create_rate_history():
|
208 |
+
fig = go.Figure()
|
209 |
+
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 )))
|
210 |
+
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 )))
|
211 |
+
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='green', width = 2 )))
|
212 |
+
|
213 |
+
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)
|
214 |
+
return fig
|
215 |
+
|
216 |
+
def create_backtest_line_chart():
|
217 |
+
"""Tạo biểu đồ đường cho kết quả backtest"""
|
218 |
+
fig = go.Figure()
|
219 |
+
|
220 |
+
fig.add_trace(go.Scatter(
|
221 |
+
x=df_backtest['Tuần'],
|
222 |
+
y=df_backtest['MAE'],
|
223 |
+
mode='lines+markers',
|
224 |
+
name='MAE',
|
225 |
+
line=dict(color='#4ecdc4', width=3),
|
226 |
+
marker=dict(size=8)
|
227 |
+
))
|
228 |
+
|
229 |
+
fig.add_trace(go.Scatter(
|
230 |
+
x=df_backtest['Tuần'],
|
231 |
+
y=df_backtest['MAPE (%)'],
|
232 |
+
mode='lines+markers',
|
233 |
+
name='MAPE (%)',
|
234 |
+
line=dict(color='#ffe66d', width=3),
|
235 |
+
marker=dict(size=8),
|
236 |
+
yaxis='y2'
|
237 |
+
))
|
238 |
+
|
239 |
+
fig.update_layout(
|
240 |
+
title="Sai Số Mô Hình Theo Tuần (Line Chart)",
|
241 |
+
xaxis_title="Tuần",
|
242 |
+
yaxis_title="MAE",
|
243 |
+
yaxis2=dict(
|
244 |
+
title="MAPE (%)",
|
245 |
+
overlaying='y',
|
246 |
+
side='right'
|
247 |
+
),
|
248 |
+
template="plotly_dark",
|
249 |
+
height=400
|
250 |
+
)
|
251 |
+
|
252 |
+
return fig
|
253 |
+
# Tạo biểu đồ backtest
|
254 |
+
def create_test1():
|
255 |
+
fig = go.Figure()
|
256 |
+
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 )))
|
257 |
+
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 )))
|
258 |
+
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)
|
259 |
+
return fig
|
260 |
+
def create_test2():
|
261 |
+
fig = go.Figure()
|
262 |
+
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 )))
|
263 |
+
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 )))
|
264 |
+
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)
|
265 |
+
return fig
|
266 |
+
def create_test3():
|
267 |
+
fig = go.Figure()
|
268 |
+
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 )))
|
269 |
+
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 )))
|
270 |
+
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)
|
271 |
+
return fig
|
272 |
+
|
273 |
+
def create_backtest_bar_chart():
|
274 |
+
"""Tạo biểu đồ cột cho kết quả backtest"""
|
275 |
+
fig = go.Figure()
|
276 |
+
|
277 |
+
fig.add_trace(go.Bar(
|
278 |
+
x=df_backtest['Tuần'],
|
279 |
+
y=df_backtest['MAE'],
|
280 |
+
name='MAE',
|
281 |
+
marker_color='#4ecdc4',
|
282 |
+
yaxis='y'
|
283 |
+
))
|
284 |
+
|
285 |
+
fig.add_trace(go.Bar(
|
286 |
+
x=df_backtest['Tuần'],
|
287 |
+
y=df_backtest['MAPE (%)'],
|
288 |
+
name='MAPE (%)',
|
289 |
+
marker_color='#ffe66d',
|
290 |
+
yaxis='y2'
|
291 |
+
))
|
292 |
+
|
293 |
+
fig.update_layout(
|
294 |
+
title="Sai Số Mô Hình Theo Tuần (Bar Chart)",
|
295 |
+
xaxis_title="Tuần",
|
296 |
+
yaxis_title="MAE",
|
297 |
+
yaxis2=dict(
|
298 |
+
title="MAPE (%)",
|
299 |
+
overlaying='y',
|
300 |
+
side='right'
|
301 |
+
),
|
302 |
+
template="plotly_dark",
|
303 |
+
height=400,
|
304 |
+
barmode='group'
|
305 |
+
)
|
306 |
+
|
307 |
+
return fig
|
308 |
+
|
309 |
+
# CSS để tạo theme tối
|
310 |
+
css = """
|
311 |
+
.gradio-container {
|
312 |
+
background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%) !important;
|
313 |
+
color: #ffffff !important;
|
314 |
+
}
|
315 |
+
.dark {
|
316 |
+
background: #1a1a1a !important;
|
317 |
+
color: #ffffff !important;
|
318 |
+
}
|
319 |
+
/* Chuyển tất cả text sang màu trắng */
|
320 |
+
body, .gr-form, .gr-box, .gr-padded, .gr-panel, .gr-block, .gr-row, .gr-column {
|
321 |
+
color: #ffffff !important;
|
322 |
+
}
|
323 |
+
/* Markdown text */
|
324 |
+
.prose, .markdown, .gr-markdown {
|
325 |
+
color: #ffffff !important;
|
326 |
+
}
|
327 |
+
.prose h1, .prose h2, .prose h3, .prose h4, .prose h5, .prose h6 {
|
328 |
+
color: #ffffff !important;
|
329 |
+
}
|
330 |
+
.prose p, .prose li, .prose span, .prose div {
|
331 |
+
color: #ffffff !important;
|
332 |
+
}
|
333 |
+
/* Dataframe styling */
|
334 |
+
.gr-dataframe, .gr-dataframe table, .gr-dataframe th, .gr-dataframe td {
|
335 |
+
color: #ffffff !important;
|
336 |
+
background-color: rgba(255, 255, 255, 0.1) !important;
|
337 |
+
}
|
338 |
+
.gr-dataframe th {
|
339 |
+
background-color: rgba(255, 255, 255, 0.2) !important;
|
340 |
+
}
|
341 |
+
/* Tab styling */
|
342 |
+
.gr-tabs .gr-tab {
|
343 |
+
color: #ffffff !important;
|
344 |
+
}
|
345 |
+
.gr-tabs .gr-tab.selected {
|
346 |
+
color: #ffffff !important;
|
347 |
+
background-color: rgba(255, 255, 255, 0.1) !important;
|
348 |
+
}
|
349 |
+
/* Input fields */
|
350 |
+
.gr-textbox, .gr-number, .gr-slider {
|
351 |
+
color: #ffffff !important;
|
352 |
+
background-color: rgba(255, 255, 255, 0.1) !important;
|
353 |
+
}
|
354 |
+
/* Labels */
|
355 |
+
label, .gr-label {
|
356 |
+
color: #ffffff !important;
|
357 |
+
}
|
358 |
+
"""
|
359 |
+
|
360 |
+
# Tạo giao diện với Gradio
|
361 |
+
with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="cyan"), css=css) as demo:
|
362 |
+
gr.HTML("""
|
363 |
+
<div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 10px; margin-bottom: 20px;">
|
364 |
+
<h1 style="color: white; font-size: 2.5em; margin: 0;">📊 Dự Báo Tỷ Giá USD/VND và Lãi Suất VND</h1>
|
365 |
+
<p style="color: #e0e0e0; font-size: 1.2em; margin: 10px 0 0 0;">Tuần 07/07 - 11/07/2024</p>
|
366 |
+
</div>
|
367 |
+
""")
|
368 |
+
|
369 |
+
gr.Markdown("### 🔄 Cập nhật từ mô hình dự báo và kết quả backtest")
|
370 |
+
|
371 |
+
with gr.Tabs():
|
372 |
+
with gr.TabItem("📈 Dự Báo Tỷ Giá"):
|
373 |
+
gr.Markdown("## 💱 Dự Báo Tỷ Giá USD/VND")
|
374 |
+
gr.Dataframe(df_forex_forecast)
|
375 |
+
|
376 |
+
gr.Markdown("## 📊 Biểu Đồ Tỷ Giá Lịch Sử")
|
377 |
+
gr.Plot(create_fx_history())
|
378 |
+
gr.Plot(create_fx_chart())
|
379 |
+
#gr.Plot(create_fx_history())
|
380 |
+
gr.Markdown("## 📋 Phân tích:")
|
381 |
+
gr.Markdown("""
|
382 |
+
- Theo kết quả của mô hình dự báo tỷ giá USD/VND, tỷ giá USD có thể tăng trong khoảng 26157.6 - 26198.5, giảm 20đ -tăng 22đ tương đương giao động trong khoảng 0.2% so với giá cuối tuần trước. Chỉ số DXY đang giữ nguyên và hiện ở mốc đạt 97.22. Trong tuần qua, Việt Nam và Mỹ đã đạt được thỏa thuận về Thuế đối ứng khi tổng thống Trump đã thông báo áp mức thuế 20% lên hàng hóa Việt Nam và 40% lên hàng hóa chuyển tiếp, như vậy mức thuế nằm trong kịch bản đã định của thị trường giúp cho tâm lý thị trường có phần giảm áp lực cho tỷ giá. Tuy nhiên, vẫn còn đây mới chỉ là thông báo, các điều khoản, các định nghĩa của thỏa thuận cuối cùng vẫn đang trong thời gian thương thảo. Hơn thế nữa, rủi ro địa chính trị và tranh chấp thương mại Mỹ, Trung bắt đầu hiện hữu, khi Trung Quốc gay gắt chỉ trích Mỹ và các nước đàm phán ngay sau thỏa thuận thuế quan của Việt Nam-Mỹ.
|
383 |
+
- Tỷ giá trung tâm của Ngân hàng Nhà Nước cũng vẫn tăng và duy trình ở mức 25116, tăng hơn 50đ so với đầu tuần trước, điều này là vì tỷ giá trên thị trường chợ đen liên tục tăng cao bất chấp sự suy giảm trên thị trường liên ngân hàng. Hiện tỷ giá trên thị trường chợ đen đã đạt 26500 bán ra, sự chênh lệch này cũng ảnh hưởng, tạo áp lực tới tỷ gía trên liên ngân hàng và có khiến tỷ giá LNH tăng trở lại. Tỷ giá chợ đen ở mức cao chứng tỏ rằng nhu cầu thị trường vẫn ở mức cao mặc dù có sự suy giảm trên thị trường LNH.
|
384 |
+
- Mặc dù có dấu hiệu suy giảm nhẹ nhưng vẫn còn một số yếu tố tạo nên áp lực cho tỷ giá trong dài hạn như thặng dư thương mại của Việt Nam với Hoa Kì thời gian tới có thể giảm do các tác động của thuế quan với mức thuế 20% (40% hàng chuyển tiếp) và rủi ro trả đũa từ phía Trung Quốc sẽ tạo nhiều áp lực lên tỷ giá. Cần tiếp tục theo dõi sát diễn biến của thị trường, sự điều tiết thị trường từ NHNN, đặc biệt là những rủi ro xoay chiến tranh thương mại Mỹ Trung.
|
385 |
+
""")
|
386 |
+
|
387 |
+
with gr.TabItem("💰 Dự Báo Lãi Suất"):
|
388 |
+
gr.Markdown("## 🏦 Dự Báo Lãi Suất VND (3 tháng)")
|
389 |
+
gr.Dataframe(df_rate_forecast)
|
390 |
+
|
391 |
+
gr.Markdown("## 📊 Biểu Đồ Lãi Suất Lịch Sử")
|
392 |
+
with gr.Row():
|
393 |
+
with gr.Column():
|
394 |
+
gr.Plot(create_rate_history())
|
395 |
+
with gr.Column():
|
396 |
+
gr.Plot(create_interest_rate_chart())
|
397 |
+
#gr.Plot(create_interest_rate_chart())
|
398 |
+
#gr.Plot(create_rate_history())
|
399 |
+
gr.Markdown("## 📋 Phân tích:")
|
400 |
+
gr.Markdown("""
|
401 |
+
- Kết quả dự báo lãi suất VND IRD kì hạn 3 tháng theo mô hình có xu hướng đi ngang và suy giảm. Trong tuần 30/06 - 04/07, lãi suất kì hạn 3 tháng tăng mạnh ở hai ngày đầu tuần lên mốc 4.8% và giảm về 4.45% và giữ cho tới cuối tuần. Đây là do đợt điều chỉnh của NHNN hút tiền thông qua tín phiếu vào ngày 24/06/2025 khiến lãi suất tăng vọt và bơm tiền cho các ngân hàng thành viên trên hệ thống từ 27/06-30/06 với lãi suất 4% cho tất cả các kì hạn, giúp lãi suất đảo chiều về quanh mốc 4.45%. Theo mô hình dự báo, lãi suất thị trường vẫn duy trì quanh mức 4.45% và dưới lãi suất tái chiết khấu của NHNN là 4.5% trong tuần 07/07-11/07. Nhưng sang tuần 14/07-18/07, lãi suất có thể tăng lên 4.8% và giảm lại về 4.4%. Xu hướng đi ngang và có phần suy giảm là do NHNN đang muốn có lãi suất thấp để thúc đẩy tăng trưởng của nền kinh tế. Nhưng không loại trừ khả năng sẽ có điều chỉnh do áp lực tỷ giá.
|
402 |
+
- Cuối tháng 6 đã có một đợt tăng lãi suất mạnh trên LNH, cụ thể lãi suất VND IRD 3 tháng đã tăng từ 4.4% lên 4.6% vào 26/06 và lên 4.8% vào 30/6. Lãi suất LNH tăng đột biến là do vào ngày 24/06 NHNN đã có đợt hút tiền thông qua tín phiếu để điều chỉnh tỷ giá. Sau khi hút hơn 22,500 tỷ đồng, thị trường đã có phản ứng, lãi suất LNH các kì hạn đều bật tăng, cho thấy nhu cầu thanh khoản của các ngân hàng trong hệ thống gia tăng vào giữa năm, khiến NHNN đã phải có đợt điều chỉnh lớn, bơm ra hơn 90000 tỷ để hạ nhiệt ( tất cả đều trúng thầu và không có khoản nào đáo hạn ) và duy trì lãi suất thấp. Điều này là do theo chủ trương của Chính Phủ về cắt giảm lãi suất cho vay trên thị trường theo công điện số 22/CĐ-TTg tại mục 6 về “Tiếp tục điều hành quyết liệt chính sách tín dụng theo hướng giảm mặt bằng lãi suất cho vay”. Như vậy các ngân hàng đang rất cần nguồn vốn chi phí thấp từ NHNN để hạ mặt bằng lãi vay trên thị trường 1 và do nhu cầu thanh khoản đang ở mức cao nên khi NHNN có động thái hút tiền vào thì lãi suất trên LNH sẽ có động thái tăng nhanh như vậy.
|
403 |
+
""")
|
404 |
+
|
405 |
+
with gr.TabItem("🧪 Kết Quả Backtest"):
|
406 |
+
gr.Markdown("## 📊 Kết Quả Backtest Mô Hình Tỷ Giá")
|
407 |
+
gr.Dataframe(df_backtest)
|
408 |
+
|
409 |
+
gr.Markdown("### 📈 Biểu Đồ Sai Số (MAE và MAPE)")
|
410 |
+
with gr.Row():
|
411 |
+
with gr.Column():
|
412 |
+
gr.Plot(create_test1())
|
413 |
+
with gr.Column():
|
414 |
+
gr.Plot(create_test2())
|
415 |
+
with gr.Row():
|
416 |
+
with gr.Column():
|
417 |
+
gr.Plot(create_test3())
|
418 |
+
with gr.Column():
|
419 |
+
gr.Plot(create_backtest_line_chart())
|
420 |
+
|
421 |
+
|
422 |
+
with gr.TabItem("📋 Thông Tin"):
|
423 |
+
gr.Markdown("""
|
424 |
+
### 📝 Ghi Chú Quan Trọng:
|
425 |
+
🔍 **Phương Pháp Dự Báo:**
|
426 |
+
- Dữ liệu dự báo dựa trên mô hình phân tích kỹ thuật
|
427 |
+
- Tích hợp yếu tố địa chính trị và kinh tế vĩ mô
|
428 |
+
- Sử dụng thuật toán deep learning để tối ưu độ chính xác
|
429 |
+
📊 **Chỉ Số Đánh Giá:**
|
430 |
+
- **MAE (Mean Absolute Error):** Sai số tuyệt đối trung bình
|
431 |
+
- **MAPE (Mean Absolute Percentage Error):** Sai số phần trăm tuyệt đối trung bình
|
432 |
+
⚠️ **Lưu Ý:**
|
433 |
+
- Cần cập nhật dữ liệu thực tế hàng tuần để cải thiện độ chính xác
|
434 |
+
- Kết quả dự báo chỉ mang tính chất tham khảo
|
435 |
+
- Nên kết hợp với các nguồn thông tin khác để đưa ra quyết định đầu tư
|
436 |
+
🔄 **Cập Nhật:** Dữ liệu được cập nhật liên tục từ các nguồn đáng tin cậy
|
437 |
+
""")
|
438 |
+
|
439 |
+
# Chạy ứng dụng
|
440 |
+
if __name__ == "__main__":
|
441 |
+
demo.launch(
|
442 |
+
share=True,
|
443 |
+
server_name="0.0.0.0",
|
444 |
+
show_error=True,
|
445 |
+
inbrowser=True
|
446 |
+
)
|