import type { HLineStyle, PlotDef } from './indicatorRegistry'; const DEFAULT_HIST_UP = '#26A69A'; const DEFAULT_HIST_DOWN = '#EF5350'; /** 업비트/트레이딩뷰 스타일 색상 팔레트 (10×7) */ export const COLOR_PALETTE: string[] = [ '#FFFFFF', '#F5F5F5', '#E0E3EB', '#B2B5BE', '#9598A1', '#787B86', '#5D606B', '#434651', '#2A2E39', '#131722', '#FCE4EC', '#FFCDD2', '#EF9A9A', '#E57373', '#EF5350', '#F44336', '#E53935', '#D32F2F', '#C62828', '#B71C1C', '#FFF3E0', '#FFE0B2', '#FFCC80', '#FFB74D', '#FFA726', '#FF9800', '#FB8C00', '#F57C00', '#EF6C00', '#E65100', '#FFFDE7', '#FFF9C4', '#FFF59D', '#FFF176', '#FFEE58', '#FFEB3B', '#FDD835', '#FBC02D', '#F9A825', '#F57F17', '#E8F5E9', '#C8E6C9', '#A5D6A7', '#81C784', '#66BB6A', '#4CAF50', '#43A047', '#388E3C', '#2E7D32', '#1B5E20', '#E0F7FA', '#B2EBF2', '#80DEEA', '#4DD0E1', '#26C6DA', '#00BCD4', '#00ACC1', '#0097A7', '#00838F', '#006064', '#E3F2FD', '#BBDEFB', '#90CAF9', '#64B5F6', '#42A5F5', '#2196F3', '#1E88E5', '#1976D2', '#1565C0', '#0D47A1', ]; export function parsePlotColor(value: string): { hex6: string; alpha: number } { const v = value.trim(); if (v.length >= 9 && v.startsWith('#')) { const hex6 = v.slice(0, 7); const alpha = Math.round(parseInt(v.slice(7, 9), 16) / 255 * 100); return { hex6, alpha: Math.max(0, Math.min(100, alpha)) }; } if (v.length >= 7 && v.startsWith('#')) { return { hex6: v.slice(0, 7), alpha: 100 }; } return { hex6: '#2962FF', alpha: 100 }; } export function formatPlotColor(hex6: string, alphaPercent: number): string { const h = hex6.length >= 7 ? hex6.slice(0, 7) : '#2962FF'; const a = Math.max(0, Math.min(100, alphaPercent)); const alphaHex = Math.round(a / 100 * 255).toString(16).padStart(2, '0'); return h + alphaHex; } export function plotColorCss(value: string): string { const v = value.trim(); if (/^rgba?\(/i.test(v) || /^hsla?\(/i.test(v)) return v; const { hex6, alpha } = parsePlotColor(value); if (alpha >= 100) return hex6; const r = parseInt(hex6.slice(1, 3), 16); const g = parseInt(hex6.slice(3, 5), 16); const b = parseInt(hex6.slice(5, 7), 16); return `rgba(${r},${g},${b},${(alpha / 100).toFixed(2)})`; } export const LINE_WIDTH_OPTIONS = [1, 2, 3, 4] as const; export const LINE_STYLE_OPTIONS: HLineStyle[] = ['solid', 'dashed', 'dotted']; export const LINE_STYLE_LABELS: Record = { solid: '실선', dashed: '점선', dotted: '도트', }; /** histogram 막대 색에 투명도(88) 보장 */ export function withHistogramAlpha(color: string): string { if (color.startsWith('rgba(') || color.startsWith('rgb(')) return color; if (color.length >= 9 && color.startsWith('#')) return color; if (color.length >= 7 && color.startsWith('#')) return `${color}88`; return `${color}88`; } export function resolveHistogramUpColor(plot: PlotDef): string { return plot.histogramUpColor ?? plot.color ?? DEFAULT_HIST_UP; } export function resolveHistogramDownColor(plot: PlotDef): string { return plot.histogramDownColor ?? DEFAULT_HIST_DOWN; } /** MACD 히스토그램 — histogramUp/DownColor 로 0선 위·아래 색 분리 */ export function isMacdDualHistogramPlot(plot: PlotDef): boolean { return plot.type === 'histogram' && plot.histogramUpColor != null && plot.histogramDownColor != null; } /** * histogram 막대 색. * - MACD(상·하 색 지정): 0선 기준 — 양수=상승색, 음수=하락색 (전봴 대비 혼합 없음) * - 기타: 전봴 대비 방향 + 음수 영역 하락색 */ export function histogramBarColor( value: number, prev: number | null | undefined, plot: PlotDef, ): string { if (isMacdDualHistogramPlot(plot)) { const raw = value < 0 ? resolveHistogramDownColor(plot) : resolveHistogramUpColor(plot); return withHistogramAlpha(raw); } const isDown = prev != null && !isNaN(prev) && value < prev; const isNeg = value < 0; const raw = (isDown || isNeg) ? resolveHistogramDownColor(plot) : resolveHistogramUpColor(plot); return withHistogramAlpha(raw); } export function mapHistogramSeriesData( filtered: Array<{ time: number; value: number; color?: string }>, plot: PlotDef, ): Array<{ time: import('lightweight-charts').Time; value: number; color: string }> { return filtered.map((p, idx, arr) => ({ time: p.time as import('lightweight-charts').Time, value: p.value, // lightweight-charts-indicators MACD 등이 막대별 color를 넣어도 설정(상승/하락) 색을 우선 color: histogramBarColor(p.value, idx > 0 ? arr[idx - 1].value : null, plot), })); }