File size: 4,786 Bytes
102d91b
 
 
8a71435
102d91b
8a71435
102d91b
8a71435
102d91b
 
8a71435
 
 
 
 
102d91b
8a71435
 
417c32f
8a71435
3953dff
8a71435
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55635e7
8a71435
55635e7
8a71435
 
 
 
 
 
 
 
 
102d91b
 
8a71435
55635e7
8a71435
55635e7
 
 
 
 
 
102d91b
55635e7
102d91b
 
 
8a71435
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102d91b
8a71435
102d91b
8a71435
 
 
 
 
 
 
 
 
102d91b
8a71435
 
 
 
 
 
 
 
102d91b
8a71435
 
 
 
 
 
 
 
 
 
102d91b
8a71435
 
102d91b
8a71435
102d91b
8a71435
 
 
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
131
132
133
import numpy as np
import pandas as pd
import plotly.express as px
import streamlit as st
import yfinance as yf
from sklearn import preprocessing
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split

# Streamlit app
st.title("CUSTOM Stock Price Prediction 💰")
st.write(
    'This model predicts based on trends. It may not perform well with volatile history. Setting the time frame to "max" is recommended. Your predicted days value cannot exceed the time frame days. Have fun!'
)

# Input widgets
stock = st.text_input("Stock ticker symbol", value="NVDA")
daysago = st.text_input(
    'Time frame in days (write "max" for maximum time)', value="max"
)
forecast_out = st.number_input("Predicted days", value=24, min_value=1)
forecast_col = "Close"


def prepare_data(df, forecast_col, forecast_out):
    # Check if the dataframe is empty or too small for forecast
    if df.empty or len(df) <= forecast_out:
        st.error("Insufficient data available for the given forecast period.")
        return None, None, None, None, None

    label = df[forecast_col].shift(
        -forecast_out
    )  # Shift the column to create a future prediction label
    X = np.array(df[[forecast_col]])  # Create feature array

    # Check if X has enough samples
    if X.shape[0] == 0:
        st.error("No data available for scaling.")
        return None, None, None, None, None

    X = preprocessing.scale(X)  # Scale the feature array
    X_lately = X[-forecast_out:]  # The data that will be predicted on
    X = X[:-forecast_out]  # Training data
    label.dropna(inplace=True)  # Drop NaN values from the label

    y = np.array(label)  # Target array

    # Check if we have enough data for train-test split
    if len(X) < 2 or len(y) < 2:  # Need at least two samples to split
        st.error(
            "Not enough data for splitting into training and testing sets. Please adjust the date range or prediction period."
        )
        return None, None, None, None, None

    X_train, X_test, Y_train, Y_test = train_test_split(
        X, y, test_size=0.2, random_state=42
    )  # Train/test split

    return X_train, X_test, Y_train, Y_test, X_lately


# Button to trigger model generation and prediction
if st.button("Generate"):
    # Ensure the days are in proper format
    if daysago != "max":
        try:
            # Convert daysago to the correct format recognized by yfinance
            daysago = str(int(daysago)) + "d"
        except ValueError:
            st.error("Invalid time frame. Please enter a number or 'max'.")
            st.stop()

    # Fetch stock data
    ticker = yf.Ticker(stock)
    data = ticker.history(period=daysago)

    if data.empty:
        st.error(
            "Failed to retrieve data for the ticker symbol. Please check the stock symbol and try again."
        )
    else:
        X_train, X_test, Y_train, Y_test, X_lately = prepare_data(
            data, forecast_col, forecast_out
        )  # Call data preparation method

        if X_train is not None:
            # Model generation
            learner = LinearRegression()
            learner.fit(X_train, Y_train)
            score = learner.score(X_test, Y_test)
            forecast = learner.predict(X_lately)

            st.write("Accuracy Score:", score)

            # Create a DataFrame with future dates and predicted values
            future_dates = pd.date_range(
                start=data.index[-1] + pd.Timedelta(days=1),
                periods=forecast_out,
                freq="D",
            )
            predicted_data = pd.DataFrame(
                {"Date": future_dates, "Predicted Close": forecast}
            )

            # Concatenate original data and predicted data
            combined_data = pd.concat(
                [
                    data.rename(columns={"Close": "Actual Close"}),
                    predicted_data.set_index("Date"),
                ],
                axis=1,
            )

            # Plot original and predicted stock prices
            fig = px.line(
                combined_data,
                x=combined_data.index,
                y=["Actual Close", "Predicted Close"],
                title=f"Predicted {stock} Stock Prices",
            )
            fig.update_layout(
                xaxis_title="Date", yaxis_title="Price", legend_title_text=""
            )

            # Set line colors
            fig.data[1].line.color = "orange"

            st.plotly_chart(fig)

            st.write(
                "Findings: Linear Regression often performs poorly on volatile stock prices, so this model may not be highly accurate for certain stocks. Consider using deep learning methods for improved accuracy on volatile stocks."
            )