9일 신고가 매수 조건 오류
This commit is contained in:
@@ -68,4 +68,14 @@ class IndicatorHlineResolverTest {
|
||||
assertNull(IndicatorHlineResolver.resolveThresholdField(
|
||||
null, "", "RSI", Map.of()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void nhPriorField_notParsedAsNumericConstant() {
|
||||
assertNull(IndicatorHlineResolver.resolveThresholdField(
|
||||
null, "NH_PRIOR_9", "NEW_HIGH", Map.of()));
|
||||
assertNull(IndicatorHlineResolver.resolveThresholdField(
|
||||
null, "NL_PRIOR_20", "NEW_LOW", Map.of()));
|
||||
assertNull(IndicatorHlineResolver.resolveThresholdField(
|
||||
null, "DC_UPPER_9", "DONCHIAN", Map.of()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,8 +173,56 @@ class PriceExtremeRuleTest {
|
||||
assertFalse(hits.isEmpty(), "하락 추세에서 9·20일 신저가 복합 매도 조건이 최소 1회 충족되어야 함");
|
||||
}
|
||||
|
||||
@Test
|
||||
void nhPrior_crossUp_firesOnRealPriceBreakout_notConstantNine() throws Exception {
|
||||
BarSeries series = buildFlatThenBreakoutSeries(97_000_000.0, 97_500_000.0, 15);
|
||||
Rule buy = rule(series, """
|
||||
{ "type": "CONDITION", "condition": {
|
||||
"indicatorType": "NEW_HIGH",
|
||||
"conditionType": "CROSS_UP",
|
||||
"leftField": "CLOSE_PRICE",
|
||||
"rightField": "NH_PRIOR_9",
|
||||
"period": 9
|
||||
}}
|
||||
""");
|
||||
|
||||
List<Integer> hits = satisfiedIndices(buy, series);
|
||||
assertFalse(hits.isEmpty(),
|
||||
"97M대 종가가 9일 신고가선 상향 돌파 시 CROSS_UP — NH_PRIOR_9를 상수 9로 해석하면 영원히 false");
|
||||
assertTrue(hits.stream().anyMatch(i -> i >= 9),
|
||||
"9봉 워밍업 이후 돌파 봉에서만 시그널");
|
||||
}
|
||||
|
||||
// ── helpers ─────────────────────────────────────────────────────────────
|
||||
|
||||
/** 횡보 후 한 봉에 종가 돌파 — NH_PRIOR CROSS_UP 검증용 */
|
||||
private static BarSeries buildFlatThenBreakoutSeries(double flatPrice, double breakoutClose, int flatBars) {
|
||||
Duration period = Duration.ofMinutes(3);
|
||||
BarSeries series = new BaseBarSeriesBuilder()
|
||||
.withName("flat-breakout")
|
||||
.withNumFactory(DoubleNumFactory.getInstance())
|
||||
.withBarBuilderFactory(new TimeBarBuilderFactory())
|
||||
.build();
|
||||
TimeBarBuilderFactory factory = new TimeBarBuilderFactory();
|
||||
Instant base = Instant.parse("2024-01-01T00:00:00Z");
|
||||
for (int i = 0; i < flatBars; i++) {
|
||||
factory.createBarBuilder(series)
|
||||
.timePeriod(period)
|
||||
.endTime(base.plus(period.multipliedBy(i + 1L)))
|
||||
.openPrice(flatPrice).highPrice(flatPrice + 1000).lowPrice(flatPrice - 1000).closePrice(flatPrice)
|
||||
.volume(1000)
|
||||
.add();
|
||||
}
|
||||
int i = flatBars;
|
||||
factory.createBarBuilder(series)
|
||||
.timePeriod(period)
|
||||
.endTime(base.plus(period.multipliedBy(i + 1L)))
|
||||
.openPrice(flatPrice).highPrice(breakoutClose + 500).lowPrice(flatPrice - 500).closePrice(breakoutClose)
|
||||
.volume(5000)
|
||||
.add();
|
||||
return series;
|
||||
}
|
||||
|
||||
private Rule rule(BarSeries series, String json) throws Exception {
|
||||
JsonNode node = MAPPER.readTree(json);
|
||||
return adapter.toRule(node, series, Map.of());
|
||||
|
||||
Reference in New Issue
Block a user