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:
30
backend/app/api/routes/candles.py
Normal file
30
backend/app/api/routes/candles.py
Normal file
@@ -0,0 +1,30 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.core.database import get_db
|
||||
from app.services.market_data import MarketDataService
|
||||
|
||||
router = APIRouter(prefix="/candles", tags=["candles"])
|
||||
|
||||
VALID_GRANULARITIES = {"M1", "M5", "M15", "M30", "H1", "H4", "D"}
|
||||
|
||||
|
||||
@router.get("")
|
||||
async def get_candles(
|
||||
instrument: str = Query(default="EUR_USD", description="Ex: EUR_USD, GBP_USD, SPX500_USD"),
|
||||
granularity: str = Query(default="H1", description="M1, M5, M15, M30, H1, H4, D"),
|
||||
count: int = Query(default=200, ge=10, le=5000),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
if granularity not in VALID_GRANULARITIES:
|
||||
raise HTTPException(400, f"Granularité invalide. Valides: {VALID_GRANULARITIES}")
|
||||
|
||||
service = MarketDataService(db)
|
||||
df = await service.get_candles(instrument, granularity, count)
|
||||
|
||||
return {
|
||||
"instrument": instrument,
|
||||
"granularity": granularity,
|
||||
"count": len(df),
|
||||
"candles": df.to_dict(orient="records") if not df.empty else [],
|
||||
}
|
||||
Reference in New Issue
Block a user