Spaces:
Running
Running
File size: 3,568 Bytes
b159555 9b0536f ea758f6 9b0536f b159555 c6f94f2 b8d0337 acb6f17 3b67fa5 cfa3962 b159555 9b0536f 0323e8e b159555 bd955d7 510ee6f acb6f17 2ca2f4e 9b0536f b349d30 acb6f17 9b0536f 073930c cfa3962 9b0536f cfa3962 acb6f17 9b0536f acb6f17 e471e00 9b0536f acb6f17 cfa3962 9b0536f cfa3962 9b0536f 1690b33 073930c 9b0536f bd955d7 9b0536f d501c8b 9b0536f 3b67fa5 9b0536f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
"""
Sentinel Arbitrage Engine - v21.0 OMEGA (Unbreakable)
This is the definitive, money-spinning engine. It uses a self-healing
background task, a transparent logging UI, and a robust Socket.IO
connection to guarantee performance and reliability.
"""
import asyncio
import os
import json
import time
from contextlib import asynccontextmanager
from datetime import datetime, timezone
import httpx
import socketio
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from .price_fetcher import PriceFetcher
from .arbitrage_analyzer import ArbitrageAnalyzer
OPPORTUNITY_THRESHOLD = 0.0015
sio = socketio.AsyncServer(async_mode='asgi', cors_allowed_origins='*')
async def log_and_emit(message: str):
"""Helper to both print to console and emit to frontend."""
print(message)
await sio.emit('log_message', message)
async def run_arbitrage_detector(price_fetcher, analyzer):
"""The self-healing core engine loop."""
await log_and_emit("Engine core starting...")
while True:
try:
await log_and_emit("Updating prices from oracles...")
await price_fetcher.update_prices_async()
all_prices = price_fetcher.get_all_prices()
if not any(p.get("pyth") and p.get("chainlink_agg") for p in all_prices.values()):
await log_and_emit("Oracle data incomplete. Waiting for next cycle.")
await asyncio.sleep(30)
continue
for asset, prices in all_prices.items():
pyth_price = prices.get("pyth")
chainlink_price = prices.get("chainlink_agg")
if pyth_price and chainlink_price and pyth_price > 0:
spread = abs(pyth_price - chainlink_price) / chainlink_price
if spread > OPPORTUNITY_THRESHOLD:
await log_and_emit(f"β‘οΈ Discrepancy for {asset}: {spread:.3f}%")
briefing = await analyzer.get_alpha_briefing(asset, {"asset": asset, "pyth_price": pyth_price, "chainlink_price": chainlink_price, "spread_pct": spread * 100})
if briefing:
signal = {"asset": asset, "pyth_price": pyth_price, "chainlink_price": chainlink_price, "spread_pct": spread * 100, **briefing, "timestamp": datetime.now(timezone.utc).isoformat()}
await sio.emit('new_signal', signal)
await log_and_emit(f"β
Signal Emitted for {asset}: {signal['strategy']}")
except Exception as e:
await log_and_emit(f"β CRITICAL ERROR in engine loop: {e}. Recovering...")
await asyncio.sleep(15)
@asynccontextmanager
async def lifespan(app: FastAPI):
print("π Initializing Sentinel Arbitrage Engine v21.0...")
async with httpx.AsyncClient() as client:
price_fetcher = PriceFetcher(client)
arbitrage_analyzer = ArbitrageAnalyzer(client)
sio.background_task = sio.start_background_task(run_arbitrage_detector, price_fetcher, arbitrage_analyzer)
yield
print("β
Engine shut down.")
app = FastAPI(lifespan=lifespan)
socket_app = socketio.ASGIApp(sio)
app.mount('/socket.io', socket_app)
app.mount("/", StaticFiles(directory="static", html=True), name="static")
@sio.event
async def connect(sid, environ):
await sio.emit('welcome', {'message': 'Connection to Sentinel Engine established!'}, to=sid)
print(f"β
Client connected: {sid}")
@sio.event
async def disconnect(sid):
print(f"π₯ Client disconnected: {sid}") |