위젯 종료버튼 겹침문제 수정
This commit is contained in:
@@ -9,9 +9,10 @@ import {
|
||||
} from '../../utils/backendApi';
|
||||
import { loadAnalysisCandles } from '../../utils/analysisChartData';
|
||||
import { normalizeChartTimeframe } from '../../utils/backtestUiUtils';
|
||||
import { mergeWidgetTimeframeOptions } from '../../utils/chartWidgetTimeframes';
|
||||
import { resolveStrategyPrimaryTimeframe } from '../../utils/strategyToChartIndicators';
|
||||
import { resolveEvaluationFromLoadedBars } from '../../utils/backtestWarmup';
|
||||
import type { OHLCVBar, Theme } from '../../types';
|
||||
import type { OHLCVBar, Theme, Timeframe } from '../../types';
|
||||
import { useIndicatorSettings } from '../../hooks/useIndicatorSettings';
|
||||
import {
|
||||
DEFAULT_PAPER_OVERLAY_VISIBILITY,
|
||||
@@ -28,6 +29,8 @@ interface Props {
|
||||
theme?: Theme;
|
||||
/** 위젯 임베드 시 하단 줌/패닝 툴바 숨김 */
|
||||
showHoverToolbar?: boolean;
|
||||
/** 위젯 — 종목 우측 시간봉 선택 */
|
||||
enableTimeframePicker?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,12 +38,16 @@ interface Props {
|
||||
* 좌측(과거) 스크롤 시 추가 캔들·보조지표 로드 후 전체 구간 시그널 재계산.
|
||||
*/
|
||||
const PaperAnalysisChart: React.FC<Props> = ({
|
||||
market, strategyId, theme = 'dark', showHoverToolbar = true,
|
||||
market,
|
||||
strategyId,
|
||||
theme = 'dark',
|
||||
showHoverToolbar = true,
|
||||
enableTimeframePicker = false,
|
||||
}) => {
|
||||
const { getParams } = useIndicatorSettings();
|
||||
const [signals, setSignals] = useState<BacktestSignal[]>([]);
|
||||
const [strategy, setStrategy] = useState<StrategyDto | undefined>();
|
||||
const [timeframe, setTimeframe] = useState('1h');
|
||||
const [timeframe, setTimeframe] = useState<Timeframe>('1h');
|
||||
const [running, setRunning] = useState(false);
|
||||
const [historyLoading, setHistoryLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
@@ -53,8 +60,15 @@ const PaperAnalysisChart: React.FC<Props> = ({
|
||||
const historyDebounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const strategyRef = useRef(strategy);
|
||||
const strategyIdRef = useRef(strategyId);
|
||||
const timeframeRef = useRef(timeframe);
|
||||
strategyRef.current = strategy;
|
||||
strategyIdRef.current = strategyId;
|
||||
timeframeRef.current = timeframe;
|
||||
|
||||
const timeframeOptions = useMemo(
|
||||
() => mergeWidgetTimeframeOptions(strategy),
|
||||
[strategy],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!strategyId) {
|
||||
@@ -71,6 +85,11 @@ const PaperAnalysisChart: React.FC<Props> = ({
|
||||
return () => { cancelled = true; };
|
||||
}, [strategyId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!strategy) return;
|
||||
setTimeframe(normalizeChartTimeframe(resolveStrategyPrimaryTimeframe(strategy)));
|
||||
}, [strategyId, strategy?.id]);
|
||||
|
||||
const runSignalsForBars = useCallback(async (
|
||||
bars: OHLCVBar[],
|
||||
tf: string,
|
||||
@@ -139,8 +158,7 @@ const PaperAnalysisChart: React.FC<Props> = ({
|
||||
return;
|
||||
}
|
||||
let cancelled = false;
|
||||
const tf = normalizeChartTimeframe(resolveStrategyPrimaryTimeframe(strategy));
|
||||
setTimeframe(tf);
|
||||
const tf = normalizeChartTimeframe(timeframe);
|
||||
setError(null);
|
||||
|
||||
void (async () => {
|
||||
@@ -162,7 +180,7 @@ const PaperAnalysisChart: React.FC<Props> = ({
|
||||
cancelled = true;
|
||||
++backtestGenRef.current;
|
||||
};
|
||||
}, [market, strategyId, strategy, toTimeSec, runSignalsForBars]);
|
||||
}, [market, strategyId, strategy, timeframe, toTimeSec, runSignalsForBars]);
|
||||
|
||||
const handleToggleOverlay = useCallback((key: PaperOverlayToggleKey) => {
|
||||
setOverlayVisibility(prev => ({ ...prev, [key]: !prev[key] }));
|
||||
@@ -172,7 +190,7 @@ const PaperAnalysisChart: React.FC<Props> = ({
|
||||
const strat = strategyRef.current;
|
||||
const sid = strategyIdRef.current;
|
||||
if (!strat || !sid) return;
|
||||
const tf = normalizeChartTimeframe(resolveStrategyPrimaryTimeframe(strat));
|
||||
const tf = normalizeChartTimeframe(timeframeRef.current);
|
||||
if (historyDebounceRef.current) clearTimeout(historyDebounceRef.current);
|
||||
historyDebounceRef.current = setTimeout(() => {
|
||||
historyDebounceRef.current = null;
|
||||
@@ -180,6 +198,10 @@ const PaperAnalysisChart: React.FC<Props> = ({
|
||||
}, HISTORY_BACKTEST_DEBOUNCE_MS);
|
||||
}, [runSignalsForBars]);
|
||||
|
||||
const handleTimeframeChange = useCallback((tf: Timeframe) => {
|
||||
setTimeframe(tf);
|
||||
}, []);
|
||||
|
||||
useEffect(() => () => {
|
||||
if (historyDebounceRef.current) clearTimeout(historyDebounceRef.current);
|
||||
}, []);
|
||||
@@ -195,6 +217,7 @@ const PaperAnalysisChart: React.FC<Props> = ({
|
||||
}
|
||||
|
||||
const statusBusy = running || historyLoading;
|
||||
const chartTimeframe = normalizeChartTimeframe(timeframe);
|
||||
|
||||
return (
|
||||
<div className="ptd-analysis-chart ptd-analysis-chart--backtest">
|
||||
@@ -208,7 +231,7 @@ const PaperAnalysisChart: React.FC<Props> = ({
|
||||
)}
|
||||
<BacktestAnalysisChart
|
||||
symbol={market}
|
||||
timeframe={timeframe}
|
||||
timeframe={chartTimeframe}
|
||||
toTimeSec={toTimeSec}
|
||||
barCount={BAR_COUNT}
|
||||
signals={signals}
|
||||
@@ -219,6 +242,8 @@ const PaperAnalysisChart: React.FC<Props> = ({
|
||||
overlayVisibility={overlayVisibility}
|
||||
onToggleOverlay={handleToggleOverlay}
|
||||
showHoverToolbar={showHoverToolbar}
|
||||
timeframeOptions={enableTimeframePicker ? timeframeOptions : undefined}
|
||||
onTimeframeChange={enableTimeframePicker ? handleTimeframeChange : undefined}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user