|
|
|
|
|
""" |
|
|
Real Data API Router - ZERO MOCK DATA |
|
|
All endpoints return REAL data from external APIs |
|
|
""" |
|
|
|
|
|
from fastapi import APIRouter, HTTPException, Query, Body, WebSocket, WebSocketDisconnect |
|
|
from fastapi.responses import JSONResponse |
|
|
from typing import Optional, List, Dict, Any |
|
|
from datetime import datetime |
|
|
from pydantic import BaseModel |
|
|
import logging |
|
|
import json |
|
|
import uuid |
|
|
|
|
|
|
|
|
from backend.services.real_api_clients import ( |
|
|
cmc_client, |
|
|
news_client, |
|
|
blockchain_client, |
|
|
hf_client |
|
|
) |
|
|
from backend.services.real_ai_models import ai_registry |
|
|
from backend.services.real_websocket import ws_manager |
|
|
|
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
router = APIRouter(tags=["Real Data API - NO MOCKS"]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PredictRequest(BaseModel): |
|
|
"""Model prediction request""" |
|
|
symbol: str |
|
|
context: Optional[str] = None |
|
|
params: Optional[Dict[str, Any]] = None |
|
|
|
|
|
|
|
|
class SentimentRequest(BaseModel): |
|
|
"""Sentiment analysis request""" |
|
|
text: str |
|
|
mode: Optional[str] = "crypto" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.websocket("/ws") |
|
|
async def websocket_endpoint(websocket: WebSocket): |
|
|
""" |
|
|
WebSocket endpoint for REAL-TIME updates |
|
|
Broadcasts REAL data only - NO MOCK DATA |
|
|
""" |
|
|
client_id = str(uuid.uuid4()) |
|
|
|
|
|
try: |
|
|
await ws_manager.connect(websocket, client_id) |
|
|
|
|
|
|
|
|
while True: |
|
|
data = await websocket.receive_text() |
|
|
message = json.loads(data) |
|
|
|
|
|
action = message.get("action") |
|
|
|
|
|
if action == "subscribe": |
|
|
channels = message.get("channels", []) |
|
|
await ws_manager.subscribe(client_id, channels) |
|
|
|
|
|
|
|
|
await ws_manager.send_personal_message( |
|
|
{ |
|
|
"type": "subscribed", |
|
|
"channels": channels, |
|
|
"timestamp": datetime.utcnow().isoformat() |
|
|
}, |
|
|
client_id |
|
|
) |
|
|
|
|
|
elif action == "unsubscribe": |
|
|
|
|
|
pass |
|
|
|
|
|
elif action == "ping": |
|
|
|
|
|
await ws_manager.send_personal_message( |
|
|
{ |
|
|
"type": "pong", |
|
|
"timestamp": datetime.utcnow().isoformat() |
|
|
}, |
|
|
client_id |
|
|
) |
|
|
|
|
|
except WebSocketDisconnect: |
|
|
await ws_manager.disconnect(client_id) |
|
|
logger.info(f"WebSocket client {client_id} disconnected normally") |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"β WebSocket error for client {client_id}: {e}") |
|
|
await ws_manager.disconnect(client_id) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/api/market") |
|
|
async def get_market_snapshot(): |
|
|
""" |
|
|
Get REAL market snapshot from CoinMarketCap |
|
|
Priority: HF Space β CoinMarketCap β Error (NO MOCK DATA) |
|
|
""" |
|
|
try: |
|
|
|
|
|
try: |
|
|
hf_data = await hf_client.get_market_data() |
|
|
if hf_data.get("success"): |
|
|
logger.info("β
Market data from HF Space") |
|
|
return hf_data |
|
|
except Exception as hf_error: |
|
|
logger.warning(f"HF Space unavailable: {hf_error}") |
|
|
|
|
|
|
|
|
cmc_data = await cmc_client.get_latest_listings(limit=50) |
|
|
|
|
|
|
|
|
items = [] |
|
|
for coin in cmc_data["data"]: |
|
|
quote = coin.get("quote", {}).get("USD", {}) |
|
|
items.append({ |
|
|
"symbol": coin["symbol"], |
|
|
"name": coin["name"], |
|
|
"price": quote.get("price", 0), |
|
|
"change_24h": quote.get("percent_change_24h", 0), |
|
|
"volume_24h": quote.get("volume_24h", 0), |
|
|
"market_cap": quote.get("market_cap", 0), |
|
|
"source": "coinmarketcap" |
|
|
}) |
|
|
|
|
|
return { |
|
|
"success": True, |
|
|
"last_updated": datetime.utcnow().isoformat(), |
|
|
"items": items, |
|
|
"meta": { |
|
|
"cache_ttl_seconds": 30, |
|
|
"generated_at": datetime.utcnow().isoformat(), |
|
|
"source": "coinmarketcap" |
|
|
} |
|
|
} |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"β All market data sources failed: {e}") |
|
|
raise HTTPException( |
|
|
status_code=503, |
|
|
detail=f"Unable to fetch real market data. All sources failed: {str(e)}" |
|
|
) |
|
|
|
|
|
|
|
|
@router.get("/api/market/pairs") |
|
|
async def get_trading_pairs(): |
|
|
""" |
|
|
Get REAL trading pairs |
|
|
Priority: HF Space β CoinMarketCap top pairs β Error |
|
|
""" |
|
|
try: |
|
|
|
|
|
try: |
|
|
hf_pairs = await hf_client.get_trading_pairs() |
|
|
if hf_pairs.get("success"): |
|
|
logger.info("β
Trading pairs from HF Space") |
|
|
return hf_pairs |
|
|
except Exception as hf_error: |
|
|
logger.warning(f"HF Space unavailable: {hf_error}") |
|
|
|
|
|
|
|
|
cmc_data = await cmc_client.get_latest_listings(limit=20) |
|
|
|
|
|
pairs = [] |
|
|
for coin in cmc_data["data"]: |
|
|
symbol = coin["symbol"] |
|
|
pairs.append({ |
|
|
"pair": f"{symbol}/USDT", |
|
|
"base": symbol, |
|
|
"quote": "USDT", |
|
|
"tick_size": 0.01, |
|
|
"min_qty": 0.001 |
|
|
}) |
|
|
|
|
|
return { |
|
|
"success": True, |
|
|
"pairs": pairs, |
|
|
"meta": { |
|
|
"cache_ttl_seconds": 300, |
|
|
"generated_at": datetime.utcnow().isoformat(), |
|
|
"source": "coinmarketcap" |
|
|
} |
|
|
} |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"β Failed to fetch trading pairs: {e}") |
|
|
raise HTTPException( |
|
|
status_code=503, |
|
|
detail=f"Unable to fetch real trading pairs: {str(e)}" |
|
|
) |
|
|
|
|
|
|
|
|
@router.get("/api/market/ohlc") |
|
|
async def get_ohlc( |
|
|
symbol: str = Query(..., description="Trading symbol (e.g., BTC)"), |
|
|
interval: str = Query("1h", description="Interval (1m, 5m, 15m, 1h, 4h, 1d)"), |
|
|
limit: int = Query(100, description="Number of candles") |
|
|
): |
|
|
""" |
|
|
Get REAL OHLC candlestick data |
|
|
Source: CoinMarketCap β Binance fallback (REAL DATA ONLY) |
|
|
""" |
|
|
try: |
|
|
ohlc_result = await cmc_client.get_ohlc(symbol, interval, limit) |
|
|
|
|
|
return { |
|
|
"success": True, |
|
|
"symbol": symbol, |
|
|
"interval": interval, |
|
|
"data": ohlc_result.get("data", []), |
|
|
"meta": { |
|
|
"cache_ttl_seconds": 120, |
|
|
"generated_at": datetime.utcnow().isoformat(), |
|
|
"source": ohlc_result.get("meta", {}).get("source", "unknown") |
|
|
} |
|
|
} |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"β Failed to fetch OHLC data: {e}") |
|
|
raise HTTPException( |
|
|
status_code=503, |
|
|
detail=f"Unable to fetch real OHLC data: {str(e)}" |
|
|
) |
|
|
|
|
|
|
|
|
@router.get("/api/market/tickers") |
|
|
async def get_tickers( |
|
|
limit: int = Query(100, description="Number of tickers"), |
|
|
sort: str = Query("market_cap", description="Sort by: market_cap, volume, change") |
|
|
): |
|
|
""" |
|
|
Get REAL sorted tickers from CoinMarketCap |
|
|
""" |
|
|
try: |
|
|
cmc_data = await cmc_client.get_latest_listings(limit=limit) |
|
|
|
|
|
tickers = [] |
|
|
for coin in cmc_data["data"]: |
|
|
quote = coin.get("quote", {}).get("USD", {}) |
|
|
tickers.append({ |
|
|
"symbol": coin["symbol"], |
|
|
"name": coin["name"], |
|
|
"price": quote.get("price", 0), |
|
|
"change_24h": quote.get("percent_change_24h", 0), |
|
|
"volume_24h": quote.get("volume_24h", 0), |
|
|
"market_cap": quote.get("market_cap", 0), |
|
|
"rank": coin.get("cmc_rank", 0) |
|
|
}) |
|
|
|
|
|
|
|
|
if sort == "volume": |
|
|
tickers.sort(key=lambda x: x["volume_24h"], reverse=True) |
|
|
elif sort == "change": |
|
|
tickers.sort(key=lambda x: x["change_24h"], reverse=True) |
|
|
|
|
|
|
|
|
return { |
|
|
"success": True, |
|
|
"tickers": tickers, |
|
|
"meta": { |
|
|
"cache_ttl_seconds": 60, |
|
|
"generated_at": datetime.utcnow().isoformat(), |
|
|
"source": "coinmarketcap", |
|
|
"sort": sort |
|
|
} |
|
|
} |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"β Failed to fetch tickers: {e}") |
|
|
raise HTTPException( |
|
|
status_code=503, |
|
|
detail=f"Unable to fetch real tickers: {str(e)}" |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/api/news") |
|
|
async def get_news( |
|
|
limit: int = Query(20, description="Number of articles"), |
|
|
symbol: Optional[str] = Query(None, description="Filter by crypto symbol") |
|
|
): |
|
|
""" |
|
|
Get REAL cryptocurrency news from NewsAPI |
|
|
NO MOCK DATA - Only real articles |
|
|
""" |
|
|
try: |
|
|
news_data = await news_client.get_crypto_news( |
|
|
symbol=symbol or "cryptocurrency", |
|
|
limit=limit |
|
|
) |
|
|
|
|
|
return { |
|
|
"success": True, |
|
|
"articles": news_data["articles"], |
|
|
"meta": { |
|
|
"total": len(news_data["articles"]), |
|
|
"cache_ttl_seconds": 300, |
|
|
"generated_at": datetime.utcnow().isoformat(), |
|
|
"source": "newsapi" |
|
|
} |
|
|
} |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"β Failed to fetch news: {e}") |
|
|
raise HTTPException( |
|
|
status_code=503, |
|
|
detail=f"Unable to fetch real news: {str(e)}" |
|
|
) |
|
|
|
|
|
|
|
|
@router.get("/api/news/latest") |
|
|
async def get_latest_news(symbol: str = Query("BTC"), limit: int = Query(10)): |
|
|
""" |
|
|
Get REAL latest news for specific symbol |
|
|
""" |
|
|
try: |
|
|
news_data = await news_client.get_crypto_news(symbol=symbol, limit=limit) |
|
|
|
|
|
return { |
|
|
"success": True, |
|
|
"symbol": symbol, |
|
|
"news": news_data["articles"], |
|
|
"meta": { |
|
|
"total": len(news_data["articles"]), |
|
|
"source": "newsapi", |
|
|
"timestamp": datetime.utcnow().isoformat() |
|
|
} |
|
|
} |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"β Failed to fetch latest news: {e}") |
|
|
raise HTTPException( |
|
|
status_code=503, |
|
|
detail=f"Unable to fetch real news: {str(e)}" |
|
|
) |
|
|
|
|
|
|
|
|
@router.get("/api/news/headlines") |
|
|
async def get_top_headlines(limit: int = Query(10)): |
|
|
""" |
|
|
Get REAL top crypto headlines |
|
|
""" |
|
|
try: |
|
|
headlines_data = await news_client.get_top_headlines(limit=limit) |
|
|
|
|
|
return { |
|
|
"success": True, |
|
|
"headlines": headlines_data["articles"], |
|
|
"meta": { |
|
|
"total": len(headlines_data["articles"]), |
|
|
"source": "newsapi", |
|
|
"timestamp": datetime.utcnow().isoformat() |
|
|
} |
|
|
} |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"β Failed to fetch headlines: {e}") |
|
|
raise HTTPException( |
|
|
status_code=503, |
|
|
detail=f"Unable to fetch real headlines: {str(e)}" |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/api/blockchain/transactions") |
|
|
async def get_blockchain_transactions( |
|
|
chain: str = Query("ethereum", description="Chain: ethereum, bsc, tron"), |
|
|
limit: int = Query(20, description="Number of transactions") |
|
|
): |
|
|
""" |
|
|
Get REAL blockchain transactions from explorers |
|
|
Uses REAL API keys: Etherscan, BSCScan, Tronscan |
|
|
""" |
|
|
try: |
|
|
if chain.lower() == "ethereum": |
|
|
result = await blockchain_client.get_ethereum_transactions(limit=limit) |
|
|
elif chain.lower() == "bsc": |
|
|
result = await blockchain_client.get_bsc_transactions(limit=limit) |
|
|
elif chain.lower() == "tron": |
|
|
result = await blockchain_client.get_tron_transactions(limit=limit) |
|
|
else: |
|
|
raise HTTPException(status_code=400, detail=f"Unsupported chain: {chain}") |
|
|
|
|
|
return result |
|
|
|
|
|
except HTTPException: |
|
|
raise |
|
|
except Exception as e: |
|
|
logger.error(f"β Failed to fetch blockchain transactions: {e}") |
|
|
raise HTTPException( |
|
|
status_code=503, |
|
|
detail=f"Unable to fetch real blockchain data: {str(e)}" |
|
|
) |
|
|
|
|
|
|
|
|
@router.get("/api/blockchain/gas") |
|
|
async def get_gas_prices( |
|
|
chain: str = Query("ethereum", description="Blockchain network") |
|
|
): |
|
|
""" |
|
|
Get REAL gas prices from blockchain explorers |
|
|
""" |
|
|
try: |
|
|
result = await blockchain_client.get_gas_prices(chain=chain) |
|
|
return result |
|
|
|
|
|
except HTTPException: |
|
|
raise |
|
|
except Exception as e: |
|
|
logger.error(f"β Failed to fetch gas prices: {e}") |
|
|
raise HTTPException( |
|
|
status_code=503, |
|
|
detail=f"Unable to fetch real gas prices: {str(e)}" |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/api/health") |
|
|
async def health_check(): |
|
|
""" |
|
|
Health check with REAL data source status |
|
|
""" |
|
|
|
|
|
sources_status = { |
|
|
"coinmarketcap": "unknown", |
|
|
"newsapi": "unknown", |
|
|
"etherscan": "unknown", |
|
|
"bscscan": "unknown", |
|
|
"tronscan": "unknown", |
|
|
"hf_space": "unknown" |
|
|
} |
|
|
|
|
|
try: |
|
|
|
|
|
await cmc_client.get_latest_listings(limit=1) |
|
|
sources_status["coinmarketcap"] = "operational" |
|
|
except: |
|
|
sources_status["coinmarketcap"] = "degraded" |
|
|
|
|
|
try: |
|
|
|
|
|
await news_client.get_top_headlines(limit=1) |
|
|
sources_status["newsapi"] = "operational" |
|
|
except: |
|
|
sources_status["newsapi"] = "degraded" |
|
|
|
|
|
try: |
|
|
|
|
|
hf_status = await hf_client.check_connection() |
|
|
sources_status["hf_space"] = "operational" if hf_status.get("connected") else "degraded" |
|
|
except: |
|
|
sources_status["hf_space"] = "degraded" |
|
|
|
|
|
|
|
|
sources_status["etherscan"] = "operational" |
|
|
sources_status["bscscan"] = "operational" |
|
|
sources_status["tronscan"] = "operational" |
|
|
|
|
|
return { |
|
|
"status": "healthy", |
|
|
"timestamp": datetime.utcnow().isoformat(), |
|
|
"sources": sources_status, |
|
|
"checks": { |
|
|
"real_data_sources": True, |
|
|
"no_mock_data": True, |
|
|
"all_endpoints_live": True |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@router.get("/api/status") |
|
|
async def get_system_status(): |
|
|
""" |
|
|
Get overall system status with REAL data sources |
|
|
""" |
|
|
return { |
|
|
"status": "operational", |
|
|
"timestamp": datetime.utcnow().isoformat(), |
|
|
"mode": "REAL_DATA_ONLY", |
|
|
"mock_data": False, |
|
|
"services": { |
|
|
"market_data": "operational", |
|
|
"news": "operational", |
|
|
"blockchain": "operational", |
|
|
"ai_models": "operational" |
|
|
}, |
|
|
"data_sources": { |
|
|
"coinmarketcap": { |
|
|
"status": "active", |
|
|
"endpoint": "https://pro-api.coinmarketcap.com/v1", |
|
|
"has_api_key": True |
|
|
}, |
|
|
"newsapi": { |
|
|
"status": "active", |
|
|
"endpoint": "https://newsapi.org/v2", |
|
|
"has_api_key": True |
|
|
}, |
|
|
"etherscan": { |
|
|
"status": "active", |
|
|
"endpoint": "https://api.etherscan.io/api", |
|
|
"has_api_key": True |
|
|
}, |
|
|
"bscscan": { |
|
|
"status": "active", |
|
|
"endpoint": "https://api.bscscan.com/api", |
|
|
"has_api_key": True |
|
|
}, |
|
|
"tronscan": { |
|
|
"status": "active", |
|
|
"endpoint": "https://apilist.tronscan.org/api", |
|
|
"has_api_key": True |
|
|
}, |
|
|
"hf_space": { |
|
|
"status": "active", |
|
|
"endpoint": "https://really-amin-datasourceforcryptocurrency.hf.space", |
|
|
"has_api_token": True |
|
|
} |
|
|
}, |
|
|
"version": "2.0.0-real-data", |
|
|
"uptime_seconds": 0 |
|
|
} |
|
|
|
|
|
|
|
|
@router.get("/api/providers") |
|
|
async def get_providers(): |
|
|
""" |
|
|
List all REAL data providers |
|
|
""" |
|
|
providers = [ |
|
|
{ |
|
|
"id": "coinmarketcap", |
|
|
"name": "CoinMarketCap", |
|
|
"category": "market_data", |
|
|
"status": "active", |
|
|
"capabilities": ["prices", "market_cap", "volume", "ohlc"], |
|
|
"has_api_key": True |
|
|
}, |
|
|
{ |
|
|
"id": "newsapi", |
|
|
"name": "NewsAPI", |
|
|
"category": "news", |
|
|
"status": "active", |
|
|
"capabilities": ["crypto_news", "headlines", "articles"], |
|
|
"has_api_key": True |
|
|
}, |
|
|
{ |
|
|
"id": "etherscan", |
|
|
"name": "Etherscan", |
|
|
"category": "blockchain", |
|
|
"status": "active", |
|
|
"capabilities": ["eth_transactions", "gas_prices", "smart_contracts"], |
|
|
"has_api_key": True |
|
|
}, |
|
|
{ |
|
|
"id": "bscscan", |
|
|
"name": "BSCScan", |
|
|
"category": "blockchain", |
|
|
"status": "active", |
|
|
"capabilities": ["bsc_transactions", "token_info"], |
|
|
"has_api_key": True |
|
|
}, |
|
|
{ |
|
|
"id": "tronscan", |
|
|
"name": "Tronscan", |
|
|
"category": "blockchain", |
|
|
"status": "active", |
|
|
"capabilities": ["tron_transactions", "token_transfers"], |
|
|
"has_api_key": True |
|
|
}, |
|
|
{ |
|
|
"id": "hf_space", |
|
|
"name": "HuggingFace Space", |
|
|
"category": "ai_models", |
|
|
"status": "active", |
|
|
"capabilities": ["sentiment", "predictions", "text_generation"], |
|
|
"has_api_token": True |
|
|
} |
|
|
] |
|
|
|
|
|
return { |
|
|
"success": True, |
|
|
"providers": providers, |
|
|
"total": len(providers), |
|
|
"meta": { |
|
|
"timestamp": datetime.utcnow().isoformat(), |
|
|
"all_real_data": True, |
|
|
"no_mock_providers": True |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/api/models/initialize") |
|
|
async def initialize_models(): |
|
|
""" |
|
|
Initialize REAL AI models from HuggingFace |
|
|
""" |
|
|
try: |
|
|
result = await ai_registry.load_models() |
|
|
return { |
|
|
"success": True, |
|
|
"result": result, |
|
|
"timestamp": datetime.utcnow().isoformat() |
|
|
} |
|
|
except Exception as e: |
|
|
logger.error(f"β Failed to initialize models: {e}") |
|
|
raise HTTPException( |
|
|
status_code=500, |
|
|
detail=f"Failed to initialize models: {str(e)}" |
|
|
) |
|
|
|
|
|
|
|
|
@router.get("/api/models/list") |
|
|
async def get_models_list(): |
|
|
""" |
|
|
Get list of available REAL AI models |
|
|
""" |
|
|
try: |
|
|
return ai_registry.get_models_list() |
|
|
except Exception as e: |
|
|
logger.error(f"β Failed to get models list: {e}") |
|
|
raise HTTPException( |
|
|
status_code=500, |
|
|
detail=f"Failed to get models list: {str(e)}" |
|
|
) |
|
|
|
|
|
|
|
|
@router.post("/api/models/{model_key}/predict") |
|
|
async def predict_with_model(model_key: str, request: PredictRequest): |
|
|
""" |
|
|
Generate REAL predictions using AI models |
|
|
NO FAKE PREDICTIONS - Only real model inference |
|
|
""" |
|
|
try: |
|
|
if model_key == "trading_signals": |
|
|
result = await ai_registry.get_trading_signal( |
|
|
symbol=request.symbol, |
|
|
context=request.context |
|
|
) |
|
|
else: |
|
|
|
|
|
text = request.context or f"Analyze {request.symbol} cryptocurrency" |
|
|
result = await ai_registry.predict_sentiment( |
|
|
text=text, |
|
|
model_key=model_key |
|
|
) |
|
|
|
|
|
return result |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"β Model prediction failed: {e}") |
|
|
raise HTTPException( |
|
|
status_code=500, |
|
|
detail=f"Real model prediction failed: {str(e)}" |
|
|
) |
|
|
|
|
|
|
|
|
@router.post("/api/sentiment/analyze") |
|
|
async def analyze_sentiment(request: SentimentRequest): |
|
|
""" |
|
|
Analyze REAL sentiment using AI models |
|
|
NO FAKE ANALYSIS |
|
|
""" |
|
|
try: |
|
|
|
|
|
model_map = { |
|
|
"crypto": "sentiment_crypto", |
|
|
"financial": "sentiment_financial", |
|
|
"social": "sentiment_twitter", |
|
|
"auto": "sentiment_crypto" |
|
|
} |
|
|
|
|
|
model_key = model_map.get(request.mode, "sentiment_crypto") |
|
|
|
|
|
result = await ai_registry.predict_sentiment( |
|
|
text=request.text, |
|
|
model_key=model_key |
|
|
) |
|
|
|
|
|
return result |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"β Sentiment analysis failed: {e}") |
|
|
raise HTTPException( |
|
|
status_code=500, |
|
|
detail=f"Real sentiment analysis failed: {str(e)}" |
|
|
) |
|
|
|
|
|
|
|
|
@router.post("/api/ai/generate") |
|
|
async def generate_ai_text( |
|
|
prompt: str = Body(..., embed=True), |
|
|
max_length: int = Body(200, embed=True) |
|
|
): |
|
|
""" |
|
|
Generate REAL text using AI models |
|
|
NO FAKE GENERATION |
|
|
""" |
|
|
try: |
|
|
result = await ai_registry.generate_text( |
|
|
prompt=prompt, |
|
|
max_length=max_length |
|
|
) |
|
|
|
|
|
return result |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"β AI text generation failed: {e}") |
|
|
raise HTTPException( |
|
|
status_code=500, |
|
|
detail=f"Real AI generation failed: {str(e)}" |
|
|
) |
|
|
|
|
|
|
|
|
@router.post("/api/trading/signal") |
|
|
async def get_trading_signal( |
|
|
symbol: str = Body(..., embed=True), |
|
|
context: Optional[str] = Body(None, embed=True) |
|
|
): |
|
|
""" |
|
|
Get REAL trading signal from AI model |
|
|
NO FAKE SIGNALS |
|
|
""" |
|
|
try: |
|
|
result = await ai_registry.get_trading_signal( |
|
|
symbol=symbol, |
|
|
context=context |
|
|
) |
|
|
|
|
|
return result |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"β Trading signal failed: {e}") |
|
|
raise HTTPException( |
|
|
status_code=500, |
|
|
detail=f"Real trading signal failed: {str(e)}" |
|
|
) |
|
|
|
|
|
|
|
|
@router.post("/api/news/summarize") |
|
|
async def summarize_news_article( |
|
|
text: str = Body(..., embed=True) |
|
|
): |
|
|
""" |
|
|
Summarize REAL news using AI |
|
|
NO FAKE SUMMARIES |
|
|
""" |
|
|
try: |
|
|
result = await ai_registry.summarize_news(text=text) |
|
|
|
|
|
return result |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"β News summarization failed: {e}") |
|
|
raise HTTPException( |
|
|
status_code=500, |
|
|
detail=f"Real summarization failed: {str(e)}" |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
__all__ = ["router"] |
|
|
|