Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -21,7 +21,9 @@ for module_name, pip_name in REQUIRED_PACKAGES.items():
|
|
| 21 |
print(f"✅ {pip_name} установлен!")
|
| 22 |
|
| 23 |
# ============================================
|
| 24 |
-
# 👑 TOMIRIS SPACE 26
|
|
|
|
|
|
|
| 25 |
# ============================================
|
| 26 |
import os, time, json, logging, asyncio
|
| 27 |
from typing import Dict, Any, List, Optional
|
|
@@ -37,12 +39,19 @@ logger = logging.getLogger("Space26_Options")
|
|
| 37 |
|
| 38 |
# ================= КОНФИГУРАЦИЯ =================
|
| 39 |
SYMBOLS = ["XAU/USD", "ETH/USD", "SOL/USD"]
|
| 40 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
TWELVE_DATA_KEY = os.getenv("TWELVE_DATA_KEY", "58e67e0008e24161ac9b1671b7c2d2d0")
|
| 42 |
FRED_KEY = os.getenv("FRED_KEY", "faa11c8e2e4beee08c5b966e8b63a513")
|
| 43 |
|
|
|
|
|
|
|
|
|
|
| 44 |
# Интервал авто-отправки
|
| 45 |
-
AUTO_SEND_INTERVAL = int(os.getenv("AUTO_SEND_INTERVAL", "
|
| 46 |
|
| 47 |
HISTORY_FILE = "options_history.json"
|
| 48 |
CACHE_TTL = {
|
|
@@ -53,6 +62,10 @@ CACHE_TTL = {
|
|
| 53 |
# ================= HTTP КЛИЕНТ =================
|
| 54 |
http_client = httpx.AsyncClient(timeout=15.0)
|
| 55 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
# ================= ГЛОБАЛЬНЫЙ КЭШ И BREAKER =================
|
| 57 |
cache_store = {}
|
| 58 |
cache_times = {}
|
|
@@ -172,8 +185,10 @@ async def fetch_gold_derivatives() -> Dict[str, Any]:
|
|
| 172 |
|
| 173 |
async def get_current_price(symbol: str) -> float:
|
| 174 |
try:
|
| 175 |
-
r = await http_client.get(f"{HUB_URL}/price/{symbol}")
|
| 176 |
-
if r.status_code == 200:
|
|
|
|
|
|
|
| 177 |
except: pass
|
| 178 |
bin_symbol = symbol.replace("/", "")
|
| 179 |
try:
|
|
@@ -263,14 +278,29 @@ async def analyze_derivatives(symbol: str) -> Dict[str, Any]:
|
|
| 263 |
# ================= ОТПРАВКА В HUB =================
|
| 264 |
async def send_signal_to_hub(symbol: str, direction: str, confidence: float):
|
| 265 |
try:
|
| 266 |
-
|
| 267 |
-
"space": "space_26_options",
|
| 268 |
-
"
|
| 269 |
-
"
|
| 270 |
-
|
| 271 |
-
|
| 272 |
-
|
| 273 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 274 |
|
| 275 |
# ================= ГЛАВНЫЙ СИГНАЛ =================
|
| 276 |
async def get_derivative_signal(symbol: str = "ETH/USD") -> Dict[str, Any]:
|
|
@@ -283,8 +313,9 @@ async def get_derivative_signal(symbol: str = "ETH/USD") -> Dict[str, Any]:
|
|
| 283 |
|
| 284 |
# ================= АВТО-ОТПРАВКА =================
|
| 285 |
async def auto_send_loop():
|
|
|
|
|
|
|
| 286 |
logger.info(f"🔄 Авто-отправка Options Engine запущена (интервал {AUTO_SEND_INTERVAL}с)")
|
| 287 |
-
await asyncio.sleep(30)
|
| 288 |
while True:
|
| 289 |
try:
|
| 290 |
for symbol in SYMBOLS:
|
|
@@ -294,19 +325,24 @@ async def auto_send_loop():
|
|
| 294 |
await asyncio.sleep(AUTO_SEND_INTERVAL)
|
| 295 |
|
| 296 |
# ================= FASTAPI =================
|
| 297 |
-
app = FastAPI(title="Tomiris Space 26
|
| 298 |
|
| 299 |
@app.on_event("startup")
|
| 300 |
async def startup():
|
| 301 |
asyncio.create_task(auto_send_loop())
|
| 302 |
-
logger.info("🚀 Space 26
|
| 303 |
|
| 304 |
@app.on_event("shutdown")
|
| 305 |
async def shutdown(): await http_client.aclose()
|
| 306 |
|
| 307 |
@app.get("/health")
|
| 308 |
async def health():
|
| 309 |
-
return {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 310 |
|
| 311 |
@app.get("/consilium")
|
| 312 |
async def consilium(symbol: str = Query("ETH/USD")):
|
|
@@ -339,8 +375,12 @@ async def send_now():
|
|
| 339 |
results[symbol] = analysis.get("signal", {}).get("direction", "WAIT")
|
| 340 |
return {"status": "sent", "results": results}
|
| 341 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 342 |
if __name__ == "__main__":
|
| 343 |
import uvicorn
|
| 344 |
uvicorn.run(app, host="0.0.0.0", port=7860)
|
| 345 |
|
| 346 |
-
print("🚀 SPACE 26
|
|
|
|
| 21 |
print(f"✅ {pip_name} установлен!")
|
| 22 |
|
| 23 |
# ============================================
|
| 24 |
+
# 👑 TOMIRIS SPACE 26 v3.0 — OPTIONS & DERIVATIVES ENGINE (PRO-8/tomiris-options)
|
| 25 |
+
# Миграция с v2.4. Все функции сохранены.
|
| 26 |
+
# HUB_URL обновлён, HUB_SECRET во всех запросах.
|
| 27 |
# ============================================
|
| 28 |
import os, time, json, logging, asyncio
|
| 29 |
from typing import Dict, Any, List, Optional
|
|
|
|
| 39 |
|
| 40 |
# ================= КОНФИГУРАЦИЯ =================
|
| 41 |
SYMBOLS = ["XAU/USD", "ETH/USD", "SOL/USD"]
|
| 42 |
+
|
| 43 |
+
# ================= ОБНОВЛЁННЫЙ HUB URL =================
|
| 44 |
+
HUB_URL = "https://pro-3-tomiris-hub.hf.space"
|
| 45 |
+
HUB_SECRET = os.getenv("HUB_SECRET", "TomyrisUltraSecret2026!")
|
| 46 |
+
|
| 47 |
TWELVE_DATA_KEY = os.getenv("TWELVE_DATA_KEY", "58e67e0008e24161ac9b1671b7c2d2d0")
|
| 48 |
FRED_KEY = os.getenv("FRED_KEY", "faa11c8e2e4beee08c5b966e8b63a513")
|
| 49 |
|
| 50 |
+
# ================= СТАРТОВЫЙ СОН =================
|
| 51 |
+
STARTUP_SLEEP = int(os.getenv("STARTUP_SLEEP", 600)) # 10 минут
|
| 52 |
+
|
| 53 |
# Интервал авто-отправки
|
| 54 |
+
AUTO_SEND_INTERVAL = int(os.getenv("AUTO_SEND_INTERVAL", "600")) # 10 минут
|
| 55 |
|
| 56 |
HISTORY_FILE = "options_history.json"
|
| 57 |
CACHE_TTL = {
|
|
|
|
| 62 |
# ================= HTTP КЛИЕНТ =================
|
| 63 |
http_client = httpx.AsyncClient(timeout=15.0)
|
| 64 |
|
| 65 |
+
# ================= ЗАГОЛОВКИ ДЛЯ ХАБА =================
|
| 66 |
+
def hub_headers():
|
| 67 |
+
return {"X-Hub-Secret": HUB_SECRET} if HUB_SECRET else {}
|
| 68 |
+
|
| 69 |
# ================= ГЛОБАЛЬНЫЙ КЭШ И BREAKER =================
|
| 70 |
cache_store = {}
|
| 71 |
cache_times = {}
|
|
|
|
| 185 |
|
| 186 |
async def get_current_price(symbol: str) -> float:
|
| 187 |
try:
|
| 188 |
+
r = await http_client.get(f"{HUB_URL}/price/{symbol}", headers=hub_headers())
|
| 189 |
+
if r.status_code == 200:
|
| 190 |
+
data = r.json()
|
| 191 |
+
return float(data.get("price", data.get("mid", 0)))
|
| 192 |
except: pass
|
| 193 |
bin_symbol = symbol.replace("/", "")
|
| 194 |
try:
|
|
|
|
| 278 |
# ================= ОТПРАВКА В HUB =================
|
| 279 |
async def send_signal_to_hub(symbol: str, direction: str, confidence: float):
|
| 280 |
try:
|
| 281 |
+
payload = {
|
| 282 |
+
"space": "space_26_options",
|
| 283 |
+
"space_name": "space_26_options",
|
| 284 |
+
"symbol": symbol,
|
| 285 |
+
"direction": direction,
|
| 286 |
+
"confidence": confidence,
|
| 287 |
+
"features": {},
|
| 288 |
+
"metadata": {"version": "3.0", "source": "PRO-8/tomiris-options"}
|
| 289 |
+
}
|
| 290 |
+
r = await http_client.post(f"{HUB_URL}/signals", json=payload, timeout=10, headers=hub_headers())
|
| 291 |
+
if r.status_code == 200:
|
| 292 |
+
logger.info(f"📤 {symbol}: {direction} conf={confidence:.3f} отправлен в Hub")
|
| 293 |
+
else:
|
| 294 |
+
r = await http_client.post(f"{HUB_URL}/signal", json={
|
| 295 |
+
"space": "space_26_options", "symbol": symbol,
|
| 296 |
+
"direction": direction, "confidence": confidence
|
| 297 |
+
}, timeout=10, headers=hub_headers())
|
| 298 |
+
if r.status_code == 200:
|
| 299 |
+
logger.info(f"📤 {symbol}: {direction} conf={confidence:.3f} (через /signal)")
|
| 300 |
+
else:
|
| 301 |
+
logger.warning(f"Hub вернул {r.status_code}")
|
| 302 |
+
except Exception as e:
|
| 303 |
+
logger.error(f"Ошибка отправки в Hub: {e}")
|
| 304 |
|
| 305 |
# ================= ГЛАВНЫЙ СИГНАЛ =================
|
| 306 |
async def get_derivative_signal(symbol: str = "ETH/USD") -> Dict[str, Any]:
|
|
|
|
| 313 |
|
| 314 |
# ================= АВТО-ОТПРАВКА =================
|
| 315 |
async def auto_send_loop():
|
| 316 |
+
logger.info(f"⏳ Стартовый сон {STARTUP_SLEEP} секунд...")
|
| 317 |
+
await asyncio.sleep(STARTUP_SLEEP)
|
| 318 |
logger.info(f"🔄 Авто-отправка Options Engine запущена (интервал {AUTO_SEND_INTERVAL}с)")
|
|
|
|
| 319 |
while True:
|
| 320 |
try:
|
| 321 |
for symbol in SYMBOLS:
|
|
|
|
| 325 |
await asyncio.sleep(AUTO_SEND_INTERVAL)
|
| 326 |
|
| 327 |
# ================= FASTAPI =================
|
| 328 |
+
app = FastAPI(title="Tomiris Space 26 v3.0 — Options & Derivatives Engine (PRO-8)")
|
| 329 |
|
| 330 |
@app.on_event("startup")
|
| 331 |
async def startup():
|
| 332 |
asyncio.create_task(auto_send_loop())
|
| 333 |
+
logger.info("🚀 Space 26 v3.0 запущен на PRO-8/tomiris-options")
|
| 334 |
|
| 335 |
@app.on_event("shutdown")
|
| 336 |
async def shutdown(): await http_client.aclose()
|
| 337 |
|
| 338 |
@app.get("/health")
|
| 339 |
async def health():
|
| 340 |
+
return {
|
| 341 |
+
"status": "operational", "version": "3.0",
|
| 342 |
+
"space": "PRO-8/tomiris-options",
|
| 343 |
+
"hub_url": HUB_URL, "auto_send_interval": AUTO_SEND_INTERVAL,
|
| 344 |
+
"startup_sleep": STARTUP_SLEEP
|
| 345 |
+
}
|
| 346 |
|
| 347 |
@app.get("/consilium")
|
| 348 |
async def consilium(symbol: str = Query("ETH/USD")):
|
|
|
|
| 375 |
results[symbol] = analysis.get("signal", {}).get("direction", "WAIT")
|
| 376 |
return {"status": "sent", "results": results}
|
| 377 |
|
| 378 |
+
@app.get("/")
|
| 379 |
+
async def root():
|
| 380 |
+
return {"name": "Options Engine v3.0", "space": "PRO-8/tomiris-options", "hub": HUB_URL}
|
| 381 |
+
|
| 382 |
if __name__ == "__main__":
|
| 383 |
import uvicorn
|
| 384 |
uvicorn.run(app, host="0.0.0.0", port=7860)
|
| 385 |
|
| 386 |
+
print("🚀 SPACE 26 v3.0 — OPTIONS & DERIVATIVES ENGINE (PRO-8/tomiris-options) ЗАПУЩЕН!")
|