ta4j简介

对于做金融分析的从业者而言,python的ta-lib是不可或缺的技术分析库,具有简单易用、功能强大的特点。 各种SMA、MACD、BOLL等指标计算,应有尽有。

那么对于擅长Java语言的开发者而言,有没有对应的功能强大的Java类库呢?答案是Java版ta4j。

ta4j是使用纯Java实现的,不是ta-lib的简单封装,因此具有简单易用、无其他依赖的特点。

GitHub: https://github.com/ta4j/ta4j

WiKi: https://ta4j.github.io/ta4j-wiki/Getting-started.html

WebSite: https://ta4j.github.io/ta4j-wiki/

布林带简介

布林带(Bollinger Bands)是股票技术分析中广泛使用的技术指标,由约翰・布林格(John Bollinger)在 20 世纪 80 年代初期发明。它通过价格的标准差来显示股价的波动范围,帮助投资者分析股价走势、判断市场趋势以及识别潜在的交易信号。

布林带的构成

布林带由三条线组成:

. 中轨(Middle Band):通常是特定周期内的简单移动平均线(SMA)。例如,常见的计算周期为 20 日,即通过计算过去 20 个交易日的收盘价总和,再除以 20 得到中轨数值。它反映了股价的平均成本和中期趋势方向。

. 上轨(Upper Band):基于中轨和价格的标准差计算得出。

. 下轨(Lower Band):计算方式与上轨类似。

布林带的应用

判断股价趋势:

上升趋势:

当股价在布林带中轨上方运行,且布林带开口逐渐扩大,表明股价处于上升趋势,市场多头力量较强。随着股价上涨,上轨和中轨同步上升,下轨也可能跟随上升但幅度相对较小。例如,在一段上升行情中,股价不断创新高,同时布林带开口放大,显示市场情绪积极,股价有进一步上升动力。 下降趋势:若股价在布林带中轨下方运行,且布林带开口逐渐扩大,意味着股价处于下降趋势,空头力量占据优势。股价下跌过程中,下轨和中轨同步下降,上轨虽也可能下降但幅度相对较小。比如,某股票股价持续走低,布林带开口扩张,反映市场看空情绪浓厚。

识别股价波动:

布林带收口: 当股价波动逐渐减小,布林带的上轨和下轨逐渐靠近,即开口收窄。这通常预示着市场即将选择方向,可能是股价即将突破或反转的信号。例如,在横盘整理行情后期,布林带收口,表明市场多空双方力量趋于平衡,等待新的驱动因素打破平衡,引发股价的大幅波动。 布林带开口: 与收口相反,当股价波动加剧,布林带的上轨和下轨距离逐渐拉大,即开口扩张。这表示市场活跃度增加,股价波动幅度加大。如在市场出现重大消息时,股价大幅波动,布林带开口迅速扩大。

寻找交易信号:

突破交易:当股价向上突破上轨,可能是短期买入信号,表明股价强势上涨,市场多头力量强劲。但需注意,这种突破可能是短期的超买现象,股价可能很快回调。反之,当股价向下突破下轨,可能是短期卖出信号,暗示股价弱势下跌,空头力量占优,但也可能是短期超卖,随后股价可能反弹。例如,股价突然放量向上突破上轨,一些投资者可能会根据这一信号买入股票,期待股价继续上涨。

回踩交易:股价在上升过程中,回调至中轨附近获得支撑并再次上涨,是一种潜在的买入机会;股价在下降过程中,反弹至中轨附近遇阻回落,则是潜在的卖出机会。这是因为中轨代表了股价的平均成本线,具有一定的支撑和阻力作用。例如,某股票在上升趋势中,股价回调到中轨附近企稳,随后再次上扬,投资者可在股价企稳时考虑买入。

布林带虽然是一种有效的技术分析工具,但在实际应用中,不能仅仅依赖布林带指标做出交易决策,还需要结合其他技术指标(如 MACD、KDJ 等)、基本面分析以及市场环境等因素,综合判断股票的投资价值和交易时机。

使用ta4j计算股票日线级别的布林带

首先你需要有某股票足够多的日线级别的数据(包含开盘价、收盘价、盘中最高价、盘中最低价),至少30个交易日的数据。 因为通常情况下计算20个交易日的布林带。

我们先定义股票日线价格表的实体类,例如:

package top.yjp.app.stock.entity;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.math.BigDecimal;
import java.time.LocalDate;

@Data
@TableName("price_info")
public class Price {
    /**
     * ID
     */
    @TableId
    private Long id;

    /**
     * 股票ID
     */
    @TableField
    private Long stockId;

    /**
     * 交易日
     */
    @TableField
    private LocalDate exchangeDate;

    /**
     * 开盘价
     */
    @TableField
    private BigDecimal openPrice;

    /**
     * 收盘价
     */
    @TableField
    private BigDecimal closePrice;

    /**
     * 最高价
     */
    @TableField
    private BigDecimal highPrice;

    /**
     * 最低价
     */
    @TableField
    private BigDecimal lowPrice;

    /**
     * 布林带中轨
     */
    @TableField
    private BigDecimal boll;

    /**
     * 布林带上轨
     */
    @TableField
    private BigDecimal bollUpper;

    /**
     * 布林带下轨
     */
    @TableField
    private BigDecimal bollLower;

    /**
     * 数据同步日期
     */
    @TableField
    private LocalDate syncDate;
    /**
     * 上一个交易日
     */
    @TableField
    private LocalDate preExchangeDate;
    
    /**
     * 上一个交易日收盘价
     */
    @TableField
    private BigDecimal preClosePrice;
}

计算布林带的方法定义如下:

 /**
     * 计算并更新布林线信息
     *
     * @param prices 待计算的日线价格数据
     */
    public void computeBollInfo(List<Price> prices) {
        // 创建BarSeries
        // 20日
        // k 个标准差
        int period = 20;
        double stdDevMultiplier = 2;
        BarSeries series = new BaseBarSeriesBuilder().withName("BOLL").build();
        for (Price price : prices) {
            ZonedDateTime exchangeDate = ZonedDateTime.of(price.getExchangeDate(), LocalTime.of(0, 0), ZoneId.systemDefault());
            Double openPrice = price.getOpenPrice().doubleValue();
            Double closePrice = price.getClosePrice().doubleValue();
            Double highPrice = price.getHighPrice().doubleValue();
            Double lowPrice = price.getLowPrice().doubleValue();
            series.addBar(Duration.ofDays(period), exchangeDate, openPrice, highPrice, lowPrice, closePrice, 0);
        }
        // 计算布林线指标
        BollingerBandFacade bollingerBandFacade = new BollingerBandFacade(series, period, stdDevMultiplier);
        for (int i = 0; i < series.getBarCount(); i++) {
            BigDecimal middlePrice = fix(bollingerBandFacade.middle().getValue(i).doubleValue());
            BigDecimal upperPrice = fix(bollingerBandFacade.upper().getValue(i).doubleValue());
            BigDecimal lowerPrice = fix(bollingerBandFacade.lower().getValue(i).doubleValue());
            Price price = prices.get(i);
            price.setBoll(middlePrice);
            price.setBollUpper(upperPrice);
            price.setBollLower(lowerPrice);
            price.setSyncDate(LocalDate.now());
            // 将计算后的布林带价格信息使用priceMapper工具类更新回到数据库
            priceMapper.updateById(price);
        }
    }