tomiris-executor/Final_last_bablo
0
1# ============================================2# АВТО-УСТАНОВКА ПАКЕТОВ3# ============================================4import subprocess, sys, importlib5 6REQUIRED_PACKAGES = {7 'numpy': 'numpy',8 'httpx': 'httpx',9 'fastapi': 'fastapi',10 'uvicorn': 'uvicorn',11 'requests': 'requests'12}13 14for module_name, pip_name in REQUIRED_PACKAGES.items():15 try:16 importlib.import_module(module_name)17 except ImportError:18 print(f"📦 Устанавливаю {pip_name}...")19 subprocess.check_call([sys.executable, "-m", "pip", "install", pip_name])20 print(f"✅ {pip_name} установлен!")21 22# ============================================23# 👑 TOMIRIS SPACE 24 v3.1 — ECOSYSTEM AGGREGATOR PRO24# ============================================25import os, time, json, logging, asyncio26from typing import Dict, Any, List, Optional27from datetime import datetime, timezone28from collections import deque29import numpy as np30import httpx31from fastapi import FastAPI, Query32 33logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")34logger = logging.getLogger("Space24_Ecosystem")35 36# ================= КОНФИГУРАЦИЯ =================37SPACE_ID = 2438SPACE_NAME = "Ecosystem Aggregator"39SYMBOLS = ["XAU/USD", "ETH/USD", "SOL/USD"]40 41HUB_URL = "https://TOMI-HUB-HUB-FINAL.hf.space"42HUB_SECRET = os.getenv("HUB_SECRET", "TomyrisUltraSecret2026!")43 44STARTUP_SLEEP = int(os.getenv("STARTUP_SLEEP", "120")) # 2 минуты45AUTO_SEND_INTERVAL = int(os.getenv("AUTO_SEND_INTERVAL", "300")) # 5 минут46 47logger.info(f"🔗 Хаб: {HUB_URL} | Старт: {STARTUP_SLEEP}с | Интервал: {AUTO_SEND_INTERVAL}с")48 49# ================= HTTP КЛИЕНТ =================50http_client = httpx.AsyncClient(timeout=15.0)51 52def hub_headers():53 return {"X-Hub-Secret": HUB_SECRET, "Content-Type": "application/json"}54 55# ================= ЛОГГЕР В ХАБ =================56async def log_to_hub(event_type: str, message: str, details: dict = None):57 try:58 await http_client.post(59 f"{HUB_URL}/log",60 json={61 "space_id": str(SPACE_ID),62 "event_type": event_type,63 "message": message,64 "details": details or {}65 },66 headers=hub_headers(),67 timeout=568 )69 except: pass70 71# ================= ECOSYSTEM SPACES (по space_id) =================72ECOSYSTEM_SPACES = {73 "19": {74 "weight": 0.25,75 "symbols": ["SOL/USD"],76 "description": "SOL Master",77 "cache_ttl": 30078 },79 "20": {80 "weight": 0.25,81 "symbols": ["ETH/USD"],82 "description": "L2 & DeFi Pulse",83 "cache_ttl": 30084 },85 "21": {86 "weight": 0.25,87 "symbols": ["XAU/USD"],88 "description": "Gold Macro & Flow",89 "cache_ttl": 60090 },91 "22": {92 "weight": 0.15,93 "symbols": ["XAU/USD", "ETH/USD", "SOL/USD"],94 "description": "Cross-Asset Sentiment",95 "cache_ttl": 30096 },97 "23": {98 "weight": 0.10,99 "symbols": ["ETH/USD", "SOL/USD"],100 "description": "On-Chain Anomaly",101 "cache_ttl": 60102 }103}104 105# ================= ГЛОБАЛЬНЫЙ КЭШ =================106cache_store = {}107cache_times = {}108 109# ================= ПОЛУЧЕНИЕ СИГНАЛОВ ЧЕРЕЗ ХАБ =================110async def fetch_space_signal_from_hub(space_id: str, config: Dict, symbol: str) -> Optional[Dict]:111 """Получает последний сигнал Space'а через Хаб (по space_id)"""112 cache_key = f"space_{space_id}_{symbol}"113 ttl = config.get("cache_ttl", 300)114 now = time.time()115 116 if cache_key in cache_store and (now - cache_times.get(cache_key, 0)) < ttl:117 return cache_store[cache_key]118 119 try:120 r = await http_client.get(121 f"{HUB_URL}/signals",122 params={"symbol": symbol, "limit": 100},123 timeout=10,124 headers=hub_headers()125 )126 if r.status_code == 200:127 signals = r.json()128 # Ищем последний сигнал от нужного space_id129 for s in reversed(signals):130 sid = str(s.get("space_id", ""))131 if sid == space_id:132 direction = s.get("direction", s.get("signal", "WAIT"))133 # Нормализуем134 if direction in ("LONG", "BUY"):135 direction = "BUY"136 elif direction in ("SHORT", "SELL"):137 direction = "SELL"138 else:139 direction = "WAIT"140 141 data = {142 "signal": {143 "direction": direction,144 "confidence": float(s.get("confidence", 0))145 }146 }147 cache_store[cache_key] = data148 cache_times[cache_key] = time.time()149 return data150 151 # Не нашли — WAIT152 data = {"signal": {"direction": "WAIT", "confidence": 0.0}}153 cache_store[cache_key] = data154 cache_times[cache_key] = time.time()155 return data156 except Exception as e:157 logger.warning(f"Hub fetch space {space_id}: {e}")158 return {"signal": {"direction": "WAIT", "confidence": 0.0}}159 160# ================= ДИНАМИЧЕСКИЕ ВЕСА =================161async def fetch_dynamic_weights() -> Dict[str, float]:162 try:163 r = await http_client.get(f"{HUB_URL}/weights", timeout=8, headers=hub_headers())164 if r.status_code == 200:165 data = r.json()166 weights = data.get("weights", {})167 if weights:168 return {k: v for k, v in weights.items() if k in ECOSYSTEM_SPACES}169 except:170 pass171 return {space_id: cfg["weight"] for space_id, cfg in ECOSYSTEM_SPACES.items()}172 173# ================= АГРЕГАЦИЯ =================174async def aggregate_ecosystem(symbol: str) -> Dict[str, Any]:175 dynamic_weights = await fetch_dynamic_weights()176 177 tasks = []178 space_ids = []179 for space_id, cfg in ECOSYSTEM_SPACES.items():180 if symbol in cfg["symbols"]:181 tasks.append(fetch_space_signal_from_hub(space_id, cfg, symbol))182 space_ids.append(space_id)183 184 results = await asyncio.gather(*tasks)185 186 signals = {}187 errors = []188 for space_id, res in zip(space_ids, results):189 if res and isinstance(res, dict):190 signals[space_id] = res191 else:192 errors.append(space_id)193 194 total_weight = 0.0195 buy_votes = 0.0196 sell_votes = 0.0197 wait_votes = 0.0198 details = {}199 200 for space_id, data in signals.items():201 weight = dynamic_weights.get(space_id, ECOSYSTEM_SPACES[space_id]["weight"])202 sig = data.get("signal", {})203 direction = sig.get("direction", "WAIT")204 confidence = sig.get("confidence", 0)205 206 if direction == "BUY":207 buy_votes += weight * confidence208 elif direction == "SELL":209 sell_votes += weight * confidence210 else:211 wait_votes += weight * confidence212 213 total_weight += weight214 details[space_id] = {215 "direction": direction,216 "confidence": confidence,217 "weight": weight,218 "status": "active",219 "description": ECOSYSTEM_SPACES[space_id]["description"]220 }221 222 for space_id in errors:223 weight = dynamic_weights.get(space_id, ECOSYSTEM_SPACES[space_id]["weight"])224 details[space_id] = {225 "direction": "ERROR",226 "confidence": 0,227 "weight": weight,228 "status": "error",229 "description": ECOSYSTEM_SPACES[space_id]["description"]230 }231 232 if total_weight == 0:233 return {234 "ecosystem_score": 50.0,235 "direction": "WAIT",236 "confidence": 0.0,237 "active_spaces": 0,238 "error_spaces": len(errors),239 "signals_detail": details240 }241 242 bias = (buy_votes - sell_votes) / total_weight243 ecosystem_score = 50.0 + bias * 50.0244 ecosystem_score = max(0, min(100, ecosystem_score))245 246 wait_ratio = wait_votes / total_weight247 248 if wait_ratio > 0.6:249 direction = "WAIT"250 confidence = wait_ratio251 elif buy_votes > sell_votes * 1.3:252 direction = "BUY"253 confidence = min(0.9, buy_votes / total_weight)254 elif sell_votes > buy_votes * 1.3:255 direction = "SELL"256 confidence = min(0.9, sell_votes / total_weight)257 else:258 direction = "WAIT"259 confidence = max(buy_votes, sell_votes) / total_weight260 261 active_ratio = len(signals) / len(space_ids) if space_ids else 0262 confidence *= 0.5 + 0.5 * active_ratio263 264 return {265 "ecosystem_score": round(ecosystem_score, 2),266 "direction": direction,267 "confidence": round(confidence, 4),268 "active_spaces": len(signals),269 "error_spaces": len(errors),270 "signals_detail": details,271 "votes": {272 "BUY": round(buy_votes, 4),273 "SELL": round(sell_votes, 4),274 "WAIT": round(wait_votes, 4)275 }276 }277 278# ================= ОТПРАВКА В HUB =================279async def send_signal_to_hub(symbol: str, signal: str, confidence: float, features: Dict = None):280 if features is None:281 features = {}282 283 payload = {284 "space_id": SPACE_ID,285 "space_name": SPACE_NAME,286 "symbol": symbol,287 "signal": signal,288 "confidence": round(confidence, 4),289 "features": features,290 "metadata": {"version": "3.1"},291 "timestamp": datetime.now(timezone.utc).isoformat()292 }293 294 for attempt in range(3):295 try:296 r = await http_client.post(f"{HUB_URL}/signals", json=payload, timeout=15, headers=hub_headers())297 if r.status_code == 200:298 logger.info(f"📤 {symbol}: {signal} conf={confidence:.3f}")299 return True300 await asyncio.sleep(2)301 except Exception as e:302 logger.warning(f"Попытка {attempt+1}: {e}")303 await asyncio.sleep(2)304 305 logger.error(f"❌ Не удалось отправить {symbol}")306 return False307 308# ================= ГЛАВНЫЙ СИГНАЛ =================309async def get_ecosystem_aggregate(symbol: str = "XAU/USD") -> Dict[str, Any]:310 start = time.time()311 agg = await aggregate_ecosystem(symbol)312 latency = int((time.time() - start) * 1000)313 314 signal = agg['direction']315 confidence = agg['confidence']316 317 features = {318 "ecosystem_score": agg['ecosystem_score'],319 "active_spaces": agg['active_spaces'],320 "votes": agg['votes']321 }322 323 await send_signal_to_hub(symbol, signal, confidence, features)324 325 logger.info(f"🌐 Ecosystem {symbol}: {signal} conf={confidence:.3f} score={agg['ecosystem_score']} | {latency}ms")326 327 return {328 "space_id": SPACE_ID,329 "timestamp": int(time.time()),330 "symbol": symbol,331 "signal": signal,332 "confidence": confidence,333 "ecosystem_analysis": agg,334 "latency_ms": latency335 }336 337# ================= АВТО-ОТПРАВКА =================338async def auto_send_loop():339 logger.info(f"⏳ Стартовый сон {STARTUP_SLEEP}с...")340 await log_to_hub("STARTUP", f"Ecosystem Aggregator v3.1 запущен, жду {STARTUP_SLEEP}с")341 await asyncio.sleep(STARTUP_SLEEP)342 logger.info(f"🔄 Авто-отправка (интервал {AUTO_SEND_INTERVAL}с)")343 344 while True:345 try:346 for symbol in SYMBOLS:347 await get_ecosystem_aggregate(symbol)348 await asyncio.sleep(2)349 logger.info("✅ Ecosystem цикл завершён")350 except Exception as e:351 logger.error(f"Ошибка: {e}")352 await log_to_hub("ERROR", f"Ошибка: {str(e)[:200]}")353 await asyncio.sleep(AUTO_SEND_INTERVAL)354 355# ================= FASTAPI =================356app = FastAPI(title="Tomiris Space 24 v3.1 — Ecosystem Aggregator Pro")357 358@app.on_event("startup")359async def startup():360 asyncio.create_task(auto_send_loop())361 logger.info(f"🚀 Space 24 v3.1 запущен | Hub: {HUB_URL}")362 363@app.on_event("shutdown")364async def shutdown():365 await http_client.aclose()366 367@app.get("/health")368async def health():369 return {"space_id": SPACE_ID, "status": "operational", "version": "3.1", "ecosystem_spaces": len(ECOSYSTEM_SPACES)}370 371@app.get("/consilium")372async def consilium(symbol: str = Query("XAU/USD")):373 if symbol not in SYMBOLS:374 return {"error": "Invalid symbol"}375 return await get_ecosystem_aggregate(symbol)376 377@app.get("/breakdown/{symbol}")378async def breakdown(symbol: str):379 agg = await aggregate_ecosystem(symbol)380 return {"symbol": symbol, "aggregate": agg}381 382@app.get("/all")383async def all_signals():384 results = {}385 for sym in SYMBOLS:386 results[sym] = await aggregate_ecosystem(sym)387 return results388 389@app.get("/send_now")390async def send_now():391 results = {}392 for symbol in SYMBOLS:393 sig = await get_ecosystem_aggregate(symbol)394 results[symbol] = sig.get("signal", "WAIT")395 return {"status": "sent", "results": results}396 397@app.get("/")398async def root():399 return {"name": "Ecosystem Aggregator v3.1", "space_id": SPACE_ID, "hub": HUB_URL}400 401if __name__ == "__main__":402 import uvicorn403 uvicorn.run(app, host="0.0.0.0", port=7860)404 405print("🚀 SPACE 24 v3.1 — ECOSYSTEM AGGREGATOR PRO ЗАПУЩЕН!")