编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

TA-Lib技术指标计算库(td技术指标)

wxchong 2025-04-30 20:20:42 开源技术 23 ℃ 0 评论

今天浅用了下 Gemini 2.5 pro,Gemini在介绍多时间框架验证策略的时候提到了技术指标计算库:TA-Lib。这还是我在开发程序化交易系统以来头一次听到这个工具库,第一感觉就是我是不是又重复造轮子了,之前写的那么多指标计算公式,是不是在浪费时间?

大概了解了下这个库,TA-Lib库它是一种流行的技术分析库,提供了多种常用的技术分析指标函数,如SMA,EMA,MACD,RSI等等上百个函数。于是我写了个调用ta-lib的例子,跟我自己实现的指标计算方法做了个比较:

public static void main(String[] args) {
    // 构造测试数据(最新数据在列表末尾)
  	//StrategyDataDTO里包含了开盘价,收盘价,最高价,最低价,持仓量等等,计算sma 需用到收盘价
    List<StrategyDataDTO> testData = new ArrayList<>();
    testData.add(new StrategyDataDTO(new BigDecimal(10.0), 0l));
    testData.add(new StrategyDataDTO(new BigDecimal(12.0), 0l));
    testData.add(new StrategyDataDTO(new BigDecimal(11.0), 0l));
    testData.add(new StrategyDataDTO(new BigDecimal(13.0), 0l));
    testData.add(new StrategyDataDTO(new BigDecimal(14.0), 0l));
    testData.add(new StrategyDataDTO(new BigDecimal(12.5), 0l));
    testData.add(new StrategyDataDTO(new BigDecimal(11.0), 0l));

  	double[] closePrices = testData.stream().map(StrategyDataDTO::getClosePrice).mapToDouble(BigDecimal::doubleValue).toArray();
    System.out.println("priceList:{}", JSONObject.toJSONString(closePrices));
    
    double sma = calculateSMA(testData, 7);
    System.out.println("SMA:{}", sma);

    /**
     * 使用TA-Lib计算SMA
     */
    //计算SMA(周期=7)
    int smaPeriod = 7; 
  	//用于存储结果的数组。为了方便起见,它的大小与输入相同,但只有前几个 outNBElement.value 元素有效
    double[] outputSma = new double[closePrices.length];
  	//TA-Lib 使用此可变整数包装器返回输入数组中第一个有效输出值对应的索引。对于 SMA(7),第一次计算需要 7 个数据点,因此第一个 SMA 值对应于索引 6 的输入价格(从 0 开始)。因此,outBegIdx.value 将为 6。
    MInteger outBegIdx = new MInteger(); 
  	//使用此值返回计算并存储在 outputSma 数组中的有效 SMA 值的总数。该值为 input_length - (period - 1)。
    MInteger outNBElement = new MInteger(); 

		Core core = new Core();
  	/**
     * 方法参数说明:第一个是开始下标、结束的下标、外界输入的数组样本、函数计算周期、是有效数据开始位置、有效数据长度、输出的结果数组 
     * 这里, 结果存放在outputSma数组中, 但是有效数字是从outBegIdx.value开始的, 也就是前几个数字是无效的, 所以循环并不是从index 0开始
     */
  	RetCode retCode = core.sma(0, closePrices.length - 1, closePrices, smaPeriod, outBegIdx, outNBElement, outputSma);
    if (retCode == RetCode.Success) {
        double[] finalSmaValues = Arrays.copyOfRange(outputSma, 0, outNBElement.value);
        System.out.println("\nFinal SMA array (size " + finalSmaValues.length + "): " + Arrays.toString(finalSmaValues));
    } else {
      System.err.println("Error calculating SMA. TA-Lib RetCode: " + retCode);
    }
}

/**
     * 简单移动平均(SMA)
     * @param bars
     * @param period
     * @return
     */
public static double calculateSMA(List<StrategyDataDTO> bars, int period) {
  if (bars.size() < period) return 0;

  //计算SMA(简单移动平均)
  double sma = bars.stream()
    .skip(bars.size() - period)
    .limit(period)
    .mapToDouble(b -> b.getClosePrice().doubleValue())
    .average()
    .orElse(0);

  return sma;
}

输出结果:

priceList:[10.0,12.0,11.0,13.0,14.0,12.5,11.0]
SMA:11.928571428571429
Final SMA array (size 1): [11.928571428571429]

我自己写的方法目前只是计算指标周期最后一个sma值,不是一个数组,而ta-lib计算出来的是一个数组,会把之前所有的sam的指标都计算出来。因为周期是7,输入样本数据只有 7 个,所以ta-lib的结果只有一个,如果把周期改成 3,则结果为:

priceList:[10.0,12.0,11.0,13.0,14.0,12.5,11.0]
SMA:12.5
Final SMA array (size 5): [11.0, 12.0, 12.666666666666666, 13.166666666666666, 12.5]

ta-lib的sma函数会把输入的数据样本按照周期 3 来计算所有的 sma值,也就是从第三个数开始,计算每一个周期为 3的sma值:

第1个周期用到的数据:SMA(10.0,12.0,11.0)= 11.0
第2个周期用到的数据:SMA(12.0,11.0,13.0)= 12.0
第3个周期用到的数据:SMA(11.0,13.0,14.0)= 12.666666666666666
第4个周期用到的数据:SMA(13.0,14.0,12.5)= 13.166666666666666
第5个周期用到的数据:SMA(14.0,12.5,11.0)= 12.5

ta-lib还是很给力的,懒人必备。我想去了解下tb-lib的api文档,没找到,了解到原来tb-lib原生是用C写的,java只是做了个封装,所以java-source代码里都没有看到注释。

使用很简单,引入 maven依赖即可:

<!-- https://mvnrepository.com/artifact/com.tictactec/ta-lib -->
<dependency>
    <groupId>com.tictactec</groupId>
    <artifactId>ta-lib</artifactId>
    <version>0.4.0</version>
</dependency>


结论:相比我自己实现的指标计算方法,感觉tb-lib计算的结果更适合图表展示,因为它计算的结果是一个数组(也许有单个指标值,未深入研究),可以在图表上展示为一条sma线,而我的自己实现的计算方法,更有效率,只需获取当前实时的一个指标值,以判断当前是否可以作为开仓信号的参考,同时自己实现也能更好的了解各个指标的计算原理。如果我的系统有图表展示指标的需求,ta-lib还是很好用的,至少减少了很多开发量。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表