전략 시간봉 오류 수정
This commit is contained in:
+39
-7
@@ -68,8 +68,20 @@ public class StrategyConditionTimeframeService {
|
||||
ensureDslRepaired(strategy);
|
||||
|
||||
Set<String> out = new LinkedHashSet<>();
|
||||
collectFromJson(strategy.getBuyConditionJson(), out, strategy.getName());
|
||||
collectFromJson(strategy.getSellConditionJson(), out, strategy.getName());
|
||||
boolean buyScoped = collectStartScopeFromJson(strategy.getBuyConditionJson(), out);
|
||||
boolean sellScoped = collectStartScopeFromJson(strategy.getSellConditionJson(), out);
|
||||
|
||||
if (!out.isEmpty()) {
|
||||
return out;
|
||||
}
|
||||
|
||||
// 레거시: START(TIMEFRAME) 래핑 없는 DSL
|
||||
if (!buyScoped) {
|
||||
collectLegacyFromJson(strategy.getBuyConditionJson(), out, strategy.getName());
|
||||
}
|
||||
if (!sellScoped) {
|
||||
collectLegacyFromJson(strategy.getSellConditionJson(), out, strategy.getName());
|
||||
}
|
||||
|
||||
if (out.isEmpty()) {
|
||||
String fromName = StrategyDslTimeframeNormalizer.inferFromStrategyName(strategy.getName());
|
||||
@@ -106,19 +118,39 @@ public class StrategyConditionTimeframeService {
|
||||
}
|
||||
}
|
||||
|
||||
private void collectFromJson(String json, Set<String> out, String strategyName) {
|
||||
if (json == null || json.isBlank()) return;
|
||||
/**
|
||||
* START 루트 TIMEFRAME(candleTypes)만 수집 — 조건 노드 leftCandleType·내부 1m 기본값은 제외.
|
||||
*
|
||||
* @return JSON 에 START 스코프가 있으면 true (빈 조건이어도)
|
||||
*/
|
||||
private boolean collectStartScopeFromJson(String json, Set<String> out) {
|
||||
if (json == null || json.isBlank()) return false;
|
||||
try {
|
||||
collectFromNode(objectMapper.readTree(json), out, strategyName);
|
||||
return collectStartScopeFromNode(objectMapper.readTree(json), out);
|
||||
} catch (Exception e) {
|
||||
log.warn("[StrategyTimeframes] JSON 파싱 실패: {}", e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean collectStartScopeFromNode(JsonNode node, Set<String> out) {
|
||||
if (node == null || node.isNull()) return false;
|
||||
return collectTimeframesFromNode(node, out);
|
||||
}
|
||||
|
||||
/** 레거시 DSL — START 래핑 없을 때만 조건 트리·전략명에서 추론 */
|
||||
private void collectLegacyFromJson(String json, Set<String> out, String strategyName) {
|
||||
if (json == null || json.isBlank()) return;
|
||||
try {
|
||||
collectLegacyFromNode(objectMapper.readTree(json), out, strategyName);
|
||||
} catch (Exception e) {
|
||||
log.warn("[StrategyTimeframes] legacy JSON 파싱 실패: {}", e.getMessage());
|
||||
addFallbackTimeframe(out, strategyName);
|
||||
}
|
||||
}
|
||||
|
||||
private void collectFromNode(JsonNode node, Set<String> out, String strategyName) {
|
||||
private void collectLegacyFromNode(JsonNode node, Set<String> out, String strategyName) {
|
||||
if (node == null || node.isNull()) return;
|
||||
if (collectTimeframesFromNode(node, out)) return;
|
||||
|
||||
Set<String> meaningful = StrategyDslTimeframeNormalizer.collectMeaningfulCandleTypes(node);
|
||||
if (!meaningful.isEmpty()) {
|
||||
|
||||
+32
@@ -101,6 +101,38 @@ class StrategyConditionTimeframeServiceTest {
|
||||
assertTrue(service.usesTimeframe(3L, "3m"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void collectForStrategy_buyStartScopeIgnoresSellLegacy1m() {
|
||||
GcStrategy mixed = new GcStrategy();
|
||||
mixed.setId(5L);
|
||||
mixed.setBuyConditionJson("""
|
||||
{
|
||||
"type": "TIMEFRAME",
|
||||
"candleType": "3m",
|
||||
"candleTypes": ["3m", "5m"],
|
||||
"children": [{
|
||||
"type": "CONDITION",
|
||||
"condition": { "indicatorType": "STOCHASTIC", "period": 14 }
|
||||
}]
|
||||
}
|
||||
""");
|
||||
mixed.setSellConditionJson("""
|
||||
{
|
||||
"type": "TIMEFRAME",
|
||||
"candleType": "1m",
|
||||
"children": [{
|
||||
"type": "CONDITION",
|
||||
"condition": { "indicatorType": "STOCHASTIC", "period": 14 }
|
||||
}]
|
||||
}
|
||||
""");
|
||||
when(strategyRepo.findById(5L)).thenReturn(Optional.of(mixed));
|
||||
|
||||
Set<String> tfs = service.collectForStrategy(5L);
|
||||
assertEquals(Set.of("3m", "5m"), tfs);
|
||||
assertFalse(service.usesTimeframe(5L, "1m"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void collectForStrategy_legacyTreeDefaultsTo1m() {
|
||||
GcStrategy legacy = new GcStrategy();
|
||||
|
||||
Reference in New Issue
Block a user