# QUASAR System — Deployment Guide ## v2.0 Architecture-Strict | 2026-03-25 --- ## Overview The refactored system enforces a **strict one-way data pipeline**: ``` Asset Spaces (V75, V100_1s, Crash500) │ WebSocket PUBLISH (send-only) ▼ Central WebSocket Hub ←── ingest, normalize, broadcast │ WebSocket SUBSCRIBE (read-only) ▼ Ranker Space (Quasar_axrvi_ranker.py) │ REST / Dashboard outputs ▼ Rankings • REST API • Dashboard ``` **No feedback loop exists.** The Ranker never writes back to the Hub or Asset Spaces. --- ## File Reference | File | Role | Deploy As | |------|------|-----------| | `websocket_hub.py` | Central Hub — ingest, normalize, broadcast | Standalone FastAPI service | | `websocket_client.py` | Publisher — Asset Space send-only client | Imported in each Asset Space | | `Quasar_axrvi_ranker.py` | Ranker Space — subscriber + neural ranker + trading | Standalone process | --- ## 1. Requirements ```bash pip install fastapi uvicorn websockets websocket-client torch numpy pydantic ``` For Hugging Face Spaces, add to `requirements.txt`: ``` fastapi uvicorn[standard] websockets websocket-client torch numpy pydantic nest_asyncio ``` --- ## 2. Deploy the Central Hub ```bash # Local python websocket_hub.py # With explicit port PORT=7860 python websocket_hub.py # Production (Hugging Face Space) # Set Space SDK to "Docker" or use app.py entry with: uvicorn websocket_hub:app --host 0.0.0.0 --port 7860 ``` **Hub endpoints:** | Endpoint | Protocol | Role | |----------|----------|------| | `/ws/publish/{space_name}` | WebSocket | Publisher (Asset Spaces connect here) | | `/ws/subscribe` | WebSocket | Subscriber (Ranker connects here) | | `/rankings` | GET | Latest snapshots for all assets | | `/metrics/{space_name}` | GET | Single-asset snapshot | | `/health` | GET | Hub health and connection stats | --- ## 3. Integrate the Publisher into an Asset Space Each asset space (V75, V100_1s, Crash500) imports `AssetSpacePublisher`: ```python from websocket_client import AssetSpacePublisher, TrainingMetrics, VotingMetrics # ── Create and start (once, at startup) ────────────────────────────────────── publisher = AssetSpacePublisher( space_name = "V75", hub_url = "ws://your-hub-host:7860/ws/publish/V75", ) publisher.start() # ── In your training loop ────────────────────────────────────────────────── # After each training update: publisher.publish_training(TrainingMetrics( training_steps = step, actor_loss = actor_loss, critic_loss = critic_loss, avn_loss = avn_loss, avn_accuracy = avn_accuracy, )) # After each agent vote: publisher.publish_voting(VotingMetrics( dominant_signal = "BUY", # "BUY" | "SELL" | "NEUTRAL" buy_count = 7, sell_count = 3, )) # Or publish both together (preferred — fewer messages): publisher.publish_combined( training = TrainingMetrics(...), voting = VotingMetrics(...), ) ``` **Reminder:** The publisher is send-only. Any unexpected message from the hub is logged as a warning and discarded. No callbacks are invoked. --- ## 4. Deploy the Ranker Space ```bash # Point at your hub's subscribe endpoint python Quasar_axrvi_ranker.py \ --hub ws://your-hub-host:7860/ws/subscribe \ --assets V75 V100_1s CRASH1000 \ --bandit ucb \ --reward simple \ --model deriv_axrvi_model.pt # Sync/thread mode (e.g., inside a Jupyter notebook or larger process) python Quasar_axrvi_ranker.py --sync --hub ws://... # Component tests (no network required) python Quasar_axrvi_ranker.py --test ``` --- ## 5. Ranking Formula ``` signal_confidence = max(buy_count, sell_count) / (buy_count + sell_count) score = signal_confidence - avn_accuracy ``` | Scenario | Result | |----------|--------| | High confidence (0.9) + high accuracy (0.8) | score = +0.10 → good | | High confidence (0.9) + low accuracy (0.3) | score = +0.60 → penalized (large gap) | | Low confidence (0.5) + any accuracy | score ≤ 0.0 → weak | Assets are sorted by score in **ascending** order (smallest = most balanced = best). --- ## 6. Strict Data Schema The hub enforces and broadcasts **only** these fields: ``` training: training_steps (int) actor_loss (float) critic_loss (float) avn_loss (float) avn_accuracy (float, clamped [0,1]) voting: dominant_signal ("BUY" | "SELL" | "NEUTRAL") buy_count (int) sell_count (int) ``` The following fields are **explicitly stripped** at the hub ingestion layer and will never reach the Ranker: - ❌ rewards (matched, unmatched, duplicates, match_rate) - ❌ resource metrics (cpu_percent, memory_percent, memory_used_gb, quasar_memory_gb) - ❌ agent-level metrics (q_buy, q_sell, entropy, per-agent data) - ❌ buffer_size - ❌ any q-values or internal model outputs --- ## 7. Hugging Face Spaces Deployment ### Hub Space (`quasar-hub`) `app.py`: ```python from websocket_hub import app # FastAPI app, ready for uvicorn ``` `README.md` front-matter: ```yaml --- sdk: docker app_port: 7860 --- ``` ### Asset Space (e.g., `quasar-v75`) In your existing Space's training entry point: ```python from websocket_client import AssetSpacePublisher, TrainingMetrics, VotingMetrics import os HUB_URL = os.environ.get("HUB_WS_URL", "wss://your-hub-space.hf.space/ws/publish/V75") publisher = AssetSpacePublisher("V75", HUB_URL) publisher.start() ``` Set the environment variable `HUB_WS_URL` in each Space's settings. ### Ranker Space (`quasar-ranker`) ```python # main.py (entry point) import asyncio, os from Quasar_axrvi_ranker import run_live_trading_system HUB_SUB = os.environ.get("HUB_SUB_URL", "wss://your-hub-space.hf.space/ws/subscribe") asyncio.run(run_live_trading_system( asset_symbols = ["V75", "V100_1s", "CRASH1000"], hub_ws_url = HUB_SUB, )) ``` --- ## 8. Architecture Constraints (enforced in code) | Constraint | Where enforced | |------------|----------------| | Publishers cannot receive data | `_on_message` in `AssetSpacePublisher` discards all inbound messages | | Hub never writes to publishers | Publisher WebSocket endpoint is receive-only; no sends | | Subscribers are read-only | Subscriber endpoint drains inbound messages without processing | | No feedback loop | `HubSubscriber` has no send methods | | Minimal schema | Hub `_validate_and_normalize()` strips all non-permitted fields | | Thread-safe | All shared state protected by `asyncio.Lock` (hub) / `threading.Lock` (client, ranker) | --- ## 9. Environment Variables | Variable | Used By | Description | |----------|---------|-------------| | `DERIV_API_KEY` | Ranker | Deriv API key for live trading | | `PORT` | Hub | FastAPI server port (default 7860) | | `HUB_WS_URL` | Asset Spaces | Publisher WebSocket URL | | `HUB_SUB_URL` | Ranker | Subscriber WebSocket URL | --- ## 10. Quick Smoke Test ```bash # Terminal 1 — start hub python websocket_hub.py # Terminal 2 — ranker tests (no network) python Quasar_axrvi_ranker.py --test # Terminal 3 — simulate a publisher python - <<'EOF' from websocket_client import AssetSpacePublisher, TrainingMetrics, VotingMetrics import time pub = AssetSpacePublisher("V75_TEST", "ws://localhost:7860/ws/publish/V75_TEST") pub.start() time.sleep(1) for step in range(10): pub.publish_combined( TrainingMetrics(training_steps=step*100, avn_accuracy=0.5+step*0.04), VotingMetrics(dominant_signal="BUY", buy_count=7, sell_count=3), ) time.sleep(0.5) print("Done. Check /rankings endpoint.") EOF # Terminal 4 — verify hub received data curl http://localhost:7860/rankings | python -m json.tool ``` --- *End of deployment guide.*