fix: 백테스팅 시 인디케이터 파라미터를 DB에서 자동 로드
BacktestingService에 IndicatorSettingsService를 주입하여 백테스팅 실행 시 deviceId 기반으로 DB 저장 인디케이터 설정을 자동으로 로드한다. - 프론트엔드가 indicatorParams를 전달하지 않아도 DB 저장값 사용 보장 - 요청에 포함된 indicatorParams는 DB값 위에 override로 적용(우선순위 높음) - 어떠한 경우에도 백엔드 하드코딩 기본값만으로 테스트되는 상황 방지 - mergeIndicatorParams() 헬퍼로 DB+요청 파라미터 내부 필드 단위 병합 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -39,9 +39,10 @@ public class BacktestRequest {
|
|||||||
private String timeframe;
|
private String timeframe;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 지표 파라미터 오버라이드.
|
* 지표 파라미터 오버라이드 (선택).
|
||||||
* key = indicatorType (e.g. "CCI"), value = {length:13, ...}
|
* key = indicatorType (e.g. "CCI"), value = {length:13, ...}
|
||||||
* 없으면 IndicatorService 기본값 사용.
|
* BacktestingService 가 deviceId 기반으로 DB 저장값을 자동 로드하므로
|
||||||
|
* 보통 생략해도 되며, 명시 시 DB 값 위에 덮어쓴다(우선 적용).
|
||||||
*/
|
*/
|
||||||
private Map<String, Map<String, Object>> indicatorParams;
|
private Map<String, Map<String, Object>> indicatorParams;
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ public class BacktestingService {
|
|||||||
private final GcStrategyRepository strategyRepository;
|
private final GcStrategyRepository strategyRepository;
|
||||||
private final GcBacktestResultRepository resultRepository;
|
private final GcBacktestResultRepository resultRepository;
|
||||||
private final ObjectMapper objectMapper;
|
private final ObjectMapper objectMapper;
|
||||||
|
private final IndicatorSettingsService indicatorSettingsService;
|
||||||
|
|
||||||
private static final BacktestSettingsDto DEFAULT_SETTINGS = new BacktestSettingsDto();
|
private static final BacktestSettingsDto DEFAULT_SETTINGS = new BacktestSettingsDto();
|
||||||
|
|
||||||
@@ -76,8 +77,20 @@ public class BacktestingService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Map<String, Object>> params = req.getIndicatorParams() != null
|
// DB 저장 인디케이터 설정을 기본으로 로드 (디바이스별 저장값 → 하드코딩 기본값 방지)
|
||||||
? req.getIndicatorParams() : Map.of();
|
Map<String, Map<String, Object>> 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<String, Map<String, Object>> params = mergeIndicatorParams(dbParams, req.getIndicatorParams());
|
||||||
|
if (params.isEmpty()) {
|
||||||
|
log.warn("[Backtest] 인디케이터 파라미터 없음 — deviceId={}, 지표 기본값 사용 가능성 있음", req.getDeviceId());
|
||||||
|
}
|
||||||
|
|
||||||
BacktestSettingsDto cfg = req.getSettings() != null ? req.getSettings() : DEFAULT_SETTINGS;
|
BacktestSettingsDto cfg = req.getSettings() != null ? req.getSettings() : DEFAULT_SETTINGS;
|
||||||
|
|
||||||
@@ -814,6 +827,36 @@ public class BacktestingService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DB 기본 파라미터 위에 요청 파라미터를 병합한다 (요청값 우선).
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>base: DB에서 로드한 사용자 저장 인디케이터 파라미터</li>
|
||||||
|
* <li>override: 요청에 포함된 파라미터 (없으면 null)</li>
|
||||||
|
* </ul>
|
||||||
|
* 같은 indicatorType 키가 있을 경우 override 내부 필드가 base를 덮어씌운다.
|
||||||
|
*/
|
||||||
|
private static Map<String, Map<String, Object>> mergeIndicatorParams(
|
||||||
|
Map<String, Map<String, Object>> base,
|
||||||
|
Map<String, Map<String, Object>> override) {
|
||||||
|
|
||||||
|
if (override == null || override.isEmpty()) return base;
|
||||||
|
if (base == null || base.isEmpty()) return override;
|
||||||
|
|
||||||
|
Map<String, Map<String, Object>> merged = new java.util.LinkedHashMap<>(base);
|
||||||
|
override.forEach((type, overrideParams) -> {
|
||||||
|
Map<String, Object> baseParams = merged.get(type);
|
||||||
|
if (baseParams == null || baseParams.isEmpty()) {
|
||||||
|
merged.put(type, overrideParams);
|
||||||
|
} else {
|
||||||
|
Map<String, Object> inner = new java.util.LinkedHashMap<>(baseParams);
|
||||||
|
inner.putAll(overrideParams);
|
||||||
|
merged.put(type, inner);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return merged;
|
||||||
|
}
|
||||||
|
|
||||||
private BacktestResponse emptyResponse(String reason) {
|
private BacktestResponse emptyResponse(String reason) {
|
||||||
log.warn("[BacktestingService] 빈 결과: {}", reason);
|
log.warn("[BacktestingService] 빈 결과: {}", reason);
|
||||||
BacktestAnalysisDto emptyAnalysis = BacktestAnalysisDto.builder().build();
|
BacktestAnalysisDto emptyAnalysis = BacktestAnalysisDto.builder().build();
|
||||||
|
|||||||
Reference in New Issue
Block a user