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,88 @@
from abc import ABC, abstractmethod
from dataclasses import dataclass
from datetime import datetime
from typing import Optional
import pandas as pd
@dataclass
class OrderResult:
trade_id: str
instrument: str
direction: str # "buy" | "sell"
units: float
entry_price: float
stop_loss: float
take_profit: float
opened_at: datetime
@dataclass
class OpenTrade:
trade_id: str
instrument: str
direction: str
units: float
entry_price: float
stop_loss: float
take_profit: float
unrealized_pnl: float
opened_at: datetime
@dataclass
class AccountInfo:
balance: float
nav: float # Net Asset Value
unrealized_pnl: float
currency: str
class AbstractExchange(ABC):
"""Interface commune pour tous les exchanges/brokers."""
@abstractmethod
async def get_candles(
self,
instrument: str,
granularity: str,
count: int = 200,
from_time: Optional[datetime] = None,
to_time: Optional[datetime] = None,
) -> pd.DataFrame:
"""
Retourne un DataFrame avec colonnes : time, open, high, low, close, volume.
"""
...
@abstractmethod
async def place_order(
self,
instrument: str,
units: float, # positif = buy, négatif = sell
stop_loss: float,
take_profit: float,
) -> OrderResult:
"""Place un ordre au marché avec SL et TP."""
...
@abstractmethod
async def close_trade(self, trade_id: str) -> float:
"""Ferme un trade par son ID. Retourne le PnL réalisé."""
...
@abstractmethod
async def get_open_trades(self) -> list[OpenTrade]:
"""Retourne la liste des positions ouvertes."""
...
@abstractmethod
async def get_account_info(self) -> AccountInfo:
"""Retourne les infos du compte (solde, PnL, etc.)."""
...
@abstractmethod
async def get_price(self, instrument: str) -> float:
"""Retourne le prix mid actuel."""
...