전략평가 툴바 적용

This commit is contained in:
Macbook
2026-06-17 01:57:15 +09:00
parent ec7355aab7
commit 89db874759
@@ -22,7 +22,18 @@ import {
} from '../../utils/backtestWarmup'; } from '../../utils/backtestWarmup';
import type { EvalIndicatorParams } from '../../utils/strategyEvaluationParams'; import type { EvalIndicatorParams } from '../../utils/strategyEvaluationParams';
import { DISPLAY_COUNT } from '../../hooks/useUpbitData'; import { DISPLAY_COUNT } from '../../hooks/useUpbitData';
import { buildVirtualTradingChartIndicators } from '../../utils/strategyToChartIndicators'; import {
chartOverlayKeyForType,
DEFAULT_CHART_OVERLAY_VISIBILITY,
effectiveConfigForOverlay,
listChartOverlayToggleItems,
type ChartOverlayToggleKey,
type ChartOverlayVisibility,
} from '../../utils/chartOverlayVisibility';
import {
buildVirtualTradingChartIndicators,
ensurePaperChartOverlays,
} from '../../utils/strategyToChartIndicators';
import { buildEvalParamsFromStrategy } from '../../utils/strategyEvaluationParams'; import { buildEvalParamsFromStrategy } from '../../utils/strategyEvaluationParams';
import { indicatorDefaultsFingerprint } from '../../utils/indicatorDefaultsFingerprint'; import { indicatorDefaultsFingerprint } from '../../utils/indicatorDefaultsFingerprint';
import { repairUtf8Mojibake } from '../../utils/textEncoding'; import { repairUtf8Mojibake } from '../../utils/textEncoding';
@@ -138,17 +149,59 @@ const StrategyEvaluationChart: React.FC<Props> = ({
const [magnifierActive, setMagnifierActive] = useState(false); const [magnifierActive, setMagnifierActive] = useState(false);
const marketBtnRef = useRef<HTMLButtonElement>(null); const marketBtnRef = useRef<HTMLButtonElement>(null);
const managerRef = useRef<ChartManager | null>(null); const managerRef = useRef<ChartManager | null>(null);
const [overlayVisibility, setOverlayVisibility] = useState<ChartOverlayVisibility>(
() => ({ ...DEFAULT_CHART_OVERLAY_VISIBILITY }),
);
const overlayVisibilityRef = useRef(overlayVisibility);
useEffect(() => {
overlayVisibilityRef.current = overlayVisibility;
}, [overlayVisibility]);
const backtestGenRef = useRef(0); const backtestGenRef = useRef(0);
const evaluationBarCountRef = useRef(BACKTEST_DISPLAY_BAR_COUNT); const evaluationBarCountRef = useRef(BACKTEST_DISPLAY_BAR_COUNT);
const signalsRef = useRef(signals); const signalsRef = useRef(signals);
signalsRef.current = signals; signalsRef.current = signals;
const chartType: ChartType = 'candlestick'; const chartType: ChartType = 'candlestick';
const indicators = useMemo(() => { const baseIndicators = useMemo(() => {
if (!strategy) return [] as IndicatorConfig[]; if (!strategy) return [] as IndicatorConfig[];
return buildVirtualTradingChartIndicators(strategy, getParams, getVisualConfig); let inds = buildVirtualTradingChartIndicators(strategy, getParams, getVisualConfig);
inds = ensurePaperChartOverlays(inds, getParams, getVisualConfig);
return inds;
}, [strategy, getParams, getVisualConfig, settingsRevision]); }, [strategy, getParams, getVisualConfig, settingsRevision]);
const indicators = useMemo(
() => baseIndicators.map(ind => effectiveConfigForOverlay(ind, overlayVisibility)),
[baseIndicators, overlayVisibility],
);
const indicatorsRef = useRef(indicators);
useEffect(() => {
indicatorsRef.current = indicators;
}, [indicators]);
const candleOverlayToggles = useMemo(
() => listChartOverlayToggleItems(overlayVisibility),
[overlayVisibility],
);
const handleToggleCandleOverlay = useCallback((key: ChartOverlayToggleKey) => {
setOverlayVisibility(prev => {
const next = { ...prev, [key]: !prev[key] };
const mgr = managerRef.current;
mgr?.setChartOverlayGroupVisible(key, next[key]);
if (mgr) {
for (const info of mgr.getIndicatorPaneInfo()) {
if (chartOverlayKeyForType(info.type) !== key) continue;
const reactInd = indicatorsRef.current.find(i => i.id === info.id);
mgr.applyIndicatorStyle(reactInd
? { ...info.config, ...reactInd, id: info.id, type: info.type }
: info.config);
}
}
return next;
});
}, []);
const auxPaneCount = useMemo( const auxPaneCount = useMemo(
() => countNonOverlayIndicatorPanes(indicators, isOverlayType), () => countNonOverlayIndicatorPanes(indicators, isOverlayType),
[indicators], [indicators],
@@ -313,6 +366,7 @@ const StrategyEvaluationChart: React.FC<Props> = ({
const onManagerReady = useCallback((mgr: ChartManager) => { const onManagerReady = useCallback((mgr: ChartManager) => {
managerRef.current = mgr; managerRef.current = mgr;
setChartMgr(mgr); setChartMgr(mgr);
mgr.setChartOverlayVisibility(overlayVisibilityRef.current);
if (paneAreaRatio && paneAreaRatio.aux > 0) { if (paneAreaRatio && paneAreaRatio.aux > 0) {
mgr.setPaneAreaRatio(paneAreaRatio.candle, paneAreaRatio.aux); mgr.setPaneAreaRatio(paneAreaRatio.candle, paneAreaRatio.aux);
} }
@@ -568,6 +622,9 @@ const StrategyEvaluationChart: React.FC<Props> = ({
showHoverToolbar={false} showHoverToolbar={false}
showChartRightToolbar={false} showChartRightToolbar={false}
showCandlePaneControls={false} showCandlePaneControls={false}
showCandleOverlayControls
candleOverlayToggles={candleOverlayToggles}
onToggleCandleOverlay={handleToggleCandleOverlay}
magnifierEnabled={magnifierActive} magnifierEnabled={magnifierActive}
onMagnifierClose={() => setMagnifierActive(false)} onMagnifierClose={() => setMagnifierActive(false)}
resolveInitialDisplayCount={resolveInitialDisplayCount} resolveInitialDisplayCount={resolveInitialDisplayCount}