백엔드 전략 조건 평가 버그 3건 수정
1. evaluateOverallRule: 5m 전략 평가 시 1m 고정 시리즈 사용 버그 수정 - DSL에서 주 시간봉(TIMEFRAME 노드 candleType)을 추출하여 해당 시리즈 사용 - 없으면 1m 폴백 유지 2. buildConditionRule: kLength 등 지표 파라미터를 조건 노드 params에서 우선 읽도록 수정 - 조건 DSL의 params 필드가 있으면 전역 indicator settings보다 우선 적용 - 서버 DB에 indicator settings 없어도 전략 저장 당시 값 사용 가능 3. LiveConditionController: deviceId 헤더를 indicatorSettingsService에 전달 - x-device-id 헤더를 읽어 device 단위 지표 설정 조회 지원 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -427,9 +427,14 @@ public class StrategyDslToTa4jAdapter {
|
||||
|
||||
// DSL 타입(STOCHASTIC 등) → DB 레지스트리 키(Stochastic 등) 변환 후 파라미터 조회
|
||||
String registryKey = toRegistryKey(indType);
|
||||
Map<String, Object> indParams = params != null
|
||||
Map<String, Object> globalParams = params != null
|
||||
? params.getOrDefault(registryKey, Map.of())
|
||||
: Map.of();
|
||||
// 조건 노드에 직접 저장된 params가 있으면 전역 설정보다 우선 적용
|
||||
// 예) {"kLength": 12, "smooth": 3} → 전역 Stochastic 설정(kLength=14)을 덮어씀
|
||||
Map<String, Object> condNodeParams = extractConditionNodeParams(cond);
|
||||
Map<String, Object> indParams = condNodeParams.isEmpty() ? globalParams
|
||||
: mergeParams(globalParams, condNodeParams);
|
||||
|
||||
try {
|
||||
Indicator<Num> left = resolveField(leftField, indType, indParams, series, condPeriod, leftPeriod, cond, ctx);
|
||||
@@ -1217,12 +1222,50 @@ public class StrategyDslToTa4jAdapter {
|
||||
private int intP(Map<String, Object> p, String k, int def) {
|
||||
if (p == null) return def;
|
||||
Object v = p.get(k);
|
||||
return v == null ? def : ((Number) v).intValue();
|
||||
if (v == null) return def;
|
||||
if (v instanceof Number n) return n.intValue();
|
||||
try { return Integer.parseInt(v.toString()); } catch (NumberFormatException e) { return def; }
|
||||
}
|
||||
|
||||
private double dblP(Map<String, Object> p, String k, double def) {
|
||||
if (p == null) return def;
|
||||
Object v = p.get(k);
|
||||
return v == null ? def : ((Number) v).doubleValue();
|
||||
if (v == null) return def;
|
||||
if (v instanceof Number n) return n.doubleValue();
|
||||
try { return Double.parseDouble(v.toString()); } catch (NumberFormatException e) { return def; }
|
||||
}
|
||||
|
||||
/**
|
||||
* 조건 노드 JSON에서 직접 저장된 파라미터를 추출한다.
|
||||
* 전략 편집기가 저장한 조건별 override params (예: {"kLength": 12}).
|
||||
* 없거나 객체가 아니면 빈 맵 반환.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, Object> extractConditionNodeParams(JsonNode cond) {
|
||||
if (cond == null || cond.isNull()) return Map.of();
|
||||
JsonNode paramsNode = cond.path("params");
|
||||
if (paramsNode.isMissingNode() || paramsNode.isNull() || !paramsNode.isObject()) {
|
||||
return Map.of();
|
||||
}
|
||||
try {
|
||||
Map<String, Object> result = new java.util.LinkedHashMap<>();
|
||||
paramsNode.fields().forEachRemaining(e -> {
|
||||
com.fasterxml.jackson.databind.JsonNode v = e.getValue();
|
||||
if (v.isNumber()) result.put(e.getKey(), v.numberValue());
|
||||
else if (v.isTextual()) result.put(e.getKey(), v.textValue());
|
||||
else if (v.isBoolean()) result.put(e.getKey(), v.booleanValue());
|
||||
});
|
||||
return result;
|
||||
} catch (Exception ex) {
|
||||
return Map.of();
|
||||
}
|
||||
}
|
||||
|
||||
/** globalParams 위에 overrides를 덮어쓴 새 맵 반환 */
|
||||
private Map<String, Object> mergeParams(Map<String, Object> global,
|
||||
Map<String, Object> overrides) {
|
||||
Map<String, Object> merged = new java.util.LinkedHashMap<>(global);
|
||||
merged.putAll(overrides);
|
||||
return merged;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user