Spaces:
Running
Running
| import React from 'react' | |
| import { | |
| ComposedChart, | |
| Bar, | |
| Line, | |
| Cell, | |
| XAxis, | |
| YAxis, | |
| CartesianGrid, | |
| Tooltip, | |
| Legend, | |
| ReferenceLine, | |
| ResponsiveContainer, | |
| } from 'recharts' | |
| import { OHLCVPoint } from '../api/stockApi' | |
| interface Props { | |
| data: OHLCVPoint[] | |
| } | |
| const CustomTooltip = ({ active, payload, label }: any) => { | |
| if (!active || !payload?.length) return null | |
| const d: OHLCVPoint = payload[0]?.payload | |
| return ( | |
| <div className="bg-slate-800 border border-slate-600 rounded p-2 text-xs shadow-lg"> | |
| <p className="text-slate-300">{label}</p> | |
| {d.macd != null && ( | |
| <p>MACD: <span className="text-blue-400">{d.macd.toFixed(3)}</span></p> | |
| )} | |
| {d.macd_signal != null && ( | |
| <p>Signal: <span className="text-orange-400">{d.macd_signal.toFixed(3)}</span></p> | |
| )} | |
| {d.macd_hist != null && ( | |
| <p> | |
| Hist:{' '} | |
| <span className={d.macd_hist >= 0 ? 'text-green-400' : 'text-red-400'}> | |
| {d.macd_hist.toFixed(3)} | |
| </span> | |
| </p> | |
| )} | |
| </div> | |
| ) | |
| } | |
| export const MACDChart: React.FC<Props> = ({ data }) => { | |
| const len = data.length | |
| return ( | |
| <ResponsiveContainer width="100%" height={180}> | |
| <ComposedChart data={data} margin={{ top: 4, right: 16, left: 0, bottom: 0 }}> | |
| <CartesianGrid strokeDasharray="3 3" stroke="#1e293b" /> | |
| <XAxis | |
| dataKey="date" | |
| tick={{ fill: '#94a3b8', fontSize: 10 }} | |
| tickLine={false} | |
| tickFormatter={(val, idx) => { | |
| const step = Math.max(1, Math.floor(len / 10)) | |
| return idx % step === 0 ? val : '' | |
| }} | |
| interval={0} | |
| /> | |
| <YAxis | |
| tick={{ fill: '#94a3b8', fontSize: 10 }} | |
| tickLine={false} | |
| tickFormatter={(v) => v.toFixed(1)} | |
| width={40} | |
| /> | |
| <Tooltip content={<CustomTooltip />} /> | |
| <Legend | |
| wrapperStyle={{ fontSize: 12 }} | |
| formatter={(value) => <span style={{ color: '#94a3b8' }}>{value}</span>} | |
| /> | |
| <ReferenceLine y={0} stroke="#475569" strokeWidth={1} /> | |
| {/* MACD Histogram */} | |
| <Bar dataKey="macd_hist" name="Histogram" isAnimationActive={false} maxBarSize={4}> | |
| {data.map((d, i) => ( | |
| <Cell | |
| key={i} | |
| fill={(d.macd_hist ?? 0) >= 0 ? '#22c55e' : '#ef4444'} | |
| fillOpacity={0.7} | |
| /> | |
| ))} | |
| </Bar> | |
| {/* MACD Line */} | |
| <Line | |
| dataKey="macd" | |
| stroke="#60a5fa" | |
| strokeWidth={1.5} | |
| dot={false} | |
| name="MACD" | |
| isAnimationActive={false} | |
| connectNulls | |
| /> | |
| {/* Signal Line */} | |
| <Line | |
| dataKey="macd_signal" | |
| stroke="#fb923c" | |
| strokeWidth={1.5} | |
| dot={false} | |
| name="Signal" | |
| isAnimationActive={false} | |
| connectNulls | |
| /> | |
| </ComposedChart> | |
| </ResponsiveContainer> | |
| ) | |
| } | |