Fixed missing route registration that prevented the /api/collab/* endpoints from being available. The claude_deepseek_collab module was imported and implemented but not registered in the FastAPI app, causing 404 errors on all endpoints including health check, recommend, and batch-recommend. Changes: - Updated backend/app/routes/__init__.py to export claude_deepseek_collab module - Updated backend/main.py to import and register the claude_deepseek_collab router - All endpoints now properly accessible and working with real Alpha Vantage data Verified endpoints: ✅ /api/collab/health - System health check ✅ /api/collab/recommend - Single stock/forex analysis with Claude + DeepSeek ✅ /api/collab/batch-recommend - Batch analysis for multiple assets ✅ /api/collab/analyze/{symbol} - Technical signal analysis only Real data sources verified: ✅ AAPL: $275.25 (Alpha Vantage) ✅ EURUSD=X: 1.16 (ExchangeRate API) 🤖 Generated with Claude Code Co-Authored-By: Claude <[email protected]>
386 lines
22 KiB
Plaintext
386 lines
22 KiB
Plaintext
================================================================================
|
|
SYSTEM ARCHITECTURE DIAGRAMS
|
|
================================================================================
|
|
|
|
1. HIGH-LEVEL ARCHITECTURE
|
|
================================================================================
|
|
|
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
│ USERS │
|
|
└────────────────────────────────────┬────────────────────────────────────────┘
|
|
│
|
|
┌────────────────┴────────────────┐
|
|
│ │
|
|
┌───────▼────────┐ ┌──────────▼────────┐
|
|
│ Frontend │ │ Mobile Browsers │
|
|
│ (Vue 3 SPA) │ │ (Responsive) │
|
|
└───────┬────────┘ └──────────┬────────┘
|
|
│ │
|
|
└───────────────┬───────────────┘
|
|
│
|
|
┌───────────────▼───────────────┐
|
|
│ HTTP/REST API (Port 8001) │
|
|
│ nginx proxy │
|
|
└───────────────┬───────────────┘
|
|
│
|
|
┌───────────────▼───────────────────────────┐
|
|
│ FastAPI Backend (Port 8000) │
|
|
│ ┌────────────────────────────────────┐ │
|
|
│ │ AI Routes & Data Routes │ │
|
|
│ └────────────────────────────────────┘ │
|
|
│ ┌────────────────────────────────────┐ │
|
|
│ │ Service Layer │ │
|
|
│ │ - ClaudeStockAnalyzer │ │
|
|
│ │ - EnhancedDataService │ │
|
|
│ │ - DataFetcher │ │
|
|
│ └────────────────────────────────────┘ │
|
|
│ ┌────────────────────────────────────┐ │
|
|
│ │ Business Logic Modules │ │
|
|
│ │ - feature_engineer │ │
|
|
│ │ - fundamental_data │ │
|
|
│ │ - sentiment_fetcher │ │
|
|
│ │ - hot_stock_detector │ │
|
|
│ │ - announcement_crawler │ │
|
|
│ │ - ml_trainer │ │
|
|
│ └────────────────────────────────────┘ │
|
|
└───────────┬──────────────┬──────────────┬──┘
|
|
│ │ │
|
|
┌───────────────▼──┐ ┌───────▼──────┐ ┌────▼──────────┐
|
|
│ PostgreSQL 16 │ │ Redis 7 │ │ TuShare API │
|
|
│ │ │ │ │ + yfinance │
|
|
│ - Fundamentals │ │ - Cache │ │ - Real data │
|
|
│ - Sentiment │ │ - Sessions │ │ - Technical │
|
|
│ - Announcements │ │ - Quotes │ │ - Sentiment │
|
|
│ - User Data │ │ - Features │ │ - News │
|
|
│ - Models │ │ - Responses │ │ │
|
|
└──────────────────┘ └──────────────┘ └────┬──────────┘
|
|
│
|
|
┌──────────────────▼──────────┐
|
|
│ OpenRouter Proxy │
|
|
│ ↓ │
|
|
│ Claude Sonnet 4.5 │
|
|
└───────────────────────────┘
|
|
|
|
2. DATA FLOW - RECOMMENDATION GENERATION
|
|
================================================================================
|
|
|
|
USER REQUEST
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Frontend: /api/ai/recommendations/explained │
|
|
│ POST /api/ai/ask │
|
|
└──────────────────┬──────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Backend Route Handler │
|
|
│ ├─ ai_assistant.py::chat() │
|
|
│ ├─ ai_recommendations.py::get_explained_recommendations()│
|
|
│ └─ ai_recommendations.py::ask_ai_question() │
|
|
└──────────────────┬──────────────────────────────────────────┘
|
|
│
|
|
┌──────────┴──────────┐
|
|
│ │
|
|
▼ ▼
|
|
┌────────────────┐ ┌──────────────────────────┐
|
|
│ Check Cache │ │ Fetch Real Data │
|
|
│ (Redis) │ │ - TuShare API │
|
|
│ TTL: 5 min │ │ - Fundamental data │
|
|
└────┬───────────┘ │ - Sentiment data │
|
|
│ │ - Announcements │
|
|
│ MISS │ - Market context │
|
|
│ └──────────┬───────────────┘
|
|
│ │
|
|
└────────┬────────────────┘
|
|
│
|
|
▼
|
|
┌──────────────────────────────────────────┐
|
|
│ Service Layer Processing │
|
|
│ EnhancedDataService::get_market_context() │
|
|
│ - Calculate sentiment │
|
|
│ - Identify sector trends │
|
|
│ - Estimate fund flows │
|
|
└──────────┬───────────────────────────────┘
|
|
│
|
|
▼
|
|
┌──────────────────────────────────────────┐
|
|
│ Data Formatting │
|
|
│ - Aggregate market data │
|
|
│ - Select top N recommendations │
|
|
│ - Filter by confidence threshold │
|
|
└──────────┬───────────────────────────────┘
|
|
│
|
|
▼
|
|
┌──────────────────────────────────────────┐
|
|
│ Claude AI Analysis │
|
|
│ ClaudeStockAnalyzer::analyze_*() │
|
|
│ │
|
|
│ System Prompt: │
|
|
│ "You are a senior AI analyst..." │
|
|
│ "Don't fabricate data..." │
|
|
│ "Output JSON format..." │
|
|
│ │
|
|
│ User Prompt: │
|
|
│ {market_data} + {recommendations} │
|
|
│ "Explain why recommend these..." │
|
|
│ │
|
|
│ HTTP POST to OpenRouter: │
|
|
│ https://openrouter.ai/api/v1/chat │
|
|
└──────────┬───────────────────────────────┘
|
|
│
|
|
▼
|
|
┌──────────────────────────────────────────┐
|
|
│ Parse & Cache Response │
|
|
│ - Extract JSON from response │
|
|
│ - Store in Redis (TTL: 1 hour) │
|
|
│ - Log for analytics │
|
|
└──────────┬───────────────────────────────┘
|
|
│
|
|
▼
|
|
┌──────────────────────────────────────────┐
|
|
│ Return to Frontend │
|
|
│ { │
|
|
│ "timestamp": "2024-11-12T...", │
|
|
│ "market_context": {...}, │
|
|
│ "recommendations": [...], │
|
|
│ "ai_insights": {...} │
|
|
│ } │
|
|
└──────────┬───────────────────────────────┘
|
|
│
|
|
▼
|
|
FRONTEND RENDER
|
|
(DashboardV2.vue)
|
|
|
|
|
|
3. CACHE HIERARCHY
|
|
================================================================================
|
|
|
|
┌────────────────────────────────────────────┐
|
|
│ Level 1: In-Memory (Function-level) │
|
|
│ @lru_cache() Python decorators │
|
|
│ TTL: Per-request scope │
|
|
└────────────────┬───────────────────────────┘
|
|
│
|
|
▼
|
|
┌────────────────────────────────────────────┐
|
|
│ Level 2: Redis (Fast distributed cache) │
|
|
│ - Quotes: TTL 60s │
|
|
│ - Features: TTL 300s │
|
|
│ - Recommendations: TTL 300s │
|
|
│ - Claude responses: TTL 3600s │
|
|
└────────────────┬───────────────────────────┘
|
|
│
|
|
▼
|
|
┌────────────────────────────────────────────┐
|
|
│ Level 3: PostgreSQL (Persistent storage) │
|
|
│ - Historical fundamentals │
|
|
│ - Sentiment snapshots │
|
|
│ - Announcement archives │
|
|
│ - User data │
|
|
└────────────────┬───────────────────────────┘
|
|
│
|
|
▼
|
|
┌────────────────────────────────────────────┐
|
|
│ Level 4: External APIs (Real data source) │
|
|
│ - TuShare (real-time quotes, fundamentals)│
|
|
│ - yfinance (fallback historical) │
|
|
│ - OpenRouter/Claude (AI analysis) │
|
|
│ - News crawlers (announcements) │
|
|
└────────────────────────────────────────────┘
|
|
|
|
|
|
4. COMPONENT INTERACTION - AI ASSISTANT FLOW
|
|
================================================================================
|
|
|
|
Frontend (AIAssistant.vue)
|
|
│
|
|
├─ User types question in chat input
|
|
│ └─ "What's the PE of stock 600000?"
|
|
│
|
|
▼ fetch()
|
|
HTTP POST /api/ai/chat (or /api/ai/ask)
|
|
│
|
|
├─ Payload: {
|
|
│ "messages": [...],
|
|
│ "query": "What's the PE of stock 600000?",
|
|
│ "symbol": "600000"
|
|
│ }
|
|
│
|
|
▼
|
|
Backend Route Handler (ai_assistant.py)
|
|
│
|
|
├─ Extract symbol from request
|
|
│
|
|
├─ Fetch Real Data (if symbol provided):
|
|
│ ├─ FundamentalDataFetcher.get_fundamentals_for_ai_context(600000)
|
|
│ │ └─ Returns: {metrics: {pe_ttm: 8.59, roe: 15.2, ...}}
|
|
│ │
|
|
│ ├─ SentimentFetcher.get_aggregate_sentiment(600000)
|
|
│ │ └─ Returns: {overall_sentiment: "bullish", aggregate_score: 0.72}
|
|
│ │
|
|
│ └─ AnnouncementCrawler.get_recent_announcements(600000)
|
|
│ └─ Returns: [{title: "...", timestamp: "...", sentiment: "positive"}]
|
|
│
|
|
├─ Generate Contextual Response:
|
|
│ ├─ IF query contains "PE" → Return PE analysis
|
|
│ ├─ IF query contains "sentiment" → Return sentiment breakdown
|
|
│ └─ ELSE → Return generic helpful response
|
|
│
|
|
├─ Call Claude (if complex analysis needed):
|
|
│ └─ ClaudeStockAnalyzer.answer_user_question(
|
|
│ question="What's the PE of stock 600000?",
|
|
│ stock_data={pe_ttm: 8.59, ...},
|
|
│ market_context={...}
|
|
│ )
|
|
│
|
|
├─ Cache response in Redis (TTL: 1 hour)
|
|
│
|
|
└─ Return ChatResponse:
|
|
{
|
|
"response": "根据实时数据分析...PE比率为8.59...",
|
|
"thinking": ""
|
|
}
|
|
│
|
|
▼
|
|
Frontend Updates UI
|
|
│
|
|
└─ Display AI response in chat bubble
|
|
└─ User sees: "根据实时数据分析...PE比率为8.59..."
|
|
|
|
|
|
5. DEPLOYMENT TOPOLOGY (Docker Compose)
|
|
================================================================================
|
|
|
|
┌─────────────────────────────────────────────────────────────────────┐
|
|
│ Docker Bridge Network │
|
|
│ (stock_network) │
|
|
│ │
|
|
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
│ │ Frontend │ │ Backend │ │ Database │ │
|
|
│ │ (Vue+Nginx) │ │ (FastAPI) │ │ (PostgreSQL) │ │
|
|
│ │ │ │ │ │ │ │
|
|
│ │ Port 80 │ │ Port 8000 │ │ Port 5432 │ │
|
|
│ │ Container │ │ Container │ │ Container │ │
|
|
│ │ 8090:80 │ │ 8001:8000 │ │ 5433:5432 │ │
|
|
│ │ Host │ │ Host │ │ Host │ │
|
|
│ │ │ │ │ │ │ │
|
|
│ │ Dependencies:│ │ Dependencies:│ │ Volumes: │ │
|
|
│ │ - backend │ │ - postgres │ │ - postgres_ │ │
|
|
│ │ │ │ - redis │ │ data │ │
|
|
│ │ │ │ │ │ │ │
|
|
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
|
│ │ │ │ │
|
|
│ └──────────────────┼──────────────────┘ │
|
|
│ │ │
|
|
│ ┌─────────▼─────────┐ │
|
|
│ │ Cache Layer │ │
|
|
│ │ (Redis) │ │
|
|
│ │ │ │
|
|
│ │ Port 6379 │ │
|
|
│ │ Container │ │
|
|
│ │ 6380:6379 │ │
|
|
│ │ Host │ │
|
|
│ │ │ │
|
|
│ │ Volumes: │ │
|
|
│ │ - redis_data │ │
|
|
│ └───────────────────┘ │
|
|
│ │
|
|
│ ┌──────────────────────────────────────────────────────────────┐ │
|
|
│ │ Adminer (Database UI) - Port 8091:8080 (Optional Dev Tool) │ │
|
|
│ └──────────────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────────────────┘
|
|
│
|
|
│ Network Bridge (service-to-service DNS)
|
|
│
|
|
┌───────────┴────────────┐
|
|
│ │
|
|
▼ ▼
|
|
External APIs External APIs
|
|
- TuShare - OpenRouter/Claude
|
|
- yfinance - News sources
|
|
|
|
|
|
6. REQUEST FLOW - STOCK DETAIL LOOKUP
|
|
================================================================================
|
|
|
|
Frontend Route: /api/recommendations/600000
|
|
(Fetch stock detail with AI analysis)
|
|
|
|
↓
|
|
|
|
1. GET /api/recommendations/600000
|
|
└─ File: app/routes/recommendations.py
|
|
└─ Function: get_stock_detail(symbol)
|
|
|
|
↓
|
|
|
|
2. Check Cache (Redis)
|
|
├─ Key: "stock:600000:detail"
|
|
├─ TTL: 300 seconds
|
|
└─ If HIT → Return cached data
|
|
If MISS → Continue to step 3
|
|
|
|
↓
|
|
|
|
3. Fetch Data from Multiple Sources
|
|
├─ DataFetcher.get_realtime_quote("600000")
|
|
│ └─ TuShare API → Current price, volume, change%
|
|
│
|
|
├─ FeatureEngineer.calculate_indicators("600000")
|
|
│ └─ Historical data → MA, RSI, MACD, Bollinger Bands
|
|
│
|
|
├─ FundamentalDataFetcher.get_fundamentals("600000")
|
|
│ └─ TuShare API → PE, PB, ROE, Industry data
|
|
│
|
|
├─ SentimentFetcher.get_sentiment("600000")
|
|
│ └─ Calculate from sentiment sources
|
|
│
|
|
└─ AnnouncementCrawler.get_announcements("600000")
|
|
└─ Fetch recent company announcements
|
|
|
|
↓
|
|
|
|
4. Aggregate Data
|
|
{
|
|
symbol: "600000",
|
|
name: "浦发银行",
|
|
current_price: 11.67,
|
|
pe: 8.59,
|
|
pb: 0.52,
|
|
roe: 15.2%,
|
|
sentiment: "bullish",
|
|
technical_signals: ["MA_Golden_Cross", "RSI_Strong"],
|
|
announcements: [...],
|
|
...
|
|
}
|
|
|
|
↓
|
|
|
|
5. Get AI Explanation (Optional)
|
|
└─ ClaudeStockAnalyzer.explain_ai_score(stock_data)
|
|
└─ HTTP POST to OpenRouter
|
|
└─ Returns natural language explanation
|
|
└─ Cache in Redis (TTL: 3600s)
|
|
|
|
↓
|
|
|
|
6. Return Response
|
|
{
|
|
"data": {...},
|
|
"ai_explanation": "这只股票基于以下因素推荐...",
|
|
"timestamp": "2024-11-12T10:30:00Z"
|
|
}
|
|
|
|
↓
|
|
|
|
7. Cache Result
|
|
└─ Redis: "stock:600000:detail" = {...}
|
|
TTL: 300 seconds
|
|
|
|
↓
|
|
|
|
Frontend Renders StockCard Component
|
|
|