전략편집기 목록방식 오류 수정
This commit is contained in:
@@ -52,6 +52,17 @@ class IndicatorHlineResolverTest {
|
||||
assertEquals(48.0, val, 0.0001);
|
||||
}
|
||||
|
||||
@Test
|
||||
void rsiValue_withThresholdOverride_doesNotUseTargetValue() throws Exception {
|
||||
var cond = MAPPER.readTree("""
|
||||
{"thresholdOverride": true, "targetValue": 55}
|
||||
""");
|
||||
assertNull(IndicatorHlineResolver.resolveThresholdField(
|
||||
cond, "RSI_VALUE", "RSI", Map.of()));
|
||||
assertEquals(55.0, IndicatorHlineResolver.resolveThresholdField(
|
||||
cond, "K_55", "RSI", Map.of()), 0.0001);
|
||||
}
|
||||
|
||||
@Test
|
||||
void blankField_returnsNull() {
|
||||
assertNull(IndicatorHlineResolver.resolveThresholdField(
|
||||
|
||||
@@ -31,6 +31,70 @@ class RsiChartScanIntegrationTest {
|
||||
normalizer = new StrategyDslTimeframeNormalizer(MAPPER);
|
||||
}
|
||||
|
||||
@Test
|
||||
void chartScan_strategy195Exact_k55_vs_hlMid() throws Exception {
|
||||
String chartTf = "3m";
|
||||
List<OhlcvBar> bars = buildOscillatingOhlcvBars(300, chartTf);
|
||||
BarSeries primarySeries = OhlcvBarSeriesSupport.buildSeries(bars, chartTf);
|
||||
|
||||
JsonNode buyDslRaw = MAPPER.readTree("""
|
||||
{
|
||||
"type": "TIMEFRAME",
|
||||
"candleTypes": ["3m"],
|
||||
"candleType": "3m",
|
||||
"children": [{
|
||||
"type": "CONDITION",
|
||||
"condition": {
|
||||
"indicatorType": "RSI",
|
||||
"conditionType": "CROSS_UP",
|
||||
"leftField": "RSI_VALUE",
|
||||
"rightField": "K_55",
|
||||
"targetValue": 55,
|
||||
"thresholdOverride": true,
|
||||
"valuePeriodOverride": false,
|
||||
"leftCandleType": "3m",
|
||||
"rightCandleType": "3m",
|
||||
"candleRange": 1
|
||||
}
|
||||
}]
|
||||
}
|
||||
""");
|
||||
|
||||
JsonNode buyDsl = normalizer.remapForChartTimeframe(
|
||||
StrategyConditionThresholdNormalizer.normalizeTree(buyDslRaw), chartTf);
|
||||
Map<String, BarSeries> seriesOverrides = OhlcvBarSeriesSupport.buildSeriesOverrides(
|
||||
primarySeries, chartTf, buyDsl, null);
|
||||
Map<String, Map<String, Object>> params = Map.of(
|
||||
"RSI", Map.of("length", 9, "maLength", 5, "maType", "SMA", "src", "close"));
|
||||
|
||||
StrategyDslToTa4jAdapter.RuleBuildContext ctx =
|
||||
new StrategyDslToTa4jAdapter.RuleBuildContext(
|
||||
primarySeries, params, Map.of(), "KRW-BTC", null, false, seriesOverrides);
|
||||
Rule ruleK55 = adapter.toRule(buyDsl, ctx);
|
||||
int hits55 = countHitsFrom(ruleK55, primarySeries, 100);
|
||||
|
||||
JsonNode buyHlMid = buyDsl.deepCopy();
|
||||
JsonNode cond = buyHlMid.path("children").get(0).path("condition");
|
||||
var condObj = (com.fasterxml.jackson.databind.node.ObjectNode) cond;
|
||||
condObj.put("rightField", "HL_MID");
|
||||
condObj.remove("targetValue");
|
||||
condObj.put("thresholdOverride", false);
|
||||
Rule ruleMid = adapter.toRule(buyHlMid, ctx);
|
||||
int hitsMid = countHitsFrom(ruleMid, primarySeries, 100);
|
||||
|
||||
assertFalse(hits55 == 0, "strategy195-like K_55 should produce signals, got " + hits55);
|
||||
assertTrue(hits55 <= hitsMid,
|
||||
"K_55 hits=" + hits55 + " should be <= HL_MID hits=" + hitsMid);
|
||||
}
|
||||
|
||||
private static int countHitsFrom(Rule rule, BarSeries series, int startIdx) {
|
||||
int hits = 0;
|
||||
for (int i = startIdx; i <= series.getEndIndex(); i++) {
|
||||
if (rule.isSatisfied(i, null)) hits++;
|
||||
}
|
||||
return hits;
|
||||
}
|
||||
|
||||
@Test
|
||||
void chartScan_rsiCrossUpK55_firesSignals() throws Exception {
|
||||
String chartTf = "3m";
|
||||
|
||||
Reference in New Issue
Block a user