Spaces:
Running
on
Zero
Running
on
Zero
Initial commit: Stock prediction application with Chronos integration
Browse files- .gitignore +41 -0
- README.md +34 -191
- app.py +26 -11
- src/app.py +117 -0
- src/data/stock_data.py +62 -0
.gitignore
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Python
|
2 |
+
__pycache__/
|
3 |
+
*.py[cod]
|
4 |
+
*$py.class
|
5 |
+
*.so
|
6 |
+
.Python
|
7 |
+
build/
|
8 |
+
develop-eggs/
|
9 |
+
dist/
|
10 |
+
downloads/
|
11 |
+
eggs/
|
12 |
+
.eggs/
|
13 |
+
lib/
|
14 |
+
lib64/
|
15 |
+
parts/
|
16 |
+
sdist/
|
17 |
+
var/
|
18 |
+
wheels/
|
19 |
+
*.egg-info/
|
20 |
+
.installed.cfg
|
21 |
+
*.egg
|
22 |
+
|
23 |
+
# Virtual Environment
|
24 |
+
venv/
|
25 |
+
env/
|
26 |
+
ENV/
|
27 |
+
|
28 |
+
# IDE
|
29 |
+
.idea/
|
30 |
+
.vscode/
|
31 |
+
*.swp
|
32 |
+
*.swo
|
33 |
+
|
34 |
+
# OS
|
35 |
+
.DS_Store
|
36 |
+
Thumbs.db
|
37 |
+
|
38 |
+
# Project specific
|
39 |
+
*.log
|
40 |
+
.env
|
41 |
+
.env.local
|
README.md
CHANGED
@@ -13,223 +13,66 @@ tags:
|
|
13 |
- mcp-server-track
|
14 |
---
|
15 |
|
16 |
-
# Stock
|
17 |
|
18 |
-
A
|
19 |
|
20 |
## Features
|
21 |
|
22 |
-
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
-
|
38 |
-
|
39 |
-
|
40 |
-
- Volume analysis
|
41 |
-
- Historical price trends
|
42 |
-
|
43 |
-
- **Structured Product Analysis**:
|
44 |
-
- Extended prediction horizons (up to 1 year)
|
45 |
-
- Historical analysis up to 10 years
|
46 |
-
- Comprehensive risk metrics
|
47 |
-
- Sector and industry analysis
|
48 |
-
- Liquidity assessment
|
49 |
-
|
50 |
-
## Structured Product Features
|
51 |
-
|
52 |
-
### Extended Time Horizons
|
53 |
-
- Prediction window up to 365 days
|
54 |
-
- Historical data analysis up to 10 years
|
55 |
-
- Long-term trend analysis
|
56 |
-
- Extended technical indicators
|
57 |
-
|
58 |
-
### Risk Analysis
|
59 |
-
- Annualized volatility
|
60 |
-
- Maximum drawdown analysis
|
61 |
-
- Current drawdown tracking
|
62 |
-
- Sharpe and Sortino ratios
|
63 |
-
- Risk-adjusted return metrics
|
64 |
-
|
65 |
-
### Product Metrics
|
66 |
-
- Market capitalization
|
67 |
-
- Sector and industry classification
|
68 |
-
- Dividend yield analysis
|
69 |
-
- Volume metrics
|
70 |
-
- Liquidity scoring
|
71 |
-
|
72 |
-
### Sector Analysis
|
73 |
-
- Market cap ranking (Large/Mid/Small)
|
74 |
-
- Sector exposure
|
75 |
-
- Industry classification
|
76 |
-
- Liquidity assessment
|
77 |
|
78 |
## Installation
|
79 |
|
80 |
1. Clone the repository:
|
81 |
```bash
|
82 |
-
git clone
|
83 |
-
cd stock-
|
84 |
```
|
85 |
|
86 |
-
2.
|
87 |
-
```bash
|
88 |
-
python -m venv .venv
|
89 |
-
source .venv/bin/activate # On Windows: .venv\Scripts\activate
|
90 |
-
```
|
91 |
-
|
92 |
-
3. Install dependencies:
|
93 |
```bash
|
94 |
pip install -r requirements.txt
|
95 |
```
|
96 |
|
97 |
## Usage
|
98 |
|
99 |
-
|
100 |
```bash
|
101 |
python app.py
|
102 |
```
|
103 |
|
104 |
-
|
105 |
-
|
106 |
-
3. Enter a stock symbol (e.g., AAPL, GOOGL, MSFT) and select your desired parameters:
|
107 |
-
- Timeframe (1d, 1h, 15m)
|
108 |
-
- Number of days to predict (up to 365 days)
|
109 |
-
- Historical lookback period (up to 10 years)
|
110 |
-
- Prediction strategy (Chronos or Technical)
|
111 |
-
|
112 |
-
4. Click "Analyze Stock" to get:
|
113 |
-
- Price predictions and trading signals
|
114 |
-
- Structured product metrics
|
115 |
-
- Risk analysis
|
116 |
-
- Sector analysis
|
117 |
-
|
118 |
-
## Using for Structured Products
|
119 |
-
|
120 |
-
### Initial Screening
|
121 |
-
1. Use extended lookback period (up to 10 years) for long-term performance analysis
|
122 |
-
2. Look for stocks with stable volatility and good risk-adjusted returns
|
123 |
-
3. Check liquidity scores for trading feasibility
|
124 |
-
|
125 |
-
### Risk Assessment
|
126 |
-
1. Review risk metrics to match client risk profile
|
127 |
-
2. Analyze maximum drawdowns for worst-case scenarios
|
128 |
-
3. Compare risk-adjusted returns using Sharpe and Sortino ratios
|
129 |
-
|
130 |
-
### Product Structuring
|
131 |
-
1. Use prediction horizon (up to 1 year) for product maturity design
|
132 |
-
2. Consider dividend yields for income-generating products
|
133 |
-
3. Use sector analysis for proper diversification
|
134 |
|
135 |
-
|
136 |
-
1. Analyze multiple stocks for diversified bundles
|
137 |
-
2. Use sector metrics to avoid overexposure
|
138 |
-
3. Consider market cap rankings for appropriate sizing
|
139 |
-
|
140 |
-
## Prediction Strategies
|
141 |
-
|
142 |
-
### Chronos Strategy
|
143 |
-
Uses Amazon's Chronos model for ML-based price prediction. This strategy:
|
144 |
-
- Analyzes historical price patterns
|
145 |
-
- Generates probabilistic forecasts
|
146 |
-
- Provides confidence intervals
|
147 |
-
|
148 |
-
### Technical Strategy
|
149 |
-
Uses traditional technical analysis indicators to generate predictions:
|
150 |
-
- RSI for overbought/oversold conditions
|
151 |
-
- MACD for trend direction
|
152 |
-
- Bollinger Bands for volatility
|
153 |
-
- Moving Averages for trend confirmation
|
154 |
|
155 |
-
|
|
|
|
|
|
|
|
|
|
|
156 |
|
157 |
-
|
158 |
-
- RSI: Oversold (<30), Overbought (>70), Neutral
|
159 |
-
- MACD: Buy (MACD > Signal), Sell (MACD < Signal)
|
160 |
-
- Bollinger Bands: Buy (price < lower band), Sell (price > upper band)
|
161 |
-
- SMA: Buy (20-day > 50-day), Sell (20-day < 50-day)
|
162 |
|
163 |
-
|
164 |
|
165 |
## Contributing
|
166 |
|
167 |
Contributions are welcome! Please feel free to submit a Pull Request.
|
168 |
-
|
169 |
-
## License
|
170 |
-
|
171 |
-
This project is licensed under the MIT License - see the LICENSE file for details.
|
172 |
-
|
173 |
-
## Practical Example: Creating a 6-Month 8% Yield Structured Product
|
174 |
-
|
175 |
-
### Scenario
|
176 |
-
A bank needs to create a structured product that offers an 8% yield over 6 months while maintaining profitability for the institution.
|
177 |
-
|
178 |
-
### Step-by-Step Implementation
|
179 |
-
|
180 |
-
1. **Initial Stock Screening**
|
181 |
-
- Use the application to analyze stocks with:
|
182 |
-
- High liquidity (for easy hedging)
|
183 |
-
- Stable volatility (for predictable risk)
|
184 |
-
- Strong technical indicators
|
185 |
-
- Positive long-term trends
|
186 |
-
- Recommended stocks: AAPL, MSFT, GOOGL (high liquidity, stable volatility)
|
187 |
-
|
188 |
-
2. **Product Structure Design**
|
189 |
-
- Use the 6-month prediction horizon
|
190 |
-
- Analyze historical volatility for barrier setting
|
191 |
-
- Set participation rate based on risk metrics
|
192 |
-
- Structure: Reverse Convertible with 8% coupon
|
193 |
-
|
194 |
-
3. **Risk Analysis**
|
195 |
-
- Use the application's risk metrics:
|
196 |
-
- Check maximum drawdown (should be < 15% for 6 months)
|
197 |
-
- Verify liquidity scores (should be > 80%)
|
198 |
-
- Analyze Sharpe ratio (should be > 1.5)
|
199 |
-
|
200 |
-
4. **Business Case Example**
|
201 |
-
|
202 |
-
**Product Parameters:**
|
203 |
-
- Notional Amount: $1,000,000
|
204 |
-
- Term: 6 months
|
205 |
-
- Coupon: 8% p.a. (4% for 6 months)
|
206 |
-
- Underlying: AAPL
|
207 |
-
- Barrier: 85% of initial price
|
208 |
-
- Participation: 100%
|
209 |
-
|
210 |
-
**Revenue Structure:**
|
211 |
-
- Client receives: 8% p.a. (4% for 6 months)
|
212 |
-
- Bank's hedging cost: ~5% p.a.
|
213 |
-
- Bank's profit margin: ~3% p.a.
|
214 |
-
- Total client payout: $40,000 (4% of $1M)
|
215 |
-
- Bank's profit: $15,000 (1.5% of $1M)
|
216 |
-
|
217 |
-
5. **Implementation Steps**
|
218 |
-
- Use the application's extended prediction horizon (180 days)
|
219 |
-
- Set technical indicators to monitor barrier risk
|
220 |
-
- Implement dynamic delta hedging based on predictions
|
221 |
-
- Monitor risk metrics daily using the application
|
222 |
-
|
223 |
-
6. **Risk Management**
|
224 |
-
- Use the application's volatility predictions for dynamic hedging
|
225 |
-
- Monitor technical indicators for early warning signals
|
226 |
-
- Set up automated alerts for barrier proximity
|
227 |
-
- Regular rebalancing based on prediction updates
|
228 |
-
|
229 |
-
### Key Success Factors
|
230 |
-
- Regular monitoring of prediction accuracy
|
231 |
-
- Dynamic adjustment of hedging strategy
|
232 |
-
- Clear communication of product risks to clients
|
233 |
-
- Proper documentation of all assumptions and methodologies
|
234 |
-
|
235 |
-
This example demonstrates how the application can be used to create profitable structured products while managing risk effectively. The bank can use this framework to create similar products with different underlying assets, terms, and yield targets.
|
|
|
13 |
- mcp-server-track
|
14 |
---
|
15 |
|
16 |
+
# Stock Predictions with Chronos
|
17 |
|
18 |
+
A powerful stock prediction application that uses the Chronos model and technical analysis to predict stock prices across different timeframes.
|
19 |
|
20 |
## Features
|
21 |
|
22 |
+
- Multiple timeframe analysis (Daily, Hourly, 15-minute)
|
23 |
+
- Integration with Chronos AI model for predictions
|
24 |
+
- Technical analysis with multiple indicators
|
25 |
+
- Real-time market data using Yahoo Finance
|
26 |
+
- Beautiful interactive visualizations using Plotly
|
27 |
+
- Risk analysis and sector metrics
|
28 |
+
- Trading signals generation
|
29 |
+
|
30 |
+
## Requirements
|
31 |
+
|
32 |
+
- Python 3.8+
|
33 |
+
- PyTorch
|
34 |
+
- Gradio
|
35 |
+
- yfinance
|
36 |
+
- pandas
|
37 |
+
- numpy
|
38 |
+
- plotly
|
39 |
+
- scikit-learn
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
|
41 |
## Installation
|
42 |
|
43 |
1. Clone the repository:
|
44 |
```bash
|
45 |
+
git clone https://github.com/yourusername/stock-predictions.git
|
46 |
+
cd stock-predictions
|
47 |
```
|
48 |
|
49 |
+
2. Install the required packages:
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
```bash
|
51 |
pip install -r requirements.txt
|
52 |
```
|
53 |
|
54 |
## Usage
|
55 |
|
56 |
+
Run the application:
|
57 |
```bash
|
58 |
python app.py
|
59 |
```
|
60 |
|
61 |
+
The application will start and provide a local URL (usually http://127.0.0.1:7860) where you can access the interface.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
|
63 |
+
## Features
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
|
65 |
+
- **Daily Analysis**: Long-term predictions and analysis
|
66 |
+
- **Hourly Analysis**: Medium-term predictions with 30-day lookback
|
67 |
+
- **15-Minute Analysis**: Short-term predictions with 5-day lookback
|
68 |
+
- **Technical Indicators**: RSI, MACD, Bollinger Bands, SMAs
|
69 |
+
- **Risk Metrics**: Volatility, Drawdown, Sharpe Ratio
|
70 |
+
- **Sector Analysis**: Market cap, industry classification, liquidity metrics
|
71 |
|
72 |
+
## License
|
|
|
|
|
|
|
|
|
73 |
|
74 |
+
MIT License
|
75 |
|
76 |
## Contributing
|
77 |
|
78 |
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app.py
CHANGED
@@ -137,16 +137,17 @@ def get_historical_data(symbol: str, timeframe: str = "1d", lookback_days: int =
|
|
137 |
sma_window_200 = 200 * 24 # ~40 trading days
|
138 |
vol_window = 20 * 24
|
139 |
|
140 |
-
|
141 |
-
df['
|
142 |
-
df['
|
|
|
143 |
df['RSI'] = calculate_rsi(df['Close'])
|
144 |
df['MACD'], df['MACD_Signal'] = calculate_macd(df['Close'])
|
145 |
df['BB_Upper'], df['BB_Middle'], df['BB_Lower'] = calculate_bollinger_bands(df['Close'])
|
146 |
|
147 |
# Calculate returns and volatility
|
148 |
df['Returns'] = df['Close'].pct_change()
|
149 |
-
df['Volatility'] = df['Returns'].rolling(window=vol_window).std()
|
150 |
df['Annualized_Vol'] = df['Volatility'] * np.sqrt(252)
|
151 |
|
152 |
# Calculate drawdown metrics
|
@@ -155,11 +156,21 @@ def get_historical_data(symbol: str, timeframe: str = "1d", lookback_days: int =
|
|
155 |
df['Max_Drawdown'] = df['Drawdown'].rolling(window=len(df), min_periods=1).min()
|
156 |
|
157 |
# Calculate liquidity metrics
|
158 |
-
df['Avg_Daily_Volume'] = df['Volume'].rolling(window=vol_window).mean()
|
159 |
-
df['Volume_Volatility'] = df['Volume'].rolling(window=vol_window).std()
|
160 |
-
|
161 |
-
#
|
162 |
-
df = df.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
|
164 |
if len(df) < 2:
|
165 |
raise Exception(f"Insufficient data points for {symbol} in {timeframe} timeframe")
|
@@ -217,14 +228,18 @@ def make_prediction(symbol: str, timeframe: str = "1d", prediction_days: int = 5
|
|
217 |
returns = df['Returns'].values
|
218 |
normalized_returns = (returns - returns.mean()) / returns.std()
|
219 |
|
220 |
-
# Ensure we have enough data points
|
221 |
min_data_points = 64 # Minimum required by Chronos
|
222 |
if len(normalized_returns) < min_data_points:
|
223 |
# Pad the data with the last value
|
224 |
padding = np.full(min_data_points - len(normalized_returns), normalized_returns[-1])
|
225 |
normalized_returns = np.concatenate([padding, normalized_returns])
|
|
|
|
|
|
|
226 |
|
227 |
-
|
|
|
228 |
|
229 |
# Make prediction with GPU acceleration
|
230 |
pipe = load_pipeline()
|
|
|
137 |
sma_window_200 = 200 * 24 # ~40 trading days
|
138 |
vol_window = 20 * 24
|
139 |
|
140 |
+
# Calculate technical indicators
|
141 |
+
df['SMA_20'] = df['Close'].rolling(window=sma_window_20, min_periods=1).mean()
|
142 |
+
df['SMA_50'] = df['Close'].rolling(window=sma_window_50, min_periods=1).mean()
|
143 |
+
df['SMA_200'] = df['Close'].rolling(window=sma_window_200, min_periods=1).mean()
|
144 |
df['RSI'] = calculate_rsi(df['Close'])
|
145 |
df['MACD'], df['MACD_Signal'] = calculate_macd(df['Close'])
|
146 |
df['BB_Upper'], df['BB_Middle'], df['BB_Lower'] = calculate_bollinger_bands(df['Close'])
|
147 |
|
148 |
# Calculate returns and volatility
|
149 |
df['Returns'] = df['Close'].pct_change()
|
150 |
+
df['Volatility'] = df['Returns'].rolling(window=vol_window, min_periods=1).std()
|
151 |
df['Annualized_Vol'] = df['Volatility'] * np.sqrt(252)
|
152 |
|
153 |
# Calculate drawdown metrics
|
|
|
156 |
df['Max_Drawdown'] = df['Drawdown'].rolling(window=len(df), min_periods=1).min()
|
157 |
|
158 |
# Calculate liquidity metrics
|
159 |
+
df['Avg_Daily_Volume'] = df['Volume'].rolling(window=vol_window, min_periods=1).mean()
|
160 |
+
df['Volume_Volatility'] = df['Volume'].rolling(window=vol_window, min_periods=1).std()
|
161 |
+
|
162 |
+
# Fill NaN values with forward fill, then backward fill
|
163 |
+
df = df.fillna(method='ffill').fillna(method='bfill')
|
164 |
+
|
165 |
+
# Ensure we have enough data points
|
166 |
+
min_required_points = 64 # Minimum required for Chronos
|
167 |
+
if len(df) < min_required_points:
|
168 |
+
# Try to fetch more historical data
|
169 |
+
extended_start_date = start_date - timedelta(days=min_required_points - len(df))
|
170 |
+
extended_df = ticker.history(start=extended_start_date, end=start_date, interval=interval)
|
171 |
+
if not extended_df.empty:
|
172 |
+
df = pd.concat([extended_df, df])
|
173 |
+
df = df.fillna(method='ffill').fillna(method='bfill')
|
174 |
|
175 |
if len(df) < 2:
|
176 |
raise Exception(f"Insufficient data points for {symbol} in {timeframe} timeframe")
|
|
|
228 |
returns = df['Returns'].values
|
229 |
normalized_returns = (returns - returns.mean()) / returns.std()
|
230 |
|
231 |
+
# Ensure we have enough data points and pad if necessary
|
232 |
min_data_points = 64 # Minimum required by Chronos
|
233 |
if len(normalized_returns) < min_data_points:
|
234 |
# Pad the data with the last value
|
235 |
padding = np.full(min_data_points - len(normalized_returns), normalized_returns[-1])
|
236 |
normalized_returns = np.concatenate([padding, normalized_returns])
|
237 |
+
elif len(normalized_returns) > min_data_points:
|
238 |
+
# Take the most recent data points
|
239 |
+
normalized_returns = normalized_returns[-min_data_points:]
|
240 |
|
241 |
+
# Reshape for Chronos (batch_size=1, sequence_length, features=1)
|
242 |
+
context = torch.tensor(normalized_returns.reshape(1, -1, 1), dtype=torch.float32)
|
243 |
|
244 |
# Make prediction with GPU acceleration
|
245 |
pipe = load_pipeline()
|
src/app.py
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from fastapi import FastAPI, HTTPException
|
2 |
+
from fastapi.middleware.cors import CORSMiddleware
|
3 |
+
import yfinance as yf
|
4 |
+
import pandas as pd
|
5 |
+
from datetime import datetime, timedelta
|
6 |
+
import logging
|
7 |
+
from typing import Optional
|
8 |
+
|
9 |
+
# Configure logging
|
10 |
+
logging.basicConfig(level=logging.INFO)
|
11 |
+
logger = logging.getLogger(__name__)
|
12 |
+
|
13 |
+
app = FastAPI()
|
14 |
+
|
15 |
+
# Configure CORS
|
16 |
+
app.add_middleware(
|
17 |
+
CORSMiddleware,
|
18 |
+
allow_origins=["*"], # Allows all origins
|
19 |
+
allow_credentials=True,
|
20 |
+
allow_methods=["*"], # Allows all methods
|
21 |
+
allow_headers=["*"], # Allows all headers
|
22 |
+
)
|
23 |
+
|
24 |
+
def fetch_stock_data(symbol: str, period: str = "1y") -> pd.DataFrame:
|
25 |
+
"""
|
26 |
+
Fetch historical stock data for a given symbol using yfinance with authentication.
|
27 |
+
|
28 |
+
Args:
|
29 |
+
symbol (str): Stock symbol (e.g., 'AAPL')
|
30 |
+
period (str): Time period to fetch (default: '1y')
|
31 |
+
|
32 |
+
Returns:
|
33 |
+
pd.DataFrame: DataFrame containing historical stock data
|
34 |
+
"""
|
35 |
+
try:
|
36 |
+
# Create a Ticker object with authentication
|
37 |
+
ticker = yf.Ticker(symbol)
|
38 |
+
|
39 |
+
# Set authentication credentials
|
40 |
+
ticker._session.headers.update({
|
41 |
+
'User-Agent': 'Mozilla/5.0',
|
42 |
+
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
|
43 |
+
'Accept-Language': 'en-US,en;q=0.5',
|
44 |
+
'Connection': 'keep-alive',
|
45 |
+
'Upgrade-Insecure-Requests': '1',
|
46 |
+
})
|
47 |
+
|
48 |
+
# Fetch historical data
|
49 |
+
df = ticker.history(period=period)
|
50 |
+
|
51 |
+
if df.empty:
|
52 |
+
logger.warning(f"No data found for symbol {symbol}")
|
53 |
+
return pd.DataFrame()
|
54 |
+
|
55 |
+
# Reset index to make Date a column
|
56 |
+
df = df.reset_index()
|
57 |
+
|
58 |
+
# Rename columns to match expected format
|
59 |
+
df = df.rename(columns={
|
60 |
+
'Date': 'date',
|
61 |
+
'Open': 'open',
|
62 |
+
'High': 'high',
|
63 |
+
'Low': 'low',
|
64 |
+
'Close': 'close',
|
65 |
+
'Volume': 'volume'
|
66 |
+
})
|
67 |
+
|
68 |
+
# Convert date to string format
|
69 |
+
df['date'] = df['date'].dt.strftime('%Y-%m-%d')
|
70 |
+
|
71 |
+
logger.info(f"Successfully fetched data for {symbol}")
|
72 |
+
return df
|
73 |
+
|
74 |
+
except Exception as e:
|
75 |
+
logger.error(f"Error fetching data for {symbol}: {str(e)}")
|
76 |
+
return pd.DataFrame()
|
77 |
+
|
78 |
+
@app.get("/")
|
79 |
+
async def root():
|
80 |
+
return {"message": "Stock Prediction API"}
|
81 |
+
|
82 |
+
@app.get("/api/stock/{symbol}")
|
83 |
+
async def get_stock_data(symbol: str, period: Optional[str] = "1y"):
|
84 |
+
"""
|
85 |
+
Get historical stock data for a given symbol.
|
86 |
+
|
87 |
+
Args:
|
88 |
+
symbol (str): Stock symbol (e.g., 'AAPL')
|
89 |
+
period (str, optional): Time period to fetch. Defaults to "1y".
|
90 |
+
Valid periods: 1d, 5d, 1mo, 3mo, 6mo, 1y, 2y, 5y, 10y, ytd, max
|
91 |
+
|
92 |
+
Returns:
|
93 |
+
dict: Dictionary containing stock data and metadata
|
94 |
+
"""
|
95 |
+
try:
|
96 |
+
df = fetch_stock_data(symbol, period)
|
97 |
+
|
98 |
+
if df.empty:
|
99 |
+
raise HTTPException(status_code=404, detail=f"No data found for symbol {symbol}")
|
100 |
+
|
101 |
+
# Convert DataFrame to dictionary format
|
102 |
+
data = df.to_dict(orient='records')
|
103 |
+
|
104 |
+
return {
|
105 |
+
"symbol": symbol,
|
106 |
+
"period": period,
|
107 |
+
"data": data,
|
108 |
+
"count": len(data)
|
109 |
+
}
|
110 |
+
|
111 |
+
except Exception as e:
|
112 |
+
logger.error(f"Error processing request for {symbol}: {str(e)}")
|
113 |
+
raise HTTPException(status_code=500, detail=str(e))
|
114 |
+
|
115 |
+
if __name__ == "__main__":
|
116 |
+
import uvicorn
|
117 |
+
uvicorn.run(app, host="0.0.0.0", port=8000)
|
src/data/stock_data.py
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import yfinance as yf
|
2 |
+
import pandas as pd
|
3 |
+
from datetime import datetime, timedelta
|
4 |
+
import logging
|
5 |
+
|
6 |
+
# Configure logging
|
7 |
+
logging.basicConfig(level=logging.INFO)
|
8 |
+
logger = logging.getLogger(__name__)
|
9 |
+
|
10 |
+
def fetch_stock_data(symbol: str, period: str = "1y") -> pd.DataFrame:
|
11 |
+
"""
|
12 |
+
Fetch historical stock data for a given symbol using yfinance with authentication.
|
13 |
+
|
14 |
+
Args:
|
15 |
+
symbol (str): Stock symbol (e.g., 'AAPL')
|
16 |
+
period (str): Time period to fetch (default: '1y')
|
17 |
+
|
18 |
+
Returns:
|
19 |
+
pd.DataFrame: DataFrame containing historical stock data
|
20 |
+
"""
|
21 |
+
try:
|
22 |
+
# Create a Ticker object with authentication
|
23 |
+
ticker = yf.Ticker(symbol)
|
24 |
+
|
25 |
+
# Set authentication credentials
|
26 |
+
ticker._session.headers.update({
|
27 |
+
'User-Agent': 'Mozilla/5.0',
|
28 |
+
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
|
29 |
+
'Accept-Language': 'en-US,en;q=0.5',
|
30 |
+
'Connection': 'keep-alive',
|
31 |
+
'Upgrade-Insecure-Requests': '1',
|
32 |
+
})
|
33 |
+
|
34 |
+
# Fetch historical data
|
35 |
+
df = ticker.history(period=period)
|
36 |
+
|
37 |
+
if df.empty:
|
38 |
+
logger.warning(f"No data found for symbol {symbol}")
|
39 |
+
return pd.DataFrame()
|
40 |
+
|
41 |
+
# Reset index to make Date a column
|
42 |
+
df = df.reset_index()
|
43 |
+
|
44 |
+
# Rename columns to match expected format
|
45 |
+
df = df.rename(columns={
|
46 |
+
'Date': 'date',
|
47 |
+
'Open': 'open',
|
48 |
+
'High': 'high',
|
49 |
+
'Low': 'low',
|
50 |
+
'Close': 'close',
|
51 |
+
'Volume': 'volume'
|
52 |
+
})
|
53 |
+
|
54 |
+
# Convert date to string format
|
55 |
+
df['date'] = df['date'].dt.strftime('%Y-%m-%d')
|
56 |
+
|
57 |
+
logger.info(f"Successfully fetched data for {symbol}")
|
58 |
+
return df
|
59 |
+
|
60 |
+
except Exception as e:
|
61 |
+
logger.error(f"Error fetching data for {symbol}: {str(e)}")
|
62 |
+
return pd.DataFrame()
|