An AI-powered crypto trading system for CoinDCX with technical analysis, LLM-assisted signal classification, paper/live execution, risk controls, and walk-forward backtesting.
Safety first: the LLM classifies signals and writes reasoning.
Code computes every number risk depends on. A bad LLM output can only produceno_trade; it cannot place an order or silently change risk.
- Technical indicators such as RSI, SMA, ATR, and ADX
- LLM-based signal interpretation with JSON validation
- Paper trading and live trading support
- Risk engine with sizing, correlation, and kill switch logic
- SQLite logging and backtesting workflow
Data intake (candles + news + calendar)
↓
Data quality gate (stale? gaps? exchange down?) ──fail──→ skip cycle + alert
↓
Scoring engine (RSI, SMA, ATR, ADX, support/resistance — all in code)
↓
LLM decision layer (classifies signal agreement, returns JSON only)
↓
Schema validation (reject malformed JSON → retry once → no_trade + alert)
↓
Risk & sizing engine (fees, slippage, correlation, daily loss, kill switch)
↓
Execution (CoinDCX API — paper mode or live mode)
↓
SQLite log (every decision, including rejections and no_trades)
↺ feeds backtesting and expectancy calculation
git clone https://github.com/YOUR_USERNAME/crypto-agent.git
cd crypto-agent
python -m venv venv
venv\Scripts\activate # Windows
pip install -r requirements.txtcopy backend\config\.env.example backend\config\.env
# Open .env and fill in your keys (see section below)python -m backend.mainuvicorn backend.api:app --reload --port 8000Endpoints:
GET http://localhost:8000/api/status— system stateGET http://localhost:8000/api/trades— paginated trade logGET http://localhost:8000/api/health— liveness probePOST http://localhost:8000/api/kill_switch/engage— halt tradingPOST http://localhost:8000/api/kill_switch/disengage— resume
pytest backend/tests/ -v
# Expected: 52 passedpython -m backtest.walk_forward --symbol BTCUSDT --interval 1h --limit 1000Copy backend/config/.env.example → backend/config/.env and fill in:
| Variable | Default | Required | Description |
|---|---|---|---|
PAPER_MODE |
true |
✅ | Keep true until weeks of paper testing |
LLM_PROVIDER |
gemini |
✅ | gemini / anthropic / openai / ollama |
GEMINI_API_KEY |
— | If using Gemini | Free at aistudio.google.com |
ANTHROPIC_API_KEY |
— | If using Anthropic | console.anthropic.com |
COINDCX_API_KEY |
— | For live trading | Trading permission only, no withdrawal |
COINDCX_API_SECRET |
— | For live trading | Enable IP whitelist on CoinDCX |
SYMBOLS |
BTCUSDT,ETHUSDT,SOLUSDT |
✅ | Comma-separated pairs |
CANDLE_INTERVAL |
1h |
✅ | 1h, 4h, 1d, etc. |
MAX_RISK_PCT |
0.01 |
✅ | 1% of balance per trade |
DAILY_LOSS_LIMIT_PCT |
0.05 |
✅ | Halt at 5% daily loss |
TELEGRAM_BOT_TOKEN |
— | Optional | For alert notifications |
TELEGRAM_CHAT_ID |
— | Optional | For alert notifications |
Halt all trading instantly (survives restarts via flag file):
# Via API
curl -X POST http://localhost:8000/api/kill_switch/engage \
-H "X-Admin-Token: your_ADMIN_TOKEN"
# Via file (works even if the API is down)
echo "manual halt" > kill_switch.flag
# Resume
curl -X POST http://localhost:8000/api/kill_switch/disengage \
-H "X-Admin-Token: your_ADMIN_TOKEN"crypto-agent/
├── backend/
│ ├── config/
│ │ ├── .env.example ← copy to .env, never commit .env
│ │ └── settings.py ← typed config, loaded once at startup
│ ├── data/
│ │ ├── candles.py ← CoinDCX OHLCV fetch + cache
│ │ ├── news.py ← NewsAPI + CryptoPanic + CoinDesk RSS
│ │ ├── calendar.py ← CoinMarketCal upcoming events
│ │ └── quality.py ← stale/gap/volume quality gate
│ ├── indicators/
│ │ └── technical.py ← SMA, RSI, ATR, ADX, support/resistance
│ ├── agent/
│ │ ├── system_prompt.py ← spec §5 prompt, versioned
│ │ ├── llm_client.py ← Gemini/Anthropic/OpenAI/Ollama, validates JSON
│ │ └── tools.py ← function-calling stub (future use)
│ ├── risk/
│ │ ├── risk_engine.py ← all money math, 9-step gate
│ │ ├── correlation.py ← correlated exposure cap
│ │ └── kill_switch.py ← dual-layer halt (memory + flag file)
│ ├── execution/
│ │ ├── coindcx_client.py ← HMAC auth, idempotency, retry
│ │ └── paper_broker.py ← simulated fills with slippage/fees
│ ├── alerts/
│ │ └── notifier.py ← Telegram + console alerts
│ ├── storage/
│ │ └── db.py ← SQLite, full spec §7 schema
│ ├── tests/ ← 52 unit tests (all passing)
│ ├── main.py ← 12-step pipeline loop
│ └── api.py ← FastAPI dashboard + kill switch API
├── backtest/
│ ├── engine.py ← same code path as live, fee-simulated
│ └── walk_forward.py ← rolling train/test windows + CLI
├── requirements.txt
├── .gitignore ← .env and trades.db excluded
├── README.md ← this file
└── PROJECT_STATUS.md ← build log, test status, next steps
Before generating a live trading key:
- Read-only CoinDCX key — validate candle pulls with zero trading permission
- Paper-trade for several weeks on live prices
- Walk-forward backtest on 6+ months of BTC/ETH historical data
- Confirm kill switch fires:
POST /api/kill_switch/engage - Confirm Telegram alerts arrive on each trigger event
- Only then: generate trading-enabled key (no withdrawal, IP whitelisted)
- Start live with minimum lot size for weeks before scaling
- Track expectancy (net of fees), not win rate, as your go/no-go metric
Not "rarely any losses." Target: positive expectancy, net of fees, over 50–100+ logged trades.
The metric is stored in trades.db as outcome_pct (already fee/slippage-adjusted).
Expectancy = (win_rate × avg_net_win) − (loss_rate × avg_net_loss)
If this number is positive over a statistically meaningful sample, the system is worth running live.
.envis git-ignored — never commit ittrades.dbis git-ignored — contains trade history- CoinDCX key: trading permission only, never withdrawal, IP whitelist on
- The LLM is never sent raw API keys or your account balance
- News headlines are explicitly flagged as untrusted data in the system prompt (prompt injection defence)
Not financial advice. Check local regulations and CoinDCX terms of service before running live.