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>
91 lines
2.7 KiB
Python
91 lines
2.7 KiB
Python
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),
|
|
},
|
|
}
|