H1209 commited on
Commit
6e49796
·
verified ·
1 Parent(s): 1ac57ca

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +347 -231
app.py CHANGED
@@ -1,3 +1,4 @@
 
1
  import gradio as gr
2
  import pandas as pd
3
  import matplotlib.pyplot as plt
@@ -5,97 +6,85 @@ 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": ["14/07-18/07"],
89
  "Giá Trị Dự Báo (USD/VND)": ["26,093 – 26,144"],
90
  "Biến Động": ["-0.1% - 0.3%"],
91
- "Xu Hướng": [" thể giảm do những tín hiệu tích cực từ thuế quan và thị trường chứng khoán."]
92
  }
93
 
94
  # Dự báo lãi suất
95
  interest_rate_forecast = {
96
  "Tuần": ["14/07-18/07", "21/07-25/07"],
97
  "Lãi Suất Dự Báo (%)": ["4.75-4.8", "4.8-4.9"],
98
- "Xu Hướng": ["Tăng", "Có thể tăng (do đáo hạn các khoản vay OMO, thắt chặt chính sách tiền tệ do rủi ro lạm phát )"]
99
  }
100
 
101
  # Backtest tỷ giá
@@ -113,7 +102,7 @@ mape3 = np.mean(np.abs(data_test3['Market price'] - data_test3['Forecast price']
113
 
114
 
115
  backtest_data = {
116
- "Tuần": ["23/06-27/06", "30/06-04/07", "07/07-11/07"],
117
  "MAE": [round(mae1,2), round(mae2,2), round(mae3,2)],
118
  "MAPE (%)": [round(mape1,3), round(mape2,3), round(mape3,3)]
119
  }
@@ -123,188 +112,295 @@ 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='Tỷ giá thị trường',
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='Tỷ giá dự báo',
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='red', 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='blue', 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='yellow', 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 = """
@@ -427,18 +523,38 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="cyan"), c
427
  gr.Markdown("""
428
  ### 📝 Ghi Chú Quan Trọng:
429
  🔍 **Phương Pháp Dự Báo:**
430
- - Dữ liệu dự báo dựa trên hình phân tích kỹ thuật
431
- - Tích hợp yếu tố địa chính trị và kinh tế vĩ mô
432
- - Sử dụng thuật toán deep learning để tối ưu độ chính xác
433
  📊 **Chỉ Số Đánh Giá:**
434
- - **MAE (Mean Absolute Error):** Sai số tuyệt đối trung bình
435
- - **MAPE (Mean Absolute Percentage Error):** Sai số phần trăm tuyệt đối trung bình
436
  ⚠️ **Lưu Ý:**
437
  - Cần cập nhật dữ liệu thực tế hàng tuần để cải thiện độ chính xác
438
  - Kết quả dự báo chỉ mang tính chất tham khảo
439
  - Nên kết hợp với các nguồn thông tin khác để đưa ra quyết định đầu tư
440
  🔄 **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
441
  """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
442
 
443
  # Chạy ứng dụng
444
  if __name__ == "__main__":
 
1
+ # Thư viện để tạo Space
2
  import gradio as gr
3
  import pandas as pd
4
  import matplotlib.pyplot as plt
 
6
  import plotly.graph_objs as go
7
  import plotly.io as pio
8
 
9
+ # Thư viện để tạo file
10
+ import os
11
+ import io
12
+ from docx import Document
13
+ from docx.shared import Inches
14
+
15
+
16
+
17
  # Thiết lập theme tối cho matplotlib
18
  plt.style.use('dark_background')
19
 
20
  # Thiết lập theme tối cho plotly
21
  pio.templates.default = "plotly_dark"
22
 
23
+
24
+
25
+
26
  # Đọc dữ liệu từ file Excel
27
+ file_configs = {
28
+ 'data_fx': ('df_fx.xlsx', ['Date','Market price','Forecast price']),
29
+ 'data_fx1': ('df_fx1.xlsx', ['Date','Market price','Forecast price','Cap price','STB price']),
30
+ 'data_rate': ('df_rate.xlsx', ['Date','Market rate','Forecast rate','STB rate']),
31
+ 'data_rate1': ('df_rate1.xlsx', ['Date','Market rate','Forecast rate','STB rate']),
32
+ 'data_test1': ('df_test1.xlsx', ['Date','Market price','Forecast price']),
33
+ 'data_test2': ('df_test2.xlsx', ['Date','Market price','Forecast price']),
34
+ 'data_test3': ('df_test3.xlsx', ['Date','Market price','Forecast price']),
35
+ }
36
+
37
+ # Hàm xử từng file
38
+ def process_excel(file_path, columns, scale_rates=False):
39
+ df = pd.read_excel(file_path, engine='openpyxl', header=0)
40
+ data = df[columns]
41
+ # Chuyển đổi kiểu dữ liệu
42
+ for col in columns:
43
+ if col != 'Date':
44
+ data[col] = pd.to_numeric(data[col], errors='coerce')
45
+ # Nhân 100 nếu là dữ liệu lãi suất
46
+ if scale_rates:
47
+ for col in ['Market rate', 'Forecast rate', 'STB rate']:
48
+ if col in data.columns:
49
+ data[col] *= 100
50
+ data['Date'] = pd.to_datetime(data['Date'])
51
+ data.set_index('Date', inplace=True)
52
+ return data
53
+
54
+ # Dictionary chứa kết quả đã xử lý
55
+ processed_data = {}
56
+
57
+ # Lặp qua từng file và xử lý
58
+ for var_name, (file_path, cols) in file_configs.items():
59
+ scale = 'rate' in var_name # Nhân 100 nếu là dữ liệu lãi suất
60
+ processed_data[var_name] = process_excel(file_path, cols, scale_rates=scale)
61
+
62
+ # Truy cập dữ liệu như sau:
63
+ data_fx = processed_data['data_fx']
64
+ data_fx1 = processed_data['data_fx1']
65
+ data_rate = processed_data['data_rate']
66
+ data_rate1 = processed_data['data_rate1']
67
+ data_test1 = processed_data['data_test1']
68
+ data_test2 = processed_data['data_test2']
69
+ data_test3 = processed_data['data_test3']
70
+
71
+
72
+
73
+
74
+ # Summary dashboard
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  # Dự báo tỷ giá
76
  forex_forecast = {
77
  "Tuần": ["14/07-18/07"],
78
  "Giá Trị Dự Báo (USD/VND)": ["26,093 – 26,144"],
79
  "Biến Động": ["-0.1% - 0.3%"],
80
+ "Xu Hướng": ["Dao động và có thể giảm do những tín hiệu tích cực từ thuế quan và thị trường chứng khoán trong nước."]
81
  }
82
 
83
  # Dự báo lãi suất
84
  interest_rate_forecast = {
85
  "Tuần": ["14/07-18/07", "21/07-25/07"],
86
  "Lãi Suất Dự Báo (%)": ["4.75-4.8", "4.8-4.9"],
87
+ "Xu Hướng": ["Có thể tăng nhẹ", "Có thể tăng (do đáo hạn các khoản vay OMO, thắt chặt chính sách tiền tệ do rủi ro lạm phát )"]
88
  }
89
 
90
  # Backtest tỷ giá
 
102
 
103
 
104
  backtest_data = {
105
+ "Tuần": ["30/06-04/07", "07/07-11/07","14/07-18/07"],
106
  "MAE": [round(mae1,2), round(mae2,2), round(mae3,2)],
107
  "MAPE (%)": [round(mape1,3), round(mape2,3), round(mape3,3)]
108
  }
 
112
  df_rate_forecast = pd.DataFrame(interest_rate_forecast)
113
  df_backtest = pd.DataFrame(backtest_data)
114
 
115
+
116
+
117
  # Tạo biểu đồ
118
  # Tạo biểu đồ Dự Báo Tỷ Giá USD/VND
119
  def create_fx_chart():
120
  """Tạo biểu đồ tỷ giá từ DataFrame"""
121
  fig = go.Figure()
122
+ fig.add_trace(go.Scatter(x=data_fx.index, y=data_fx['Market price'], mode='lines', name='Market price', line=dict(color='red', width=2), marker=dict(size=4)))
123
+ fig.add_trace(go.Scatter(x=data_fx.index, y=data_fx['Forecast price'], mode='lines', name='Forecast price', line=dict(color='blue', width=2), marker=dict(size=4)))
124
+ # Layout
125
+ 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)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  return fig
127
 
128
  # Tạo biểu đồ Dữ liệu tỷ giá USD/VND
129
  def create_fx_history():
130
+ fig = go.Figure()
131
+ 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 )))
132
+ 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 )))
133
+ 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 )))
134
+ 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 )))
135
+ # Layout
136
+ 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)
137
+ return fig
 
138
 
139
  # Tạo biểu đồ Dự Báo Lãi Suất VN IRD 3M
140
  def create_interest_rate_chart():
141
  """Tạo biểu đồ lãi suất từ DataFrame"""
142
  fig = go.Figure()
143
+ 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)))
144
+ 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)))
145
+ 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)))
146
+ # Layout
147
+ fig.update_layout(title="Dự Báo Lãi Suất VN LNH 3M", xaxis_title="Ngày", yaxis_title="Lãi Suất (%)", template="plotly_dark", height=400)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  return fig
149
 
 
150
  # Tạo biểu đồ Dữ liệu Lãi Suất VN IRD 3M
151
  def create_rate_history():
152
+ fig = go.Figure()
153
+ 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 )))
154
+ 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 )))
155
+ 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 )))
156
+ # Layout
157
+ fig.update_layout( title = "Dữ liệu Lãi Suất VN LNH 3M", xaxis_title = "Ngày", yaxis_title = "Lãi Suất (%)", template = "plotly_dark", height = 400)
158
+ return fig
159
 
160
  def create_backtest_line_chart():
161
  """Tạo biểu đồ đường cho kết quả backtest"""
162
  fig = go.Figure()
163
+ 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)))
164
+ 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'))
165
+ # Layout
166
+ 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)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  return fig
168
+
169
  # Tạo biểu đồ backtest
170
  def create_test1():
171
+ fig = go.Figure()
172
+ 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 )))
173
+ 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 )))
174
+ # Layout
175
+ fig.update_layout( title = f"Backtest Tuần {data_test1.index.min().strftime('%d/%m/%Y')} - {data_test1.index.max().strftime('%d/%m/%Y')} ", xaxis_title = "Ngày", yaxis_title = "Tỷ Giá (VND)", template = "plotly_dark", height = 400)
176
+ return fig
177
+
178
  def create_test2():
179
+ fig = go.Figure()
180
+ 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 )))
181
+ 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 )))
182
+ # Layout
183
+ fig.update_layout( title = f"Backtest Tuần {data_test2.index.min().strftime('%d/%m/%Y')} - {data_test2.index.max().strftime('%d/%m/%Y')} ", xaxis_title = "Ngày", yaxis_title = "Tỷ Giá (VND)", template = "plotly_dark", height = 400)
184
+ return fig
185
+
186
  def create_test3():
 
 
 
 
 
 
 
 
187
  fig = go.Figure()
188
+ 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 )))
189
+ 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 )))
190
+ # Layout
191
+ fig.update_layout( title = f"Backtest Tuần {data_test3.index.min().strftime('%d/%m/%Y')} - {data_test3.index.max().strftime('%d/%m/%Y')} ", xaxis_title = "Ngày", yaxis_title = "Tỷ Giá (VND)", template = "plotly_dark", height = 400)
192
+ return fig
193
+
194
+ # Tạo môi trường của Báo cáo Word
195
+ REPORT_FOLDER = "bao_cao_word"
196
+ if not os.path.exists(REPORT_FOLDER):
197
+ os.makedirs(REPORT_FOLDER)
198
+ # Báo cáo Word
199
+ def create_word_report():
200
+ doc = Document()
201
+
202
+ # Tiêu đề báo cáo
203
+ title1 = "Báo Cáo Dự Báo Tỷ Giá USD/VND và Lãi Suất VND"
204
+ title2 = "Tuần 14/07 - 18/07/2025"
205
+
206
+ doc.add_heading(title1, level = 1)
207
+ doc.add_heading(title2, level = 4)
208
+ doc.add_paragraph('')
209
+
210
+ # Dự Báo Tỷ Giá USD/VND
211
+ heading1 = "📈Dự Báo Tỷ Giá USD/VND"
212
+ doc.add_heading(heading1, level = 2)
213
+
214
+ # Thêm bảng dữ liệu Dự Báo Tỷ Giá tóm tắt
215
+ table = doc.add_table(rows=2, cols=4)
216
+ # hàng tiêu đề
217
+ hdr_cells = table.rows[0].cells
218
+ hdr_cells[0].text = 'Tuần'
219
+ hdr_cells[1].text = 'Giá Trị Dự Báo (USD/VND)'
220
+ hdr_cells[2].text = 'Biến động'
221
+ hdr_cells[3].text = 'Xu Hướng'
222
+ # Bôi đậm hàng tiêu đề
223
+ for cell in hdr_cells:
224
+ for paragraph in cell.paragraphs:
225
+ for run in paragraph.runs:
226
+ run.bold = True
227
+ # hàng data
228
+ hdr_cells1 = table.rows[1].cells
229
+ hdr_cells1[0].text = '14/07-18/07'
230
+ hdr_cells1[1].text = '26093 - 26144'
231
+ hdr_cells1[2].text = '-0.1% - 0.3%'
232
+ hdr_cells1[3].text = "Dao động và có thể giảm do những tín hiệu tích cực từ thuế quan và thị trường chứng khoán trong nước."
233
+
234
+
235
+
236
+ # Thêm hình ảnh Dự Báo Tỷ Giá
237
+ doc.add_heading('Biểu Ðồ Tỷ Giá Lịch Sử', level=3)
238
+
239
+ image_path1 = os.path.join(REPORT_FOLDER, "ty_gia_lich_su.png")
240
+ fig1 = create_fx_history()
241
+ fig1.write_image(image_path1, engine='kaleido')
242
+ doc.add_picture(image_path1, width=Inches(6))
243
+
244
+ image_path2 = os.path.join(REPORT_FOLDER, "du_bao_ty_gia.png")
245
+ fig2 = create_fx_chart()
246
+ fig2.write_image(image_path2, engine='kaleido')
247
+ doc.add_picture(image_path2, width=Inches(6))
248
+
249
+ # Phân tích:
250
+ doc.add_heading('📋 Phân tích:', level=3)
251
+ doc.add_paragraph("""
252
+ - Theo kết quả của mô hình dự báo tỷ giá USD/VND, tỷ giá USD có thể giao động trong khoảng 26093 – 26144, giảm 10đ -tăng 32đ tương đương giao động trong khoảng -0.1% - 0.3% so với giá cuối tuần trước. Chỉ số DXY tăng nhẹ và hiện ở mốc đạt 97.9.
253
+ - Trong tuần qua, Tổng thống Trump đã thông báo các mức thuế mới sẽ áp lên hàng hóa các đối tác khác ngoài Việt Nam sẽ có hiệu lực sau ngày 1/8/2025, hầu hết các nước trong khu vực Đông Nam Á và Đông Bắc Á như Nhật Bản, Hàn Quốc đều cao hơn mức thuế Mỹ áp dụng với Việt Nam. Như vậy mức thuế mới sẽ không làm mất tính cạnh tranh của hàng hóa Việt Nam so với các nước trong khu vực và còn tạo một chút lợi thế nhỏ. Tâm lý thị trường cũng dần ổn định, trên thị trường chứng khoán liên tục lập đỉnh mới tại 1469, VN30 vượt 1500 điểm, cùng với đó dòng vốn ngoại đã quay lại thị trường sau nhiều phiên bán ròng cũng góp phần ổn định tỷ giá.
254
+ - Tuy nhiên, nhu cầu ngoại tệ trên thị trường vẫn ở mức cao để phục vụ sản xuất. Ngoài ra, thị trường cũng đang trong tâm lý chờ đợi những điều tiết của NHNN và các diễn biến tiếp theo của cuộc chiến thuế quan.
255
+ - 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 25128, tăng hơn 12đ so với đầu tuần trước, điều này là vì tỷ giá trên thị trường chợ đen vẫn ở mức 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 26430 bán ra.
256
+ """)
257
+
258
+
259
+ # Dự Báo Lãi Suất
260
+ heading2 = "💰 Dự Báo Lãi Suất"
261
+ doc.add_heading(heading2, level = 2)
262
+
263
+ # Thêm bảng dữ liệu Dự Báo Lãi Suất tóm tắt
264
+ table2 = doc.add_table(rows=3, cols=3)
265
+ # hàng tiêu đề
266
+ hdr_cells_rate = table2.rows[0].cells
267
+ hdr_cells_rate[0].text = 'Tuần'
268
+ hdr_cells_rate[1].text = 'Lãi Suất Dự Báo (USD/VND)'
269
+ hdr_cells_rate[2].text = 'Xu Hướng'
270
+ # Bôi đậm hàng tiêu đề
271
+ for cell in hdr_cells_rate:
272
+ for paragraph in cell.paragraphs:
273
+ for run in paragraph.runs:
274
+ run.bold = True
275
+ # hàng data
276
+ hdr_cells_rate1 = table2.rows[1].cells
277
+ hdr_cells_rate1[0].text = '14/07-18/07'
278
+ hdr_cells_rate1[1].text = '4.75 - 4.8'
279
+ hdr_cells_rate1[2].text = "Có thể tăng nhẹ"
280
+
281
+ hdr_cells_rate2 = table2.rows[2].cells
282
+ hdr_cells_rate2[0].text = '21/07-25/07'
283
+ hdr_cells_rate2[1].text = '4.8 - 4.9'
284
+ hdr_cells_rate2[2].text = "Có thể tăng (do đáo hạn các khoản vay OMO, thắt chặt chính sách tiền tệ do rủi ro lạm phát )"
285
+
286
+ # Thêm hình ảnh Dự Báo Lãi Suất
287
+ doc.add_heading('Biểu Ðồ Lãi Suất Lịch Sử', level=3)
288
+
289
+ image_path3 = os.path.join(REPORT_FOLDER, "lich_su_lai_suat.png")
290
+ fig3 = create_rate_history()
291
+ fig3.write_image(image_path3, engine='kaleido')
292
+ doc.add_picture(image_path3, width=Inches(6))
293
+
294
+ image_path4 = os.path.join(REPORT_FOLDER, "du_bao_lai_suat.png")
295
+ fig4 = create_interest_rate_chart()
296
+ fig4.write_image(image_path4, engine='kaleido')
297
+ doc.add_picture(image_path4, width=Inches(6))
298
+
299
+ # Phân tích:
300
+ doc.add_heading('📋 Phân tích:', level=3)
301
+ doc.add_paragraph("""
302
+ - Kết quả dự báo lãi suất VND LNH kì hạn 3 tháng theo mô hình có xu hướng đi ngang và tiếp tục tăng. Trong tuần 07/07 - 11/07, lãi suất kì hạn 3 tháng giữ nguyên và tăng vào cuối tuần lên mốc 4.8%. Đâ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 09/07/2025 khiến lãi suất tăng vọt, mặc dù NHNN có bơm 77000 tỷ thông qua kênh OMO nhưng vẫn hút ròng hơn 7000 tỷ đồng. Ngoài ra, các khoản vay OMO đáo hạn là hơn 61700 tỷ của đợt bơm tiền cuối tháng 6, cũng làm tăng áp lực lên lãi suất.
303
+ - Theo mô hình dự báo, lãi suất thị trường vẫn duy trì quanh mức 4.75% và trên lãi suất tái chiết khấu của NHNN là 4.5% trong tuần 14/07-18/07. Nhưng sang tuần 21/07-25/07, lãi suất có thể tăng lên mức 4.8% và tăng tiếp lên 4.9% vào cuối tuần.
304
+ - Xu hướng tăng là do NHNN đang muốn có kiểm soát tỷ giá USD/VND trong bối cảnh tỷ giá chợ đen và trên thị trường vẫn đang ở mức cao. Ngoài ra, lạm phát khi mà chỉ số CPI tháng 6 đạt 3.57% tăng 0.48% so với tháng 5, cũng tạo áp lực phải có sự điều tiết tới từ NHNN. Nhiều khả năng mức lãi suất VND LNH 3M có thể tiếp tục dao động ở mức 4.8% để vừa ổn định tỷ giá và tạo mặt bằng lãi suất thấp cho các ngân hàng, hướng tới mục tiêu tăng trưởng tín dụng 16% trong năm nay.
305
+
306
+ """)
307
+
308
+ # Backtest
309
+ heading3 = "📊 Kết Quả Backtest Mô Hình Tỷ Giá"
310
+ doc.add_heading(heading3, level = 2)
311
+
312
+ # Thêm bảng dữ liệu backtest
313
+ table3 = doc.add_table(rows = 4, cols=3)
314
+ # hàng tiêu đề
315
+ hdr_cells_test = table3.rows[0].cells
316
+ hdr_cells_test[0].text = 'Tuần'
317
+ hdr_cells_test[1].text = 'MAE'
318
+ hdr_cells_test[2].text = 'MAPE (%)'
319
+ # Bôi đậm hàng tiêu đề
320
+ for cell in hdr_cells_test:
321
+ for paragraph in cell.paragraphs:
322
+ for run in paragraph.runs:
323
+ run.bold = True
324
+ # hàng data
325
+ hdr_cells_test1 = table3.rows[1].cells
326
+ hdr_cells_test1[0].text = f"{data_test1.index.min().strftime('%d/%m/%Y')} - {data_test1.index.max().strftime('%d/%m/%Y')}"
327
+ hdr_cells_test1[1].text = str(round(mae1,2))
328
+ hdr_cells_test1[2].text = str(round(mape1,3))
329
+
330
+ hdr_cells_test2 = table3.rows[2].cells
331
+ hdr_cells_test2[0].text = f"{data_test2.index.min().strftime('%d/%m/%Y')} - {data_test2.index.max().strftime('%d/%m/%Y')}"
332
+ hdr_cells_test2[1].text = str(round(mae2,2))
333
+ hdr_cells_test2[2].text = str(round(mape2,3))
334
+
335
+ hdr_cells_test3 = table3.rows[3].cells
336
+ hdr_cells_test3[0].text = f"{data_test3.index.min().strftime('%d/%m/%Y')} - {data_test3.index.max().strftime('%d/%m/%Y')}"
337
+ hdr_cells_test3[1].text = str(round(mae3,2))
338
+ hdr_cells_test3[2].text = str(round(mape3,3))
339
+
340
+ # Thêm hình ảnh Backtest Mô Hình Tỷ Giá
341
+ doc.add_heading('Biểu Ðồ Backtest Mô Hình Tỷ Giá', level=3)
342
+
343
+ image_path5 = os.path.join(REPORT_FOLDER, "test1.png")
344
+ fig5 = create_test1()
345
+ fig5.write_image(image_path5, engine='kaleido')
346
+ doc.add_picture(image_path5, width=Inches(6))
347
+
348
+ image_path6 = os.path.join(REPORT_FOLDER, "test2.png")
349
+ fig6 = create_test2()
350
+ fig6.write_image(image_path6, engine='kaleido')
351
+ doc.add_picture(image_path6, width=Inches(6))
352
+
353
+ image_path7 = os.path.join(REPORT_FOLDER, "test3.png")
354
+ fig7 = create_test3()
355
+ fig7.write_image(image_path7, engine='kaleido')
356
+ doc.add_picture(image_path7, width=Inches(6))
357
+
358
+ image_path8 = os.path.join(REPORT_FOLDER, "line_test.png")
359
+ fig8 = create_backtest_line_chart()
360
+ fig8.write_image(image_path8, engine='kaleido')
361
+ doc.add_picture(image_path8, width=Inches(6))
362
+
363
+ # Các Thông Tin mô hình:
364
+ heading3 = "📋 Thông Tin"
365
+ doc.add_heading(heading3, level = 2)
366
+
367
+ # Tiêu đề phụ: Ghi Chú Quan Trọng
368
+ doc.add_paragraph("📝 Ghi Chú Quan Trọng:", style='Heading 4')
369
+ # Phương Pháp Dự Báo
370
+ doc.add_paragraph("🔍 Phương Pháp Dự Báo:", style='Heading 5')
371
+ doc.add_paragraph("""
372
+ - Dữ liệu dự báo dựa trên một số chỉ báo phân tích kỹ thuật.
373
+ - Tích hợp một số chỉ số kinh tế vĩ mô và ảnh hưởng của tin tức thị trường.
374
+ - Sử dụng các thuật toán máy học và học sâu để tối ưu độ chính xác.
375
+ """)
376
+ # Chỉ Số Đánh Giá
377
+ doc.add_paragraph("📊 Chỉ Số Đánh Giá:", style='Heading 5')
378
+ doc.add_paragraph("""
379
+ - MAE (Mean Absolute Error): Sai số tuyệt đối trung bình, là trung bình chênh lệch tuyệt đối giữa giá dự báo và giá thực tế trên thị trường trong 1 tuần.
380
+ - MAPE (Mean Absolute Percentage Error): Sai số phần trăm tuyệt đối trung bình, là trung bình phần trăm chênh lệch tuyệt đối giữa giá dự báo và giá thực tế trên thị trường trong 1 tuần.
381
+ """)
382
+ # Lưu ý
383
+ doc.add_paragraph("⚠️ Lưu Ý:", style='Heading 5')
384
+ doc.add_paragraph("""
385
+ - Cần cập nhật dữ liệu thực tế hàng tuần để cải thiện độ chính xác.
386
+ - Kết quả dự báo chỉ mang tính chất tham khảo.
387
+ - Nên kết hợp với các nguồn thông tin khác để đưa ra quyết định đầu tư.
388
+ """)
389
+
390
+
391
+ # Cập Nhật
392
+ p = doc.add_paragraph()
393
+ p.add_run("🔄 Cập Nhật: ").bold = True
394
+ p.add_run("Dữ liệu được cập nhật hàng tuần từ các nguồn đáng tin cậy")
395
+
396
+
397
+ # Lưu file Word
398
+ report_title = "Bao_cao_Ty_Gia_va_Lai_Suat_Tuan_14-07-2025.docx"
399
+ output_path = os.path.join(REPORT_FOLDER, report_title)
400
+ doc.save(output_path)
401
+ return output_path
402
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
403
 
 
404
 
405
  # CSS để tạo theme tối
406
  css = """
 
523
  gr.Markdown("""
524
  ### 📝 Ghi Chú Quan Trọng:
525
  🔍 **Phương Pháp Dự Báo:**
526
+ - Dữ liệu dự báo dựa trên một số chỉ báo phân tích kỹ thuật
527
+ - Tích hợp một số chỉ số kinh tế vĩ mô và ảnh hưởng của tin tức thị trường
528
+ - Sử dụng các thuật toán máy học và học sâu để tối ưu độ chính xác
529
  📊 **Chỉ Số Đánh Giá:**
530
+ - **MAE (Mean Absolute Error):** Sai số tuyệt đối trung bình, là trung bình chênh lệch tuyệt đối giữa giá dự báo và giá thực tế trên thị trường trong 1 tuần.
531
+ - **MAPE (Mean Absolute Percentage Error):** Sai số phần trăm tuyệt đối trung bình, là trung bình phần trăm chênh lệch tuyệt đối giữa giá dự báo và giá thực tế trên thị trường trong 1 tuần.
532
  ⚠️ **Lưu Ý:**
533
  - Cần cập nhật dữ liệu thực tế hàng tuần để cải thiện độ chính xác
534
  - Kết quả dự báo chỉ mang tính chất tham khảo
535
  - Nên kết hợp với các nguồn thông tin khác để đưa ra quyết định đầu tư
536
  🔄 **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
537
  """)
538
+ with gr.Row():
539
+ word_btn_fx = gr.Button("📥 Xuất Word", size="sm", variant="secondary")
540
+ report_output_fx = gr.File(label="Báo cáo đã tải", visible=True)
541
+ word_btn_fx.click(fn=create_word_report,outputs=report_output_fx)
542
+ gr.HTML("""
543
+ <script>
544
+ document.addEventListener('DOMContentLoaded', function() {
545
+ const observer = new MutationObserver((mutations) => {
546
+ mutations.forEach((mutation) => {
547
+ if (mutation.type === 'childList' && mutation.target.id === 'report_output_fx') {
548
+ const link = document.querySelector('#report_output_fx a');
549
+ if (link) link.click(); // Tự động tải file
550
+ }
551
+ });
552
+ });
553
+ observer.observe(document.body, { childList: true, subtree: true });
554
+ });
555
+ </script>
556
+ """)
557
+
558
 
559
  # Chạy ứng dụng
560
  if __name__ == "__main__":