186 lines
6.4 KiB
Java
186 lines
6.4 KiB
Java
package com.goldenchart.service;
|
|
|
|
import com.fasterxml.jackson.databind.JsonNode;
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
import org.junit.jupiter.api.Test;
|
|
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
|
|
import static org.junit.jupiter.api.Assertions.*;
|
|
|
|
class StrategyDslTimeframeNormalizerTest {
|
|
|
|
private final ObjectMapper objectMapper = new ObjectMapper();
|
|
private final StrategyDslTimeframeNormalizer normalizer = new StrategyDslTimeframeNormalizer(objectMapper);
|
|
|
|
@Test
|
|
void normalize_preserves3mAnd5mWithout1m() throws Exception {
|
|
String json = """
|
|
{
|
|
"type": "TIMEFRAME",
|
|
"candleType": "1m",
|
|
"candleTypes": ["3m", "5m"],
|
|
"children": [{
|
|
"type": "CONDITION",
|
|
"condition": { "indicatorType": "RSI", "period": 14 }
|
|
}]
|
|
}
|
|
""";
|
|
String normalized = normalizer.normalizeJson(json, "테스트");
|
|
JsonNode root = objectMapper.readTree(normalized);
|
|
assertEquals(2, root.path("candleTypes").size());
|
|
assertEquals("3m", root.path("candleTypes").get(0).asText());
|
|
assertEquals("5m", root.path("candleTypes").get(1).asText());
|
|
assertEquals("3m", root.path("candleType").asText());
|
|
}
|
|
|
|
@Test
|
|
void normalize_preservesSingleExplicit3m() throws Exception {
|
|
String json = """
|
|
{
|
|
"type": "TIMEFRAME",
|
|
"candleType": "3m",
|
|
"children": [{
|
|
"type": "CONDITION",
|
|
"condition": { "indicatorType": "RSI", "period": 14 }
|
|
}]
|
|
}
|
|
""";
|
|
String normalized = normalizer.normalizeJson(json, "테스트");
|
|
JsonNode root = objectMapper.readTree(normalized);
|
|
assertEquals("3m", root.path("candleType").asText());
|
|
}
|
|
|
|
@Test
|
|
void normalize_dropsStale1mWhenConditionsUse5mOnly() throws Exception {
|
|
String json = """
|
|
{
|
|
"type": "TIMEFRAME",
|
|
"candleType": "1m",
|
|
"candleTypes": ["1m", "5m"],
|
|
"children": [{
|
|
"type": "CONDITION",
|
|
"condition": {
|
|
"indicatorType": "CCI",
|
|
"leftCandleType": "5m",
|
|
"rightCandleType": "5m"
|
|
}
|
|
}]
|
|
}
|
|
""";
|
|
String normalized = normalizer.normalizeJson(json, "알트레이어 매수 알림");
|
|
JsonNode root = objectMapper.readTree(normalized);
|
|
assertEquals(1, root.path("candleTypes").size());
|
|
assertEquals("5m", root.path("candleTypes").get(0).asText());
|
|
assertEquals("5m", root.path("candleType").asText());
|
|
}
|
|
|
|
@Test
|
|
void resolveStartCandleTypes_meaningfulOverridesStaleStart1m() throws Exception {
|
|
String json = """
|
|
{
|
|
"type": "TIMEFRAME",
|
|
"candleType": "1m",
|
|
"children": [{
|
|
"type": "CONDITION",
|
|
"condition": {
|
|
"indicatorType": "CCI",
|
|
"leftCandleType": "5m",
|
|
"rightCandleType": "5m"
|
|
}
|
|
}]
|
|
}
|
|
""";
|
|
JsonNode root = objectMapper.readTree(json);
|
|
assertEquals(Set.of("5m"), StrategyDslTimeframeNormalizer.resolveStartCandleTypes(root));
|
|
}
|
|
|
|
@Test
|
|
void resolveStartCandleTypes_dropsStale1mPair() throws Exception {
|
|
String json = """
|
|
{
|
|
"type": "TIMEFRAME",
|
|
"candleType": "1m",
|
|
"candleTypes": ["1m", "5m"],
|
|
"children": [{
|
|
"type": "CONDITION",
|
|
"condition": {
|
|
"indicatorType": "CCI",
|
|
"leftCandleType": "5m"
|
|
}
|
|
}]
|
|
}
|
|
""";
|
|
JsonNode root = objectMapper.readTree(json);
|
|
assertEquals(Set.of("5m"), StrategyDslTimeframeNormalizer.resolveStartCandleTypes(root));
|
|
}
|
|
|
|
@Test
|
|
void resolveStartCandleTypes_resolves3mAnd15mAnd1h() throws Exception {
|
|
for (String tf : List.of("3m", "15m", "1h")) {
|
|
String json = """
|
|
{
|
|
"type": "TIMEFRAME",
|
|
"candleType": "1m",
|
|
"children": [{
|
|
"type": "CONDITION",
|
|
"condition": {
|
|
"indicatorType": "RSI",
|
|
"leftCandleType": "%s",
|
|
"rightCandleType": "%s"
|
|
}
|
|
}]
|
|
}
|
|
""".formatted(tf, tf);
|
|
JsonNode root = objectMapper.readTree(json);
|
|
assertEquals(Set.of(tf), StrategyDslTimeframeNormalizer.resolveStartCandleTypes(root),
|
|
"expected " + tf);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
void normalize_alignsStaleStartToConditionTimeframe() throws Exception {
|
|
String json = """
|
|
{
|
|
"type": "TIMEFRAME",
|
|
"candleType": "1m",
|
|
"candleTypes": ["1m", "15m"],
|
|
"children": [{
|
|
"type": "CONDITION",
|
|
"condition": {
|
|
"indicatorType": "CCI",
|
|
"leftCandleType": "15m"
|
|
}
|
|
}]
|
|
}
|
|
""";
|
|
JsonNode root = objectMapper.readTree(normalizer.normalizeJson(json, "test"));
|
|
assertEquals(1, root.path("candleTypes").size());
|
|
assertEquals("15m", root.path("candleTypes").get(0).asText());
|
|
assertEquals("15m", root.path("candleType").asText());
|
|
}
|
|
|
|
@Test
|
|
void normalize_preservesMultiCandleTypesOnSave() throws Exception {
|
|
String json = """
|
|
{
|
|
"type": "TIMEFRAME",
|
|
"candleType": "1m",
|
|
"candleTypes": ["1m", "3m", "5m"],
|
|
"children": [{
|
|
"type": "CONDITION",
|
|
"condition": { "indicatorType": "RSI", "period": 14 }
|
|
}]
|
|
}
|
|
""";
|
|
String normalized = normalizer.normalizeJson(json, "5분봉 테스트 전략");
|
|
JsonNode root = objectMapper.readTree(normalized);
|
|
assertTrue(root.path("candleTypes").isArray());
|
|
assertEquals(3, root.path("candleTypes").size());
|
|
assertEquals("1m", root.path("candleTypes").get(0).asText());
|
|
assertEquals("3m", root.path("candleTypes").get(1).asText());
|
|
assertEquals("5m", root.path("candleTypes").get(2).asText());
|
|
}
|
|
}
|