Solar-Iz commited on
Commit
9943273
·
verified ·
1 Parent(s): 53f2004

Update pages/3_BiLTSM_Прогноз bitcoin.py

Browse files
pages/3_BiLTSM_Прогноз bitcoin.py CHANGED
@@ -1,46 +1,36 @@
1
  import streamlit as st
2
- import torch
3
- import torch.nn as nn
4
- import numpy as np
5
  import pandas as pd
 
6
  import matplotlib.pyplot as plt
7
- from sklearn.preprocessing import MinMaxScaler
8
- from datetime import timedelta
9
- import yfinance as yf
10
- from model.lstm_model import BiLSTM
11
  import torch.optim as optim
 
 
 
 
 
12
 
 
 
 
 
13
 
14
- # # Загрузка данных для BTC-USD
15
- # def load_data():
16
- # START = "2023-01-01" # Замените на нужную вам дату начала
17
- # TODAY = "2024-01-01" # Замените на текущую дату или нужную вам дату окончания
18
- # btc_usdt = yf.download('BTC-USD', START, TODAY)
19
- # btc_usdt.reset_index(inplace=True)
20
- # return btc_usdt
21
 
22
- # # Загрузка данных для BTC_USDT
23
- # btc_usdt = load_data()
 
24
 
25
- # Загрузка данных из файла CSV
26
- data_path = "model/BTC-USD_data.csv"
27
- btc_usdt = pd.read_csv(data_path)
28
 
29
  scaler = MinMaxScaler(feature_range=(0, 1))
30
- scaled_data = scaler.fit_transform(btc_usdt['Adj Close'].values.reshape(-1, 1))
31
-
32
- def rmse(predictions, targets):
33
- return np.sqrt(((predictions - targets) ** 2).mean())
34
-
35
- def mape(predictions, targets):
36
- return np.mean(np.abs((targets - predictions) / targets)) * 100
37
 
38
- def weighted_mape(predictions, targets, weights):
39
- errors = np.abs(targets - predictions)
40
- weighted_errors = errors * weights
41
- weighted_mape = np.sum(weighted_errors) / np.sum(np.abs(targets) * weights) * 100
42
- return weighted_mape
43
-
44
  def create_dataset(data, time_step=1):
45
  X, Y = [], []
46
  for i in range(len(data)-time_step-1):
@@ -49,94 +39,105 @@ def create_dataset(data, time_step=1):
49
  Y.append(data[i + time_step, 0])
50
  return np.array(X), np.array(Y)
51
 
52
- time_step = 14
53
-
54
- X, y = create_dataset(scaled_data, time_step)
55
 
56
  # Разделяем данные на обучающую и тестовую выборки
57
- test_size = 14 # 14 дней для теста
58
  train_size = len(X) - test_size
59
  X_train, X_test = X[:train_size], X[train_size:]
60
  y_train, y_test = y[:train_size], y[train_size:]
61
 
62
- X_train = torch.Tensor(X_train).unsqueeze(-1) # Добавляем размерность
63
- X_test = torch.Tensor(X_test).unsqueeze(-1) # Для совместимости с LSTM
64
  y_train = torch.Tensor(y_train)
65
  y_test = torch.Tensor(y_test)
66
 
67
- # Загрузка весов модели
68
- weights_path = "model/model_weights.pth"
69
  input_size = 1
70
- hidden_size = 128 # Используем тот же размер, что и при обучении
71
- num_layers = 3 # Используем тот же размер, что и при обучении
72
  output_size = 1
73
-
74
- # Создание BiLSTM модели
75
  model = BiLSTM(input_size, hidden_size, num_layers, output_size)
76
  criterion = nn.MSELoss()
77
- optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
78
 
79
- # Загрузка весов
80
- model.load_state_dict(torch.load(weights_path))
81
  model.eval()
82
-
83
- # Получение предсказаний с помощью загруженной модели
84
  with torch.no_grad():
85
  test_predictions = model(X_test)
86
  test_loss = criterion(test_predictions, y_test.view(-1, 1))
87
 
88
- test_predictions = scaler.inverse_transform(test_predictions.numpy())
89
- y_test = scaler.inverse_transform(y_test.numpy().reshape(-1, 1))
90
- test_rmse = rmse(test_predictions, y_test)
91
- test_mape = mape(test_predictions, y_test)
 
92
  weights = np.array([1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4])
93
- test_weighted_mape = weighted_mape(test_predictions, y_test, weights)
94
 
95
- # Вывод графика и метрик
96
- st.title("Bitcoin Price Prediction")
97
- st.write("### Predictions vs Actual (Last 14 Days)")
98
 
99
- # Генерация предсказаний для будущих дат
100
- with torch.no_grad():
101
- future_predictions = model(X_test) # Предсказания для тестовой выборки
102
- future_predictions = scaler.inverse_transform(future_predictions.numpy())
103
 
104
- # Генерация дат для будущих предсказаний
105
- future_dates = [btc_usdt['Date'].values[-1] + np.timedelta64(i + 1, 'D') for i in range(14)]
106
-
107
- # Преобразование предсказаний для будущих дат в формат DataFrame
108
- future_df = pd.DataFrame({
109
- 'Date': future_dates,
110
- 'Predicted_Price': future_predictions.flatten()
111
- })
112
-
113
- # Вывод графика предсказаний на будущие даты
114
- st.line_chart(future_df.set_index('Date')['Predicted_Price'], use_container_width=True)
115
- st.title("Future Bitcoin Price Predictions")
116
-
117
- # Вывод метрик по кнопке
118
- if st.button("Show Metrics"):
119
- st.write("### Test Metrics")
120
- st.write(f"**Test Loss:** {test_loss.item():.4f}")
121
- st.write(f"**Test RMSE:** {test_rmse:.4f}")
122
- st.write(f"**Test MAPE:** {test_mape:.4f}%")
123
- st.write(f"**Test Weighted MAPE:** {test_weighted_mape:.4f}%")
124
- # Вывод графика предсказаний на будущие даты
125
- st.line_chart(future_df.set_index('Date')['Predicted_Price'], use_container_width=True)
126
- st.title("Future Bitcoin Price Predictions")
127
-
128
- # Вывод метрик
129
- st.write("### Future Predictions (Next 14 Days)")
130
- st.write(f"**Average Predicted Price:** {future_df['Predicted_Price'].mean():.2f}")
131
- st.write(f"**Maximum Predicted Price:** {future_df['Predicted_Price'].max():.2f}")
132
- st.write(f"**Minimum Predicted Price:** {future_df['Predicted_Price'].min():.2f}")
133
 
134
- # Вывод тренда на первый и последний день
135
- trend_first_day = future_df['Predicted_Price'].iloc[0] - btc_usdt['Adj Close'].iloc[-1]
136
- trend_last_day = future_df['Predicted_Price'].iloc[-1] - future_df['Predicted_Price'].iloc[0]
 
 
 
 
 
 
 
 
 
 
 
 
137
 
138
- trend_first_day_text = "Growth" if trend_first_day > 0 else "Decline" if trend_first_day < 0 else "No trend"
139
- trend_last_day_text = "Growth" if trend_last_day > 0 else "Decline" if trend_last_day < 0 else "No trend"
140
 
141
- st.write(f"**Trend on the First Day:** {trend_first_day_text}")
142
- st.write(f"**Trend on the Last Day:** {trend_last_day_text}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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.lstm_model import BiLSTM
11
+ from sklearn.metrics import mean_squared_error
12
+ from sklearn.preprocessing import MinMaxScaler
13
+ import plotly.graph_objects as go
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
+ df['Date'] = pd.to_datetime(df['Date']) # Преобразование в формат datetime
27
 
28
+ latest_date = df['Date'].iloc[-1].strftime('%Y-%m-%d')
29
+ st.markdown(f"<h3 style='text-align: center;'>Цены актуальны на последнюю дату закрытия торгов {latest_date}</h3>", unsafe_allow_html=True)
 
30
 
31
  scaler = MinMaxScaler(feature_range=(0, 1))
32
+ scaled_data = scaler.fit_transform(df['Adj Close'].values.reshape(-1, 1))
 
 
 
 
 
 
33
 
 
 
 
 
 
 
34
  def create_dataset(data, time_step=1):
35
  X, Y = [], []
36
  for i in range(len(data)-time_step-1):
 
39
  Y.append(data[i + time_step, 0])
40
  return np.array(X), np.array(Y)
41
 
42
+ X, y = create_dataset(scaled_data, time_step=period)
 
 
43
 
44
  # Разделяем данные на обучающую и тестовую выборки
45
+ test_size = period
46
  train_size = len(X) - test_size
47
  X_train, X_test = X[:train_size], X[train_size:]
48
  y_train, y_test = y[:train_size], y[train_size:]
49
 
50
+ X_train = torch.Tensor(X_train).unsqueeze(-1)
51
+ X_test = torch.Tensor(X_test).unsqueeze(-1)
52
  y_train = torch.Tensor(y_train)
53
  y_test = torch.Tensor(y_test)
54
 
 
 
55
  input_size = 1
56
+ hidden_size = 128
57
+ num_layers = 3
58
  output_size = 1
 
 
59
  model = BiLSTM(input_size, hidden_size, num_layers, output_size)
60
  criterion = nn.MSELoss()
61
+ optimizer = optim.Adam(model.parameters(), lr=0.001)
62
 
63
+ model.load_state_dict(torch.load('model/model_weights.pth'))
 
64
  model.eval()
 
 
65
  with torch.no_grad():
66
  test_predictions = model(X_test)
67
  test_loss = criterion(test_predictions, y_test.view(-1, 1))
68
 
69
+ test_predictions = scaler.inverse_transform(test_predictions.cpu().numpy())
70
+ y_test = scaler.inverse_transform(y_test.view(-1, 1).cpu().numpy())
71
+
72
+ test_rmse = np.sqrt(mean_squared_error(test_predictions, y_test))
73
+ test_mape = np.mean(np.abs((y_test - test_predictions) / y_test)) * 100
74
  weights = np.array([1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4])
75
+ test_weighted_mape = np.sum(np.abs(y_test - test_predictions) * weights) / np.sum(np.abs(y_test) * weights) * 100
76
 
77
+ st.write(f'Test RMSE: {test_rmse:.4f}')
78
+ st.write(f'Test MAPE: {test_mape:.4f}%')
79
+ st.write(f'Test Weighted MAPE: {test_weighted_mape:.4f}%')
80
 
 
 
 
 
81
 
82
+ # Получение дат для будущих предсказаний
83
+ future_dates = pd.date_range(df['Date'].iloc[-1] + timedelta(days=1), periods=14)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
 
85
+ # Прогнозы с учетом трендов
86
+ trend_first_day = test_predictions[0] - df['Adj Close'].iloc[-1]
87
+ trend_last_day = test_predictions[-1] - test_predictions[0]
88
+ adjusted_future_predictions = [df['Adj Close'].iloc[-1] + trend_first_day + (trend_last_day / 14) * i for i in range(14)]
89
+
90
+ # Создание графика
91
+ plt.figure(figsize=(12, 6))
92
+ plt.plot(df['Date'], df['Adj Close'], label='Actual', linewidth=2)
93
+ plt.plot(future_dates, adjusted_future_predictions, label='Предсказание на 14 дней', linestyle='--', linewidth=2)
94
+
95
+ plt.title('Предсказание стоимости Bitcoin на 14 Дней')
96
+ plt.xlabel('Date')
97
+ plt.ylabel('Price')
98
+ plt.xticks(rotation=45)
99
+ plt.legend()
100
 
101
+ # Отображение графика в Streamlit
102
+ st.pyplot(plt)
103
 
104
+ # Вывод прогнозов
105
+ st.write("Прогноз на 14 дней вперед:")
106
+ for i, (date, pred) in enumerate(zip(future_dates, adjusted_future_predictions)):
107
+ st.write(f"День {i + 1} ({date}): Прогноз: {float(pred):.2f}")
108
+
109
+ # Вывод тренда на первый и последний день
110
+ trend_first_day_text = "Рост" if trend_first_day > 0 else "Падение" if trend_first_day < 0 else "Нет тренда"
111
+ trend_last_day_text = "Рост" if trend_last_day > 0 else "Падение" if trend_last_day < 0 else "Нет тренда"
112
+
113
+ st.write(f"Тренд на первый день: {trend_first_day_text}")
114
+ st.write(f"Тренд на последний день: {trend_last_day_text}")
115
+
116
+ # Создание графика с использованием Plotly
117
+ fig = go.Figure()
118
+ # График для фактических данных
119
+ fig.add_trace(go.Scatter(x=df['Date'], y=df['Adj Close'], mode='lines', name='Фактические данные', line=dict(width=2)))
120
+ # График для предсказаний на 14 дней
121
+ fig.add_trace(go.Scatter(x=future_dates, y=adjusted_future_predictions, mode='lines', name='Прогноз (14 дней)', line=dict(width=2, dash='dash')))
122
+
123
+ # Настройки макета графика
124
+ fig.update_layout(
125
+ title='Прогноз стоимости Bitcoin на следующие 14 дней',
126
+ xaxis_title='Дата',
127
+ yaxis_title='Цена',
128
+ xaxis=dict(tickangle=-45),
129
+ legend=dict(x=0, y=1, traceorder='normal'),
130
+ margin=dict(l=0, r=0, t=30, b=0),
131
+
132
+ # range slider
133
+ xaxis_rangeslider=dict(
134
+ visible=True,
135
+ thickness=0.05, # Толщина слайдера
136
+ bordercolor='white', # Цвет границы слайдера
137
+ bgcolor='rgba(219, 219, 219, 0.25)', # Цвет фона слайдера
138
+ range=[df['Date'].iloc[0], future_dates[-1]] # Обновление диапазона дат
139
+ )
140
+ )
141
+
142
+ # Отображение графика
143
+ st.plotly_chart(fig, use_container_width=True)