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:
46
frontend/src/components/Dashboard/PnLSummary.tsx
Normal file
46
frontend/src/components/Dashboard/PnLSummary.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user