fix: 백테스트 시간봉·캔들 수 불일치로 시그널 누락 문제 해결

- 전략 DSL 시간봉(5m)과 실행 시간봉(3m) 불일치 시 자동 동기화
- 업비트 캔들 200봉 제한 → 페이지네이션으로 800봉까지 조회
- 백테스트 차트는 실행 타임프레임 기준으로 표시 (시그널·지표 정렬)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Macbook
2026-06-11 18:16:53 +09:00
parent 44c46eee1b
commit b34bdda073
4 changed files with 70 additions and 12 deletions
@@ -51,6 +51,7 @@ import { getKoreanName } from '../utils/marketNameCache';
import { repairUtf8Mojibake } from '../utils/textEncoding';
import { enrichStrategyNameMap, strategyNamesFromList } from '../utils/strategyNameResolver';
import { markStrategyIdsMissingUnlessValid } from '../utils/strategyMissingCache';
import { resolveStrategyPrimaryTimeframe } from '../utils/strategyToChartIndicators';
const LEFT_KEY = 'btd-left-width';
const RIGHT_KEY = 'btd-right-width';
@@ -213,6 +214,15 @@ export function BacktestHistoryPage({ theme = 'dark' }: Props) {
useEffect(() => { void fetchAll(); }, [fetchAll]);
// 전략 선택 시 DSL 기준 시간봉으로 자동 동기화 (예: 전략 4=5m 조건인데 3m 실행 방지)
useEffect(() => {
if (!runStrategyId) return;
const strat = strategies.find(s => s.id === runStrategyId);
if (!strat) return;
const tf = resolveStrategyPrimaryTimeframe(strat);
setRunTimeframe(prev => (prev === tf ? prev : tf));
}, [runStrategyId, strategies]);
useEffect(() => {
const onTradesChanged = () => { void refreshLiveTrades(); };
window.addEventListener(PAPER_TRADES_CHANGED_EVENT, onTradesChanged);
@@ -234,12 +244,14 @@ export function BacktestHistoryPage({ theme = 'dark' }: Props) {
setRunLoading(true);
setRunError(null);
try {
const strategy = strategies.find(s => s.id === runStrategyId);
const execTimeframe = strategy ? resolveStrategyPrimaryTimeframe(strategy) : runTimeframe;
const [settings, indicatorParams, barsRes] = await Promise.all([
loadBacktestSettings(),
loadIndicatorSettings(),
fetch(`${API_BASE}/candles/history?${new URLSearchParams({
market: runMarket,
type: timeframeToCandleType(runTimeframe),
type: timeframeToCandleType(execTimeframe),
count: '800',
})}`),
]);
@@ -250,11 +262,10 @@ export function BacktestHistoryPage({ theme = 'dark' }: Props) {
if (bars.length < 5) {
throw new Error('캔들 데이터가 부족합니다. 잠시 후 다시 시도하거나 타임프레임을 변경해 주세요.');
}
const strategy = strategies.find(s => s.id === runStrategyId);
const result = await runBacktest({
strategyId: runStrategyId,
bars,
timeframe: runTimeframe,
timeframe: execTimeframe,
settings,
indicatorParams,
symbol: runMarket,