전략편집기 기준값 보조지표 설정값 동기화
This commit is contained in:
@@ -96,6 +96,11 @@ public class StrategyDslToTa4jAdapter {
|
||||
* 매핑 없으면 원본 반환 (이미 레지스트리 형식인 경우).
|
||||
*/
|
||||
private static String toRegistryKey(String dslType) {
|
||||
return registryKeyForDsl(dslType);
|
||||
}
|
||||
|
||||
/** DSL indicatorType → DB 레지스트리 키 (외부 hline resolver용) */
|
||||
public static String registryKeyForDsl(String dslType) {
|
||||
return DSL_TO_REGISTRY.getOrDefault(dslType, dslType);
|
||||
}
|
||||
|
||||
@@ -104,9 +109,18 @@ public class StrategyDslToTa4jAdapter {
|
||||
public record RuleBuildContext(
|
||||
BarSeries primarySeries,
|
||||
Map<String, Map<String, Object>> indicatorParams,
|
||||
Map<String, Map<String, Object>> indicatorVisual,
|
||||
String market,
|
||||
Ta4jStorage storage
|
||||
) {
|
||||
/** visual 미전달 호환 */
|
||||
public RuleBuildContext(BarSeries primarySeries,
|
||||
Map<String, Map<String, Object>> indicatorParams,
|
||||
String market,
|
||||
Ta4jStorage storage) {
|
||||
this(primarySeries, indicatorParams, Map.of(), market, storage);
|
||||
}
|
||||
|
||||
BarSeries resolveSeries(String candleType) {
|
||||
String ct = LiveStrategyTimeframeService.normalize(candleType);
|
||||
if (storage != null && market != null && !market.isBlank()
|
||||
@@ -119,13 +133,20 @@ public class StrategyDslToTa4jAdapter {
|
||||
|
||||
public Rule toRule(JsonNode node, BarSeries series,
|
||||
Map<String, Map<String, Object>> indicatorParams) {
|
||||
return toRule(node, new RuleBuildContext(series, indicatorParams, null, null));
|
||||
return toRule(node, new RuleBuildContext(series, indicatorParams, Map.of(), null, null));
|
||||
}
|
||||
|
||||
public Rule toRule(JsonNode node, BarSeries series,
|
||||
Map<String, Map<String, Object>> indicatorParams,
|
||||
String market, Ta4jStorage storage) {
|
||||
return toRule(node, new RuleBuildContext(series, indicatorParams, market, storage));
|
||||
return toRule(node, new RuleBuildContext(series, indicatorParams, Map.of(), market, storage));
|
||||
}
|
||||
|
||||
public Rule toRule(JsonNode node, BarSeries series,
|
||||
Map<String, Map<String, Object>> indicatorParams,
|
||||
Map<String, Map<String, Object>> indicatorVisual,
|
||||
String market, Ta4jStorage storage) {
|
||||
return toRule(node, new RuleBuildContext(series, indicatorParams, indicatorVisual, market, storage));
|
||||
}
|
||||
|
||||
public Rule toRule(JsonNode node, RuleBuildContext ctx) {
|
||||
@@ -178,7 +199,7 @@ public class StrategyDslToTa4jAdapter {
|
||||
String ct = node.path("candleType").asText("1m");
|
||||
BarSeries branchSeries = ctx.resolveSeries(ct);
|
||||
RuleBuildContext branchCtx = new RuleBuildContext(
|
||||
branchSeries, ctx.indicatorParams(), ctx.market(), ctx.storage());
|
||||
branchSeries, ctx.indicatorParams(), ctx.indicatorVisual(), ctx.market(), ctx.storage());
|
||||
List<Rule> rules = childRules(node, branchCtx);
|
||||
if (rules.isEmpty()) return new BooleanRule(false);
|
||||
Rule inner = rules.get(0);
|
||||
@@ -243,22 +264,22 @@ public class StrategyDslToTa4jAdapter {
|
||||
|
||||
private Rule buildAndRule(JsonNode node, BarSeries series,
|
||||
Map<String, Map<String, Object>> p) {
|
||||
return buildAndRule(node, new RuleBuildContext(series, p, null, null));
|
||||
return buildAndRule(node, new RuleBuildContext(series, p, Map.of(), null, null));
|
||||
}
|
||||
|
||||
private Rule buildOrRule(JsonNode node, BarSeries series,
|
||||
Map<String, Map<String, Object>> p) {
|
||||
return buildOrRule(node, new RuleBuildContext(series, p, null, null));
|
||||
return buildOrRule(node, new RuleBuildContext(series, p, Map.of(), null, null));
|
||||
}
|
||||
|
||||
private Rule buildNotRule(JsonNode node, BarSeries series,
|
||||
Map<String, Map<String, Object>> p) {
|
||||
return buildNotRule(node, new RuleBuildContext(series, p, null, null));
|
||||
return buildNotRule(node, new RuleBuildContext(series, p, Map.of(), null, null));
|
||||
}
|
||||
|
||||
private List<Rule> childRules(JsonNode node, BarSeries series,
|
||||
Map<String, Map<String, Object>> p) {
|
||||
return childRules(node, new RuleBuildContext(series, p, null, null));
|
||||
return childRules(node, new RuleBuildContext(series, p, Map.of(), null, null));
|
||||
}
|
||||
|
||||
// ── CONDITION ─────────────────────────────────────────────────────────────
|
||||
@@ -299,8 +320,8 @@ public class StrategyDslToTa4jAdapter {
|
||||
: Map.of();
|
||||
|
||||
try {
|
||||
Indicator<Num> left = resolveField(leftField, indType, indParams, series, condPeriod, leftPeriod);
|
||||
Indicator<Num> right = resolveField(rightField, indType, indParams, series, condPeriod, rightPeriod);
|
||||
Indicator<Num> left = resolveField(leftField, indType, indParams, series, condPeriod, leftPeriod, cond, ctx);
|
||||
Indicator<Num> right = resolveField(rightField, indType, indParams, series, condPeriod, rightPeriod, cond, ctx);
|
||||
|
||||
Rule core = switch (condType) {
|
||||
case "GT" -> new OverIndicatorRule(left, right);
|
||||
@@ -447,8 +468,8 @@ public class StrategyDslToTa4jAdapter {
|
||||
BarSeries rightSeries = ctx.resolveSeries(rightCt);
|
||||
|
||||
try {
|
||||
Indicator<Num> left = resolveField(leftField, indType, indParams, leftSeries, condPeriod, leftPeriod);
|
||||
Indicator<Num> right = resolveField(rightField, indType, indParams, rightSeries, condPeriod, rightPeriod);
|
||||
Indicator<Num> left = resolveField(leftField, indType, indParams, leftSeries, condPeriod, leftPeriod, cond, ctx);
|
||||
Indicator<Num> right = resolveField(rightField, indType, indParams, rightSeries, condPeriod, rightPeriod, cond, ctx);
|
||||
return new CrossTimeframeCompositeRule(condType, left, right, trigger, leftSeries, rightSeries);
|
||||
} catch (Exception e) {
|
||||
log.warn("[Adapter] 복합 교차시간봉 빌드 실패 ind={} cond={}: {}",
|
||||
@@ -515,7 +536,8 @@ public class StrategyDslToTa4jAdapter {
|
||||
|
||||
private Indicator<Num> resolveField(String field, String indType,
|
||||
Map<String, Object> p, BarSeries s,
|
||||
int condPeriod, int sidePeriod) {
|
||||
int condPeriod, int sidePeriod,
|
||||
JsonNode cond, RuleBuildContext ctx) {
|
||||
if (field == null || field.isBlank() || field.equals("NONE")) {
|
||||
return new ConstantIndicator<>(s, s.numFactory().numOf(0));
|
||||
}
|
||||
@@ -526,6 +548,11 @@ public class StrategyDslToTa4jAdapter {
|
||||
case "LOW_PRICE" -> new LowPriceIndicator(s);
|
||||
case "VOLUME_VALUE" -> new VolumeIndicator(s, 1);
|
||||
default -> {
|
||||
Double hlineVal = IndicatorHlineResolver.resolveThresholdField(
|
||||
cond, field, indType, ctx.indicatorVisual());
|
||||
if (hlineVal != null) {
|
||||
yield new ConstantIndicator<>(s, s.numFactory().numOf(hlineVal));
|
||||
}
|
||||
double constant = resolveConstantField(field);
|
||||
if (!Double.isNaN(constant)) {
|
||||
yield new ConstantIndicator<>(s, s.numFactory().numOf(constant));
|
||||
@@ -535,6 +562,14 @@ public class StrategyDslToTa4jAdapter {
|
||||
};
|
||||
}
|
||||
|
||||
/** @deprecated cond/ctx 없이 호출 — hline 역할(HL_OVER) 미해석 */
|
||||
private Indicator<Num> resolveField(String field, String indType,
|
||||
Map<String, Object> p, BarSeries s,
|
||||
int condPeriod, int sidePeriod) {
|
||||
return resolveField(field, indType, p, s, condPeriod, sidePeriod, null,
|
||||
new RuleBuildContext(s, Map.of(), Map.of(), null, null));
|
||||
}
|
||||
|
||||
private double resolveConstantField(String field) {
|
||||
// K_ 접두사: 프론트엔드가 hline 실제값으로 생성한 상수 필드
|
||||
// 예) K_60 → 60, K_-100 → -100, K_0 → 0
|
||||
|
||||
Reference in New Issue
Block a user