feat: trading bot MVP — ICT Order Block + Liquidity Sweep strategy

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>
This commit is contained in:
2026-02-24 23:25:51 +01:00
commit 4df8d53b1a
58 changed files with 7484 additions and 0 deletions

View File

@@ -0,0 +1,46 @@
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from app.core.config import settings
router = APIRouter(prefix="/bot", tags=["bot"])
# Instance globale du bot (initialisée dans main.py)
_bot_runner = None
def set_bot_runner(runner) -> None:
global _bot_runner
_bot_runner = runner
class BotStartRequest(BaseModel):
instrument: str = ""
granularity: str = ""
@router.get("/status")
async def bot_status():
if _bot_runner is None:
return {"running": False, "message": "Bot non initialisé"}
return _bot_runner.get_status()
@router.post("/start")
async def start_bot(req: BotStartRequest):
if _bot_runner is None:
raise HTTPException(503, "Bot non initialisé")
if req.instrument:
_bot_runner.instrument = req.instrument
if req.granularity:
_bot_runner.granularity = req.granularity
await _bot_runner.start()
return {"message": "Bot démarré", "status": _bot_runner.get_status()}
@router.post("/stop")
async def stop_bot():
if _bot_runner is None:
raise HTTPException(503, "Bot non initialisé")
await _bot_runner.stop()
return {"message": "Bot arrêté"}