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>
89 lines
2.0 KiB
Python
89 lines
2.0 KiB
Python
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."""
|
|
...
|