diff --git a/README.md b/README.md index 2cde146..25d7f9a 100644 --- a/README.md +++ b/README.md @@ -1,62 +1,53 @@
-# 📈 AlphaEdge: AI-Powered CAC40 Portfolio Manager +# 📈 AlphaEdge: AI-Powered Multi-Market Portfolio Manager **Production-Ready Quantitative Trading System with Daily MLOps Pipeline** -Combining Unsupervised Learning, XGBoost & Modern Portfolio Theory for Automated Asset Allocation +Machine-learning driven portfolio allocation for CAC40, with a reusable architecture that can be extended to additional markets. [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/) [![Streamlit App](https://static.streamlit.io/badges/streamlit_badge_black_white.svg)](https://cac40-smart-portfolio-asset.streamlit.app/) +[![MLflow Registry](https://img.shields.io/badge/MLflow-Model%20Registry-0194E2.svg)](https://soradata-alphaedge-registry.hf.space) [![GitHub release (latest by date)](https://img.shields.io/github/v/release/SORADATA/CAC40-Quantitative-Analysis-Predictive-Asset-Allocation?color=orange&label=version)](https://github.com/SORADATA/CAC40-Quantitative-Analysis-Predictive-Asset-Allocation/releases) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Code Style: Black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) -[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/SORADATA/CAC40-Quantitative-Analysis-Predictive-Asset-Allocation/graphs/commit-activity) -![Daily Pipeline](https://github.com/SORADATA/CAC40-Quantitative-Analysis-Predictive-Asset-Allocation/actions/workflows/daily_run.yml/badge.svg) -[🌐 **Live Dashboard**](https://cac40-smart-portfolio-asset.streamlit.app/) • [📊 **View Results**](#-performance-metrics) • [🚀 **Quick Start**](#-quick-start) • [🐛 **Report Issue**](https://github.com/SORADATA/CAC40-Quantitative-Analysis-Predictive-Asset-Allocation/issues) +[🌐 **Live Dashboard**](https://cac40-smart-portfolio-asset.streamlit.app/) • [📊 **Performance**](#-performance-metrics) • [🏗️ **Architecture**](#️-system-architecture) • [🚀 **Quick Start**](#-quick-start) • [🐛 **Issues**](https://github.com/SORADATA/CAC40-Quantitative-Analysis-Predictive-Asset-Allocation/issues)
--- -## 🎯 Why AlphaEdge? +## 🎯 Overview -Traditional portfolio management relies on static allocations and reactive rebalancing. **AlphaEdge** flips this paradigm by implementing a **fully automated, AI-driven investment strategy** that: +AlphaEdge is a quantitative portfolio management project that combines feature engineering, ensemble machine learning, portfolio optimization, and a Streamlit dashboard in a single codebase. -- 🔄 **Rebalances daily** based on market regime detection and predictive signals -- 🤖 **Requires zero manual intervention** through GitHub Actions automation -- 📈 **Adapts to market conditions** using unsupervised learning for regime classification -- ⚡ **Responds to signals in real-time** with optimized portfolio weights -- 🎓 **Built on academic rigor** from quantitative finance research - -> **Perfect for:** Quantitative researchers, algo traders, data scientists, and finance students looking to deploy production-grade ML strategies. +The current repository is organized around a **CAC40 production setup**, while keeping reusable modules for extension to other universes and market configurations. --- -## 🌟 Key Features +## 🌟 Core Features -### 🧠 Hybrid AI Architecture -- **Market Regime Detection:** K-Means clustering identifies bullish, bearish, and neutral market states -- **Directional Forecasting:** XGBoost predicts next-day returns with probability scores -- **Ensemble Strategy:** Combines both models for robust signal generation +### 🧠 Machine Learning Engine +- Ensemble modeling with **XGBoost, LightGBM, Ridge, and Logistic Regression stacking** +- Market regime detection using **K-Means** on technical features +- Walk-forward validation to evaluate temporal robustness before promotion -### ⚖️ Advanced Portfolio Optimization -- **Markowitz Mean-Variance Framework** with Ledoit-Wolf covariance shrinkage -- **Dynamic risk constraints** adjusted by market volatility -- **Transaction cost modeling** to minimize portfolio turnover +### ⚖️ Portfolio Construction +- Mean-variance optimization with **PyPortfolioOpt** +- Ledoit-Wolf covariance shrinkage for more stable risk estimates +- Monthly rebalancing with transaction cost handling and fallback allocation logic -### ☁️ Production-Grade MLOps -- **Automated daily ETL** via GitHub Actions (no servers needed) -- **Version-controlled models** with reproducible training pipeline -- **Monitoring & alerting** through Streamlit dashboard -- **Scalable architecture** ready for multi-asset expansion +### ☁️ MLOps Workflow +- MLflow-based registry / promotion workflow for model tracking +- Local model fallback with `ensemble_model.pkl` and `model_card.json` +- Automated workflows under `.github/workflows/` for training, releases, and updates -### 📊 Interactive Analytics -- Real-time performance tracking vs CAC40 benchmark -- Signal visualization with confidence intervals -- Drawdown analysis and risk metrics -- Portfolio composition timeline +### 📊 Visualization +- Streamlit dashboard for performance monitoring and signal inspection +- Dashboard screenshots already included in `images/` +- Changelog and contribution files maintained at repository root --- @@ -64,64 +55,43 @@ Traditional portfolio management relies on static allocations and reactive rebal
-| **Portfolio Performance** | **AI Trading Signals** | +| Portfolio Performance | AI Trading Signals | |:---:|:---:| | ![Dashboard Overview](images/Dashboard.png) | ![Trading Signals](images/Signal.png) | -*Live tracking of cumulative returns, Sharpe ratio, and maximum drawdown (left). Daily probabilistic forecasts with market regime indicators (right).* -
--- -## 📊 Performance Metrics (Live & Backtest) - -Data updated as of: **2026-02-05** -| Metric | AlphaEdge Strategy 🤖 | CAC40 Benchmark 🇫🇷 | -| :--- | :---: | :---: | -| **Total Return** | **+121.9%** 🚀 | +87.9% | -| **Alpha (vs Bench)** | **+34.0%** | N/A | -| **YTD Performance** | **+9.5%** | TBD | -| **Sharpe Ratio** | **0.63** | N/A | -| **Max Drawdown** | **-32.0%** | TBD | +## 📊 Performance Metrics -> **Note:** The strategy has shown significant outperformance in the recent period (2024-2026), successfully identifying market regime shifts. +The dashboard section can display strategy return, benchmark comparison, drawdown, and signal information. -*Metrics updated daily. View real-time performance on the [live dashboard](https://cac40-smart-portfolio-asset.streamlit.app/).* +If you want this README to stay strictly accurate over time, update the numeric metrics directly from the latest dashboard or backtest output before each release. --- ## 🏗️ System Architecture -The entire pipeline runs autonomously with zero maintenance required. - ```mermaid graph TB - A[🌐 Yahoo Finance API] -->|Daily at Market Close| B[Data Ingestion] + A[Market Data] --> B[ETL Pipeline] B --> C[Feature Engineering] - C --> D{AI Model Ensemble} - D -->|Regime Detection| E[K-Means Clustering] - D -->|Return Prediction| F[XGBoost Classifier] - E & F --> G[Signal Aggregation] - G --> H[Portfolio Optimization] - H -->|Markowitz + Constraints| I[Weight Allocation] - I --> J[📁 Export Results] - J --> K[📊 Streamlit Dashboard] - J --> L[📈 Backtest Analysis] - - style A fill:#e1f5ff - style D fill:#fff4e1 - style H fill:#ffe1f5 - style K fill:#e1ffe1 + C --> D[AlphaEdge Ensemble] + D --> E[Backtest & Signal Engine] + E --> F[Portfolio Optimization] + F --> G[Artifacts / Model Cards / Signals] + G --> H[Streamlit Dashboard] + D -.-> I[MLflow Registry] ``` -### Pipeline Components +### Main Components -1. **Data Layer:** Real-time market data from Yahoo Finance API -2. **Feature Store:** Technical indicators (RSI, MACD, Bollinger Bands) + macro factors -3. **ML Models:** Pre-trained and versioned in `/src/models/` -4. **Optimization Engine:** PyPortfolioOpt with custom risk models -5. **Deployment:** GitHub Actions + Streamlit Cloud (serverless) +1. **Extraction layer**: market data loading and preprocessing +2. **Feature layer**: momentum, volatility, risk-adjusted, and technical features +3. **Model layer**: ensemble training, cross-validation, model loading, and promotion logic +4. **Pipeline layer**: ETL, backtest, and daily execution utilities +5. **Presentation layer**: Streamlit app for monitoring results --- @@ -129,212 +99,181 @@ graph TB ### Prerequisites -- Python 3.10 or higher -- Git installed -- (Optional) Virtual environment tool +- Python 3.10+ +- Git +- Recommended: virtual environment +- Optional: `HF_TOKEN` for remote sync / registry integration ### Installation ```bash -# Clone the repository git clone https://github.com/SORADATA/CAC40-Quantitative-Analysis-Predictive-Asset-Allocation.git cd CAC40-Quantitative-Analysis-Predictive-Asset-Allocation - -# Create virtual environment (recommended) python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate - -# Install dependencies pip install -r requirements.txt ``` -### Running Locally +### Run the dashboard -**Option 1: Launch Dashboard** ```bash streamlit run app.py ``` -Opens interactive dashboard at `http://localhost:8501` -**Option 2: Run Pipeline Manually** +### Run the daily pipeline + ```bash -python daily_run.py +python src/pipeline/daily_run.py ``` -Executes full ETL, prediction, and optimization cycle -**Option 3: Explore Notebooks** +### Train the model + ```bash -jupyter notebook notebooks/ +python src/models/train.py ``` -Access research notebooks for model training and backtesting --- ## 📂 Project Structure -``` -CAC40-Quantitative-Analysis-Predictive-Asset-Allocation/ -├── .github/ -│ └── workflows/ -│ └── daily_pipeline.yml # Automated daily execution -├── data/ -│ ├── raw/ # Historical price data -│ ├── processed/ # Feature-engineered datasets -│ └── results/ # Portfolio weights & signals -├── images/ # Screenshots & visualizations -├── notebooks/ -│ ├── 01_EDA.ipynb # Exploratory data analysis -│ ├── 02_Model_Training.ipynb # ML model development -│ └── 03_Backtesting.ipynb # Strategy validation -├── src/ -│ ├── models/ -│ │ ├── xgboost_model.pkl # Trained predictor -│ │ └── kmeans_model.pkl # Regime classifier -│ ├── utils/ -│ │ ├── data_loader.py # ETL functions -│ │ ├── feature_engineering.py # Indicator calculations -│ │ ├── optimization.py # Portfolio allocation -│ │ └── evaluation.py # Performance metrics -│ └── config.py # Centralized configuration -│ ├── pipeline/ -│ │ ├── backtest.py -│ │ └── etl.py -├── app.py # Streamlit dashboard -├── daily_run.py # Main pipeline orchestrator -├── const.py # Constants variables -├── requirements.txt # Python dependencies -├── LICENSE # MIT License -└── README.md # You are here! +```text +. +├── .github +│ └── workflows +│ ├── daily_update.yml +│ ├── ml_pipeline.yml +│ ├── pre-release.yml +│ ├── python-app.yml +│ └── release.yml +├── CHANGELOG.md +├── CONTRIBUTING.md +├── README.md +├── app.py +├── config +│ └── markets +│ └── cac40.json +├── const.py +├── debug_run.txt +├── dev.sh +├── images +│ ├── Dashboard.png +│ └── Signal.png +├── notebooks +│ └── 01_EDA.ipynb +├── requirements.txt +├── src +│ ├── extract +│ │ ├── extractor.py +│ │ └── yfinance_downloader_test.py +│ ├── features +│ │ └── alpha_features.py +│ ├── models +│ │ ├── CAC40 +│ │ │ ├── ensemble_model.pkl +│ │ │ └── model_card.json +│ │ ├── US_TECH +│ │ │ ├── ensemble_model.pkl +│ │ │ └── model_card.json +│ │ ├── __init__.py +│ │ ├── cv.py +│ │ ├── ensemble.py +│ │ ├── ensemble_model.pkl +│ │ ├── model_card.json +│ │ ├── model_loader.py +│ │ └── train.py +│ ├── pipeline +│ │ ├── backtest.py +│ │ ├── daily_run.py +│ │ └── etl.py +│ ├── transform +│ │ ├── processor.py +│ │ └── ticker_manager.py +│ └── utils +│ ├── config_loader.py +│ ├── feature_utils.py +│ ├── logger.py +│ ├── market_utils.py +│ ├── math_utils.py +│ └── metrics.py +└── tests + ├── get_composition.py + ├── plot_results.py + └── test_pipeline.py ``` --- -## 🔧 Customization Guide - -### Adapting to Other Markets +## 🔧 Customization -Want to apply this strategy to S&P 500, FTSE 100, or cryptocurrencies? +### Add a new market -1. **Fork this repository** (click the Fork button above) +Create a new JSON file in `config/markets/`, for example: -2. **Modify the ticker list** in `src/config.py`: -```python -# Example: Switch to S&P 500 -TICKERS = ['AAPL', 'MSFT', 'GOOGL', 'AMZN', 'NVDA', ...] -BENCHMARK = '^GSPC' # S&P 500 index +```json +{ + "market_name": "SP500", + "tickers": ["AAPL", "MSFT", "GOOGL", "AMZN", "NVDA"], + "benchmark_ticker": "^GSPC" +} ``` -3. **Retrain models** (optional but recommended): -```bash -python notebooks/02_Model_Training.ipynb -``` - -4. **Push changes** and the automated pipeline handles the rest! +Then adapt the training and pipeline entry points so the new configuration is discovered and processed consistently. -### Tuning Parameters +### Useful parameters -Key configuration options in `src/config.py`: - -| Parameter | Description | Default | -|-----------|-------------|---------| -| `LOOKBACK_PERIOD` | Historical window for features | 252 days | -| `N_CLUSTERS` | Market regimes for K-Means | 3 | -| `RISK_AVERSION` | Portfolio risk tolerance | 2.5 | -| `MAX_WEIGHT` | Position size limit per asset | 0.15 | -| `REBALANCE_THRESHOLD` | Trigger for portfolio adjustment | 5% | +| Parameter | Role | +|---|---| +| `SHARPE_THRESHOLD` | Promotion safety threshold | +| `MAX_DD_THRESHOLD` | Max drawdown safety filter | +| `PROBA_MIN` | Minimum prediction probability for selection | +| `MAX_STOCKS_SELECT` | Maximum number of selected assets | +| `MIN_STOCKS_OPTIM` | Minimum assets required for optimizer | +| `TRANSACTION_COST` | Cost applied at rebalance | +| `BACKTEST_YEARS` | Lookback window used in backtesting | --- -## 📚 Technical Deep Dive +## 📚 Technical Notes ### Feature Engineering -The model uses 50+ features across multiple categories: +The project computes momentum, mean-reversion, volatility, technical, and risk-adjusted features inside `src/features/alpha_features.py`. -- **Price-based:** Returns (1d, 5d, 20d), log-returns, price ratios -- **Technical Indicators:** RSI, MACD, Bollinger Bands, ATR, Stochastic Oscillator -- **Volume Metrics:** OBV, Volume MA ratios, VWAP -- **Volatility Measures:** Historical vol, Parkinson estimator, Garman-Klass -- **Market Microstructure:** Bid-ask spread proxies, Amihud illiquidity +This layer is central because it transforms raw price history into the model inputs used for ranking and allocation. -### Model Training +### Training Stack -**XGBoost Classifier:** -- Binary classification (up/down next day) -- Custom weighted loss function (asymmetric) -- 5-fold time-series cross-validation -- Hyperparameter tuning via Optuna +The training logic lives in `src/models/train.py`, while the ensemble definition is implemented in `src/models/ensemble.py`. -**K-Means Clustering:** -- Applied to 10 macro features (volatility, momentum, correlation) -- Elbow method + Silhouette score for optimal K -- Regime labels: Bull (0), Neutral (1), Bear (2) +Model loading and champion selection behavior are handled through `src/models/model_loader.py` plus local fallback artifacts. -### Portfolio Optimization +### Backtesting -Implements **Markowitz Mean-Variance Optimization** with: -- Expected returns via **exponentially weighted moving average** (EWMA) -- Covariance matrix via **Ledoit-Wolf shrinkage** (addresses estimation error) -- Constraints: Long-only, box constraints, sector limits -- Objective: Maximize Sharpe ratio with L2 regularization +The simulation and rebalance logic are implemented in `src/pipeline/backtest.py`. ---- +This is where signal generation, allocation logic, and portfolio performance evaluation come together. +--- ## 🤝 Contributing -Contributions are welcome! Here's how you can help: - -1. **Report bugs** via [GitHub Issues](https://github.com/SORADATA/CAC40-Quantitative-Analysis-Predictive-Asset-Allocation/issues) -2. **Suggest features** in the Discussions tab -3. **Submit pull requests** following the code style guidelines +Contributions are welcome through issues, discussions, and pull requests. -### Development Setup +Before opening a PR, run formatting, linting, and tests locally where applicable. ```bash -# Install development dependencies -pip install -r requirements-dev.txt - -# Run linting black src/ --check flake8 src/ - -# Run tests pytest tests/ ``` ---- - -## 📖 Research & References - -This project builds upon: - -- Markowitz, H. (1952). "Portfolio Selection". *Journal of Finance* -- Friedman, J. et al. (2001). "Greedy Function Approximation: A Gradient Boosting Machine" -- Ledoit, O. & Wolf, M. (2004). "Honey, I Shrunk the Sample Covariance Matrix" -- Bailey, D. et al. (2017). "Stock Portfolio Design and Backtest Overfitting". *Journal of Investment Management* - - --- ## ⚠️ Disclaimer -**This project is for educational and research purposes only.** +This repository is for **educational and research purposes only**. -- ❌ Not financial advice or investment recommendations -- ❌ No guarantee of profitability or performance -- ❌ Past results do not predict future outcomes -- ⚠️ Algorithmic trading involves substantial risk of capital loss - -Always consult with a licensed financial advisor before making investment decisions. - ---- - -## 📜 License - -This project is licensed under the **MIT License** - see the [LICENSE](LICENSE) file for details. - -You are free to use, modify, and distribute this code with attribution. +It does not constitute financial advice, and past performance does not guarantee future results. --- @@ -342,29 +281,12 @@ You are free to use, modify, and distribute this code with attribution. Developed as part of the **Master 2 - Statistics Expertise for Finance & Economics** program at **Université de Lorraine**. -Special thanks to: -- Professor [Name] for guidance on quantitative methods -- The open-source community for libraries (Streamlit, scikit-learn, PyPortfolioOpt) -- CAC40 companies for providing publicly available data +Thanks to the open-source ecosystem around Streamlit, scikit-learn, XGBoost, LightGBM, PyPortfolioOpt, and MLflow. ---
-### 💡 Found this useful? - -⭐ **Star this repo** to show support! - -🔀 **Fork it** to build your own strategy! - -📢 **Share it** with fellow quants and developers! - ---- - **Developed by [SORADATA](https://github.com/SORADATA)** - -[![GitHub followers](https://img.shields.io/github/followers/SORADATA?style=social)](https://github.com/SORADATA) -[![Twitter Follow](https://img.shields.io/twitter/follow/SORADATA?style=social)](https://twitter.com/SORADATA) -
diff --git a/app.py b/app.py index 9ec9e3f..174f908 100644 --- a/app.py +++ b/app.py @@ -1,22 +1,21 @@ -import streamlit as st +import os +import json +import time +import numpy as np import pandas as pd +import streamlit as st import plotly.express as px import plotly.graph_objects as go -from plotly.subplots import make_subplots -from datetime import datetime, timedelta from pathlib import Path -import numpy as np -import json -import yfinance as yf +from datetime import datetime, timedelta +from plotly.subplots import make_subplots from streamlit_autorefresh import st_autorefresh -import time -import os +import yfinance as yf import mlflow from mlflow.tracking import MlflowClient from mlflow.exceptions import MlflowException - # ============================================================================= # CONFIGURATION & STYLE # ============================================================================= @@ -38,8 +37,39 @@ os.environ["MLFLOW_TRACKING_USERNAME"] = "SORADATA" os.environ["MLFLOW_TRACKING_PASSWORD"] = HF_TOKEN mlflow.set_tracking_uri(MLFLOW_TRACKING_URI) + MODEL_DIR = BASE_DIR / "models" -MARKET_OPTIONS = ["CAC40", "BRVM"] + +@st.cache_data(ttl=1800, show_spinner=False) +def _discover_markets(): + """ + Decouvre dynamiquement les marches disponibles en interrogeant le repo + Hugging Face distant (dataset HF_REPO_ID), sous le prefixe data//. + Fallback sur un scan local (data/processed) si l'API HF echoue, puis sur + une liste par defaut en dernier recours. + """ + try: + from huggingface_hub import HfApi + api = HfApi() + files = api.list_repo_files(repo_id=HF_REPO_ID, repo_type="dataset", token=HF_TOKEN) + markets = sorted({ + f.split("/")[1] for f in files + if f.startswith("data/") and len(f.split("/")) > 2 + }) + if markets: + return markets + except Exception: + pass + + local_dir = BASE_DIR / "data" / "processed" + if local_dir.exists(): + found = sorted([p.name for p in local_dir.iterdir() if p.is_dir()]) + if found: + return found + + return ["CAC40", "BRVM"] + +MARKET_OPTIONS = _discover_markets() st.markdown("""