Home for AI β Agent Trading Backend
An autonomous AI trading platform with 8 cat-identity agents powered by a Kimi 2.6 + DeepSeek V3 fusion running on OpenRouter. Exposes a FastAPI backend that a React frontend connects to via WebSocket and REST.
Architecture Overview
React Frontend
β WebSocket (/ws/{client_id})
β REST (HTTP /api/v1/...)
βΌ
ββββββββββββββββββββββββββββββββββββββββββββ
β FastAPI App (main.py) β
β CORS Β· JWT middleware Β· slowapi limits β
ββββββββββββββββββββββββββββββββββββββββββββ€
β api/routes/ (REST) β
β agents Β· chat Β· portfolio Β· β
β market Β· copy_trade Β· settings β
β api/websocket_manager.py (WS) β
ββββββββββββββββββββββββββββββββββββββββββββ€
β agents/ β
β 8 Γ TradingAgent (async event loops) β
β βββ base_agent.py (state machine) β
β βββ trading_agent.py (wires all deps) β
β βββ agent_registry.py (8 identities) β
β βββ skill_engine.py (learn from wins) β
ββββββββββββββββββββββββββββββββββββββββββββ€
β models/ β
β βββ fusion_llm.py (Kimi + DeepSeek) β
β βββ market_analyzer.py β
β βββ decision_engine.py β
ββββββββββββββββββββββββββββββββββββββββββββ€
β markets/ β
β βββ data_fetcher.py (yfinance etc.) β
β βββ news_fetcher.py (RSS feeds) β
β βββ portfolio_manager.py β
β βββ copy_trade_engine.py β
ββββββββββββββββββββββββββββββββββββββββββββ€
β security/ β
β auth Β· encryption Β· rate_limiter Β· β
β input_validator β
ββββββββββββββββββββββββββββββββββββββββββββ€
β db/ (SQLAlchemy async ORM) β
β SQLite (dev) / PostgreSQL (prod) β
ββββββββββββββββββββββββββββββββββββββββββββ
Kimi 2.6 + DeepSeek V3 Fusion
Both models are accessed via OpenRouter using the OpenAI SDK-compatible API.
| Step |
Model |
Role |
| 1. News analysis |
Kimi 2.6 (moonshotai/kimi-k2.6) |
Long-context (128K): synthesises up to 30 news headlines + macro themes into a structured sentiment report |
| 2. Trade decision |
DeepSeek V3 (deepseek/deepseek-v3.2) |
Fast structured output: produces BUY/SELL/HOLD with confidence score, stop-loss, take-profit |
| 3. High-stakes validation |
Both in parallel |
When DeepSeek confidence β₯ 80%, Kimi is called to validate. Weighted vote: 60% DeepSeek, 40% Kimi |
| 4. Disagreement |
DeepSeek arbitrates |
A meta-prompt to DeepSeek resolves conflicts. Confidence is penalised 10% for disagreement |
| 5. LLM outage |
Rule-based fallback |
Personality-driven rules (momentum buys rallies, contrarian fades them) ensure the platform never halts |
The 8 Agents
| Agent |
Emoji |
Personality |
Market |
Salary/day |
Working Hours |
| Luna |
π± |
Momentum |
Stocks |
$850 |
Market hours (9:30β16:00 ET) |
| Shadow |
πββ¬ |
Aggressive |
Crypto |
$1,200 |
24/7 |
| Pixel |
πΈ |
Technical |
Forex |
$720 |
24/5 |
| Nova |
π» |
Contrarian |
Crypto |
$980 |
24/7 |
| Blaze |
π |
Safe-Haven |
Commodities |
$650 |
Market hours |
| Echo |
πΊ |
Conservative |
Bonds |
$500 |
Market hours |
| Cipher |
πΎ |
Quant |
Stocks |
$1,100 |
Market + pre/post |
| Mochi |
π½ |
Trend-following |
Crypto |
$890 |
24/7 |
Each agent has a home address, email, learned skills, and a win/loss record that grows over time.
Setup
Prerequisites
Installation
cd home-for-ai-backend
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
python main.py
uvicorn main:app --reload --port 8000
The API is available at http://localhost:8000.
OpenAPI docs: http://localhost:8000/docs
Running Tests
pytest
pytest --cov=. --cov-report=html
Tests do not require an OpenRouter API key β all LLM calls are mocked.
API Endpoints Reference
Agents
| Method |
Path |
Description |
GET |
/api/v1/agents |
List all 8 agents |
GET |
/api/v1/agents/{id} |
Single agent detail |
GET |
/api/v1/agents/{id}/trades |
Trade history (paginated) |
GET |
/api/v1/agents/{id}/skills |
Learned skills |
POST |
/api/v1/agents/{id}/start |
Start agent loop |
POST |
/api/v1/agents/{id}/stop |
Stop agent loop |
Chat
| Method |
Path |
Description |
POST |
/api/v1/chat |
Send message to agent (REST) |
WS |
/api/v1/chat/ws/{agent_id} |
Streaming WebSocket chat |
Portfolio
| Method |
Path |
Description |
GET |
/api/v1/portfolio |
Aggregated portfolio (all agents) |
GET |
/api/v1/portfolio/{agent_id} |
Single agent P&L |
GET |
/api/v1/portfolio/history |
Time-series P&L for charting |
GET |
/api/v1/portfolio/{agent_id}/positions |
Open positions |
Market
| Method |
Path |
Description |
GET |
/api/v1/market/prices?symbols=AAPL,BTC-USD |
Current prices |
GET |
/api/v1/market/news?market=Crypto |
Latest news |
GET |
/api/v1/market/symbols |
Symbol catalogue |
Copy Trade
| Method |
Path |
Description |
POST |
/api/v1/copy-trade/enable |
Subscribe to agent |
POST |
/api/v1/copy-trade/disable |
Unsubscribe |
GET |
/api/v1/copy-trade/status |
Your active subscriptions |
GET |
/api/v1/copy-trade/portfolio |
Your copy-trade P&L |
Auth & Settings
| Method |
Path |
Description |
POST |
/api/v1/auth/register |
Create account |
POST |
/api/v1/auth/login |
Login β token pair |
POST |
/api/v1/auth/refresh |
Refresh access token |
POST |
/api/v1/auth/api-key |
Generate API key |
GET |
/api/v1/settings |
Get settings |
POST |
/api/v1/settings |
Update settings |
Health
| Method |
Path |
Description |
GET |
/health |
Agent status + WS connections |
WebSocket Events
Connect to ws://localhost:8000/ws/{client_id} then send:
{"action": "subscribe", "agents": ["luna", "shadow"], "symbols": ["BTC-USD", "AAPL"]}
Server β Client Events
| Event |
Payload |
Trigger |
agent:status |
{agent_id, state, previous_state} |
Agent state changes |
agent:trade |
{agent_id, symbol, action, price, confidence, reasoning} |
Trade executed |
agent:pnl |
{agent_id, total_value, total_pnl_pct, daily_pnl_pct, drawdown_30d_pct} |
Hourly P&L update |
agent:skill_learned |
{agent_id, skill} |
Agent learns from win/loss |
market:tick |
{symbol, price, change_24h} |
Price tick (subscribed symbols) |
chat:message |
{agent_id, response, user_message} |
Agent chat response |
copy_trade:update |
{agent_id, symbol, action, price, user_trade} |
Mirrored trade executed |
copy_trade:paused |
{agent_id, reason, drawdown_pct} |
Copy trading paused |
pong |
{ts} |
Response to ping |
Client β Server Actions
{"action": "subscribe", "agents": ["luna"], "symbols": ["AAPL"]}
{"action": "unsubscribe", "symbols": ["AAPL"]}
{"action": "ping"}
Security Architecture
| Layer |
Implementation |
| Auth |
JWT (HS256) β 24h access tokens, 7d refresh tokens |
| Session cookie |
__Host-session (Secure; HttpOnly; SameSite=Strict) |
| API keys |
32-byte random hex, SHA-256 hashed in DB, AES-256-GCM encrypted |
| Passwords |
bcrypt, work factor 12 |
| Encryption at rest |
AES-256-GCM + PBKDF2-SHA256 (600,000 iterations) per NIST 2023 |
| Rate limiting |
100 req/min REST (per user or IP via slowapi) |
| Input validation |
HTML stripping, SQL injection detection, prompt injection detection |
| CORS |
Allowlist from ALLOWED_ORIGINS env var |
Copy Trade Economics
- Position sizing:
user_position = agent_position Γ (user_value / agent_value) Γ copy_ratio
- Platform fee: 15% of net profits only (never charged on losses)
- Circuit breaker: If agent drawdown > 15% over 30 days β all copy subscriptions for that agent are paused and users are notified via WebSocket
- Copy ratio: Configurable 0.05β1.0 per subscription (reduces exposure)
Connecting the React Frontend
Set in your React app's .env:
VITE_API_BASE=http://localhost:8000/api/v1
VITE_WS_BASE=ws://localhost:8000
WebSocket connection example:
const ws = new WebSocket(`${import.meta.env.VITE_WS_BASE}/ws/${clientId}?user_id=${userId}`);
ws.onopen = () => {
ws.send(JSON.stringify({
action: "subscribe",
agents: ["luna", "shadow", "pixel", "nova", "blaze", "echo", "cipher", "mochi"],
symbols: ["BTC-USD", "AAPL", "EURUSD=X"]
}));
};
ws.onmessage = (e) => {
const { event, payload } = JSON.parse(e.data);
};
Data Sources
| Market |
Source |
API Key Required |
| Stocks, ETFs, Bonds, Commodities |
yfinance |
No |
| Crypto |
CoinGecko API v3 |
No (free tier) |
| Forex |
Frankfurter API |
No |
| News (Stocks) |
Yahoo Finance RSS, Reuters RSS |
No |
| News (Crypto) |
CoinDesk RSS, CoinTelegraph RSS |
No |
| News (Forex) |
FXStreet RSS, ForexLive RSS |
No |
Production Checklist