일목균형표 전략 추가

This commit is contained in:
Macbook
2026-06-23 20:42:04 +09:00
parent d352b01b3c
commit 3e26373bfe
18 changed files with 674 additions and 31 deletions
@@ -487,6 +487,10 @@ public class StrategyDslToTa4jAdapter {
Map<String, Object> indParams = condNodeParams.isEmpty() ? globalParams
: mergeParams(globalParams, condNodeParams);
if ("ICHIMOKU_BB".equals(indType)) {
return buildIchimokuBbRule(series, ctx, cond, condType, candleRangeMode, candleRange);
}
try {
Indicator<Num> left = resolveField(leftField, indType, indParams, series, condPeriod, leftPeriod, cond, ctx);
Indicator<Num> right = resolveField(rightField, indType, indParams, series, condPeriod, rightPeriod, cond, ctx);
@@ -1138,6 +1142,54 @@ public class StrategyDslToTa4jAdapter {
return new CrossedUpIndicatorRule(close, priorCloudTop);
}
/**
* 일목 후행스팬(현재 종가) vs N봉 전 볼린저밴드 — 상향/하향 돌파·위/아래 유지.
* cond.params.chikouDisplacement (기본 26), rightField: UPPER_BAND | MIDDLE_BAND | LOWER_BAND
*/
private Rule buildIchimokuBbRule(
BarSeries series,
RuleBuildContext ctx,
JsonNode cond,
String condType,
String candleRangeMode,
int candleRange) {
Map<String, Map<String, Object>> allParams = ctx.indicatorParams();
Map<String, Object> ichGlobal = allParams != null
? allParams.getOrDefault("IchimokuCloud", Map.of())
: Map.of();
Map<String, Object> bbGlobal = allParams != null
? allParams.getOrDefault("BollingerBands", Map.of())
: Map.of();
Map<String, Object> nodeParams = extractConditionNodeParams(cond);
Map<String, Object> ichParams = nodeParams.isEmpty() ? ichGlobal
: mergeParams(ichGlobal, nodeParams);
Map<String, Object> bbParams = nodeParams.isEmpty() ? bbGlobal
: mergeParams(bbGlobal, nodeParams);
int d = intP(ichParams, "chikouDisplacement",
ichimokuChikouDisplacement(ichParams));
String bandField = cond.path("rightField").asText("UPPER_BAND");
if (!"UPPER_BAND".equals(bandField) && !"MIDDLE_BAND".equals(bandField) && !"LOWER_BAND".equals(bandField)) {
bandField = "UPPER_BAND";
}
ClosePriceIndicator close = new ClosePriceIndicator(series);
Indicator<Num> bbLine = resolveField(bandField, "BOLLINGER", bbParams, series, -1, -1, cond, ctx);
Indicator<Num> priorBb = new PreviousValueIndicator(bbLine, d);
Rule core = switch (condType) {
case "CROSS_UP" -> buildCrossUpRule(close, priorBb);
case "CROSS_DOWN" -> buildCrossDownRule(close, priorBb);
case "GT", "GTE" -> new OverIndicatorRule(close, priorBb);
case "LT", "LTE" -> new UnderIndicatorRule(close, priorBb);
default -> {
log.warn("[Adapter] ICHIMOKU_BB 미지원 conditionType: {}", condType);
yield new BooleanRule(false);
}
};
return applyCandleRangeWindow(core, candleRangeMode, candleRange, condType);
}
/** 종가가 구름 위 */
private Rule buildCloudAboveRule(BarSeries s, Map<String, Object> p) {
NumericIndicator cloudTop = NumericIndicator.of(ichimokuSpanA(s, p)).max(ichimokuSpanB(s, p));