File size: 6,208 Bytes
821b9f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6d02cce
821b9f1
879b684
821b9f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0063565
 
 
 
 
 
821b9f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import streamlit as st
import yfinance as yf
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from tensorflow.keras.models import load_model
import plotly.graph_objs as go
import numpy as np
import base64

# Function to make predictions using the LSTM model
def make_predictions(model, data, scaler, look_back, prediction_days):
    predictions = []
    scaled_data = scaler.transform(data[-look_back:].reshape(-1, 1))
    scaled_data = scaled_data.reshape((1, look_back, 1))
    
    for _ in range(prediction_days):
        # Make the prediction
        predicted_price = model.predict(scaled_data)
        # Inverse transform to get the actual price
        predicted_price = scaler.inverse_transform(predicted_price)
        predictions.append(predicted_price.ravel()[0])
        
        # Append prediction to scaled_data for making subsequent predictions
        next_input = scaler.transform(predicted_price.reshape(-1, 1))
        scaled_data = np.append(scaled_data[:, 1:, :], [next_input], axis=1)
        
    return predictions


# Function to download prediction data as a CSV file
def get_table_download_link(df):
    csv = df.to_csv(index=True)
    b64 = base64.b64encode(csv.encode()).decode()
    href = f'<a href="data:file/csv;base64,{b64}" download="predictions.csv">Download CSV file</a>'
    return href


# Streamlit app layout
st.title('Real-time Crypto Prediction with LSTM')

# User input parameters (no longer in the sidebar)
st.header('User Input Parameters')
ticker = st.selectbox('Select Ticker', ('BTC-USD', 'ETH-USD', 'LTC-USD'))
start_date = st.date_input('Start date', pd.to_datetime('2021-01-01'))
end_date = st.date_input('End date', pd.to_datetime('2023-11-01'))
look_back = st.number_input('Look Back Period',value=60)
prediction_days = st.slider('Days to Predict', 1, 30, 3)

# Load pre-trained LSTM model and scaler
with st.spinner('Loading model and scaler...'):
    model = load_model('./best_model.h5')  # make sure to use the correct path to your model
    scaler = MinMaxScaler(feature_range=(0, 1))  # Assuming the scaler was fitted to the training data

# Fetch historical data from yfinance
with st.spinner(f'Downloading {ticker} data...'):
    data = yf.download(ticker, start=start_date, end=end_date)
st.success('Downloaded data successfully!')

# Prepare data for prediction
data_close = data['Close'].values.reshape(-1, 1)
scaler.fit(data_close)

# Make real-time prediction
if len(data_close) >= look_back:
    with st.spinner('Making predictions...'):
        predictions = make_predictions(model, data_close, scaler, look_back, prediction_days)
        # Convert predictions to a list of Python floats
        predictions_list = [float(pred) for pred in predictions]
    st.success('Predictions made successfully!')

    # Plot the results using Plotly
    fig = go.Figure()
    fig.add_trace(go.Scatter(x=data.index, y=data['Close'], mode='lines+markers', name='Close Price'))
    
    # Generate prediction dates without using the 'closed' parameter
    last_date = data.index[-1]
    prediction_dates = pd.date_range(start=last_date, periods=prediction_days+1)[1:]
    # The [1:] slice is used to exclude the starting date and effectively achieve 'closed=right'

    # Add predicted prices to the plot
    fig.add_trace(go.Scatter(x=prediction_dates, y=predictions_list, mode='lines+markers', name='Predicted Price', marker=dict(color='red')))
    fig.update_layout(title='Cryptocurrency Price Prediction', xaxis_title='Date', yaxis_title='Price', legend_title='Legend')
    st.plotly_chart(fig, use_container_width=True)

    # Display download link for predictions with actual prices included
    prediction_df = pd.DataFrame(index=prediction_dates)
    prediction_df['Predicted Price'] = predictions_list
    prediction_df['Actual Price'] = data['Close'][-prediction_days:].values
    st.markdown(get_table_download_link(prediction_df), unsafe_allow_html=True)

    # Display the last prediction
    st.write(f'Last Predicted Closing Price for {ticker}: ${predictions_list[-1]:.2f}')
    
    # Simulate investment results based on predictions
    # Simulate investment results based on the last prediction
    initial_account_balance = 1000000  
    account_balance_predicted = initial_account_balance
    account_balance_actual = initial_account_balance

    # Get the last actual closing price and the last predicted price
    last_invest_price = data['Close'].iloc[-prediction_days-1]  # Price at which we "buy"
    last_sell_price_predicted = predictions_list[-1]  # Predicted price at which we "sell"
    last_sell_price_actual = data['Close'].iloc[-prediction_days] if prediction_days <= len(data['Close']) else last_sell_price_predicted

    # Update account balances based on the last day's prediction and actual price
    account_balance_predicted += (last_sell_price_predicted - last_invest_price) * (account_balance_predicted / last_invest_price)
    account_balance_actual += (last_sell_price_actual - last_invest_price) * (account_balance_actual / last_invest_price)


    # Assuming investing at the closing price and selling at the next day's predicted/actual price
    for i in range(1, prediction_days + 1):
        invest_price = data['Close'].iloc[-i-1]  # Price at which we "buy"
        sell_price_predicted = predictions_list[-i]  # Predicted price at which we "sell"
        sell_price_actual = data['Close'].iloc[-i] if i <= len(data['Close']) else sell_price_predicted

        # Update account balances
        account_balance_predicted += (sell_price_predicted - invest_price) * (account_balance_predicted / invest_price)
        account_balance_actual += (sell_price_actual - invest_price) * (account_balance_actual / invest_price)

    # Display simulated investment results
    st.write(f"Initial Account Balance: ${initial_account_balance:,.2f}")
    st.write(f"Account Balance based on Predictions: ${account_balance_predicted:,.2f}")
    st.write(f"Account Balance based on Actual Prices: ${account_balance_actual:,.2f}")

else:
    st.error('Not enough data to make a prediction.')

# Refresh the page to update the predictions
if st.button("Refresh Predictions"):
    st.experimental_rerun()