A hierarchical multi-agent trading system for the National Stock Exchange of India (NSE), replicating the QuantAgents (2025) paper architecture with an Indian market adaptation.
Four specialized AI agents collaborate in a structured meeting loop — news sentiment, simulated trading, portfolio risk, and final decision synthesis — to produce a single, explainable BUY / SELL / HOLD call.
python main.py --symbol RELIANCE.NS --mode quick┌─────────────────────────────────────────────────────────────┐
│ Agent Meeting Loop │
│ │
│ Phase 1 Phase 2 Phase 3 │
│ ┌───────┐ ┌──────┐ ┌──────┐ │
│ │ Emily │ │ Bob │ │ Dave │ │
│ │ 30% │ │ 40% │ │ 30% │ │
│ └───────┘ └──────┘ └──────┘ │
│ │ │ │ │
│ └────────────────►│◄────────────────┘ │
│ ▼ │
│ ┌────────┐ │
│ │ Otto │ Final Decision │
│ └────────┘ BUY / SELL / HOLD │
└─────────────────────────────────────────────────────────────┘
| Agent | Role | Input | Output |
|---|---|---|---|
| Emily | Market News Analyst | MoneyControl, ET, Google News | Sentiment score τ ∈ [-1, 1] |
| Bob | Simulated Trading Analyst | OHLCV + 88 indicators | BUY/SELL/HOLD + Sharpe/WinRate |
| Dave | Risk Control Analyst | Portfolio beta, sector, VIX | R_score ∈ [0, 1], alert flag |
| Otto | Manager Agent | All three reports | Final JSON decision |
# 1. Clone and install dependencies
git clone https://github.com/PreethamSanji/QuantAgents-NSE.git
cd QuantAgents-NSE
pip install -r requirements.txt
# 2. Copy and configure environment
cp config/.env.example .env
# Edit .env with your DhanHQ credentials (optional for paper trading)
# 3. Run analysis (quick mode — ~30 seconds)
python main.py --symbol RELIANCE.NS
# Full mode with sliding-window backtests (~3-5 minutes)
python main.py --symbol TCS.NS --mode full
# Portfolio risk analysis across multiple stocks
python main.py --symbols RELIANCE.NS,HDFCBANK.NS,TCS.NS
# Save decision to JSON
python main.py --symbol RELIANCE.NS --output decision.jsonOptional: Ollama LLM (for richer narratives)
# Install from https://ollama.com and pull the model
ollama pull qwen2.5:7bThe system works fully without Ollama — all agents have rule-based fallbacks.
==============================================================
QUANTAGENTS-NSE — DECISION SUMMARY
==============================================================
Symbol: RELIANCE.NS
Action: BUY
Confidence: 68%
--------------------------------------------------------------
Emily (Sentiment): POSITIVE τ=+0.312 [weight: 30%]
Bob (Technical): BUY conf=72% [weight: 40%]
Dave (Risk): R=0.487 OK [weight: 30%]
--------------------------------------------------------------
Weighted Score: +0.2416 → BUY
--------------------------------------------------------------
Bob's strong BUY signal (72% confidence, Sharpe 1.14)
is the decisive factor. Watch Dave's sector concentration
(100% Energy) if adding to this position.
==============================================================
| Variable | Meaning | Weight |
|---|---|---|
| Portfolio beta vs Nifty 50 | 25% | |
| Liquidity ratio (current vol / avg 20d vol) | 25% | |
| Maximum sector concentration | 25% | |
| Annualized portfolio volatility | 25% |
Alert triggered when
Bob's PPO agent is trained to optimize this dual reward (simulated backtest return + real market return), with
Scrapes headlines from MoneyControl, Economic Times, and Google News RSS. Runs FinBERT (ProsusAI/finbert) for financial sentiment scoring, producing τ ∈ [-1, 1]. Optionally uses Ollama Qwen2.5:7b for a richer macro narrative combining India VIX, Nifty 50 trend, and news sentiment.
Fetches OHLCV data enriched with 88 technical indicators (RSI, MACD, Bollinger, ATR, OBV, VWAP, and more). Runs a FinRL PPO model through Backtrader with 7-day sliding windows, computing the Strategy Analysis Suite: Sharpe Ratio, Max Drawdown, Win Rate, Cumulative Return. Falls back to a multi-indicator rule-based strategy when no model is loaded.
Implements Equation 3 exactly: calculates portfolio beta against ^NSEI, liquidity ratio from recent volume, sector concentration via the Nifty 50 constituent list, and annualized portfolio volatility. Uses PyPortfolioOpt for parametric VaR (falls back to historical percentile). Triggers a Risk Alert Meeting when R_score > 0.75.
Synthesizes all three agents using a weighted voting scheme. Dave's signal is always a risk penalty (-risk_score), acting as a brake on over-confident BUY/SELL calls. If Dave's alert fires, confidence is hard-capped at 60%. Uses Ollama for a 2-sentence synthesis narrative; falls back to rule-based text. Outputs the final paper-specified JSON: {action, symbol, confidence, context}.
QuantAgents-NSE/
├── agents/
│ ├── emily.py # Market News Analyst (news + FinBERT + Ollama)
│ ├── bob.py # Simulated Trading Analyst (FinRL PPO + Backtrader)
│ ├── dave.py # Risk Control Analyst (Equation 3 + PyPortfolioOpt)
│ └── otto.py # Manager Agent (weighted synthesis)
├── tools/
│ ├── scrapers/ # MoneyControl, Economic Times, Google News scrapers
│ ├── indicators/ # 88-indicator pipeline (pandas-ta)
│ └── utils/ # Shared helpers
├── config/
│ ├── config.yaml # All agent weights, thresholds, and settings
│ └── .env.example # API key template
├── scripts/
│ ├── data_collection/ # yfinance historical data fetcher + indicator enrichment
│ └── kaggle_training/ # FinRL PPO training notebook (GPU)
├── data/
│ ├── raw/ # OHLCV parquet files (48 Nifty 50 stocks, 5 years)
│ ├── processed/ # Indicator-enriched data (93 columns)
│ ├── nifty50.csv # Nifty 50 constituents with sectors
│ └── reports/ # Agent JSON reports (auto-saved per run)
├── models/
│ └── ppo_nifty50_final.zip # Trained FinRL PPO model
├── tests/
│ ├── test_dave.py # Unit tests for risk math (no network)
│ ├── test_otto.py # Unit tests for decision synthesis (no network)
│ └── test_integration.py # End-to-end pipeline tests
├── main.py # CLI orchestrator (the meeting loop)
└── requirements.txt
Key settings in config/config.yaml:
agents:
dave:
risk_score_weights:
beta: 0.25 # w1
liquidity: 0.25 # w2
sector_exposure: 0.25 # w3
volatility: 0.25 # w4
alert_threshold: 0.75
otto:
agent_weights:
emily: 0.30
bob: 0.40
dave: 0.30
trading:
mode: paper # paper | live
default_capital: 500000 # INR
rl:
reward_function:
sim_weight: 0.6 # w^sim (Equation 5)
real_weight: 0.4 # w^real (Equation 5)# Unit tests only (no internet, no Ollama required)
pytest tests/test_dave.py tests/test_otto.py -v
# Full test suite (excludes integration)
pytest tests/ -v -m "not integration"
# Integration tests (requires internet + yfinance)
pytest tests/test_integration.py -v -m integrationpython main.py [OPTIONS]
Options:
--symbol TEXT NSE symbol to analyze (default: RELIANCE.NS)
--symbols TEXT Comma-separated symbols for portfolio mode
--mode {quick,full} quick=~30s | full=~3-5min with sliding windows
--skip-emily Skip news sentiment analysis
--skip-bob Skip technical analysis and backtesting
--skip-dave Skip portfolio risk assessment
--output PATH Save final decision JSON to file
--log-level LEVEL DEBUG | INFO | WARNING (default: INFO)
- Python 3.10+
- Internet access (yfinance for market data, scrapers for news)
- Ollama (optional, for LLM narratives) —
ollama pull qwen2.5:7b - DhanHQ API credentials (optional, for live trading — paper mode by default)
See requirements.txt for full dependency list. Core dependencies: pandas-ta, yfinance, backtrader, finrl, stable-baselines3, pypfopt, transformers, loguru.
Historical data for all 48 Nifty 50 stocks (5 years, 2020–2025) is collected via yfinance and enriched with 88 technical indicators using pandas-ta. To refresh:
python scripts/data_collection/fetch_historical_data.py
python scripts/data_collection/enrich_data.pyPPO model training (GPU-intensive) is done on Kaggle. See scripts/kaggle_training/README.md.
QuantAgents: Towards Multi-agent Financial System via Simulated Trading
Xiangyu Li, Yawen Zeng et al., South China University of Technology (2025)
arXiv:2501.04916
This project is an independent NSE adaptation for educational and research purposes. Not financial advice. Paper trading mode is enabled by default.