Really-amin commited on
Commit
650bbdc
·
verified ·
1 Parent(s): eebf5c4

Upload 317 files

Browse files
config.py CHANGED
@@ -192,3 +192,8 @@ SUCCESS_MESSAGES = {
192
  "cache_cleared": "Cache cleared successfully.",
193
  "database_initialized": "Database initialized successfully.",
194
  }
 
 
 
 
 
 
192
  "cache_cleared": "Cache cleared successfully.",
193
  "database_initialized": "Database initialized successfully.",
194
  }
195
+
196
+ # Backward-compatible alias so that `from config import config`
197
+ # returns the config module itself.
198
+ import sys as _sys
199
+ config = _sys.modules[__name__]
hf-data-engine/.dockerignore CHANGED
@@ -4,6 +4,9 @@ __pycache__/
4
  *$py.class
5
  *.so
6
  .Python
 
 
 
7
  build/
8
  develop-eggs/
9
  dist/
@@ -19,15 +22,10 @@ wheels/
19
  *.egg-info/
20
  .installed.cfg
21
  *.egg
22
- MANIFEST
23
- pip-log.txt
24
- pip-delete-this-directory.txt
25
 
26
- # Virtual environments
27
- venv/
28
- ENV/
29
- env/
30
- .venv
31
 
32
  # IDE
33
  .vscode/
@@ -35,87 +33,19 @@ env/
35
  *.swp
36
  *.swo
37
  *~
38
- .DS_Store
 
 
 
 
39
 
40
  # Git
41
  .git/
42
  .gitignore
43
- .gitattributes
44
 
45
  # Documentation
46
  *.md
47
  docs/
48
- README*.md
49
- CHANGELOG.md
50
- LICENSE
51
 
52
- # Testing
53
- .pytest_cache/
54
- .coverage
55
- htmlcov/
56
- .tox/
57
- .hypothesis/
58
- tests/
59
- test_*.py
60
-
61
- # Logs and databases (will be created in container)
62
  *.log
63
- logs/
64
- data/*.db
65
- data/*.sqlite
66
- data/*.db-journal
67
-
68
- # Environment files (should be set via docker-compose or HF Secrets)
69
- .env
70
- .env.*
71
- !.env.example
72
-
73
- # Docker
74
- docker-compose*.yml
75
- !docker-compose.yml
76
- Dockerfile
77
- .dockerignore
78
-
79
- # CI/CD
80
- .github/
81
- .gitlab-ci.yml
82
- .travis.yml
83
- azure-pipelines.yml
84
-
85
- # Temporary files
86
- *.tmp
87
- *.bak
88
- *.swp
89
- temp/
90
- tmp/
91
-
92
- # Node modules (if any)
93
- node_modules/
94
- package-lock.json
95
- yarn.lock
96
-
97
- # OS files
98
- Thumbs.db
99
- .DS_Store
100
- desktop.ini
101
-
102
- # Jupyter notebooks
103
- .ipynb_checkpoints/
104
- *.ipynb
105
-
106
- # Model cache (models will be downloaded in container)
107
- models/
108
- .cache/
109
- .huggingface/
110
-
111
- # Large files that shouldn't be in image
112
- *.tar
113
- *.tar.gz
114
- *.zip
115
- *.rar
116
- *.7z
117
-
118
- # Screenshots and assets not needed
119
- screenshots/
120
- assets/*.png
121
- assets/*.jpg
 
4
  *$py.class
5
  *.so
6
  .Python
7
+ env/
8
+ venv/
9
+ ENV/
10
  build/
11
  develop-eggs/
12
  dist/
 
22
  *.egg-info/
23
  .installed.cfg
24
  *.egg
 
 
 
25
 
26
+ # Environment
27
+ .env
28
+ .env.local
 
 
29
 
30
  # IDE
31
  .vscode/
 
33
  *.swp
34
  *.swo
35
  *~
36
+
37
+ # Tests
38
+ .pytest_cache/
39
+ .coverage
40
+ htmlcov/
41
 
42
  # Git
43
  .git/
44
  .gitignore
 
45
 
46
  # Documentation
47
  *.md
48
  docs/
 
 
 
49
 
50
+ # Logs
 
 
 
 
 
 
 
 
 
51
  *.log
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
hf-data-engine/.env.example CHANGED
@@ -1,17 +1,47 @@
1
- # HuggingFace Configuration
2
- HUGGINGFACE_TOKEN=your_token_here
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  ENABLE_SENTIMENT=true
4
- SENTIMENT_SOCIAL_MODEL=ElKulako/cryptobert
5
- SENTIMENT_NEWS_MODEL=kk08/CryptoBERT
6
- HF_REGISTRY_REFRESH_SEC=21600
7
- HF_HTTP_TIMEOUT=8.0
8
-
9
- # Existing API Keys (if any)
10
- ETHERSCAN_KEY_1=
11
- ETHERSCAN_KEY_2=
12
- BSCSCAN_KEY=
13
- TRONSCAN_KEY=
14
- COINMARKETCAP_KEY_1=
15
- COINMARKETCAP_KEY_2=
16
- NEWSAPI_KEY=
17
- CRYPTOCOMPARE_KEY=
 
1
+ # Server Configuration
2
+ HOST=0.0.0.0
3
+ PORT=8000
4
+ ENV=production
5
+ VERSION=1.0.0
6
+
7
+ # Cache Configuration
8
+ CACHE_TYPE=memory
9
+ CACHE_TTL_PRICES=30
10
+ CACHE_TTL_OHLCV=300
11
+ CACHE_TTL_SENTIMENT=600
12
+ CACHE_TTL_MARKET=300
13
+
14
+ # Redis (if using Redis cache)
15
+ # REDIS_URL=redis://localhost:6379
16
+
17
+ # Rate Limiting
18
+ RATE_LIMIT_ENABLED=true
19
+ RATE_LIMIT_PRICES=120
20
+ RATE_LIMIT_OHLCV=60
21
+ RATE_LIMIT_SENTIMENT=30
22
+ RATE_LIMIT_HEALTH=0
23
+
24
+ # Optional API Keys (for higher rate limits)
25
+ # BINANCE_API_KEY=
26
+ # BINANCE_API_SECRET=
27
+ # COINGECKO_API_KEY=
28
+ # CRYPTOCOMPARE_API_KEY=
29
+ # CRYPTOPANIC_API_KEY=
30
+ # NEWSAPI_KEY=
31
+
32
+ # Features
33
  ENABLE_SENTIMENT=true
34
+ ENABLE_NEWS=false
35
+
36
+ # Circuit Breaker
37
+ CIRCUIT_BREAKER_THRESHOLD=5
38
+ CIRCUIT_BREAKER_TIMEOUT=60
39
+
40
+ # Request Timeouts
41
+ REQUEST_TIMEOUT=10
42
+
43
+ # Supported Symbols (comma-separated)
44
+ SUPPORTED_SYMBOLS=BTC,ETH,SOL,XRP,BNB,ADA,DOT,LINK,LTC,BCH,MATIC,AVAX,XLM,TRX
45
+
46
+ # Supported Intervals (comma-separated)
47
+ SUPPORTED_INTERVALS=1m,5m,15m,1h,4h,1d,1w
hf-data-engine/.gitignore CHANGED
@@ -4,6 +4,9 @@ __pycache__/
4
  *$py.class
5
  *.so
6
  .Python
 
 
 
7
  build/
8
  develop-eggs/
9
  dist/
@@ -20,29 +23,25 @@ wheels/
20
  .installed.cfg
21
  *.egg
22
 
23
- # Virtual environments
24
- venv/
25
- ENV/
26
- env/
27
 
28
  # IDE
29
  .vscode/
30
  .idea/
31
  *.swp
32
  *.swo
 
33
 
34
- # Data
35
- data/*.db
36
- data/*.db-journal
37
- data/exports/
38
- crypto_monitor.db
39
- crypto_monitor.db-journal
40
-
41
- # Environment
42
- .env
43
 
44
  # Logs
45
  *.log
 
46
 
47
  # OS
48
  .DS_Store
 
4
  *$py.class
5
  *.so
6
  .Python
7
+ env/
8
+ venv/
9
+ ENV/
10
  build/
11
  develop-eggs/
12
  dist/
 
23
  .installed.cfg
24
  *.egg
25
 
26
+ # Environment
27
+ .env
28
+ .env.local
 
29
 
30
  # IDE
31
  .vscode/
32
  .idea/
33
  *.swp
34
  *.swo
35
+ *~
36
 
37
+ # Tests
38
+ .pytest_cache/
39
+ .coverage
40
+ htmlcov/
 
 
 
 
 
41
 
42
  # Logs
43
  *.log
44
+ logs/
45
 
46
  # OS
47
  .DS_Store
hf-data-engine/Dockerfile CHANGED
@@ -1,41 +1,20 @@
1
- # Use Python 3.11 Slim base image
2
  FROM python:3.11-slim
3
 
4
- # Set environment variables
5
- ENV PYTHONUNBUFFERED=1 \
6
- PYTHONDONTWRITEBYTECODE=1 \
7
- PIP_NO_CACHE_DIR=1 \
8
- PIP_DISABLE_PIP_VERSION_CHECK=1 \
9
- ENABLE_AUTO_DISCOVERY=false
10
-
11
- # Install system dependencies
12
- RUN apt-get update && apt-get install -y \
13
- gcc \
14
- g++ \
15
- curl \
16
- && rm -rf /var/lib/apt/lists/*
17
-
18
- # Set working directory
19
  WORKDIR /app
20
 
21
- # Copy dependency files
22
  COPY requirements.txt .
23
-
24
- # Install Python dependencies
25
  RUN pip install --no-cache-dir -r requirements.txt
26
 
27
  # Copy application code
28
  COPY . .
29
 
30
- # Create necessary directories
31
- RUN mkdir -p logs data data/exports data/backups
32
-
33
- # Expose ports (Hugging Face uses PORT env variable, default 7860)
34
- EXPOSE 7860 8000
35
 
36
- # Health check (simplified to avoid requests dependency in healthcheck)
37
- HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
38
- CMD curl -f http://localhost:${PORT:-8000}/health || exit 1
39
 
40
- # Run server with uvicorn (supports Hugging Face PORT env variable)
41
- CMD ["sh", "-c", "uvicorn api_server_extended:app --host 0.0.0.0 --port ${PORT:-8000}"]
 
 
1
  FROM python:3.11-slim
2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  WORKDIR /app
4
 
5
+ # Install dependencies
6
  COPY requirements.txt .
 
 
7
  RUN pip install --no-cache-dir -r requirements.txt
8
 
9
  # Copy application code
10
  COPY . .
11
 
12
+ # Expose port
13
+ EXPOSE 8000
 
 
 
14
 
15
+ # Health check
16
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
17
+ CMD python -c "import httpx; httpx.get('http://localhost:8000/api/health', timeout=5)"
18
 
19
+ # Run the application
20
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
hf-data-engine/main.py CHANGED
@@ -1,30 +1,326 @@
1
- #!/usr/bin/env python3
2
- """
3
- Local Development Entry Point
4
- This file is for local development only and is NOT used by Hugging Face Docker runtime.
5
- For production deployment, use: uvicorn api_server_extended:app
6
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
  if __name__ == "__main__":
9
  import uvicorn
10
- import os
11
-
12
- # Get port from environment or use default
13
- port = int(os.getenv("PORT", "8000"))
14
-
15
- print(f"""
16
- ╔═══════════════════════════════════════════════════════════╗
17
- ║ 🚀 Crypto Monitor - Local Development Server ║
18
- ║ Port: {port} ║
19
- ║ Docs: http://localhost:{port}/docs ║
20
- ╚═══════════════════════════════════════════════════════════╝
21
- """)
22
-
23
- # Run with reload for local development
24
  uvicorn.run(
25
- "api_server_extended:app",
26
- host="0.0.0.0",
27
- port=port,
28
- reload=True,
29
  log_level="info"
30
  )
 
1
+ """HuggingFace Cryptocurrency Data Engine - Main Application"""
2
+ from __future__ import annotations
3
+ import time
4
+ import logging
5
+ from contextlib import asynccontextmanager
6
+ from fastapi import FastAPI, HTTPException, Query, Request
7
+ from fastapi.middleware.cors import CORSMiddleware
8
+ from fastapi.responses import JSONResponse
9
+ from slowapi import Limiter, _rate_limit_exceeded_handler
10
+ from slowapi.util import get_remote_address
11
+ from slowapi.errors import RateLimitExceeded
12
+
13
+ from core.config import settings, get_supported_symbols, get_supported_intervals
14
+ from core.aggregator import get_aggregator
15
+ from core.cache import cache, cache_key, get_or_set
16
+ from core.models import (
17
+ OHLCVResponse, PricesResponse, SentimentResponse,
18
+ MarketOverviewResponse, HealthResponse, ErrorResponse, ErrorDetail, CacheInfo
19
+ )
20
+
21
+ # Configure logging
22
+ logging.basicConfig(
23
+ level=logging.INFO,
24
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
25
+ )
26
+ logger = logging.getLogger(__name__)
27
+
28
+
29
+ # Rate limiter
30
+ limiter = Limiter(key_func=get_remote_address)
31
+
32
+
33
+ @asynccontextmanager
34
+ async def lifespan(app: FastAPI):
35
+ """Lifecycle manager for the application"""
36
+ logger.info("Starting HuggingFace Crypto Data Engine...")
37
+ logger.info(f"Version: {settings.VERSION}")
38
+ logger.info(f"Environment: {settings.ENV}")
39
+
40
+ # Initialize aggregator
41
+ aggregator = get_aggregator()
42
+
43
+ yield
44
+
45
+ # Cleanup
46
+ logger.info("Shutting down...")
47
+ await aggregator.close()
48
+
49
+
50
+ # Create FastAPI app
51
+ app = FastAPI(
52
+ title="HuggingFace Cryptocurrency Data Engine",
53
+ description="Comprehensive cryptocurrency data aggregator with multi-provider support",
54
+ version=settings.VERSION,
55
+ lifespan=lifespan
56
+ )
57
+
58
+ # Add rate limiter
59
+ app.state.limiter = limiter
60
+ app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
61
+
62
+ # CORS middleware
63
+ app.add_middleware(
64
+ CORSMiddleware,
65
+ allow_origins=["*"],
66
+ allow_credentials=True,
67
+ allow_methods=["*"],
68
+ allow_headers=["*"],
69
+ )
70
+
71
+
72
+ @app.exception_handler(Exception)
73
+ async def global_exception_handler(request: Request, exc: Exception):
74
+ """Global exception handler"""
75
+ logger.error(f"Unhandled exception: {exc}", exc_info=True)
76
+
77
+ return JSONResponse(
78
+ status_code=500,
79
+ content=ErrorResponse(
80
+ error=ErrorDetail(
81
+ code="INTERNAL_ERROR",
82
+ message=str(exc)
83
+ ),
84
+ timestamp=int(time.time() * 1000)
85
+ ).dict()
86
+ )
87
+
88
+
89
+ @app.get("/")
90
+ async def root():
91
+ """Root endpoint"""
92
+ return {
93
+ "service": "HuggingFace Cryptocurrency Data Engine",
94
+ "version": settings.VERSION,
95
+ "status": "online",
96
+ "endpoints": {
97
+ "health": "/api/health",
98
+ "ohlcv": "/api/ohlcv",
99
+ "prices": "/api/prices",
100
+ "sentiment": "/api/sentiment",
101
+ "market": "/api/market/overview",
102
+ "docs": "/docs"
103
+ }
104
+ }
105
+
106
+
107
+ @app.get("/api/health", response_model=HealthResponse)
108
+ @limiter.limit(f"{settings.RATE_LIMIT_HEALTH or 999999}/minute")
109
+ async def health_check(request: Request):
110
+ """Health check endpoint with provider status"""
111
+ aggregator = get_aggregator()
112
+
113
+ # Get provider health
114
+ providers = await aggregator.get_all_provider_health()
115
+
116
+ # Determine overall status
117
+ online_count = sum(1 for p in providers if p.status == "online")
118
+ if online_count == 0:
119
+ overall_status = "unhealthy"
120
+ elif online_count < len(providers) / 2:
121
+ overall_status = "degraded"
122
+ else:
123
+ overall_status = "healthy"
124
+
125
+ # Get cache stats
126
+ cache_stats = cache.get_stats()
127
+
128
+ return HealthResponse(
129
+ status=overall_status,
130
+ uptime=aggregator.get_uptime(),
131
+ version=settings.VERSION,
132
+ providers=providers,
133
+ cache=CacheInfo(**cache_stats)
134
+ )
135
+
136
+
137
+ @app.get("/api/ohlcv", response_model=OHLCVResponse)
138
+ @limiter.limit(f"{settings.RATE_LIMIT_OHLCV}/minute")
139
+ async def get_ohlcv(
140
+ request: Request,
141
+ symbol: str = Query(..., description="Symbol (e.g., BTC, BTCUSDT, BTC/USDT)"),
142
+ interval: str = Query("1h", description="Interval (1m, 5m, 15m, 1h, 4h, 1d, 1w)"),
143
+ limit: int = Query(100, ge=1, le=1000, description="Number of candles (1-1000)")
144
+ ):
145
+ """Get OHLCV candlestick data with multi-provider fallback"""
146
+
147
+ # Validate interval
148
+ if interval not in get_supported_intervals():
149
+ raise HTTPException(
150
+ status_code=400,
151
+ detail=f"Invalid interval. Supported: {', '.join(get_supported_intervals())}"
152
+ )
153
+
154
+ # Normalize symbol
155
+ normalized_symbol = symbol.upper().replace("/", "").replace("-", "")
156
+
157
+ # Generate cache key
158
+ key = cache_key("ohlcv", symbol=normalized_symbol, interval=interval, limit=limit)
159
+
160
+ async def fetch():
161
+ aggregator = get_aggregator()
162
+ data, source = await aggregator.fetch_ohlcv(normalized_symbol, interval, limit)
163
+ return {"data": data, "source": source}
164
+
165
+ try:
166
+ # Get from cache or fetch
167
+ result = await get_or_set(key, settings.CACHE_TTL_OHLCV, fetch)
168
+
169
+ return OHLCVResponse(
170
+ data=result["data"],
171
+ symbol=normalized_symbol,
172
+ interval=interval,
173
+ count=len(result["data"]),
174
+ source=result["source"],
175
+ timestamp=int(time.time() * 1000)
176
+ )
177
+
178
+ except Exception as e:
179
+ logger.error(f"OHLCV fetch failed: {e}")
180
+ raise HTTPException(
181
+ status_code=503,
182
+ detail=ErrorDetail(
183
+ code="PROVIDER_ERROR",
184
+ message=f"All data providers failed: {str(e)}"
185
+ ).dict()
186
+ )
187
+
188
+
189
+ @app.get("/api/prices", response_model=PricesResponse)
190
+ @limiter.limit(f"{settings.RATE_LIMIT_PRICES}/minute")
191
+ async def get_prices(
192
+ request: Request,
193
+ symbols: str = Query(None, description="Comma-separated symbols (e.g., BTC,ETH,SOL)"),
194
+ convert: str = Query("USDT", description="Convert to currency (USD, USDT)")
195
+ ):
196
+ """Get real-time prices with multi-provider aggregation"""
197
+
198
+ # Parse symbols
199
+ if symbols:
200
+ symbol_list = [s.strip().upper() for s in symbols.split(",")]
201
+ else:
202
+ # Use default symbols
203
+ symbol_list = get_supported_symbols()
204
+
205
+ # Generate cache key
206
+ key = cache_key("prices", symbols=",".join(sorted(symbol_list)))
207
+
208
+ async def fetch():
209
+ aggregator = get_aggregator()
210
+ data, source = await aggregator.fetch_prices(symbol_list)
211
+ return {"data": data, "source": source}
212
+
213
+ try:
214
+ # Get from cache or fetch
215
+ result = await get_or_set(key, settings.CACHE_TTL_PRICES, fetch)
216
+
217
+ return PricesResponse(
218
+ data=result["data"],
219
+ timestamp=int(time.time() * 1000),
220
+ source=result["source"]
221
+ )
222
+
223
+ except Exception as e:
224
+ logger.error(f"Price fetch failed: {e}")
225
+ raise HTTPException(
226
+ status_code=503,
227
+ detail=ErrorDetail(
228
+ code="PROVIDER_ERROR",
229
+ message=f"All price providers failed: {str(e)}"
230
+ ).dict()
231
+ )
232
+
233
+
234
+ @app.get("/api/sentiment", response_model=SentimentResponse)
235
+ @limiter.limit(f"{settings.RATE_LIMIT_SENTIMENT}/minute")
236
+ async def get_sentiment(request: Request):
237
+ """Get market sentiment data (Fear & Greed Index)"""
238
+
239
+ if not settings.ENABLE_SENTIMENT:
240
+ raise HTTPException(
241
+ status_code=503,
242
+ detail="Sentiment analysis is disabled"
243
+ )
244
+
245
+ # Cache key
246
+ key = cache_key("sentiment")
247
+
248
+ async def fetch():
249
+ aggregator = get_aggregator()
250
+ return await aggregator.fetch_sentiment()
251
+
252
+ try:
253
+ # Get from cache or fetch
254
+ data = await get_or_set(key, settings.CACHE_TTL_SENTIMENT, fetch)
255
+
256
+ return SentimentResponse(
257
+ data=data,
258
+ timestamp=int(time.time() * 1000)
259
+ )
260
+
261
+ except Exception as e:
262
+ logger.error(f"Sentiment fetch failed: {e}")
263
+ raise HTTPException(
264
+ status_code=503,
265
+ detail=ErrorDetail(
266
+ code="PROVIDER_ERROR",
267
+ message=f"Failed to fetch sentiment: {str(e)}"
268
+ ).dict()
269
+ )
270
+
271
+
272
+ @app.get("/api/market/overview", response_model=MarketOverviewResponse)
273
+ @limiter.limit(f"{settings.RATE_LIMIT_SENTIMENT}/minute")
274
+ async def get_market_overview(request: Request):
275
+ """Get market overview with global statistics"""
276
+
277
+ # Cache key
278
+ key = cache_key("market_overview")
279
+
280
+ async def fetch():
281
+ aggregator = get_aggregator()
282
+ return await aggregator.fetch_market_overview()
283
+
284
+ try:
285
+ # Get from cache or fetch
286
+ data = await get_or_set(key, settings.CACHE_TTL_MARKET, fetch)
287
+
288
+ return MarketOverviewResponse(
289
+ data=data,
290
+ timestamp=int(time.time() * 1000)
291
+ )
292
+
293
+ except Exception as e:
294
+ logger.error(f"Market overview fetch failed: {e}")
295
+ raise HTTPException(
296
+ status_code=503,
297
+ detail=ErrorDetail(
298
+ code="PROVIDER_ERROR",
299
+ message=f"Failed to fetch market overview: {str(e)}"
300
+ ).dict()
301
+ )
302
+
303
+
304
+ @app.post("/api/cache/clear")
305
+ async def clear_cache():
306
+ """Clear all cached data"""
307
+ cache.clear()
308
+ return {"success": True, "message": "Cache cleared"}
309
+
310
+
311
+ @app.get("/api/cache/stats")
312
+ async def cache_stats():
313
+ """Get cache statistics"""
314
+ return cache.get_stats()
315
+
316
 
317
  if __name__ == "__main__":
318
  import uvicorn
319
+
 
 
 
 
 
 
 
 
 
 
 
 
 
320
  uvicorn.run(
321
+ "main:app",
322
+ host=settings.HOST,
323
+ port=settings.PORT,
324
+ reload=(settings.ENV == "development"),
325
  log_level="info"
326
  )
hf-data-engine/requirements.txt CHANGED
@@ -1,58 +1,18 @@
1
- # Crypto Data Aggregator - Complete Requirements
2
- # Production-ready dependencies with exact versions
 
 
 
3
 
4
- # ==================== GRADIO INTERFACE ====================
5
- gradio>=4.44.0
6
 
7
- # ==================== DATA PROCESSING ====================
8
- pandas>=2.0.0
9
- numpy>=1.24.0
10
 
11
- # ==================== HTTP CLIENTS ====================
12
- requests>=2.31.0
13
- aiohttp>=3.8.0
14
- httpx>=0.26.0
15
 
16
- # ==================== WEB BACKEND ====================
17
- fastapi>=0.109.0
18
- uvicorn[standard]>=0.27.0
19
- slowapi>=0.1.9
20
- python-multipart>=0.0.6
21
- websockets>=12.0
22
-
23
- # ==================== DATA MODELS & CONFIG ====================
24
- pydantic>=2.5.3
25
- pydantic-settings>=2.1.0
26
-
27
- # ==================== WEB SCRAPING & RSS ====================
28
- beautifulsoup4>=4.12.0
29
- feedparser>=6.0.10
30
-
31
- # ==================== AI/ML - HUGGING FACE ====================
32
- transformers>=4.30.0
33
- torch>=2.0.0
34
- sentencepiece>=0.1.99
35
- tokenizers>=0.13.0
36
- huggingface-hub>=0.16.0
37
-
38
- # ==================== PLOTTING & VISUALIZATION ====================
39
- plotly>=5.14.0
40
- kaleido>=0.2.1
41
-
42
- # ==================== DATABASE & STORAGE ====================
43
- sqlalchemy>=2.0.25
44
-
45
- # ==================== AUTHENTICATION & SECURITY ====================
46
- PyJWT>=2.8.0
47
-
48
- # ==================== DATE/TIME HELPERS ====================
49
- python-dateutil>=2.8.2
50
-
51
- # ==================== OPTIONAL: ACCELERATED INFERENCE ====================
52
- # accelerate>=0.20.0 # Uncomment for faster model loading
53
- # bitsandbytes>=0.39.0 # Uncomment for quantization
54
-
55
- # ==================== NOTES ====================
56
- # No API keys required - all data sources are free
57
- # SQLite is included in Python standard library
58
- # All packages are production-tested and stable
 
1
+ # FastAPI and server
2
+ fastapi==0.109.0
3
+ uvicorn[standard]==0.27.0
4
+ pydantic==2.5.3
5
+ pydantic-settings==2.1.0
6
 
7
+ # HTTP client
8
+ httpx==0.26.0
9
 
10
+ # Rate limiting
11
+ slowapi==0.1.9
 
12
 
13
+ # Optional: Redis support (uncomment if using Redis)
14
+ # redis==5.0.1
15
+ # aioredis==2.0.1
 
16
 
17
+ # Utilities
18
+ python-dotenv==1.0.0