전략평가 로직 개선

This commit is contained in:
Macbook
2026-06-05 10:59:23 +09:00
parent 5278177bbb
commit 0aaf4ac19c
14 changed files with 441 additions and 60 deletions
@@ -124,11 +124,19 @@ public class LiveConditionStatusService {
int matchRate = evaluable > 0 ? Math.round(100f * met / evaluable) : 0;
String tfSummary = String.join(", ", timeframes);
// [항목6] 전체 논리 트리 평가 — matchRate 와 달리 AND/OR/NOT 게이트 완전 반영
Boolean overallEntryMet = evaluateOverallRule(
strategy.getBuyConditionJson(), market, params, visual);
Boolean overallExitMet = evaluateOverallRule(
strategy.getSellConditionJson(), market, params, visual);
return LiveConditionStatusDto.builder()
.market(market)
.strategyId(strategyId)
.timeframe(tfSummary)
.matchRate(matchRate)
.overallEntryMet(overallEntryMet)
.overallExitMet(overallExitMet)
.rows(rows)
.updatedAt(System.currentTimeMillis())
.build();
@@ -145,6 +153,43 @@ public class LiveConditionStatusService {
.build();
}
// ── [항목6] 전체 논리 트리 평가 ────────────────────────────────────────────
/**
* 전략 DSL 전체를 Ta4j Rule 로 변환하여 현재 시계열에 대해 평가한다.
*
* <p>기존 {@code matchRate} 는 단순 CONDITION 리프 충족 비율이지만,
* 이 메서드는 AND/OR/NOT 게이트까지 완전히 반영하여 실제 시그널과 동일한
* 논리 결과를 반환한다.
*
* @return {@code true} = 현재 조건 충족, {@code false} = 미충족,
* {@code null} = 데이터 부족·평가 불가
*/
private Boolean evaluateOverallRule(String conditionJson, String market,
Map<String, Map<String, Object>> params,
Map<String, Map<String, Object>> visual) {
if (conditionJson == null || conditionJson.isBlank()) return null;
try {
com.fasterxml.jackson.databind.JsonNode dsl =
objectMapper.readTree(conditionJson);
if (dsl == null || dsl.isNull()) return null;
// 기준 시리즈: 1m 봉
if (!ta4jStorage.exists(market, "1m")) return null;
BarSeries series = ta4jStorage.getOrCreate(market, "1m");
if (series.isEmpty()) return null;
StrategyDslToTa4jAdapter.RuleBuildContext ctx =
new StrategyDslToTa4jAdapter.RuleBuildContext(
series, params, visual, market, ta4jStorage, false, java.util.Map.of());
org.ta4j.core.Rule rule = adapter.toRule(dsl, ctx);
return rule.isSatisfied(series.getEndIndex(), null);
} catch (Exception e) {
log.debug("[LiveCondition] overall rule eval fail market={}: {}", market, e.getMessage());
return null;
}
}
private void collectConditions(String json, String timeframe, String side,
List<PendingCond> out) {
if (json == null || json.isBlank()) return;