From dafb1e49af4a552caa8b2341e91479bfedba3f66 Mon Sep 17 00:00:00 2001 From: Macbook Date: Thu, 11 Jun 2026 17:48:21 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EB=B0=B1=ED=85=8C=EC=8A=A4=ED=8C=85=20?= =?UTF-8?q?=EC=8B=9C=20=EC=9D=B8=EB=94=94=EC=BC=80=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=EB=A5=BC=20DB=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=9E=90=EB=8F=99=20=EB=A1=9C=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BacktestingService에 IndicatorSettingsService를 주입하여 백테스팅 실행 시 deviceId 기반으로 DB 저장 인디케이터 설정을 자동으로 로드한다. - 프론트엔드가 indicatorParams를 전달하지 않아도 DB 저장값 사용 보장 - 요청에 포함된 indicatorParams는 DB값 위에 override로 적용(우선순위 높음) - 어떠한 경우에도 백엔드 하드코딩 기본값만으로 테스트되는 상황 방지 - mergeIndicatorParams() 헬퍼로 DB+요청 파라미터 내부 필드 단위 병합 Co-authored-by: Cursor --- .../com/goldenchart/dto/BacktestRequest.java | 5 +- .../service/BacktestingService.java | 47 ++++++++++++++++++- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/com/goldenchart/dto/BacktestRequest.java b/backend/src/main/java/com/goldenchart/dto/BacktestRequest.java index 9019673..1d4e247 100644 --- a/backend/src/main/java/com/goldenchart/dto/BacktestRequest.java +++ b/backend/src/main/java/com/goldenchart/dto/BacktestRequest.java @@ -39,9 +39,10 @@ public class BacktestRequest { private String timeframe; /** - * 지표 파라미터 오버라이드. + * 지표 파라미터 오버라이드 (선택). * key = indicatorType (e.g. "CCI"), value = {length:13, ...} - * 없으면 IndicatorService 기본값 사용. + * BacktestingService 가 deviceId 기반으로 DB 저장값을 자동 로드하므로 + * 보통 생략해도 되며, 명시 시 DB 값 위에 덮어쓴다(우선 적용). */ private Map> indicatorParams; diff --git a/backend/src/main/java/com/goldenchart/service/BacktestingService.java b/backend/src/main/java/com/goldenchart/service/BacktestingService.java index d383929..acc511e 100644 --- a/backend/src/main/java/com/goldenchart/service/BacktestingService.java +++ b/backend/src/main/java/com/goldenchart/service/BacktestingService.java @@ -45,6 +45,7 @@ public class BacktestingService { private final GcStrategyRepository strategyRepository; private final GcBacktestResultRepository resultRepository; private final ObjectMapper objectMapper; + private final IndicatorSettingsService indicatorSettingsService; private static final BacktestSettingsDto DEFAULT_SETTINGS = new BacktestSettingsDto(); @@ -76,8 +77,20 @@ public class BacktestingService { } } - Map> params = req.getIndicatorParams() != null - ? req.getIndicatorParams() : Map.of(); + // DB 저장 인디케이터 설정을 기본으로 로드 (디바이스별 저장값 → 하드코딩 기본값 방지) + Map> dbParams = Map.of(); + if (req.getDeviceId() != null && !req.getDeviceId().isBlank()) { + try { + dbParams = indicatorSettingsService.getAll(null, req.getDeviceId()); + } catch (Exception e) { + log.warn("[Backtest] 인디케이터 설정 DB 로드 실패 (deviceId={}): {}", req.getDeviceId(), e.getMessage()); + } + } + // 요청에 포함된 파라미터가 있으면 DB 값 위에 덮어씀 (요청값 우선) + Map> params = mergeIndicatorParams(dbParams, req.getIndicatorParams()); + if (params.isEmpty()) { + log.warn("[Backtest] 인디케이터 파라미터 없음 — deviceId={}, 지표 기본값 사용 가능성 있음", req.getDeviceId()); + } BacktestSettingsDto cfg = req.getSettings() != null ? req.getSettings() : DEFAULT_SETTINGS; @@ -814,6 +827,36 @@ public class BacktestingService { }; } + /** + * DB 기본 파라미터 위에 요청 파라미터를 병합한다 (요청값 우선). + * + *
    + *
  • base: DB에서 로드한 사용자 저장 인디케이터 파라미터
  • + *
  • override: 요청에 포함된 파라미터 (없으면 null)
  • + *
+ * 같은 indicatorType 키가 있을 경우 override 내부 필드가 base를 덮어씌운다. + */ + private static Map> mergeIndicatorParams( + Map> base, + Map> override) { + + if (override == null || override.isEmpty()) return base; + if (base == null || base.isEmpty()) return override; + + Map> merged = new java.util.LinkedHashMap<>(base); + override.forEach((type, overrideParams) -> { + Map baseParams = merged.get(type); + if (baseParams == null || baseParams.isEmpty()) { + merged.put(type, overrideParams); + } else { + Map inner = new java.util.LinkedHashMap<>(baseParams); + inner.putAll(overrideParams); + merged.put(type, inner); + } + }); + return merged; + } + private BacktestResponse emptyResponse(String reason) { log.warn("[BacktestingService] 빈 결과: {}", reason); BacktestAnalysisDto emptyAnalysis = BacktestAnalysisDto.builder().build();