Add trader filter to chart and per-trader stats

This commit is contained in:
root
2026-02-23 17:10:32 +00:00
parent c2e9e0f3ad
commit acf5eadf54
+30 -3
View File
@@ -192,6 +192,7 @@ export function TradingChart() {
const [chartData, setChartData] = useState<ChartData[]>([])
const [secondChartData, setSecondChartData] = useState<ChartData[]>([])
const [trades, setTrades] = useState<Trade[]>([])
const [traderFilter, setTraderFilter] = useState<string>('all')
const [thothView, setThothView] = useState<Record<string, ThothView>>({})
const [priceData, setPriceData] = useState<PriceData>({ price: 0, change24h: 0 })
const [loading, setLoading] = useState(true)
@@ -320,7 +321,15 @@ export function TradingChart() {
}
const closedTrades = trades.filter(t => t.result === 'win' || t.result === 'loss')
const wins = closedTrades.filter(t => t.result === 'win').length, winRate = closedTrades.length ? Math.round(wins / closedTrades.length * 100) : 0, totalPnl = closedTrades.reduce((s, t) => s + (t.pnl || 0), 0), avgRr = closedTrades.length ? closedTrades.reduce((s, t) => s + (t.rr || 0), 0) / closedTrades.length : 0
const filteredTrades = traderFilter === 'all' ? trades : trades.filter(t => t.trader === traderFilter)
const filteredClosed = filteredTrades.filter(t => t.result === 'win' || t.result === 'loss')
const wins = filteredClosed.filter(t => t.result === 'win').length
const winRate = filteredClosed.length ? Math.round(wins / filteredClosed.length * 100) : 0
const totalPnl = filteredClosed.reduce((s, t) => s + (t.pnl || 0), 0)
const avgRr = filteredClosed.length ? filteredClosed.reduce((s, t) => s + (t.rr || 0), 0) / filteredClosed.length : 0
// Get unique traders from trades
const tradersList = ['all', ...new Set(trades.map(t => t.trader).filter(Boolean))]
const cv = thothView[selectedAsset]
const getTE = (t: string) => t === 'uptrend' ? '🟢' : t === 'downtrend' ? '🔴' : '⚪️'
const getBC = (b: string) => b === 'bullish' ? 'text-green-400' : b === 'bearish' ? 'text-red-400' : 'text-yellow-400'
@@ -336,6 +345,24 @@ export function TradingChart() {
<div className="flex gap-2 flex-wrap">{(Object.keys(indicators) as (keyof IndicatorState)[]).map(k => <button key={k} onClick={() => toggleIndicator(k)} className={`px-3 py-1 rounded text-sm ${indicators[k] ? 'bg-brand-pink text-white' : 'bg-white/10 text-white/50'}`}>{k === 'thoth' ? '👁 THOTH' : k === 'srZones' ? 'S/R' : k === 'volume' ? 'VOL' : k === 'news' ? 'NEWS' : k === 'patterns' ? 'PATTERNS' : k === 'fib' ? 'FIB' : k === 'countdown' ? '⏱️' : k === 'calendar' ? '📅' : k === 'correlation' ? '📊 CORR' : k === 'funding' ? '💰 FUND' : k.toUpperCase()}</button>)}</div>
{/* Trader Filter */}
<div className="flex gap-2 items-center flex-wrap">
<span className="text-white/50 text-sm">Trader:</span>
{tradersList.map(t => (
<button
key={t}
onClick={() => setTraderFilter(t)}
className={`px-3 py-1 rounded text-sm ${
traderFilter === t
? 'bg-brand-pink text-white'
: 'bg-white/10 text-white/50 hover:bg-white/20'
}`}
>
{t === 'all' ? 'All' : t}
</button>
))}
</div>
<div className="flex justify-between p-4 rounded-lg bg-black/50 border border-white/10"><div><span className="text-2xl font-bold">{selectedAsset}/USD</span></div><div className="text-right"><div className="text-2xl font-bold">${priceData.price.toLocaleString()}</div><div className={`text-sm ${priceData.change24h >= 0 ? 'text-green-400' : 'text-red-400'}`}>{priceData.change24h >= 0 ? '↑' : '↓'} {Math.abs(priceData.change24h).toFixed(2)}%</div></div></div>
{cv && <div className="rounded-lg border border-brand-pink/30 bg-brand-pink/5 p-4"><div className="flex items-center gap-2 mb-3"><span className="text-xl">👁</span><h3 className="font-bold text-brand-pink">THOTH'S VIEW</h3><span className="text-xs text-white/40 ml-auto">{new Date(cv.updated_at).toLocaleString()}</span></div><p className="text-white/90 mb-4 italic">"{cv.thought}"</p><div className="grid grid-cols-2 md:grid-cols-4 gap-3 text-sm"><div><p className="text-white/50 text-xs">Trend</p><p className="font-medium">{getTE(cv.trend)} {cv.trend}</p></div><div><p className="text-white/50 text-xs">Phase</p><p className="font-medium">{cv.phase}</p></div><div><p className="text-white/50 text-xs">Key Level</p><p className="font-medium">${cv.key_level.toLocaleString()}</p></div><div><p className="text-white/50 text-xs">Bias</p><p className={`font-medium ${getBC(cv.bias)}`}>{cv.bias.toUpperCase()} ({cv.confidence}/10)</p></div></div></div>}
@@ -347,9 +374,9 @@ export function TradingChart() {
{indicators.rsi && <div className="rounded-lg bg-black/50 border border-white/10" style={{ height: '150px' }}><canvas ref={rsiChartRef} /></div>}
{indicators.macd && <div className="rounded-lg bg-black/50 border border-white/10" style={{ height: '150px' }}><canvas ref={macdChartRef} /></div>}
<div className="grid grid-cols-5 gap-3">{[{ v: trades.filter(t => t.result === 'open').length, l: 'Open' }, { v: totalPnl, l: 'P&L', c: 'text-green-400' }, { v: winRate + '%', l: 'Win Rate' }, { v: closedTrades.length, l: 'Trades' }, { v: avgRr.toFixed(1) + ':1', l: 'Avg R:R' }].map((s, i) => <div key={i} className="p-3 rounded-lg bg-white/5 border border-white/10 text-center"><p className={`text-2xl font-bold ${s.c || ''}`}>{s.v}</p><p className="text-xs text-white/50">{s.l}</p></div>)}</div>
<div className="grid grid-cols-5 gap-3">{[{ v: filteredTrades.filter(t => t.result === 'open').length, l: 'Open' }, { v: totalPnl, l: 'P&L', c: 'text-green-400' }, { v: winRate + '%', l: 'Win Rate' }, { v: filteredClosed.length, l: 'Trades' }, { v: avgRr.toFixed(1) + ':1', l: 'Avg R:R' }].map((s, i) => <div key={i} className="p-3 rounded-lg bg-white/5 border border-white/10 text-center"><p className={`text-2xl font-bold ${s.c || ''}`}>{s.v}</p><p className="text-xs text-white/50">{s.l}</p></div>)}</div>
<div className="rounded-lg border border-white/10 bg-white/5 overflow-hidden"><div className="px-4 py-3 border-b border-white/10"><h3 className="font-bold">📊 Trade History</h3></div>{trades.length === 0 ? <div className="p-8 text-center text-white/50">No trades yet</div> : <div className="max-h-48 overflow-y-auto"><table className="w-full text-sm"><thead className="bg-white/5 text-white/70 sticky top-0"><tr><th className="px-4 py-2 text-left">Date</th><th className="px-4 py-2">Asset</th><th className="px-4 py-2">Dir</th><th className="px-4 py-2 text-right">Entry</th><th className="px-4 py-2 text-right">SL</th><th className="px-4 py-2 text-right">TP</th><th className="px-4 py-2 text-right">R:R</th><th className="px-4 py-2 text-right">Result</th></tr></thead><tbody>{trades.map((t, i) => <tr key={i} className={`border-t border-white/5 ${t.result === 'win' ? 'bg-green-500/10' : t.result === 'loss' ? 'bg-red-500/10' : 'bg-yellow-500/10'}`}><td className="px-4 py-2">{t.date}</td><td className="px-4 py-2 text-center">{t.pair}</td><td className="px-4 py-2 text-center"><span className={t.direction === 'long' ? 'text-green-400' : 'text-red-400'}>{t.direction.toUpperCase()}</span></td><td className="px-4 py-2 text-right">${t.entry.toLocaleString()}</td><td className="px-4 py-2 text-right text-red-400">${t.stopLoss.toLocaleString()}</td><td className="px-4 py-2 text-right text-green-400">${t.takeProfit.toLocaleString()}</td><td className="px-4 py-2 text-right">{t.rr?.toFixed(1)}:1</td><td className="px-4 py-2 text-right">{t.result === 'win' ? '' : t.result === 'loss' ? '' : ''}</td></tr>)}</tbody></table></div>}</div>
<div className="rounded-lg border border-white/10 bg-white/5 overflow-hidden"><div className="px-4 py-3 border-b border-white/10"><h3 className="font-bold">📊 Trade History - {traderFilter === 'all' ? 'All Traders' : traderFilter}</h3></div>{filteredTrades.length === 0 ? <div className="p-8 text-center text-white/50">No trades yet</div> : <div className="max-h-48 overflow-y-auto"><table className="w-full text-sm"><thead className="bg-white/5 text-white/70 sticky top-0"><tr><th className="px-4 py-2 text-left">Date</th><th className="px-4 py-2">Asset</th><th className="px-4 py-2">Dir</th><th className="px-4 py-2 text-right">Entry</th><th className="px-4 py-2 text-right">SL</th><th className="px-4 py-2 text-right">TP</th><th className="px-4 py-2 text-right">R:R</th><th className="px-4 py-2 text-right">Result</th></tr></thead><tbody>{filteredTrades.map((t, i) => <tr key={i} className={`border-t border-white/5 ${t.result === 'win' ? 'bg-green-500/10' : t.result === 'loss' ? 'bg-red-500/10' : 'bg-yellow-500/10'}`}><td className="px-4 py-2">{t.date}</td><td className="px-4 py-2 text-center">{t.pair}</td><td className="px-4 py-2 text-center"><span className={t.direction === 'long' ? 'text-green-400' : 'text-red-400'}>{t.direction.toUpperCase()}</span></td><td className="px-4 py-2 text-right">${t.entry.toLocaleString()}</td><td className="px-4 py-2 text-right text-red-400">${t.stopLoss.toLocaleString()}</td><td className="px-4 py-2 text-right text-green-400">${t.takeProfit.toLocaleString()}</td><td className="px-4 py-2 text-right">{t.rr?.toFixed(1)}:1</td><td className="px-4 py-2 text-right">{t.result === 'win' ? '' : t.result === 'loss' ? '' : ''}</td></tr>)}</tbody></table></div>}</div>
</div>
)
}