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>
35 lines
1.6 KiB
Python
35 lines
1.6 KiB
Python
from datetime import datetime
|
|
from typing import Optional
|
|
|
|
from sqlalchemy import Float, Integer, String, DateTime
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
|
|
from app.core.database import Base
|
|
|
|
|
|
class Trade(Base):
|
|
__tablename__ = "trades"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
# "live" | "backtest"
|
|
source: Mapped[str] = mapped_column(String(10), default="live")
|
|
# identifiant OANDA du trade live (si applicable)
|
|
oanda_trade_id: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
|
|
instrument: Mapped[str] = mapped_column(String(20), index=True)
|
|
# "buy" | "sell"
|
|
direction: Mapped[str] = mapped_column(String(4))
|
|
units: Mapped[float] = mapped_column(Float)
|
|
entry_price: Mapped[float] = mapped_column(Float)
|
|
stop_loss: Mapped[float] = mapped_column(Float)
|
|
take_profit: Mapped[float] = mapped_column(Float)
|
|
exit_price: Mapped[Optional[float]] = mapped_column(Float, nullable=True)
|
|
pnl: Mapped[Optional[float]] = mapped_column(Float, nullable=True)
|
|
# "open" | "closed" | "cancelled"
|
|
status: Mapped[str] = mapped_column(String(10), default="open")
|
|
# Signal ayant déclenché le trade
|
|
signal_type: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
|
|
opened_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
|
closed_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
|
|
# ID du backtest parent (si applicable)
|
|
backtest_id: Mapped[Optional[int]] = mapped_column(Integer, nullable=True, index=True)
|