Files
trader-bot/frontend/src/components/Dashboard/PnLSummary.tsx
tika 4df8d53b1a 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>
2026-02-24 23:25:51 +01:00

47 lines
1.3 KiB
TypeScript

import type { Trade } from '../../lib/api'
interface Props {
trades: Trade[]
}
export default function PnLSummary({ trades }: Props) {
const closed = trades.filter((t) => t.status === 'closed' && t.pnl !== null)
const totalPnl = closed.reduce((acc, t) => acc + (t.pnl ?? 0), 0)
const winners = closed.filter((t) => (t.pnl ?? 0) > 0)
const winRate = closed.length > 0 ? (winners.length / closed.length) * 100 : 0
const stats = [
{
label: 'PnL Total',
value: `${totalPnl >= 0 ? '+' : ''}${totalPnl.toFixed(2)}`,
color: totalPnl >= 0 ? 'text-[#26a69a]' : 'text-[#ef5350]',
},
{
label: 'Win Rate',
value: `${winRate.toFixed(1)}%`,
color: winRate >= 50 ? 'text-[#26a69a]' : 'text-[#ef5350]',
},
{
label: 'Trades',
value: closed.length.toString(),
color: 'text-white',
},
{
label: 'Ouverts',
value: trades.filter((t) => t.status === 'open').length.toString(),
color: 'text-[#6366f1]',
},
]
return (
<div className="grid grid-cols-2 gap-3">
{stats.map((s) => (
<div key={s.label} className="bg-[#1a1d27] border border-[#2a2d3e] rounded-xl p-4">
<div className="text-xs text-[#64748b] mb-1">{s.label}</div>
<div className={`text-xl font-bold ${s.color}`}>{s.value}</div>
</div>
))}
</div>
)
}