Анастасия commited on
Commit
8eaf5b2
·
1 Parent(s): a0ac03a
.DS_Store CHANGED
Binary files a/.DS_Store and b/.DS_Store differ
 
pages/3_🪙_Прогноз_Bitcoin USD. BiLSTM.py ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import yfinance as yf
3
+ import pandas as pd
4
+ import numpy as np
5
+ import matplotlib.pyplot as plt
6
+ import torch
7
+ import torch.nn as nn
8
+ import torch.optim as optim
9
+ from datetime import date, datetime, timedelta
10
+ from model.BiLSTM_model import BiLSTM
11
+ from sklearn.metrics import mean_squared_error
12
+ from sklearn.preprocessing import MinMaxScaler
13
+ from datetime import timedelta
14
+
15
+ st.set_page_config(layout='wide', initial_sidebar_state='expanded')
16
+ st.set_option('deprecation.showPyplotGlobalUse', False)
17
+ st.title('ML Wall Street')
18
+ st.image('images/img.png')
19
+
20
+ START = "2021-01-01"
21
+ TODAY = date.today().strftime("%Y-%m-%d")
22
+ period = st.slider('Количество дней прогноза:', 1, 14, 14)
23
+
24
+ df = yf.download('BTC-USD', START, TODAY)
25
+ df.reset_index(inplace=True)
26
+
27
+ latest_date = df['Date'].iloc[-1].strftime('%Y-%m-%d')
28
+ st.markdown(f"<h3 style='text-align: center;'>Цены актуальны на последнюю дату закрытия торгов {latest_date}</h3>", unsafe_allow_html=True)
29
+
30
+ def rmse(predictions, targets):
31
+ return np.sqrt(((predictions - targets) ** 2).mean())
32
+
33
+ def mape(predictions, targets):
34
+ return np.mean(np.abs((targets - predictions) / targets)) * 100
35
+
36
+ def weighted_mape(predictions, targets, weights):
37
+ errors = np.abs(targets - predictions)
38
+ weighted_errors = errors * weights
39
+ weighted_mape = np.sum(weighted_errors) / np.sum(np.abs(targets) * weights) * 100
40
+ return weighted_mape
41
+
42
+ scaler = MinMaxScaler(feature_range=(0, 1))
43
+ scaled_data = scaler.fit_transform(df['Adj Close'].values.reshape(-1,1))
44
+
45
+ def create_dataset(data, time_step=1):
46
+ X, Y = [], []
47
+ for i in range(len(data)-time_step-1):
48
+ a = data[i:(i+time_step), 0]
49
+ X.append(a)
50
+ Y.append(data[i + time_step, 0])
51
+ return np.array(X), np.array(Y)
52
+
53
+ X, y = create_dataset(scaled_data, time_step=period)
54
+
55
+ # Разделяем данные на обучающую и тестовую выборки
56
+ test_size = period # 14 дней для теста
57
+ train_size = len(X) - test_size
58
+ X_train, X_test = X[:train_size], X[train_size:]
59
+ y_train, y_test = y[:train_size], y[train_size:]
60
+
61
+ X_train = torch.Tensor(X_train).unsqueeze(-1) # Добавляем размерность
62
+ X_test = torch.Tensor(X_test).unsqueeze(-1) # Для совместимости с LSTM
63
+ y_train = torch.Tensor(y_train)
64
+ y_test = torch.Tensor(y_test)
65
+
66
+ input_size = 1 # Входной размер равен 1, так как мы рассматриваем одну фичу - цену
67
+ hidden_size = 128
68
+ num_layers = 3
69
+ output_size = 1
70
+ model = BiLSTM(input_size, hidden_size, num_layers, output_size)
71
+ criterion = nn.MSELoss()
72
+ optimizer = optim.Adam(model.parameters(), lr=0.001)
73
+
74
+ model = BiLSTM(1, 128, 3, 1)
75
+ model.load_state_dict(torch.load('model/model_weights.pth'))
76
+ model.eval()
77
+
78
+ model.eval()
79
+ with torch.no_grad():
80
+ test_predictions = model(X_test)
81
+ test_loss = criterion(test_predictions, y_test.view(-1, 1))
82
+
83
+ test_predictions = scaler.inverse_transform(test_predictions.cpu().numpy())
84
+ y_test = scaler.inverse_transform(y_test.view(-1, 1).cpu().numpy())
85
+
86
+ test_rmse = rmse(test_predictions, y_test)
87
+ test_mape = mape(test_predictions, y_test)
88
+ weights = np.array([1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4])
89
+ test_weighted_mape = weighted_mape(test_predictions, y_test, weights)
90
+
91
+ # st.write(f'Test Loss: {test_loss.item():.4f}')
92
+ st.write(f'Test RMSE: {test_rmse:.4f}')
93
+ st.write(f'Test MAPE: {test_mape:.4f}%')
94
+ st.write(f'Test Weighted MAPE: {test_weighted_mape:.4f}%')
95
+
96
+ # Предсказания на тестовых данных
97
+ with torch.no_grad():
98
+ test_predictions = model(X_test)
99
+ adjusted_future_predictions = scaler.inverse_transform(test_predictions.cpu().numpy())
100
+
101
+ # st.write(adjusted_future_predictions)
102
+ # df_predictions = pd.DataFrame({'Predictions': adjusted_future_predictions.flatten()})
103
+ # df_predictions['Predictions'] = df.iloc[:, 0].values
104
+ # sum_test = pd.concat([df['Date'][train_size:], df_predictions], axis=1)
105
+ # st.write(sum_test)
106
+ # # adjusted_future_predictions = pd.DataFrame({'Date': df['Date'][train_size:].reset_index(), 'Predictions': adjusted_future_predictions})
107
+ # # st.write(adjusted_future_predictions)
108
+ # # pd.concat(df['Date'][train_size:], adjusted_future_predictions)
109
+ filtered_df = df
110
+
111
+ # Прогнозы с учетом трендов
112
+ trend_first_day = adjusted_future_predictions[0] - filtered_df['Adj Close'].iloc[-1]
113
+ trend_14_days = adjusted_future_predictions[-1] - adjusted_future_predictions[0]
114
+ adjusted_future_predictions = [filtered_df['Adj Close'].iloc[-1] + trend_first_day + (trend_14_days / 14) * i for i in range(14)]
115
+
116
+ # Вычисление даты, которая находится на 3 месяца назад
117
+ start_date = datetime.strptime(latest_date, '%Y-%m-%d') - timedelta(days=90)
118
+
119
+ # Преобразование строк столбца 'Date' в объекты datetime
120
+ df['Date'] = pd.to_datetime(df['Date'])
121
+
122
+ # Фильтра��ия данных за последние 3 месяца
123
+ filtered_df = df[(df['Date'] >= start_date) & (df['Date'] <= latest_date)]
124
+
125
+ # Генерация дат для будущих предсказаний
126
+ future_dates = [filtered_df['Date'].values[-1] + np.timedelta64(i+1, 'D') for i in range(14)]
127
+
128
+ # Расчет тренда на первый день
129
+ trend_first_day = adjusted_future_predictions[0] - filtered_df['Adj Close'].iloc[-1]
130
+
131
+ # Расчет тренда за 14 дней (как разницу между первым и последним днем)
132
+ trend_14_days = adjusted_future_predictions[-1] - adjusted_future_predictions[0]
133
+
134
+ # Прогнозы с учетом трендов
135
+ adjusted_future_predictions = [filtered_df['Adj Close'].iloc[-1] + trend_first_day + (trend_14_days / 14) * i for i in range(14)]
136
+
137
+ # Создание графика
138
+ plt.figure(figsize=(12,6))
139
+ plt.plot(filtered_df['Date'], filtered_df['Adj Close'], label='Actual', linewidth=2)
140
+ plt.plot(future_dates, adjusted_future_predictions, label='Future Predictions (with Trends)', linestyle='--', linewidth=2)
141
+
142
+ plt.title('Bitcoin Price Prediction (Last 3 Months)')
143
+ plt.xlabel('Date')
144
+ plt.ylabel('Price')
145
+ plt.xticks(rotation=45)
146
+ plt.legend()
147
+ # Отображение графика в Streamlit
148
+ st.pyplot(plt)
149
+
150
+ # Генерация дат для будущих предсказаний
151
+ future_dates = [df['Date'].values[-1] + np.timedelta64(i+1, 'D') for i in range(14)]
152
+
153
+ # Расчет тренда на первый день
154
+ trend_first_day = adjusted_future_predictions[0] - filtered_df['Adj Close'].iloc[-1]
155
+
156
+ # Расчет тренда на последний день
157
+ trend_last_day = adjusted_future_predictions[-1] - adjusted_future_predictions[0]
158
+
159
+ # Вывод прогнозов
160
+ print("Прогноз на 14 дней вперед:")
161
+ for i, (date, pred) in enumerate(zip(future_dates, adjusted_future_predictions)):
162
+ print(f"День {i+1} ({date}): Прогноз: {float(pred):.2f}")
163
+
164
+ # Вывод тренда на первый и последний день
165
+ trend_first_day_text = "Рост" if trend_first_day > 0 else "Падение" if trend_first_day < 0 else "Нет тренда"
166
+ trend_last_day_text = "Рост" if trend_last_day > 0 else "Падение" if trend_last_day < 0 else "Нет тренда"
167
+
168
+ st.write(f"Тренд на первый день: {trend_first_day_text}")
169
+ st.write(f"Тренд на последний день: {trend_last_day_text}")