Upload 18 files
Browse files- .gitattributes +1 -0
- README.md +81 -14
- attached_assets/Screenshot 2025-03-10 at 8.38.32/342/200/257PM.png +0 -0
- attached_assets/nse_stock_signals_app_plan.md +259 -0
- attached_assets/symbol.csv +218 -0
- generated-icon.png +3 -0
- main.py +79 -0
- pages/news.py +89 -0
- pages/recommendations.py +129 -0
- pages/stock_analysis.py +126 -0
- pages/stock_screener.py +107 -0
- pyproject.toml +14 -0
- replit.nix +5 -0
- requirements.txt.rtf +14 -0
- utils/indicators.py +66 -0
- utils/recommendation_engine.py +95 -0
- utils/signals.py +52 -0
- utils/stock_data.py +50 -0
- uv.lock +0 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
generated-icon.png filter=lfs diff=lfs merge=lfs -text
|
README.md
CHANGED
|
@@ -1,14 +1,81 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# NSE Stock Analysis Platform 📈
|
| 2 |
+
|
| 3 |
+
A comprehensive NSE stock analysis platform built with Streamlit, providing real-time technical indicators, trading signals, and news insights for investors.
|
| 4 |
+
|
| 5 |
+
## Features
|
| 6 |
+
|
| 7 |
+
- **Real-time Stock Analysis**: Technical indicators and interactive charts
|
| 8 |
+
- **AI-Powered Recommendations**: Smart stock recommendations based on technical analysis
|
| 9 |
+
- **Stock Screener**: Filter stocks based on custom technical criteria
|
| 10 |
+
- **Live News Feed**: Latest news for NSE stocks using Google News RSS
|
| 11 |
+
- **Interactive Charts**: Multi-timeframe analysis with various technical indicators
|
| 12 |
+
|
| 13 |
+
## Technical Stack
|
| 14 |
+
|
| 15 |
+
- **Frontend**: Streamlit
|
| 16 |
+
- **Data Processing**: Pandas, NumPy
|
| 17 |
+
- **Technical Analysis**: Custom implementations of technical indicators
|
| 18 |
+
- **Data Source**: yfinance API
|
| 19 |
+
- **News Feed**: Google News RSS
|
| 20 |
+
- **Visualization**: Plotly
|
| 21 |
+
|
| 22 |
+
## Dependencies
|
| 23 |
+
|
| 24 |
+
```txt
|
| 25 |
+
streamlit
|
| 26 |
+
pandas
|
| 27 |
+
numpy
|
| 28 |
+
plotly
|
| 29 |
+
yfinance
|
| 30 |
+
feedparser
|
| 31 |
+
pytz
|
| 32 |
+
```
|
| 33 |
+
|
| 34 |
+
## Deployment on Hugging Face Spaces
|
| 35 |
+
|
| 36 |
+
1. Create a new Space on Hugging Face:
|
| 37 |
+
- Go to huggingface.co/spaces
|
| 38 |
+
- Click "Create new Space"
|
| 39 |
+
- Select "Streamlit" as the SDK
|
| 40 |
+
- Choose a name for your space
|
| 41 |
+
|
| 42 |
+
2. Upload the Project Files:
|
| 43 |
+
- Upload all project files to your Space
|
| 44 |
+
- Ensure the file structure matches the repository
|
| 45 |
+
|
| 46 |
+
3. Configure Environment:
|
| 47 |
+
- The platform will automatically install dependencies
|
| 48 |
+
- The app will run on the default Streamlit port
|
| 49 |
+
|
| 50 |
+
4. Access Your App:
|
| 51 |
+
- Once deployed, your app will be available at: https://huggingface.co/spaces/[USERNAME]/[SPACE-NAME]
|
| 52 |
+
|
| 53 |
+
## Usage
|
| 54 |
+
|
| 55 |
+
1. **Stock Analysis**:
|
| 56 |
+
- Select a stock from the dropdown
|
| 57 |
+
- Choose timeframe and interval
|
| 58 |
+
- View technical indicators and signals
|
| 59 |
+
|
| 60 |
+
2. **Stock Screener**:
|
| 61 |
+
- Set your screening criteria
|
| 62 |
+
- Get filtered results based on technical indicators
|
| 63 |
+
|
| 64 |
+
3. **AI Recommendations**:
|
| 65 |
+
- View AI-generated stock recommendations
|
| 66 |
+
- Check confidence levels and recommendation basis
|
| 67 |
+
|
| 68 |
+
4. **News Feed**:
|
| 69 |
+
- Access latest news for all NSE stocks
|
| 70 |
+
- Click on news titles to read full articles
|
| 71 |
+
|
| 72 |
+
## Local Development
|
| 73 |
+
|
| 74 |
+
1. Clone the repository
|
| 75 |
+
2. Install dependencies: `pip install -r requirements.txt`
|
| 76 |
+
3. Run the app: `streamlit run main.py`
|
| 77 |
+
4. Access at: `http://localhost:5000`
|
| 78 |
+
|
| 79 |
+
## License
|
| 80 |
+
|
| 81 |
+
This project is licensed under the MIT License - see the LICENSE file for details.
|
attached_assets/Screenshot 2025-03-10 at 8.38.32/342/200/257PM.png
ADDED
|
attached_assets/nse_stock_signals_app_plan.md
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# AI-Based NSE Stock Technical Signals Web Application Plan
|
| 2 |
+
|
| 3 |
+
## 1. System Architecture
|
| 4 |
+
|
| 5 |
+
```mermaid
|
| 6 |
+
graph TD
|
| 7 |
+
A[Data Collection Layer] --> B[Data Processing Layer]
|
| 8 |
+
B --> C[AI Analysis Layer]
|
| 9 |
+
C --> D[Signal Generation Layer]
|
| 10 |
+
D --> E[Web Interface Layer]
|
| 11 |
+
|
| 12 |
+
subgraph "Data Sources"
|
| 13 |
+
F[yFinance API]
|
| 14 |
+
G[Google Finance]
|
| 15 |
+
H[Historical Data Storage]
|
| 16 |
+
end
|
| 17 |
+
|
| 18 |
+
F --> A
|
| 19 |
+
G --> A
|
| 20 |
+
A --> H
|
| 21 |
+
H --> B
|
| 22 |
+
```
|
| 23 |
+
|
| 24 |
+
## 2. Component Breakdown
|
| 25 |
+
|
| 26 |
+
### 2.1 Data Collection Layer
|
| 27 |
+
- **Purpose**: Fetch financial data from yFinance and Google Finance APIs
|
| 28 |
+
- **Components**:
|
| 29 |
+
- Stock Data Fetcher: Retrieves real-time and historical price data
|
| 30 |
+
- Financial Metrics Collector: Gathers fundamental data and market metrics
|
| 31 |
+
- Data Synchronization Manager: Ensures consistent data across sources
|
| 32 |
+
- **Technologies**: Python, yfinance library, requests/BeautifulSoup for Google Finance
|
| 33 |
+
|
| 34 |
+
### 2.2 Data Processing Layer
|
| 35 |
+
- **Purpose**: Clean, normalize, and prepare data for analysis
|
| 36 |
+
- **Components**:
|
| 37 |
+
- Data Cleaner: Handles missing values and outliers
|
| 38 |
+
- Feature Engineering: Creates derived features for technical analysis
|
| 39 |
+
- Technical Indicator Calculator: Computes standard technical indicators
|
| 40 |
+
- **Technologies**: Pandas, NumPy, TA-Lib
|
| 41 |
+
|
| 42 |
+
### 2.3 AI Analysis Layer
|
| 43 |
+
- **Purpose**: Apply AI/ML techniques to analyze stock patterns
|
| 44 |
+
- **Components**:
|
| 45 |
+
- Prediction Models: Time-series forecasting for price movements
|
| 46 |
+
- Pattern Recognition: Identify chart patterns and formations
|
| 47 |
+
- Anomaly Detection: Spot unusual market behavior
|
| 48 |
+
- **Technologies**: Scikit-learn, TensorFlow/Keras, Prophet, LSTM networks
|
| 49 |
+
|
| 50 |
+
### 2.4 Signal Generation Layer
|
| 51 |
+
- **Purpose**: Generate actionable trading signals based on AI analysis
|
| 52 |
+
- **Components**:
|
| 53 |
+
- Signal Aggregator: Combines signals from multiple sources
|
| 54 |
+
- Confidence Calculator: Assigns confidence scores to signals
|
| 55 |
+
- Alert Generator: Creates notifications for significant signals
|
| 56 |
+
- **Technologies**: Custom Python algorithms, rule-based systems
|
| 57 |
+
|
| 58 |
+
### 2.5 Web Interface Layer
|
| 59 |
+
- **Purpose**: Present signals and analysis to users
|
| 60 |
+
- **Components**:
|
| 61 |
+
- Dashboard: Visual overview of signals and market status
|
| 62 |
+
- Stock Screener: Filter stocks based on signals and criteria
|
| 63 |
+
- Detailed Analysis View: In-depth analysis for individual stocks
|
| 64 |
+
- User Preferences: Customization options for alerts and display
|
| 65 |
+
- **Technologies**: Flask/FastAPI backend, React/Vue frontend, Plotly/D3.js for charts
|
| 66 |
+
|
| 67 |
+
## 3. Technical Indicators to Implement
|
| 68 |
+
|
| 69 |
+
We'll implement the most reliable technical indicators:
|
| 70 |
+
|
| 71 |
+
1. **Trend Indicators**:
|
| 72 |
+
- Moving Averages (SMA, EMA, VWAP)
|
| 73 |
+
- MACD (Moving Average Convergence Divergence)
|
| 74 |
+
- ADX (Average Directional Index)
|
| 75 |
+
- Parabolic SAR
|
| 76 |
+
|
| 77 |
+
2. **Momentum Indicators**:
|
| 78 |
+
- RSI (Relative Strength Index)
|
| 79 |
+
- Stochastic Oscillator
|
| 80 |
+
- CCI (Commodity Channel Index)
|
| 81 |
+
- Williams %R
|
| 82 |
+
|
| 83 |
+
3. **Volatility Indicators**:
|
| 84 |
+
- Bollinger Bands
|
| 85 |
+
- ATR (Average True Range)
|
| 86 |
+
- Standard Deviation
|
| 87 |
+
|
| 88 |
+
4. **Volume Indicators**:
|
| 89 |
+
- OBV (On-Balance Volume)
|
| 90 |
+
- Volume Rate of Change
|
| 91 |
+
- Accumulation/Distribution Line
|
| 92 |
+
- Money Flow Index
|
| 93 |
+
|
| 94 |
+
## 4. AI Implementation Approach
|
| 95 |
+
|
| 96 |
+
### 4.1 Prediction Models
|
| 97 |
+
- **Time Series Forecasting**:
|
| 98 |
+
- ARIMA/SARIMA models for short-term predictions
|
| 99 |
+
- LSTM/GRU neural networks for capturing long-term dependencies
|
| 100 |
+
- Prophet for trend and seasonality decomposition
|
| 101 |
+
- **Ensemble Methods**:
|
| 102 |
+
- Combine multiple forecasting models for improved accuracy
|
| 103 |
+
- Use techniques like stacking and boosting
|
| 104 |
+
|
| 105 |
+
### 4.2 Pattern Recognition
|
| 106 |
+
- **Candlestick Pattern Detection**:
|
| 107 |
+
- CNN-based image recognition for chart patterns
|
| 108 |
+
- Rule-based detection for common patterns (head and shoulders, double tops, etc.)
|
| 109 |
+
- **Support/Resistance Level Identification**:
|
| 110 |
+
- Clustering algorithms to identify price levels
|
| 111 |
+
- Fractal analysis for multi-timeframe support/resistance
|
| 112 |
+
|
| 113 |
+
### 4.3 Anomaly Detection
|
| 114 |
+
- **Statistical Methods**:
|
| 115 |
+
- Z-score analysis for outlier detection
|
| 116 |
+
- DBSCAN for identifying unusual price/volume clusters
|
| 117 |
+
- **Deep Learning Approaches**:
|
| 118 |
+
- Autoencoders for unsupervised anomaly detection
|
| 119 |
+
- Sequence models to detect unusual patterns in time series
|
| 120 |
+
|
| 121 |
+
## 5. Development Roadmap
|
| 122 |
+
|
| 123 |
+
### Phase 1: Foundation (Weeks 1-2)
|
| 124 |
+
- Set up project structure and environment
|
| 125 |
+
- Implement data collection from yFinance and Google Finance
|
| 126 |
+
- Create basic data processing pipeline
|
| 127 |
+
- Develop database schema for storing historical data
|
| 128 |
+
|
| 129 |
+
### Phase 2: Technical Analysis Engine (Weeks 3-4)
|
| 130 |
+
- Implement all technical indicators
|
| 131 |
+
- Create visualization components for indicators
|
| 132 |
+
- Develop backtesting framework for indicator performance
|
| 133 |
+
|
| 134 |
+
### Phase 3: AI Model Development (Weeks 5-8)
|
| 135 |
+
- Develop and train prediction models
|
| 136 |
+
- Implement pattern recognition algorithms
|
| 137 |
+
- Create anomaly detection systems
|
| 138 |
+
- Integrate all AI components
|
| 139 |
+
|
| 140 |
+
### Phase 4: Signal Generation (Weeks 9-10)
|
| 141 |
+
- Develop signal generation logic
|
| 142 |
+
- Implement confidence scoring system
|
| 143 |
+
- Create alert mechanism
|
| 144 |
+
- Test and optimize signal accuracy
|
| 145 |
+
|
| 146 |
+
### Phase 5: Web Interface (Weeks 11-14)
|
| 147 |
+
- Develop backend API
|
| 148 |
+
- Create frontend dashboard
|
| 149 |
+
- Implement stock screener
|
| 150 |
+
- Add user preference management
|
| 151 |
+
- Optimize performance and UX
|
| 152 |
+
|
| 153 |
+
### Phase 6: Testing and Deployment (Weeks 15-16)
|
| 154 |
+
- Comprehensive testing
|
| 155 |
+
- Performance optimization
|
| 156 |
+
- Deployment to production
|
| 157 |
+
- Documentation and user guides
|
| 158 |
+
|
| 159 |
+
## 6. Technology Stack Recommendation
|
| 160 |
+
|
| 161 |
+
### Backend
|
| 162 |
+
- **Language**: Python 3.9+
|
| 163 |
+
- **Web Framework**: FastAPI (high performance, easy API development)
|
| 164 |
+
- **Data Processing**: Pandas, NumPy, TA-Lib
|
| 165 |
+
- **Machine Learning**: Scikit-learn, TensorFlow/Keras, Prophet
|
| 166 |
+
- **Database**: PostgreSQL (time-series data), Redis (caching)
|
| 167 |
+
- **Task Queue**: Celery (for background processing)
|
| 168 |
+
|
| 169 |
+
### Frontend
|
| 170 |
+
- **Framework**: React with TypeScript
|
| 171 |
+
- **State Management**: Redux or Context API
|
| 172 |
+
- **Charting**: TradingView Lightweight Charts or Plotly
|
| 173 |
+
- **UI Components**: Material-UI or Ant Design
|
| 174 |
+
- **API Communication**: Axios
|
| 175 |
+
|
| 176 |
+
### DevOps
|
| 177 |
+
- **Containerization**: Docker
|
| 178 |
+
- **Orchestration**: Docker Compose (development), Kubernetes (production)
|
| 179 |
+
- **CI/CD**: GitHub Actions
|
| 180 |
+
- **Monitoring**: Prometheus, Grafana
|
| 181 |
+
- **Hosting**: AWS or GCP
|
| 182 |
+
|
| 183 |
+
## 7. Data Flow and Processing
|
| 184 |
+
|
| 185 |
+
```mermaid
|
| 186 |
+
sequenceDiagram
|
| 187 |
+
participant DS as Data Sources
|
| 188 |
+
participant DL as Data Layer
|
| 189 |
+
participant AI as AI Layer
|
| 190 |
+
participant SG as Signal Generator
|
| 191 |
+
participant UI as Web Interface
|
| 192 |
+
participant User
|
| 193 |
+
|
| 194 |
+
DS->>DL: Raw stock data
|
| 195 |
+
DL->>DL: Clean and process data
|
| 196 |
+
DL->>DL: Calculate technical indicators
|
| 197 |
+
DL->>AI: Processed data
|
| 198 |
+
AI->>AI: Apply prediction models
|
| 199 |
+
AI->>AI: Perform pattern recognition
|
| 200 |
+
AI->>AI: Detect anomalies
|
| 201 |
+
AI->>SG: Analysis results
|
| 202 |
+
SG->>SG: Generate signals
|
| 203 |
+
SG->>SG: Calculate confidence scores
|
| 204 |
+
SG->>UI: Trading signals
|
| 205 |
+
UI->>User: Display dashboard
|
| 206 |
+
User->>UI: Select stock/timeframe
|
| 207 |
+
UI->>DL: Request specific data
|
| 208 |
+
DL->>UI: Return requested data
|
| 209 |
+
UI->>User: Show detailed analysis
|
| 210 |
+
```
|
| 211 |
+
|
| 212 |
+
## 8. Key Challenges and Considerations
|
| 213 |
+
|
| 214 |
+
1. **Data Quality and Consistency**:
|
| 215 |
+
- Handling missing data points
|
| 216 |
+
- Reconciling differences between data sources
|
| 217 |
+
- Managing API rate limits and outages
|
| 218 |
+
|
| 219 |
+
2. **Model Accuracy and Reliability**:
|
| 220 |
+
- Avoiding overfitting in prediction models
|
| 221 |
+
- Balancing sensitivity and specificity in signal generation
|
| 222 |
+
- Adapting to changing market conditions
|
| 223 |
+
|
| 224 |
+
3. **Performance Optimization**:
|
| 225 |
+
- Efficient processing of large datasets
|
| 226 |
+
- Real-time updates without overwhelming resources
|
| 227 |
+
- Caching strategies for frequently accessed data
|
| 228 |
+
|
| 229 |
+
4. **Scalability**:
|
| 230 |
+
- Supporting a growing number of stocks
|
| 231 |
+
- Handling increased user load
|
| 232 |
+
- Managing computational resources for AI models
|
| 233 |
+
|
| 234 |
+
5. **User Experience**:
|
| 235 |
+
- Presenting complex information in an intuitive way
|
| 236 |
+
- Providing appropriate level of detail for different user types
|
| 237 |
+
- Ensuring responsive performance across devices
|
| 238 |
+
|
| 239 |
+
## 9. Future Expansion Possibilities
|
| 240 |
+
|
| 241 |
+
1. **Additional Data Sources**:
|
| 242 |
+
- News sentiment analysis
|
| 243 |
+
- Social media trends
|
| 244 |
+
- Economic indicators
|
| 245 |
+
|
| 246 |
+
2. **Advanced AI Features**:
|
| 247 |
+
- Reinforcement learning for strategy optimization
|
| 248 |
+
- NLP for news and report analysis
|
| 249 |
+
- Explainable AI for signal justification
|
| 250 |
+
|
| 251 |
+
3. **User Features**:
|
| 252 |
+
- Custom strategy builder
|
| 253 |
+
- Portfolio tracking and optimization
|
| 254 |
+
- Performance analytics and reporting
|
| 255 |
+
|
| 256 |
+
4. **Integration Options**:
|
| 257 |
+
- Broker API connections for automated trading
|
| 258 |
+
- Export to trading platforms
|
| 259 |
+
- Mobile app development
|
attached_assets/symbol.csv
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"SYMBOL
|
| 2 |
+
"
|
| 3 |
+
KEI
|
| 4 |
+
BANDHANBNK
|
| 5 |
+
SHRIRAMFIN
|
| 6 |
+
HDFCBANK
|
| 7 |
+
PHOENIXLTD
|
| 8 |
+
AUBANK
|
| 9 |
+
COALINDIA
|
| 10 |
+
DIXON
|
| 11 |
+
LUPIN
|
| 12 |
+
JSWENERGY
|
| 13 |
+
POLYCAB
|
| 14 |
+
INDIGO
|
| 15 |
+
VOLTAS
|
| 16 |
+
TRENT
|
| 17 |
+
SOLARINDS
|
| 18 |
+
HINDALCO
|
| 19 |
+
ANGELONE
|
| 20 |
+
GMRAIRPORT
|
| 21 |
+
PIIND
|
| 22 |
+
LICI
|
| 23 |
+
NYKAA
|
| 24 |
+
AXISBANK
|
| 25 |
+
ABFRL
|
| 26 |
+
KALYANKJIL
|
| 27 |
+
MRF
|
| 28 |
+
FEDERALBNK
|
| 29 |
+
IEX
|
| 30 |
+
ACC
|
| 31 |
+
GODREJPROP
|
| 32 |
+
ICICIGI
|
| 33 |
+
PIDILITIND
|
| 34 |
+
APLAPOLLO
|
| 35 |
+
ABCAPITAL
|
| 36 |
+
ADANIENT
|
| 37 |
+
ADANIPORTS
|
| 38 |
+
GRASIM
|
| 39 |
+
ALKEM
|
| 40 |
+
RELIANCE
|
| 41 |
+
PRESTIGE
|
| 42 |
+
GAIL
|
| 43 |
+
DRREDDY
|
| 44 |
+
POONAWALLA
|
| 45 |
+
SAIL
|
| 46 |
+
NATIONALUM
|
| 47 |
+
COLPAL
|
| 48 |
+
AMBUJACEM
|
| 49 |
+
BOSCHLTD
|
| 50 |
+
TATASTEEL
|
| 51 |
+
IDFCFIRSTB
|
| 52 |
+
RAMCOCEM
|
| 53 |
+
ZYDUSLIFE
|
| 54 |
+
INDHOTEL
|
| 55 |
+
LT
|
| 56 |
+
TATAPOWER
|
| 57 |
+
BANKINDIA
|
| 58 |
+
JINDALSTEL
|
| 59 |
+
ITC
|
| 60 |
+
HDFCLIFE
|
| 61 |
+
DLF
|
| 62 |
+
ASIANPAINT
|
| 63 |
+
CROMPTON
|
| 64 |
+
HEROMOTOCO
|
| 65 |
+
ADANIENSOL
|
| 66 |
+
DEEPAKNTR
|
| 67 |
+
CGPOWER
|
| 68 |
+
SIEMENS
|
| 69 |
+
NHPC
|
| 70 |
+
NTPC
|
| 71 |
+
PAYTM
|
| 72 |
+
DALBHARAT
|
| 73 |
+
HDFCAMC
|
| 74 |
+
APOLLOHOSP
|
| 75 |
+
ICICIPRULI
|
| 76 |
+
POWERGRID
|
| 77 |
+
ICICIBANK
|
| 78 |
+
PATANJALI
|
| 79 |
+
DABUR
|
| 80 |
+
BAJFINANCE
|
| 81 |
+
HAVELLS
|
| 82 |
+
JKCEMENT
|
| 83 |
+
EXIDEIND
|
| 84 |
+
NCC
|
| 85 |
+
ESCORTS
|
| 86 |
+
JSL
|
| 87 |
+
SBIN
|
| 88 |
+
UNIONBANK
|
| 89 |
+
SRF
|
| 90 |
+
BEL
|
| 91 |
+
TORNTPHARM
|
| 92 |
+
UPL
|
| 93 |
+
IOC
|
| 94 |
+
JSWSTEEL
|
| 95 |
+
HINDUNILVR
|
| 96 |
+
INDIANB
|
| 97 |
+
GLENMARK
|
| 98 |
+
POLICYBZR
|
| 99 |
+
BHARATFORG
|
| 100 |
+
AUROPHARMA
|
| 101 |
+
ONGC
|
| 102 |
+
VEDL
|
| 103 |
+
MFSL
|
| 104 |
+
SONACOMS
|
| 105 |
+
OBEROIRLTY
|
| 106 |
+
CIPLA
|
| 107 |
+
KOTAKBANK
|
| 108 |
+
COFORGE
|
| 109 |
+
SBICARD
|
| 110 |
+
TATACHEM
|
| 111 |
+
TATAELXSI
|
| 112 |
+
EICHERMOT
|
| 113 |
+
CUMMINSIND
|
| 114 |
+
DELHIVERY
|
| 115 |
+
CANBK
|
| 116 |
+
SBILIFE
|
| 117 |
+
BPCL
|
| 118 |
+
DIVISLAB
|
| 119 |
+
CESC
|
| 120 |
+
TATACOMM
|
| 121 |
+
DMART
|
| 122 |
+
RBLBANK
|
| 123 |
+
BANKBARODA
|
| 124 |
+
TORNTPOWER
|
| 125 |
+
BAJAJFINSV
|
| 126 |
+
BIOCON
|
| 127 |
+
LTTS
|
| 128 |
+
IRCTC
|
| 129 |
+
TIINDIA
|
| 130 |
+
CHOLAFIN
|
| 131 |
+
BERGEPAINT
|
| 132 |
+
IDEA
|
| 133 |
+
CYIENT
|
| 134 |
+
PAGEIND
|
| 135 |
+
IGL
|
| 136 |
+
BALKRISIND
|
| 137 |
+
ASTRAL
|
| 138 |
+
LTF
|
| 139 |
+
MOTHERSON
|
| 140 |
+
LICHSGFIN
|
| 141 |
+
LAURUSLABS
|
| 142 |
+
HCLTECH
|
| 143 |
+
CAMS
|
| 144 |
+
YESBANK
|
| 145 |
+
ZOMATO
|
| 146 |
+
ULTRACEMCO
|
| 147 |
+
PEL
|
| 148 |
+
SYNGENE
|
| 149 |
+
PFC
|
| 150 |
+
MARUTI
|
| 151 |
+
SUNPHARMA
|
| 152 |
+
VBL
|
| 153 |
+
SHREECEM
|
| 154 |
+
MUTHOOTFIN
|
| 155 |
+
NESTLEIND
|
| 156 |
+
NBCC
|
| 157 |
+
TCS
|
| 158 |
+
ATGL
|
| 159 |
+
MARICO
|
| 160 |
+
M&MFIN
|
| 161 |
+
UNITDSPR
|
| 162 |
+
PERSISTENT
|
| 163 |
+
APOLLOTYRE
|
| 164 |
+
BAJAJ-AUTO
|
| 165 |
+
CDSL
|
| 166 |
+
HINDPETRO
|
| 167 |
+
NMDC
|
| 168 |
+
MANAPPURAM
|
| 169 |
+
ABB
|
| 170 |
+
BRITANNIA
|
| 171 |
+
OFSS
|
| 172 |
+
GODREJCP
|
| 173 |
+
INFY
|
| 174 |
+
IRB
|
| 175 |
+
TATACONSUM
|
| 176 |
+
HUDCO
|
| 177 |
+
TITAN
|
| 178 |
+
TATAMOTORS
|
| 179 |
+
INDUSTOWER
|
| 180 |
+
KPITTECH
|
| 181 |
+
RECLTD
|
| 182 |
+
LTIM
|
| 183 |
+
TVSMOTOR
|
| 184 |
+
BHEL
|
| 185 |
+
HAL
|
| 186 |
+
SUPREMEIND
|
| 187 |
+
HFCL
|
| 188 |
+
MAXHEALTH
|
| 189 |
+
AARTIIND
|
| 190 |
+
SJVN
|
| 191 |
+
M&M
|
| 192 |
+
BHARTIARTL
|
| 193 |
+
PNB
|
| 194 |
+
IIFL
|
| 195 |
+
NAUKRI
|
| 196 |
+
HINDCOPPER
|
| 197 |
+
PETRONET
|
| 198 |
+
ASHOKLEY
|
| 199 |
+
MPHASIS
|
| 200 |
+
WIPRO
|
| 201 |
+
BSOFT
|
| 202 |
+
CONCOR
|
| 203 |
+
TITAGARH
|
| 204 |
+
MGL
|
| 205 |
+
LODHA
|
| 206 |
+
ADANIGREEN
|
| 207 |
+
IREDA
|
| 208 |
+
TATATECH
|
| 209 |
+
JIOFIN
|
| 210 |
+
OIL
|
| 211 |
+
TECHM
|
| 212 |
+
IRFC
|
| 213 |
+
CHAMBLFERT
|
| 214 |
+
JUBLFOOD
|
| 215 |
+
INDUSINDBK
|
| 216 |
+
MCX
|
| 217 |
+
GRANULES
|
| 218 |
+
BSE
|
generated-icon.png
ADDED
|
|
Git LFS Details
|
main.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
|
| 3 |
+
st.set_page_config(
|
| 4 |
+
page_title="NSE Stock Analysis",
|
| 5 |
+
page_icon="📈",
|
| 6 |
+
layout="wide",
|
| 7 |
+
initial_sidebar_state="expanded"
|
| 8 |
+
)
|
| 9 |
+
|
| 10 |
+
# Custom CSS to reduce sidebar width and improve layout
|
| 11 |
+
st.markdown("""
|
| 12 |
+
<style>
|
| 13 |
+
[data-testid="stSidebar"][aria-expanded="true"] {
|
| 14 |
+
min-width: 200px;
|
| 15 |
+
max-width: 200px;
|
| 16 |
+
}
|
| 17 |
+
[data-testid="stSidebar"][aria-expanded="false"] {
|
| 18 |
+
min-width: 200px;
|
| 19 |
+
margin-left: -200px;
|
| 20 |
+
}
|
| 21 |
+
.css-1d391kg {
|
| 22 |
+
padding-top: 1rem;
|
| 23 |
+
}
|
| 24 |
+
.stApp > header {
|
| 25 |
+
background-color: transparent;
|
| 26 |
+
}
|
| 27 |
+
.news-table {
|
| 28 |
+
font-size: 14px;
|
| 29 |
+
width: 100%;
|
| 30 |
+
}
|
| 31 |
+
.news-table td {
|
| 32 |
+
padding: 8px;
|
| 33 |
+
}
|
| 34 |
+
</style>
|
| 35 |
+
""", unsafe_allow_html=True)
|
| 36 |
+
|
| 37 |
+
def main():
|
| 38 |
+
st.title("NSE Stock Analysis Platform")
|
| 39 |
+
|
| 40 |
+
st.markdown("""
|
| 41 |
+
Welcome to the NSE Stock Analysis Platform. This tool provides technical analysis and trading signals
|
| 42 |
+
for NSE-listed stocks.
|
| 43 |
+
|
| 44 |
+
### Features:
|
| 45 |
+
- Real-time stock data and technical indicators
|
| 46 |
+
- Interactive charts with multiple timeframes
|
| 47 |
+
- Trading signals based on technical analysis
|
| 48 |
+
- Stock screener with customizable criteria
|
| 49 |
+
- Latest news for NSE stocks
|
| 50 |
+
- AI-powered stock recommendations
|
| 51 |
+
|
| 52 |
+
### Available Tools:
|
| 53 |
+
1. **Stock Analysis**: Detailed technical analysis with multiple indicators
|
| 54 |
+
2. **Stock Screener**: Screen stocks based on technical criteria
|
| 55 |
+
3. **AI Recommendations**: Get AI-powered stock recommendations
|
| 56 |
+
4. **News**: Latest news articles for NSE stocks
|
| 57 |
+
|
| 58 |
+
Choose a tool from the sidebar to get started.
|
| 59 |
+
""")
|
| 60 |
+
|
| 61 |
+
st.sidebar.title("Navigation")
|
| 62 |
+
page = st.sidebar.radio("Select a Tool",
|
| 63 |
+
["Stock Analysis", "Stock Screener", "AI Recommendations", "News"])
|
| 64 |
+
|
| 65 |
+
if page == "Stock Analysis":
|
| 66 |
+
from pages.stock_analysis import stock_analysis_page
|
| 67 |
+
stock_analysis_page()
|
| 68 |
+
elif page == "Stock Screener":
|
| 69 |
+
from pages.stock_screener import stock_screener_page
|
| 70 |
+
stock_screener_page()
|
| 71 |
+
elif page == "AI Recommendations":
|
| 72 |
+
from pages.recommendations import recommendations_page
|
| 73 |
+
recommendations_page()
|
| 74 |
+
else:
|
| 75 |
+
from pages.news import news_page
|
| 76 |
+
news_page()
|
| 77 |
+
|
| 78 |
+
if __name__ == "__main__":
|
| 79 |
+
main()
|
pages/news.py
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
import feedparser
|
| 3 |
+
import pandas as pd
|
| 4 |
+
from datetime import datetime
|
| 5 |
+
from urllib.parse import quote
|
| 6 |
+
import pytz
|
| 7 |
+
|
| 8 |
+
def fetch_stock_news(symbol):
|
| 9 |
+
"""Fetch news for a specific stock symbol."""
|
| 10 |
+
query = f"{symbol} NSE stock"
|
| 11 |
+
encoded_query = quote(query)
|
| 12 |
+
feed_url = f"https://news.google.com/rss/search?q={encoded_query}&hl=en-IN&gl=IN&ceid=IN:en"
|
| 13 |
+
|
| 14 |
+
try:
|
| 15 |
+
feed = feedparser.parse(feed_url)
|
| 16 |
+
news_items = []
|
| 17 |
+
|
| 18 |
+
for entry in feed.entries[:5]: # Get top 5 news items per stock
|
| 19 |
+
# Convert UTC time to IST
|
| 20 |
+
utc_time = datetime.strptime(entry.published, '%a, %d %b %Y %H:%M:%S %Z')
|
| 21 |
+
ist_timezone = pytz.timezone('Asia/Kolkata')
|
| 22 |
+
ist_time = utc_time.replace(tzinfo=pytz.UTC).astimezone(ist_timezone)
|
| 23 |
+
|
| 24 |
+
news_items.append({
|
| 25 |
+
'Symbol': symbol,
|
| 26 |
+
'Title': entry.title,
|
| 27 |
+
'Link': entry.link,
|
| 28 |
+
'Published': ist_time,
|
| 29 |
+
'Source': entry.source.title if hasattr(entry, 'source') else 'Unknown'
|
| 30 |
+
})
|
| 31 |
+
|
| 32 |
+
return news_items
|
| 33 |
+
except Exception as e:
|
| 34 |
+
st.error(f"Error fetching news for {symbol}: {str(e)}")
|
| 35 |
+
return []
|
| 36 |
+
|
| 37 |
+
def news_page():
|
| 38 |
+
st.title("NSE Stocks News")
|
| 39 |
+
|
| 40 |
+
try:
|
| 41 |
+
# Read symbols from CSV
|
| 42 |
+
symbols = pd.read_csv("attached_assets/symbol.csv", names=['Symbol'], skiprows=1)
|
| 43 |
+
symbols_list = symbols['Symbol'].dropna().tolist()
|
| 44 |
+
|
| 45 |
+
# Fetch news for all symbols
|
| 46 |
+
with st.spinner("Fetching latest news..."):
|
| 47 |
+
all_news = []
|
| 48 |
+
for symbol in symbols_list:
|
| 49 |
+
all_news.extend(fetch_stock_news(symbol))
|
| 50 |
+
|
| 51 |
+
# Sort news by publication date
|
| 52 |
+
all_news.sort(key=lambda x: x['Published'], reverse=True)
|
| 53 |
+
|
| 54 |
+
# Create DataFrame for display
|
| 55 |
+
news_df = pd.DataFrame(all_news)
|
| 56 |
+
|
| 57 |
+
# Format the table
|
| 58 |
+
if not news_df.empty:
|
| 59 |
+
# Convert datetime to IST 12-hour format string
|
| 60 |
+
news_df['Published'] = news_df['Published'].dt.strftime('%I:%M %p, %d %b %Y')
|
| 61 |
+
|
| 62 |
+
# Create clickable links
|
| 63 |
+
news_df['Title'] = news_df.apply(
|
| 64 |
+
lambda row: f'<a href="{row["Link"]}" target="_blank">{row["Title"]}</a>',
|
| 65 |
+
axis=1
|
| 66 |
+
)
|
| 67 |
+
|
| 68 |
+
# Display the table with HTML
|
| 69 |
+
st.markdown("""
|
| 70 |
+
<style>
|
| 71 |
+
.news-table {
|
| 72 |
+
font-size: 14px;
|
| 73 |
+
}
|
| 74 |
+
</style>
|
| 75 |
+
""", unsafe_allow_html=True)
|
| 76 |
+
|
| 77 |
+
st.markdown(
|
| 78 |
+
news_df[['Published', 'Symbol', 'Title', 'Source']]
|
| 79 |
+
.to_html(escape=False, index=False, classes='news-table'),
|
| 80 |
+
unsafe_allow_html=True
|
| 81 |
+
)
|
| 82 |
+
else:
|
| 83 |
+
st.info("No news articles found.")
|
| 84 |
+
|
| 85 |
+
except Exception as e:
|
| 86 |
+
st.error(f"Error loading news: {str(e)}")
|
| 87 |
+
|
| 88 |
+
if __name__ == "__main__":
|
| 89 |
+
news_page()
|
pages/recommendations.py
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
import pandas as pd
|
| 3 |
+
from utils.stock_data import get_stock_data, format_number
|
| 4 |
+
from utils.recommendation_engine import analyze_stock
|
| 5 |
+
|
| 6 |
+
def recommendations_page():
|
| 7 |
+
st.title("AI Stock Recommendations")
|
| 8 |
+
|
| 9 |
+
# Load symbols
|
| 10 |
+
try:
|
| 11 |
+
symbols = pd.read_csv("attached_assets/symbol.csv", names=['Symbol'], skiprows=1)
|
| 12 |
+
symbols_list = symbols['Symbol'].dropna().tolist()
|
| 13 |
+
except Exception as e:
|
| 14 |
+
st.error(f"Error loading symbols: {str(e)}")
|
| 15 |
+
return
|
| 16 |
+
|
| 17 |
+
# Analysis parameters
|
| 18 |
+
min_confidence = st.selectbox("Minimum Confidence Level", ["Low", "Medium", "High"])
|
| 19 |
+
|
| 20 |
+
if st.button("Generate Recommendations"):
|
| 21 |
+
with st.spinner("Analyzing all NSE stocks..."):
|
| 22 |
+
recommendations = []
|
| 23 |
+
|
| 24 |
+
# Progress bar for analysis
|
| 25 |
+
progress_bar = st.progress(0)
|
| 26 |
+
total_stocks = len(symbols_list)
|
| 27 |
+
|
| 28 |
+
# Analyze each stock
|
| 29 |
+
for idx, symbol in enumerate(symbols_list):
|
| 30 |
+
df, error = get_stock_data(symbol, period='3mo', interval='1d')
|
| 31 |
+
if error:
|
| 32 |
+
continue
|
| 33 |
+
|
| 34 |
+
analysis = analyze_stock(symbol, df)
|
| 35 |
+
if analysis:
|
| 36 |
+
recommendations.append(analysis)
|
| 37 |
+
|
| 38 |
+
# Update progress
|
| 39 |
+
progress_bar.progress((idx + 1) / total_stocks)
|
| 40 |
+
|
| 41 |
+
if recommendations:
|
| 42 |
+
# Convert to DataFrame
|
| 43 |
+
rec_df = pd.DataFrame(recommendations)
|
| 44 |
+
|
| 45 |
+
# Filter by confidence
|
| 46 |
+
confidence_levels = {'Low': 0, 'Medium': 1, 'High': 2}
|
| 47 |
+
min_conf_level = confidence_levels[min_confidence]
|
| 48 |
+
rec_df = rec_df[rec_df['confidence'].map(lambda x: confidence_levels[x]) >= min_conf_level]
|
| 49 |
+
|
| 50 |
+
# Sort by technical score
|
| 51 |
+
rec_df = rec_df.sort_values('technical_score', ascending=False)
|
| 52 |
+
|
| 53 |
+
# Display recommendations
|
| 54 |
+
st.subheader("Stock Recommendations")
|
| 55 |
+
|
| 56 |
+
# Format DataFrame for display
|
| 57 |
+
display_df = rec_df.copy()
|
| 58 |
+
display_df['price_change'] = display_df['price_change'].round(2).astype(str) + '%'
|
| 59 |
+
display_df['technical_score'] = display_df['technical_score'].round(2)
|
| 60 |
+
|
| 61 |
+
# Generate recommendation basis
|
| 62 |
+
basis_list = []
|
| 63 |
+
for _, row in display_df.iterrows():
|
| 64 |
+
signals = []
|
| 65 |
+
if row['technical_score'] > 50:
|
| 66 |
+
signals.append("Strong technical indicators")
|
| 67 |
+
if 'RSI' in row['signal_summary'] and row['signal_summary']['RSI'] == 'Oversold':
|
| 68 |
+
signals.append("Oversold (RSI)")
|
| 69 |
+
if 'MACD' in row['signal_summary'] and row['signal_summary']['MACD'] == 'Buy':
|
| 70 |
+
signals.append("Bullish MACD crossover")
|
| 71 |
+
if 'Moving Average' in row['signal_summary'] and row['signal_summary']['Moving Average'] == 'Bullish':
|
| 72 |
+
signals.append("Above key moving averages")
|
| 73 |
+
basis_list.append(", ".join(signals) if signals else "Multiple factors")
|
| 74 |
+
|
| 75 |
+
display_df['Basis'] = basis_list
|
| 76 |
+
|
| 77 |
+
# Color-code recommendations
|
| 78 |
+
def color_recommendations(val):
|
| 79 |
+
if 'Strong Buy' in val:
|
| 80 |
+
return 'background-color: #9fff9c'
|
| 81 |
+
elif 'Buy' in val:
|
| 82 |
+
return 'background-color: #c8ffc6'
|
| 83 |
+
elif 'Strong Sell' in val:
|
| 84 |
+
return 'background-color: #ffc6c6'
|
| 85 |
+
elif 'Sell' in val:
|
| 86 |
+
return 'background-color: #ffdede'
|
| 87 |
+
return ''
|
| 88 |
+
|
| 89 |
+
# Display styled table
|
| 90 |
+
st.dataframe(
|
| 91 |
+
display_df[['symbol', 'recommendation', 'confidence', 'technical_score',
|
| 92 |
+
'price_change', 'last_price', 'Basis']]
|
| 93 |
+
.style
|
| 94 |
+
.apply(lambda x: [color_recommendations(val) for val in x], axis=1, subset=['recommendation'])
|
| 95 |
+
.format({'last_price': '₹{:.2f}'})
|
| 96 |
+
)
|
| 97 |
+
|
| 98 |
+
# Display analysis insights
|
| 99 |
+
st.subheader("Analysis Insights")
|
| 100 |
+
total_analyzed = len(recommendations)
|
| 101 |
+
buy_signals = len(rec_df[rec_df['recommendation'].isin(['Buy', 'Strong Buy'])])
|
| 102 |
+
sell_signals = len(rec_df[rec_df['recommendation'].isin(['Sell', 'Strong Sell'])])
|
| 103 |
+
|
| 104 |
+
col1, col2, col3 = st.columns(3)
|
| 105 |
+
col1.metric("Total Stocks Analyzed", total_analyzed)
|
| 106 |
+
col2.metric("Buy Signals", buy_signals)
|
| 107 |
+
col3.metric("Sell Signals", sell_signals)
|
| 108 |
+
|
| 109 |
+
# Display market sentiment
|
| 110 |
+
st.subheader("Market Sentiment")
|
| 111 |
+
buy_percentage = (buy_signals / total_analyzed) * 100
|
| 112 |
+
if buy_percentage > 60:
|
| 113 |
+
sentiment = "Bullish"
|
| 114 |
+
color = "green"
|
| 115 |
+
elif buy_percentage < 40:
|
| 116 |
+
sentiment = "Bearish"
|
| 117 |
+
color = "red"
|
| 118 |
+
else:
|
| 119 |
+
sentiment = "Neutral"
|
| 120 |
+
color = "gray"
|
| 121 |
+
|
| 122 |
+
st.markdown(f"Overall Market Sentiment: <span style='color: {color}'>{sentiment}</span>",
|
| 123 |
+
unsafe_allow_html=True)
|
| 124 |
+
|
| 125 |
+
else:
|
| 126 |
+
st.warning("No recommendations generated. Please try with different parameters.")
|
| 127 |
+
|
| 128 |
+
if __name__ == "__main__":
|
| 129 |
+
recommendations_page()
|
pages/stock_analysis.py
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
import plotly.graph_objects as go
|
| 3 |
+
from plotly.subplots import make_subplots
|
| 4 |
+
import pandas as pd
|
| 5 |
+
|
| 6 |
+
from utils.stock_data import get_stock_data, get_company_info, format_number
|
| 7 |
+
from utils.indicators import add_indicators
|
| 8 |
+
from utils.signals import generate_signals, get_signal_summary
|
| 9 |
+
|
| 10 |
+
def plot_stock_data(df, signals):
|
| 11 |
+
"""Create interactive stock charts with indicators."""
|
| 12 |
+
fig = make_subplots(rows=3, cols=1,
|
| 13 |
+
shared_xaxes=True,
|
| 14 |
+
vertical_spacing=0.05,
|
| 15 |
+
row_heights=[0.6, 0.2, 0.2])
|
| 16 |
+
|
| 17 |
+
# Candlestick chart
|
| 18 |
+
fig.add_trace(go.Candlestick(
|
| 19 |
+
x=df.index,
|
| 20 |
+
open=df['Open'],
|
| 21 |
+
high=df['High'],
|
| 22 |
+
low=df['Low'],
|
| 23 |
+
close=df['Close'],
|
| 24 |
+
name='OHLC'
|
| 25 |
+
), row=1, col=1)
|
| 26 |
+
|
| 27 |
+
# Add indicators
|
| 28 |
+
fig.add_trace(go.Scatter(x=df.index, y=df['SMA_20'], name='SMA 20', line=dict(color='blue')), row=1, col=1)
|
| 29 |
+
fig.add_trace(go.Scatter(x=df.index, y=df['BB_Upper'], name='BB Upper', line=dict(color='gray', dash='dash')), row=1, col=1)
|
| 30 |
+
fig.add_trace(go.Scatter(x=df.index, y=df['BB_Lower'], name='BB Lower', line=dict(color='gray', dash='dash')), row=1, col=1)
|
| 31 |
+
|
| 32 |
+
# MACD
|
| 33 |
+
fig.add_trace(go.Bar(x=df.index, y=df['MACD_Hist'], name='MACD Hist'), row=2, col=1)
|
| 34 |
+
fig.add_trace(go.Scatter(x=df.index, y=df['MACD'], name='MACD'), row=2, col=1)
|
| 35 |
+
fig.add_trace(go.Scatter(x=df.index, y=df['MACD_Signal'], name='MACD Signal'), row=2, col=1)
|
| 36 |
+
|
| 37 |
+
# RSI
|
| 38 |
+
fig.add_trace(go.Scatter(x=df.index, y=df['RSI'], name='RSI'), row=3, col=1)
|
| 39 |
+
fig.add_hline(y=70, line_dash="dash", line_color="red", row=3, col=1)
|
| 40 |
+
fig.add_hline(y=30, line_dash="dash", line_color="green", row=3, col=1)
|
| 41 |
+
|
| 42 |
+
# Update layout
|
| 43 |
+
fig.update_layout(
|
| 44 |
+
height=800,
|
| 45 |
+
xaxis_rangeslider_visible=False,
|
| 46 |
+
template='plotly_white',
|
| 47 |
+
showlegend=True,
|
| 48 |
+
legend=dict(
|
| 49 |
+
orientation="h",
|
| 50 |
+
yanchor="bottom",
|
| 51 |
+
y=1.02,
|
| 52 |
+
xanchor="right",
|
| 53 |
+
x=1
|
| 54 |
+
)
|
| 55 |
+
)
|
| 56 |
+
|
| 57 |
+
# Update y-axis titles
|
| 58 |
+
fig.update_yaxes(title_text="Price", row=1, col=1)
|
| 59 |
+
fig.update_yaxes(title_text="MACD", row=2, col=1)
|
| 60 |
+
fig.update_yaxes(title_text="RSI", row=3, col=1)
|
| 61 |
+
|
| 62 |
+
return fig
|
| 63 |
+
|
| 64 |
+
def stock_analysis_page():
|
| 65 |
+
st.title("Stock Technical Analysis")
|
| 66 |
+
|
| 67 |
+
# Load symbols from CSV
|
| 68 |
+
try:
|
| 69 |
+
# Read CSV file with no header, then assign column name
|
| 70 |
+
symbols = pd.read_csv("attached_assets/symbol.csv", names=['Symbol'], skiprows=1)
|
| 71 |
+
selected_symbol = st.selectbox("Select Stock", symbols['Symbol'].dropna())
|
| 72 |
+
except Exception as e:
|
| 73 |
+
st.error(f"Error loading symbols: {str(e)}")
|
| 74 |
+
return
|
| 75 |
+
|
| 76 |
+
col1, col2, col3 = st.columns(3)
|
| 77 |
+
timeframe = col1.selectbox("Timeframe", ['1mo', '3mo', '6mo', '1y', '2y', '5y'])
|
| 78 |
+
interval = col2.selectbox("Interval", ['1d', '5d', '1wk', '1mo'])
|
| 79 |
+
|
| 80 |
+
if col3.button("Analyze"):
|
| 81 |
+
with st.spinner("Fetching data..."):
|
| 82 |
+
df, error = get_stock_data(selected_symbol, timeframe, interval)
|
| 83 |
+
|
| 84 |
+
if error:
|
| 85 |
+
st.error(error)
|
| 86 |
+
return
|
| 87 |
+
|
| 88 |
+
# Calculate price change
|
| 89 |
+
current_price = df['Close'].iloc[-1]
|
| 90 |
+
prev_price = df['Close'].iloc[-2]
|
| 91 |
+
price_change = ((current_price / prev_price) - 1) * 100
|
| 92 |
+
price_change_color = "green" if price_change >= 0 else "red"
|
| 93 |
+
|
| 94 |
+
# Get company info
|
| 95 |
+
info = get_company_info(selected_symbol)
|
| 96 |
+
|
| 97 |
+
# Display company info with current price and change
|
| 98 |
+
st.subheader(info['name'])
|
| 99 |
+
cols = st.columns(6)
|
| 100 |
+
cols[0].metric("Sector", info['sector'])
|
| 101 |
+
cols[1].metric("Industry", info['industry'])
|
| 102 |
+
cols[2].metric("Market Cap", format_number(info['market_cap']))
|
| 103 |
+
cols[3].metric("Volume", format_number(info['volume']))
|
| 104 |
+
cols[4].metric("Current Price", f"₹{current_price:.2f}")
|
| 105 |
+
cols[5].metric("Day Change", f"{price_change:+.2f}%",
|
| 106 |
+
delta_color="normal" if price_change >= 0 else "inverse")
|
| 107 |
+
|
| 108 |
+
# Calculate indicators and signals
|
| 109 |
+
df = add_indicators(df)
|
| 110 |
+
signals = generate_signals(df)
|
| 111 |
+
|
| 112 |
+
# Plot charts
|
| 113 |
+
st.plotly_chart(plot_stock_data(df, signals), use_container_width=True)
|
| 114 |
+
|
| 115 |
+
# Display signals
|
| 116 |
+
st.subheader("Trading Signals")
|
| 117 |
+
signal_summary = get_signal_summary(signals)
|
| 118 |
+
|
| 119 |
+
signal_cols = st.columns(5)
|
| 120 |
+
for i, (indicator, signal) in enumerate(signal_summary.items()):
|
| 121 |
+
color = "green" if signal in ['Buy', 'Bullish', 'Oversold'] else "red" if signal in ['Sell', 'Bearish', 'Overbought'] else "gray"
|
| 122 |
+
signal_cols[i].markdown(f"**{indicator}**")
|
| 123 |
+
signal_cols[i].markdown(f"<p style='color: {color}'>{signal}</p>", unsafe_allow_html=True)
|
| 124 |
+
|
| 125 |
+
if __name__ == "__main__":
|
| 126 |
+
stock_analysis_page()
|
pages/stock_screener.py
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st
|
| 2 |
+
import pandas as pd
|
| 3 |
+
from utils.stock_data import get_stock_data
|
| 4 |
+
from utils.indicators import add_indicators
|
| 5 |
+
from utils.signals import generate_signals
|
| 6 |
+
|
| 7 |
+
def screen_stocks(symbols, criteria):
|
| 8 |
+
"""Screen stocks based on technical criteria."""
|
| 9 |
+
results = []
|
| 10 |
+
|
| 11 |
+
for symbol in symbols:
|
| 12 |
+
df, error = get_stock_data(symbol, period='1mo', interval='1d')
|
| 13 |
+
if error:
|
| 14 |
+
continue
|
| 15 |
+
|
| 16 |
+
df = add_indicators(df)
|
| 17 |
+
signals = generate_signals(df)
|
| 18 |
+
latest = df.iloc[-1]
|
| 19 |
+
signal_summary = signals.iloc[-1]
|
| 20 |
+
|
| 21 |
+
meets_criteria = True
|
| 22 |
+
for criterion in criteria:
|
| 23 |
+
if criterion == 'RSI_Oversold' and latest['RSI'] >= 30:
|
| 24 |
+
meets_criteria = False
|
| 25 |
+
elif criterion == 'RSI_Overbought' and latest['RSI'] <= 70:
|
| 26 |
+
meets_criteria = False
|
| 27 |
+
elif criterion == 'Above_SMA20' and latest['Close'] <= latest['SMA_20']:
|
| 28 |
+
meets_criteria = False
|
| 29 |
+
elif criterion == 'Below_SMA20' and latest['Close'] >= latest['SMA_20']:
|
| 30 |
+
meets_criteria = False
|
| 31 |
+
elif criterion == 'MACD_Bullish' and signal_summary['MACD_Signal'] != 'Buy':
|
| 32 |
+
meets_criteria = False
|
| 33 |
+
elif criterion == 'MACD_Bearish' and signal_summary['MACD_Signal'] != 'Sell':
|
| 34 |
+
meets_criteria = False
|
| 35 |
+
|
| 36 |
+
if meets_criteria:
|
| 37 |
+
results.append({
|
| 38 |
+
'Symbol': symbol,
|
| 39 |
+
'Close': latest['Close'],
|
| 40 |
+
'RSI': latest['RSI'],
|
| 41 |
+
'MACD_Signal': signal_summary['MACD_Signal'],
|
| 42 |
+
'MA_Signal': signal_summary['MA_Signal']
|
| 43 |
+
})
|
| 44 |
+
|
| 45 |
+
return pd.DataFrame(results)
|
| 46 |
+
|
| 47 |
+
def stock_screener_page():
|
| 48 |
+
st.title("Stock Screener")
|
| 49 |
+
|
| 50 |
+
# Load symbols
|
| 51 |
+
try:
|
| 52 |
+
# Read CSV file with no header, then assign column name
|
| 53 |
+
symbols = pd.read_csv("attached_assets/symbol.csv", names=['Symbol'], skiprows=1)
|
| 54 |
+
symbols_list = symbols['Symbol'].dropna().tolist()
|
| 55 |
+
except Exception as e:
|
| 56 |
+
st.error(f"Error loading symbols: {str(e)}")
|
| 57 |
+
return
|
| 58 |
+
|
| 59 |
+
# Screening criteria
|
| 60 |
+
st.subheader("Select Screening Criteria")
|
| 61 |
+
|
| 62 |
+
col1, col2 = st.columns(2)
|
| 63 |
+
|
| 64 |
+
criteria = []
|
| 65 |
+
|
| 66 |
+
with col1:
|
| 67 |
+
if st.checkbox("RSI Conditions"):
|
| 68 |
+
if st.checkbox("Oversold (RSI < 30)"):
|
| 69 |
+
criteria.append('RSI_Oversold')
|
| 70 |
+
if st.checkbox("Overbought (RSI > 70)"):
|
| 71 |
+
criteria.append('RSI_Overbought')
|
| 72 |
+
|
| 73 |
+
with col2:
|
| 74 |
+
if st.checkbox("Moving Average Conditions"):
|
| 75 |
+
if st.checkbox("Price Above SMA20"):
|
| 76 |
+
criteria.append('Above_SMA20')
|
| 77 |
+
if st.checkbox("Price Below SMA20"):
|
| 78 |
+
criteria.append('Below_SMA20')
|
| 79 |
+
|
| 80 |
+
if st.checkbox("MACD Conditions"):
|
| 81 |
+
col3, col4 = st.columns(2)
|
| 82 |
+
with col3:
|
| 83 |
+
if st.checkbox("Bullish MACD Crossover"):
|
| 84 |
+
criteria.append('MACD_Bullish')
|
| 85 |
+
with col4:
|
| 86 |
+
if st.checkbox("Bearish MACD Crossover"):
|
| 87 |
+
criteria.append('MACD_Bearish')
|
| 88 |
+
|
| 89 |
+
if st.button("Run Screener"):
|
| 90 |
+
if not criteria:
|
| 91 |
+
st.warning("Please select at least one screening criterion")
|
| 92 |
+
return
|
| 93 |
+
|
| 94 |
+
with st.spinner("Screening stocks..."):
|
| 95 |
+
results = screen_stocks(symbols_list, criteria)
|
| 96 |
+
|
| 97 |
+
if results.empty:
|
| 98 |
+
st.info("No stocks found matching the selected criteria")
|
| 99 |
+
else:
|
| 100 |
+
st.subheader("Screening Results")
|
| 101 |
+
st.dataframe(results.style.format({
|
| 102 |
+
'Close': '{:.2f}',
|
| 103 |
+
'RSI': '{:.2f}'
|
| 104 |
+
}))
|
| 105 |
+
|
| 106 |
+
if __name__ == "__main__":
|
| 107 |
+
stock_screener_page()
|
pyproject.toml
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[project]
|
| 2 |
+
name = "repl-nix-workspace"
|
| 3 |
+
version = "0.1.0"
|
| 4 |
+
description = "Add your description here"
|
| 5 |
+
requires-python = ">=3.11"
|
| 6 |
+
dependencies = [
|
| 7 |
+
"feedparser>=6.0.11",
|
| 8 |
+
"numpy>=2.2.3",
|
| 9 |
+
"pandas>=2.2.3",
|
| 10 |
+
"plotly>=6.0.0",
|
| 11 |
+
"pytz>=2025.1",
|
| 12 |
+
"streamlit>=1.43.1",
|
| 13 |
+
"yfinance>=0.2.54",
|
| 14 |
+
]
|
replit.nix
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{pkgs}: {
|
| 2 |
+
deps = [
|
| 3 |
+
pkgs.glibcLocales
|
| 4 |
+
];
|
| 5 |
+
}
|
requirements.txt.rtf
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{\rtf1\ansi\ansicpg1252\cocoartf2821
|
| 2 |
+
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
|
| 3 |
+
{\colortbl;\red255\green255\blue255;}
|
| 4 |
+
{\*\expandedcolortbl;;}
|
| 5 |
+
\paperw11900\paperh16840\margl1440\margr1440\vieww11520\viewh8400\viewkind0
|
| 6 |
+
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
|
| 7 |
+
|
| 8 |
+
\f0\fs24 \cf0 streamlit\
|
| 9 |
+
pandas\
|
| 10 |
+
numpy\
|
| 11 |
+
plotly\
|
| 12 |
+
yfinance\
|
| 13 |
+
feedparser\
|
| 14 |
+
pytz}
|
utils/indicators.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
import numpy as np
|
| 3 |
+
|
| 4 |
+
def calculate_sma(data, period=20):
|
| 5 |
+
"""Calculate Simple Moving Average."""
|
| 6 |
+
return data.rolling(window=period).mean()
|
| 7 |
+
|
| 8 |
+
def calculate_ema(data, period=20):
|
| 9 |
+
"""Calculate Exponential Moving Average."""
|
| 10 |
+
return data.ewm(span=period, adjust=False).mean()
|
| 11 |
+
|
| 12 |
+
def calculate_rsi(data, period=14):
|
| 13 |
+
"""Calculate Relative Strength Index."""
|
| 14 |
+
delta = data.diff()
|
| 15 |
+
gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
|
| 16 |
+
loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
|
| 17 |
+
rs = gain / loss
|
| 18 |
+
return 100 - (100 / (1 + rs))
|
| 19 |
+
|
| 20 |
+
def calculate_macd(data):
|
| 21 |
+
"""Calculate MACD."""
|
| 22 |
+
exp1 = data.ewm(span=12, adjust=False).mean()
|
| 23 |
+
exp2 = data.ewm(span=26, adjust=False).mean()
|
| 24 |
+
macd = exp1 - exp2
|
| 25 |
+
signal = macd.ewm(span=9, adjust=False).mean()
|
| 26 |
+
hist = macd - signal
|
| 27 |
+
return pd.DataFrame({
|
| 28 |
+
'MACD': macd,
|
| 29 |
+
'Signal': signal,
|
| 30 |
+
'Histogram': hist
|
| 31 |
+
})
|
| 32 |
+
|
| 33 |
+
def calculate_bollinger_bands(data, period=20, num_std=2):
|
| 34 |
+
"""Calculate Bollinger Bands."""
|
| 35 |
+
sma = data.rolling(window=period).mean()
|
| 36 |
+
std = data.rolling(window=period).std()
|
| 37 |
+
upper = sma + (std * num_std)
|
| 38 |
+
lower = sma - (std * num_std)
|
| 39 |
+
return pd.DataFrame({
|
| 40 |
+
'Upper': upper,
|
| 41 |
+
'Middle': sma,
|
| 42 |
+
'Lower': lower
|
| 43 |
+
})
|
| 44 |
+
|
| 45 |
+
def add_indicators(df):
|
| 46 |
+
"""Add all technical indicators to the dataframe."""
|
| 47 |
+
df = df.copy()
|
| 48 |
+
|
| 49 |
+
# Calculate indicators
|
| 50 |
+
df['SMA_20'] = calculate_sma(df['Close'], 20)
|
| 51 |
+
df['EMA_20'] = calculate_ema(df['Close'], 20)
|
| 52 |
+
df['RSI'] = calculate_rsi(df['Close'])
|
| 53 |
+
|
| 54 |
+
# MACD
|
| 55 |
+
macd_data = calculate_macd(df['Close'])
|
| 56 |
+
df['MACD'] = macd_data['MACD']
|
| 57 |
+
df['MACD_Signal'] = macd_data['Signal']
|
| 58 |
+
df['MACD_Hist'] = macd_data['Histogram']
|
| 59 |
+
|
| 60 |
+
# Bollinger Bands
|
| 61 |
+
bbands = calculate_bollinger_bands(df['Close'])
|
| 62 |
+
df['BB_Upper'] = bbands['Upper']
|
| 63 |
+
df['BB_Middle'] = bbands['Middle']
|
| 64 |
+
df['BB_Lower'] = bbands['Lower']
|
| 65 |
+
|
| 66 |
+
return df
|
utils/recommendation_engine.py
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
import numpy as np
|
| 3 |
+
from utils.indicators import add_indicators
|
| 4 |
+
from utils.signals import generate_signals, get_signal_summary
|
| 5 |
+
|
| 6 |
+
def calculate_technical_score(df):
|
| 7 |
+
"""Calculate technical analysis score based on multiple indicators."""
|
| 8 |
+
score = 0
|
| 9 |
+
latest = df.iloc[-1]
|
| 10 |
+
|
| 11 |
+
# RSI Analysis (0-100)
|
| 12 |
+
rsi = latest['RSI']
|
| 13 |
+
if rsi < 30: # Oversold
|
| 14 |
+
score += 20
|
| 15 |
+
elif rsi > 70: # Overbought
|
| 16 |
+
score -= 20
|
| 17 |
+
else: # Neutral
|
| 18 |
+
score += 10
|
| 19 |
+
|
| 20 |
+
# MACD Analysis
|
| 21 |
+
if latest['MACD'] > latest['MACD_Signal']: # Bullish crossover
|
| 22 |
+
score += 20
|
| 23 |
+
elif latest['MACD'] < latest['MACD_Signal']: # Bearish crossover
|
| 24 |
+
score -= 20
|
| 25 |
+
|
| 26 |
+
# Moving Average Analysis
|
| 27 |
+
if latest['Close'] > latest['SMA_20']: # Above MA
|
| 28 |
+
score += 15
|
| 29 |
+
else: # Below MA
|
| 30 |
+
score -= 15
|
| 31 |
+
|
| 32 |
+
# Bollinger Bands Analysis
|
| 33 |
+
if latest['Close'] < latest['BB_Lower']: # Oversold
|
| 34 |
+
score += 15
|
| 35 |
+
elif latest['Close'] > latest['BB_Upper']: # Overbought
|
| 36 |
+
score -= 15
|
| 37 |
+
|
| 38 |
+
# Volume Analysis
|
| 39 |
+
vol_sma = df['Volume'].rolling(window=20).mean().iloc[-1]
|
| 40 |
+
if latest['Volume'] > vol_sma * 1.5: # High volume
|
| 41 |
+
score += 10
|
| 42 |
+
|
| 43 |
+
return max(min(score, 100), -100) # Normalize between -100 and 100
|
| 44 |
+
|
| 45 |
+
def get_recommendation(score):
|
| 46 |
+
"""Convert technical score to recommendation."""
|
| 47 |
+
if score >= 50:
|
| 48 |
+
return 'Strong Buy'
|
| 49 |
+
elif score >= 20:
|
| 50 |
+
return 'Buy'
|
| 51 |
+
elif score <= -50:
|
| 52 |
+
return 'Strong Sell'
|
| 53 |
+
elif score <= -20:
|
| 54 |
+
return 'Sell'
|
| 55 |
+
else:
|
| 56 |
+
return 'Hold'
|
| 57 |
+
|
| 58 |
+
def get_confidence_level(score):
|
| 59 |
+
"""Calculate confidence level based on absolute score."""
|
| 60 |
+
abs_score = abs(score)
|
| 61 |
+
if abs_score >= 70:
|
| 62 |
+
return 'High'
|
| 63 |
+
elif abs_score >= 40:
|
| 64 |
+
return 'Medium'
|
| 65 |
+
else:
|
| 66 |
+
return 'Low'
|
| 67 |
+
|
| 68 |
+
def analyze_stock(symbol, df):
|
| 69 |
+
"""Generate comprehensive stock analysis and recommendation."""
|
| 70 |
+
try:
|
| 71 |
+
# Add technical indicators
|
| 72 |
+
df = add_indicators(df)
|
| 73 |
+
|
| 74 |
+
# Generate signals
|
| 75 |
+
signals = generate_signals(df)
|
| 76 |
+
signal_summary = get_signal_summary(signals)
|
| 77 |
+
|
| 78 |
+
# Calculate technical score
|
| 79 |
+
tech_score = calculate_technical_score(df)
|
| 80 |
+
|
| 81 |
+
# Generate recommendation
|
| 82 |
+
recommendation = get_recommendation(tech_score)
|
| 83 |
+
confidence = get_confidence_level(tech_score)
|
| 84 |
+
|
| 85 |
+
return {
|
| 86 |
+
'symbol': symbol,
|
| 87 |
+
'recommendation': recommendation,
|
| 88 |
+
'technical_score': tech_score,
|
| 89 |
+
'confidence': confidence,
|
| 90 |
+
'signal_summary': signal_summary,
|
| 91 |
+
'last_price': df['Close'].iloc[-1],
|
| 92 |
+
'price_change': ((df['Close'].iloc[-1] / df['Close'].iloc[-2]) - 1) * 100
|
| 93 |
+
}
|
| 94 |
+
except Exception as e:
|
| 95 |
+
return None
|
utils/signals.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
import pandas as pd
|
| 3 |
+
|
| 4 |
+
def generate_signals(df):
|
| 5 |
+
"""Generate trading signals based on technical indicators."""
|
| 6 |
+
signals = pd.DataFrame(index=df.index)
|
| 7 |
+
|
| 8 |
+
# RSI Signals
|
| 9 |
+
signals['RSI_Signal'] = 'Neutral'
|
| 10 |
+
signals.loc[df['RSI'] < 30, 'RSI_Signal'] = 'Oversold'
|
| 11 |
+
signals.loc[df['RSI'] > 70, 'RSI_Signal'] = 'Overbought'
|
| 12 |
+
|
| 13 |
+
# MACD Signals
|
| 14 |
+
signals['MACD_Signal'] = 'Neutral'
|
| 15 |
+
signals.loc[df['MACD'] > df['MACD_Signal'], 'MACD_Signal'] = 'Buy'
|
| 16 |
+
signals.loc[df['MACD'] < df['MACD_Signal'], 'MACD_Signal'] = 'Sell'
|
| 17 |
+
|
| 18 |
+
# Bollinger Bands Signals
|
| 19 |
+
signals['BB_Signal'] = 'Neutral'
|
| 20 |
+
signals.loc[df['Close'] < df['BB_Lower'], 'BB_Signal'] = 'Oversold'
|
| 21 |
+
signals.loc[df['Close'] > df['BB_Upper'], 'BB_Signal'] = 'Overbought'
|
| 22 |
+
|
| 23 |
+
# Moving Average Signals
|
| 24 |
+
signals['MA_Signal'] = 'Neutral'
|
| 25 |
+
signals.loc[df['Close'] > df['SMA_20'], 'MA_Signal'] = 'Bullish'
|
| 26 |
+
signals.loc[df['Close'] < df['SMA_20'], 'MA_Signal'] = 'Bearish'
|
| 27 |
+
|
| 28 |
+
return signals
|
| 29 |
+
|
| 30 |
+
def get_signal_summary(signals):
|
| 31 |
+
"""Generate a summary of current signals."""
|
| 32 |
+
latest_signals = signals.iloc[-1]
|
| 33 |
+
|
| 34 |
+
summary = {
|
| 35 |
+
'RSI': latest_signals['RSI_Signal'],
|
| 36 |
+
'MACD': latest_signals['MACD_Signal'],
|
| 37 |
+
'Bollinger': latest_signals['BB_Signal'],
|
| 38 |
+
'Moving Average': latest_signals['MA_Signal']
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
# Overall sentiment
|
| 42 |
+
bullish_count = sum(1 for signal in summary.values() if signal in ['Buy', 'Bullish', 'Oversold'])
|
| 43 |
+
bearish_count = sum(1 for signal in summary.values() if signal in ['Sell', 'Bearish', 'Overbought'])
|
| 44 |
+
|
| 45 |
+
if bullish_count > bearish_count:
|
| 46 |
+
summary['Overall'] = 'Bullish'
|
| 47 |
+
elif bearish_count > bullish_count:
|
| 48 |
+
summary['Overall'] = 'Bearish'
|
| 49 |
+
else:
|
| 50 |
+
summary['Overall'] = 'Neutral'
|
| 51 |
+
|
| 52 |
+
return summary
|
utils/stock_data.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import yfinance as yf
|
| 2 |
+
import pandas as pd
|
| 3 |
+
from datetime import datetime, timedelta
|
| 4 |
+
|
| 5 |
+
def get_stock_data(symbol, period='1y', interval='1d'):
|
| 6 |
+
"""Fetch stock data from yfinance."""
|
| 7 |
+
try:
|
| 8 |
+
# Add .NS suffix for NSE stocks
|
| 9 |
+
ticker = yf.Ticker(f"{symbol}.NS")
|
| 10 |
+
df = ticker.history(period=period, interval=interval)
|
| 11 |
+
|
| 12 |
+
if df.empty:
|
| 13 |
+
return None, "No data available for this symbol"
|
| 14 |
+
|
| 15 |
+
return df, None
|
| 16 |
+
except Exception as e:
|
| 17 |
+
return None, f"Error fetching data: {str(e)}"
|
| 18 |
+
|
| 19 |
+
def get_company_info(symbol):
|
| 20 |
+
"""Get company information."""
|
| 21 |
+
try:
|
| 22 |
+
ticker = yf.Ticker(f"{symbol}.NS")
|
| 23 |
+
info = ticker.info
|
| 24 |
+
return {
|
| 25 |
+
'name': info.get('longName', symbol),
|
| 26 |
+
'sector': info.get('sector', 'N/A'),
|
| 27 |
+
'industry': info.get('industry', 'N/A'),
|
| 28 |
+
'market_cap': info.get('marketCap', 'N/A'),
|
| 29 |
+
'volume': info.get('volume', 'N/A')
|
| 30 |
+
}
|
| 31 |
+
except:
|
| 32 |
+
return {
|
| 33 |
+
'name': symbol,
|
| 34 |
+
'sector': 'N/A',
|
| 35 |
+
'industry': 'N/A',
|
| 36 |
+
'market_cap': 'N/A',
|
| 37 |
+
'volume': 'N/A'
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
def format_number(number):
|
| 41 |
+
"""Format large numbers to readable format."""
|
| 42 |
+
if not isinstance(number, (int, float)) or pd.isna(number):
|
| 43 |
+
return 'N/A'
|
| 44 |
+
|
| 45 |
+
if number >= 1e9:
|
| 46 |
+
return f'₹{number/1e9:.2f}B'
|
| 47 |
+
elif number >= 1e6:
|
| 48 |
+
return f'₹{number/1e6:.2f}M'
|
| 49 |
+
else:
|
| 50 |
+
return f'₹{number:,.2f}'
|
uv.lock
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|