Full-stack trading bot with: - FastAPI backend with ICT strategy (Order Block + Liquidity Sweep detection) - Backtester engine with rolling window, spread simulation, and performance metrics - Hybrid market data service (yfinance + TwelveData with rate limiting + SQLite cache) - Simulated exchange for paper trading - React/TypeScript frontend with TradingView lightweight-charts v5 - Live dashboard with candlestick chart, OHLC legend, trade markers - Backtest page with configurable parameters, equity curve, and trade table - WebSocket support for real-time updates - Bot runner with asyncio loop for automated trading Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
58 lines
1.6 KiB
Python
58 lines
1.6 KiB
Python
"""
|
|
WebSocket endpoint pour le streaming de données live.
|
|
|
|
Broadcast les événements du bot (ticks, nouveaux trades, etc.)
|
|
vers tous les clients connectés.
|
|
"""
|
|
|
|
import asyncio
|
|
import json
|
|
import logging
|
|
from typing import Set
|
|
|
|
from fastapi import WebSocket, WebSocketDisconnect
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class ConnectionManager:
|
|
def __init__(self) -> None:
|
|
self._active: Set[WebSocket] = set()
|
|
|
|
async def connect(self, ws: WebSocket) -> None:
|
|
await ws.accept()
|
|
self._active.add(ws)
|
|
logger.info("WS client connecté — %d total", len(self._active))
|
|
|
|
def disconnect(self, ws: WebSocket) -> None:
|
|
self._active.discard(ws)
|
|
logger.info("WS client déconnecté — %d restants", len(self._active))
|
|
|
|
async def broadcast(self, data: dict) -> None:
|
|
if not self._active:
|
|
return
|
|
message = json.dumps(data, default=str)
|
|
dead: Set[WebSocket] = set()
|
|
for ws in list(self._active):
|
|
try:
|
|
await ws.send_text(message)
|
|
except Exception:
|
|
dead.add(ws)
|
|
for ws in dead:
|
|
self.disconnect(ws)
|
|
|
|
|
|
manager = ConnectionManager()
|
|
|
|
|
|
async def websocket_endpoint(ws: WebSocket) -> None:
|
|
await manager.connect(ws)
|
|
try:
|
|
while True:
|
|
# Garder la connexion ouverte, le client peut envoyer des pings
|
|
data = await ws.receive_text()
|
|
if data == "ping":
|
|
await ws.send_text(json.dumps({"type": "pong"}))
|
|
except WebSocketDisconnect:
|
|
manager.disconnect(ws)
|