Skip to content
Open
26 changes: 25 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,37 @@ SKOPAQ_SUPABASE_SERVICE_KEY=eyJ...
SKOPAQ_UPSTASH_REDIS_URL=https://your-redis.upstash.io
SKOPAQ_UPSTASH_REDIS_TOKEN=AX...

# ===== Broker Selection =====
# indstocks = INDstocks, kite = Kite Connect (Zerodha)
SKOPAQ_BROKER=indstocks

# ===== INDstocks Broker =====
SKOPAQ_INDSTOCKS_TOKEN=
SKOPAQ_INDSTOCKS_BASE_URL=https://api.indstocks.com

# ===== Kite Connect (Zerodha) Broker =====
SKOPAQ_KITE_API_KEY=
SKOPAQ_KITE_API_SECRET=
SKOPAQ_KITE_ACCESS_TOKEN=

# ===== Angel One SmartAPI (free real-time market data) =====
# Free account at angelone.com, API key at smartapi.angelbroking.com
SKOPAQ_ANGELONE_API_KEY=
SKOPAQ_ANGELONE_CLIENT_ID=
SKOPAQ_ANGELONE_PASSWORD=
SKOPAQ_ANGELONE_TOTP_SECRET=

# ===== Upstox API (free real-time market data) =====
# Free account at upstox.com, app at upstox.com/developer/apps
SKOPAQ_UPSTOX_API_KEY=
SKOPAQ_UPSTOX_API_SECRET=
SKOPAQ_UPSTOX_ACCESS_TOKEN=

# ===== Trading Mode =====
# paper = simulated trades, live = real money via INDstocks
# paper = simulated trades, live = real money via configured broker
SKOPAQ_TRADING_MODE=paper
# CNC = delivery (hold overnight), MIS = intraday (squared off by 3:15 PM)
SKOPAQ_DEFAULT_PRODUCT=CNC

# ===== Asset Class =====
# equity = Indian equities (NSE/BSE), crypto = Binance Spot
Expand Down
59 changes: 52 additions & 7 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This file provides context for AI coding agents working on the SkopaqTrader code

## Project Overview

AI algorithmic trading platform for Indian equities. Built on vendored [TradingAgents v0.2.0](https://github.com/TauricResearch/TradingAgents) (Apache 2.0) with a custom `skopaq/` layer for INDstocks broker integration, multi-model LLM tiering, and an autonomous execution pipeline.
AI algorithmic trading platform for Indian equities. Built on vendored [TradingAgents v0.2.0](https://github.com/TauricResearch/TradingAgents) (Apache 2.0) with a custom `skopaq/` layer for multi-broker integration (INDstocks + Kite Connect), multi-model LLM tiering, and an autonomous execution pipeline.

## Architecture

Expand All @@ -17,8 +17,8 @@ Two codebases in one repo:

```
CLI/API → SkopaqTradingGraph → [upstream LangGraph agents] → TradeSignal
→ SafetyChecker → PositionSizer → OrderRouter → INDstocks/Paper
→ PositionMonitor → SellAnalyst → exit
→ SafetyChecker → PositionSizer → OrderRouter → Broker(INDstocks|Kite)/Paper
→ PositionMonitor(MarketDataProvider) → SellAnalyst → exit
```

### Daemon Flow (autonomous)
Expand All @@ -44,11 +44,21 @@ python3 -m pytest tests/integration/ -v -m integration
# CLI commands
skopaq status # Health check
skopaq analyze RELIANCE # Analysis only
skopaq trade RELIANCE # Analysis + execution (paper default)
skopaq scan # Scanner cycle
skopaq trade RELIANCE # Trade specific symbol (full lifecycle)
skopaq trade # Auto-scan → trade best pick → monitor → close
skopaq trade --top 3 # Auto-scan → trade top 3 → monitor → close
skopaq trade --no-monitor # Trade without position monitoring
skopaq scan # Scanner cycle (no execution)
skopaq daemon --once --paper # Full autonomous session
skopaq monitor # Monitor existing positions
skopaq serve # FastAPI server

# Kite Connect (Zerodha) broker
skopaq kite login-url # Print OAuth login URL
skopaq kite session <tok> # Exchange request_token for access_token
skopaq kite set-token <tok># Store access_token directly
skopaq kite status # Check Kite token health
skopaq kite clear # Delete stored Kite token
```

## Configuration
Expand All @@ -73,6 +83,10 @@ skopaq serve # FastAPI server

**Critical:** Gemini 3 returns `response.content` as a list of dicts, not a string. Always use `skopaq.llm.extract_text()` to normalize.

## Broker Selection

Set `SKOPAQ_BROKER=indstocks` (default) or `SKOPAQ_BROKER=kite` to choose the broker. The `OrderRouter` dispatches to either client via a `BrokerClient` protocol. Paper mode works without any broker credentials — the `MarketDataProvider` falls back to yfinance.

## INDstocks API

- ALL market data endpoints use `scrip-codes=NSE_2885` format (NOT `symbols=NSE:RELIANCE`)
Expand All @@ -82,13 +96,40 @@ skopaq serve # FastAPI server
- Quote fields: `live_price`, `day_open`, `day_high`, `day_low`, `prev_close`
- Always refer to `docs/indstocks_api.md` for endpoint reference — do not assume

## Kite Connect API

- Auth header: `Authorization: token api_key:access_token`
- Quote endpoint: `GET /quote?i=NSE:RELIANCE` (instrument key format `EXCHANGE:SYMBOL`)
- Orders: `POST /orders/{variety}` where variety = `regular`, `amo`, `co`, `iceberg`
- Product types: `CNC` (delivery), `MIS` (intraday), `NRML` (F&O)
- Positions: `GET /portfolio/positions` returns `{"net": [...], "day": [...]}`
- Historical: `GET /instruments/historical/{token}/{interval}` with datetime strings
- Instruments: `GET /instruments/NSE` returns CSV with `instrument_token`, `tradingsymbol`
- Token lifecycle: OAuth2 flow → `access_token` valid until ~6:00 AM IST next day
- CLI: `skopaq kite login-url`, `skopaq kite session <request_token>`, `skopaq kite status`

## MarketDataProvider

`skopaq/broker/market_data.py` — unified async market data layer used by paper engine and position monitor. Tries sources in priority order:

1. **Broker API** (INDstocks or Kite) — best data, real bid/ask
2. **Angel One SmartAPI** (free, real-time) — real bid/ask, 5-level depth
3. **Upstox API** (free, real-time) — real bid/ask, backup source
4. **yfinance** (no credentials) — free fallback, delayed, synthetic bid/ask
5. **Binance public API** — for crypto (no auth needed)
6. **Stale cache** — last resort, returns last known quote

Angel One and Upstox auto-initialize on first use if credentials are configured. No code changes needed — just set env vars.

Paper mode auto-refreshes quotes before every fill via `PaperEngine.execute_order_async()`.

## File Organization

```
skopaq/
├── agents/ # Sell analyst (AI exit decisions)
├── api/ # FastAPI backend
├── broker/ # INDstocks REST/WS + Binance + paper engine
├── broker/ # INDstocks + Kite Connect + Binance + paper engine + market data provider
├── cli/ # Typer CLI (main.py = all commands, display.py = Rich output)
├── db/ # Supabase client + repositories
├── execution/ # Executor, safety checker, order router, daemon, position monitor
Expand All @@ -112,7 +153,8 @@ skopaq/
## Key Conventions

1. **Safety rules are immutable** — `SafetyRules` in `constants.py` cannot be overridden at runtime. The `SafetyChecker` enforces them before every order.
2. **Paper mode is default** — All CLI commands default to paper trading. Live mode requires explicit `--live` or `SKOPAQ_TRADING_MODE=live` + confirmation prompt.
2. **Paper mode is default** — All CLI commands default to paper trading. Paper mode works without broker credentials (yfinance fallback). Live mode requires explicit `--live` or `SKOPAQ_TRADING_MODE=live` + confirmation prompt.
7. **MarketDataProvider for paper mode** — The `PaperEngine` uses `MarketDataProvider` to auto-refresh quotes before fills. Use `execute_order_async()` (not `execute_order()`) when a provider is attached. The `PositionMonitor` uses `MarketDataProvider` for LTP polling (not a broker client directly).
3. **Upstream modifications are minimal** — Changes to `tradingagents/` must be documented in `UPSTREAM_CHANGES.md` with backward-compatibility notes.
4. **No secrets in code** — All credentials come from environment variables. Never commit `.env`, token files, or API keys.
5. **Pydantic v2 models** — Broker models in `skopaq/broker/models.py` use Pydantic v2. Use attribute access (`model.field`), not dict access (`model["field"]` or `model.get("field")`).
Expand All @@ -125,6 +167,9 @@ skopaq/
- **yfinance suffixes**: LLM agents generate `RELIANCE.NS` (Yahoo Finance convention). The routing layer adds/strips suffixes automatically, but new data flows must handle this.
- **Local imports in daemon.py**: Many imports are inside method bodies to avoid circular imports. This affects mock patch targets in tests (see Testing Patterns above).
- **Stop event propagation**: The daemon's `stop_event` must be checked before every major operation, not just inside delay waits.
- **Broker client type**: `OrderRouter` uses a `BrokerClient` protocol — both `INDstocksClient` and `KiteConnectClient` satisfy it. Don't use `isinstance` checks; use `config.broker` to dispatch.
- **Kite token expiry**: Kite tokens expire at ~6:00 AM IST daily (not rolling 24h like INDstocks). The `KiteTokenManager` calculates expiry to next 6 AM.
- **PositionMonitor no longer takes a broker client** — it takes a `MarketDataProvider` instead. The old `client` parameter is ignored (backward compat).

## Deployment

Expand Down
47 changes: 36 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ SkopaqTrader extends the [TradingAgents](https://github.com/TauricResearch/Tradi
- **Multi-model tiering** — Per-role LLM assignment across multiple providers for cost optimization and capability matching. See the [model tiering table](#multi-model-tiering) below for details.
- **Semantic LLM Caching** — Built-in Redis LangCache provides significant speedup (up to ~45x in our benchmarks) on repeated queries and reduces API costs, with automatic semantic invalidation on memory updates.
- **Advanced Risk Management** — Features ATR-based position sizing, India VIX/NIFTY SMA market regime detection, NSE event calendar handling (F&O expiry, RBI policy), and sector concentration limits.
- **Live Algo Trading** — Integrates with the INDstocks broker API for execution on Indian equities (NSE/BSE). Start in paper mode, graduate to live when ready.
- **Live Algo Trading** — Integrates with INDstocks and Kite Connect (Zerodha) broker APIs for execution on Indian equities (NSE/BSE). Start in paper mode, graduate to live when ready.
- **Live-Data Paper Trading** — Paper mode uses real market data from any source (broker API, yfinance, Binance public) with automatic fallback. No broker credentials required to paper trade.
- **Confidence-Scored Position Sizing** — The Risk Manager evaluates trades with strict confidence scores (50-100%). Position sizes are dynamically scaled based on this AI confidence level.
- **Parallel Scanner Engine** — 30-second multi-model screening cycle on the NIFTY 50 watchlist, wired directly to INDstocks batch quotes and 3 LLM screeners (Gemini, Grok, Perplexity) running concurrently.
- **Safety-First Execution** — Immutable position limits, persistent drawdown tracking, daily loss circuit breakers, and small-account exemptions.
Expand Down Expand Up @@ -87,7 +88,7 @@ graph TD
end

subgraph Infra["Infrastructure"]
INDstocks["INDstocks Broker<br/>NSE / BSE Trading"]:::external
Broker["INDstocks / Kite Connect<br/>NSE / BSE Trading"]:::external
Supabase["Supabase DB<br/>State, History, Auth"]:::external
Redis["Redis LangCache<br/>Semantic LLM Caching"]:::external
end
Expand All @@ -101,14 +102,14 @@ graph TD
RiskAgent -- "Confidence %" --> TraderAgent
TraderAgent --> Safety
Safety --> Router
Router --> INDstocks
Router --> Broker
Orchestrator -.-> Supabase
Orchestrator -.-> Redis
Router -. "Trade Result" .-> Orchestrator
Orchestrator -. "Reflection" .-> DataAgents
```

*High-level overview of the SkopaqTrader architecture, connecting the user interfaces to the multi-agent AI team and the INDstocks execution engine.*
*High-level overview of the SkopaqTrader architecture, connecting the user interfaces to the multi-agent AI team and the broker execution engine.*

### 🤖 AI Agent Workflow

Expand All @@ -124,7 +125,7 @@ sequenceDiagram
participant Research as Researchers
participant Risk as Risk Manager
participant Trader as Trader Agent
participant Broker as INDstocks Broker
participant Broker as Broker (INDstocks / Kite)

User->>Orch: Request Analysis (e.g. RELIANCE)
Orch->>Analysts: Gather Market, News, Social Data
Expand Down Expand Up @@ -160,7 +161,7 @@ flowchart LR
S2["2. AI Team Analyzes<br/>News, Trends, Fundamentals"]:::step
S3["3. AI Debate and Decision<br/>Bull vs Bear Arguments"]:::step
S4["4. Risk and Confidence Check<br/>Score validates position size"]:::step
S5["5. Execute Trade<br/>Paper or Live via INDstocks"]:::highlight
S5["5. Execute Trade<br/>Paper or Live via Broker"]:::highlight
S6["6. Reflect and Learn<br/>Lessons feed future trades"]:::step

S1 --> S2 --> S3 --> S4 --> S5 -.-> S6
Expand All @@ -186,7 +187,7 @@ flowchart TD
classDef memory fill:#475569,stroke:#334155,color:#fff

Start(("skopaq scan<br/>NIFTY 50")):::trigger
INDapi["INDstocks API Batch Quote"]:::data
INDapi["Broker API Batch Quote<br/>(INDstocks / Kite / yfinance)"]:::data
CacheCheck{"Redis LangCache<br/>Semantic Check"}:::check
CachedData["Return Cached Inference"]:::llm

Expand Down Expand Up @@ -247,6 +248,7 @@ SkopaqTrader includes comprehensive blockchain infrastructure for crypto trading

| Feature | Module | Description |
|---------|--------|-------------|
| **Kite Connect** | `skopaq/broker/kite_client.py` | Zerodha Kite Connect REST API v3 for NSE/BSE trading |
| **Live Trading** | `skopaq/broker/binance_auth.py` | Authenticated Binance API for spot trading with API keys |
| **Real-Time Feeds** | `skopaq/broker/binance_ws.py` | WebSocket streams for ticker, trades, order book, klines |
| **Gas Oracle** | `skopaq/blockchain/gas.py` | ETH, Polygon, Arbitrum, Optimism gas prices + tx cost estimates |
Expand Down Expand Up @@ -333,10 +335,16 @@ skopaq status
skopaq analyze RELIANCE
skopaq analyze TATAMOTORS --date 2026-02-28

# Analyze + execute (paper mode by default)
# Trade a specific stock (full lifecycle: analyze + trade + monitor + close)
skopaq trade RELIANCE

# Run scanner cycle
# Auto-discover and trade (scan NIFTY 50 → pick best → trade → monitor)
skopaq trade # Best single pick
skopaq trade --top 3 # Trade top 3 candidates
skopaq trade --watchlist "RELIANCE,TCS,INFY" # Scan only these symbols
skopaq trade --no-monitor # Skip position monitoring

# Run scanner cycle (no execution)
skopaq scan --max-candidates 5

# Autonomous daemon (full session: scan → trade → monitor → close)
Expand All @@ -354,8 +362,24 @@ skopaq serve --port 8000
# Token management (INDstocks broker)
skopaq token set <your-token>
skopaq token status

# Kite Connect (Zerodha) broker
skopaq kite login-url # Get OAuth login URL
skopaq kite session <request-token> # Exchange for access token
skopaq kite status # Check Kite token health
```

### Broker Selection

Set `SKOPAQ_BROKER` in `.env` to choose your broker:

```bash
SKOPAQ_BROKER=indstocks # INDstocks (default)
SKOPAQ_BROKER=kite # Kite Connect (Zerodha)
```

Paper trading works **without any broker credentials** — the `MarketDataProvider` automatically falls back to yfinance for market data.

### Python API

```python
Expand Down Expand Up @@ -406,7 +430,7 @@ skopaqtrader/
│ ├── agents/ # Sell analyst (AI exit decisions)
│ ├── api/ # FastAPI backend server
│ ├── blockchain/ # Gas oracle, whale alerts
│ ├── broker/ # INDstocks REST/WebSocket + Binance + paper engine
│ ├── broker/ # INDstocks + Kite Connect + Binance + paper engine + market data provider
│ ├── cli/ # Typer CLI (analyze, trade, scan, daemon, monitor)
│ ├── db/ # Supabase client + repositories
│ ├── execution/ # Executor, safety checker, order router, daemon, monitor
Expand Down Expand Up @@ -437,7 +461,7 @@ skopaqtrader/
## Security

- **No secrets in the repository.** All API keys, tokens, and credentials are loaded from environment variables via `.env` (gitignored). See [`.env.example`](.env.example) for the full list of configurable keys.
- **INDstocks tokens** are stored locally in `~/.skopaq/token.json` (gitignored) and validated on every daemon session start.
- **Broker tokens** are encrypted at rest in `~/.skopaq/` (INDstocks: `token.enc`, Kite: `kite_token.enc`) using Fernet symmetric encryption and validated on every daemon session start.
- **Immutable safety rules** in `skopaq/constants.py` enforce position limits, order value caps, and rate limits that cannot be overridden at runtime.
- **Daemon safety variants** apply tighter limits for unattended operation (fewer positions, lower order caps, slower pace).
- **Live trading double-gate** — the `trade` and `daemon` CLI commands require an explicit confirmation prompt before executing real orders.
Expand Down Expand Up @@ -533,6 +557,7 @@ All product names, logos, and brands mentioned in this project are property of t
- **NSE** is a trademark of National Stock Exchange of India Limited.
- **BSE** is a trademark of BSE Limited.
- **INDstocks** is a trademark of its respective owner.
- **Zerodha** and **Kite Connect** are trademarks of Zerodha Broking Ltd.
- **Supabase**, **Vercel**, **Railway**, **Upstash**, **Cloudflare**, and **OpenRouter** are trademarks of their respective companies.

All trademarks are used here solely for identification and interoperability purposes.
Expand Down
Loading