'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 }[] } 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 seriesRef = 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: number; change24h: number }>({ price: 0, change24h: 0 }) const [loading, setLoading] = useState(true) const [trades, setTrades] = useState([]) const [thothView, setThothView] = useState>({}) const [mounted, setMounted] = useState(false) // Load chart library from CDN on mount useEffect(() => { setMounted(true) // Load lightweight-charts from CDN const script = document.createElement('script') script.src = 'https://unpkg.com/lightweight-charts@4.1.0/dist/lightweight-charts.standalone.production.js' script.onload = initChart script.onerror = () => console.error('Failed to load chart library') document.head.appendChild(script) return () => { if (chartRef.current) { chartRef.current.remove() } } }, []) const initChart = () => { if (!chartContainerRef.current || !(window as any).LightweightCharts) return const chart = (window as any).LightweightCharts.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', }, }) const candlestickSeries = chart.addCandlestickSeries({ upColor: '#22c55e', downColor: '#ef4444', borderUpColor: '#22c55e', borderDownColor: '#ef4444', wickUpColor: '#22c55e', wickDownColor: '#ef4444', }) chartRef.current = chart seriesRef.current = candlestickSeries // Handle resize const handleResize = () => { if (chartContainerRef.current && chartRef.current) { chartRef.current.applyOptions({ width: chartContainerRef.current.clientWidth }) } } window.addEventListener('resize', handleResize) // Fetch data fetchChartData() fetchPriceData() fetchTrades() fetchThothView() } 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) { 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 formattedData = 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(formattedData) // Update chart if (seriesRef.current) { seriesRef.current.setData(formattedData) } if (chartRef.current) { chartRef.current.timeScale().fitContent() } } catch (e) { console.error('Chart fetch error:', e) } 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(() => { if (mounted && chartRef.current) { fetchChartData() fetchPriceData() } }, [selectedAsset, selectedTimeframe, mounted]) const closedTrades = trades.filter((t) => t.result === 'win' || t.result === 'loss') const wins = closedTrades.filter((t) => t.result === 'win').length const winRate = closedTrades.length ? Math.round(wins / closedTrades.length * 100) : 0 const totalPnl = closedTrades.reduce((s, t) => s + (t.pnl || 0), 0) const avgRr = closedTrades.length ? closedTrades.reduce((s, t) => 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 => ( ))}
{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

) }