Akshit Chaturvedi commited on
Commit
a3a6afc
ยท
1 Parent(s): 59edb04

initial commit

Browse files
Files changed (5) hide show
  1. .github/workflows/sync-to-hf-space.yml +40 -0
  2. README.md +58 -0
  3. app.py +154 -0
  4. readme.md +0 -1
  5. requirements.txt +6 -0
.github/workflows/sync-to-hf-space.yml ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # .github/workflows/sync-to-hf-space.yml
2
+ name: Sync to Hugging Face Space
3
+
4
+ on:
5
+ push:
6
+ branches:
7
+ - main # Or whatever your default branch is
8
+
9
+ jobs:
10
+ sync:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - name: Checkout repository
14
+ uses: actions/checkout@v3
15
+ with:
16
+ fetch-depth: 0 # Fetch all history for accurate diffs
17
+
18
+ - name: Push to Hugging Face Space
19
+ env:
20
+ HF_TOKEN: ${{ secrets.HF_TOKEN }}
21
+ # Your Hugging Face username
22
+ HF_USERNAME: GuitarGeorge
23
+ # The ID of your Space (username/space-name)
24
+ SPACE_ID: GuitarGeorge/Neural-Prophet-Predictor
25
+ run: |
26
+ echo "Attempting to push to Hugging Face Space: $SPACE_ID"
27
+ # Add Hugging Face as a remote
28
+ git remote add hf_space "https://dummy:${HF_TOKEN}@huggingface.co/spaces/${SPACE_ID}"
29
+
30
+ # Check if the remote was added
31
+ git remote -v
32
+
33
+ # Configure Git user
34
+ git config --global user.email "action@github.com"
35
+ git config --global user.name "GitHub Action"
36
+
37
+ # Force push to ensure the Space mirrors GitHub
38
+ git push --force hf_space HEAD:refs/heads/main
39
+
40
+ echo "Push to Hugging Face Space completed."
README.md ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Neural Prophet Stock Predictor
3
+ emoji: ๐Ÿ”ฎ
4
+ colorFrom: indigo
5
+ colorTo: blue
6
+ sdk: gradio
7
+ sdk_version: 5.29.1
8
+ app_file: app.py
9
+ python_version: 3.10
10
+ pinned: false
11
+ ---
12
+
13
+ # NeuralProphet Stock Predictor ๐Ÿ“ˆ
14
+
15
+ ## Project Goal
16
+ This project uses **NeuralProphet**, a PyTorch-based hybrid forecasting framework (inspired by Facebook Prophet and Neural Networks), to predict the **90-day forward price** for any valid stock ticker found on Yahoo Finance.
17
+
18
+ Unlike simple linear regressions, this model accounts for time-series specific components such as:
19
+ - **Trend Changes:** Detecting shifts in the stock's growth trajectory.
20
+ - **Seasonality:** analyzing Yearly and Weekly patterns (e.g., does the stock typically rise in January?).
21
+
22
+ ## How to Use
23
+
24
+ ### Using the UI
25
+ 1. Enter a valid Ticker Symbol in the textbox (e.g., `AAPL` for Apple, `AZN.L` for AstraZeneca UK).
26
+ 2. Click **"Analyze Stock"**.
27
+ 3. Wait approximately 10-30 seconds for the model to train on-the-fly.
28
+ 4. View the **ROI Verdict**, the **Forecast Chart**, and the **Seasonality breakdown**.
29
+
30
+ ### Interpretation
31
+ - **Blue Line (Forecast):** The predicted price path.
32
+ - **Yearly Seasonality:** Shows which months are historically bullish or bearish for this specific asset.
33
+ - **Verdict:**
34
+ - ๐ŸŸข **STRONG BUY:** ROI > 10%
35
+ - ๐ŸŸข **BUY:** ROI > 2%
36
+ - ๐ŸŸก **HOLD:** ROI > -5%
37
+ - ๐Ÿ”ด **SELL:** ROI <= -5%
38
+
39
+ ## Model Methodology
40
+
41
+ This application trains a *fresh* model every time you request a ticker. It does not use pre-trained weights because stock data changes daily.
42
+
43
+ 1. **Data Fetching:** Downloads 3 years of daily historical data via `yfinance`.
44
+ 2. **Preprocessing:** Cleans data and handles timezone formatting.
45
+ 3. **Training:** Fits a NeuralProphet model with:
46
+ * Yearly Seasonality: Enabled
47
+ * Weekly Seasonality: Enabled
48
+ * Daily Seasonality: Disabled (Noise reduction)
49
+ * Learning Rate: 0.01
50
+ 4. **Forecasting:** Projects 90 days into the future.
51
+
52
+ ## Tech Stack
53
+ - **NeuralProphet:** For time-series forecasting.
54
+ - **YFinance:** For live market data.
55
+ - **Gradio:** For the web interface.
56
+ - **Plotly:** For interactive charting.
57
+
58
+ *Disclaimer: Stock market predictions are inherently uncertain. Do not trade based solely on these results.*
app.py ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ import logging
4
+ import warnings
5
+ import os
6
+ import yfinance as yf
7
+ import pandas as pd
8
+ from neuralprophet import NeuralProphet
9
+ import plotly.graph_objs as go
10
+
11
+ # --- STEP 1: CONFIGURATION & PATCHES ---
12
+
13
+ # Suppress messy logs
14
+ logging.getLogger("neuralprophet").setLevel(logging.ERROR)
15
+ logging.getLogger("pytorch_lightning").setLevel(logging.ERROR)
16
+ warnings.filterwarnings("ignore")
17
+ os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
18
+
19
+ # Fix for PyTorch 2.6+ security check
20
+ original_load = torch.load
21
+ def patched_load(*args, **kwargs):
22
+ if 'weights_only' not in kwargs:
23
+ kwargs['weights_only'] = False
24
+ return original_load(*args, **kwargs)
25
+ torch.load = patched_load
26
+
27
+ # --- STEP 2: PREDICTION LOGIC ---
28
+
29
+ def predict_stock(ticker):
30
+ """
31
+ Takes a ticker symbol, trains a NeuralProphet model,
32
+ and returns a textual report and two Plotly figures.
33
+ """
34
+ ticker = ticker.strip().upper()
35
+
36
+ if not ticker:
37
+ return "โš ๏ธ Please enter a ticker symbol.", None, None
38
+
39
+ status_msg = f"โณ Analyzing {ticker}... Please wait (approx 10-30 seconds)."
40
+ print(f"Processing {ticker}")
41
+
42
+ try:
43
+ # 1. Get Data
44
+ data = yf.download(ticker, period="3y", interval="1d", progress=False)
45
+
46
+ # Handle cases where yfinance returns empty dataframe or multi-index columns
47
+ if data.empty:
48
+ return f"โŒ Could not find data for ticker '{ticker}'. Please check the symbol.", None, None
49
+
50
+ # Flatten MultiIndex if present (yfinance update quirk)
51
+ if isinstance(data.columns, pd.MultiIndex):
52
+ try:
53
+ # Attempt to extract just the Close column for the specific ticker
54
+ df = data.xs(ticker, axis=1, level=1)
55
+ if 'Close' in df.columns:
56
+ df = df[['Close']].reset_index()
57
+ else:
58
+ # Fallback for single level extraction
59
+ df = data['Close'].reset_index()
60
+ except:
61
+ # Brute force flatten
62
+ df = data.copy()
63
+ df.columns = ['_'.join(col).strip() for col in df.columns.values]
64
+ # Look for a column containing "Close"
65
+ close_col = [c for c in df.columns if "Close" in c][0]
66
+ df = df[[close_col]].reset_index()
67
+ else:
68
+ df = data[['Close']].reset_index()
69
+
70
+ # Rename for NeuralProphet
71
+ df.columns = ['ds', 'y']
72
+
73
+ # Ensure dates are timezone-naive
74
+ df['ds'] = df['ds'].dt.tz_localize(None)
75
+
76
+ if len(df) < 100:
77
+ return f"โŒ Not enough historical data found for {ticker} (Need > 100 days).", None, None
78
+
79
+ # 2. Train Model
80
+ m = NeuralProphet(
81
+ yearly_seasonality=True,
82
+ weekly_seasonality=True,
83
+ daily_seasonality=False,
84
+ learning_rate=0.01,
85
+ # Disable progress bars for clean logs
86
+ trainer_config={"enable_progress_bar": False}
87
+ )
88
+
89
+ m.fit(df, freq="D")
90
+
91
+ # 3. Predict 90 Days out
92
+ future = m.make_future_dataframe(df, periods=90)
93
+ forecast = m.predict(future)
94
+
95
+ # 4. Extract Metrics
96
+ current_price = df['y'].iloc[-1]
97
+ predicted_price = forecast['yhat1'].iloc[-1]
98
+
99
+ # Calculate ROI
100
+ roi = ((predicted_price - current_price) / current_price) * 100
101
+
102
+ # Generate Verdict
103
+ if roi > 10: verdict = "STRONG BUY ๐ŸŸข"
104
+ elif roi > 2: verdict = "BUY ๐ŸŸข"
105
+ elif roi > -5: verdict = "HOLD ๐ŸŸก"
106
+ else: verdict = "SELL ๐Ÿ”ด"
107
+
108
+ # 5. formatting Output Text
109
+ report = f"""
110
+ ### ๐Ÿ“Š Analysis Report: {ticker}
111
+ **Current Price:** {current_price:.2f}
112
+ **90-Day Target:** {predicted_price:.2f}
113
+ **Projected ROI:** {roi:.2f}%
114
+ **Verdict:** {verdict}
115
+
116
+ *Disclaimer: This is an AI-generated forecast based on historical trends. Not financial advice.*
117
+ """
118
+
119
+ # 6. Generate Plots
120
+ # NeuralProphet plot() returns a plotly figure object
121
+ fig_forecast = m.plot(forecast)
122
+ fig_components = m.plot_components(forecast)
123
+
124
+ return report, fig_forecast, fig_components
125
+
126
+ except Exception as e:
127
+ import traceback
128
+ traceback.print_exc()
129
+ return f"โŒ An error occurred while processing {ticker}: {str(e)}", None, None
130
+
131
+ # --- STEP 3: GRADIO INTERFACE ---
132
+
133
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
134
+ gr.Markdown("# ๐Ÿ“ˆ NeuralProphet Stock Predictor")
135
+ gr.Markdown("Enter a stock ticker (e.g., `AAPL`, `TSLA`, `AZN.L`) to generate a 90-day forecast.")
136
+
137
+ with gr.Row():
138
+ ticker_input = gr.Textbox(label="Ticker Symbol", placeholder="e.g. AZN.L", value="AZN.L")
139
+ submit_btn = gr.Button("Analyze Stock", variant="primary")
140
+
141
+ result_text = gr.Markdown(label="Verdict")
142
+
143
+ with gr.Row():
144
+ plot1 = gr.Plot(label="Price Forecast")
145
+ plot2 = gr.Plot(label="Seasonality Components")
146
+
147
+ submit_btn.click(
148
+ fn=predict_stock,
149
+ inputs=ticker_input,
150
+ outputs=[result_text, plot1, plot2]
151
+ )
152
+
153
+ if __name__ == "__main__":
154
+ demo.launch()
readme.md DELETED
@@ -1 +0,0 @@
1
-
 
 
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ neuralprophet
2
+ yfinance
3
+ pandas
4
+ gradio
5
+ plotly
6
+ torch