package org.ripple.power.hft.computer; import java.util.Arrays; import org.apache.commons.math3.fitting.PolynomialCurveFitter; import org.apache.commons.math3.fitting.WeightedObservedPoints; import com.tictactec.ta.lib.Core; import com.tictactec.ta.lib.MInteger; public class ADXComputer { private Core core = new Core(); /** * * 计算adx * * @param close * 至少150元素,150 periods are required to absorb the smoothing * techniques * @param high * @param low * @param period * 建议14 * @return */ public double[] computeADX(double[] close, double[] high, double[] low, int period) { MInteger begin = new MInteger(); MInteger length = new MInteger(); double[] out = new double[close.length - period * 2 + 1]; core.adx(0, close.length - 1, high, low, close, period, begin, length, out); return out; } /** * 根据输入的adx数组判断趋势是否在形成当中 * * @param adx * @param trendingGrayTH * 判断趋势正在形成 adx的下限值, 比如20-25一般是趋势模糊的值 * @Param trendingTH 强趋势下限值, 一般25 * @param lookbackPeriod * 从最后adx元素起, 往前取多少个元素做趋势形成判断 * * @return */ public boolean adxTrendForming(double[] adx, double trendingGrayTH, double trendingTH, int lookbackPeriod) { double[] adxSubset = Arrays.copyOfRange(adx, adx.length - lookbackPeriod, adx.length); double adxSum = 0; double directionTH = 0.5; // adx均值>trendingGrayTH, 总体向上, 有adx>trendingTH 3者满足2个当作形成中 boolean hasAdxOverTH = false; double directionIndex = 0; for (int i = 0; i < adxSubset.length - 1; i++) { adxSum += adxSubset[i]; if (adxSubset[i] > trendingTH) { hasAdxOverTH = true; } if (adxSubset[i + 1] > adxSubset[i]) { directionIndex++; } } boolean avgOverTH = adxSum / lookbackPeriod >= trendingGrayTH; boolean hasUpDirection = directionIndex / lookbackPeriod > directionTH; boolean adxTrendBoosting = adxTrendBoosting(adxSubset, 1); int satisfied = 0; if (hasAdxOverTH) { satisfied++; } if (avgOverTH) { satisfied++; } if (hasUpDirection) { satisfied++; } if (adxTrendBoosting) { satisfied++; } return satisfied >= 2; } /** * 判断adx是否快速上升中 * * @param adx * @param coeffTH * @return */ public boolean adxTrendBoosting(double[] adx, double coeffTH) { double min = adx[0]; for (double adxValue : adx) { min = Math.min(min, adxValue); } // normalize WeightedObservedPoints points = new WeightedObservedPoints(); for (int i = 0; i < adx.length; i++) { points.add(i, adx[i] - min); } // 1阶拟合 PolynomialCurveFitter fitter = PolynomialCurveFitter.create(1); return fitter.fit(points.toList())[1] >= coeffTH; } }