import {
ResponsiveContainer,
ComposedChart,
Line,
XAxis,
YAxis,
Tooltip,
ReferenceLine,
CartesianGrid,
} from 'recharts'
function CustomTooltip({ active, payload, label }) {
if (!active || !payload?.length) return null
const price = payload.find(p => p.dataKey === 'price')
return (
{label}
{price && (
${Number(price.value).toFixed(2)}
)}
)
}
export default function PriceChart({ data }) {
const { price_series, ma20, ma50, bb_upper, bb_lower, current_price } = data
if (!price_series || Object.keys(price_series).length === 0) return null
const chartData = Object.entries(price_series).map(([date, price]) => ({
date: date.slice(5),
price: Number(price),
ma20: ma20 ? Number(ma20) : undefined,
ma50: ma50 ? Number(ma50) : undefined,
bbUpper: bb_upper ? Number(bb_upper) : undefined,
bbLower: bb_lower ? Number(bb_lower) : undefined,
}))
const prices = chartData.map(d => d.price)
const lastPrice = prices[prices.length - 1]
const isUp = lastPrice >= prices[0]
const lineColor = isUp ? 'var(--buy)' : 'var(--sell)'
const allValues = [
...prices,
bb_upper ? Number(bb_upper) : null,
bb_lower ? Number(bb_lower) : null,
].filter(Boolean)
const minY = Math.min(...allValues) * 0.995
const maxY = Math.max(...allValues) * 1.005
const change = lastPrice - prices[0]
const changePct = ((change / prices[0]) * 100).toFixed(2)
return (
30-Day Price
{change >= 0 ? '+' : ''}{changePct}%
`$${v.toFixed(0)}`}
width={50}
/>
} />
{/* Bollinger band lines */}
{chartData[0]?.bbUpper && (
)}
{chartData[0]?.bbLower && (
)}
{/* MA50 */}
{ma50 && (
)}
{/* MA20 */}
{ma20 && (
)}
{/* Price */}
{/* Current price dashed line */}
— Price
{ma20 && -- MA20}
{ma50 && -- MA50}
{bb_upper && -- Bollinger}
)
}