'use client' import { useState, useEffect, useRef } from 'react' interface Trade { id: string date: string pair: string direction: 'long' | 'short' entry: number stopLoss: number takeProfit: number result?: 'win' | 'loss' | 'open' pnl?: number rr?: number } interface ChartData { time: number open: number high: number low: number close: number volume?: number } interface ThothView { thought: string trend: string phase: string key_level: number bias: string confidence: number reason: string next_action: string updated_at: string bias_history?: { time: number; bias: string; price: number }[] support_zones?: { level: number; strength: number }[] resistance_zones?: { level: number; strength: number }[] } interface PriceData { price: number change24h: number } interface IndicatorState { ema20: boolean ema50: boolean ema200: boolean bb: boolean rsi: boolean macd: boolean thoth: boolean volume: boolean srZones: boolean news: boolean patterns: boolean fib: boolean countdown: boolean calendar: boolean correlation: boolean funding: boolean } const getCandleLimit = (tf: string) => ({ '15m': 80, '1h': 100, '4h': 60, '1D': 90 }[tf] || 100) export default function TradingChart() { const chartContainerRef = useRef(null) const chartRef = useRef(null) const candlestickSeriesRef = useRef(null) const volumeSeriesRef = useRef(null) const ema20Ref = useRef(null) const ema50Ref = useRef(null) const ema200Ref = useRef(null) const [selectedAsset, setSelectedAsset] = useState<'BTC' | 'SOL' | 'ETH'>('BTC') const [selectedTimeframe, setSelectedTimeframe] = useState<'15m' | '1h' | '4h' | '1D'>('1h') const [chartData, setChartData] = useState([]) const [priceData, setPriceData] = useState({ price: 0, change24h: 0 }) const [loading, setLoading] = useState(true) const [trades, setTrades] = useState([]) const [thothView, setThothView] = useState>({}) const [indicators, setIndicators] = useState({ ema20: false, ema50: false, ema200: false, bb: false, rsi: false, macd: false, thoth: true, volume: true, srZones: true, news: false, patterns: false, fib: false, countdown: false, calendar: false, correlation: false, funding: false }) const [mounted, setMounted] = useState(false) // Initialize on mount (client only) useEffect(() => { setMounted(true) let chartInstance: any = null let candleSeries: any = null let volSeries: any = null let e20: any = null let e50: any = null let e200: any = null const initChart = async () => { if (!chartContainerRef.current) return try { const { createChart } = await import('lightweight-charts') chartInstance = createChart(chartContainerRef.current, { layout: { background: { color: '#0a0a0f' }, textColor: '#a0a0a0' }, grid: { vertLines: { color: '#1a1a2e' }, horzLines: { color: '#1a1a2e' } }, width: chartContainerRef.current.clientWidth, height: 400, timeScale: { timeVisible: true, secondsVisible: false }, rightPriceScale: { borderColor: '#2a2a4e' }, }) candleSeries = chartInstance.addCandlestickSeries({ upColor: '#22c55e', downColor: '#ef4444', borderUpColor: '#22c55e', borderDownColor: '#ef4444', wickUpColor: '#22c55e', wickDownColor: '#ef4444', }) volSeries = chartInstance.addHistogramSeries({ color: '#26a69a', priceFormat: { type: 'volume' }, priceScaleId: '' }) volSeries.priceScale().applyOptions({ scaleMargins: { top: 0.8, bottom: 0 } }) chartRef.current = chartInstance candlestickSeriesRef.current = candleSeries volumeSeriesRef.current = volSeries ema20Ref.current = e20 ema50Ref.current = e50 ema200Ref.current = e200 const handleResize = () => { if (chartContainerRef.current) chartInstance.applyOptions({ width: chartContainerRef.current.clientWidth }) } window.addEventListener('resize', handleResize) // Fetch initial data fetchChartData() fetchPriceData() fetchTrades() fetchThothView() } catch (e) { console.error('Chart init error:', e) } } initChart() return () => { if (chartInstance) { chartInstance.remove() } } }, []) const fetchPriceData = async () => { try { const idMap: Record = { 'BTC': 'bitcoin', 'SOL': 'solana', 'ETH': 'ethereum' } const res = await fetch(`https://api.coingecko.com/api/v3/simple/price?ids=${idMap[selectedAsset]}&vs_currencies=usd&include_24hr_change=true`) const data = await res.json() setPriceData({ price: data[idMap[selectedAsset]]?.usd || 0, change24h: data[idMap[selectedAsset]]?.usd_24h_change || 0 }) } catch (e) { console.warn('Price fetch failed') const fallback: Record = { 'BTC': { price: 105000, change24h: 2.5 }, 'SOL': { price: 180, change24h: -1.2 }, 'ETH': { price: 3200, change24h: 1.8 } } setPriceData(fallback[selectedAsset] || { price: 0, change24h: 0 }) } } const fetchChartData = async () => { setLoading(true) try { const symbol = selectedAsset === 'BTC' ? 'BTCUSDT' : selectedAsset === 'SOL' ? 'SOLUSDT' : 'ETHUSDT' const interval = { '15m': '15m', '1h': '1h', '4h': '4h', '1D': '1d' }[selectedTimeframe] || '1h' const res = await fetch(`https://api.binance.com/api/v3/klines?symbol=${symbol}&interval=${interval}&limit=${getCandleLimit(selectedTimeframe)}`) const data = await res.json() const chartData = data.map((k: any[]) => ({ time: k[0] / 1000, open: parseFloat(k[1]), high: parseFloat(k[2]), low: parseFloat(k[3]), close: parseFloat(k[4]), volume: parseFloat(k[5]) })) setChartData(chartData) // Update chart if (candlestickSeriesRef.current) { candlestickSeriesRef.current.setData(chartData.map((d: any) => ({ time: d.time, open: d.open, high: d.high, low: d.low, close: d.close }))) } if (volumeSeriesRef.current && chartData[0]?.volume) { volumeSeriesRef.current.setData(chartData.map((d: any) => ({ time: d.time, value: d.volume || 0, color: d.close >= d.open ? 'rgba(34,197,94,0.5)' : 'rgba(239,68,68,0.5)' }))) } if (chartRef.current) chartRef.current.timeScale().fitContent() } catch (e) { console.error('Chart fetch error:', e) } finally { setLoading(false) } } const fetchTrades = async () => { try { const res = await fetch('/api/trading/trades'); if (res.ok) setTrades((await res.json()).trades || []) } catch (e) { console.warn(e) } } const fetchThothView = async () => { try { const res = await fetch('/thoth_view.json'); if (res.ok) setThothView(await res.json()) } catch (e) { console.warn(e) } } useEffect(() => { fetchChartData() fetchPriceData() }, [selectedAsset, selectedTimeframe]) const toggleIndicator = (key: keyof IndicatorState) => setIndicators((p: any) => ({ ...p, [key]: !p[key] })) const closedTrades = trades.filter((t: Trade) => t.result === 'win' || t.result === 'loss') const wins = closedTrades.filter((t: Trade) => t.result === 'win').length const winRate = closedTrades.length ? Math.round(wins / closedTrades.length * 100) : 0 const totalPnl = closedTrades.reduce((s: number, t: Trade) => s + (t.pnl || 0), 0) const avgRr = closedTrades.length ? closedTrades.reduce((s: number, t: Trade) => s + (t.rr || 0), 0) / closedTrades.length : 0 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' if (!mounted) { return
Loading chart...
} return (
{(['BTC', 'SOL', 'ETH'] as const).map(a => ( ))}
{(['15m', '1h', '4h', '1D'] as const).map(tf => ( ))}
{(Object.keys(indicators) as (keyof IndicatorState)[]).map(k => ( ))}
{selectedAsset}/USD
${priceData.price.toLocaleString()}
= 0 ? 'text-green-400' : 'text-red-400'}`}>{priceData.change24h >= 0 ? '↑' : '↓'} {Math.abs(priceData.change24h).toFixed(2)}%
{cv && (
👁️

THOTH'S VIEW

{new Date(cv.updated_at).toLocaleString()}

"{cv.thought}"

Trend

{getTE(cv.trend)} {cv.trend}

Phase

{cv.phase}

Key Level

${cv.key_level.toLocaleString()}

Bias

{cv.bias.toUpperCase()} ({cv.confidence}/10)

)}
{loading &&
Loading...
}

Trades

{closedTrades.length}

Win Rate

{winRate}%

Total PnL

= 0 ? 'text-green-400' : 'text-red-400'}`}>${totalPnl.toFixed(2)}

Avg R:R

{avgRr.toFixed(2)}R

) }