백테스팅 오류 수정
This commit is contained in:
+30
-11
@@ -650,6 +650,9 @@ function App() {
|
|||||||
signals: BacktestSignal[];
|
signals: BacktestSignal[];
|
||||||
showPrice: boolean;
|
showPrice: boolean;
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
|
/** applyBacktestMarkersWhenReady rAF 재시도 시 최신 차트 종목·타임프레임 검증용 */
|
||||||
|
const chartContextRef = useRef({ symbol, timeframe });
|
||||||
|
chartContextRef.current = { symbol, timeframe };
|
||||||
|
|
||||||
const syncBacktestMarkersRef = useRef<() => void>(() => {});
|
const syncBacktestMarkersRef = useRef<() => void>(() => {});
|
||||||
|
|
||||||
@@ -658,17 +661,23 @@ function App() {
|
|||||||
payload: NonNullable<typeof btMarkerPayloadRef.current>,
|
payload: NonNullable<typeof btMarkerPayloadRef.current>,
|
||||||
attempt = 0,
|
attempt = 0,
|
||||||
) => {
|
) => {
|
||||||
|
btMarkerPayloadRef.current = payload;
|
||||||
|
const { symbol: curSym, timeframe: curTf } = chartContextRef.current;
|
||||||
|
if (payload.symbol !== curSym || payload.timeframe !== curTf) return;
|
||||||
|
|
||||||
const mgr = managerRef.current;
|
const mgr = managerRef.current;
|
||||||
if (!mgr || !mgr.hasMainSeries()) {
|
if (!mgr || !mgr.hasMainSeries()) {
|
||||||
if (attempt < 30) {
|
if (attempt < 120) {
|
||||||
requestAnimationFrame(() => applyBacktestMarkersWhenReady(payload, attempt + 1));
|
requestAnimationFrame(() => applyBacktestMarkersWhenReady(payload, attempt + 1));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
btMarkerPayloadRef.current = payload;
|
if (payload.symbol !== chartContextRef.current.symbol
|
||||||
|
|| payload.timeframe !== chartContextRef.current.timeframe) return;
|
||||||
mgr.setBacktestMarkers(payload.signals, payload.showPrice);
|
mgr.setBacktestMarkers(payload.signals, payload.showPrice);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
/** reloadAll 직후 등 — payload 가 있을 때만 재적용 (없을 때 clear 하지 않음, 경쟁 방지) */
|
||||||
const syncBacktestMarkers = useCallback(() => {
|
const syncBacktestMarkers = useCallback(() => {
|
||||||
const payload = btMarkerPayloadRef.current;
|
const payload = btMarkerPayloadRef.current;
|
||||||
if (
|
if (
|
||||||
@@ -678,9 +687,7 @@ function App() {
|
|||||||
payload.signals.length > 0
|
payload.signals.length > 0
|
||||||
) {
|
) {
|
||||||
applyBacktestMarkersWhenReady(payload);
|
applyBacktestMarkersWhenReady(payload);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
managerRef.current?.clearBacktestMarkers();
|
|
||||||
}, [symbol, timeframe, applyBacktestMarkersWhenReady]);
|
}, [symbol, timeframe, applyBacktestMarkersWhenReady]);
|
||||||
|
|
||||||
syncBacktestMarkersRef.current = syncBacktestMarkers;
|
syncBacktestMarkersRef.current = syncBacktestMarkers;
|
||||||
@@ -897,16 +904,18 @@ function App() {
|
|||||||
// 백테스팅 시그널 → ref 갱신 후 ChartManager 마커 동기화
|
// 백테스팅 시그널 → ref 갱신 후 ChartManager 마커 동기화
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (btMatchesChart && btSignals.length > 0) {
|
if (btMatchesChart && btSignals.length > 0) {
|
||||||
btMarkerPayloadRef.current = {
|
const payload = {
|
||||||
symbol,
|
symbol,
|
||||||
timeframe,
|
timeframe,
|
||||||
signals: btSignals,
|
signals: btSignals,
|
||||||
showPrice: appDefaults.btShowPrice,
|
showPrice: appDefaults.btShowPrice,
|
||||||
};
|
};
|
||||||
|
btMarkerPayloadRef.current = payload;
|
||||||
|
applyBacktestMarkersWhenReady(payload);
|
||||||
} else {
|
} else {
|
||||||
btMarkerPayloadRef.current = null;
|
btMarkerPayloadRef.current = null;
|
||||||
|
managerRef.current?.clearBacktestMarkers();
|
||||||
}
|
}
|
||||||
syncBacktestMarkers();
|
|
||||||
let innerRaf = 0;
|
let innerRaf = 0;
|
||||||
const outerRaf = requestAnimationFrame(() => {
|
const outerRaf = requestAnimationFrame(() => {
|
||||||
innerRaf = requestAnimationFrame(syncBacktestMarkers);
|
innerRaf = requestAnimationFrame(syncBacktestMarkers);
|
||||||
@@ -915,7 +924,7 @@ function App() {
|
|||||||
cancelAnimationFrame(outerRaf);
|
cancelAnimationFrame(outerRaf);
|
||||||
if (innerRaf) cancelAnimationFrame(innerRaf);
|
if (innerRaf) cancelAnimationFrame(innerRaf);
|
||||||
};
|
};
|
||||||
}, [btMatchesChart, btSignals, btRunSeq, symbol, timeframe, appDefaults.btShowPrice, syncBacktestMarkers]);
|
}, [btMatchesChart, btSignals, btRunSeq, symbol, timeframe, appDefaults.btShowPrice, applyBacktestMarkersWhenReady, syncBacktestMarkers]);
|
||||||
|
|
||||||
// ── 시뮬레이션 데이터 (Upbit 아닐 때) ──────────────────────────────────
|
// ── 시뮬레이션 데이터 (Upbit 아닐 때) ──────────────────────────────────
|
||||||
const [simBars, setSimBars] = useState<OHLCVBar[]>(() =>
|
const [simBars, setSimBars] = useState<OHLCVBar[]>(() =>
|
||||||
@@ -1716,12 +1725,14 @@ function App() {
|
|||||||
r.signals.length > 0
|
r.signals.length > 0
|
||||||
) {
|
) {
|
||||||
const showPrice = appDefaults.btShowPrice;
|
const showPrice = appDefaults.btShowPrice;
|
||||||
applyBacktestMarkersWhenReady({
|
const payload = {
|
||||||
symbol: runSymbol,
|
symbol: runSymbol,
|
||||||
timeframe: runTf,
|
timeframe: runTf,
|
||||||
signals: r.signals,
|
signals: r.signals,
|
||||||
showPrice,
|
showPrice,
|
||||||
});
|
};
|
||||||
|
btMarkerPayloadRef.current = payload;
|
||||||
|
applyBacktestMarkersWhenReady(payload);
|
||||||
}
|
}
|
||||||
if (appDefaults.btAutoPopup) setShowBtResult(true);
|
if (appDefaults.btAutoPopup) setShowBtResult(true);
|
||||||
}
|
}
|
||||||
@@ -1729,7 +1740,11 @@ function App() {
|
|||||||
onOpenBtSettings={() => setShowBtSettings(true)}
|
onOpenBtSettings={() => setShowBtSettings(true)}
|
||||||
onOpenBtResults={() => setShowBtResult(true)}
|
onOpenBtResults={() => setShowBtResult(true)}
|
||||||
hasBtResult={btMatchesChart}
|
hasBtResult={btMatchesChart}
|
||||||
onClearBtMarkers={() => { btClear(); managerRef.current?.clearBacktestMarkers(); }}
|
onClearBtMarkers={() => {
|
||||||
|
btMarkerPayloadRef.current = null;
|
||||||
|
btClear();
|
||||||
|
managerRef.current?.clearBacktestMarkers();
|
||||||
|
}}
|
||||||
onToggleLiveStrategy={() => setShowLivePanel(v => !v)}
|
onToggleLiveStrategy={() => setShowLivePanel(v => !v)}
|
||||||
liveStrategyActive={showLivePanel || monitoredMarkets.length > 0}
|
liveStrategyActive={showLivePanel || monitoredMarkets.length > 0}
|
||||||
/>
|
/>
|
||||||
@@ -2003,7 +2018,11 @@ function App() {
|
|||||||
<BacktestPanel
|
<BacktestPanel
|
||||||
stats={btStats}
|
stats={btStats}
|
||||||
signalCount={btSignals.length}
|
signalCount={btSignals.length}
|
||||||
onClear={() => { btClear(); managerRef.current?.clearBacktestMarkers(); }}
|
onClear={() => {
|
||||||
|
btMarkerPayloadRef.current = null;
|
||||||
|
btClear();
|
||||||
|
managerRef.current?.clearBacktestMarkers();
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -306,6 +306,7 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
|||||||
m.resetPaneHeights(w.clientHeight);
|
m.resetPaneHeights(w.clientHeight);
|
||||||
const fb = m.hasIchimoku() ? 28 : 0;
|
const fb = m.hasIchimoku() ? 28 : 0;
|
||||||
m.setInitialVisibleRange(DISPLAY_COUNT, fb);
|
m.setInitialVisibleRange(DISPLAY_COUNT, fb);
|
||||||
|
if (delay === 1400) onDataLoaded?.();
|
||||||
}, delay)
|
}, delay)
|
||||||
);
|
);
|
||||||
}, [applyPaneLayout, onDataLoaded, displayTimezone, timeframe, market]);
|
}, [applyPaneLayout, onDataLoaded, displayTimezone, timeframe, market]);
|
||||||
|
|||||||
Reference in New Issue
Block a user