package com.goldenchart.service; import org.ta4j.core.BarSeries; import org.ta4j.core.Indicator; import org.ta4j.core.indicators.CachedIndicator; import org.ta4j.core.indicators.averages.SMAIndicator; import org.ta4j.core.indicators.statistics.MeanDeviationIndicator; import org.ta4j.core.num.Num; import java.util.HashMap; import java.util.Map; /** * TradingView/업비트 CCI — 임의 가격 소스에 대해 * (src - SMA) / (0.015 × MeanDeviation) 계산. */ public class CciOnSourceIndicator extends CachedIndicator { /** 업비트·TradingView 기본: hlc3(고저종), 기간 13, 신호 SMA 10 */ public static Map normalizeParams(Map p) { Map out = new HashMap<>(p); String maType = String.valueOf(p.getOrDefault("maType", "SMA")); int length = intParam(p, "length", 13); int maLength = intParam(p, "maLength", 10); String src = String.valueOf(p.getOrDefault("src", "hlc3")); if ("close".equals(src) && length == 13 && maLength == 10 && "SMA".equals(maType)) { src = "hlc3"; } out.put("src", src); return out; } private static int intParam(Map p, String k, int def) { Object v = p.get(k); return v == null ? def : ((Number) v).intValue(); } private final Indicator price; private final SMAIndicator sma; private final MeanDeviationIndicator meanDeviation; private final Num factor; private final int barCount; public CciOnSourceIndicator(Indicator price, int barCount) { super(price); this.price = price; this.barCount = barCount; this.factor = getBarSeries().numFactory().numOf(0.015); this.sma = new SMAIndicator(price, barCount); this.meanDeviation = new MeanDeviationIndicator(price, barCount); } @Override protected Num calculate(int index) { final Num meanDeviation = this.meanDeviation.getValue(index); if (meanDeviation.isZero()) { return getBarSeries().numFactory().zero(); } return price.getValue(index).minus(sma.getValue(index)) .dividedBy(meanDeviation.multipliedBy(factor)); } @Override public int getCountOfUnstableBars() { return barCount - 1; } }