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:
90
backend/app/main.py
Normal file
90
backend/app/main.py
Normal file
@@ -0,0 +1,90 @@
|
||||
import logging
|
||||
|
||||
from fastapi import FastAPI, WebSocket
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
|
||||
from app.api.routes import backtest, bot, candles, trades
|
||||
from app.api.routes.bot import set_bot_runner
|
||||
from app.api.websocket import manager, websocket_endpoint
|
||||
from app.core.bot import BotRunner
|
||||
from app.core.config import settings
|
||||
from app.core.database import AsyncSessionLocal, init_db
|
||||
from app.core.exchange.simulated import SimulatedExchange
|
||||
from app.core.strategy.order_block_sweep import OrderBlockSweepStrategy
|
||||
from app.services.market_data import MarketDataService
|
||||
from app.services.trade_manager import TradeManager
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
app = FastAPI(
|
||||
title="Trader Bot API",
|
||||
description="Bot de trading ICT — Order Block + Liquidity Sweep",
|
||||
version="0.1.0",
|
||||
)
|
||||
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["http://localhost:5173", "http://localhost:3000"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
app.include_router(candles.router, prefix="/api")
|
||||
app.include_router(trades.router, prefix="/api")
|
||||
app.include_router(backtest.router, prefix="/api")
|
||||
app.include_router(bot.router, prefix="/api")
|
||||
|
||||
|
||||
@app.websocket("/ws/live")
|
||||
async def ws_live(websocket: WebSocket):
|
||||
await websocket_endpoint(websocket)
|
||||
|
||||
|
||||
@app.on_event("startup")
|
||||
async def startup():
|
||||
await init_db()
|
||||
logger.info("Base de données initialisée")
|
||||
|
||||
# Initialiser le bot avec l'exchange simulé (paper trading local)
|
||||
async with AsyncSessionLocal() as db:
|
||||
market_data = MarketDataService(db)
|
||||
exchange = SimulatedExchange(
|
||||
market_data_service=market_data,
|
||||
initial_balance=settings.bot_initial_balance,
|
||||
)
|
||||
strategy = OrderBlockSweepStrategy()
|
||||
trade_mgr = TradeManager(exchange)
|
||||
runner = BotRunner(
|
||||
exchange=exchange,
|
||||
strategy=strategy,
|
||||
trade_manager=trade_mgr,
|
||||
)
|
||||
|
||||
async def broadcast_event(event: dict):
|
||||
await manager.broadcast(event)
|
||||
|
||||
runner.set_event_callback(broadcast_event)
|
||||
set_bot_runner(runner)
|
||||
|
||||
td_status = "✓ configurée" if settings.twelvedata_api_key else "✗ manquante (historique limité)"
|
||||
logger.info(
|
||||
"Bot initialisé — SimulatedExchange | balance=%.0f$ | TwelveData=%s",
|
||||
settings.bot_initial_balance,
|
||||
td_status,
|
||||
)
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def root():
|
||||
return {
|
||||
"name": "Trader Bot API",
|
||||
"version": "0.1.0",
|
||||
"docs": "/docs",
|
||||
"data_sources": {
|
||||
"primary": "yfinance",
|
||||
"fallback_historical": "TwelveData",
|
||||
"twelvedata_configured": bool(settings.twelvedata_api_key),
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user