obv 그래프 오류

This commit is contained in:
Macbook
2026-06-09 02:25:59 +09:00
parent 8670e58c78
commit 7c1cc2ee4b
4 changed files with 58 additions and 13 deletions
@@ -54,7 +54,7 @@ const TradeSignalMiniChart: React.FC<Props> = ({
}) => {
const { getParams, getVisualConfig } = useIndicatorSettings();
const { defaults: appDefaults } = useAppSettings();
const chartRealtimeSource = (appDefaults.chartRealtimeSource ?? 'BACKEND_STOMP') as ChartRealtimeSource;
const appChartSource = (appDefaults.chartRealtimeSource ?? 'BACKEND_STOMP') as ChartRealtimeSource;
const managerRef = useRef<ChartManager | null>(null);
const canvasWrapRef = useRef<HTMLDivElement | null>(null);
const [chartReloadTick, setChartReloadTick] = useState(0);
@@ -77,6 +77,9 @@ const TradeSignalMiniChart: React.FC<Props> = ({
[baseIndicators],
);
/** OBV 누적값 — Upbit REST 직접 (STOMP 백엔드 volume=0 이면 본선 미표시) */
const chartRealtimeSource: ChartRealtimeSource = needsDeepObv ? 'UPBIT_DIRECT' : appChartSource;
const {
indicators: chartIndicators,
candleOverlayToggles,
@@ -166,6 +169,14 @@ const TradeSignalMiniChart: React.FC<Props> = ({
barsMarketRef.current = barsMarket;
const barsReady = bars.length >= 2 && barsMarket === market;
const obvBarsReady = useMemo(() => {
if (!needsDeepObv) return true;
if (bars.length < 2) return false;
return bars.some(b => (Number(b.volume) || 0) > 0);
}, [needsDeepObv, bars]);
const chartDataReady = barsReady && obvBarsReady;
useLayoutEffect(() => {
chartLiveReadyRef.current = false;
pendingBarRef.current = null;
@@ -191,7 +202,7 @@ const TradeSignalMiniChart: React.FC<Props> = ({
if (!canvasWrapRef.current) return;
if (managerRef.current?.hasMainSeries()) {
syncChartLayout();
} else if (!chartReloadTriggeredRef.current && delay >= 600 && barsReady) {
} else if (!chartReloadTriggeredRef.current && delay >= 600 && chartDataReady) {
chartReloadTriggeredRef.current = true;
setChartReloadTick(t => t + 1);
}
@@ -204,15 +215,15 @@ const TradeSignalMiniChart: React.FC<Props> = ({
timers.forEach(clearTimeout);
ro.disconnect();
};
}, [market, timeframe, enabled, barsReady, syncChartLayout, fillHeight]);
}, [market, timeframe, enabled, chartDataReady, syncChartLayout, fillHeight]);
useEffect(() => {
if (!enabled || !barsReady) return;
if (!enabled || !chartDataReady) return;
if (!managerRef.current?.hasMainSeries() && !chartReloadTriggeredRef.current) {
chartReloadTriggeredRef.current = true;
setChartReloadTick(t => t + 1);
}
}, [enabled, barsReady]);
}, [enabled, chartDataReady]);
useEffect(() => {
if (!enabled) return;
@@ -246,13 +257,17 @@ const TradeSignalMiniChart: React.FC<Props> = ({
].filter(Boolean).join(' ')}
>
{isLoading && <div className="tnl-mini-chart-loading"></div>}
{needsDeepObv && !isLoading && !obvBarsReady && (
<div className="tnl-mini-chart-loading">OBV </div>
)}
{isLoadingMore && (
<div className="chart-history-loading">
<div className="loading-spinner" style={{ width: 12, height: 12 }} />
</div>
)}
{chartDataReady && (
<TradingChart
key={`${market}-${timeframe}-${chartReloadTick}-${chartIndicators.map(i => i.id).join(',')}`}
key={`${market}-${timeframe}-${chartReloadTick}-${chartRealtimeSource}-${needsDeepObv ? 'obv' : 'std'}-${chartIndicators.map(i => i.id).join(',')}`}
chartVisible
bars={bars}
barsMarket={barsMarket}
@@ -283,6 +298,7 @@ const TradeSignalMiniChart: React.FC<Props> = ({
onToggleCandleOverlay={handleToggleCandleOverlay}
crosshairInfoVisible={false}
/>
)}
</div>
);
};