Skip to main content
Glama
emerzon

MetaTrader5 MCP Server

by emerzon
OHLCChart.tsx5.04 kB
import { createChart, IChartApi, LineStyle, Time, UTCTimestamp } from 'lightweight-charts' import { useEffect, useRef } from 'react' import type { HistoryBar } from '../types' export type OHLCChartProps = { data: HistoryBar[] onAnchor?: (t: number) => void onNeedMoreLeft?: (earliestTime: number) => void overlays?: { name: string; points: { time: number; value: number }[]; color?: string; lineWidth?: number; lineStyle?: 'solid' | 'dashed' | 'dotted'; priceScaleId?: string }[] anchorTime?: number } export function OHLCChart({ data, onAnchor, onNeedMoreLeft, overlays, anchorTime }: OHLCChartProps) { const ref = useRef<HTMLDivElement | null>(null) const apiRef = useRef<IChartApi | null>(null) const candleRef = useRef<any>(null) const anchorRef = useRef<any>(null) useEffect(() => { if (!ref.current) return const chart = createChart(ref.current, { autoSize: true, layout: { background: { color: '#0f172a' }, textColor: '#a3b3c7' }, grid: { vertLines: { color: '#1f2937' }, horzLines: { color: '#1f2937' } }, crosshair: { mode: 1 }, rightPriceScale: { borderColor: '#1f2937' }, // Show time of day on the axis; toggle seconds later based on data granularity timeScale: { borderColor: '#1f2937', timeVisible: true, secondsVisible: true }, }) const series = chart.addCandlestickSeries({ upColor: '#22c55e', downColor: '#ef4444', borderVisible: false, wickUpColor: '#22c55e', wickDownColor: '#ef4444' }) apiRef.current = chart candleRef.current = series const clickSub = chart.subscribeClick((p) => { if (!p || p.time === undefined) return const t = (p.time as UTCTimestamp) as number onAnchor?.(t) }) const rangeSub = chart.timeScale().subscribeVisibleTimeRangeChange((r) => { if (!r || !onNeedMoreLeft) return const from = r.from as number | undefined if (from && data.length > 0) { const earliest = data[0]?.time // When user scrolls close to the left edge, request more if (from <= earliest + 2) { onNeedMoreLeft(earliest) } } }) return () => { chart.unsubscribeClick(clickSub) chart.timeScale().unsubscribeVisibleTimeRangeChange(rangeSub) chart.remove() apiRef.current = null candleRef.current = null } }, []) useEffect(() => { if (!candleRef.current) return const series = candleRef.current const points = data.map((b) => ({ time: b.time as Time, open: b.open, high: b.high, low: b.low, close: b.close })) series.setData(points) // Adjust seconds visibility based on detected bar spacing if (apiRef.current && data.length >= 2) { const dt = Math.abs(Math.floor(data[1].time) - Math.floor(data[0].time)) const secondsVisible = dt < 60 // e.g., tick/second data apiRef.current.applyOptions({ timeScale: { timeVisible: true, secondsVisible } }) } }, [data]) useEffect(() => { if (!apiRef.current) return const chart = apiRef.current const overlaySeries: any[] = [] overlays?.forEach((ov) => { if (!ov?.points?.length) return const style = ov.lineStyle === 'dashed' ? LineStyle.Dashed : ov.lineStyle === 'dotted' ? LineStyle.Dotted : LineStyle.Solid const series = chart.addLineSeries({ color: ov.color || '#60a5fa', lineWidth: ov.lineWidth ?? 2, lineStyle: style, priceScaleId: ov.priceScaleId || 'right', }) series.setData( ov.points .filter((p) => Number.isFinite(p.time) && Number.isFinite(p.value)) .map((p) => ({ time: (Math.floor(p.time) as unknown as UTCTimestamp) as Time, value: p.value, })), ) overlaySeries.push(series) }) return () => { overlaySeries.forEach((series) => chart.removeSeries(series)) } }, [overlays]) // Anchor vertical marker using a 1-candle series with long wick spanning min..max useEffect(() => { const chart = apiRef.current if (!chart) return if (anchorRef.current) { chart.removeSeries(anchorRef.current) anchorRef.current = null } if (!data?.length || !Number.isFinite(anchorTime as number)) return const minLow = Math.min(...data.map(d => d.low)) const maxHigh = Math.max(...data.map(d => d.high)) const center = (minLow + maxHigh) / 2 const s = chart.addCandlestickSeries({ upColor: '#facc15', downColor: '#facc15', borderVisible: false, wickUpColor: '#facc15', wickDownColor: '#facc15', priceScaleId: 'right', }) s.setData([{ time: (Math.floor(anchorTime as number) as unknown as UTCTimestamp) as Time, open: center, high: maxHigh, low: minLow, close: center }]) anchorRef.current = s return () => { if (anchorRef.current) { chart.removeSeries(anchorRef.current) anchorRef.current = null } } }, [anchorTime, data]) return <div className="w-full h-[520px]" ref={ref} /> }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/emerzon/mt-data-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server