All Downloads are FREE. Search and download functionalities are using the official Maven repository.

xlc.quant.data.indicator.calculator.RSI Maven / Gradle / Ivy

package xlc.quant.data.indicator.calculator;

import java.math.BigDecimal;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import xlc.quant.data.indicator.Indicator;
import xlc.quant.data.indicator.IndicatorCalculator;
import xlc.quant.data.indicator.IndicatorCalculatorCallback;


/**
 * @author Rootfive
 * 百度百科:https://baike.baidu.com/item/%E7%9B%B8%E5%AF%B9%E5%BC%BA%E5%BC%B1%E6%8C%87%E6%A0%87
 * 
 * 中文名 RSI指标    是相对强弱指标
 * 
 * 相对强弱指标RSI是用以计测市场供需关系和买卖力道的方法及指标。
 * 计算公式:
 * N日RSI =A/(A+B)×100
 * A=N日内收盘涨额之和
 * B=N日内收盘跌额之和(取正值)
 * 由上面算式可知RSI指标的技术含义,即以向上的力量与向下的力量进行比较,若向上的力量较大,则计算出来的指标上升;若向下的力量较大,则指标下降,由此测算出市场走势的强弱。
 * 以日为计算周期为例,计算RSI值一般是以5日、10日、14日为一周期。
 * 另外也有以6日、12日、24日为计算周期。
 * 一般而言,若采用的周期的日数短,RSI指标反应可能比较敏感;日数较长,可能反应迟钝。
 * ===============================================================
 * RSI的变动范围在0—100之间,强弱指标值一般分布在20—80。
 * 80-100 极强 卖出
 * 50-80 强 买入
 * 20-50 弱 观望
 * 0-20 极弱 买入
 * 这里的“极强”、“强”、“弱”、“极弱”只是一个相对的分析概念。
 */
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class RSI extends Indicator {

	/** RSI值 */
	private BigDecimal value;

	private BigDecimal emaUp;

	private BigDecimal emaDown;

	public RSI(BigDecimal value, BigDecimal emaUp, BigDecimal emaDown) {
		super();
		this.value = value;
		this.emaUp = emaUp;
		this.emaDown = emaDown;
	}

	//=============
	//内部类分隔符 XXX
	//=============
	/**
	 * 构建-计算器
	 * 
	 * @param capacity
	 * @return
	 */
	public static IndicatorCalculator buildCalculator(int capacity) {
		return new RSICalculator(capacity);
	}

	/**
	 * 计算器
	 * @author Rootfive
	 */
	private static class RSICalculator extends IndicatorCalculator {

		private final BigDecimal α;
		private final BigDecimal β;

		/**
		 * @param capacity
		 */
		public RSICalculator(int capacity) {
			super(capacity, true);
			this.α = divide(new BigDecimal(capacity - 1), new BigDecimal(capacity), 4);
			this.β = BigDecimal.ONE.subtract(α);
		}

		@Override
		protected RSI executeCalculate() {

			BigDecimal emaUp = null;
			BigDecimal emaDown = null;

			RSI prevRSI = getPrev().getIndicator();
			if (prevRSI == null) {
				// 涨额之和
				BigDecimal sumUp = BigDecimal.ZERO;
				// 跌额之和
				BigDecimal sumDown = BigDecimal.ZERO;
				for (IndicatorCalculatorCallback calculate : super.getCalculatorDataList()) {
					BigDecimal changePrice = calculate.getPriceChange();
					if (changePrice == null) {
						// 第一根K线可能没有统计到涨跌幅,跳过
						continue;
					}

					// 涨幅之和累加
					
					if (changePrice.compareTo(BigDecimal.ZERO) > 0) {
						sumUp = sumUp.add(changePrice);
					} else if (changePrice.compareTo(BigDecimal.ZERO) < 0) {
						sumDown = sumDown.subtract(changePrice);
					}
				}

				emaUp = divide(sumUp, fwcPeriod, 4);
				emaDown = divide(sumDown, fwcPeriod, 4);
				;
			} else {
				BigDecimal prevEmaUp = prevRSI.getEmaUp();
				BigDecimal prevEmaDown = prevRSI.getEmaDown();

				IndicatorCalculatorCallback head = getHead();
				BigDecimal changePrice = head.getPriceChange();

				// 涨幅之和累加
				int compareTo = changePrice.compareTo(BigDecimal.ZERO);
				if (compareTo > 0) {
					emaUp = (prevEmaUp.multiply(α)).add((changePrice.multiply(β)));
					emaDown = (prevEmaDown.multiply(α)).add((BigDecimal.ZERO.multiply(β)));
				}

				if (compareTo < 0) {
					emaUp = (prevEmaUp.multiply(α)).add((BigDecimal.ZERO.multiply(β)));
					emaDown = (prevEmaDown.multiply(α)).add((changePrice.abs().multiply(β)));
				}

				if (compareTo == 0) {
					emaUp = (prevEmaUp.multiply(α)).add((BigDecimal.ZERO.multiply(β)));
					emaDown = (prevEmaDown.multiply(α)).add((BigDecimal.ZERO.multiply(β)));
				}
			}

			BigDecimal sumEmaChanges = emaUp.add(emaDown);
			BigDecimal rsi = null;
			
			if (sumEmaChanges.compareTo(BigDecimal.ZERO) !=0) {
				rsi = divideByPct(emaUp, sumEmaChanges);
			}
			return new RSI(rsi, emaUp, emaDown);
		}

	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy