n봉 침체 터치 조건 추가

This commit is contained in:
Macbook
2026-06-12 09:29:59 +09:00
parent d741d3fec6
commit 94934d8ce5
7 changed files with 109 additions and 6 deletions
@@ -36,6 +36,8 @@ public class LiveConditionStatusService {
Map.entry("CROSS_UP", "상향 돌파"),
Map.entry("CROSS_DOWN", "하향 돌파"),
Map.entry("SLOPE_UP", "상승 중"),
Map.entry("LOWEST_LTE", "N봉 최저 ≤"),
Map.entry("LOWEST_GTE", "N봉 최저 ≥"),
Map.entry("SLOPE_DOWN", "하락 중")
);
@@ -411,6 +411,7 @@ public class StrategyDslToTa4jAdapter {
int rightPeriod = cond.path("rightPeriod").asInt(-1);
int slopePeriod = cond.path("slopePeriod").asInt(3);
int holdDays = cond.path("holdDays").asInt(3);
int lookbackPeriod = cond.path("lookbackPeriod").asInt(20);
if (needsCrossTimeframeComposite(cond, ctx)) {
return buildCrossTimeframeCompositeRule(cond, ctx);
@@ -468,6 +469,16 @@ public class StrategyDslToTa4jAdapter {
new ConstantIndicator<>(series, series.numFactory().numOf(v)));
}
case "HOLD_N_DAYS" -> buildHoldRule(new OverIndicatorRule(left, right), holdDays);
case "LOWEST_LTE" -> {
Indicator<Num> rollingMin = new LowestValueIndicator(left, lookbackPeriod);
yield new OrRule(new UnderIndicatorRule(rollingMin, right),
buildEqRule(rollingMin, right, series));
}
case "LOWEST_GTE" -> {
Indicator<Num> rollingMin = new LowestValueIndicator(left, lookbackPeriod);
yield new OrRule(new OverIndicatorRule(rollingMin, right),
buildEqRule(rollingMin, right, series));
}
// ── 일목균형표 전용 ────────────────────────────────────────────
case "ABOVE_CLOUD" -> buildCloudAboveRule(series, indParams);
case "BELOW_CLOUD" -> buildCloudBelowRule(series, indParams);
@@ -288,6 +288,28 @@ class ComplexStrategyDslAdapterTest {
assertDoesNotThrow(() -> rule.isSatisfied(primary1m.getEndIndex(), null));
}
@Test
void stochLowestLte_compilesAndEvaluates() throws Exception {
JsonNode cond = MAPPER.readTree("""
{
"id": "c-stoch-lowest",
"type": "CONDITION",
"condition": {
"indicatorType": "STOCHASTIC",
"conditionType": "LOWEST_LTE",
"leftField": "STOCH_K",
"rightField": "HL_UNDER",
"lookbackPeriod": 20,
"candleRange": 1
}
}
""");
Rule rule = adapter.toRule(cond, primary1m, Map.of());
assertNotNull(rule);
assertDoesNotThrow(() -> evaluateRange(rule, primary1m.getEndIndex()));
}
// ── helpers ────────────────────────────────────────────────────────────────
private static void evaluateRange(Rule rule, int endIndex) {