Spaces:
Sleeping
Sleeping
Анастасия
commited on
Commit
·
8eaf5b2
1
Parent(s):
a0ac03a
- .DS_Store +0 -0
- pages/3_🪙_Прогноз_Bitcoin USD. BiLSTM.py +169 -0
.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}")
|