CoolFace
Apppublic

Knight-coderr/StockAnalysis

sourceHugging Faceupdated 1y agoView on Hugging Face
12likes
app.py202 linesDownload Raw Back to root
1import streamlit as st2import pandas as pd3import yfinance as yf4from textblob import TextBlob5import joblib6import matplotlib.pyplot as plt7from datetime import datetime8import plotly.express as px9 10# Function to load stock data using yfinance/ this is going to refresh after 1 day11@st.cache_data(ttl=86400)12def load_stock_data(tickers, start_date, end_date):13    with st.spinner('Downloading stock data...'):14        data = yf.download(tickers, start=start_date, end=end_date, group_by='ticker', auto_adjust=True)15        16        all_data = []17        for ticker in tickers:18            df = data[ticker].copy().reset_index()19            df['Stock Name'] = ticker20            all_data.append(df)21 22        merged_data = pd.concat(all_data, ignore_index=True)23    return merged_data24 25tickers = ['TSLA', 'MSFT', 'PG', 'META', 'AMZN', 'GOOG', 'AMD', 'AAPL', 'NFLX', 'TSM',26           'KO', 'F', 'COST', 'DIS', 'VZ', 'CRM', 'INTC', 'BA', 'BX', 'NOC', 'PYPL', 'ENPH', 'NIO', 'ZS', 'XPEV']27start_date = (datetime.today() - pd.DateOffset(years=1)).strftime('%Y-%m-%d')28end_date = datetime.today().strftime('%Y-%m-%d')29 30# Cache stock data for 1 day using st.cache_data31@st.cache_data(ttl=86400)32def load_and_cache_stock_data():33    return load_stock_data(tickers, start_date, end_date)34 35# Initialize stock_data once at app startup36if "stock_data" not in st.session_state:37    st.session_state["stock_data"] = load_and_cache_stock_data()38 39stock_data = st.session_state["stock_data"]40 41 42# Perform sentiment analysis on tweets (assuming you still have your tweets data)43tweets_data = pd.read_csv('data/stock_tweets.csv')44 45# Convert the Date columns to datetime46tweets_data['Date'] = pd.to_datetime(tweets_data['Date']).dt.date47 48# Perform sentiment analysis on tweets49def get_sentiment(tweet):50    analysis = TextBlob(tweet)51    return analysis.sentiment.polarity52 53tweets_data['Sentiment'] = tweets_data['Tweet'].apply(get_sentiment)54 55# Aggregate sentiment by date and stock56daily_sentiment = tweets_data.groupby(['Date', 'Stock Name']).mean(numeric_only=True).reset_index()57 58# Convert the Date column in daily_sentiment to datetime64[ns]59daily_sentiment['Date'] = pd.to_datetime(daily_sentiment['Date'])60 61# Merge stock data with sentiment data62merged_data = pd.merge(stock_data, daily_sentiment, how='left', on=['Date', 'Stock Name'])63 64# Fill missing sentiment values with 0 (neutral sentiment)65merged_data['Sentiment'] = merged_data['Sentiment'].fillna(0)66 67# Sort the data by date68merged_data = merged_data.sort_values(by='Date')69 70# Create lagged features71merged_data['Prev_Close'] = merged_data.groupby('Stock Name')['Close'].shift(1)72merged_data['Prev_Sentiment'] = merged_data.groupby('Stock Name')['Sentiment'].shift(1)73 74# Create moving averages75merged_data['MA7'] = merged_data.groupby('Stock Name')['Close'].transform(lambda x: x.rolling(window=7).mean())76merged_data['MA14'] = merged_data.groupby('Stock Name')['Close'].transform(lambda x: x.rolling(window=14).mean())77 78# Create daily price changes79merged_data['Daily_Change'] = merged_data['Close'] - merged_data['Prev_Close']80 81# Create volatility82merged_data['Volatility'] = merged_data.groupby('Stock Name')['Close'].transform(lambda x: x.rolling(window=7).std())83 84# Drop rows with missing values85merged_data.dropna(inplace=True)86 87# Load the best model88model_filename = 'model/best_model.pkl'89model = joblib.load(model_filename)90 91# Streamlit application layout92st.title("Stock Price Prediction Using Sentiment Analysis")93 94# User input for stock data95st.header("Input Stock Data")96stock_names = merged_data['Stock Name'].unique()97selected_stock = st.selectbox("Select Stock Name", stock_names)98days_to_predict = st.number_input("Number of Days to Predict", min_value=1, max_value=30, value=10)99 100# Get the latest data for the selected stock101latest_data = merged_data[merged_data['Stock Name'] == selected_stock].iloc[-1]102prev_close = latest_data['Close']103prev_sentiment = latest_data['Sentiment']104ma7 = latest_data['MA7']105ma14 = latest_data['MA14']106daily_change = latest_data['Daily_Change']107volatility = latest_data['Volatility']108 109# Display the latest stock data in a table110latest_data_df = pd.DataFrame({111    'Metric': ['Previous Close Price', 'Previous Sentiment', '7-day Moving Average', '14-day Moving Average', 'Daily Change', 'Volatility'],112    'Value': [prev_close, prev_sentiment, ma7, ma14, daily_change, volatility]113})114 115st.write("Latest Stock Data:")116st.write(latest_data_df)117 118st.write("Use the inputs above to predict the next days close prices of the stock.")119if st.button("Predict"):120    predictions = []121    latest_date = datetime.now()122 123    for i in range(days_to_predict):124        X_future = pd.DataFrame({125            'Prev_Close': [prev_close],126            'Prev_Sentiment': [prev_sentiment],127            'MA7': [ma7],128            'MA14': [ma14],129            'Daily_Change': [daily_change],130            'Volatility': [volatility]131        })132 133        next_day_prediction = model.predict(X_future)[0]134        predictions.append(next_day_prediction)135 136        # Update features for next prediction137        prev_close = next_day_prediction138        ma7 = (ma7 * 6 + next_day_prediction) / 7  # Simplified rolling calculation139        ma14 = (ma14 * 13 + next_day_prediction) / 14  # Simplified rolling calculation140        daily_change = next_day_prediction - prev_close141 142    # Prepare prediction data for display143    prediction_dates = pd.date_range(start=latest_date + pd.Timedelta(days=1), periods=days_to_predict)144    prediction_df = pd.DataFrame({145        'Date': prediction_dates,146        'Predicted Close Price': predictions147    })148 149    st.subheader("Predicted Prices")150    st.dataframe(prediction_df)151    152    # Plot predictions using Plotly153    fig = px.line(prediction_df, x='Date', y='Predicted Close Price', markers=True, title=f"{selected_stock} Predicted Close Prices")154    st.plotly_chart(fig, use_container_width=True)155 156    # ----------------------------------------157    # Enhanced Visualizations158    st.header("Enhanced Stock Analysis")159    stock_history = merged_data[merged_data['Stock Name'] == selected_stock]160 161    # Date filter slider162    min_date = pd.to_datetime(merged_data['Date'].min()).date()163    max_date = pd.to_datetime(merged_data['Date'].max()).date()164    165    date_range = st.slider(166        "Select Date Range for Visualizations",167        min_value=min_date,168        max_value=max_date,169        value=(min_date, max_date),170        format="YYYY-MM-DD"171    )172 173    filtered_data = stock_history[(stock_history['Date'] >= pd.to_datetime(date_range[0])) & 174                              (stock_history['Date'] <= pd.to_datetime(date_range[1]))]175 176    with st.expander("Price vs Sentiment Trend"):177        fig1 = px.line(filtered_data, x='Date', y=['Close', 'Sentiment'],178                       labels={'value': 'Price / Sentiment', 'variable': 'Metric'},179                       title=f"{selected_stock} - Close Price & Sentiment")180        st.plotly_chart(fig1, use_container_width=True)181 182    with st.expander("Volatility Over Time"):183        fig2 = px.line(filtered_data, x='Date', y='Volatility',184                       title=f"{selected_stock} - 7-Day Rolling Volatility")185        st.plotly_chart(fig2, use_container_width=True)186 187    with st.expander("Moving Averages (MA7 vs MA14)"):188        fig3 = px.line(filtered_data, x='Date', y=['MA7', 'MA14'],189                       labels={'value': 'Price', 'variable': 'Moving Average'},190                       title=f"{selected_stock} - Moving Averages")191        st.plotly_chart(fig3, use_container_width=True)192 193    with st.expander("Daily Price Change"):194        fig4 = px.line(filtered_data, x='Date', y='Daily_Change',195                       title=f"{selected_stock} - Daily Price Change")196        st.plotly_chart(fig4, use_container_width=True)197 198    with st.expander("Sentiment Distribution"):199        fig5 = px.histogram(filtered_data, x='Sentiment', nbins=30,200                            title=f"{selected_stock} - Sentiment Score Distribution")201        st.plotly_chart(fig5, use_container_width=True)202